@rljson/rljson 0.0.56 → 0.0.58

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.
@@ -0,0 +1,23 @@
1
+ import { Json, JsonH, JsonValueH } from '@rljson/json';
2
+ import { Ingredient } from '../example/bakery-example.ts';
3
+ import { RljsonTable } from '../rljson.ts';
4
+ import { Ref } from '../typedefs.ts';
5
+ /**
6
+ * A reference to a Edit row in a Edit table
7
+ */
8
+ export type EditRef = Ref;
9
+ export type Edit<T extends Json> = {
10
+ value: T & JsonValueH;
11
+ route: string;
12
+ origin?: Ref;
13
+ previous?: EditRef;
14
+ acknowledged?: boolean;
15
+ } & JsonH;
16
+ /**
17
+ * A table containing components
18
+ */
19
+ export type EditsTable<T extends Json> = RljsonTable<Edit<T>, 'edits'>;
20
+ /**
21
+ * Provides an example Edits table for test purposes
22
+ */
23
+ export declare const exampleEditsTable: () => EditsTable<Ingredient>;
@@ -0,0 +1,6 @@
1
+ export declare class Route {
2
+ private segments;
3
+ constructor(segments: string[]);
4
+ static fromFlat(route: string): Route;
5
+ get flat(): string;
6
+ }
@@ -4,6 +4,7 @@ import { CakesTable } from '../content/cake.ts';
4
4
  import { ComponentsTable } from '../content/components.ts';
5
5
  import { LayersTable } from '../content/layer.ts';
6
6
  import { SliceIdsTable } from '../content/slice-ids.ts';
7
+ import { EditsTable } from '../edit/edit.ts';
7
8
  import { Rljson } from '../rljson.ts';
8
9
  import { Ref } from '../typedefs.ts';
