@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
Maintainers
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
- Object : sort = {age:'desc', name:'asc'}
the sort properties are:
Pagination
- Object : pagination = {page:1, limit:10}
the sort properties are:
- case page: Int value
- case limit: Int value
- Object : pagination = {page:1, limit:10}
the sort properties are:
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']
- Object : mod = {with:['name','age'],}
the mod properties are:
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]
- String : db.ref('/path/users![a]').query()
the available string param are:
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!