Skip to content

Instantly share code, notes, and snippets.

@ptgamr
Created September 15, 2017 11:03
Show Gist options
  • Save ptgamr/ea1b711ca7785288a512eefd00b56fb0 to your computer and use it in GitHub Desktop.
Save ptgamr/ea1b711ca7785288a512eefd00b56fb0 to your computer and use it in GitHub Desktop.
dirty.js
const isValid = (v) => {
return v !== null && v !== undefined;
}
const isObject = (v) => {
return typeof(v) === 'object';
}
const isCallable = (v) => {
return typeof(v) === 'function';
}
const smartString = (v) => {
if( isValid(v) ) {
return `${v.constructor.name === 'Object' ? JSON.stringify(v) : v}`;
}
return `${v}`;
}
const defaultConfig = {
date: false,
name: 'dirty',
meta: 'meta',
setLogging: false,
getLogging: false
}
/// configuration
let config = Object.assign({}, defaultConfig);
const configure = (options = defaultConfig) => {
config = Object.assign({}, config, defaultConfig, options);
}
/// library
const __generate__ = (clz, key, val, path) => {
let _f = val;
return {
__proto__: null,
enumerable: true,
configurable: true,
get: function() {
if( config.getLogging ) {
console.log(`getting prop ${path}.${key}`)
}
return _f;
},
set: function(v) {
let meta = clz[config.meta][`${path}.${key}`]
if (!meta) {
meta = {
originalVal: val
}
clz[config.meta][`${path}.${key}`] = meta
}
meta.currentVal = v
if( config.setLogging ) {
console.log(`setting prop ${path}.${key} with ${smartString(v)}`)
}
_f = v;
}
}
}
const observe_child = (obj = {}, root, path) => {
if( !root ) root = obj;
const keys = Object.keys(obj);
for( let key of keys ) {
if( `${key}` === config.name ) continue;
// copy current value
let seed = obj[key];
// ignore functions
if( isCallable(seed) ) {
continue;
}
// delete existing value
delete obj[key];
Object.defineProperty(obj, key, __generate__(root, key, seed, path ? path : '' ))
if( isValid(seed) && isObject(seed) ) {
observe_child(seed, root, path ? `${path}.${key}` : key);
}
}
}
const observe = (root) => {
root[config.name] = false;
root[config.meta] = {};
observe_child(root);
return root;
}
const obj = {
name: 'anh',
address: {
line1: 'line1',
line2: 'line2',
},
child: [
{name: 'frank'},
{name: 'toni'}
]
}
configure({
name: '__dirty__',
meta: '__meta__',
setLogging: true
});
observe(obj)
obj.address.line1 = 'anh';
obj.address.line1 = 'em'
obj.child[0].name = 'other name';
obj.child[0] = {name: 'kaka'};
obj.child[0].name = 'other name';
console.log(JSON.stringify(obj, null, 2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment