@rljson/rljson 0.0.66 → 0.0.67
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/bakery-example.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/insertHistory/insertHistory.d.ts +24 -0
- package/dist/rljson.d.ts +2 -2
- package/dist/rljson.js +204 -76
- package/dist/route/route.d.ts +76 -5
- package/dist/typedefs.d.ts +1 -1
- package/package.json +11 -11
- package/dist/history/history.d.ts +0 -24
|
@@ -4,7 +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 {
|
|
7
|
+
import { InsertHistory } from '../insertHistory/insertHistory.ts';
|
|
8
8
|
import { Rljson } from '../rljson.ts';
|
|
9
9
|
import { Ref } from '../typedefs.ts';
|
|
10
10
|
export interface Ingredient extends Json {
|
|
@@ -32,6 +32,6 @@ export interface Bakery extends Rljson {
|
|
|
32
32
|
recipeIngredients: ComponentsTable<RecipIngredient>;
|
|
33
33
|
ingredients: ComponentsTable<Ingredient>;
|
|
34
34
|
nutritionalValues: ComponentsTable<NutritionalValues>;
|
|
35
|
-
|
|
35
|
+
ingredientsInsertHistory: InsertHistory<'Ingredients'>;
|
|
36
36
|
}
|
|
37
37
|
export declare const bakeryExample: () => Bakery;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,9 @@ export * from './content/slice-ids.ts';
|
|
|
7
7
|
export * from './content/table-cfg.ts';
|
|
8
8
|
export * from './example.ts';
|
|
9
9
|
export * from './example/bakery-example.ts';
|
|
10
|
-
export * from './history/history.ts';
|
|
11
10
|
export * from './insert/insert-validator.ts';
|
|
12
11
|
export * from './insert/insert.ts';
|
|
12
|
+
export * from './insertHistory/insertHistory.ts';
|
|
13
13
|
export * from './rljson.ts';
|
|
14
14
|
export * from './route/route.ts';
|
|
15
15
|
export * from './tools/remove-duplicates.ts';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TableCfg } from '../content/table-cfg.ts';
|
|
2
|
+
import { RljsonTable } from '../rljson.ts';
|
|
3
|
+
import { RouteRef } from '../route/route.ts';
|
|
4
|
+
import { Ref } from '../typedefs.ts';
|
|
5
|
+
export type InsertHistoryTimeId = string;
|
|
6
|
+
export type InsertHistoryRow<Str extends string> = {
|
|
7
|
+
[key in Str as `${Uncapitalize<string & key>}Ref`]: string;
|
|
8
|
+
} & {
|
|
9
|
+
timeId: InsertHistoryTimeId;
|
|
10
|
+
route: RouteRef;
|
|
11
|
+
origin?: Ref;
|
|
12
|
+
previous?: InsertHistoryTimeId[];
|
|
13
|
+
};
|
|
14
|
+
export type InsertHistory<Str extends string> = RljsonTable<InsertHistoryRow<Str>, 'insertHistory'>;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a TableCfg for a InsertHistory table for the given table configuration
|
|
17
|
+
* @param tableCfg - The table configuration to create the InsertHistory table for
|
|
18
|
+
* @returns The TableCfg for the InsertHistory table
|
|
19
|
+
*/
|
|
20
|
+
export declare const createInsertHistoryTableCfg: (tableCfg: TableCfg) => TableCfg;
|
|
21
|
+
/**
|
|
22
|
+
* Provides an example insertHistory table for test purposes
|
|
23
|
+
*/
|
|
24
|
+
export declare const exampleInsertHistoryTable: () => InsertHistory<any>;
|
package/dist/rljson.d.ts
CHANGED
|
@@ -6,14 +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 {
|
|
9
|
+
import { InsertHistory } from './insertHistory/insertHistory.ts';
|
|
10
10
|
import { ContentType, Ref, TableKey } from './typedefs.ts';
|
|
11
11
|
export declare const reservedFieldNames: string[];
|
|
12
12
|
export declare const reservedTableKeys: string[];
|
|
13
13
|
/**
|
|
14
14
|
* One of the supported Rljson table types
|
|
15
15
|
*/
|
|
16
|
-
export type TableType = BuffetsTable | ComponentsTable<any> | LayersTable | SliceIdsTable | CakesTable | RevisionsTable | TablesCfgTable |
|
|
16
|
+
export type TableType = BuffetsTable | ComponentsTable<any> | LayersTable | SliceIdsTable | CakesTable | RevisionsTable | TablesCfgTable | InsertHistory<any>;
|
|
17
17
|
/** The rljson data format */
|
|
18
18
|
export interface Rljson extends Json {
|
|
19
19
|
[tableId: TableKey]: TableType;
|
package/dist/rljson.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
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
|
-
// @license
|
|
5
4
|
class Route {
|
|
6
5
|
constructor(_segments) {
|
|
7
6
|
this._segments = _segments;
|
|
8
7
|
}
|
|
8
|
+
_propertyKey;
|
|
9
9
|
// .............................................................................
|
|
10
10
|
/**
|
|
11
11
|
* Creates a Route from a flat string representation.
|
|
@@ -17,7 +17,7 @@ class Route {
|
|
|
17
17
|
const segments = [];
|
|
18
18
|
for (const segmentFlat of segmentsFlat) {
|
|
19
19
|
const [tableKey, refFlat] = segmentFlat.split("@");
|
|
20
|
-
const ref = !!refFlat ? refFlat.split(":").length == 2 ? { [tableKey + "
|
|
20
|
+
const ref = !!refFlat ? refFlat.split(":").length == 2 ? { [tableKey + "InsertHistoryRef"]: refFlat } : { [tableKey + "Ref"]: refFlat } : {};
|
|
21
21
|
const segment = {
|
|
22
22
|
tableKey,
|
|
23
23
|
...ref
|
|
@@ -59,6 +59,78 @@ class Route {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
// .............................................................................
|
|
62
|
+
/**
|
|
63
|
+
* Returns a new Route that is one level higher than the current route.
|
|
64
|
+
* If steps is provided, it returns a new Route that is 'steps' levels higher.
|
|
65
|
+
* @param steps - The number of levels to go higher (optional)
|
|
66
|
+
* @returns A new Route that is one level higher or 'steps' levels higher
|
|
67
|
+
*/
|
|
68
|
+
upper(steps) {
|
|
69
|
+
if (steps === void 0) {
|
|
70
|
+
return new Route(this._segments.slice(0, -1));
|
|
71
|
+
} else {
|
|
72
|
+
if (steps < 1) {
|
|
73
|
+
throw new Error("Steps must be greater than 0");
|
|
74
|
+
}
|
|
75
|
+
if (steps >= this._segments.length) {
|
|
76
|
+
throw new Error("Cannot go upper than the top level");
|
|
77
|
+
}
|
|
78
|
+
return new Route(this._segments.slice(0, -steps));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// .............................................................................
|
|
82
|
+
/**
|
|
83
|
+
* Returns a new Route with the property key set to the last segment's table key.
|
|
84
|
+
* If the property key is already set, it returns the current route.
|
|
85
|
+
* @returns A new Route with the property key set
|
|
86
|
+
*/
|
|
87
|
+
toRouteWithProperty() {
|
|
88
|
+
if (this.hasPropertyKey) return this;
|
|
89
|
+
const route = this.upper();
|
|
90
|
+
route.propertyKey = this.segment().tableKey;
|
|
91
|
+
return route;
|
|
92
|
+
}
|
|
93
|
+
// .............................................................................
|
|
94
|
+
/**
|
|
95
|
+
* Returns a new Route without the property key.
|
|
96
|
+
* If the property key is not set, it returns the current route.
|
|
97
|
+
* @returns A new Route without the property key
|
|
98
|
+
*/
|
|
99
|
+
toRouteWithoutProperty() {
|
|
100
|
+
if (!this.hasPropertyKey) return this;
|
|
101
|
+
const route = new Route(this._segments);
|
|
102
|
+
route.propertyKey = void 0;
|
|
103
|
+
return route;
|
|
104
|
+
}
|
|
105
|
+
// .............................................................................
|
|
106
|
+
/**
|
|
107
|
+
* Checks if the current route includes another route.
|
|
108
|
+
* A route includes another route if all segments of the other route
|
|
109
|
+
* are present in the current route in the same order.
|
|
110
|
+
* @param other - The other route to check
|
|
111
|
+
* @returns True if the current route includes the other route, false otherwise
|
|
112
|
+
*/
|
|
113
|
+
includes(other) {
|
|
114
|
+
if (other._segments.length < this._segments.length) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
for (let i = 0; i < this._segments.length; i++) {
|
|
118
|
+
const thisSegment = this._segments[i];
|
|
119
|
+
const otherSegment = other._segments[i];
|
|
120
|
+
if (thisSegment.tableKey !== otherSegment.tableKey) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (Route.segmentHasRef(thisSegment) && Route.segmentHasRef(otherSegment)) {
|
|
124
|
+
const thisRef = Route.segmentRef(thisSegment);
|
|
125
|
+
const otherRef = Route.segmentRef(otherSegment);
|
|
126
|
+
if (thisRef !== otherRef) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
// .............................................................................
|
|
62
134
|
/**
|
|
63
135
|
* Checks if the current route is the root route.
|
|
64
136
|
* @returns True if the current route is the root route, false otherwise
|
|
@@ -72,6 +144,18 @@ class Route {
|
|
|
72
144
|
* @returns The flat string representation of the route (e.g. "/a/b/c")
|
|
73
145
|
*/
|
|
74
146
|
get flat() {
|
|
147
|
+
let flat = this.flatWithoutPropertyKey;
|
|
148
|
+
if (this.hasPropertyKey) {
|
|
149
|
+
flat += `/${this.propertyKey}`;
|
|
150
|
+
}
|
|
151
|
+
return flat;
|
|
152
|
+
}
|
|
153
|
+
// .............................................................................
|
|
154
|
+
/**
|
|
155
|
+
* Returns the flat string representation of the route without the property key.
|
|
156
|
+
* @returns The flat string representation of the route without the property key
|
|
157
|
+
*/
|
|
158
|
+
get flatWithoutPropertyKey() {
|
|
75
159
|
let flat = "";
|
|
76
160
|
for (const segment of this._segments) {
|
|
77
161
|
const tableKey = segment.tableKey;
|
|
@@ -81,6 +165,22 @@ class Route {
|
|
|
81
165
|
return flat;
|
|
82
166
|
}
|
|
83
167
|
// .............................................................................
|
|
168
|
+
/**
|
|
169
|
+
* Returns the flat string representation of the route without any references.
|
|
170
|
+
* @returns The flat string representation of the route without any references
|
|
171
|
+
*/
|
|
172
|
+
get flatWithoutRefs() {
|
|
173
|
+
let flat = "";
|
|
174
|
+
for (const segment of this._segments) {
|
|
175
|
+
const tableKey = segment.tableKey;
|
|
176
|
+
flat += `/${tableKey}`;
|
|
177
|
+
}
|
|
178
|
+
if (this.hasPropertyKey) {
|
|
179
|
+
flat += `/${this.propertyKey}`;
|
|
180
|
+
}
|
|
181
|
+
return flat;
|
|
182
|
+
}
|
|
183
|
+
// .............................................................................
|
|
84
184
|
/**
|
|
85
185
|
* Returns the segments of the route as an array of strings.
|
|
86
186
|
* @returns The segments of the route as an array of strings
|
|
@@ -121,6 +221,57 @@ class Route {
|
|
|
121
221
|
return this._segments.length > 0 && this._segments.every((s) => s.tableKey.length > 0);
|
|
122
222
|
}
|
|
123
223
|
// .............................................................................
|
|
224
|
+
/**
|
|
225
|
+
* Checks if the route has a property key.
|
|
226
|
+
* @returns True if the route has a property key, false otherwise
|
|
227
|
+
*/
|
|
228
|
+
get hasPropertyKey() {
|
|
229
|
+
return this._propertyKey !== void 0;
|
|
230
|
+
}
|
|
231
|
+
// .............................................................................
|
|
232
|
+
/**
|
|
233
|
+
* Returns the property key of the route if it exists.
|
|
234
|
+
* @returns The property key of the route or undefined if it doesn't exist
|
|
235
|
+
*/
|
|
236
|
+
get propertyKey() {
|
|
237
|
+
return this._propertyKey;
|
|
238
|
+
}
|
|
239
|
+
// .............................................................................
|
|
240
|
+
/**
|
|
241
|
+
* Sets the property key of the route.
|
|
242
|
+
* @param key - The property key to set
|
|
243
|
+
*/
|
|
244
|
+
set propertyKey(key) {
|
|
245
|
+
this._propertyKey = key;
|
|
246
|
+
}
|
|
247
|
+
// .............................................................................
|
|
248
|
+
/**
|
|
249
|
+
* Checks if two routes are equal.
|
|
250
|
+
* @param other - The other route to compare with
|
|
251
|
+
* @returns True if the routes are equal, false otherwise
|
|
252
|
+
*/
|
|
253
|
+
equals(other) {
|
|
254
|
+
return this.flat === other.flat;
|
|
255
|
+
}
|
|
256
|
+
// .............................................................................
|
|
257
|
+
/**
|
|
258
|
+
* Checks if two routes are equal without considering the property key.
|
|
259
|
+
* @param other - The other route to compare with
|
|
260
|
+
* @returns True if the routes are equal without considering the property key, false otherwise
|
|
261
|
+
*/
|
|
262
|
+
equalsWithoutPropertyKey(other) {
|
|
263
|
+
return this.flatWithoutPropertyKey === other.flatWithoutPropertyKey;
|
|
264
|
+
}
|
|
265
|
+
// .............................................................................
|
|
266
|
+
/**
|
|
267
|
+
* Checks if two routes are equal without considering the references.
|
|
268
|
+
* @param other - The other route to compare with
|
|
269
|
+
* @returns True if the routes are equal without considering the references, false otherwise
|
|
270
|
+
*/
|
|
271
|
+
equalsWithoutRefs(other) {
|
|
272
|
+
return this.flatWithoutRefs === other.flatWithoutRefs;
|
|
273
|
+
}
|
|
274
|
+
// .............................................................................
|
|
124
275
|
/**
|
|
125
276
|
* Returns the reference of a segment if it exists.
|
|
126
277
|
* @param segment - The segment to get the reference from
|
|
@@ -131,7 +282,6 @@ class Route {
|
|
|
131
282
|
const refKey = Object.keys(segment).find(
|
|
132
283
|
(k) => k.endsWith("Ref") && k !== "tableKey"
|
|
133
284
|
);
|
|
134
|
-
/* v8 ignore next -- @preserve */
|
|
135
285
|
if (refKey) {
|
|
136
286
|
return segment[refKey];
|
|
137
287
|
}
|
|
@@ -140,7 +290,7 @@ class Route {
|
|
|
140
290
|
}
|
|
141
291
|
// .............................................................................
|
|
142
292
|
/**
|
|
143
|
-
* Checks if a segment has any reference (either default or
|
|
293
|
+
* Checks if a segment has any reference (either default or insertHistory).
|
|
144
294
|
* @param segment - The segment to check
|
|
145
295
|
* @returns True if the segment has any reference, false otherwise
|
|
146
296
|
*/
|
|
@@ -149,24 +299,23 @@ class Route {
|
|
|
149
299
|
}
|
|
150
300
|
// .............................................................................
|
|
151
301
|
/**
|
|
152
|
-
* Checks if a segment has a default reference (i.e. not a
|
|
302
|
+
* Checks if a segment has a default reference (i.e. not a insertHistory reference).
|
|
153
303
|
* @param segment - The segment to check
|
|
154
304
|
* @returns True if the segment has a default reference, false otherwise
|
|
155
305
|
*/
|
|
156
306
|
static segmentHasDefaultRef(segment) {
|
|
157
|
-
return this.segmentHasRef(segment) && !this.
|
|
307
|
+
return this.segmentHasRef(segment) && !this.segmentHasInsertHistoryRef(segment);
|
|
158
308
|
}
|
|
159
309
|
// .............................................................................
|
|
160
310
|
/**
|
|
161
|
-
* Checks if a segment has a
|
|
311
|
+
* Checks if a segment has a insertHistory reference (i.e. an InsertHistoryRef).
|
|
162
312
|
* @param segment - The segment to check
|
|
163
|
-
* @returns True if the segment has a
|
|
313
|
+
* @returns True if the segment has a insertHistory reference, false otherwise
|
|
164
314
|
*/
|
|
165
|
-
static
|
|
166
|
-
return this.segmentHasRef(segment) && Object.keys(segment).some((k) => k.endsWith("
|
|
315
|
+
static segmentHasInsertHistoryRef(segment) {
|
|
316
|
+
return this.segmentHasRef(segment) && Object.keys(segment).some((k) => k.endsWith("InsertHistoryRef"));
|
|
167
317
|
}
|
|
168
318
|
}
|
|
169
|
-
// @license
|
|
170
319
|
const bakeryExample = () => {
|
|
171
320
|
const nutritionalValues = hip({
|
|
172
321
|
_type: "components",
|
|
@@ -294,8 +443,8 @@ const bakeryExample = () => {
|
|
|
294
443
|
}
|
|
295
444
|
]
|
|
296
445
|
});
|
|
297
|
-
const
|
|
298
|
-
_type: "
|
|
446
|
+
const ingredientsInsertHistory = hip({
|
|
447
|
+
_type: "insertHistory",
|
|
299
448
|
_data: [
|
|
300
449
|
{
|
|
301
450
|
timeId: "de72:1759123957292",
|
|
@@ -324,13 +473,11 @@ const bakeryExample = () => {
|
|
|
324
473
|
recipeIngredients,
|
|
325
474
|
ingredients,
|
|
326
475
|
nutritionalValues,
|
|
327
|
-
|
|
476
|
+
ingredientsInsertHistory
|
|
328
477
|
};
|
|
329
478
|
return result;
|
|
330
479
|
};
|
|
331
|
-
// @license
|
|
332
480
|
const exampleBuffetsTable = () => bakeryExample().buffets;
|
|
333
|
-
// @license
|
|
334
481
|
const createCakeTableCfg = (cakeKey) => ({
|
|
335
482
|
key: cakeKey,
|
|
336
483
|
type: "cakes",
|
|
@@ -356,9 +503,7 @@ const createCakeTableCfg = (cakeKey) => ({
|
|
|
356
503
|
isShared: true
|
|
357
504
|
});
|
|
358
505
|
const exampleCakesTable = () => bakeryExample().cakes;
|
|
359
|
-
// @license
|
|
360
506
|
const exampleComponentsTable = () => bakeryExample().nutritionalValues;
|
|
361
|
-
// @license
|
|
362
507
|
const createLayerTableCfg = (layerKey) => ({
|
|
363
508
|
key: layerKey,
|
|
364
509
|
type: "layers",
|
|
@@ -391,7 +536,6 @@ const createLayerTableCfg = (layerKey) => ({
|
|
|
391
536
|
isShared: true
|
|
392
537
|
});
|
|
393
538
|
const exampleLayersTable = () => bakeryExample().recipeLayers;
|
|
394
|
-
// @license
|
|
395
539
|
const exampleRevision = () => ({
|
|
396
540
|
table: "nutritionalValues",
|
|
397
541
|
id: "flour",
|
|
@@ -399,9 +543,7 @@ const exampleRevision = () => ({
|
|
|
399
543
|
successor: "IqeoWJjZQNlr-NVk2QT15B",
|
|
400
544
|
timestamp: 1743558427
|
|
401
545
|
});
|
|
402
|
-
// @license
|
|
403
546
|
const exampleSliceIdsTable = () => bakeryExample().slices;
|
|
404
|
-
// @license
|
|
405
547
|
class Example {
|
|
406
548
|
static ok = {
|
|
407
549
|
bakery: () => bakeryExample(),
|
|
@@ -1188,7 +1330,6 @@ class Example {
|
|
|
1188
1330
|
}
|
|
1189
1331
|
};
|
|
1190
1332
|
}
|
|
1191
|
-
// @license
|
|
1192
1333
|
const throwOnInvalidTableCfg = (tableCfg) => {
|
|
1193
1334
|
if (tableCfg.columns.length < 2) {
|
|
1194
1335
|
throw new Error(
|
|
@@ -1295,46 +1436,7 @@ const exampleTableCfg = (tableCfg = void 0) => {
|
|
|
1295
1436
|
isShared: false
|
|
1296
1437
|
};
|
|
1297
1438
|
};
|
|
1298
|
-
// @license
|
|
1299
|
-
const createHistoryTableCfg = (tableCfg) => ({
|
|
1300
|
-
key: `${tableCfg.key}History`,
|
|
1301
|
-
type: "history",
|
|
1302
|
-
columns: [
|
|
1303
|
-
{ key: "_hash", type: "string", titleLong: "Hash", titleShort: "Hash" },
|
|
1304
|
-
{
|
|
1305
|
-
key: "timeId",
|
|
1306
|
-
type: "string",
|
|
1307
|
-
titleLong: "Time ID",
|
|
1308
|
-
titleShort: "Time ID"
|
|
1309
|
-
},
|
|
1310
|
-
{
|
|
1311
|
-
key: `${tableCfg.key}Ref`,
|
|
1312
|
-
type: "string",
|
|
1313
|
-
titleLong: "Reference",
|
|
1314
|
-
titleShort: "Ref"
|
|
1315
|
-
},
|
|
1316
|
-
{ key: "route", type: "string", titleLong: "Route", titleShort: "Route" },
|
|
1317
|
-
{
|
|
1318
|
-
key: "origin",
|
|
1319
|
-
type: "string",
|
|
1320
|
-
titleLong: "Origin",
|
|
1321
|
-
titleShort: "Origin"
|
|
1322
|
-
},
|
|
1323
|
-
{
|
|
1324
|
-
key: "previous",
|
|
1325
|
-
type: "jsonArray",
|
|
1326
|
-
titleLong: "Previous",
|
|
1327
|
-
titleShort: "Previous"
|
|
1328
|
-
}
|
|
1329
|
-
],
|
|
1330
|
-
isHead: false,
|
|
1331
|
-
isRoot: false,
|
|
1332
|
-
isShared: false
|
|
1333
|
-
});
|
|
1334
|
-
const exampleHistoryTable = () => bakeryExample().ingredientsHistory;
|
|
1335
|
-
// @license
|
|
1336
1439
|
const objectDepth = (o) => Object(o) === o ? 1 + Math.max(-1, ...Object.values(o).map(objectDepth)) : 0;
|
|
1337
|
-
// @license
|
|
1338
1440
|
class InsertValidator {
|
|
1339
1441
|
constructor(_insert) {
|
|
1340
1442
|
this._insert = _insert;
|
|
@@ -1388,9 +1490,9 @@ class InsertValidator {
|
|
|
1388
1490
|
if (route.isValid) {
|
|
1389
1491
|
const routeDepth = route.segments.length;
|
|
1390
1492
|
const valueDepth = objectDepth(this._insert.value);
|
|
1391
|
-
if (routeDepth
|
|
1493
|
+
if (routeDepth > valueDepth) {
|
|
1392
1494
|
this.errors.dataRouteMismatch = {
|
|
1393
|
-
error: "Insert route depth does not match value depth. Route depth must
|
|
1495
|
+
error: "Insert route depth does not match value depth. Route depth must be lower than the depth of the value object.",
|
|
1394
1496
|
route: this._insert.route,
|
|
1395
1497
|
routeDepth,
|
|
1396
1498
|
valueDepth
|
|
@@ -1440,13 +1542,47 @@ class InsertValidator {
|
|
|
1440
1542
|
const validateInsert = (insert) => {
|
|
1441
1543
|
return InsertValidator.create(insert).validate();
|
|
1442
1544
|
};
|
|
1443
|
-
// @license
|
|
1444
1545
|
const exampleInsert = () => ({
|
|
1445
1546
|
route: "a/b/c",
|
|
1446
1547
|
command: "add",
|
|
1447
1548
|
value: { x: { y: { z: true } } }
|
|
1448
1549
|
});
|
|
1449
|
-
|
|
1550
|
+
const createInsertHistoryTableCfg = (tableCfg) => ({
|
|
1551
|
+
key: `${tableCfg.key}InsertHistory`,
|
|
1552
|
+
type: "insertHistory",
|
|
1553
|
+
columns: [
|
|
1554
|
+
{ key: "_hash", type: "string", titleLong: "Hash", titleShort: "Hash" },
|
|
1555
|
+
{
|
|
1556
|
+
key: "timeId",
|
|
1557
|
+
type: "string",
|
|
1558
|
+
titleLong: "Time ID",
|
|
1559
|
+
titleShort: "Time ID"
|
|
1560
|
+
},
|
|
1561
|
+
{
|
|
1562
|
+
key: `${tableCfg.key}Ref`,
|
|
1563
|
+
type: "string",
|
|
1564
|
+
titleLong: "Reference",
|
|
1565
|
+
titleShort: "Ref"
|
|
1566
|
+
},
|
|
1567
|
+
{ key: "route", type: "string", titleLong: "Route", titleShort: "Route" },
|
|
1568
|
+
{
|
|
1569
|
+
key: "origin",
|
|
1570
|
+
type: "string",
|
|
1571
|
+
titleLong: "Origin",
|
|
1572
|
+
titleShort: "Origin"
|
|
1573
|
+
},
|
|
1574
|
+
{
|
|
1575
|
+
key: "previous",
|
|
1576
|
+
type: "jsonArray",
|
|
1577
|
+
titleLong: "Previous",
|
|
1578
|
+
titleShort: "Previous"
|
|
1579
|
+
}
|
|
1580
|
+
],
|
|
1581
|
+
isHead: false,
|
|
1582
|
+
isRoot: false,
|
|
1583
|
+
isShared: false
|
|
1584
|
+
});
|
|
1585
|
+
const exampleInsertHistoryTable = () => bakeryExample().ingredientsInsertHistory;
|
|
1450
1586
|
const reservedFieldNames = ["_data"];
|
|
1451
1587
|
const reservedTableKeys = [
|
|
1452
1588
|
"_hash",
|
|
@@ -1486,7 +1622,6 @@ const iterateTables = async (rljson, callback) => {
|
|
|
1486
1622
|
throw errors;
|
|
1487
1623
|
}
|
|
1488
1624
|
};
|
|
1489
|
-
// @license
|
|
1490
1625
|
const removeDuplicates = (rljson) => {
|
|
1491
1626
|
const result = {};
|
|
1492
1627
|
for (const key in rljson) {
|
|
@@ -1500,7 +1635,6 @@ const removeDuplicates = (rljson) => {
|
|
|
1500
1635
|
}
|
|
1501
1636
|
return hip(result, { throwOnWrongHashes: false, updateExistingHashes: true });
|
|
1502
1637
|
};
|
|
1503
|
-
// @license
|
|
1504
1638
|
const timeId = () => {
|
|
1505
1639
|
return nanoid(4) + ":" + Date.now();
|
|
1506
1640
|
};
|
|
@@ -1510,7 +1644,6 @@ const isTimeId = (id) => {
|
|
|
1510
1644
|
if (isNaN(Number(parts[1]))) return false;
|
|
1511
1645
|
return parts[0].length === 4;
|
|
1512
1646
|
};
|
|
1513
|
-
// @license
|
|
1514
1647
|
const contentTypes = [
|
|
1515
1648
|
"buffets",
|
|
1516
1649
|
"cakes",
|
|
@@ -1519,7 +1652,7 @@ const contentTypes = [
|
|
|
1519
1652
|
"components",
|
|
1520
1653
|
"revisions",
|
|
1521
1654
|
"tableCfgs",
|
|
1522
|
-
"
|
|
1655
|
+
"insertHistory"
|
|
1523
1656
|
];
|
|
1524
1657
|
const exampleTypedefs = () => {
|
|
1525
1658
|
return {
|
|
@@ -1529,7 +1662,6 @@ const exampleTypedefs = () => {
|
|
|
1529
1662
|
contentType: "layers"
|
|
1530
1663
|
};
|
|
1531
1664
|
};
|
|
1532
|
-
// @license
|
|
1533
1665
|
const rljsonIndexed = (rljson) => {
|
|
1534
1666
|
const result = {};
|
|
1535
1667
|
for (const key in rljson) {
|
|
@@ -1552,7 +1684,6 @@ const rljsonIndexed = (rljson) => {
|
|
|
1552
1684
|
}
|
|
1553
1685
|
return result;
|
|
1554
1686
|
};
|
|
1555
|
-
// @license
|
|
1556
1687
|
class BaseValidator {
|
|
1557
1688
|
name = "base";
|
|
1558
1689
|
async validate(rljson) {
|
|
@@ -1968,7 +2099,6 @@ class _BaseValidator {
|
|
|
1968
2099
|
const tableCfgRef = table._tableCfg;
|
|
1969
2100
|
if (!tableCfgRef) return;
|
|
1970
2101
|
const tableCfg = this.rljsonIndexed.tableCfgs._data[tableCfgRef];
|
|
1971
|
-
/* v8 ignore next -- @preserve */
|
|
1972
2102
|
if (!tableCfg) return;
|
|
1973
2103
|
const tableRows = table._data;
|
|
1974
2104
|
for (const row of tableRows) {
|
|
@@ -1977,7 +2107,6 @@ class _BaseValidator {
|
|
|
1977
2107
|
const columnCfg = tableCfg.columns.find(
|
|
1978
2108
|
(col) => col.key === columnKey
|
|
1979
2109
|
);
|
|
1980
|
-
/* v8 ignore next -- @preserve */
|
|
1981
2110
|
if (columnCfg === void 0) continue;
|
|
1982
2111
|
if (columnCfg.ref && columnCfg.ref.tableKey) {
|
|
1983
2112
|
const targetTableKey = columnCfg.ref.tableKey;
|
|
@@ -2331,7 +2460,6 @@ class _BaseValidator {
|
|
|
2331
2460
|
}
|
|
2332
2461
|
}
|
|
2333
2462
|
const isValidFieldName = (fieldName) => BaseValidator.isValidFieldName(fieldName);
|
|
2334
|
-
// @license
|
|
2335
2463
|
class Validate {
|
|
2336
2464
|
addValidator(validator) {
|
|
2337
2465
|
this._validators.push(validator);
|
|
@@ -2376,13 +2504,13 @@ export {
|
|
|
2376
2504
|
bakeryExample,
|
|
2377
2505
|
contentTypes,
|
|
2378
2506
|
createCakeTableCfg,
|
|
2379
|
-
|
|
2507
|
+
createInsertHistoryTableCfg,
|
|
2380
2508
|
createLayerTableCfg,
|
|
2381
2509
|
exampleBuffetsTable,
|
|
2382
2510
|
exampleCakesTable,
|
|
2383
2511
|
exampleComponentsTable,
|
|
2384
|
-
exampleHistoryTable,
|
|
2385
2512
|
exampleInsert,
|
|
2513
|
+
exampleInsertHistoryTable,
|
|
2386
2514
|
exampleLayersTable,
|
|
2387
2515
|
exampleRevision,
|
|
2388
2516
|
exampleRljson,
|
package/dist/route/route.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type RouteSegmentFlat<N extends string> = `${N}` | `${N}@${string}` | `${
|
|
|
11
11
|
*/
|
|
12
12
|
export declare class Route {
|
|
13
13
|
private readonly _segments;
|
|
14
|
+
private _propertyKey?;
|
|
14
15
|
constructor(_segments: RouteSegment<any>[]);
|
|
15
16
|
/**
|
|
16
17
|
* Creates a Route from a flat string representation.
|
|
@@ -31,6 +32,33 @@ export declare class Route {
|
|
|
31
32
|
* @returns A new Route that is one level deeper or 'steps' levels deeper
|
|
32
33
|
*/
|
|
33
34
|
deeper(steps?: number): Route;
|
|
35
|
+
/**
|
|
36
|
+
* Returns a new Route that is one level higher than the current route.
|
|
37
|
+
* If steps is provided, it returns a new Route that is 'steps' levels higher.
|
|
38
|
+
* @param steps - The number of levels to go higher (optional)
|
|
39
|
+
* @returns A new Route that is one level higher or 'steps' levels higher
|
|
40
|
+
*/
|
|
41
|
+
upper(steps?: number): Route;
|
|
42
|
+
/**
|
|
43
|
+
* Returns a new Route with the property key set to the last segment's table key.
|
|
44
|
+
* If the property key is already set, it returns the current route.
|
|
45
|
+
* @returns A new Route with the property key set
|
|
46
|
+
*/
|
|
47
|
+
toRouteWithProperty(): Route;
|
|
48
|
+
/**
|
|
49
|
+
* Returns a new Route without the property key.
|
|
50
|
+
* If the property key is not set, it returns the current route.
|
|
51
|
+
* @returns A new Route without the property key
|
|
52
|
+
*/
|
|
53
|
+
toRouteWithoutProperty(): Route;
|
|
54
|
+
/**
|
|
55
|
+
* Checks if the current route includes another route.
|
|
56
|
+
* A route includes another route if all segments of the other route
|
|
57
|
+
* are present in the current route in the same order.
|
|
58
|
+
* @param other - The other route to check
|
|
59
|
+
* @returns True if the current route includes the other route, false otherwise
|
|
60
|
+
*/
|
|
61
|
+
includes(other: Route): boolean;
|
|
34
62
|
/**
|
|
35
63
|
* Checks if the current route is the root route.
|
|
36
64
|
* @returns True if the current route is the root route, false otherwise
|
|
@@ -41,6 +69,16 @@ export declare class Route {
|
|
|
41
69
|
* @returns The flat string representation of the route (e.g. "/a/b/c")
|
|
42
70
|
*/
|
|
43
71
|
get flat(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Returns the flat string representation of the route without the property key.
|
|
74
|
+
* @returns The flat string representation of the route without the property key
|
|
75
|
+
*/
|
|
76
|
+
get flatWithoutPropertyKey(): string;
|
|
77
|
+
/**
|
|
78
|
+
* Returns the flat string representation of the route without any references.
|
|
79
|
+
* @returns The flat string representation of the route without any references
|
|
80
|
+
*/
|
|
81
|
+
get flatWithoutRefs(): string;
|
|
44
82
|
/**
|
|
45
83
|
* Returns the segments of the route as an array of strings.
|
|
46
84
|
* @returns The segments of the route as an array of strings
|
|
@@ -66,6 +104,39 @@ export declare class Route {
|
|
|
66
104
|
* @returns True if the route is valid, false otherwise
|
|
67
105
|
*/
|
|
68
106
|
get isValid(): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Checks if the route has a property key.
|
|
109
|
+
* @returns True if the route has a property key, false otherwise
|
|
110
|
+
*/
|
|
111
|
+
get hasPropertyKey(): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Returns the property key of the route if it exists.
|
|
114
|
+
* @returns The property key of the route or undefined if it doesn't exist
|
|
115
|
+
*/
|
|
116
|
+
get propertyKey(): string | undefined;
|
|
117
|
+
/**
|
|
118
|
+
* Sets the property key of the route.
|
|
119
|
+
* @param key - The property key to set
|
|
120
|
+
*/
|
|
121
|
+
set propertyKey(key: string | undefined);
|
|
122
|
+
/**
|
|
123
|
+
* Checks if two routes are equal.
|
|
124
|
+
* @param other - The other route to compare with
|
|
125
|
+
* @returns True if the routes are equal, false otherwise
|
|
126
|
+
*/
|
|
127
|
+
equals(other: Route): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Checks if two routes are equal without considering the property key.
|
|
130
|
+
* @param other - The other route to compare with
|
|
131
|
+
* @returns True if the routes are equal without considering the property key, false otherwise
|
|
132
|
+
*/
|
|
133
|
+
equalsWithoutPropertyKey(other: Route): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Checks if two routes are equal without considering the references.
|
|
136
|
+
* @param other - The other route to compare with
|
|
137
|
+
* @returns True if the routes are equal without considering the references, false otherwise
|
|
138
|
+
*/
|
|
139
|
+
equalsWithoutRefs(other: Route): boolean;
|
|
69
140
|
/**
|
|
70
141
|
* Returns the reference of a segment if it exists.
|
|
71
142
|
* @param segment - The segment to get the reference from
|
|
@@ -73,21 +144,21 @@ export declare class Route {
|
|
|
73
144
|
*/
|
|
74
145
|
static segmentRef(segment: RouteSegment<any>): string | undefined;
|
|
75
146
|
/**
|
|
76
|
-
* Checks if a segment has any reference (either default or
|
|
147
|
+
* Checks if a segment has any reference (either default or insertHistory).
|
|
77
148
|
* @param segment - The segment to check
|
|
78
149
|
* @returns True if the segment has any reference, false otherwise
|
|
79
150
|
*/
|
|
80
151
|
static segmentHasRef(segment: RouteSegment<any>): boolean;
|
|
81
152
|
/**
|
|
82
|
-
* Checks if a segment has a default reference (i.e. not a
|
|
153
|
+
* Checks if a segment has a default reference (i.e. not a insertHistory reference).
|
|
83
154
|
* @param segment - The segment to check
|
|
84
155
|
* @returns True if the segment has a default reference, false otherwise
|
|
85
156
|
*/
|
|
86
157
|
static segmentHasDefaultRef(segment: RouteSegment<any>): boolean;
|
|
87
158
|
/**
|
|
88
|
-
* Checks if a segment has a
|
|
159
|
+
* Checks if a segment has a insertHistory reference (i.e. an InsertHistoryRef).
|
|
89
160
|
* @param segment - The segment to check
|
|
90
|
-
* @returns True if the segment has a
|
|
161
|
+
* @returns True if the segment has a insertHistory reference, false otherwise
|
|
91
162
|
*/
|
|
92
|
-
static
|
|
163
|
+
static segmentHasInsertHistoryRef(segment: RouteSegment<any>): boolean;
|
|
93
164
|
}
|
package/dist/typedefs.d.ts
CHANGED
|
@@ -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", "insertHistory"];
|
|
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.
|
|
3
|
+
"version": "0.0.67",
|
|
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",
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
],
|
|
21
21
|
"type": "module",
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@types/node": "^24.
|
|
24
|
-
"@typescript-eslint/eslint-plugin": "^8.46.
|
|
25
|
-
"@typescript-eslint/parser": "^8.46.
|
|
26
|
-
"@vitest/coverage-v8": "^4.0.
|
|
23
|
+
"@types/node": "^24.10.0",
|
|
24
|
+
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
|
25
|
+
"@typescript-eslint/parser": "^8.46.3",
|
|
26
|
+
"@vitest/coverage-v8": "^4.0.7",
|
|
27
27
|
"cross-env": "^10.1.0",
|
|
28
|
-
"eslint": "^9.
|
|
29
|
-
"eslint-plugin-jsdoc": "^61.1.
|
|
28
|
+
"eslint": "^9.39.1",
|
|
29
|
+
"eslint-plugin-jsdoc": "^61.1.12",
|
|
30
30
|
"eslint-plugin-tsdoc": "^0.4.0",
|
|
31
|
-
"globals": "^16.
|
|
31
|
+
"globals": "^16.5.0",
|
|
32
32
|
"jsdoc": "^4.0.5",
|
|
33
33
|
"read-pkg": "^9.0.1",
|
|
34
34
|
"typescript": "~5.9.3",
|
|
35
|
-
"typescript-eslint": "^8.46.
|
|
36
|
-
"vite": "^7.
|
|
35
|
+
"typescript-eslint": "^8.46.3",
|
|
36
|
+
"vite": "^7.2.0",
|
|
37
37
|
"vite-node": "^3.2.4",
|
|
38
38
|
"vite-plugin-dts": "^4.5.4",
|
|
39
39
|
"vite-tsconfig-paths": "^5.1.4",
|
|
40
|
-
"vitest": "^4.0.
|
|
40
|
+
"vitest": "^4.0.7",
|
|
41
41
|
"vitest-dom": "^0.1.1"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { TableCfg } from '../content/table-cfg.ts';
|
|
2
|
-
import { RljsonTable } from '../rljson.ts';
|
|
3
|
-
import { RouteRef } from '../route/route.ts';
|
|
4
|
-
import { Ref } from '../typedefs.ts';
|
|
5
|
-
export type HistoryTimeId = string;
|
|
6
|
-
export type HistoryRow<Str extends string> = {
|
|
7
|
-
[key in Str as `${Uncapitalize<string & key>}Ref`]: string;
|
|
8
|
-
} & {
|
|
9
|
-
timeId: HistoryTimeId;
|
|
10
|
-
route: RouteRef;
|
|
11
|
-
origin?: Ref;
|
|
12
|
-
previous?: HistoryTimeId[];
|
|
13
|
-
};
|
|
14
|
-
export type History<Str extends string> = RljsonTable<HistoryRow<Str>, 'history'>;
|
|
15
|
-
/**
|
|
16
|
-
* Creates a TableCfg for a History table for the given table configuration
|
|
17
|
-
* @param tableCfg - The table configuration to create the History table for
|
|
18
|
-
* @returns The TableCfg for the History table
|
|
19
|
-
*/
|
|
20
|
-
export declare const createHistoryTableCfg: (tableCfg: TableCfg) => TableCfg;
|
|
21
|
-
/**
|
|
22
|
-
* Provides an example history table for test purposes
|
|
23
|
-
*/
|
|
24
|
-
export declare const exampleHistoryTable: () => History<any>;
|