npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sodular/lite

v0.1.0

Published

Sodular a Lite JSON database similar to firebase. Visit the master branch: https://github.com/coorise/sodular-lite-js.git

Downloads

4

Readme

SoduLite JS v0.1.0

SoduLite (Sodular Lite) is a lightweight JSON database based on path-like (similar to firebase database ) The data can be saved on local json file if you use Node JS or on browser with localStorage.

Get Started

0. Download the package

Node JS: npm install @sodular/lite Browser:

  • JsDelivr: https://cdn.jsdelivr.net/npm/@sodular/lite , then copy all the code from the link and paste it in a file sodulite.min.js

1. Import the database

//import SoduLite from '@sodular/lite'; //Node JS
import SoduLite from '../sodulite.min.js'; //For browser

2. Init the database

let db = SoduLite.init({
dbName: 'sodulite @&', // we use regex to replace any special character to '\_'
path: './database@/project-Z $é/', //same for path, using '/xxxx' or './xxxx' is not necessary because we use the root of the project only.
});

Note: path is only for Node JS

3. Call/Create the database service you want to work with

db = db = db.load('data'); //In Node Js, if .json is not added , it will automatically create it.

Note: load('service_name') is like your sub-dbName (sub-dbName.json if you are on Node Js). As service you have: auth, data, storage...

4. Do CRUD (Create|Read|Update|Delete) operation

Note: All operations are async, for those who don't know what we mean, it is as example below:

doSomething.then((result)=>{
  //work with your result
})

//OR 

(async () => {
  let result= await doSomething()
  //work with your result
})()
  • 4.1 Do Create operation

let op = db
    .ref('/members/users/0')
    .create({ name: 'Alice' })
    .then((node) => { // using then to get the value
      console.log('Create Alice: ', {
        path: node.path,
        key: node.key,
        value: node.value,
        error: node.error,
      });
    })
    .catch((e) => {
      console.log('Create Alice Error: ', e);
    });

//OR

let  op = await db // asuming it's in an async function
    .ref('/members/users/0') // you could generate a unique uid for your users.
    .create({ name: 'Alice' })
    .catch((e) => {
      console.log('Create Bob Error: ', e);
    });
  console.log('Create Alice:', {
    path: op.path, 
    key: op.key,
    value: op.value, // you get the object value
    error: op.error,
  });

Note: If the ref with data exists already, you won't be allowed to create, instead you have to do the Update Operation.

  • 4.2 Do Read operation

//Get the value of a path

let alice = await db // asuming it's in an async function
    .ref('/members/users/0')
    .get() //let it empty
    .catch((e) => {
      console.log('Get Alice Error: ', e);
    });
  console.log('Get Alice:', {
    path: alice.path,
    key: alice.key,
    value: alice.value,//the info of alice is here or it will return false.
    error: alice.error,
  });

//If path is an array[list of ids] or object{list of ids}

  • Get the unique value of a path with a parameter
let alice = await db // asuming it's in an async function
    .ref('/members/users') //users is an array or object with ids as property
    .get({name:'Alice'}) // Will only fetch the first Alice found, so add multiple parameter to get your result efficiently like {name:'Alice,age:30,...}, but the best is {uid:'userId'}.
    .catch((e) => {
      console.log('Get Alice Error: ', e);
    });
  console.log('Get Alice:', {
    path: alice.path,
    key: alice.key,
    value: alice.value,//the info of alice is here or it will return false.
    error: alice.error,
  });
  • Do the Query(Search), query always return an [array] of the result.
let query = await db // asuming it's in an async function
    .ref('/members/users') //users is an array or object with ids as property
    .query({ filter: { age: { _lte: 30 } } }) //Or { '$<=': 30 } , to get the condition little or equal to 30.
    .catch((e) => {
      console.log('Get Query Error: ', e);
    });
  console.log('Get Query:', {
    path: query.path,
    key: query.key,
    value: query.value,//array the value of query is here or it will return false.
    error: query.error,
  });

Note: See the parameters for query(filter = {}, sort, pagination, mod)

  • filter
  • sort
  • pagination
  • mod

//If you data is [], you could also use a path query string for a shorthand of pagination to get the list of objects in array.

let query = await db // asuming it's in an async function
    .ref('/members/users[0;1;5]') // if exist will select only the users[O], users[1] and users[5] in an array
    .query() //let it empty
    .catch((e) => {
      console.log('Get Query Error: ', e);
    });
  console.log('Get Query:', {
    path: query.path,
    key: query.key,
    value: query.value,//the array value of query is here or it will return false.
    error: query.error,
  });

Note: Check the path query string.

  • 4.3 Do Update operation

//Overwrite the previous data

let alice = await db // asuming it's in an async function
    .ref('/members/users/0')
    .update({ name: 'Alice Lite' })
    .catch((e) => {
      console.log('Update Alice Error: ', e);
    });
  console.log('Update Alice:', {
    path: alice.path,
    key: alice.key,
    value: alice.value,//the info of alice is here or it will return false.
    error: alice.error,
  });

// To merge with the previous data , you add {merge=true}

