@jackens/nnn 2026.2.7 → 2026.2.13
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/nnn.d.ts +13 -5
- package/nnn.js +20 -17
- package/package.json +1 -1
- package/readme.md +48 -14
package/nnn.d.ts
CHANGED
|
@@ -440,12 +440,20 @@ export declare const uuid_v1: (date?: Date, node?: string) => string;
|
|
|
440
440
|
/**
|
|
441
441
|
* A Proxy-based helper for auto-vivification of nested object structures.
|
|
442
442
|
*
|
|
443
|
-
* Accessing any property on the returned proxy automatically creates
|
|
444
|
-
* (or
|
|
445
|
-
* allowing deep assignments without explicit null checks.
|
|
443
|
+
* Accessing, assigning, or deleting any nested property on the returned proxy automatically creates intermediate objects
|
|
444
|
+
* (or arrays for numeric-string keys matching `^(0|[1-9]\d*)$`) as needed, allowing deep operations without explicit null checks.
|
|
446
445
|
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
446
|
+
* Intermediates of the last level in a get-only property chain are NOT auto-created.
|
|
447
|
+
* For example, `vivify(ref).one.two` will create `ref.one` as `{}`, but will NOT create `ref.one.two`.
|
|
448
|
+
* Only when a deeper access, assignment, or deletion occurs
|
|
449
|
+
* (e.g. `vivify(ref).one.two[3]` or `vivify(ref).one.two.three = 42`) will `ref.one.two` be materialized.
|
|
450
|
+
*
|
|
451
|
+
* When traversal reaches a primitive value, no auto-creation happens;
|
|
452
|
+
* the primitive’s own property is returned instead
|
|
453
|
+
* (e.g. accessing `.toString.name` on a number yields `'toString'` without modifying the underlying structure).
|
|
454
|
+
*
|
|
455
|
+
* Deletion on a non-existing intermediate path will auto-create intermediates up to the parent of the deleted key
|
|
456
|
+
* (e.g. `delete vivify(ref).a.b.c` will create `ref.a.b` as `{}` if it does not exist).
|
|
449
457
|
*
|
|
450
458
|
* @param ref
|
|
451
459
|
*
|
package/nnn.js
CHANGED
|
@@ -7,24 +7,27 @@ var is_string = (arg) => typeof arg === "string";
|
|
|
7
7
|
|
|
8
8
|
// src/nnn/vivify.ts
|
|
9
9
|
var ARRAY_INDEX_REGEXP = /^(0|[1-9]\d*)$/;
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
var _is_object = (ref) => typeof ref === "object";
|
|
11
|
+
var _get_target = (parent, parent_key, key) => parent[parent_key] ??= is_string(key) && ARRAY_INDEX_REGEXP.test(key) ? [] : {};
|
|
12
|
+
var _vivify = (parent, parent_key) => {
|
|
13
|
+
return parent != null && _is_object(parent) ? new Proxy(parent, {
|
|
14
|
+
get(_, key) {
|
|
15
|
+
const target = _get_target(parent, parent_key, key);
|
|
16
|
+
const value = target[key];
|
|
17
|
+
return is_string(key) && _is_object(target) && (value == null || _is_object(value)) ? _vivify(target, key) : value;
|
|
18
|
+
},
|
|
19
|
+
set(_, key, value) {
|
|
20
|
+
const target = _get_target(parent, parent_key, key);
|
|
21
|
+
target[key] = value;
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
deleteProperty(_, key) {
|
|
25
|
+
const target = _get_target(parent, parent_key, key);
|
|
26
|
+
return delete target[key];
|
|
15
27
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
set(target, key, value) {
|
|
20
|
-
if (should_convert_target_to_array(target, key, parent)) {
|
|
21
|
-
target = parent[parentKey] = [];
|
|
22
|
-
}
|
|
23
|
-
target[key] = value;
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
var vivify = (ref) => _vivify(ref);
|
|
28
|
+
}) : parent?.[parent_key];
|
|
29
|
+
};
|
|
30
|
+
var vivify = (ref) => _vivify({ _: ref }, "_");
|
|
28
31
|
|
|
29
32
|
// src/nnn/c.ts
|
|
30
33
|
var _c = (node, prefix, result, splitter) => {
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1252,12 +1252,20 @@ const vivify: (ref: unknown) => any;
|
|
|
1252
1252
|
|
|
1253
1253
|
A Proxy-based helper for auto-vivification of nested object structures.
|
|
1254
1254
|
|
|
1255
|
-
Accessing any property on the returned proxy automatically creates
|
|
1256
|
-
(or
|
|
1257
|
-
allowing deep assignments without explicit null checks.
|
|
1255
|
+
Accessing, assigning, or deleting any nested property on the returned proxy automatically creates intermediate objects
|
|
1256
|
+
(or arrays for numeric-string keys matching `^(0|[1-9]\d*)$`) as needed, allowing deep operations without explicit null checks.
|
|
1258
1257
|
|
|
1259
|
-
|
|
1260
|
-
|
|
1258
|
+
Intermediates of the last level in a get-only property chain are NOT auto-created.
|
|
1259
|
+
For example, `vivify(ref).one.two` will create `ref.one` as `{}`, but will NOT create `ref.one.two`.
|
|
1260
|
+
Only when a deeper access, assignment, or deletion occurs
|
|
1261
|
+
(e.g. `vivify(ref).one.two[3]` or `vivify(ref).one.two.three = 42`) will `ref.one.two` be materialized.
|
|
1262
|
+
|
|
1263
|
+
When traversal reaches a primitive value, no auto-creation happens;
|
|
1264
|
+
the primitive’s own property is returned instead
|
|
1265
|
+
(e.g. accessing `.toString.name` on a number yields `'toString'` without modifying the underlying structure).
|
|
1266
|
+
|
|
1267
|
+
Deletion on a non-existing intermediate path will auto-create intermediates up to the parent of the deleted key
|
|
1268
|
+
(e.g. `delete vivify(ref).a.b.c` will create `ref.a.b` as `{}` if it does not exist).
|
|
1261
1269
|
|
|
1262
1270
|
#### ref
|
|
1263
1271
|
|
|
@@ -1272,17 +1280,29 @@ A proxy that auto-creates nested objects/arrays on property access.
|
|
|
1272
1280
|
```ts
|
|
1273
1281
|
const ref: any = {}
|
|
1274
1282
|
|
|
1275
|
-
vivify(ref).one.two[
|
|
1283
|
+
vivify(ref).one.two[1][2] = 42
|
|
1284
|
+
|
|
1285
|
+
expect(ref).to.deep.equal({ one: { two: [undefined, [undefined, undefined, 42]] } })
|
|
1286
|
+
|
|
1287
|
+
vivify(ref).one.two[1][3] = 42
|
|
1288
|
+
|
|
1289
|
+
expect(ref).to.deep.equal({ one: { two: [undefined, [undefined, undefined, 42, 42]] } })
|
|
1290
|
+
|
|
1291
|
+
vivify(ref).one.two[1] = 42
|
|
1292
|
+
|
|
1293
|
+
expect(ref).to.deep.equal({ one: { two: [undefined, 42] } })
|
|
1294
|
+
|
|
1295
|
+
vivify(ref).one.two[3][0] = 42
|
|
1276
1296
|
|
|
1277
|
-
expect(ref).to.deep.equal({ one: { two: [, , , [
|
|
1297
|
+
expect(ref).to.deep.equal({ one: { two: [undefined, 42, undefined, [42]] } })
|
|
1278
1298
|
|
|
1279
|
-
vivify(ref).one.two[3]
|
|
1299
|
+
vivify(ref).one.two[3].length = 2
|
|
1280
1300
|
|
|
1281
|
-
expect(ref).to.deep.equal({ one: { two: [, , , [,
|
|
1301
|
+
expect(ref).to.deep.equal({ one: { two: [undefined, 42, undefined, [42, undefined]] } })
|
|
1282
1302
|
|
|
1283
|
-
vivify(ref).one.two
|
|
1303
|
+
expect(vivify(ref).one.two.length).to.deep.equal(4)
|
|
1284
1304
|
|
|
1285
|
-
expect(ref).to.deep.equal({ one: { two: [,
|
|
1305
|
+
expect(ref).to.deep.equal({ one: { two: [undefined, 42, undefined, [42, undefined]] } })
|
|
1286
1306
|
|
|
1287
1307
|
vivify(ref).one.two = 12
|
|
1288
1308
|
|
|
@@ -1296,17 +1316,31 @@ delete vivify(ref).one.two
|
|
|
1296
1316
|
|
|
1297
1317
|
expect(ref).to.deep.equal({ one: {} })
|
|
1298
1318
|
|
|
1319
|
+
expect(vivify(ref).one.toString instanceof Function).to.be.true
|
|
1320
|
+
|
|
1321
|
+
expect(vivify(ref).one.toString.name).to.equal('toString')
|
|
1322
|
+
|
|
1323
|
+
expect(ref).to.deep.equal({ one: {} })
|
|
1324
|
+
|
|
1299
1325
|
delete vivify(ref).one.two.three
|
|
1300
1326
|
|
|
1301
1327
|
expect(ref).to.deep.equal({ one: { two: {} } })
|
|
1302
1328
|
|
|
1303
1329
|
vivify(ref).one.two.three.four
|
|
1304
1330
|
|
|
1305
|
-
expect(ref).to.deep.equal({ one: { two: { three: {
|
|
1331
|
+
expect(ref).to.deep.equal({ one: { two: { three: {} } } })
|
|
1332
|
+
|
|
1333
|
+
vivify(ref).one.two[3]
|
|
1334
|
+
|
|
1335
|
+
expect(ref).to.deep.equal({ one: { two: { three: {} } } })
|
|
1336
|
+
|
|
1337
|
+
vivify(ref).one.two.three.four = 42
|
|
1338
|
+
|
|
1339
|
+
expect(ref).to.deep.equal({ one: { two: { three: { four: 42 } } } })
|
|
1306
1340
|
|
|
1307
|
-
vivify(ref).one.two.three.four
|
|
1341
|
+
expect(vivify(ref).one.two.three.four.toString.name).to.deep.equal('toString')
|
|
1308
1342
|
|
|
1309
|
-
expect(ref).to.deep.equal({ one: { two: { three: { four:
|
|
1343
|
+
expect(ref).to.deep.equal({ one: { two: { three: { four: 42 } } } })
|
|
1310
1344
|
```
|
|
1311
1345
|
|
|
1312
1346
|
## License
|