@rljson/rljson 0.0.52 → 0.0.55

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/dist/example.d.ts CHANGED
@@ -7,6 +7,10 @@ export declare class Example {
7
7
  singleRow: () => Rljson;
8
8
  multipleRows: () => Rljson;
9
9
  singleRef: () => Rljson;
10
+ singleSliceIdRef: () => Rljson;
11
+ singleNamedRef: () => Rljson;
12
+ multiRef: () => Rljson;
13
+ multiMixedRef: () => Rljson;
10
14
  complete: () => Rljson;
11
15
  };
12
16
  static readonly broken: {
@@ -19,7 +23,11 @@ export declare class Example {
19
23
  missingData: () => Rljson;
20
24
  dataNotBeingAnArray: () => Rljson;
21
25
  missingRef: () => Rljson;
26
+ missingNamedRef: () => Rljson;
27
+ missingMultiRef: () => Rljson;
22
28
  missingReferencedTable: () => Rljson;
29
+ missingSliceId: () => Rljson;
30
+ missingSliceIdTable: () => Rljson;
23
31
  };
24
32
  tableCfg: {
25
33
  wrongType: () => Rljson;
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './content/table-cfg.ts';
8
8
  export * from './example.ts';
9
9
  export * from './example/bakery-example.ts';
10
10
  export * from './rljson.ts';
11
+ export * from './tools/remove-duplicates.ts';
11
12
  export * from './typedefs.ts';
12
13
  export * from './validate/base-validator.ts';
13
14
  export * from './validate/validate.ts';
package/dist/rljson.js CHANGED
@@ -291,6 +291,109 @@ __publicField(_Example, "ok", {
291
291
  }
292
292
  };
293
293
  },
294
+ singleSliceIdRef: () => {
295
+ return {
296
+ exampleSliceId: {
297
+ _type: "sliceIds",
298
+ _data: [
299
+ {
300
+ add: ["id0", "id1"]
301
+ }
302
+ ]
303
+ },
304
+ exampleComponent: {
305
+ _type: "components",
306
+ _data: [
307
+ {
308
+ exampleSliceId: "id0"
309
+ }
310
+ ]
311
+ }
312
+ };
313
+ },
314
+ singleNamedRef: () => {
315
+ return {
316
+ tableA: {
317
+ _type: "components",
318
+ _data: [
319
+ {
320
+ keyA0: "a0"
321
+ },
322
+ {
323
+ keyA1: "a1"
324
+ }
325
+ ]
326
+ },
327
+ tableB: {
328
+ _type: "components",
329
+ _data: [
330
+ {
331
+ namedRef: { component: "tableA", ref: "KFQrf4mEz0UPmUaFHwH4T6" }
332
+ }
333
+ ]
334
+ }
335
+ };
336
+ },
337
+ multiRef: () => {
338
+ return {
339
+ tableA: {
340
+ _type: "components",
341
+ _data: [
342
+ {
343
+ keyA0: "a0"
344
+ },
345
+ {
346
+ keyA1: "a1"
347
+ }
348
+ ]
349
+ },
350
+ tableB: {
351
+ _type: "components",
352
+ _data: [
353
+ {
354
+ tableARef: ["KFQrf4mEz0UPmUaFHwH4T6", "YPw-pxhqaUOWRFGramr4B1"]
355
+ }
356
+ ]
357
+ }
358
+ };
359
+ },
360
+ multiMixedRef: () => {
361
+ return {
362
+ tableA: {
363
+ _type: "components",
364
+ _data: [
365
+ {
366
+ keyA0: "a0"
367
+ },
368
+ {
369
+ keyA1: "a1"
370
+ }
371
+ ]
372
+ },
373
+ tableB: {
374
+ _type: "components",
375
+ _data: [
376
+ {
377
+ keyB0: "b0"
378
+ },
379
+ {
380
+ keyB1: "b1"
381
+ }
382
+ ]
383
+ },
384
+ tableC: {
385
+ _type: "components",
386
+ _data: [
387
+ {
388
+ tableRef: [
389
+ { component: "tableA", ref: "KFQrf4mEz0UPmUaFHwH4T6" },
390
+ { component: "tableB", ref: "dXhIygNwNMVPEqFbsFJkn6" }
391
+ ]
392
+ }
393
+ ]
394
+ }
395
+ };
396
+ },
294
397
  complete: () => {
295
398
  const sliceIds = hip({
296
399
  _type: "sliceIds",
@@ -411,6 +514,53 @@ __publicField(_Example, "broken", {
411
514
  }
412
515
  };
413
516
  },
517
+ missingNamedRef: () => {
518
+ return {
519
+ tableA: {
520
+ _type: "components",
521
+ _data: [
522
+ {
523
+ keyA0: "a0"
524
+ },
525
+ {
526
+ keyA1: "a1"
527
+ }
528
+ ]
529
+ },
530
+ tableB: {
531
+ _type: "components",
532
+ _data: [
533
+ {
534
+ namedRef: { component: "tableA", ref: "MISSINGREF" }
535
+ // MISSINGREF does not exist in tableA
536
+ }
537
+ ]
538
+ }
539
+ };
540
+ },
541
+ missingMultiRef: () => {
542
+ return {
543
+ tableA: {
544
+ _type: "components",
545
+ _data: [
546
+ {
547
+ keyA0: "a0"
548
+ },
549
+ {
550
+ keyA1: "a1"
551
+ }
552
+ ]
553
+ },
554
+ tableB: {
555
+ _type: "components",
556
+ _data: [
557
+ {
558
+ tableARef: ["KFQrf4mEz0UPmUaFHwH4T6", "MISSING"]
559
+ }
560
+ ]
561
+ }
562
+ };
563
+ },
414
564
  missingReferencedTable: () => {
415
565
  return {
416
566
  tableB: {
@@ -423,6 +573,38 @@ __publicField(_Example, "broken", {
423
573
  ]
424
574
  }
425
575
  };
576
+ },
577
+ missingSliceId: () => {
578
+ return {
579
+ exampleSliceId: {
580
+ _type: "sliceIds",
581
+ _data: [
582
+ {
583
+ add: ["id0", "id1"]
584
+ }
585
+ ]
586
+ },
587
+ exampleComponent: {
588
+ _type: "components",
589
+ _data: [
590
+ {
591
+ exampleSliceId: "id2"
592
+ }
593
+ ]
594
+ }
595
+ };
596
+ },
597
+ missingSliceIdTable: () => {
598
+ return {
599
+ exampleComponent: {
600
+ _type: "components",
601
+ _data: [
602
+ {
603
+ exampleSliceId: "id0"
604
+ }
605
+ ]
606
+ }
607
+ };
426
608
  }
427
609
  },
428
610
  tableCfg: {
@@ -664,6 +846,20 @@ const iterateTables = async (rljson, callback) => {
664
846
  }
665
847
  };
666
848
  // @license
849
+ const removeDuplicates = (rljson) => {
850
+ const result = {};
851
+ for (const key in rljson) {
852
+ if (key.startsWith("_")) continue;
853
+ const table = rljson[key];
854
+ const data = table._data;
855
+ const newData = Array.from(
856
+ new Map(data.map((row) => [row._hash, row])).values()
857
+ );
858
+ result[key] = { ...table, _data: newData };
859
+ }
860
+ return hip(result, { throwOnWrongHashes: false });
861
+ };
862
+ // @license
667
863
  const contentTypes = [
668
864
  "buffets",
669
865
  "cakes",
@@ -755,6 +951,7 @@ class _BaseValidator {
755
951
  () => this._rootOrHeadTableHasNoIdColumn(),
756
952
  // Check references
757
953
  () => this._refsNotFound(),
954
+ () => this._sliceIdRefsNotFound(),
758
955
  // Check layers
759
956
  () => this._layerBasesNotFound(),
760
957
  () => this._layerSliceIdsTableNotFound(),
@@ -1128,43 +1325,89 @@ class _BaseValidator {
1128
1325
  for (const item of tableData) {
1129
1326
  for (const key of Object.keys(item)) {
1130
1327
  if (key.endsWith("Ref")) {
1131
- const targetItemHash = item[key];
1132
- const targetTableKey = key.substring(0, key.length - 3);
1133
- const itemHash = item._hash;
1134
- if (this.tableKeys.indexOf(targetTableKey) === -1) {
1135
- missingRefs.push({
1136
- error: `Target table "${targetTableKey}" not found.`,
1328
+ const targetItemRefs = Array.isArray(item[key]) ? item[key] : [item[key]];
1329
+ for (const targetItemRef of targetItemRefs) {
1330
+ const targetTableKey = typeof targetItemRef !== "string" ? targetItemRef.component : key.substring(0, key.length - 3);
1331
+ const targetItemHash = typeof targetItemRef !== "string" ? targetItemRef.ref : targetItemRef;
1332
+ const itemHash = item._hash;
1333
+ if (this.tableKeys.indexOf(targetTableKey) === -1) {
1334
+ missingRefs.push({
1335
+ error: `Target table "${targetTableKey}" not found.`,
1336
+ sourceTable: tableKey,
1337
+ sourceKey: key,
1338
+ sourceItemHash: itemHash,
1339
+ targetItemHash,
1340
+ targetTable: targetTableKey
1341
+ });
1342
+ continue;
1343
+ }
1344
+ const targetTableIndexed = this.rljsonIndexed[targetTableKey];
1345
+ const referencedItem = targetTableIndexed._data[targetItemHash];
1346
+ if (referencedItem === void 0) {
1347
+ missingRefs.push({
1348
+ sourceTable: tableKey,
1349
+ sourceItemHash: itemHash,
1350
+ sourceKey: key,
1351
+ targetItemHash,
1352
+ targetTable: targetTableKey,
1353
+ error: `Table "${targetTableKey}" has no item with hash "${targetItemHash}"`
1354
+ });
1355
+ }
1356
+ }
1357
+ }
1358
+ }
1359
+ }
1360
+ });
1361
+ if (missingRefs.length > 0) {
1362
+ this.errors.refsNotFound = {
1363
+ error: "Broken references",
1364
+ missingRefs
1365
+ };
1366
+ }
1367
+ }
1368
+ // ...........................................................................
1369
+ _sliceIdRefsNotFound() {
1370
+ const missingSliceIdRefs = [];
1371
+ iterateTablesSync(this.rljson, (tableKey, table) => {
1372
+ const tableData = table._data;
1373
+ for (const item of tableData) {
1374
+ for (const key of Object.keys(item)) {
1375
+ if (key.endsWith("SliceId")) {
1376
+ const targetSliceId = item[key];
1377
+ if (this.tableKeys.indexOf(key) === -1) {
1378
+ missingSliceIdRefs.push({
1137
1379
  sourceTable: tableKey,
1138
- sourceKey: key,
1139
- sourceItemHash: itemHash,
1140
- targetItemHash,
1141
- targetTable: targetTableKey
1380
+ targetSliceId,
1381
+ targetTable: key,
1382
+ error: `Target table "${targetSliceId}" not found.`
1142
1383
  });
1143
1384
  continue;
1144
1385
  }
1145
- const targetTableIndexed = this.rljsonIndexed[targetTableKey];
1146
- const referencedItem = targetTableIndexed._data[targetItemHash];
1147
- if (referencedItem === void 0) {
1148
- missingRefs.push({
1386
+ const targetSliceIdsTable = this.rljson[key];
1387
+ const targetSliceIds = targetSliceIdsTable._data.flatMap((d) => [
1388
+ ...d.add,
1389
+ ...d.remove ?? []
1390
+ ]);
1391
+ if (targetSliceIds.indexOf(targetSliceId) === -1) {
1392
+ missingSliceIdRefs.push({
1149
1393
  sourceTable: tableKey,
1150
- sourceItemHash: itemHash,
1151
- sourceKey: key,
1152
- targetItemHash,
1153
- targetTable: targetTableKey,
1154
- error: `Table "${targetTableKey}" has no item with hash "${targetItemHash}"`
1394
+ targetSliceId,
1395
+ targetTable: key,
1396
+ error: `Table "${key}" has no sliceId "${targetSliceId}"`
1155
1397
  });
1156
1398
  }
1157
1399
  }
1158
1400
  }
1159
1401
  }
1160
1402
  });
1161
- if (missingRefs.length > 0) {
1403
+ if (missingSliceIdRefs.length > 0) {
1162
1404
  this.errors.refsNotFound = {
1163
1405
  error: "Broken references",
1164
- missingRefs
1406
+ missingRefs: missingSliceIdRefs
1165
1407
  };
1166
1408
  }
1167
1409
  }
1410
+ // ...........................................................................
1168
1411
  _layerBasesNotFound() {
1169
1412
  const brokenLayers = [];
1170
1413
  iterateTablesSync(this.rljson, (tableKey, table) => {
@@ -1534,6 +1777,7 @@ export {
1534
1777
  isValidFieldName,
1535
1778
  iterateTables,
1536
1779
  iterateTablesSync,
1780
+ removeDuplicates,
1537
1781
  reservedFieldNames,
1538
1782
  reservedTableKeys,
1539
1783
  throwOnInvalidTableCfg,
@@ -5,7 +5,7 @@
5
5
  // found in the LICENSE file in the root of this package.
6
6
 
7
7
  import { hip } from '@rljson/hash';
8
- import { exampleJsonObject } from '@rljson/json';
8
+ import { exampleJsonObject, Json } from '@rljson/json';
9
9
 
10
10
  import { BuffetsTable } from './content/buffet.ts';
11
11
  import { Cake, CakesTable } from './content/cake.ts';
@@ -157,6 +157,110 @@ export class Example {
157
157
  },
158
158
  };
159
159
  },
160
+ singleSliceIdRef: (): Rljson => {
161
+ return {
162
+ exampleSliceId: {
163
+ _type: 'sliceIds',
164
+ _data: [
165
+ {
166
+ add: ['id0', 'id1'],
167
+ },
168
+ ],
169
+ } as SliceIdsTable,
170
+ exampleComponent: {
171
+ _type: 'components',
172
+ _data: [
173
+ {
174
+ exampleSliceId: 'id0',
175
+ },
176
+ ],
177
+ } as ComponentsTable<Json>,
178
+ };
179
+ },
180
+ singleNamedRef: (): Rljson => {
181
+ return {
182
+ tableA: {
183
+ _type: 'components',
184
+ _data: [
185
+ {
186
+ keyA0: 'a0',
187
+ },
188
+ {
189
+ keyA1: 'a1',
190
+ },
191
+ ],
192
+ },
193
+ tableB: {
194
+ _type: 'components',
195
+ _data: [
196
+ {
197
+ namedRef: { component: 'tableA', ref: 'KFQrf4mEz0UPmUaFHwH4T6' },
198
+ },
199
+ ],
200
+ },
201
+ };
202
+ },
203
+ multiRef: (): Rljson => {
204
+ return {
205
+ tableA: {
206
+ _type: 'components',
207
+ _data: [
208
+ {
209
+ keyA0: 'a0',
210
+ },
211
+ {
212
+ keyA1: 'a1',
213
+ },
214
+ ],
215
+ },
216
+ tableB: {
217
+ _type: 'components',
218
+ _data: [
219
+ {
220
+ tableARef: ['KFQrf4mEz0UPmUaFHwH4T6', 'YPw-pxhqaUOWRFGramr4B1'],
221
+ },
222
+ ],
223
+ },
224
+ };
225
+ },
226
+ multiMixedRef: (): Rljson => {
227
+ return {
228
+ tableA: {
229
+ _type: 'components',
230
+ _data: [
231
+ {
232
+ keyA0: 'a0',
233
+ },
234
+ {
235
+ keyA1: 'a1',
236
+ },
237
+ ],
238
+ },
239
+ tableB: {
240
+ _type: 'components',
241
+ _data: [
242
+ {
243
+ keyB0: 'b0',
244
+ },
245
+ {
246
+ keyB1: 'b1',
247
+ },
248
+ ],
249
+ },
250
+ tableC: {
251
+ _type: 'components',
252
+ _data: [
253
+ {
254
+ tableRef: [
255
+ { component: 'tableA', ref: 'KFQrf4mEz0UPmUaFHwH4T6' },
256
+ { component: 'tableB', ref: 'dXhIygNwNMVPEqFbsFJkn6' },
257
+ ],
258
+ },
259
+ ],
260
+ },
261
+ };
262
+ },
263
+
160
264
  complete: (): Rljson => {
161
265
  const sliceIds = hip<SliceIdsTable>({
162
266
  _type: 'sliceIds',
@@ -289,6 +393,54 @@ export class Example {
289
393
  };
290
394
  },
291
395
 
396
+ missingNamedRef: (): Rljson => {
397
+ return {
398
+ tableA: {
399
+ _type: 'components',
400
+ _data: [
401
+ {
402
+ keyA0: 'a0',
403
+ },
404
+ {
405
+ keyA1: 'a1',
406
+ },
407
+ ],
408
+ },
409
+ tableB: {
410
+ _type: 'components',
411
+ _data: [
412
+ {
413
+ namedRef: { component: 'tableA', ref: 'MISSINGREF' }, // MISSINGREF does not exist in tableA
414
+ },
415
+ ],
416
+ },
417
+ };
418
+ },
419
+
420
+ missingMultiRef: (): Rljson => {
421
+ return {
422
+ tableA: {
423
+ _type: 'components',
424
+ _data: [
425
+ {
426
+ keyA0: 'a0',
427
+ },
428
+ {
429
+ keyA1: 'a1',
430
+ },
431
+ ],
432
+ },
433
+ tableB: {
434
+ _type: 'components',
435
+ _data: [
436
+ {
437
+ tableARef: ['KFQrf4mEz0UPmUaFHwH4T6', 'MISSING'],
438
+ },
439
+ ],
440
+ },
441
+ };
442
+ },
443
+
292
444
  missingReferencedTable: (): Rljson => {
293
445
  return {
294
446
  tableB: {
@@ -301,6 +453,40 @@ export class Example {
301
453
  },
302
454
  };
303
455
  },
456
+
457
+ missingSliceId: (): Rljson => {
458
+ return {
459
+ exampleSliceId: {
460
+ _type: 'sliceIds',
461
+ _data: [
462
+ {
463
+ add: ['id0', 'id1'],
464
+ },
465
+ ],
466
+ } as SliceIdsTable,
467
+ exampleComponent: {
468
+ _type: 'components',
469
+ _data: [
470
+ {
471
+ exampleSliceId: 'id2',
472
+ },
473
+ ],
474
+ } as ComponentsTable<Json>,
475
+ };
476
+ },
477
+
478
+ missingSliceIdTable: (): Rljson => {
479
+ return {
480
+ exampleComponent: {
481
+ _type: 'components',
482
+ _data: [
483
+ {
484
+ exampleSliceId: 'id0',
485
+ },
486
+ ],
487
+ } as ComponentsTable<Json>,
488
+ };
489
+ },
304
490
  },
305
491
 
306
492
  tableCfg: {
@@ -0,0 +1,2 @@
1
+ import { Rljson } from '../rljson.ts';
2
+ export declare const removeDuplicates: (rljson: Rljson) => Rljson;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rljson/rljson",
3
- "version": "0.0.52",
3
+ "version": "0.0.55",
4
4
  "description": "The RLJSON data format specification",
5
5
  "homepage": "https://github.com/rljson/rljson",
6
6
  "bugs": "https://github.com/rljson/rljson/issues",