@sodular/lite

0.1.0 • Public • Published

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:

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)

//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

Contributors

  • Agglomy Team :
    • Ivan Joel Sobgui

Licence

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

Package Sidebar

Install

npm i @sodular/lite

Weekly Downloads

3

Version

0.1.0

License

MIT

Unpacked Size

88.8 kB

Total Files

13

Last publish

Collaborators

  • coorise