let alice = await db // asuming it's in an async function
    .ref('/members/users/0')
    .update({ age: 26 },{merge=true}) //Here we merge with the existing value.
    .catch((e) => {
      console.log('Update Alice Error: ', e);
    });
  console.log('Update Alice:', {
    path: alice.path,
    key: alice.key,
    value: alice.value,//the info of alice is here or it will return false.
    error: alice.error,
  });
  • 4.4 Do Delete operation

//Delete value with path

let alice = await db // asuming it's in an async function
    .ref('/members/users/0')
    .delete() //let it empty, it will delete everything on child=0
    .catch((e) => {
      console.log('Delete Alice Error: ', e);
    });
  console.log('Delete Alice:', {
    path: alice.path,
    key: alice.key,
    value: alice.value,//the info of alice is here or it will return false.
    error: alice.error,
  });

//If the final path is an array[list of ids] or object{list of ids}, the you can do the filter:

let alice = await db // asuming it's in an async function
    .ref('/members/users') //here you won't go to child=0, //users is an array or object with ids as property
    .delete({ age: 26 }) // will delete child which has age=26, 
    .catch((e) => {
      console.log('Delete Alice Error: ', e);
    });
  console.log('Delete Alice:', {
    path: alice.path,
    key: alice.key,
    value: alice.value,//the info of alice is here or it will return false.
    error: alice.error,
  });

Note:It will only delete the first object which has age=26 not all objects having age=26, so be careful to delete a unique uid, instead you should do .delete({ uid: uid_of_user }) or delete with the first method using path only.

Advanced Options

Query

let filter={
  //...
}
let sort={
  //...
}
let pagination={
  //...
}
let mod={
  //...
}
let result=await db //assuming async
           .ref()
           .query({filter,sort,pagination,mod})
           .catch((e) => {})
console.log('The result of filter: ', result?.value)
  • Filter

The available parameters are:

  • Object : filter = {age:30, name:'Alice'}
  • Object with operator: filter = {age:{'$<=':30}}, the operators are:
    • case '$<': same as
    • case '_lt': return value < operand;
    • case '$>': same as
    • case '_gt': return value > operand;
    • case '$=': same as
    • case '_eq': if (typeof operand == 'object') return deepEqual(value, operand); // can also compare array and obj else return value === operand;
    • case '$!=': same as
    • case '_neq': if (typeof operand == 'object') return !deepEqual(value, operand); // can also compare array and obj else return value !== operand;
    • case '$>=': same as
    • case '_gte': return value >= operand;
    • case '$<=': same as
    • case '_lte': return value <= operand;
    • case '$match': return new RegExp(operand).test(value);
    • case '$!match': return !new RegExp(operand).test(value);
    • case '$includes': return value?.includes(operand);
    • case '$!includes': return !value?.includes(operand);
    • case '$between': return value >= operand[0] && value <= operand[1];
    • case '$!between': return !(value >= operand[0] && value <= operand[1]);
    • case '$has': return hasProperties(value, operand); // similar to filter={a:value}, but also has the function to compare children with object {a:{a-child:'value-child'}}
    • case '$!has': return !hasProperties(value, operand);
    • case '$like': return new RegExp(^${operand?.replace(/\*/g, '.*')}$).test(value);
    • case '$!like': return !new RegExp(^${operand?.replace(/\*/g, '.*')}$).test(value);
    • case '$reg': return new RegExp(operand).test(value);
  • Sort

    • Object : sort = {age:'desc', name:'asc'} the sort properties are:
      • case 'asc': Ascendant values
      • case 'desc': Descendant values
  • Pagination

    • Object : pagination = {page:1, limit:10} the sort properties are:
      • case page: Int value
      • case limit: Int value
  • Mod

    • Object : mod = {with:['name','age'],} the mod properties are:
      • case with: Array of String regex path value, will only match the path properties you set, eg: with:['child/','child1//some_path']
      • case only: Array of String properties, select only the properties you selected, eg: only:['name']
      • case rm: Array of String properties, remove the properties you selected, eg: rm:['name']
  • Query String

    • String : db.ref('/path/users![a]').query() the available string param are:
      • case [a]: a is index int value, it will get list[a] value, eg: users[1] the second user, users[-1] the last user, users[-2] the user before the last user...etc
      • case ![a]: negation of [a]
      • case [a:b]: a,b are index int value, it will get the interval list from a to b values, eg: users[1:5]
      • case ![a:b]: negation of [a:b]
      • case [a,b,...etc]: a,b,...etc are index int value, it will select only list[a],list[b],...etc , eg: users[1,5]
      • case ![a,b]: negation of [a,b]
      • case [?a]: a is index int value, it will get list from 0 to a similar to list[0:a], eg: users[?3]
      • case [?-a]: similar to [?a], but removes the indexes starting from last item(index from -1 to -a will be removed) , eg: users[?-2] <=> users[0,-2]

Todo

  • Removing/Reduce some unusual dependencies,functions, refactoring paths/files...
  • Making good and easy documentation with tutorials (videos, webpage...)
  • Code Cleaning/ Making a suitable project structure with modular pattern (DRY and KISS dev).

Join US

If you have any suggestion, feature to add ...etc

  • Discord(Support Team, FAQ, Chat): https://discord.gg/5tHDeD3DQs

Contributors

  • Agglomy Team :
    • Ivan Joel Sobgui

Licence

MIT: You can use it for educational/personal/business purpose!