9
10
  export interface Ingredient extends Json {
@@ -31,5 +32,6 @@ export interface Bakery extends Rljson {
31
32
  recipeIngredients: ComponentsTable<RecipIngredient>;
32
33
  ingredients: ComponentsTable<Ingredient>;
33
34
  nutritionalValues: ComponentsTable<NutritionalValues>;
35
+ ingredientsEdits: EditsTable<Ingredient>;
34
36
  }
35
37
  export declare const bakeryExample: () => Bakery;
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from './content/layer.ts';
5
5
  export * from './content/revision.ts';
6
6
  export * from './content/slice-ids.ts';
7
7
  export * from './content/table-cfg.ts';
8
+ export * from './edit/edit.ts';
8
9
  export * from './example.ts';
9
10
  export * from './example/bakery-example.ts';
10
11
  export * from './rljson.ts';
package/dist/rljson.d.ts CHANGED
@@ -6,13 +6,14 @@ import { LayersTable } from './content/layer.ts';
6
6
  import { RevisionsTable } from './content/revision.ts';
7
7
  import { SliceIdsTable } from './content/slice-ids.ts';
8
8
  import { TableCfgRef, TablesCfgTable } from './content/table-cfg.ts';
9
+ import { EditsTable } from './edit/edit.ts';
9
10
  import { ContentType, Ref, TableKey } from './typedefs.ts';
10
11
  export declare const reservedFieldNames: string[];
11
12
  export declare const reservedTableKeys: string[];
12
13
  /**
13
14
  * One of the supported Rljson table types
14
15
  */
15
- export type TableType = BuffetsTable | ComponentsTable<any> | LayersTable | SliceIdsTable | CakesTable | RevisionsTable | TablesCfgTable;
16
+ export type TableType = BuffetsTable | ComponentsTable<any> | LayersTable | SliceIdsTable | CakesTable | RevisionsTable | TablesCfgTable | EditsTable<any>;
16
17
  /** The rljson data format */
17
18
  export interface Rljson extends Json {
18
19
  [tableId: TableKey]: TableType;
package/dist/rljson.js CHANGED
@@ -1,8 +1,17 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
1
  import { hip, hsh } from "@rljson/hash";
5
- import { exampleJsonObject, jsonValueTypes, jsonValueType, jsonValueMatchesType } from "@rljson/json";
2
+ import { exampleJsonObject, jsonValueTypes, jsonValueMatchesType, jsonValueType } from "@rljson/json";
3
+ // @license
4
+ class Route {
5
+ constructor(segments) {
6
+ this.segments = segments;
7
+ }
8
+ static fromFlat(route) {
9
+ return new Route(route.split("/").filter(Boolean));
10
+ }
11
+ get flat() {
12
+ return "/" + this.segments.join("/");
13
+ }
14
+ }
6
15
  // @license
7
16
  const bakeryExample = () => {
8
17
  const nutritionalValues = hip({
@@ -125,6 +134,33 @@ const bakeryExample = () => {
125
134
  }
126
135
  ]
127
136
  });
137
+ const ingredientsEdits = hip({
138
+ _type: "edits",
139
+ _data: [
140
+ {
141
+ value: {
142
+ name: "Flour A",
143
+ amountUnit: "g",
144
+ nutritionalValuesRef: nutritionalValues._data[0]._hash,
145
+ _hash: ""
146
+ },
147
+ route: Route.fromFlat("/ingredients/").flat,
148
+ _hash: ""
149
+ },
150
+ {
151
+ value: {
152
+ name: "Flour B",
153
+ amountUnit: "g",
154
+ nutritionalValuesRef: nutritionalValues._data[0]._hash,
155
+ _hash: ""
156
+ },
157
+ previous: "D2Rp36U1DBa69zAya-16EJ",
158
+ route: Route.fromFlat("/ingredients/").flat,
159
+ _hash: ""
160
+ }
161
+ ],
162
+ _hash: ""
163
+ });
128
164
  const result = {
129
165
  buffets,
130
166
  cakes,
@@ -134,7 +170,8 @@ const bakeryExample = () => {
134
170
  recipes,
135
171
  recipeIngredients,
136
172
  ingredients,
137
- nutritionalValues
173
+ nutritionalValues,
174
+ ingredientsEdits
138
175
  };
139
176
  return result;
140
177
  };
@@ -157,360 +194,121 @@ const exampleRevision = () => ({
157
194
  // @license
158
195
  const exampleSliceIdsTable = () => bakeryExample().slices;
159
196
  // @license
160
- const _Example = class _Example {
161
- };
162
- __publicField(_Example, "ok", {
163
- bakery: () => bakeryExample(),
164
- empty: () => {
165
- return {};
166
- },
167
- binary: () => {
168
- return {
169
- table: {
170
- _type: "components",
171
- _data: [
172
- { a: false, b: false },
173
- { a: false, b: true },
174
- { a: true, b: false },
175
- { a: true, b: true }
176
- ]
177
- }
178
- };
179
- },
180
- singleRow: () => {
181
- const tableCfgs = hip({
182
- _hash: "",
183
- _type: "tableCfgs",
184
- _data: [
185
- {
186
- version: 0,
187
- _hash: "",
188
- key: "table",
189
- type: "components",
190
- isHead: false,
191
- isRoot: false,
192
- isShared: true,
193
- columns: [
194
- {
195
- key: "int",
196
- type: "number"
197
- },
198
- {
199
- key: "double",
200
- type: "number"
201
- },
202
- {
203
- key: "string",
204
- type: "string"
205
- },
206
- {
207
- key: "boolean",
208
- type: "boolean"
209
- },
210
- {
211
- key: "null",
212
- type: "string"
213
- },
214
- {
215
- key: "jsonArray",
216
- type: "jsonArray"
217
- },
218
- {
219
- key: "json",
220
- type: "json"
221
- },
222
- {
223
- key: "jsonValue",
224
- type: "jsonValue"
225
- }
197
+ class Example {
198
+ static ok = {
199
+ bakery: () => bakeryExample(),
200
+ empty: () => {
201
+ return {};
202
+ },
203
+ binary: () => {
204
+ return {
205
+ table: {
206
+ _type: "components",
207
+ _data: [
208
+ { a: false, b: false },
209
+ { a: false, b: true },
210
+ { a: true, b: false },
211
+ { a: true, b: true }
226
212
  ]
227
213
  }
228
- ]
229
- });
230
- const result = {
231
- tableCfgs,
232
- table: {
233
- _tableCfg: tableCfgs._data[0]._hash,
234
- _type: "components",
235
- _data: [exampleJsonObject()],
236
- _hash: ""
237
- }
238
- };
239
- return result;
240
- },
241
- multipleRows: () => {
242
- return {
243
- table: {
244
- _type: "components",
245
- _data: [
246
- {
247
- string: "str0",
248
- boolean: true,
249
- number: 1,
250
- array: [1, "str0", true, { a: { b: "c" } }],
251
- object: { a: { b: "c" } }
252
- },
253
- {
254
- string: "str1",
255
- boolean: true,
256
- number: 1,
257
- array: [1, "str1", true, { a: { b: "c" } }],
258
- object: { a: { b: "c" } }
259
- },
260
- {
261
- string: "str2",
262
- boolean: false,
263
- number: 1,
264
- array: [1, "str1", true, { a: { b: "c" } }],
265
- object: { d: { e: "f" } }
266
- }
267
- ]
268
- }
269
- };
270
- },
271
- singleRef: () => {
272
- return {
273
- tableA: {
274
- _type: "components",
275
- _data: [
276
- {
277
- keyA0: "a0"
278
- },
279
- {
280
- keyA1: "a1"
281
- }
282
- ]
283
- },
284
- tableB: {
285
- _type: "components",
286
- _data: [
287
- {
288
- tableARef: "KFQrf4mEz0UPmUaFHwH4T6"
289
- }
290
- ]
291
- }
292
- };
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
- multiSliceIdRef: () => {
315
- return {
316
- exampleSliceId: {
317
- _type: "sliceIds",
318
- _data: [
319
- {
320
- add: ["id0", "id1"]
321
- }
322
- ]
323
- },
324
- exampleComponent: {
325
- _type: "components",
326
- _data: [
327
- {
328
- exampleSliceId: ["id0", "id1"]
329
- }
330
- ]
331
- }
332
- };
333
- },
334
- singleNamedRef: () => {
335
- return {
336
- tableA: {
337
- _type: "components",
338
- _data: [
339
- {
340
- keyA0: "a0"
341
- },
342
- {
343
- keyA1: "a1"
344
- }
345
- ]
346
- },
347
- tableB: {
348
- _type: "components",
349
- _data: [
350
- {
351
- namedRef: { component: "tableA", ref: "KFQrf4mEz0UPmUaFHwH4T6" }
352
- }
353
- ]
354
- }
355
- };
356
- },
357
- multiRef: () => {
358
- return {
359
- tableA: {
360
- _type: "components",
361
- _data: [
362
- {
363
- keyA0: "a0"
364
- },
365
- {
366
- keyA1: "a1"
367
- }
368
- ]
369
- },
370
- tableB: {
371
- _type: "components",
372
- _data: [
373
- {
374
- tableARef: ["KFQrf4mEz0UPmUaFHwH4T6", "YPw-pxhqaUOWRFGramr4B1"]
375
- }
376
- ]
377
- }
378
- };
379
- },
380
- multiMixedRef: () => {
381
- return {
382
- tableA: {
383
- _type: "components",
384
- _data: [
385
- {
386
- keyA0: "a0"
387
- },
388
- {
389
- keyA1: "a1"
390
- }
391
- ]
392
- },
393
- tableB: {
394
- _type: "components",
395
- _data: [
396
- {
397
- keyB0: "b0"
398
- },
399
- {
400
- keyB1: "b1"
401
- }
402
- ]
403
- },
404
- tableC: {
405
- _type: "components",
214
+ };
215
+ },
216
+ singleRow: () => {
217
+ const tableCfgs = hip({
218
+ _hash: "",
219
+ _type: "tableCfgs",
406
220
  _data: [
407
221
  {
408
- tableRef: [
409
- { component: "tableA", ref: "KFQrf4mEz0UPmUaFHwH4T6" },
410
- { component: "tableB", ref: "dXhIygNwNMVPEqFbsFJkn6" }
222
+ version: 0,
223
+ _hash: "",
224
+ key: "table",
225
+ type: "components",
226
+ isHead: false,
227
+ isRoot: false,
228
+ isShared: true,
229
+ columns: [
230
+ {
231
+ key: "_hash",
232
+ type: "string"
233
+ },
234
+ {
235
+ key: "int",
236
+ type: "number"
237
+ },
238
+ {
239
+ key: "double",
240
+ type: "number"
241
+ },
242
+ {
243
+ key: "string",
244
+ type: "string"
245
+ },
246
+ {
247
+ key: "boolean",
248
+ type: "boolean"
249
+ },
250
+ {
251
+ key: "null",
252
+ type: "string"
253
+ },
254
+ {
255
+ key: "jsonArray",
256
+ type: "jsonArray"
257
+ },
258
+ {
259
+ key: "json",
260
+ type: "json"
261
+ },
262
+ {
263
+ key: "jsonValue",
264
+ type: "jsonValue"
265
+ }
411
266
  ]
412
267
  }
413
268
  ]
414
- }
415
- };
416
- },
417
- complete: () => {
418
- const sliceIds = hip({
419
- _type: "sliceIds",
420
- _data: [
421
- {
422
- add: ["id0", "id1"]
269
+ });
270
+ const result = {
271
+ tableCfgs,
272
+ table: {
273
+ _tableCfg: tableCfgs._data[0]._hash,
274
+ _type: "components",
275
+ _data: [hip(exampleJsonObject())],
276
+ _hash: ""
423
277
  }
424
- ]
425
- });
426
- const components = hip({
427
- _type: "components",
428
- _data: [{ a: "0" }, { a: "1" }]
429
- });
430
- const component0 = components._data[0];
431
- const component1 = components._data[1];
432
- const abLayer0 = hip({
433
- sliceIdsTable: "sliceIds",
434
- sliceIdsTableRow: "MgHRBYSrhpyl4rvsOmAWcQ",
435
- componentsTable: "components",
436
- add: {
437
- id0: component0._hash,
438
- id1: component1._hash
439
- }
440
- });
441
- const abLayer1 = hip({
442
- base: abLayer0._hash,
443
- sliceIdsTable: "sliceIds",
444
- sliceIdsTableRow: "MgHRBYSrhpyl4rvsOmAWcQ",
445
- componentsTable: "components",
446
- add: {
447
- id0: component0._hash,
448
- id1: component1._hash
449
- }
450
- });
451
- const abLayers = hip({
452
- _type: "layers",
453
- _data: [abLayer0, abLayer1]
454
- });
455
- const cake = hip({
456
- sliceIdsTable: "sliceIds",
457
- sliceIdsRow: sliceIds._data[0]._hash,
458
- layers: {
459
- abLayers: abLayer1._hash
460
- }
461
- });
462
- const cakes = hip({
463
- _type: "cakes",
464
- _data: [cake]
465
- });
466
- const buffets = hip({
467
- _type: "buffets",
468
- _data: [
469
- {
470
- items: [
278
+ };
279
+ return result;
280
+ },
281
+ multipleRows: () => {
282
+ return {
283
+ table: {
284
+ _type: "components",
285
+ _data: [
471
286
  {
472
- table: "cakes",
473
- ref: cakes._data[0]._hash
287
+ string: "str0",
288
+ boolean: true,
289
+ number: 1,
290
+ array: [1, "str0", true, { a: { b: "c" } }],
291
+ object: { a: { b: "c" } }
474
292
  },
475
293
  {
476
- table: "abLayers",
477
- ref: abLayer0._hash
294
+ string: "str1",
295
+ boolean: true,
296
+ number: 1,
297
+ array: [1, "str1", true, { a: { b: "c" } }],
298
+ object: { a: { b: "c" } }
299
+ },
300
+ {
301
+ string: "str2",
302
+ boolean: false,
303
+ number: 1,
304
+ array: [1, "str1", true, { a: { b: "c" } }],
305
+ object: { d: { e: "f" } }
478
306
  }
479
307
  ]
480
308
  }
481
- ]
482
- });
483
- return {
484
- sliceIds,
485
- components,
486
- abLayers,
487
- cakes,
488
- buffets
489
- };
490
- }
491
- });
492
- __publicField(_Example, "broken", {
493
- base: {
494
- brokenTableKey: () => {
495
- return {
496
- brok$en: {
497
- _data: []
498
- }
499
309
  };
500
310
  },
501
- missingData: () => {
502
- return {
503
- table: {}
504
- };
505
- },
506
- dataNotBeingAnArray: () => {
507
- return {
508
- table: {
509
- _data: {}
510
- }
511
- };
512
- },
513
- missingRef: () => {
311
+ singleRef: () => {
514
312
  return {
515
313
  tableA: {
516
314
  _type: "components",
@@ -527,38 +325,53 @@ __publicField(_Example, "broken", {
527
325
  _type: "components",
528
326
  _data: [
529
327
  {
530
- tableARef: "MISSINGREF"
531
- // MISSINGREF does not exist in tableA
328
+ tableARef: "KFQrf4mEz0UPmUaFHwH4T6"
532
329
  }
533
330
  ]
534
331
  }
535
332
  };
536
333
  },
537
- missingNamedRef: () => {
334
+ singleSliceIdRef: () => {
538
335
  return {
539
- tableA: {
336
+ exampleSliceId: {
337
+ _type: "sliceIds",
338
+ _data: [
339
+ {
340
+ add: ["id0", "id1"]
341
+ }
342
+ ]
343
+ },
344
+ exampleComponent: {
540
345
  _type: "components",
541
346
  _data: [
542
347
  {
543
- keyA0: "a0"
544
- },
348
+ exampleSliceId: "id0"
349
+ }
350
+ ]
351
+ }
352
+ };
353
+ },
354
+ multiSliceIdRef: () => {
355
+ return {
356
+ exampleSliceId: {
357
+ _type: "sliceIds",
358
+ _data: [
545
359
  {
546
- keyA1: "a1"
360
+ add: ["id0", "id1"]
547
361
  }
548
362
  ]
549
363
  },
550
- tableB: {
364
+ exampleComponent: {
551
365
  _type: "components",
552
366
  _data: [
553
367
  {
554
- namedRef: { component: "tableA", ref: "MISSINGREF" }
555
- // MISSINGREF does not exist in tableA
368
+ exampleSliceId: ["id0", "id1"]
556
369
  }
557
370
  ]
558
371
  }
559
372
  };
560
373
  },
561
- missingMultiRef: () => {
374
+ singleNamedRef: () => {
562
375
  return {
563
376
  tableA: {
564
377
  _type: "components",
@@ -575,157 +388,384 @@ __publicField(_Example, "broken", {
575
388
  _type: "components",
576
389
  _data: [
577
390
  {
578
- tableARef: ["KFQrf4mEz0UPmUaFHwH4T6", "MISSING"]
391
+ namedRef: { component: "tableA", ref: "KFQrf4mEz0UPmUaFHwH4T6" }
579
392
  }
580
393
  ]
581
394
  }
582
395
  };
583
396
  },
584
- missingReferencedTable: () => {
397
+ multiRef: () => {
585
398
  return {
399
+ tableA: {
400
+ _type: "components",
401
+ _data: [
402
+ {
403
+ keyA0: "a0"
404
+ },
405
+ {
406
+ keyA1: "a1"
407
+ }
408
+ ]
409
+ },
586
410
  tableB: {
587
411
  _type: "components",
588
412
  _data: [
589
413
  {
590
- tableARef: "MISSINGREF"
591
- // tableA is missing
414
+ tableARef: ["KFQrf4mEz0UPmUaFHwH4T6", "YPw-pxhqaUOWRFGramr4B1"]
592
415
  }
593
416
  ]
594
417
  }
595
418
  };
596
419
  },
597
- missingSliceId: () => {
420
+ multiMixedRef: () => {
598
421
  return {
599
- exampleSliceId: {
600
- _type: "sliceIds",
422
+ tableA: {
423
+ _type: "components",
601
424
  _data: [
602
425
  {
603
- add: ["id0", "id1"]
426
+ keyA0: "a0"
427
+ },
428
+ {
429
+ keyA1: "a1"
604
430
  }
605
431
  ]
606
432
  },
607
- exampleComponent: {
433
+ tableB: {
608
434
  _type: "components",
609
435
  _data: [
610
436
  {
611
- exampleSliceId: "id2"
437
+ keyB0: "b0"
438
+ },
439
+ {
440
+ keyB1: "b1"
612
441
  }
613
442
  ]
614
- }
615
- };
616
- },
617
- missingSliceIdTable: () => {
618
- return {
619
- exampleComponent: {
443
+ },
444
+ tableC: {
620
445
  _type: "components",
621
446
  _data: [
622
447
  {
623
- exampleSliceId: "id0"
448
+ tableRef: [
449
+ { component: "tableA", ref: "KFQrf4mEz0UPmUaFHwH4T6" },
450
+ { component: "tableB", ref: "dXhIygNwNMVPEqFbsFJkn6" }
451
+ ]
624
452
  }
625
453
  ]
626
454
  }
627
455
  };
628
- }
629
- },
630
- tableCfg: {
631
- wrongType: () => {
632
- const result = _Example.ok.singleRow();
633
- const columns = result.tableCfgs._data[0].columns;
634
- const intColumn = columns.find((c) => c.key === "int");
635
- intColumn.type = "numberBroken";
636
- return hip(result, {
637
- updateExistingHashes: true,
638
- throwOnWrongHashes: false
456
+ },
457
+ complete: () => {
458
+ const sliceIds = hip({
459
+ _type: "sliceIds",
460
+ _data: [
461
+ {
462
+ add: ["id0", "id1"]
463
+ }
464
+ ]
639
465
  });
640
- }
641
- },
642
- layers: {
643
- missingBase: () => {
644
- const result = _Example.ok.complete();
645
- const layer1 = result.abLayers._data[1];
646
- layer1.base = "MISSING";
647
- return hip(result, {
648
- updateExistingHashes: true,
649
- throwOnWrongHashes: false
466
+ const components = hip({
467
+ _type: "components",
468
+ _data: [{ a: "0" }, { a: "1" }]
650
469
  });
651
- },
652
- missingSliceIdSet: () => {
653
- const result = _Example.ok.complete();
654
- const layer1 = result.abLayers._data[1];
655
- layer1.sliceIdsTableRow = "MISSING1";
656
- return hip(result, {
657
- updateExistingHashes: true,
658
- throwOnWrongHashes: false
470
+ const component0 = components._data[0];
471
+ const component1 = components._data[1];
472
+ const abLayer0 = hip({
473
+ sliceIdsTable: "sliceIds",
474
+ sliceIdsTableRow: "MgHRBYSrhpyl4rvsOmAWcQ",
475
+ componentsTable: "components",
476
+ add: {
477
+ id0: component0._hash,
478
+ id1: component1._hash
479
+ }
659
480
  });
660
- },
661
- missingAssignedComponentTable: () => {
662
- const result = _Example.ok.complete();
663
- delete result.components;
664
- return result;
665
- },
666
- missingAssignedComponent: () => {
667
- const result = _Example.ok.complete();
668
- result.components._data.splice(1, 2);
669
- return hip(result, {
670
- updateExistingHashes: true,
671
- throwOnWrongHashes: false
481
+ const abLayer1 = hip({
482
+ base: abLayer0._hash,
483
+ sliceIdsTable: "sliceIds",
484
+ sliceIdsTableRow: "MgHRBYSrhpyl4rvsOmAWcQ",
485
+ componentsTable: "components",
486
+ add: {
487
+ id0: component0._hash,
488
+ id1: component1._hash
489
+ }
672
490
  });
673
- }
674
- },
675
- cakes: {
676
- missingSliceIdSet: () => {
677
- const result = _Example.ok.complete();
678
- result.cakes._data[0].sliceIdsRow = "MISSING";
679
- hip(result.cakes, {
680
- updateExistingHashes: true,
681
- throwOnWrongHashes: false
491
+ const abLayers = hip({
492
+ _type: "layers",
493
+ _data: [abLayer0, abLayer1]
682
494
  });
683
- result.buffets._data[0].items[0].ref = result.cakes._data[0]._hash;
684
- hip(result.buffets, {
685
- updateExistingHashes: true,
686
- throwOnWrongHashes: false
495
+ const cake = hip({
496
+ sliceIdsTable: "sliceIds",
497
+ sliceIdsRow: sliceIds._data[0]._hash,
498
+ layers: {
499
+ abLayers: abLayer1._hash
500
+ }
687
501
  });
688
- return result;
689
- },
690
- missingLayersTable: () => {
691
- const result = _Example.ok.complete();
692
- result.cakes._data[0].layers = { MISSING: "HASH" };
693
- hip(result.cakes, {
694
- updateExistingHashes: true,
695
- throwOnWrongHashes: false
502
+ const cakes = hip({
503
+ _type: "cakes",
504
+ _data: [cake]
696
505
  });
697
- return result;
698
- },
699
- missingCakeLayer: () => {
700
- const result = _Example.ok.complete();
701
- result.cakes._data[0].layers["abLayers"] = "MISSING0";
702
- hip(result.cakes, {
703
- updateExistingHashes: true,
704
- throwOnWrongHashes: false
506
+ const buffets = hip({
507
+ _type: "buffets",
508
+ _data: [
509
+ {
510
+ items: [
511
+ {
512
+ table: "cakes",
513
+ ref: cakes._data[0]._hash
514
+ },
515
+ {
516
+ table: "abLayers",
517
+ ref: abLayer0._hash
518
+ }
519
+ ]
520
+ }
521
+ ]
705
522
  });
706
- return result;
523
+ return {
524
+ sliceIds,
525
+ components,
526
+ abLayers,
527
+ cakes,
528
+ buffets
529
+ };
707
530
  }
708
- },
709
- buffets: {
710
- missingTable: () => {
711
- const result = _Example.ok.complete();
712
- const buffet = result.buffets._data[0];
713
- buffet.items[0].table = "MISSING0";
714
- buffet.items[1].table = "MISSING1";
715
- hip(result, { updateExistingHashes: true, throwOnWrongHashes: false });
716
- return result;
531
+ };
532
+ static broken = {
533
+ base: {
534
+ brokenTableKey: () => {
535
+ return {
536
+ brok$en: {
537
+ _data: []
538
+ }
539
+ };
540
+ },
541
+ missingData: () => {
542
+ return {
543
+ table: {}
544
+ };
545
+ },
546
+ dataNotBeingAnArray: () => {
547
+ return {
548
+ table: {
549
+ _data: {}
550
+ }
551
+ };
552
+ },
553
+ missingRef: () => {
554
+ return {
555
+ tableA: {
556
+ _type: "components",
557
+ _data: [
558
+ {
559
+ keyA0: "a0"
560
+ },
561
+ {
562
+ keyA1: "a1"
563
+ }
564
+ ]
565
+ },
566
+ tableB: {
567
+ _type: "components",
568
+ _data: [
569
+ {
570
+ tableARef: "MISSINGREF"
571
+ // MISSINGREF does not exist in tableA
572
+ }
573
+ ]
574
+ }
575
+ };
576
+ },
577
+ missingNamedRef: () => {
578
+ return {
579
+ tableA: {
580
+ _type: "components",
581
+ _data: [
582
+ {
583
+ keyA0: "a0"
584
+ },
585
+ {
586
+ keyA1: "a1"
587
+ }
588
+ ]
589
+ },
590
+ tableB: {
591
+ _type: "components",
592
+ _data: [
593
+ {
594
+ namedRef: { component: "tableA", ref: "MISSINGREF" }
595
+ // MISSINGREF does not exist in tableA
596
+ }
597
+ ]
598
+ }
599
+ };
600
+ },
601
+ missingMultiRef: () => {
602
+ return {
603
+ tableA: {
604
+ _type: "components",
605
+ _data: [
606
+ {
607
+ keyA0: "a0"
608
+ },
609
+ {
610
+ keyA1: "a1"
611
+ }
612
+ ]
613
+ },
614
+ tableB: {
615
+ _type: "components",
616
+ _data: [
617
+ {
618
+ tableARef: ["KFQrf4mEz0UPmUaFHwH4T6", "MISSING"]
619
+ }
620
+ ]
621
+ }
622
+ };
623
+ },
624
+ missingReferencedTable: () => {
625
+ return {
626
+ tableB: {
627
+ _type: "components",
628
+ _data: [
629
+ {
630
+ tableARef: "MISSINGREF"
631
+ // tableA is missing
632
+ }
633
+ ]
634
+ }
635
+ };
636
+ },
637
+ missingSliceId: () => {
638
+ return {
639
+ exampleSliceId: {
640
+ _type: "sliceIds",
641
+ _data: [
642
+ {
643
+ add: ["id0", "id1"]
644
+ }
645
+ ]
646
+ },
647
+ exampleComponent: {
648
+ _type: "components",
649
+ _data: [
650
+ {
651
+ exampleSliceId: "id2"
652
+ }
653
+ ]
654
+ }
655
+ };
656
+ },
657
+ missingSliceIdTable: () => {
658
+ return {
659
+ exampleComponent: {
660
+ _type: "components",
661
+ _data: [
662
+ {
663
+ exampleSliceId: "id0"
664
+ }
665
+ ]
666
+ }
667
+ };
668
+ }
717
669
  },
718
- missingItems: () => {
719
- const result = _Example.ok.complete();
720
- const buffet = result.buffets._data[0];
721
- buffet.items[0].ref = "MISSING0";
722
- buffet.items[1].ref = "MISSING1";
723
- hip(result, { updateExistingHashes: true, throwOnWrongHashes: false });
724
- return result;
670
+ tableCfg: {
671
+ wrongType: () => {
672
+ const result = Example.ok.singleRow();
673
+ const columns = result.tableCfgs._data[0].columns;
674
+ const intColumn = columns.find((c) => c.key === "int");
675
+ intColumn.type = "numberBroken";
676
+ return hip(result, {
677
+ updateExistingHashes: true,
678
+ throwOnWrongHashes: false
679
+ });
680
+ }
681
+ },
682
+ layers: {
683
+ missingBase: () => {
684
+ const result = Example.ok.complete();
685
+ const layer1 = result.abLayers._data[1];
686
+ layer1.base = "MISSING";
687
+ return hip(result, {
688
+ updateExistingHashes: true,
689
+ throwOnWrongHashes: false
690
+ });
691
+ },
692
+ missingSliceIdSet: () => {
693
+ const result = Example.ok.complete();
694
+ const layer1 = result.abLayers._data[1];
695
+ layer1.sliceIdsTableRow = "MISSING1";
696
+ return hip(result, {
697
+ updateExistingHashes: true,
698
+ throwOnWrongHashes: false
699
+ });
700
+ },
701
+ missingAssignedComponentTable: () => {
702
+ const result = Example.ok.complete();
703
+ delete result.components;
704
+ return result;
705
+ },
706
+ missingAssignedComponent: () => {
707
+ const result = Example.ok.complete();
708
+ result.components._data.splice(1, 2);
709
+ return hip(result, {
710
+ updateExistingHashes: true,
711
+ throwOnWrongHashes: false
712
+ });
713
+ }
714
+ },
715
+ cakes: {
716
+ missingSliceIdSet: () => {
717
+ const result = Example.ok.complete();
718
+ result.cakes._data[0].sliceIdsRow = "MISSING";
719
+ hip(result.cakes, {
720
+ updateExistingHashes: true,
721
+ throwOnWrongHashes: false
722
+ });
723
+ result.buffets._data[0].items[0].ref = result.cakes._data[0]._hash;
724
+ hip(result.buffets, {
725
+ updateExistingHashes: true,
726
+ throwOnWrongHashes: false
727
+ });
728
+ return result;
729
+ },
730
+ missingLayersTable: () => {
731
+ const result = Example.ok.complete();
732
+ result.cakes._data[0].layers = { MISSING: "HASH" };
733
+ hip(result.cakes, {
734
+ updateExistingHashes: true,
735
+ throwOnWrongHashes: false
736
+ });
737
+ return result;
738
+ },
739
+ missingCakeLayer: () => {
740
+ const result = Example.ok.complete();
741
+ result.cakes._data[0].layers["abLayers"] = "MISSING0";
742
+ hip(result.cakes, {
743
+ updateExistingHashes: true,
744
+ throwOnWrongHashes: false
745
+ });
746
+ return result;
747
+ }
748
+ },
749
+ buffets: {
750
+ missingTable: () => {
751
+ const result = Example.ok.complete();
752
+ const buffet = result.buffets._data[0];
753
+ buffet.items[0].table = "MISSING0";
754
+ buffet.items[1].table = "MISSING1";
755
+ hip(result, { updateExistingHashes: true, throwOnWrongHashes: false });
756
+ return result;
757
+ },
758
+ missingItems: () => {
759
+ const result = Example.ok.complete();
760
+ const buffet = result.buffets._data[0];
761
+ buffet.items[0].ref = "MISSING0";
762
+ buffet.items[1].ref = "MISSING1";
763
+ hip(result, { updateExistingHashes: true, throwOnWrongHashes: false });
764
+ return result;
765
+ }
725
766
  }
726
- }
727
- });
728
- let Example = _Example;
767
+ };
768
+ }
729
769
  // @license
730
770
  const throwOnInvalidTableCfg = (tableCfg) => {
731
771
  if (tableCfg.columns.length < 2) {
@@ -771,10 +811,12 @@ const validateRljsonAgainstTableCfg = (rows, tableCfg) => {
771
811
  if (value === void 0 || value === null) {
772
812
  continue;
773
813
  }
774
- const actualType = jsonValueType(row[columnKey]);
775
- if (expectedType !== actualType) {
814
+ const typesMatched = jsonValueMatchesType(row[columnKey], expectedType);
815
+ if (!typesMatched) {
776
816
  errors.push(
777
- `Column "${columnKey}" in row ${i} of "${tableKey}" has type "${actualType}", but expected "${expectedType}"`
817
+ `Column "${columnKey}" in row ${i} of "${tableKey}" has type "${jsonValueType(
818
+ row[columnKey]
819
+ )}", but expected "${expectedType}"`
778
820
  );
779
821
  }
780
822
  }
@@ -804,8 +846,8 @@ const addColumnsToTableCfg = (tableCfg, columns) => {
804
846
  const exampleTableCfgTable = () => Example.ok.singleRow().tableCfgs;
805
847
  const exampleTableCfg = (tableCfg = void 0) => {
806
848
  return {
807
- key: (tableCfg == null ? void 0 : tableCfg.key) ?? "table",
808
- columns: (tableCfg == null ? void 0 : tableCfg.columns) ?? [
849
+ key: tableCfg?.key ?? "table",
850
+ columns: tableCfg?.columns ?? [
809
851
  {
810
852
  key: "_hash",
811
853
  type: "string"
@@ -819,13 +861,15 @@ const exampleTableCfg = (tableCfg = void 0) => {
819
861
  type: "number"
820
862
  }
821
863
  ],
822
- type: (tableCfg == null ? void 0 : tableCfg.type) ?? "components",
864
+ type: tableCfg?.type ?? "components",
823
865
  isHead: true,
824
866
  isRoot: true,
825
867
  isShared: false
826
868
  };
827
869
  };
828
870
  // @license
871
+ const exampleEditsTable = () => bakeryExample().ingredientsEdits;
872
+ // @license
829
873
  const reservedFieldNames = ["_data"];
830
874
  const reservedTableKeys = [
831
875
  "_hash",
@@ -887,7 +931,8 @@ const contentTypes = [
887
931
  "sliceIds",
888
932
  "components",
889
933
  "revisions",
890
- "tableCfgs"
934
+ "tableCfgs",
935
+ "edits"
891
936
  ];
892
937
  const exampleTypedefs = () => {
893
938
  return {
@@ -922,9 +967,7 @@ const rljsonIndexed = (rljson) => {
922
967
  };
923
968
  // @license
924
969
  class BaseValidator {
925
- constructor() {
926
- __publicField(this, "name", "base");
927
- }
970
+ name = "base";
928
971
  async validate(rljson) {
929
972
  return this.validateSync(rljson);
930
973
  }
@@ -937,18 +980,13 @@ class BaseValidator {
937
980
  }
938
981
  class _BaseValidator {
939
982
  constructor(rljson) {
940
- __publicField(this, "errors", { hasErrors: false });
941
- // ######################
942
- // Private
943
- // ######################
944
- __publicField(this, "tableKeys");
945
- __publicField(this, "rljsonIndexed");
946
983
  this.rljson = rljson;
947
984
  this.tableKeys = Object.keys(this.rljson).filter(
948
985
  (table) => !table.startsWith("_")
949
986
  );
950
987
  this.rljsonIndexed = rljsonIndexed(rljson);
951
988
  }
989
+ errors = { hasErrors: false };
952
990
  get hasErrors() {
953
991
  return Object.keys(this.errors).length > 1;
954
992
  }
@@ -994,6 +1032,11 @@ class _BaseValidator {
994
1032
  this.errors.hasErrors = this.hasErrors;
995
1033
  return this.errors;
996
1034
  }
1035
+ // ######################
1036
+ // Private
1037
+ // ######################
1038
+ tableKeys;
1039
+ rljsonIndexed;
997
1040
  _tableKeysNotLowerCamelCase() {
998
1041
  const invalidTableKeys = [];
999
1042
  for (const tableKey of this.tableKeys) {
@@ -1038,7 +1081,7 @@ class _BaseValidator {
1038
1081
  continue;
1039
1082
  }
1040
1083
  if (!BaseValidator.isValidFieldName(columnName)) {
1041
- invalidColumnNames[tableKey] ?? (invalidColumnNames[tableKey] = []);
1084
+ invalidColumnNames[tableKey] ??= [];
1042
1085
  invalidColumnNames[tableKey].push(columnName);
1043
1086
  hadErrors = true;
1044
1087
  }
@@ -1744,12 +1787,6 @@ class _BaseValidator {
1744
1787
  const isValidFieldName = (fieldName) => BaseValidator.isValidFieldName(fieldName);
1745
1788
  // @license
1746
1789
  class Validate {
1747
- constructor() {
1748
- // ######################
1749
- // Private
1750
- // ######################
1751
- __publicField(this, "_validators", []);
1752
- }
1753
1790
  addValidator(validator) {
1754
1791
  this._validators.push(validator);
1755
1792
  }
@@ -1778,6 +1815,10 @@ class Validate {
1778
1815
  return acc;
1779
1816
  }, {});
1780
1817
  }
1818
+ // ######################
1819
+ // Private
1820
+ // ######################
1821
+ _validators = [];
1781
1822
  }
1782
1823
  export {
1783
1824
  BaseValidator,
@@ -1789,6 +1830,7 @@ export {
1789
1830
  exampleBuffetsTable,
1790
1831
  exampleCakesTable,
1791
1832
  exampleComponentsTable,
1833
+ exampleEditsTable,
1792
1834
  exampleLayersTable,
1793
1835
  exampleRevision,
1794
1836
  exampleRljson,
@@ -52,6 +52,10 @@ export class Example {
52
52
  isRoot: false,
53
53
  isShared: true,
54
54
  columns: [
55
+ {
56
+ key: '_hash',
57
+ type: 'string',
58
+ },
55
59
  {
56
60
  key: 'int',
57
61
  type: 'number',
@@ -94,7 +98,7 @@ export class Example {
94
98
  table: {
95
99
  _tableCfg: tableCfgs._data[0]._hash as string,
96
100
  _type: 'components',
97
- _data: [exampleJsonObject()],
101
+ _data: [hip(exampleJsonObject())],
98
102
  _hash: '',
99
103
  },
100
104
  };
@@ -26,7 +26,7 @@ export type ColumnKey = JsonKey;
26
26
  * - `ids` Tables containing slice ids
27
27
  * - `components` Tables containing slice components
28
28
  */
29
- export declare const contentTypes: readonly ["buffets", "cakes", "layers", "sliceIds", "components", "revisions", "tableCfgs"];
29
+ export declare const contentTypes: readonly ["buffets", "cakes", "layers", "sliceIds", "components", "revisions", "tableCfgs", "edits"];
30
30
  export type ContentType = (typeof contentTypes)[number];
31
31
  /**
32
32
  * An example object using the typedefs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rljson/rljson",
3
- "version": "0.0.56",
3
+ "version": "0.0.58",
4
4
  "packageManager": "pnpm@10.11.0",
5
5
  "description": "The RLJSON data format specification",
6
6
  "homepage": "https://github.com/rljson/rljson",
@@ -29,20 +29,20 @@
29
29
  "updateGoldens": "cross-env UPDATE_GOLDENS=true npm test"
30
30
  },
31
31
  "devDependencies": {
32
- "@types/node": "^24.4.0",
33
- "@typescript-eslint/eslint-plugin": "^8.43.0",
34
- "@typescript-eslint/parser": "^8.43.0",
32
+ "@types/node": "^24.5.2",
33
+ "@typescript-eslint/eslint-plugin": "^8.44.1",
34
+ "@typescript-eslint/parser": "^8.44.1",
35
35
  "@vitest/coverage-v8": "^3.2.4",
36
36
  "cross-env": "^10.0.0",
37
- "eslint": "^9.35.0",
38
- "eslint-plugin-jsdoc": "^57.0.8",
37
+ "eslint": "^9.36.0",
38
+ "eslint-plugin-jsdoc": "^60.3.1",
39
39
  "eslint-plugin-tsdoc": "^0.4.0",
40
40
  "globals": "^16.4.0",
41
41
  "jsdoc": "^4.0.4",
42
42
  "read-pkg": "^9.0.1",
43
43
  "typescript": "~5.9.2",
44
- "typescript-eslint": "^8.43.0",
45
- "vite": "^7.1.5",
44
+ "typescript-eslint": "^8.44.1",
45
+ "vite": "^7.1.7",
46
46
  "vite-node": "^3.2.4",
47
47
  "vite-plugin-dts": "^4.5.4",
48
48
  "vite-tsconfig-paths": "^5.1.4",