0.1.0 • Published 2 years ago

@sodular/lite v0.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

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 arraylist 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 arraylist 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 >= operand0 && value <= operand1; - case '$!between': return !(value >= operand0 && value <= operand1); - 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/usersa').query() the available string param are:
      • case a: a is index int value, it will get lista value, eg: users1 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: users1:5
      • case a:b: negation of a:b
      • case a,b,...etc: a,b,...etc are index int value, it will select only lista,listb,...etc , eg: users1,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 list0: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 <=> users0,-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!