@jackens/nnn 2026.2.7 → 2026.2.11
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 +22 -11
- package/package.json +1 -1
- package/readme.md +125 -18
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,21 +7,32 @@ 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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
var get_target = (parent, parent_key, child_key) => {
|
|
11
|
+
if (parent_key == null) {
|
|
12
|
+
return parent;
|
|
13
|
+
}
|
|
14
|
+
if (!(parent_key in parent)) {
|
|
15
|
+
parent[parent_key] = is_string(child_key) && ARRAY_INDEX_REGEXP.test(child_key) ? [] : {};
|
|
16
|
+
}
|
|
17
|
+
return parent[parent_key];
|
|
18
|
+
};
|
|
19
|
+
var _vivify = (parent, parent_key) => new Proxy({}, {
|
|
20
|
+
get(_, key) {
|
|
21
|
+
const target = get_target(parent, parent_key, key);
|
|
22
|
+
if (target != null && typeof target === "object") {
|
|
23
|
+
return _vivify(target, key);
|
|
15
24
|
}
|
|
16
|
-
target[key]
|
|
17
|
-
return _vivify(target[key], target, key);
|
|
25
|
+
return target?.[key];
|
|
18
26
|
},
|
|
19
|
-
set(
|
|
20
|
-
|
|
21
|
-
target = parent[parentKey] = [];
|
|
22
|
-
}
|
|
27
|
+
set(_, key, value) {
|
|
28
|
+
const target = get_target(parent, parent_key, key);
|
|
23
29
|
target[key] = value;
|
|
24
30
|
return true;
|
|
31
|
+
},
|
|
32
|
+
deleteProperty(_, key) {
|
|
33
|
+
const target = get_target(parent, parent_key, key);
|
|
34
|
+
delete target[key];
|
|
35
|
+
return true;
|
|
25
36
|
}
|
|
26
37
|
});
|
|
27
38
|
var vivify = (ref) => _vivify(ref);
|
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,41 +1280,140 @@ 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
|
|
1276
1284
|
|
|
1277
|
-
expect(ref).to.deep.equal({
|
|
1285
|
+
expect(ref).to.deep.equal({
|
|
1286
|
+
one: {
|
|
1287
|
+
two: [
|
|
1288
|
+
undefined,
|
|
1289
|
+
[undefined, undefined, 42]
|
|
1290
|
+
]
|
|
1291
|
+
}
|
|
1292
|
+
})
|
|
1278
1293
|
|
|
1279
|
-
vivify(ref).one.two[
|
|
1294
|
+
vivify(ref).one.two[1][3] = 42
|
|
1280
1295
|
|
|
1281
|
-
expect(ref).to.deep.equal({
|
|
1296
|
+
expect(ref).to.deep.equal({
|
|
1297
|
+
one: {
|
|
1298
|
+
two: [
|
|
1299
|
+
undefined,
|
|
1300
|
+
[undefined, undefined, 42, 42]
|
|
1301
|
+
]
|
|
1302
|
+
}
|
|
1303
|
+
})
|
|
1282
1304
|
|
|
1283
|
-
vivify(ref).one.two[1] =
|
|
1305
|
+
vivify(ref).one.two[1] = 42
|
|
1284
1306
|
|
|
1285
|
-
expect(ref).to.deep.equal({
|
|
1307
|
+
expect(ref).to.deep.equal({
|
|
1308
|
+
one: {
|
|
1309
|
+
two: [
|
|
1310
|
+
undefined,
|
|
1311
|
+
42
|
|
1312
|
+
]
|
|
1313
|
+
}
|
|
1314
|
+
})
|
|
1315
|
+
|
|
1316
|
+
vivify(ref).one.two[3][0] = 42
|
|
1317
|
+
|
|
1318
|
+
expect(ref).to.deep.equal({
|
|
1319
|
+
one: {
|
|
1320
|
+
two: [
|
|
1321
|
+
undefined,
|
|
1322
|
+
42,
|
|
1323
|
+
undefined,
|
|
1324
|
+
[42]
|
|
1325
|
+
]
|
|
1326
|
+
}
|
|
1327
|
+
})
|
|
1328
|
+
|
|
1329
|
+
vivify(ref).one.two[3].length = 2
|
|
1330
|
+
|
|
1331
|
+
expect(ref).to.deep.equal({
|
|
1332
|
+
one: {
|
|
1333
|
+
two: [
|
|
1334
|
+
undefined,
|
|
1335
|
+
42,
|
|
1336
|
+
undefined,
|
|
1337
|
+
[42, undefined]
|
|
1338
|
+
]
|
|
1339
|
+
}
|
|
1340
|
+
})
|
|
1286
1341
|
|
|
1287
1342
|
vivify(ref).one.two = 12
|
|
1288
1343
|
|
|
1289
|
-
expect(ref).to.deep.equal({
|
|
1344
|
+
expect(ref).to.deep.equal({
|
|
1345
|
+
one: {
|
|
1346
|
+
two: 12
|
|
1347
|
+
}
|
|
1348
|
+
})
|
|
1290
1349
|
|
|
1291
1350
|
vivify(ref).one.two = undefined
|
|
1292
1351
|
|
|
1293
|
-
expect(ref).to.deep.equal({
|
|
1352
|
+
expect(ref).to.deep.equal({
|
|
1353
|
+
one: {
|
|
1354
|
+
two: undefined
|
|
1355
|
+
}
|
|
1356
|
+
})
|
|
1294
1357
|
|
|
1295
1358
|
delete vivify(ref).one.two
|
|
1296
1359
|
|
|
1297
|
-
expect(ref).to.deep.equal({
|
|
1360
|
+
expect(ref).to.deep.equal({
|
|
1361
|
+
one: {}
|
|
1362
|
+
})
|
|
1298
1363
|
|
|
1299
1364
|
delete vivify(ref).one.two.three
|
|
1300
1365
|
|
|
1301
|
-
expect(ref).to.deep.equal({
|
|
1366
|
+
expect(ref).to.deep.equal({
|
|
1367
|
+
one: {
|
|
1368
|
+
two: {}
|
|
1369
|
+
}
|
|
1370
|
+
})
|
|
1302
1371
|
|
|
1303
1372
|
vivify(ref).one.two.three.four
|
|
1304
1373
|
|
|
1305
|
-
expect(ref).to.deep.equal({
|
|
1374
|
+
expect(ref).to.deep.equal({
|
|
1375
|
+
one: {
|
|
1376
|
+
two: {
|
|
1377
|
+
three: {}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
})
|
|
1306
1381
|
|
|
1307
|
-
vivify(ref).one.two
|
|
1382
|
+
vivify(ref).one.two[3]
|
|
1308
1383
|
|
|
1309
|
-
expect(ref).to.deep.equal({
|
|
1384
|
+
expect(ref).to.deep.equal({
|
|
1385
|
+
one: {
|
|
1386
|
+
two: {
|
|
1387
|
+
three: {}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
})
|
|
1391
|
+
|
|
1392
|
+
vivify(ref).one.two.three.four = 42
|
|
1393
|
+
|
|
1394
|
+
expect(ref).to.deep.equal({
|
|
1395
|
+
one: {
|
|
1396
|
+
two: {
|
|
1397
|
+
three: {
|
|
1398
|
+
four: 42
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
})
|
|
1403
|
+
|
|
1404
|
+
const name = vivify(ref).one.two.three.four.toString.name
|
|
1405
|
+
|
|
1406
|
+
expect(name).to.deep.equal('toString')
|
|
1407
|
+
|
|
1408
|
+
expect(ref).to.deep.equal({
|
|
1409
|
+
one: {
|
|
1410
|
+
two: {
|
|
1411
|
+
three: {
|
|
1412
|
+
four: 42
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
})
|
|
1310
1417
|
```
|
|
1311
1418
|
|
|
1312
1419
|
## License
|