@rljson/rljson 0.0.71 → 0.0.73

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.
@@ -1,6 +1,6 @@
1
1
  import { Json } from '@rljson/json';
2
2
  import { RljsonTable } from '../rljson.ts';
3
- import { TableKey } from '../typedefs.ts';
3
+ import { Ref, SliceId, TableKey } from '../typedefs.ts';
4
4
  import { LayerRef } from './layer.ts';
5
5
  import { SliceIdsRef } from './slice-ids.ts';
6
6
  import { TableCfg } from './table-cfg.ts';
@@ -8,6 +8,15 @@ import { TableCfg } from './table-cfg.ts';
8
8
  * A `CakeLayerId` assigns an id or name to a cake layer
9
9
  */
10
10
  export type CakeLayerId = string;
11
+ /**
12
+ * A reference to a cake
13
+ *
14
+ * A cake reference can optionally restrict the slice ids that are used in the cake.
15
+ */
16
+ export interface CakeReference extends Json {
17
+ ref: Ref;
18
+ sliceIds?: SliceId[];
19
+ }
11
20
  /**
12
21
  * A cake is a collection of layers.
13
22
  *
@@ -0,0 +1,10 @@
1
+ import { Json } from '@rljson/json';
2
+ import { RljsonTable } from '../rljson.ts';
3
+ import { TableCfg } from './table-cfg.ts';
4
+ export interface Head extends Json {
5
+ timeId: string;
6
+ cakeRef: string;
7
+ _hash: string;
8
+ }
9
+ export type HeadsTable = RljsonTable<Head, 'head'>;
10
+ export declare const createHeadsTableCfg: (cakeKey: string) => TableCfg;
@@ -1,6 +1,7 @@
1
1
  import { Json } from '@rljson/json';
2
2
  import { RljsonTable } from '../rljson.ts';
3
3
  import { Ref, SliceId } from '../typedefs.ts';
4
+ import { TableCfg } from './table-cfg.ts';
4
5
  /**
5
6
  * An SliceIdsRef is a hash pointing to an Ids
6
7
  */
@@ -30,3 +31,9 @@ export type SliceIdsTable = RljsonTable<SliceIds, 'sliceIds'>;
30
31
  * Returns one of the layers of the example cake
31
32
  */
32
33
  export declare const exampleSliceIdsTable: () => SliceIdsTable;
