manyfest 1.0.38 → 1.0.40
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/README.md
CHANGED
|
@@ -42,15 +42,15 @@ const libManyfest = require('Manyfest');
|
|
|
42
42
|
|
|
43
43
|
// Construct a Manyfest with a few defined columns
|
|
44
44
|
let animalManyfest = new libManyfest(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
{
|
|
46
|
+
"Scope": "Animal",
|
|
47
|
+
"Descriptors":
|
|
48
|
+
{
|
|
49
|
+
"IDAnimal": { "Name":"Database ID", "Description":"The unique integer-based database identifier for an Animal record.", "DataType":"Integer", "Default":0 },
|
|
50
|
+
"Name": { "Description":"The animal's colloquial species name (e.g. Rabbit, Dog, Bear, Mongoose)." },
|
|
51
|
+
"Type": { "Description":"Whether or not the animal is wild, domesticated, agricultural, in a research lab or a part of a zoo.." }
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
54
|
|
|
55
55
|
// Make up a cute and furry test creature
|
|
56
56
|
let testAnimal = {IDAnimal:8675309, Name:'BatBrains', Type:'Lab', Color:'Brown'};
|
|
@@ -93,29 +93,29 @@ Let's use our Animal schema and extend it a little bit. In this case, a new JSO
|
|
|
93
93
|
|
|
94
94
|
```javascript
|
|
95
95
|
let animalManyfest = new libManyfest(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
96
|
+
{
|
|
97
|
+
"Scope": "Animal",
|
|
98
|
+
"Descriptors":
|
|
99
|
+
{
|
|
100
|
+
"IDAnimal": { "Name":"Database ID", "Description":"The unique integer-based database identifier for an Animal record.", "DataType":"Integer" },
|
|
101
|
+
"Name": { "Description":"The animal's colloquial species name (e.g. Rabbit, Dog, Bear, Mongoose)." },
|
|
102
|
+
"Type": { "Description":"Whether or not the animal is wild, domesticated, agricultural, in a research lab or a part of a zoo.." },
|
|
103
|
+
"MedicalStats":
|
|
104
|
+
{
|
|
105
|
+
"Name":"Medical Statistics", "Description":"Basic medical statistics for this animal"
|
|
106
|
+
},
|
|
107
|
+
"MedicalStats.Temps.MinET": { "Name":"Minimum Environmental Temperature", "NameShort":"MinET", "Description":"Safest minimum temperature for this animal to survive in."},
|
|
108
|
+
"MedicalStats.Temps.MaxET": { "Name":"Maximum Environmental Temperature", "NameShort":"MaxET", "Description":"Safest maximum temperature for this animal to survive in."},
|
|
109
|
+
"MedicalStats.Temps.CET":
|
|
110
|
+
{
|
|
111
|
+
"Name":"Comfortable Environmental Temperature",
|
|
112
|
+
"NameShort":"Comf Env Temp",
|
|
113
|
+
"Hash":"ComfET",
|
|
114
|
+
"DataType":"Float",
|
|
115
|
+
"Description":"The most comfortable temperature for this animal to survive in."
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
Notice in this example, the addresses are more complex. They have a dot syntax. This notifies Manyfest that they are nested values. Further, there is both a Name and a NameShort descriptor setup. This gives us a framework for consistently referring to the data element both internally and to the user. It is no longer a mystery what someAnimal.MedicalStats.Temps.CET means. Developers, user interface designers, database engineers, product managers and other folks who work on the software side don't have to maintain a third body of documentation about what the data means.
|
|
@@ -135,10 +135,15 @@ Boolean | A boolean value represented by the JSON true or false
|
|
|
135
135
|
Binary | A boolean value represented as 1 or 0
|
|
136
136
|
YesNo | A boolean value represented as Y or N
|
|
137
137
|
DateTime | A javascript date
|
|
138
|
+
Key | A two-part Key with an Identifier and Globally Unique Identifier (ID and GUID)
|
|
138
139
|
Array | A plain old javascript array
|
|
139
140
|
Object | A plain old javascript object
|
|
140
141
|
Null | A null value
|
|
141
142
|
|
|
143
|
+
#### Keys
|
|
144
|
+
|
|
145
|
+
Keys are a slightly more complex value type, in that they have configuration that defines cardinality. The address is meant to point to one of two of the values (either the GUID or the ID). There is a secondary parameter for the other.
|
|
146
|
+
|
|
142
147
|
## Reading and Writing Element Properties
|
|
143
148
|
|
|
144
149
|
Lastly, when working with objects, Manyfest provides a set of functions to read and write from/to these element addresses. This can be useful for consistently accessing objects across boundaries as well as filling out element defaults without requiring a crazy amount of boilerplate code.
|
|
@@ -221,15 +226,15 @@ const libManyfest = require('Manyfest');
|
|
|
221
226
|
|
|
222
227
|
// Construct a Manyfest with a few defined columns
|
|
223
228
|
let animalManyfest = new libManyfest(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
{
|
|
230
|
+
"Scope": "Animal",
|
|
231
|
+
"Descriptors":
|
|
232
|
+
{
|
|
233
|
+
"IDAnimal": { "Name":"Database ID", "Description":"The unique integer-based database identifier for an Animal record.", "DataType":"Integer" },
|
|
234
|
+
"Name": { "Description":"The animal's colloquial species name (e.g. Rabbit, Dog, Bear, Mongoose)." },
|
|
235
|
+
"Type": { "Description":"Whether or not the animal is wild, domesticated, agricultural, in a research lab or a part of a zoo.." }
|
|
236
|
+
}
|
|
237
|
+
});
|
|
233
238
|
```
|
|
234
239
|
|
|
235
240
|
The programmatic equivalent is the following code:
|
|
@@ -269,250 +274,250 @@ There is an API to access their data. It's ... really messy, the data you get b
|
|
|
269
274
|
|
|
270
275
|
```JSON
|
|
271
276
|
{
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
277
|
+
"created": 1664830085,
|
|
278
|
+
"d1": "ia600202.us.archive.org",
|
|
279
|
+
"d2": "ia800202.us.archive.org",
|
|
280
|
+
"dir": "/7/items/FrankenberryCountChoculaTevevisionCommercial1971",
|
|
281
|
+
"files": [
|
|
282
|
+
{
|
|
283
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000001.jpg",
|
|
284
|
+
"source": "derivative",
|
|
285
|
+
"format": "Thumbnail",
|
|
286
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
287
|
+
"mtime": "1296336956",
|
|
288
|
+
"size": "838",
|
|
289
|
+
"md5": "e47269cd5a82db9594f265a65785ec12",
|
|
290
|
+
"crc32": "165c668b",
|
|
291
|
+
"sha1": "383303d9546c381267569ad4e33aff691f0bb8c7"
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000004.jpg",
|
|
295
|
+
"source": "derivative",
|
|
296
|
+
"format": "Thumbnail",
|
|
297
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
298
|
+
"mtime": "1296336957",
|
|
299
|
+
"size": "6843",
|
|
300
|
+
"md5": "c93fa52000ab4665e69b25c403e11aff",
|
|
301
|
+
"crc32": "9444e6f6",
|
|
302
|
+
"sha1": "716b4f9950b8147f51d3265f9c62ff86451308d5"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000009.jpg",
|
|
306
|
+
"source": "derivative",
|
|
307
|
+
"format": "Thumbnail",
|
|
308
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
309
|
+
"mtime": "1296336957",
|
|
310
|
+
"size": "8388",
|
|
311
|
+
"md5": "30eb3eb4cbbdfa08d531a0a74da7c000",
|
|
312
|
+
"crc32": "be874a9e",
|
|
313
|
+
"sha1": "0c392d777609e967b6022be27edad678c5ae74e2"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000014.jpg",
|
|
317
|
+
"source": "derivative",
|
|
318
|
+
"format": "Thumbnail",
|
|
319
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
320
|
+
"mtime": "1296336958",
|
|
321
|
+
"size": "5993",
|
|
322
|
+
"md5": "4e9ebc3d076bec8cf7dfe76795f8c769",
|
|
323
|
+
"crc32": "912ec98c",
|
|
324
|
+
"sha1": "01dc49c852e1bbb421199450dd902935c62b06de"
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000019.jpg",
|
|
328
|
+
"source": "derivative",
|
|
329
|
+
"format": "Thumbnail",
|
|
330
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
331
|
+
"mtime": "1296336958",
|
|
332
|
+
"size": "4951",
|
|
333
|
+
"md5": "59f190f0c5b0a048415b26412860b6dd",
|
|
334
|
+
"crc32": "a70a30b1",
|
|
335
|
+
"sha1": "a284af9757cb24d28f96ec88ec1b1c23a8cea9fe"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000024.jpg",
|
|
339
|
+
"source": "derivative",
|
|
340
|
+
"format": "Thumbnail",
|
|
341
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
342
|
+
"mtime": "1296336959",
|
|
343
|
+
"size": "3383",
|
|
344
|
+
"md5": "be2a908acd563b896e7758b598295148",
|
|
345
|
+
"crc32": "ed467831",
|
|
346
|
+
"sha1": "94c001e72ebc86d837a78c61a004db9ab9d597bd"
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971.thumbs/frankerberry_countchockula_1971.0001_000029.jpg",
|
|
350
|
+
"source": "derivative",
|
|
351
|
+
"format": "Thumbnail",
|
|
352
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
353
|
+
"mtime": "1296336960",
|
|
354
|
+
"size": "3503",
|
|
355
|
+
"md5": "c82199d09be07633000fd07b363dd8a3",
|
|
356
|
+
"crc32": "a1fd79cb",
|
|
357
|
+
"sha1": "2bc8e761edb24a441fa5906dda1c424e1f98a47a"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971_archive.torrent",
|
|
361
|
+
"source": "metadata",
|
|
362
|
+
"btih": "de6b371e7cc3c83db1cc08150500753eae533409",
|
|
363
|
+
"mtime": "1542761794",
|
|
364
|
+
"size": "4093",
|
|
365
|
+
"md5": "a275d3b4028cccb5bea8b47a88c838af",
|
|
366
|
+
"crc32": "5ffa7334",
|
|
367
|
+
"sha1": "af8222637b574cba1360d0ea77e231640ffd43c4",
|
|
368
|
+
"format": "Archive BitTorrent"
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971_files.xml",
|
|
372
|
+
"source": "metadata",
|
|
373
|
+
"format": "Metadata",
|
|
374
|
+
"md5": "3a7e87b08bed1e203a5858b31352c110"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971_meta.xml",
|
|
378
|
+
"source": "metadata",
|
|
379
|
+
"format": "Metadata",
|
|
380
|
+
"mtime": "1542761793",
|
|
381
|
+
"size": "1371",
|
|
382
|
+
"md5": "0b9c9bf21b9a26aea43a2f735b404624",
|
|
383
|
+
"crc32": "41077288",
|
|
384
|
+
"sha1": "22e6f2c73bf63072f671d846355da2785db51dbd"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "FrankenberryCountChoculaTevevisionCommercial1971_reviews.xml",
|
|
388
|
+
"source": "original",
|
|
389
|
+
"mtime": "1466898697",
|
|
390
|
+
"size": "620",
|
|
391
|
+
"md5": "260bfba5d696772445dcc7ff6e6d5bdb",
|
|
392
|
+
"crc32": "25ea3229",
|
|
393
|
+
"sha1": "7d541f18fcd5ad9c6e593afe5a80f18771f23b32",
|
|
394
|
+
"format": "Metadata"
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"name": "__ia_thumb.jpg",
|
|
398
|
+
"source": "original",
|
|
399
|
+
"mtime": "1539115881",
|
|
400
|
+
"size": "7481",
|
|
401
|
+
"md5": "8cec324fa0016fd77cc04e6a4b2ebb00",
|
|
402
|
+
"crc32": "d9e1b316",
|
|
403
|
+
"sha1": "4dab42952fe0405a3b7f80146636b33d7b1bd01e",
|
|
404
|
+
"format": "Item Tile",
|
|
405
|
+
"rotation": "0"
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"name": "frankerberry_countchockula_1971.0001.gif",
|
|
409
|
+
"source": "derivative",
|
|
410
|
+
"format": "Animated GIF",
|
|
411
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
412
|
+
"mtime": "1296336965",
|
|
413
|
+
"size": "101114",
|
|
414
|
+
"md5": "b78a13094030f104900eb996bafe2b7d",
|
|
415
|
+
"crc32": "6650cd8",
|
|
416
|
+
"sha1": "669798c037205cac14f70592deef6f7831b3d4a1"
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
"name": "frankerberry_countchockula_1971.0001.mpg",
|
|
420
|
+
"source": "original",
|
|
421
|
+
"format": "MPEG2",
|
|
422
|
+
"mtime": "1296335803",
|
|
423
|
+
"size": "31625216",
|
|
424
|
+
"md5": "762ba18b026b85b3f074523e7fcb4db0",
|
|
425
|
+
"crc32": "42347f78",
|
|
426
|
+
"sha1": "41162dc2d1a91b618124c84628d0c231544a02be",
|
|
427
|
+
"length": "31.14",
|
|
428
|
+
"height": "480",
|
|
429
|
+
"width": "640"
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"name": "frankerberry_countchockula_1971.0001.mpg.idx",
|
|
433
|
+
"source": "derivative",
|
|
434
|
+
"format": "Video Index",
|
|
435
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
436
|
+
"mtime": "1296336956",
|
|
437
|
+
"size": "31141",
|
|
438
|
+
"md5": "49423e072726e4ea3cdd8ebdd26c7dfc",
|
|
439
|
+
"crc32": "ae969a68",
|
|
440
|
+
"sha1": "805782cd2d0f9002555816daadf3b8607e621f79"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"name": "frankerberry_countchockula_1971.0001.ogv",
|
|
444
|
+
"source": "derivative",
|
|
445
|
+
"format": "Ogg Video",
|
|
446
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
447
|
+
"mtime": "1296336994",
|
|
448
|
+
"size": "2248166",
|
|
449
|
+
"md5": "f1b933e97ce63594fb28a0a019ff3436",
|
|
450
|
+
"crc32": "a2a0e5e9",
|
|
451
|
+
"sha1": "a6bf0aec9f006baeca37c03f586686ebe685d59b",
|
|
452
|
+
"length": "31.15",
|
|
453
|
+
"height": "300",
|
|
454
|
+
"width": "400"
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
"name": "frankerberry_countchockula_1971.0001_512kb.mp4",
|
|
458
|
+
"source": "derivative",
|
|
459
|
+
"format": "512Kb MPEG4",
|
|
460
|
+
"original": "frankerberry_countchockula_1971.0001.mpg",
|
|
461
|
+
"mtime": "1296336977",
|
|
462
|
+
"size": "2378677",
|
|
463
|
+
"md5": "a7750839519c61ba3bb99fc66b32011d",
|
|
464
|
+
"crc32": "4dbd37c8",
|
|
465
|
+
"sha1": "3929314c192dec006fac2739bcb4730788e8c068",
|
|
466
|
+
"length": "31.13",
|
|
467
|
+
"height": "240",
|
|
468
|
+
"width": "320"
|
|
469
|
+
}
|
|
470
|
+
],
|
|
471
|
+
"files_count": 17,
|
|
472
|
+
"item_last_updated": 1542761794,
|
|
473
|
+
"item_size": 36431778,
|
|
474
|
+
"metadata": {
|
|
475
|
+
"identifier": "FrankenberryCountChoculaTevevisionCommercial1971",
|
|
476
|
+
"title": "Franken Berry / Count Chocula : Tevevision Commercial 1971",
|
|
477
|
+
"creator": "General Mills",
|
|
478
|
+
"mediatype": "movies",
|
|
479
|
+
"collection": [
|
|
480
|
+
"classic_tv_commercials",
|
|
481
|
+
"television"
|
|
482
|
+
],
|
|
483
|
+
"description": "Count Chocula and Franken Berry were both introduced in 1971. Boo Berry Cereal appeared in 1973 followed by Fruit Brute in 1974. Yummy Mummy appeared more than a decade later in 1988 - completing the the group known as the General Mills Monster Cereals.",
|
|
484
|
+
"subject": "Third Eye Cinema; Classic Television Commercials; animation; cartoons;General Mills",
|
|
485
|
+
"licenseurl": "http://creativecommons.org/publicdomain/mark/1.0/",
|
|
486
|
+
"publicdate": "2011-01-29 21:36:42",
|
|
487
|
+
"addeddate": "2011-01-29 21:35:38",
|
|
488
|
+
"uploader": "bolexman@msn.com",
|
|
489
|
+
"updater": [
|
|
490
|
+
"Bolexman",
|
|
491
|
+
"Bolexman",
|
|
492
|
+
"Jeff Kaplan"
|
|
493
|
+
],
|
|
494
|
+
"updatedate": [
|
|
495
|
+
"2011-01-29 21:45:38",
|
|
496
|
+
"2011-01-29 21:55:46",
|
|
497
|
+
"2011-01-29 23:04:55"
|
|
498
|
+
],
|
|
499
|
+
"sound": "sound",
|
|
500
|
+
"color": "color",
|
|
501
|
+
"runtime": "0:31",
|
|
502
|
+
"backup_location": "ia903608_22",
|
|
503
|
+
"ia_orig__runtime": "31 seconds"
|
|
504
|
+
},
|
|
505
|
+
"reviews": [
|
|
506
|
+
{
|
|
507
|
+
"reviewbody": "Sugar cereal cartoon Karloff and Lugosi argue self-importance pre Lorre ghost. Interesting how kids still know the voices without any idea of the origins.",
|
|
508
|
+
"reviewtitle": "pre booberry",
|
|
509
|
+
"reviewer": "outofthebox",
|
|
510
|
+
"reviewdate": "2016-06-25 23:51:36",
|
|
511
|
+
"createdate": "2016-06-25 23:51:36",
|
|
512
|
+
"stars": "4"
|
|
513
|
+
}
|
|
514
|
+
],
|
|
515
|
+
"server": "ia800202.us.archive.org",
|
|
516
|
+
"uniq": 1957612749,
|
|
517
|
+
"workable_servers": [
|
|
518
|
+
"ia800202.us.archive.org",
|
|
519
|
+
"ia600202.us.archive.org"
|
|
520
|
+
]
|
|
516
521
|
}
|
|
517
522
|
```
|
|
518
523
|
|
|
@@ -522,51 +527,51 @@ With just a small number of element descriptors, we can make this huge blob of J
|
|
|
522
527
|
|
|
523
528
|
```JSON
|
|
524
529
|
{
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
530
|
+
"Scope": "Archive.org",
|
|
531
|
+
"Descriptors": {
|
|
532
|
+
"d1": {
|
|
533
|
+
"Hash": "Server",
|
|
534
|
+
"Name": "Server",
|
|
535
|
+
"Description": "The primary server to download these files from.",
|
|
536
|
+
"DataType": "String"
|
|
537
|
+
},
|
|
538
|
+
"d2": {
|
|
539
|
+
"Hash": "ServerAlternate",
|
|
540
|
+
"Name": "Alternate Server",
|
|
541
|
+
"Description": "The alternate server to download these files from.",
|
|
542
|
+
"DataType": "String"
|
|
543
|
+
},
|
|
544
|
+
"dir": {
|
|
545
|
+
"Hash": "Path",
|
|
546
|
+
"Name": "Server URL Path",
|
|
547
|
+
"NameShort": "Path",
|
|
548
|
+
"Description": "The path on the server where these files are located."
|
|
549
|
+
},
|
|
550
|
+
"metadata.identifier": {
|
|
551
|
+
"Hash": "GUID",
|
|
552
|
+
"Name": "Globally Unique Identifier",
|
|
553
|
+
"NameShort": "GUID",
|
|
554
|
+
"Description": "Archive.org unique identifier string."
|
|
555
|
+
},
|
|
556
|
+
"metadata.title": {
|
|
557
|
+
"Hash": "Title",
|
|
558
|
+
"Name": "Title",
|
|
559
|
+
"NameShort": "Title",
|
|
560
|
+
"Description": "The title of the media item."
|
|
561
|
+
},
|
|
562
|
+
"metadata.creator": {
|
|
563
|
+
"Hash": "Creator",
|
|
564
|
+
"Name": "Creator",
|
|
565
|
+
"NameShort": "Creator",
|
|
566
|
+
"Description": "The creator of the media item."
|
|
567
|
+
},
|
|
568
|
+
"metadata.mediatype": {
|
|
569
|
+
"Hash": "Type",
|
|
570
|
+
"Name": "Media Type",
|
|
571
|
+
"NameShort": "Type",
|
|
572
|
+
"Description": "The type of media item."
|
|
573
|
+
}
|
|
574
|
+
}
|
|
570
575
|
}
|
|
571
576
|
```
|
|
572
577
|
|
|
@@ -582,6 +587,102 @@ let _Schema = new libManyfest(schemaArchiveOrg);
|
|
|
582
587
|
|
|
583
588
|
console.log(`The URL for "${_Schema.getValueByHash(dataArchiveOrg,'Title')}" is: ${_Schema.getValueByHash(dataArchiveOrg,'Server')}${_Schema.getValueByHash(dataArchiveOrg,'Path')}`);
|
|
584
589
|
```
|
|
585
|
-
# Architectural TODO:
|
|
586
590
|
|
|
587
|
-
|
|
591
|
+
### A Manyfest Schema for Book records
|
|
592
|
+
|
|
593
|
+
This shows a book record with an Author Key as well.
|
|
594
|
+
|
|
595
|
+
```JSON
|
|
596
|
+
{
|
|
597
|
+
"Scope": "Book",
|
|
598
|
+
"Descriptors": {
|
|
599
|
+
"GUIDBook": {
|
|
600
|
+
"Hash": "GUIDBook",
|
|
601
|
+
"Name": "Book GUID",
|
|
602
|
+
"DataType": "Key",
|
|
603
|
+
"KeyRepresentation": "GUID",
|
|
604
|
+
"GUIDAddress": "GUIDBook",
|
|
605
|
+
"IDAddress": "IDBook"
|
|
606
|
+
},
|
|
607
|
+
"IDBook": {
|
|
608
|
+
"Hash": "IDBook",
|
|
609
|
+
"Name": "Book Identifier",
|
|
610
|
+
"DataType": "Key",
|
|
611
|
+
"KeyRepresentation": "ID",
|
|
612
|
+
"GUIDAddress": "GUIDBook",
|
|
613
|
+
"IDAddress": "IDBook"
|
|
614
|
+
},
|
|
615
|
+
"Title": {
|
|
616
|
+
"Hash": "Title",
|
|
617
|
+
"Name": "Book Title",
|
|
618
|
+
"DataType": "String"
|
|
619
|
+
},
|
|
620
|
+
"IDAuthor": {
|
|
621
|
+
"Hash": "Book_IDAuthor",
|
|
622
|
+
"Name": "Book Primary Author",
|
|
623
|
+
"DataType": "Key",
|
|
624
|
+
"KeyRepresentation": "ID",
|
|
625
|
+
"GUIDAddress": "GUIDAuthor",
|
|
626
|
+
"IDAddress": "IDAuthor"
|
|
627
|
+
},
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
Because we expect only one scope to be the controlling scope for a particular key pair, we can use the key pair presence as a mechnism for resolution of IDs to GUIDs when they aren't natural.
|
|
633
|
+
|
|
634
|
+
What does this mean in practice?
|
|
635
|
+
|
|
636
|
+
If we have the following Book record:
|
|
637
|
+
|
|
638
|
+
```JSON
|
|
639
|
+
{
|
|
640
|
+
"GUIDBook": "SCIFI-000-Dune",
|
|
641
|
+
"Title": "Dune",
|
|
642
|
+
"GUIDAuthor": "AUTHOR-FRANK-HERBERT"
|
|
643
|
+
}
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
And the following Author record:
|
|
647
|
+
|
|
648
|
+
```JSON
|
|
649
|
+
{
|
|
650
|
+
"GUIDAuthor": "AUTHOR-FRANK-HERBERT",
|
|
651
|
+
"IDAuthor": 1001,
|
|
652
|
+
"Name": "Frank Herbert"
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
#### This gives rise to the need for a "Key" data type which is a tuple
|
|
658
|
+
|
|
659
|
+
The tuple will be a GUID or ID, but will represent both. As long as only one entity in the controlling scope (the Book table for instance) to have *both* the ID and the GUID, this can be used to make that the source of record for the Key. This allows lookups back and forth between GUID and ID.
|
|
660
|
+
|
|
661
|
+
1. Author is the cannonical source for finding the GUIDAuthor->IDAuthor connection, and vice versa. Because it is the only record shape in the model space that contains both.
|
|
662
|
+
2. GUIDAuthor is not in the Descriptors as a secondary address, but IDAuthor is. GUIDAuthor is, though, resolvable from the IDAuthor GUIDAddress property.
|
|
663
|
+
3. This means we want to treat the "GUIDAuthor"/"IDAuthor" pairing as a single entry in a manyfest, which is a departure from how the rest of them operate.
|
|
664
|
+
|
|
665
|
+
## BELOW WILL BE IN Pict
|
|
666
|
+
|
|
667
|
+
## Record "Sieve"s
|
|
668
|
+
|
|
669
|
+
Sometimes we want to take a record from a source shape, and translate it into a destination shape. This can be done with an implicit sieve or an explicit sieve.
|
|
670
|
+
|
|
671
|
+
### Handy Assertions for Working with a Sieve
|
|
672
|
+
|
|
673
|
+
* A record is a single object without loops.
|
|
674
|
+
* A record is part of a RecordSet.
|
|
675
|
+
* A record has an RecordSet key (e.g. "Users", "Projects", "Books", etc.).
|
|
676
|
+
* A record may have an Entity key (e.g. "Users", "Projects", "Books", etc.).
|
|
677
|
+
* The difference between RecordSet and Entity is that an Entity is a Record associated with a Key is expected to be stored in an Entity Storage System of some kind whereas a RecordSet Record might be abstract.
|
|
678
|
+
* A Record has a Key which represents a GUID and Identifier.
|
|
679
|
+
* GUIDs are RecordSet scoped strings that are unique to a Record.
|
|
680
|
+
* Identifiers are RecordSet Storage scoped strings or numbers that are unique to a Record.
|
|
681
|
+
* There is only one cannonical provider of each Record Entity
|
|
682
|
+
* When creating a sieve instance, we are going to migrate sets of records from one schema to another.
|
|
683
|
+
|
|
684
|
+
### Implicit Sieve
|
|
685
|
+
|
|
686
|
+
An implicit sieve embeds the configuration for Projection(s) within the current recordset. There is a Projection array, each of which has an entry for basic record projections. This should be good enough for simple transformation operations.
|
|
687
|
+
|
|
688
|
+
Each of these Projections come as a simple record shape with templated expressions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "manyfest",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"description": "JSON Object Manifest for Data Description and Parsing",
|
|
5
5
|
"main": "source/Manyfest.js",
|
|
6
6
|
"scripts": {
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"fable-serviceproviderbase": "^3.0.
|
|
47
|
+
"fable-serviceproviderbase": "^3.0.15"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"quackage": "^1.0.
|
|
50
|
+
"quackage": "^1.0.41"
|
|
51
51
|
},
|
|
52
52
|
"author": "steven velozo <steven@velozo.com>",
|
|
53
53
|
"license": "MIT",
|
|
@@ -66,6 +66,24 @@ class ManyfestObjectAddressSetValue
|
|
|
66
66
|
// The "Name" of the Object contained too the left of the bracket
|
|
67
67
|
let tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();
|
|
68
68
|
|
|
69
|
+
// The "Reference" to the property within it, either an array element or object property
|
|
70
|
+
let tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();
|
|
71
|
+
// Attempt to parse the reference as a number, which will be used as an array element
|
|
72
|
+
let tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
|
|
73
|
+
let tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);
|
|
74
|
+
|
|
75
|
+
if (pObject[tmpBoxedPropertyName] == null)
|
|
76
|
+
{
|
|
77
|
+
if (tmpIndexIsNumeric)
|
|
78
|
+
{
|
|
79
|
+
pObject[tmpBoxedPropertyName] = [];
|
|
80
|
+
}
|
|
81
|
+
else
|
|
82
|
+
{
|
|
83
|
+
pObject[tmpBoxedPropertyName] = {};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
69
87
|
// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.
|
|
70
88
|
// This is a rare case where Arrays testing as Objects is useful
|
|
71
89
|
if (typeof(pObject[tmpBoxedPropertyName]) !== 'object')
|
|
@@ -73,11 +91,6 @@ class ManyfestObjectAddressSetValue
|
|
|
73
91
|
return false;
|
|
74
92
|
}
|
|
75
93
|
|
|
76
|
-
// The "Reference" to the property within it, either an array element or object property
|
|
77
|
-
let tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();
|
|
78
|
-
// Attempt to parse the reference as a number, which will be used as an array element
|
|
79
|
-
let tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
|
|
80
|
-
|
|
81
94
|
// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
|
|
82
95
|
// This seems confusing to me at first read, so explaination:
|
|
83
96
|
// Is the Boxed Object an Array? TRUE
|
|
@@ -98,12 +111,25 @@ class ManyfestObjectAddressSetValue
|
|
|
98
111
|
tmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);
|
|
99
112
|
tmpBoxedPropertyReference = this.cleanWrapCharacters("'", tmpBoxedPropertyReference);
|
|
100
113
|
|
|
114
|
+
if (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]))
|
|
115
|
+
{
|
|
116
|
+
// If the subobject doesn't exist, create it
|
|
117
|
+
pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};
|
|
118
|
+
}
|
|
119
|
+
|
|
101
120
|
// Return the value in the property
|
|
121
|
+
//TODO: For cases where we have chained [][] properties, this needs to recurse somehow
|
|
102
122
|
pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = pValue;
|
|
103
123
|
return true;
|
|
104
124
|
}
|
|
105
125
|
else
|
|
106
126
|
{
|
|
127
|
+
while(pObject[tmpBoxedPropertyName].length < (tmpBoxedPropertyNumber + 1))
|
|
128
|
+
{
|
|
129
|
+
// If the subobject doesn't exist, create it
|
|
130
|
+
pObject[tmpBoxedPropertyName].push({});
|
|
131
|
+
}
|
|
132
|
+
|
|
107
133
|
pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber] = pValue;
|
|
108
134
|
return true;
|
|
109
135
|
}
|
|
@@ -144,6 +170,20 @@ class ManyfestObjectAddressSetValue
|
|
|
144
170
|
let tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();
|
|
145
171
|
|
|
146
172
|
let tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
|
|
173
|
+
let tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);
|
|
174
|
+
|
|
175
|
+
//if (typeof(pObject[tmpBoxedPropertyName]) !== 'object')
|
|
176
|
+
if (pObject[tmpBoxedPropertyName] == null)
|
|
177
|
+
{
|
|
178
|
+
if (tmpIndexIsNumeric)
|
|
179
|
+
{
|
|
180
|
+
pObject[tmpBoxedPropertyName] = [];
|
|
181
|
+
}
|
|
182
|
+
else
|
|
183
|
+
{
|
|
184
|
+
pObject[tmpBoxedPropertyName] = {};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
147
187
|
|
|
148
188
|
// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
|
|
149
189
|
// This seems confusing to me at first read, so explaination:
|
|
@@ -159,7 +199,7 @@ class ManyfestObjectAddressSetValue
|
|
|
159
199
|
// BUT
|
|
160
200
|
// StudentData.Sections.Algebra.Students is an array, so the ["JaneDoe"].Grade is not possible to access
|
|
161
201
|
// TODO: Should this be an error or something? Should we keep a log of failures like this?
|
|
162
|
-
if (Array.isArray(pObject[tmpBoxedPropertyName])
|
|
202
|
+
if (Array.isArray(pObject[tmpBoxedPropertyName]) != tmpIndexIsNumeric)
|
|
163
203
|
{
|
|
164
204
|
return false;
|
|
165
205
|
}
|
|
@@ -174,11 +214,23 @@ class ManyfestObjectAddressSetValue
|
|
|
174
214
|
tmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);
|
|
175
215
|
tmpBoxedPropertyReference = this.cleanWrapCharacters("'", tmpBoxedPropertyReference);
|
|
176
216
|
|
|
217
|
+
if (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]))
|
|
218
|
+
{
|
|
219
|
+
// If the subobject doesn't exist, create it
|
|
220
|
+
pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};
|
|
221
|
+
}
|
|
222
|
+
|
|
177
223
|
// Recurse directly into the subobject
|
|
178
224
|
return this.setValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, pValue);
|
|
179
225
|
}
|
|
180
226
|
else
|
|
181
227
|
{
|
|
228
|
+
while(pObject[tmpBoxedPropertyName].length < (tmpBoxedPropertyNumber + 1))
|
|
229
|
+
{
|
|
230
|
+
// If the subobject doesn't exist, create it
|
|
231
|
+
pObject[tmpBoxedPropertyName].push({});
|
|
232
|
+
}
|
|
233
|
+
|
|
182
234
|
// We parsed a valid number out of the boxed property name, so recurse into the array
|
|
183
235
|
return this.setValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, pValue);
|
|
184
236
|
}
|
|
@@ -227,6 +227,12 @@
|
|
|
227
227
|
"color": "color",
|
|
228
228
|
"runtime": "0:31",
|
|
229
229
|
"backup_location": "ia903608_22",
|
|
230
|
+
"synthesizer": {
|
|
231
|
+
"name": "Manyfest",
|
|
232
|
+
"version": "1.0.38",
|
|
233
|
+
"description": "JSON Object Manifest for Data Description and Parsing",
|
|
234
|
+
"author": "The chocula himself"
|
|
235
|
+
},
|
|
230
236
|
"ia_orig__runtime": "31 seconds"
|
|
231
237
|
},
|
|
232
238
|
"reviews": [
|
|
@@ -58,6 +58,8 @@ suite
|
|
|
58
58
|
Expect(tmpNullValue).to.equal(null);
|
|
59
59
|
Expect(tmpNullValueOneDeep).to.equal(undefined);
|
|
60
60
|
Expect(tmpNullValueTwoDeep).to.equal(undefined);
|
|
61
|
+
Expect(tmpNullValueTwoDeepObject).to.equal(undefined);
|
|
62
|
+
Expect(tmpNullValueTwoDeepArray).to.equal(undefined);
|
|
61
63
|
fTestComplete();
|
|
62
64
|
}
|
|
63
65
|
);
|
|
@@ -136,6 +138,12 @@ suite
|
|
|
136
138
|
// The .. means go back one level
|
|
137
139
|
let tmpDir = _Manyfest.getValueAtAddress(_SampleDataArchiveOrgFrankenberry, 'files[0]..dir');
|
|
138
140
|
Expect(tmpDir).to.equal("/7/items/FrankenberryCountChoculaTevevisionCommercial1971");
|
|
141
|
+
// Test a middle of address boxed object property
|
|
142
|
+
let tmpEmbeddedObjectBracket = _Manyfest.getValueAtAddress(_SampleDataArchiveOrgFrankenberry, 'metadata["synthesizer"].author');
|
|
143
|
+
Expect(tmpEmbeddedObjectBracket).to.equal('The chocula himself');
|
|
144
|
+
// Test a middle of address boxed object property where the boxed object is missing
|
|
145
|
+
let tmpEmbeddedObjectBracketMissingMidTierObject = _Manyfest.getValueAtAddress(_SampleDataArchiveOrgFrankenberry, 'metadata["chef"].author');
|
|
146
|
+
Expect(tmpEmbeddedObjectBracketMissingMidTierObject).to.be.undefined;
|
|
139
147
|
fTestComplete();
|
|
140
148
|
}
|
|
141
149
|
);
|
|
@@ -131,7 +131,10 @@ suite
|
|
|
131
131
|
(fTestComplete)=>
|
|
132
132
|
{
|
|
133
133
|
let _Manyfest = new libManyfest();
|
|
134
|
-
let _Object = {
|
|
134
|
+
let _Object = {RaceHeats: [
|
|
135
|
+
{HeatNumber:1, Dogs:{RunnerUp:'Fido',Loser:'Spot',Winner:'Trinity'}},
|
|
136
|
+
{HeatNumber:2, Dogs:{RunnerUp:'Rex',Loser:'Max',Winner:'Buddy'}}
|
|
137
|
+
], Dogs:{RunnerUp:{Name:'Fido',Speed:100},Loser:{Name:'Spot'},Winner:{Name:'Trinity'}}};
|
|
135
138
|
_Manyfest.setValueAtAddress(_Object, 'Dogs[`RunnerUp`].Speed', 300);
|
|
136
139
|
Expect(_Object.Dogs.RunnerUp.Speed)
|
|
137
140
|
.to.equal(300);
|
|
@@ -139,6 +142,13 @@ suite
|
|
|
139
142
|
_Manyfest.setValueAtAddress(_Object, 'Dogs[`Loser`].Speed', 10);
|
|
140
143
|
Expect(_Object.Dogs.Loser.Speed)
|
|
141
144
|
.to.equal(10);
|
|
145
|
+
// Set a value for an address and boxed object property that doesn't exist.
|
|
146
|
+
_Manyfest.setValueAtAddress(_Object, 'Dogs[`CriterionCollection`].MovieRating', 10000);
|
|
147
|
+
Expect(_Object.Dogs.CriterionCollection.MovieRating)
|
|
148
|
+
.to.equal(10000);
|
|
149
|
+
_Manyfest.setValueAtAddress(_Object, 'RaceHeats[2].HeatNumber', 10001);
|
|
150
|
+
Expect(_Object.RaceHeats[2].HeatNumber)
|
|
151
|
+
.to.equal(10001);
|
|
142
152
|
fTestComplete();
|
|
143
153
|
}
|
|
144
154
|
);
|
|
@@ -155,6 +165,52 @@ suite
|
|
|
155
165
|
fTestComplete();
|
|
156
166
|
}
|
|
157
167
|
);
|
|
168
|
+
test
|
|
169
|
+
(
|
|
170
|
+
'Indexed subobject are settable',
|
|
171
|
+
(fTestComplete)=>
|
|
172
|
+
{
|
|
173
|
+
let _Manyfest = new libManyfest({});
|
|
174
|
+
let _SimpleObject = {};
|
|
175
|
+
_Manyfest.setValueAtAddress(_SimpleObject, `_Object['SubObject'].Property`, '123');
|
|
176
|
+
Expect(_Manyfest.getValueAtAddress(_SimpleObject, `_Object.SubObject.Property`))
|
|
177
|
+
.to.equal('123');
|
|
178
|
+
Expect(_SimpleObject._Object.SubObject.Property)
|
|
179
|
+
.to.equal('123');
|
|
180
|
+
fTestComplete();
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
test
|
|
184
|
+
(
|
|
185
|
+
'Indexed subobject are settable unquoted',
|
|
186
|
+
(fTestComplete)=>
|
|
187
|
+
{
|
|
188
|
+
let _Manyfest = new libManyfest({});
|
|
189
|
+
let _SimpleObject = {};
|
|
190
|
+
_Manyfest.setValueAtAddress(_SimpleObject, `_Object[SubObject].Property`, '123');
|
|
191
|
+
Expect(_Manyfest.getValueAtAddress(_SimpleObject, `_Object.SubObject.Property`))
|
|
192
|
+
.to.equal('123');
|
|
193
|
+
Expect(_SimpleObject._Object.SubObject.Property)
|
|
194
|
+
.to.equal('123');
|
|
195
|
+
fTestComplete();
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
//TODO: known broken case for multiple bracketed properties
|
|
199
|
+
test.skip
|
|
200
|
+
(
|
|
201
|
+
'Indexed subobject are settable double brackets',
|
|
202
|
+
(fTestComplete)=>
|
|
203
|
+
{
|
|
204
|
+
let _Manyfest = new libManyfest({});
|
|
205
|
+
let _SimpleObject = {};
|
|
206
|
+
_Manyfest.setValueAtAddress(_SimpleObject, `_Object[SubObject]['Property']`, '123');
|
|
207
|
+
Expect(_Manyfest.getValueAtAddress(_SimpleObject, `_Object.SubObject.Property`))
|
|
208
|
+
.to.equal('123');
|
|
209
|
+
Expect(_SimpleObject._Object.SubObject.Property)
|
|
210
|
+
.to.equal('123');
|
|
211
|
+
fTestComplete();
|
|
212
|
+
}
|
|
213
|
+
);
|
|
158
214
|
}
|
|
159
215
|
);
|
|
160
216
|
}
|