Comparing version 0.1.4 to 0.2.0
255
index.js
@@ -1,249 +0,6 @@ | ||
(function() { | ||
'use strict'; | ||
function DeepCopy() { | ||
this._defined = {}; | ||
} | ||
DeepCopy.prototype.clean = function(key) { | ||
if (key) { | ||
delete this._defined[key]; | ||
} else { | ||
this._defined = {}; | ||
} | ||
return this; | ||
}; | ||
/** | ||
* Define structure automatically | ||
*/ | ||
DeepCopy.prototype.define = function(key, structure) { | ||
if (this._defined[key]) { | ||
throw new Error(key + ' is already defined.'); | ||
} | ||
var analyze = new Analyze(structure); | ||
var def = this._defined[key] = { | ||
deep: createFunc(analyze.deep()), | ||
shallow: createFunc(analyze.shallow()) | ||
}; | ||
return def.deep; | ||
}; | ||
DeepCopy.prototype._get = function(type, key, obj) { | ||
if (!this._defined[key]) { | ||
this.define(key, obj); | ||
} | ||
return this._defined[key][type]; | ||
}; | ||
DeepCopy.prototype.shallow = function(key, obj) { | ||
var func = this._get('shallow', key, obj); | ||
return arguments.length === 1 ? func : func(obj); | ||
}; | ||
DeepCopy.prototype.clone = function(key, obj) { | ||
var func = this._get('deep', key, obj); | ||
return arguments.length === 1 ? func : func(obj); | ||
}; | ||
DeepCopy.prototype.copy = DeepCopy.prototype.clone; | ||
DeepCopy.prototype.deep = DeepCopy.prototype.clone; | ||
function Analyze(structure) { | ||
this._structure = structure; | ||
this._object = []; | ||
this._keys = []; | ||
} | ||
Analyze.prototype._analyze = function(structure, keys, depth, current) { | ||
if (structure === null) { | ||
return 'null'; | ||
} | ||
var type = typeof structure; | ||
if (type === 'function') { | ||
return structure; | ||
} | ||
var index = this._object.indexOf(structure); | ||
if (index >= 0) { | ||
return resolveKey(clone(this._keys[index])).key; | ||
} | ||
current = current || 0; | ||
if (current === depth || type !== 'object') { | ||
return type; | ||
} | ||
current++; | ||
var self = this; | ||
self._object.push(structure); | ||
self._keys.push(keys); | ||
structure = map(structure, function(value, key) { | ||
return self._analyze(value, keys.concat(key), depth, current); | ||
}); | ||
if (current === 1) { | ||
this._object = []; | ||
this._keys = []; | ||
} | ||
return structure; | ||
}; | ||
Analyze.prototype.deep = function() { | ||
return this._analyze(this._structure, ['c']); | ||
}; | ||
Analyze.prototype.shallow = function() { | ||
return this._analyze(this._structure, ['c'], 1); | ||
}; | ||
function clone(obj) { | ||
return map(obj, function(value) { | ||
return value; | ||
}); | ||
} | ||
function map(obj, iter) { | ||
var index = -1; | ||
var key, keys, size, result; | ||
if (Array.isArray(obj)) { | ||
size = obj.length; | ||
result = Array(size); | ||
while (++index < size) { | ||
result[index] = iter(obj[index], index); | ||
} | ||
} else { | ||
keys = Object.keys(obj); | ||
size = keys.length; | ||
result = {}; | ||
while (++index < size) { | ||
key = keys[index]; | ||
result[key] = iter(obj[key], key); | ||
} | ||
} | ||
return result; | ||
} | ||
function replace(str, value, exp) { | ||
exp = exp || /%s/; | ||
if (!str) { | ||
return str; | ||
} | ||
if (!value || typeof value !== 'object') { | ||
return str.replace(exp, value); | ||
} | ||
map(value, function(value) { | ||
str = str.replace(exp, value); | ||
}); | ||
return str; | ||
} | ||
function resolveKey(keys) { | ||
var str = '%s'; | ||
var key = '%s'; | ||
var k = keys.shift(); | ||
var l = keys.length; | ||
if (!l) { | ||
return { | ||
str: replace(str, k), | ||
key: k | ||
}; | ||
} | ||
str = replace(str, ['%s&&%s', k]); | ||
key = replace(key, ['%s["%s"]%s', k]); | ||
while (l--) { | ||
key = replace(key, keys.shift()); | ||
str = replace(str, l ? '%s&&%s' : '%s'); | ||
str = replace(str, replace(key, '')); | ||
key = replace(key, l ? '["%s"]%s' : ''); | ||
} | ||
return { | ||
str: str, | ||
key: key | ||
}; | ||
} | ||
function resolveValue(keys, value) { | ||
var str = '%s!==u?%s:%s'; | ||
var info = resolveKey(keys); | ||
str = replace(str, info); | ||
switch (value) { | ||
case 'string': | ||
return replace(str, replace('"%s"', '')); | ||
case 'number': | ||
return replace(str, 0); | ||
case 'undefined': | ||
return replace(str, undefined); | ||
case 'boolean': | ||
return replace(str, false); | ||
case 'null': | ||
return replace(str, null); | ||
case 'object': | ||
return replace(str, '{}'); | ||
default: | ||
if (typeof value === 'function') { | ||
return replace(str, value.toString()); | ||
} | ||
// circular structure | ||
return replace(replace('%c<%s|%s>', info.key), value); | ||
} | ||
} | ||
function createFuncStr(obj, keys, str) { | ||
var type = typeof obj; | ||
if (type !== 'object') { | ||
if (!str) { | ||
return resolveValue(keys, obj); | ||
} | ||
return replace(str, resolveValue(keys, obj)); | ||
} | ||
var isArray = Array.isArray(obj); | ||
var s = isArray ? '[%s],%s' : '{%s},%s'; | ||
map(obj, function(o, k) { | ||
s = isArray ? replace(s, '%s,%s') : replace(s, "\'" + k + "\'" + ':%s,%s'); | ||
s = createFuncStr(o, keys.concat(k), s); | ||
}); | ||
s = replace(s, '', /(%s|,%s)/g); | ||
return replace(str, s) || s; | ||
} | ||
// TODO resolve deep prototype | ||
function resolveProto(str, structure) { | ||
if (typeof structure === 'object') { | ||
str = replace(str, ['p="__proto__",', "c[p]=o&&o[p];"], /%p/); | ||
} else { | ||
str = replace(str, '', /%p/g); | ||
} | ||
return str; | ||
} | ||
function resolveCircular(str) { | ||
var exp = /%c<(.*?)>/; | ||
var bar = str.match(exp); | ||
if (!bar) { | ||
return str; | ||
} | ||
str = replace(str, 'u', exp); | ||
var param = bar[1].split(/\|/); | ||
var key = replace(param[0], 'c', /o/); | ||
var val = param[1]; | ||
var s = '%s=%s;'; | ||
s = replace(s, [key, val]); | ||
str = replace(str, ['%s%s', s]); | ||
return resolveCircular(str); | ||
} | ||
function createFunc(structure) { | ||
var base = '{var u,%pc=%s;%p%sreturn c;}'; | ||
var str = createFuncStr(structure, ['o'], ''); | ||
str = replace(base, str); | ||
str = resolveProto(str, structure); | ||
str = resolveCircular(str); | ||
str = replace(str, ''); | ||
return new Function('o', str); | ||
} | ||
if (typeof module === 'object' && module.exports) { | ||
module.exports = new DeepCopy(); | ||
} else { | ||
this.dcp = new DeepCopy(); | ||
} | ||
}.call(this)); | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const DeepCopy_1 = require("./lib/DeepCopy"); | ||
exports.DeepCopy = DeepCopy_1.DeepCopy; | ||
exports.default = new DeepCopy_1.DeepCopy(); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "dcp", | ||
"version": "0.1.4", | ||
"version": "0.2.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "./node_modules/.bin/_mocha -R spec ./test --recursive" | ||
"build": "tsp build", | ||
"test": "mocha test/**/*.ts" | ||
}, | ||
"author": "", | ||
"author": "Suguru Motegi <suguru.motegi@gmail.com>", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"lodash": "^4.13.1", | ||
"mocha": "^2.5.2" | ||
"@types/lodash": "^4.14.119", | ||
"@types/mocha": "^5.2.5", | ||
"@types/node": "^10.12.18", | ||
"husky": "^1.3.1", | ||
"lint-staged": "^8.1.0", | ||
"lodash": "^4.17.11", | ||
"mocha": "^5.2.0", | ||
"prettier": "^1.15.3", | ||
"ts-node": "^7.0.1", | ||
"ts-publisher": "^0.1.1", | ||
"typescript": "^3.2.2" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"lint-staged": { | ||
"*.{js,ts}": [ | ||
"prettier --write", | ||
"git add" | ||
] | ||
}, | ||
"prettier": { | ||
"printWidth": 100, | ||
"singleQuote": true, | ||
"trailingComma": "all" | ||
} | ||
} | ||
} |
111
README.md
@@ -1,2 +0,2 @@ | ||
# Deep CoPy | ||
# dcp | ||
@@ -7,32 +7,10 @@ [![npm](https://img.shields.io/npm/v/dcp.svg)](https://www.npmjs.com/package/dcp) | ||
It needs to be defined an object structure and the module will analyse the structure. | ||
If it isn't defined, it will be defined when it is called first time. | ||
## Usage | ||
## Feature | ||
### Runtime parsing | ||
### define(key, structure) | ||
If the reference of the base object is NOT changed, you can use it without defining a key. | ||
If it is called, functions which have the structure will be made. | ||
### clone(key, [object]) | ||
alias: deep, copy | ||
The deep clone will be made by defined structure. | ||
If the key isn't defined, `define` will be called and then the deep clone function will be called. | ||
### shallow(key, [object]) | ||
The shallow clone will be made. | ||
## Example | ||
```js | ||
var structure = { | ||
a: 1, | ||
b: 'default', | ||
c: [undefined, undefined], | ||
d: { d1: true } | ||
}; | ||
var obj = { | ||
const obj = { | ||
a: 10, | ||
@@ -42,4 +20,5 @@ c: [1, 2], | ||
}; | ||
dcp.define('test', structure); | ||
var newObj = dcp.clone('test', obj); | ||
// only first time, it will be parsed | ||
const newObj = dcp.clone(obj); | ||
/* | ||
@@ -51,16 +30,44 @@ * { a: 10, | ||
*/ | ||
``` | ||
// or | ||
var clone = dcp.clone('test', structure); | ||
var newObj = clone(obj); | ||
### Runtime parsing with a key | ||
// or | ||
dcp.define('test', structure); | ||
var clone = dcp.clone('test'); | ||
var newObj = clone(obj); | ||
If the reference is changed but the format is the same, you need to use it with a key. | ||
// or | ||
var newObj = dcp.clone('test', obj); | ||
```js | ||
// only first time, it will be parsed | ||
const newObj = dcp.clone('key1', obj); | ||
/* | ||
* { a: 10, | ||
* b: '', | ||
* c: [1, 2], | ||
* d: { d1: false } } | ||
*/ | ||
// get the default values | ||
const newObj2 = dcp.clone('key1'); | ||
/* | ||
* { a: 0, | ||
* b: '', | ||
* c: [0, 0], | ||
* d: { d1: false } } | ||
*/ | ||
``` | ||
### Pre-defined | ||
It is the fastest way, but the difference is only the first clone. | ||
```js | ||
const structure = { | ||
a: 1, | ||
b: 'default', | ||
c: [undefined, undefined], | ||
d: { d1: true } | ||
}; | ||
const key = 'test'; | ||
dcp.define(key, structure); | ||
const newObj = dcp.clone(key, obj); | ||
``` | ||
## Benchmark | ||
@@ -72,3 +79,3 @@ | ||
```js | ||
var obj = { | ||
const obj = { | ||
a: 1, | ||
@@ -91,7 +98,5 @@ b: 'test', | ||
var obj = _.mapValues(_.times(10), function(num) { | ||
return _.mapValues(_.times(num), function(num) { | ||
return _.mapValues(_.times(num)); | ||
}); | ||
}); | ||
const obj = _.mapValues(_.times(count), num => | ||
_.mapValues(_.times(num), num => _.mapValues(_.times(num))), | ||
); | ||
/* | ||
@@ -104,1 +109,19 @@ * **** benchmark.js **** | ||
``` | ||
## APIs | ||
### define | ||
arguments: (key: any, structure: any) | ||
arguments: (structure: any) | ||
If it is called, functions which have the structure will be made. | ||
### clone | ||
arguments: (key: any, structure: any) | ||
arguments: (structure: any) | ||
The deep clone will be made by defined structure. | ||
If the key isn't defined, `define` will be called and then the deep clone function will be called. | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
11
1
122
18284
11
264
1