34
+ /**
35
+ * Creates a table configuration for slice ids table
36
+ * @param tableKey - the table key
37
+ * @returns the table configuration
38
+ */
39
+ export declare const createSliceIdsTableCfg: (tableKey: string) => TableCfg;
@@ -29,6 +29,7 @@ export interface ColumnCfg extends Json {
29
29
  * Defines if the column is reference column to another table (foreign key)
30
30
  */
31
31
  ref?: {
32
+ type: ContentType;
32
33
  tableKey: TableKey;
33
34
  columnKey?: ColumnKey;
34
35
  };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './content/buffet.ts';
2
2
  export * from './content/cake.ts';
3
3
  export * from './content/components.ts';
4
+ export * from './content/head.ts';
4
5
  export * from './content/layer.ts';
5
6
  export * from './content/revision.ts';
6
7
  export * from './content/slice-ids.ts';
package/dist/rljson.d.ts CHANGED
@@ -2,6 +2,7 @@ import { Json } from '@rljson/json';
2
2
  import { BuffetsTable } from './content/buffet.ts';
3
3
  import { CakesTable } from './content/cake.ts';
4
4
  import { ComponentsTable } from './content/components.ts';
5
+ import { HeadsTable } from './content/head.ts';
5
6
  import { LayersTable } from './content/layer.ts';
6
7
  import { RevisionsTable } from './content/revision.ts';
7
8
  import { SliceIdsTable } from './content/slice-ids.ts';
@@ -16,7 +17,7 @@ export declare const reservedTableKeys: string[];
16
17
  /**
17
18
  * One of the supported Rljson table types
18
19
  */
19
- export type TableType = BuffetsTable | ComponentsTable<any> | LayersTable | SliceIdsTable | CakesTable | RevisionsTable | TablesCfgTable | InsertHistoryTable<any> | EditsTable | MultiEditsTable | EditHistoryTable;
20
+ export type TableType = BuffetsTable | ComponentsTable<any> | LayersTable | SliceIdsTable | CakesTable | RevisionsTable | TablesCfgTable | InsertHistoryTable<any> | EditsTable | MultiEditsTable | EditHistoryTable | HeadsTable;
20
21
  /** The rljson data format */
21
22
  export interface Rljson extends Json {
22
23
  [tableId: TableKey]: TableType;
package/dist/rljson.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { hip, hsh } from "@rljson/hash";
2
2
  import { exampleJsonObject, jsonValueTypes, jsonValueMatchesType, jsonValueType } from "@rljson/json";
3
3
  import { nanoid } from "nanoid";
4
+ const routeRefSeperator = "@";
5
+ const routeSliceIdIndicators = ["(", ")"];
6
+ const routeSliceIdSeperator = ",";
4
7
  class Route {
5
8
  constructor(_segments) {
6
9
  this._segments = _segments;
@@ -16,12 +19,20 @@ class Route {
16
19
  const segmentsFlat = route.split("/").filter((s) => s.length > 0);
17
20
  const segments = [];
18
21
  for (const segmentFlat of segmentsFlat) {
19
- const [tableKey, refFlat] = segmentFlat.split("@");
22
+ const [tableKeyAndSliceId, refFlat] = segmentFlat.split(routeRefSeperator);
23
+ const sliceIds = tableKeyAndSliceId.substring(
24
+ tableKeyAndSliceId.indexOf(routeSliceIdIndicators[0]) + 1,
25
+ tableKeyAndSliceId.indexOf(routeSliceIdIndicators[1])
26
+ ).split(routeSliceIdSeperator).filter((s) => s.length > 0);
27
+ const tableKey = tableKeyAndSliceId.split(routeSliceIdIndicators[0])[0];
20
28
  const ref = !!refFlat ? refFlat.split(":").length == 2 ? { [tableKey + "InsertHistoryRef"]: refFlat } : { [tableKey + "Ref"]: refFlat } : {};
21
29
  const segment = {
22
30
  tableKey,
23
31
  ...ref
24
32
  };
33
+ if (sliceIds.length > 0) {
34
+ segment.sliceIds = sliceIds;
35
+ }
25
36
  segments.push(segment);
26
37
  }
27
38
  return new Route(segments);
@@ -46,8 +57,9 @@ class Route {
46
57
  * @returns A new Route that is one level deeper or 'steps' levels deeper
47
58
  */
48
59
  deeper(steps) {
60
+ let deeperRoute;
49
61
  if (steps === void 0) {
50
- return new Route(this._segments.slice(1, this._segments.length));
62
+ deeperRoute = new Route(this._segments.slice(1, this._segments.length));
51
63
  } else {
52
64
  if (steps < 1) {
53
65
  throw new Error("Steps must be greater than 0");
@@ -55,8 +67,14 @@ class Route {
55
67
  if (steps >= this._segments.length) {
56
68
  throw new Error("Cannot go deeper than the root");
57
69
  }
58
- return new Route(this._segments.slice(steps, this._segments.length));
70
+ deeperRoute = new Route(
71
+ this._segments.slice(steps, this._segments.length)
72
+ );
59
73
  }
74
+ if (!!this.propertyKey) {
75
+ deeperRoute.propertyKey = this.propertyKey;
76
+ }
77
+ return deeperRoute;
60
78
  }
61
79
  // .............................................................................
62
80
  /**
@@ -159,8 +177,13 @@ class Route {
159
177
  let flat = "";
160
178
  for (const segment of this._segments) {
161
179
  const tableKey = segment.tableKey;
162
- const ref = Object.keys(segment).filter((k) => k !== "tableKey")[0];
163
- flat += `/${tableKey}${ref ? `@${segment[ref]}` : ""}`;
180
+ const tableKeyAndSliceId = segment.sliceIds ? `${tableKey}${routeSliceIdIndicators[0]}${segment.sliceIds.join(
181
+ routeSliceIdSeperator
182
+ )}${routeSliceIdIndicators[1]}` : tableKey;
183
+ const ref = Object.keys(segment).filter(
184
+ (k) => ["tableKey", "sliceIds"].indexOf(k) === -1
185
+ )[0];
186
+ flat += `/${tableKeyAndSliceId}${ref ? `${routeRefSeperator}${segment[ref]}` : ""}`;
164
187
  }
165
188
  return flat;
166
189
  }
@@ -504,6 +527,36 @@ const createCakeTableCfg = (cakeKey) => ({
504
527
  });
505
528
  const exampleCakesTable = () => bakeryExample().cakes;
506
529
  const exampleComponentsTable = () => bakeryExample().nutritionalValues;
530
+ const createHeadsTableCfg = (cakeKey) => ({
531
+ key: `${cakeKey}Heads`,
532
+ type: "head",
533
+ columns: [
534
+ {
535
+ key: "_hash",
536
+ type: "string",
537
+ titleLong: "Hash",
538
+ titleShort: "Hash"
539
+ },
540
+ {
541
+ key: "timeId",
542
+ type: "string",
543
+ titleLong: "Time Identifier",
544
+ titleShort: "Time ID"
545
+ },
546
+ {
547
+ key: "cakeRef",
548
+ type: "string",
549
+ titleLong: "Cake Reference",
550
+ titleShort: "Cake Ref",
551
+ ref: {
552
+ tableKey: `${cakeKey}`
553
+ }
554
+ }
555
+ ],
556
+ isHead: false,
557
+ isRoot: false,
558
+ isShared: true
559
+ });
507
560
  const createLayerTableCfg = (layerKey) => ({
508
561
  key: layerKey,
509
562
  type: "layers",
@@ -544,6 +597,34 @@ const exampleRevision = () => ({
544
597
  timestamp: 1743558427
545
598
  });
546
599
  const exampleSliceIdsTable = () => bakeryExample().slices;
600
+ const createSliceIdsTableCfg = (tableKey) => ({
601
+ key: tableKey,
602
+ type: "sliceIds",
603
+ columns: [
604
+ { key: "_hash", type: "string", titleLong: "Hash", titleShort: "Hash" },
605
+ {
606
+ key: "base",
607
+ type: "string",
608
+ titleLong: "Base SliceId",
609
+ titleShort: "Base SliceId"
610
+ },
611
+ {
612
+ key: "add",
613
+ type: "jsonArray",
614
+ titleLong: "Added SliceIds",
615
+ titleShort: "Add"
616
+ },
617
+ {
618
+ key: "remove",
619
+ type: "jsonArray",
620
+ titleLong: "Removed SliceIds",
621
+ titleShort: "Remove"
622
+ }
623
+ ],
624
+ isHead: false,
625
+ isRoot: false,
626
+ isShared: true
627
+ });
547
628
  class Example {
548
629
  static ok = {
549
630
  bakery: () => bakeryExample(),
@@ -1458,7 +1539,7 @@ const createEditHistoryTableCfg = (cakeKey) => ({
1458
1539
  titleLong: "Multi Edit Reference",
1459
1540
  titleShort: "Multi Edit Ref",
1460
1541
  ref: {
1461
- tableKey: `${cakeKey}MultiEdit`
1542
+ tableKey: `${cakeKey}MultiEdits`
1462
1543
  }
1463
1544
  },
1464
1545
  {
@@ -1476,7 +1557,10 @@ const createEditHistoryTableCfg = (cakeKey) => ({
1476
1557
  titleLong: "Previous Values",
1477
1558
  titleShort: "Previous"
1478
1559
  }
1479
- ]
1560
+ ],
1561
+ isHead: false,
1562
+ isRoot: false,
1563
+ isShared: true
1480
1564
  });
1481
1565
  const createEditTableCfg = (cakeKey) => ({
1482
1566
  key: `${cakeKey}Edits`,
@@ -1500,7 +1584,10 @@ const createEditTableCfg = (cakeKey) => ({
1500
1584
  titleLong: "Edit Action Data",
1501
1585
  titleShort: "Action"
1502
1586
  }
1503
- ]
1587
+ ],
1588
+ isHead: false,
1589
+ isRoot: false,
1590
+ isShared: true
1504
1591
  });
1505
1592
  const createMultiEditTableCfg = (cakeKey) => ({
1506
1593
  key: `${cakeKey}MultiEdits`,
@@ -1527,7 +1614,10 @@ const createMultiEditTableCfg = (cakeKey) => ({
1527
1614
  tableKey: `${cakeKey}Edits`
1528
1615
  }
1529
1616
  }
1530
- ]
1617
+ ],
1618
+ isHead: false,
1619
+ isRoot: false,
1620
+ isShared: true
1531
1621
  });
1532
1622
  const objectDepth = (o) => Object(o) === o ? 1 + Math.max(-1, ...Object.values(o).map(objectDepth)) : 0;
1533
1623
  class InsertValidator {
@@ -1758,7 +1848,8 @@ const contentTypes = [
1758
1848
  "insertHistory",
1759
1849
  "edits",
1760
1850
  "multiEdits",
1761
- "editHistory"
1851
+ "editHistory",
1852
+ "head"
1762
1853
  ];
1763
1854
  const exampleTypedefs = () => {
1764
1855
  return {
@@ -2612,9 +2703,11 @@ export {
2612
2703
  createCakeTableCfg,
2613
2704
  createEditHistoryTableCfg,
2614
2705
  createEditTableCfg,
2706
+ createHeadsTableCfg,
2615
2707
  createInsertHistoryTableCfg,
2616
2708
  createLayerTableCfg,
2617
2709
  createMultiEditTableCfg,
2710
+ createSliceIdsTableCfg,
2618
2711
  exampleBuffetsTable,
2619
2712
  exampleCakesTable,
2620
2713
  exampleComponentsTable,
@@ -2636,6 +2729,9 @@ export {
2636
2729
  removeDuplicates,
2637
2730
  reservedFieldNames,
2638
2731
  reservedTableKeys,
2732
+ routeRefSeperator,
2733
+ routeSliceIdIndicators,
2734
+ routeSliceIdSeperator,
2639
2735
  throwOnInvalidTableCfg,
2640
2736
  timeId,
2641
2737
  validateInsert,
@@ -1,10 +1,14 @@
1
- import { TableKey } from '../typedefs.ts';
1
+ import { SliceId, TableKey } from '../typedefs.ts';
2
2
  export type RouteRef = string;
3
3
  export type RouteSegment<Str extends string> = {
4
4
  [key in Str as `${Uncapitalize<string & key>}Ref`]: string;
5
5
  } & {
6
6
  tableKey: TableKey;
7
+ sliceIds?: SliceId[];
7
8
  };
9
+ export declare const routeRefSeperator = "@";
10
+ export declare const routeSliceIdIndicators: readonly ["(", ")"];
11
+ export declare const routeSliceIdSeperator: ",";
8
12
  export type RouteSegmentFlat<N extends string> = `${N}` | `${N}@${string}` | `${N}@${string}:${string}`;
9
13
  /**
10
14
  * A class to handle routes in an Rljson object.
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * Generates a new TimeId.
3
- * A TimeId is a string in the format "xxxx:timestamp" where:
4
- * - "xxxx" is a 4-character unique identifier
3
+ * A TimeId has the format "timestamp:xxxx" where:
5
4
  * - "timestamp" is the current time in milliseconds since epoch
5
+ * - "xxxx" is a 4-character unique identifier
6
6
  * @returns A new TimeId string
7
7
  */
8
8
  export declare const timeId: () => string;
9
9
  /**
10
10
  * Checks if a given id is a valid TimeId.
11
- * A valid TimeId has the format "xxxx:timestamp" where:
12
- * - "xxxx" is a 4-character string
13
- * - "timestamp" is a valid number representing milliseconds since epoch
11
+ * A TimeId has the format "timestamp:xxxx" where:
12
+ * - "timestamp" is the current time in milliseconds since epoch
13
+ * - "xxxx" is a 4-character unique identifier
14
14
  * @param id - The id to check
15
15
  * @returns True if the id is a valid TimeId, false otherwise
16
16
  */
@@ -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", "insertHistory", "edits", "multiEdits", "editHistory"];
29
+ export declare const contentTypes: readonly ["buffets", "cakes", "layers", "sliceIds", "components", "revisions", "tableCfgs", "insertHistory", "edits", "multiEdits", "editHistory", "head"];
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.71",
3
+ "version": "0.0.73",
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",
@@ -21,23 +21,23 @@
21
21
  "type": "module",
22
22
  "devDependencies": {
23
23
  "@types/node": "^24.10.1",
24
- "@typescript-eslint/eslint-plugin": "^8.46.4",
25
- "@typescript-eslint/parser": "^8.46.4",
26
- "@vitest/coverage-v8": "^4.0.9",
24
+ "@typescript-eslint/eslint-plugin": "^8.48.1",
25
+ "@typescript-eslint/parser": "^8.48.1",
26
+ "@vitest/coverage-v8": "^4.0.15",
27
27
  "cross-env": "^10.1.0",
28
28
  "eslint": "^9.39.1",
29
- "eslint-plugin-jsdoc": "^61.2.1",
29
+ "eslint-plugin-jsdoc": "^61.4.1",
30
30
  "eslint-plugin-tsdoc": "^0.5.0",
31
31
  "globals": "^16.5.0",
32
32
  "jsdoc": "^4.0.5",
33
33
  "read-pkg": "^10.0.0",
34
34
  "typescript": "~5.9.3",
35
- "typescript-eslint": "^8.46.4",
36
- "vite": "^7.2.2",
37
- "vite-node": "^5.1.0",
35
+ "typescript-eslint": "^8.48.1",
36
+ "vite": "^7.2.6",
37
+ "vite-node": "^5.2.0",
38
38
  "vite-plugin-dts": "^4.5.4",
39
39
  "vite-tsconfig-paths": "^5.1.4",
40
- "vitest": "^4.0.9",
40
+ "vitest": "^4.0.15",
41
41
  "vitest-dom": "^0.1.1"
42
42
  },
43
43
  "dependencies": {