dot-object 2.1.3 → 2.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/dot-object.js DELETED
@@ -1,583 +0,0 @@
1
- 'use strict'
2
-
3
- function _process (v, mod) {
4
- var i
5
- var r
6
-
7
- if (typeof mod === 'function') {
8
- r = mod(v)
9
- if (r !== undefined) {
10
- v = r
11
- }
12
- } else if (Array.isArray(mod)) {
13
- for (i = 0; i < mod.length; i++) {
14
- r = mod[i](v)
15
- if (r !== undefined) {
16
- v = r
17
- }
18
- }
19
- }
20
-
21
- return v
22
- }
23
-
24
- function parseKey (key, val) {
25
- // detect negative index notation
26
- if (key[0] === '-' && Array.isArray(val) && /^-\d+$/.test(key)) {
27
- return val.length + parseInt(key, 10)
28
- }
29
- return key
30
- }
31
-
32
- function isIndex (k) {
33
- return /^\d+$/.test(k)
34
- }
35
-
36
- function isObject (val) {
37
- return Object.prototype.toString.call(val) === '[object Object]'
38
- }
39
-
40
- function isArrayOrObject (val) {
41
- return Object(val) === val
42
- }
43
-
44
- function isEmptyObject (val) {
45
- return Object.keys(val).length === 0
46
- }
47
-
48
- var blacklist = ['__proto__', 'prototype', 'constructor']
49
- var blacklistFilter = function (part) { return blacklist.indexOf(part) === -1 }
50
-
51
- function parsePath (path, sep) {
52
- if (path.indexOf('[') >= 0) {
53
- path = path.replace(/\[/g, '.').replace(/]/g, '')
54
- }
55
-
56
- var parts = path.split(sep)
57
-
58
- var check = parts.filter(blacklistFilter)
59
-
60
- if (check.length !== parts.length) {
61
- throw Error('Refusing to update blacklisted property ' + path)
62
- }
63
-
64
- return parts
65
- }
66
-
67
- var hasOwnProperty = Object.prototype.hasOwnProperty
68
-
69
- function DotObject (separator, override, useArray, useBrackets) {
70
- if (!(this instanceof DotObject)) {
71
- return new DotObject(separator, override, useArray, useBrackets)
72
- }
73
-
74
- if (typeof override === 'undefined') override = false
75
- if (typeof useArray === 'undefined') useArray = true
76
- if (typeof useBrackets === 'undefined') useBrackets = true
77
- this.separator = separator || '.'
78
- this.override = override
79
- this.useArray = useArray
80
- this.useBrackets = useBrackets
81
- this.keepArray = false
82
-
83
- // contains touched arrays
84
- this.cleanup = []
85
- }
86
-
87
- var dotDefault = new DotObject('.', false, true, true)
88
- function wrap (method) {
89
- return function () {
90
- return dotDefault[method].apply(dotDefault, arguments)
91
- }
92
- }
93
-
94
- DotObject.prototype._fill = function (a, obj, v, mod) {
95
- var k = a.shift()
96
-
97
- if (a.length > 0) {
98
- obj[k] = obj[k] || (this.useArray && isIndex(a[0]) ? [] : {})
99
-
100
- if (!isArrayOrObject(obj[k])) {
101
- if (this.override) {
102
- obj[k] = {}
103
- } else {
104
- if (!(isArrayOrObject(v) && isEmptyObject(v))) {
105
- throw new Error(
106
- 'Trying to redefine `' + k + '` which is a ' + typeof obj[k]
107
- )
108
- }
109
-
110
- return
111
- }
112
- }
113
-
114
- this._fill(a, obj[k], v, mod)
115
- } else {
116
- if (!this.override && isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
117
- if (!(isArrayOrObject(v) && isEmptyObject(v))) {
118
- throw new Error("Trying to redefine non-empty obj['" + k + "']")
119
- }
120
-
121
- return
122
- }
123
-
124
- obj[k] = _process(v, mod)
125
- }
126
- }
127
-
128
- /**
129
- *
130
- * Converts an object with dotted-key/value pairs to it's expanded version
131
- *
132
- * Optionally transformed by a set of modifiers.
133
- *
134
- * Usage:
135
- *
136
- * var row = {
137
- * 'nr': 200,
138
- * 'doc.name': ' My Document '
139
- * }
140
- *
141
- * var mods = {
142
- * 'doc.name': [_s.trim, _s.underscored]
143
- * }
144
- *
145
- * dot.object(row, mods)
146
- *
147
- * @param {Object} obj
148
- * @param {Object} mods
149
- */
150
- DotObject.prototype.object = function (obj, mods) {
151
- var self = this
152
-
153
- Object.keys(obj).forEach(function (k) {
154
- var mod = mods === undefined ? null : mods[k]
155
- // normalize array notation.
156
- var ok = parsePath(k, self.separator).join(self.separator)
157
-
158
- if (ok.indexOf(self.separator) !== -1) {
159
- self._fill(ok.split(self.separator), obj, obj[k], mod)
160
- delete obj[k]
161
- } else {
162
- obj[k] = _process(obj[k], mod)
163
- }
164
- })
165
-
166
- return obj
167
- }
168
-
169
- /**
170
- * @param {String} path dotted path
171
- * @param {String} v value to be set
172
- * @param {Object} obj object to be modified
173
- * @param {Function|Array} mod optional modifier
174
- */
175
- DotObject.prototype.str = function (path, v, obj, mod) {
176
- var ok = parsePath(path, this.separator).join(this.separator)
177
-
178
- if (path.indexOf(this.separator) !== -1) {
179
- this._fill(ok.split(this.separator), obj, v, mod)
180
- } else {
181
- obj[path] = _process(v, mod)
182
- }
183
-
184
- return obj
185
- }
186
-
187
- /**
188
- *
189
- * Pick a value from an object using dot notation.
190
- *
191
- * Optionally remove the value
192
- *
193
- * @param {String} path
194
- * @param {Object} obj
195
- * @param {Boolean} remove
196
- */
197
- DotObject.prototype.pick = function (path, obj, remove, reindexArray) {
198
- var i
199
- var keys
200
- var val
201
- var key
202
- var cp
203
-
204
- keys = parsePath(path, this.separator)
205
- for (i = 0; i < keys.length; i++) {
206
- key = parseKey(keys[i], obj)
207
- if (obj && typeof obj === 'object' && key in obj) {
208
- if (i === keys.length - 1) {
209
- if (remove) {
210
- val = obj[key]
211
- if (reindexArray && Array.isArray(obj)) {
212
- obj.splice(key, 1)
213
- } else {
214
- delete obj[key]
215
- }
216
- if (Array.isArray(obj)) {
217
- cp = keys.slice(0, -1).join('.')
218
- if (this.cleanup.indexOf(cp) === -1) {
219
- this.cleanup.push(cp)
220
- }
221
- }
222
- return val
223
- } else {
224
- return obj[key]
225
- }
226
- } else {
227
- obj = obj[key]
228
- }
229
- } else {
230
- return undefined
231
- }
232
- }
233
- if (remove && Array.isArray(obj)) {
234
- obj = obj.filter(function (n) {
235
- return n !== undefined
236
- })
237
- }
238
- return obj
239
- }
240
- /**
241
- *
242
- * Delete value from an object using dot notation.
243
- *
244
- * @param {String} path
245
- * @param {Object} obj
246
- * @return {any} The removed value
247
- */
248
- DotObject.prototype.delete = function (path, obj) {
249
- return this.remove(path, obj, true)
250
- }
251
-
252
- /**
253
- *
254
- * Remove value from an object using dot notation.
255
- *
256
- * Will remove multiple items if path is an array.
257
- * In this case array indexes will be retained until all
258
- * removals have been processed.
259
- *
260
- * Use dot.delete() to automatically re-index arrays.
261
- *
262
- * @param {String|Array<String>} path
263
- * @param {Object} obj
264
- * @param {Boolean} reindexArray
265
- * @return {any} The removed value
266
- */
267
- DotObject.prototype.remove = function (path, obj, reindexArray) {
268
- var i
269
-
270
- this.cleanup = []
271
- if (Array.isArray(path)) {
272
- for (i = 0; i < path.length; i++) {
273
- this.pick(path[i], obj, true, reindexArray)
274
- }
275
- if (!reindexArray) {
276
- this._cleanup(obj)
277
- }
278
- return obj
279
- } else {
280
- return this.pick(path, obj, true, reindexArray)
281
- }
282
- }
283
-
284
- DotObject.prototype._cleanup = function (obj) {
285
- var ret
286
- var i
287
- var keys
288
- var root
289
- if (this.cleanup.length) {
290
- for (i = 0; i < this.cleanup.length; i++) {
291
- keys = this.cleanup[i].split('.')
292
- root = keys.splice(0, -1).join('.')
293
- ret = root ? this.pick(root, obj) : obj
294
- ret = ret[keys[0]].filter(function (v) {
295
- return v !== undefined
296
- })
297
- this.set(this.cleanup[i], ret, obj)
298
- }
299
- this.cleanup = []
300
- }
301
- }
302
-
303
- /**
304
- * Alias method for `dot.remove`
305
- *
306
- * Note: this is not an alias for dot.delete()
307
- *
308
- * @param {String|Array<String>} path
309
- * @param {Object} obj
310
- * @param {Boolean} reindexArray
311
- * @return {any} The removed value
312
- */
313
- DotObject.prototype.del = DotObject.prototype.remove
314
-
315
- /**
316
- *
317
- * Move a property from one place to the other.
318
- *
319
- * If the source path does not exist (undefined)
320
- * the target property will not be set.
321
- *
322
- * @param {String} source
323
- * @param {String} target
324
- * @param {Object} obj
325
- * @param {Function|Array} mods
326
- * @param {Boolean} merge
327
- */
328
- DotObject.prototype.move = function (source, target, obj, mods, merge) {
329
- if (typeof mods === 'function' || Array.isArray(mods)) {
330
- this.set(target, _process(this.pick(source, obj, true), mods), obj, merge)
331
- } else {
332
- merge = mods
333
- this.set(target, this.pick(source, obj, true), obj, merge)
334
- }
335
-
336
- return obj
337
- }
338
-
339
- /**
340
- *
341
- * Transfer a property from one object to another object.
342
- *
343
- * If the source path does not exist (undefined)
344
- * the property on the other object will not be set.
345
- *
346
- * @param {String} source
347
- * @param {String} target
348
- * @param {Object} obj1
349
- * @param {Object} obj2
350
- * @param {Function|Array} mods
351
- * @param {Boolean} merge
352
- */
353
- DotObject.prototype.transfer = function (
354
- source,
355
- target,
356
- obj1,
357
- obj2,
358
- mods,
359
- merge
360
- ) {
361
- if (typeof mods === 'function' || Array.isArray(mods)) {
362
- this.set(
363
- target,
364
- _process(this.pick(source, obj1, true), mods),
365
- obj2,
366
- merge
367
- )
368
- } else {
369
- merge = mods
370
- this.set(target, this.pick(source, obj1, true), obj2, merge)
371
- }
372
-
373
- return obj2
374
- }
375
-
376
- /**
377
- *
378
- * Copy a property from one object to another object.
379
- *
380
- * If the source path does not exist (undefined)
381
- * the property on the other object will not be set.
382
- *
383
- * @param {String} source
384
- * @param {String} target
385
- * @param {Object} obj1
386
- * @param {Object} obj2
387
- * @param {Function|Array} mods
388
- * @param {Boolean} merge
389
- */
390
- DotObject.prototype.copy = function (source, target, obj1, obj2, mods, merge) {
391
- if (typeof mods === 'function' || Array.isArray(mods)) {
392
- this.set(
393
- target,
394
- _process(
395
- // clone what is picked
396
- JSON.parse(JSON.stringify(this.pick(source, obj1, false))),
397
- mods
398
- ),
399
- obj2,
400
- merge
401
- )
402
- } else {
403
- merge = mods
404
- this.set(target, this.pick(source, obj1, false), obj2, merge)
405
- }
406
-
407
- return obj2
408
- }
409
-
410
- /**
411
- *
412
- * Set a property on an object using dot notation.
413
- *
414
- * @param {String} path
415
- * @param {any} val
416
- * @param {Object} obj
417
- * @param {Boolean} merge
418
- */
419
- DotObject.prototype.set = function (path, val, obj, merge) {
420
- var i
421
- var k
422
- var keys
423
- var key
424
-
425
- // Do not operate if the value is undefined.
426
- if (typeof val === 'undefined') {
427
- return obj
428
- }
429
- keys = parsePath(path, this.separator)
430
-
431
- for (i = 0; i < keys.length; i++) {
432
- key = keys[i]
433
- if (i === keys.length - 1) {
434
- if (merge && isObject(val) && isObject(obj[key])) {
435
- for (k in val) {
436
- if (hasOwnProperty.call(val, k)) {
437
- obj[key][k] = val[k]
438
- }
439
- }
440
- } else if (merge && Array.isArray(obj[key]) && Array.isArray(val)) {
441
- for (var j = 0; j < val.length; j++) {
442
- obj[keys[i]].push(val[j])
443
- }
444
- } else {
445
- obj[key] = val
446
- }
447
- } else if (
448
- // force the value to be an object
449
- !hasOwnProperty.call(obj, key) ||
450
- (!isObject(obj[key]) && !Array.isArray(obj[key]))
451
- ) {
452
- // initialize as array if next key is numeric
453
- if (/^\d+$/.test(keys[i + 1])) {
454
- obj[key] = []
455
- } else {
456
- obj[key] = {}
457
- }
458
- }
459
- obj = obj[key]
460
- }
461
- return obj
462
- }
463
-
464
- /**
465
- *
466
- * Transform an object
467
- *
468
- * Usage:
469
- *
470
- * var obj = {
471
- * "id": 1,
472
- * "some": {
473
- * "thing": "else"
474
- * }
475
- * }
476
- *
477
- * var transform = {
478
- * "id": "nr",
479
- * "some.thing": "name"
480
- * }
481
- *
482
- * var tgt = dot.transform(transform, obj)
483
- *
484
- * @param {Object} recipe Transform recipe
485
- * @param {Object} obj Object to be transformed
486
- * @param {Array} mods modifiers for the target
487
- */
488
- DotObject.prototype.transform = function (recipe, obj, tgt) {
489
- obj = obj || {}
490
- tgt = tgt || {}
491
- Object.keys(recipe).forEach(
492
- function (key) {
493
- this.set(recipe[key], this.pick(key, obj), tgt)
494
- }.bind(this)
495
- )
496
- return tgt
497
- }
498
-
499
- /**
500
- *
501
- * Convert object to dotted-key/value pair
502
- *
503
- * Usage:
504
- *
505
- * var tgt = dot.dot(obj)
506
- *
507
- * or
508
- *
509
- * var tgt = {}
510
- * dot.dot(obj, tgt)
511
- *
512
- * @param {Object} obj source object
513
- * @param {Object} tgt target object
514
- * @param {Array} path path array (internal)
515
- */
516
- DotObject.prototype.dot = function (obj, tgt, path) {
517
- tgt = tgt || {}
518
- path = path || []
519
- var isArray = Array.isArray(obj)
520
-
521
- Object.keys(obj).forEach(
522
- function (key) {
523
- var index = isArray && this.useBrackets ? '[' + key + ']' : key
524
- if (
525
- isArrayOrObject(obj[key]) &&
526
- ((isObject(obj[key]) && !isEmptyObject(obj[key])) ||
527
- (Array.isArray(obj[key]) && !this.keepArray && obj[key].length !== 0))
528
- ) {
529
- if (isArray && this.useBrackets) {
530
- var previousKey = path[path.length - 1] || ''
531
- return this.dot(
532
- obj[key],
533
- tgt,
534
- path.slice(0, -1).concat(previousKey + index)
535
- )
536
- } else {
537
- return this.dot(obj[key], tgt, path.concat(index))
538
- }
539
- } else {
540
- if (isArray && this.useBrackets) {
541
- tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
542
- } else {
543
- tgt[path.concat(index).join(this.separator)] = obj[key]
544
- }
545
- }
546
- }.bind(this)
547
- )
548
- return tgt
549
- }
550
-
551
- DotObject.pick = wrap('pick')
552
- DotObject.move = wrap('move')
553
- DotObject.transfer = wrap('transfer')
554
- DotObject.transform = wrap('transform')
555
- DotObject.copy = wrap('copy')
556
- DotObject.object = wrap('object')
557
- DotObject.str = wrap('str')
558
- DotObject.set = wrap('set')
559
- DotObject.delete = wrap('delete')
560
- DotObject.del = DotObject.remove = wrap('remove')
561
- DotObject.dot = wrap('dot');
562
- ['override', 'overwrite'].forEach(function (prop) {
563
- Object.defineProperty(DotObject, prop, {
564
- get: function () {
565
- return dotDefault.override
566
- },
567
- set: function (val) {
568
- dotDefault.override = !!val
569
- }
570
- })
571
- });
572
- ['useArray', 'keepArray', 'useBrackets'].forEach(function (prop) {
573
- Object.defineProperty(DotObject, prop, {
574
- get: function () {
575
- return dotDefault[prop]
576
- },
577
- set: function (val) {
578
- dotDefault[prop] = val
579
- }
580
- })
581
- })
582
-
583
- DotObject._process = _process
package/src/footer.tpl DELETED
@@ -1,13 +0,0 @@
1
-
2
-
3
- if (typeof define === 'function' && define.amd) {
4
- define(function() {
5
- return DotObject
6
- })
7
- } else if (typeof module != 'undefined' && module.exports) {
8
- module.exports = DotObject
9
- } else {
10
- global[exportName] = DotObject
11
- }
12
-
13
- })(this, 'DotObject')
package/src/header.tpl DELETED
@@ -1 +0,0 @@
1
- (function(global, exportName) {
package/test/_process.js DELETED
@@ -1,125 +0,0 @@
1
- 'use strict'
2
-
3
- require('should')
4
- var Dot = require('../index')
5
-
6
- describe('_process:', function () {
7
- describe('Should process modifier', function () {
8
- describe('if value is a string', function () {
9
- function up (val) {
10
- return val.toUpperCase()
11
- }
12
-
13
- it('using a single modifier', function () {
14
- Dot._process('k', up).should.eql('K')
15
- })
16
-
17
- it('using an array of modifiers', function () {
18
- var v = 'k'
19
- Dot._process(v, [up]).should.eql('K')
20
- })
21
- })
22
-
23
- describe('if value is an object', function () {
24
- function withReturn (val) {
25
- val.withReturn = 'return'
26
- return val
27
- }
28
-
29
- function noReturn (val) {
30
- val.noReturn = 'no return'
31
- }
32
-
33
- it('using a single modifier *with* return', function () {
34
- var a = {
35
- test: 1
36
- }
37
-
38
- var expected = {
39
- test: 1,
40
- withReturn: 'return'
41
- }
42
-
43
- var ret = Dot._process(a, withReturn)
44
- a.should.eql(expected)
45
- ret.should.eql(expected)
46
- })
47
-
48
- it('using a single modifier *without* return', function () {
49
- var a = {
50
- test: 1
51
- }
52
- var expected = {
53
- test: 1,
54
- noReturn: 'no return'
55
- }
56
- var ret = Dot._process(a, noReturn)
57
- a.should.eql(expected)
58
- ret.should.eql(expected)
59
- })
60
-
61
- it('using an array of modifiers *with* return and *without* return',
62
- function () {
63
- var a = {
64
- test: 1
65
- }
66
-
67
- var expected = {
68
- test: 1,
69
- withReturn: 'return',
70
- noReturn: 'no return'
71
- }
72
-
73
- var ret = Dot._process(a, [withReturn, noReturn])
74
-
75
- a.should.eql(expected)
76
- ret.should.eql(expected)
77
- }
78
- )
79
- })
80
-
81
- describe('if value is an array', function () {
82
- function withReturn (val) {
83
- val.push('return')
84
- return val
85
- }
86
-
87
- function noReturn (val) {
88
- val.push('no return')
89
- }
90
-
91
- it('using a single modifier *with* return', function () {
92
- var a = [1]
93
-
94
- var expected = [1, 'return']
95
-
96
- var ret = Dot._process(a, withReturn)
97
- a.should.eql(expected)
98
- ret.should.eql(expected)
99
- })
100
-
101
- it('using a single modifier *without* return', function () {
102
- var a = [1]
103
-
104
- var expected = [1, 'no return']
105
-
106
- var ret = Dot._process(a, noReturn)
107
- a.should.eql(expected)
108
- ret.should.eql(expected)
109
- })
110
-
111
- it('using an array of modifiers *with* return and *without* return',
112
- function () {
113
- var a = [1]
114
-
115
- var expected = [1, 'return', 'no return']
116
-
117
- var ret = Dot._process(a, [withReturn, noReturn])
118
-
119
- a.should.eql(expected)
120
- ret.should.eql(expected)
121
- }
122
- )
123
- })
124
- })
125
- })