Suggestion
If your codebase is support Optional Chaining, i will suggest you to use that unless you have some excuse to use like, large access to single object and want to use “cursor” to make it faster. Since native supported should have better performance than this library.
Installation
Node
{
"dependencies": {
"digdata": "Oskang09/digdata#1.1.2",
},
}
Browser
// latest version from master branch
<script src="https://oskang09.github.io/digdata/index.min.js"><script>
// specific version 1.1.0 ( browser support start from 1.1.0 )
<script src="https://oskang09.github.io/digdata/versions/1.1.2/index.min.js"><script>
Example & Ussage
Comma Symbol
Comma symbols ','
is for receiving multiple from an object. etc.
const { dig } = require('digdata');
const object = {
price: 26.8,
count: 2,
name: 'A4 Paper',
buyer: [
{
name: 'Oska',
id: 1,
age: 14
},
{
name: 'Jason',
id: 2,
age: 12
}
]
};
dig(object, 'price,name'); // { "price": 26.8, "name": "A4 Paper" }
dig(object, 'buyer.*.name,age') // [ { "name": "Oska", "age": 14 }, { "name": "Jason", "age": 12 }]
Equal Symbol
Equal symbols '='
is for receive based on value from an object or array. etc.
const { dig } = require('digdata');
const object = {
type: 'SPICY',
name: 'Burger',
dine: [
'DINE_IN',
'TAKEAWAY'
],
variants: [
{
name: 'Ala Carte',
price: 8.9,
items: [ 'Burger' ],
},
{
name: 'Large Set',
price: 11.9,
items: [
'Burger',
'French Fries',
'Coca Cola'
],
},
],
};
dig(object, 'variants.name=Ala Carte'); // { "name": "Ala Carte", "price": 8.9, "items": [ "Burger" ] }
dig(object, 'dine=DINE_IN'); // "DINE_IN"
ArrayMap Symbol
ArrayMap symbols '*'
is for filter data from an array object. etc.
const object = {
owner: {
id: 14,
name: 'Jason',
age: 19
},
users: [
{
id: 1,
name: 'Oskang09',
age: 20,
email: '[email protected]',
},
{
id: 2,
name: 'Roger',
age: 24,
}
]
};
dig(object, 'users.*.name'); // [ 'Roger', 'Oskang09' ]
dig(object, 'users.*.name,id') // [ { "name": "Oskang09", "id": 1 }, { "name": "Roger", "id": 2 }]
Result as Array / Object
You can make your result as object or array. etc.
const { dig } = require('digdata');
const object = {
class: 'LECTURE',
students: [
{
id: 1,
name: 'Oska'
},
{
id: 2,
name: 'WangLin',
},
{
id: 3,
name: "Yuzy"
}
],
};
dig(object, { classType: 'class', studentNames: 'students.*.name' }); // { "classType: "LECTURE", studentNames: [ "Oska", "WangLin", "Yuzy" ] }
dig(object, [ "class", "students.id=3.name" ]); // [ 'LECTURE', 'Yuzy' ]
Pipe Symbol
Pipe symbol |
is for taking first truth value form object. etc
const { dig } = require('digdata');
const object = {
name: 'Oska',
job: 'Developer',
};
dig(object, 'address|name|job'); // Oska
dig(object, 'address|job|name'); // Developer
Invoke Symbol
Invoke symbol &
is for assigning formatter function for value. You can set formatter globally by using method setFormatter(formatter)
before any dig
have invoked.
const { dig, setFormatter } = require('digdata');
const formatter = {
moment: function (value, object) {
return Date.parse(value);
}
};
const object = {
createdAt: '12 Dec 2019 00:12:00 GMT',
updatedAt: '12 Mac 2020 00:12:00 GMT'
};
let newObject = dig(object, { createdAt: 'createdAt&moment', updatedAt: 'updatedAt&moment' }, undefined, formatter);
console.log(typeof newObject.createdAt); // number
console.log(typeof newObject.updatedAt); // number
setFormatter(formatter);
newObject = dig(object, { createdAt: 'createdAt&moment', updatedAt: 'updatedAt&moment' });
console.log(typeof newObject.createdAt); // number
console.log(typeof newObject.updatedAt); // number
Custom symbols
You can override it by using setOptions(newOpts)
method.
const { dig, setOptions } = require('digdata');
// just change whatever you want and it's using assign so unassigned value will use default.
setOptions({
seperator: '->',
// comma: ',',
// equal: '=',
// arrayMap: '*',
// pipe: '|',
// invoke: '&',
});
const object = {
update: {
options: 'OK'
}
};
dig(object, 'update->options'): // 'OK'
Caching Cursor
Usually complex object we will have more than on operation on object and geting different key or array fields. so the idea is cache every single node accessing and store the object we access, when same key is exists will get the object directly instead search through whole object again. Of course single layer object is not required with this features.
const { dig, cursor: buildCursor } = require('digdata');
const object = {
owner: {
id: 14,
name: 'Jason',
age: 19,
client: {
name: 'Yuzy',
job: "Student",
},
users: [
{
id: 1,
name: 'Oskang09',
age: 20,
email: '[email protected]',
},
{
id: 2,
name: 'Roger',
age: 24,
special: true,
}
],
},
community: [
'Oskang09',
'Roger',
'Jason'
]
};
// you can pass previous cached cursor as first params
// custom options / symbols as second params
// we always encourage using same options for same object
const options = buildCursor();
// build cache "owner"
const a = dig(object, "owner", options);
// from cache "owner"
// build cache "owner.id"
const b = dig(object, "owner.id", options);
// from cache "owner"
// build cache "owner.client"
// build cache "owner.client.name"
const c = dig(object, "owner.client.name", options);
// from cache "owner.client"
// build cache "owner.client.job"
const d = dig(object, "owner.client.job", options);
// from cache "owner"
// build cache "owner.users"
// build cache "owner.users.*"
// build cache "owner.users.*.name"
const e = dig(object, "owner.users.*.name", options);
// from cache "owner.users.*"
// build cache "owner.users.*.id"
const f = dig(object, "owner.users.*.id", options);
// from cache "owner.users.*"
// build cache "owner.users.*.special"
const g = dig(object, "owner.users.*.special", options);
// from cache "owner.users"
// build cache "owner.users.name=Oskang09"
const h = dig(object, "owner.users.name=Oskang09", options);
// from cache "owner.users.name=Oskang09"
// build cache "owner.users.name=Oskang09.age"
const i = dig(object, "owner.users.name=Oskang09.age", options);
// you will see how cache json look likes, there also an example.
console.log(options.cursor);
Example cache json look like.
{
owner: {
id: 14,
name: 'Jason',
age: 19,
client: { name: 'Yuzy', job: 'Student' },
users: [ [Object], [Object] ]
},
'owner.id': 14,
'owner.client': { name: 'Yuzy', job: 'Student' },
'owner.client.name': 'Yuzy',
'owner.client.job': 'Student',
'owner.users': [
{
id: 1,
name: 'Oskang09',
age: 20,
email: '[email protected]'
},
{ id: 2, name: 'Roger', age: 24, special: true }
],
'owner.users.*': [
{
id: 1,
name: 'Oskang09',
age: 20,
email: '[email protected]'
},
{ id: 2, name: 'Roger', age: 24, special: true }
],
'owner.users.*.name': [ 'Oskang09', 'Roger' ],
'owner.users.*.id': null,
'owner.users.*.special': null,
'owner.users.name=Oskang09': {
id: 1,
name: 'Oskang09',
age: 20,
email: '[email protected]'
},
'owner.users.name=Oskang09.age': 20
}
Test & Coverages
PASS ./index.test.js
√ Should dot string notation accepted. (3ms)
√ Should object dot string notation accepted.
√ Should array dot string notation accepted. (1ms)
√ Should equal symbol return object if target is array object based on condition.
√ Should equal symbol return array if target is array based on condition.
√ Should equal symbol return null when target not exists. (1ms)
√ Should arrayMap symbol return specific key
√ Should comma symbol work with arrayMap symbol return multiple keys
√ Should pipe symbol return first truth value (1ms)
√ Should return null if target exists.
√ Should return null if object is falsy value.
√ Should run invoke if function and data found. (1ms)
√ Should skip if function not found.
√ Should `cursor` build options object
√ Should build cache when cursor not null
√ Should get from cache when cursor not null and key exist (1ms)
√ Should `withOptions` set disableTracker on options
√ Should `setOptions` update options object.
----------|---------|----------|---------|---------|-------------------
| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
| All files | 100 | 95.83 | 100 | 100 |
| index.js | 100 | 95.83 | 100 | 100 | 155,159 |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
Test Suites: 1 passed, 1 total
Tests: 18 passed, 18 total
Snapshots: 0 total
Time: 1.562s
Ran all test suites.