dot-object 2.1.4 → 2.1.5

Sign up to get free protection for your applications and to get access to all the features.
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, sep).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
- })