@vireocodedev/history 0.2.0 → 0.2.1

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,3 @@
1
+ import { HistoryDefinition, HistoryDefinitionFields, HistoryDefinitionOptions, HistoryObjectForSchema } from './historyDefinition.types';
2
+ import { z } from 'zod';
3
+ export declare function createHistoryDefinition<TSchema extends z.ZodTypeAny>(schema: TSchema, options: HistoryDefinitionOptions<HistoryObjectForSchema<TSchema>>, fields: HistoryDefinitionFields<HistoryObjectForSchema<TSchema>>): HistoryDefinition<HistoryObjectForSchema<TSchema>, TSchema>;
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ export type HistoryEntityKey = string | number;
3
+ export type HistoryPathSegment = string | number;
4
+ export type HistoryPath = readonly HistoryPathSegment[];
5
+ export type HistoryChangeType = "added" | "removed" | "updated";
6
+ export type HistoryArrayMode = "set" | "ordered";
7
+ export type HistoryValueSide = "previous" | "current";
8
+ export type HistoryFormatContext<TParent> = {
9
+ parent: NonNullable<TParent>;
10
+ side: HistoryValueSide;
11
+ path: HistoryPath;
12
+ };
13
+ export type HistoryDefinitionOptions<TEntity extends object> = {
14
+ label: string;
15
+ key: (value: TEntity) => HistoryEntityKey;
16
+ format?: (value: TEntity, context: HistoryFormatContext<TEntity>) => string;
17
+ };
18
+ export type HistoryFieldConfig<TValue, TParent> = false | HistoryAtomicFieldConfig<TValue, TParent> | HistoryArrayFieldConfig<TValue, TParent> | HistoryObjectFieldConfig<TValue>;
19
+ export type HistoryAtomicFieldConfig<TValue, TParent> = {
20
+ kind: "field";
21
+ label: string;
22
+ format?: (value: NonNullable<TValue>, context: HistoryFormatContext<TParent>) => string;
23
+ resolveChange?: (previous: TValue, current: TValue) => HistoryChangeType | null;
24
+ };
25
+ export type HistoryArrayFieldConfig<TValue, TParent> = NonNullable<TValue> extends readonly (infer TItem)[] ? {
26
+ kind: "array";
27
+ label: string;
28
+ /** @default "set" */
29
+ mode?: HistoryArrayMode;
30
+ format?: (value: NonNullable<TValue>, context: HistoryFormatContext<TParent>) => string;
31
+ item: HistoryArrayItemConfig<TItem>;
32
+ } : never;
33
+ export type HistoryArrayItemConfig<TItem> = HistoryAtomicFieldConfig<TItem, TItem> | HistoryArrayFieldConfig<TItem, TItem> | HistoryObjectFieldConfig<TItem>;
34
+ export type HistoryObjectFieldConfig<TValue> = NonNullable<TValue> extends object ? NonNullable<TValue> extends readonly unknown[] ? never : {
35
+ kind: "object";
36
+ definition: HistoryDefinition<NonNullable<TValue>>;
37
+ } : never;
38
+ export type HistoryDefinitionFields<TEntity extends object> = {
39
+ [TKey in keyof TEntity]-?: HistoryFieldConfig<TEntity[TKey], TEntity>;
40
+ };
41
+ export type HistoryDefinition<TEntity extends object, TSchema extends z.ZodTypeAny = z.ZodTypeAny> = {
42
+ schema: TSchema;
43
+ options: HistoryDefinitionOptions<TEntity>;
44
+ fields: HistoryDefinitionFields<TEntity>;
45
+ };
46
+ export type HistoryEntityForDefinition<TDefinition> = TDefinition extends HistoryDefinition<infer TEntity, z.ZodTypeAny> ? TEntity : never;
47
+ export type HistoryObjectForSchema<TSchema extends z.ZodTypeAny> = NonNullable<z.infer<TSchema>> extends object ? NonNullable<z.infer<TSchema>> extends readonly unknown[] ? never : NonNullable<z.infer<TSchema>> : never;
@@ -0,0 +1,4 @@
1
+ import { HistoryDefinition } from '../definitions/historyDefinition.types';
2
+ import { HistoryEngineOptions, HistoryNode } from './historyNode.types';
3
+ import { z } from 'zod';
4
+ export declare function createHistoryNodes<TEntity extends object, TSchema extends z.ZodTypeAny>(definition: HistoryDefinition<TEntity, TSchema>, previous: NoInfer<TEntity> | null | undefined, current: NoInfer<TEntity> | null | undefined, options?: HistoryEngineOptions): HistoryNode[];
@@ -0,0 +1,47 @@
1
+ import { HistoryPath } from '../definitions/historyDefinition.types';
2
+ export type HistoryValue = {
3
+ raw: unknown;
4
+ formatted: string;
5
+ };
6
+ export type HistoryFieldRow = {
7
+ type: "removed";
8
+ path: HistoryPath;
9
+ label: string;
10
+ previous: HistoryValue;
11
+ } | {
12
+ type: "updated";
13
+ path: HistoryPath;
14
+ label: string;
15
+ previous: HistoryValue;
16
+ current: HistoryValue;
17
+ } | {
18
+ type: "added";
19
+ path: HistoryPath;
20
+ label: string;
21
+ current: HistoryValue;
22
+ } | {
23
+ type: "moved";
24
+ path: HistoryPath;
25
+ label: string;
26
+ previous: HistoryValue;
27
+ current: HistoryValue;
28
+ } | {
29
+ type: "unchanged";
30
+ path: HistoryPath;
31
+ label: string;
32
+ current: HistoryValue;
33
+ };
34
+ export type HistoryGroupChangeType = "added" | "updated" | "removed" | "unchanged";
35
+ export type HistoryGroupNode = {
36
+ type: "group";
37
+ path: HistoryPath;
38
+ label: string;
39
+ value?: HistoryValue;
40
+ changeType: HistoryGroupChangeType;
41
+ children: HistoryNode[];
42
+ };
43
+ export type HistoryNode = HistoryFieldRow | HistoryGroupNode;
44
+ export type HistoryEngineOptions = {
45
+ positionLabel?: string;
46
+ showUnchanged?: boolean;
47
+ };
@@ -0,0 +1,7 @@
1
+ import { HistoryFormatContext } from '../definitions/historyDefinition.types';
2
+ import { HistoryValue } from './historyNode.types';
3
+ export declare function isHistoryValuePresent(value: unknown): boolean;
4
+ export declare function formatHistoryValue<TParent>(raw: unknown, format: ((value: never, context: HistoryFormatContext<TParent>) => string) | undefined, context: HistoryFormatContext<TParent>): HistoryValue;
5
+ export declare function formatDefaultHistoryValue(value: unknown): string;
6
+ export declare function areHistoryValuesEqual(previous: unknown, current: unknown): boolean;
7
+ export declare function stableStringify(value: unknown): string;
@@ -0,0 +1,6 @@
1
+ export { createHistoryDefinition } from './definitions/createHistoryDefinition';
2
+ export type { HistoryArrayFieldConfig, HistoryArrayItemConfig, HistoryArrayMode, HistoryAtomicFieldConfig, HistoryChangeType, HistoryDefinition, HistoryDefinitionFields, HistoryDefinitionOptions, HistoryEntityForDefinition, HistoryEntityKey, HistoryFieldConfig, HistoryFormatContext, HistoryObjectFieldConfig, HistoryPath, HistoryPathSegment, HistoryValueSide, } from './definitions/historyDefinition.types';
3
+ export { createHistoryNodes } from './diff/createHistoryNodes';
4
+ export type { HistoryEngineOptions, HistoryFieldRow, HistoryGroupChangeType, HistoryGroupNode, HistoryNode, HistoryValue, } from './diff/historyNode.types';
5
+ export { createHistoryRecordSchema, HistoryActorSchema, HistoryRecordSchema, HistorySnapshotSchema, HistoryTimestampSchema, } from './records/historyRecord';
6
+ export type { HistoryActor, HistoryEntityKind, HistoryRecord, HistoryRecordSchemaOptions, HistorySnapshot, HistoryTimestamp, } from './records/historyRecord';
package/dist/index.js ADDED
@@ -0,0 +1,549 @@
1
+ import { z as e } from "zod";
2
+ //#region src/definitions/createHistoryDefinition.ts
3
+ function t(e, t, i) {
4
+ if (r(e), a(t?.label, "History definition label"), typeof t?.key != "function") throw TypeError("History definition key must be a function.");
5
+ if (o(t.format, "History definition format"), typeof i != "object" || !i || Array.isArray(i)) throw TypeError("History definition fields must be an object.");
6
+ return Object.entries(i).forEach(([e, t]) => n(t, `fields.${e}`)), {
7
+ schema: e,
8
+ options: t,
9
+ fields: i
10
+ };
11
+ }
12
+ function n(e, t) {
13
+ if (e === !1) return;
14
+ if (typeof e != "object" || !e || Array.isArray(e)) throw TypeError(`History ${t} must be false or a field configuration object.`);
15
+ let r = e;
16
+ switch (r.kind) {
17
+ case "field":
18
+ a(r.label, `History ${t} label`), o(r.format, `History ${t} format`), o(r.resolveChange, `History ${t} resolveChange`);
19
+ return;
20
+ case "array":
21
+ if (a(r.label, `History ${t} label`), o(r.format, `History ${t} format`), r.mode !== void 0 && r.mode !== "set" && r.mode !== "ordered") throw TypeError(`History ${t} mode must be "set" or "ordered".`);
22
+ if (n(r.item, `${t}.item`), r.item === !1) throw TypeError(`History ${t}.item cannot be ignored.`);
23
+ return;
24
+ case "object":
25
+ i(r.definition, `History ${t} definition`);
26
+ return;
27
+ default: throw TypeError(`History ${t} has unsupported kind "${String(r.kind)}".`);
28
+ }
29
+ }
30
+ function r(e) {
31
+ if (typeof e != "object" || !e || typeof e.parse != "function") throw TypeError("History definition schema must be a Zod schema.");
32
+ }
33
+ function i(e, t) {
34
+ if (typeof e != "object" || !e) throw TypeError(`${t} must be a history definition.`);
35
+ let n = e;
36
+ if (r(n.schema), n.options == null || typeof n.options != "object") throw TypeError(`${t} must include definition options.`);
37
+ if (a(n.options.label, `${t} label`), typeof n.options.key != "function") throw TypeError(`${t} key must be a function.`);
38
+ if (n.fields == null || typeof n.fields != "object" || Array.isArray(n.fields)) throw TypeError(`${t} fields must be an object.`);
39
+ }
40
+ function a(e, t) {
41
+ if (typeof e != "string" || e.trim().length === 0) throw TypeError(`${t} must be a non-empty string.`);
42
+ }
43
+ function o(e, t) {
44
+ if (e !== void 0 && typeof e != "function") throw TypeError(`${t} must be a function.`);
45
+ }
46
+ //#endregion
47
+ //#region src/diff/historyValue.ts
48
+ function s(e) {
49
+ return e != null;
50
+ }
51
+ function c(e, t, n) {
52
+ let r = t == null ? l(e) : t(e, n);
53
+ if (typeof r != "string") throw TypeError(`History formatter at "${n.path.join(".") || "$root"}" must return a string.`);
54
+ return {
55
+ raw: e,
56
+ formatted: r
57
+ };
58
+ }
59
+ function l(e) {
60
+ return typeof e == "string" ? e : typeof e == "number" || typeof e == "boolean" || typeof e == "bigint" ? String(e) : e instanceof Date ? e.toISOString() : p(e);
61
+ }
62
+ function u(e, t) {
63
+ return Object.is(e, t) ? !0 : typeof e != typeof t || e == null || t == null || typeof e != "object" ? !1 : d(e) === d(t);
64
+ }
65
+ function d(e) {
66
+ return JSON.stringify(f(e, /* @__PURE__ */ new Set()));
67
+ }
68
+ function f(e, t) {
69
+ if (e === null) return ["null"];
70
+ if (e === void 0) return ["undefined"];
71
+ switch (typeof e) {
72
+ case "string": return ["string", e];
73
+ case "boolean": return ["boolean", e];
74
+ case "bigint": return ["bigint", e.toString()];
75
+ case "number": return ["number", ee(e)];
76
+ case "symbol":
77
+ case "function": throw TypeError(`History values do not support ${typeof e} values.`);
78
+ case "object": break;
79
+ default: return ["unknown", String(e)];
80
+ }
81
+ if (e instanceof Date) {
82
+ if (Number.isNaN(e.getTime())) throw TypeError("History values do not support invalid Date values.");
83
+ return ["date", e.toISOString()];
84
+ }
85
+ if (h(e), t.has(e)) throw TypeError("History values must not contain cyclic references.");
86
+ t.add(e);
87
+ try {
88
+ return Array.isArray(e) ? ["array", e.map((e) => f(e, t))] : ["object", Object.entries(e).sort(([e], [t]) => g(e, t)).map(([e, n]) => [e, f(n, t)])];
89
+ } finally {
90
+ t.delete(e);
91
+ }
92
+ }
93
+ function p(e) {
94
+ return JSON.stringify(m(e, /* @__PURE__ */ new Set()));
95
+ }
96
+ function m(e, t) {
97
+ if (e == null || typeof e == "string" || typeof e == "boolean") return e;
98
+ if (typeof e == "number") return Number.isFinite(e) ? e : String(e);
99
+ if (typeof e == "bigint") return e.toString();
100
+ if (typeof e == "symbol" || typeof e == "function") throw TypeError(`History values do not support ${typeof e} values.`);
101
+ if (e instanceof Date) {
102
+ if (Number.isNaN(e.getTime())) throw TypeError("History values do not support invalid Date values.");
103
+ return e.toISOString();
104
+ }
105
+ if (h(e), t.has(e)) throw TypeError("History values must not contain cyclic references.");
106
+ t.add(e);
107
+ try {
108
+ return Array.isArray(e) ? e.map((e) => m(e, t)) : Object.fromEntries(Object.entries(e).sort(([e], [t]) => g(e, t)).map(([e, n]) => [e, m(n, t)]));
109
+ } finally {
110
+ t.delete(e);
111
+ }
112
+ }
113
+ function ee(e) {
114
+ return Number.isNaN(e) ? "NaN" : e === Infinity ? "Infinity" : e === -Infinity ? "-Infinity" : Object.is(e, -0) ? "-0" : e;
115
+ }
116
+ function h(e) {
117
+ if (Array.isArray(e)) return;
118
+ let t = Object.getPrototypeOf(e);
119
+ if (t === Object.prototype || t === null) return;
120
+ let n = e.constructor?.name ?? "unknown";
121
+ throw TypeError(`History values do not support object type "${n}".`);
122
+ }
123
+ function g(e, t) {
124
+ return e < t ? -1 : +(e > t);
125
+ }
126
+ //#endregion
127
+ //#region src/diff/createHistoryNodes.ts
128
+ var _ = "Position";
129
+ function v(e, t, n, r = {}) {
130
+ let i = y(e, b(e, t), b(e, n), [], r);
131
+ return i == null ? [] : [i];
132
+ }
133
+ function y(e, t, n, r, i = {}, a) {
134
+ let o = x(e, t, n, r, i);
135
+ return o.length === 0 && a == null ? null : {
136
+ type: "group",
137
+ path: r,
138
+ label: e.options.label,
139
+ value: J(e, s(n) ? n : t, r, s(n) ? "current" : "previous"),
140
+ changeType: a ?? z(o),
141
+ children: o
142
+ };
143
+ }
144
+ function b(e, t) {
145
+ if (s(t)) return e.schema.parse(t);
146
+ }
147
+ function x(e, t, n, r, i) {
148
+ let a = [], o = [];
149
+ for (let s of Object.keys(e.fields)) {
150
+ let c = e.fields[s];
151
+ if (c === !1) continue;
152
+ let l = [...r, s], u = S({
153
+ config: c,
154
+ previous: G(t, s),
155
+ current: G(n, s),
156
+ previousParent: t,
157
+ currentParent: n,
158
+ path: l,
159
+ options: i
160
+ });
161
+ if (c.kind === "field") {
162
+ a.push(...u);
163
+ continue;
164
+ }
165
+ o.push(...u);
166
+ }
167
+ return [...R(a), ...R(o)];
168
+ }
169
+ function S(e) {
170
+ let { config: t } = e;
171
+ switch (t.kind) {
172
+ case "field": {
173
+ let n = te({
174
+ ...e,
175
+ config: t
176
+ });
177
+ return n == null ? [] : [n];
178
+ }
179
+ case "array": return D({
180
+ ...e,
181
+ config: t
182
+ });
183
+ case "object": return T({
184
+ ...e,
185
+ config: t
186
+ });
187
+ default: return [];
188
+ }
189
+ }
190
+ function te(e) {
191
+ let { config: t, previous: n, current: r, previousParent: i, currentParent: a, path: o, options: s } = e, c = t.resolveChange == null ? W(n, r) : C(t.resolveChange(n, r), o);
192
+ return c == null ? w({
193
+ config: t,
194
+ previous: n,
195
+ current: r,
196
+ previousParent: i,
197
+ currentParent: a,
198
+ path: o,
199
+ options: s
200
+ }) : c === "removed" ? {
201
+ type: "removed",
202
+ path: o,
203
+ label: t.label,
204
+ previous: K({
205
+ config: t,
206
+ value: n,
207
+ parent: i,
208
+ side: "previous",
209
+ path: o,
210
+ options: s
211
+ })
212
+ } : c === "added" ? {
213
+ type: "added",
214
+ path: o,
215
+ label: t.label,
216
+ current: K({
217
+ config: t,
218
+ value: r,
219
+ parent: a,
220
+ side: "current",
221
+ path: o,
222
+ options: s
223
+ })
224
+ } : {
225
+ type: "updated",
226
+ path: o,
227
+ label: t.label,
228
+ previous: K({
229
+ config: t,
230
+ value: n,
231
+ parent: i,
232
+ side: "previous",
233
+ path: o,
234
+ options: s
235
+ }),
236
+ current: K({
237
+ config: t,
238
+ value: r,
239
+ parent: a,
240
+ side: "current",
241
+ path: o,
242
+ options: s
243
+ })
244
+ };
245
+ }
246
+ function C(e, t) {
247
+ if (e === null || e === "added" || e === "removed" || e === "updated") return e;
248
+ throw TypeError(`History change resolver at "${t.join(".")}" returned unsupported type "${String(e)}".`);
249
+ }
250
+ function w(e) {
251
+ let { config: t, previous: n, current: r, previousParent: i, currentParent: a, path: o, options: c } = e;
252
+ if (c.showUnchanged !== !0) return null;
253
+ let l = s(r) ? r : n;
254
+ if (!s(l)) return null;
255
+ let u = s(r) ? a : i, d = s(r) ? "current" : "previous";
256
+ return {
257
+ type: "unchanged",
258
+ path: o,
259
+ label: t.label,
260
+ current: K({
261
+ config: t,
262
+ value: l,
263
+ parent: u,
264
+ side: d,
265
+ path: o,
266
+ options: c
267
+ })
268
+ };
269
+ }
270
+ function T(e) {
271
+ let { config: t, previous: n, current: r, path: i, options: a } = e, o = y(t.definition, n, r, i, a, E(n, r));
272
+ return o == null ? [] : [o];
273
+ }
274
+ function E(e, t) {
275
+ let n = !s(e), r = !s(t);
276
+ if (n && !r) return "added";
277
+ if (!n && r) return "removed";
278
+ }
279
+ function D(e) {
280
+ let { config: t, previous: n, current: r, previousParent: i, currentParent: a, path: o, options: c } = e, l = Array.isArray(n) ? n : [], u = Array.isArray(r) ? r : [], d = t.mode ?? "set", f = E(n, r), p = d === "ordered" ? k(t, l, u, o, c) : O(t, l, u, o, c);
281
+ return p.length === 0 && f == null ? [] : [{
282
+ type: "group",
283
+ path: o,
284
+ label: t.label,
285
+ value: q(t, s(r) ? u : l, s(r) ? a : i, o, s(r) ? "current" : "previous"),
286
+ changeType: f ?? z(p),
287
+ children: p
288
+ }];
289
+ }
290
+ function O(e, t, n, r, i) {
291
+ let a = I(e, t, r, "previous"), o = I(e, n, r, "current"), s = [], c = [], l = [];
292
+ for (let [t, n] of o) {
293
+ let o = a.get(t), l = [...r, t];
294
+ if (o == null) {
295
+ s.push(...N(e, n.value, l, i));
296
+ continue;
297
+ }
298
+ c.push(...M({
299
+ config: e,
300
+ previous: o.value,
301
+ current: n.value,
302
+ path: l,
303
+ movedRow: null,
304
+ options: i
305
+ }));
306
+ }
307
+ for (let [t, n] of a) o.has(t) || l.push(...P(e, n.value, [...r, t], i));
308
+ return R([
309
+ ...s,
310
+ ...c,
311
+ ...l
312
+ ]);
313
+ }
314
+ function k(e, t, n, r, i) {
315
+ let a = I(e, t, r, "previous"), o = I(e, n, r, "current"), s = new Set(A([...a.keys()].filter((e) => o.has(e)), [...o.keys()].filter((e) => a.has(e)))), c = [], l = [], u = [];
316
+ for (let [t, n] of o) {
317
+ let o = a.get(t), u = [...r, t];
318
+ if (o == null) {
319
+ c.push(...N(e, n.value, u, i));
320
+ continue;
321
+ }
322
+ let d = s.has(t) ? null : ne(u, o.index, n.index, i);
323
+ l.push(...M({
324
+ config: e,
325
+ previous: o.value,
326
+ current: n.value,
327
+ path: u,
328
+ movedRow: d,
329
+ options: i
330
+ }));
331
+ }
332
+ for (let [t, n] of a) o.has(t) || u.push(...P(e, n.value, [...r, t], i));
333
+ return [
334
+ ...R(c),
335
+ ...R(l),
336
+ ...R(u)
337
+ ];
338
+ }
339
+ function A(e, t) {
340
+ let n = Array.from({ length: e.length + 1 }, () => Array(t.length + 1).fill(0));
341
+ for (let r = e.length - 1; r >= 0; --r) for (let i = t.length - 1; i >= 0; --i) n[r][i] = j(e[r], t[i]) ? 1 + n[r + 1][i + 1] : Math.max(n[r + 1][i], n[r][i + 1]);
342
+ let r = [], i = 0, a = 0;
343
+ for (; i < e.length && a < t.length;) {
344
+ let o = e[i], s = t[a];
345
+ if (j(o, s)) {
346
+ r.push(o), i += 1, a += 1;
347
+ continue;
348
+ }
349
+ n[i + 1][a] > n[i][a + 1] ? i += 1 : a += 1;
350
+ }
351
+ return r;
352
+ }
353
+ function j(e, t) {
354
+ return e === t || typeof e == "number" && typeof t == "number" && Number.isNaN(e) && Number.isNaN(t);
355
+ }
356
+ function M(e) {
357
+ let { config: t, previous: n, current: r, path: i, movedRow: a, options: o } = e, s = t.item;
358
+ if (s.kind === "object") {
359
+ let e = y(s.definition, n, r, i, o);
360
+ return e == null ? a == null ? [] : [F(s, r, i, a)] : [{
361
+ ...e,
362
+ children: a == null ? e.children : [a, ...e.children]
363
+ }];
364
+ }
365
+ let c = S({
366
+ config: s,
367
+ previous: n,
368
+ current: r,
369
+ previousParent: n,
370
+ currentParent: r,
371
+ path: i,
372
+ options: o
373
+ });
374
+ return a == null ? c : [a, ...c];
375
+ }
376
+ function N(e, t, n, r) {
377
+ let i = e.item;
378
+ if (i.kind === "object") {
379
+ let e = y(i.definition, void 0, t, n, r, "added");
380
+ return e == null ? [{
381
+ type: "added",
382
+ path: n,
383
+ label: i.definition.options.label,
384
+ current: J(i.definition, t, n, "current")
385
+ }] : [e];
386
+ }
387
+ return S({
388
+ config: i,
389
+ previous: void 0,
390
+ current: t,
391
+ previousParent: void 0,
392
+ currentParent: t,
393
+ path: n,
394
+ options: r
395
+ });
396
+ }
397
+ function P(e, t, n, r) {
398
+ let i = e.item;
399
+ if (i.kind === "object") {
400
+ let e = y(i.definition, t, void 0, n, r, "removed");
401
+ return e == null ? [{
402
+ type: "removed",
403
+ path: n,
404
+ label: i.definition.options.label,
405
+ previous: J(i.definition, t, n, "previous")
406
+ }] : [e];
407
+ }
408
+ return S({
409
+ config: i,
410
+ previous: t,
411
+ current: void 0,
412
+ previousParent: t,
413
+ currentParent: void 0,
414
+ path: n,
415
+ options: r
416
+ });
417
+ }
418
+ function F(e, t, n, r) {
419
+ return {
420
+ type: "group",
421
+ path: n,
422
+ label: e.definition.options.label,
423
+ value: J(e.definition, t, n, "current"),
424
+ changeType: "updated",
425
+ children: [r]
426
+ };
427
+ }
428
+ function ne(e, t, n, r) {
429
+ return {
430
+ type: "moved",
431
+ path: [...e, "$position"],
432
+ label: r.positionLabel ?? _,
433
+ previous: Y(t, String(t + 1)),
434
+ current: Y(n, String(n + 1))
435
+ };
436
+ }
437
+ function I(e, t, n, r) {
438
+ let i = /* @__PURE__ */ new Map();
439
+ return t.forEach((t, a) => {
440
+ let o = L(e, t);
441
+ if (typeof o != "string" && typeof o != "number" || typeof o == "number" && !Number.isFinite(o)) throw TypeError(`History array identity in the ${r} snapshot at "${n.join(".")}" must be a string or finite number.`);
442
+ if (i.has(o)) throw Error(`Duplicate history array identity "${String(o)}" in the ${r} snapshot at "${n.join(".")}".`);
443
+ i.set(o, {
444
+ value: t,
445
+ index: a
446
+ });
447
+ }), i;
448
+ }
449
+ function L(e, t) {
450
+ let n = e.item;
451
+ return n.kind === "object" ? n.definition.options.key(t) : typeof t == "string" || typeof t == "number" ? t : d(t);
452
+ }
453
+ function R(e) {
454
+ return [...e].sort((e, t) => V(e) - V(t));
455
+ }
456
+ function z(e) {
457
+ return e.some((e) => B(e) !== "unchanged") ? "updated" : "unchanged";
458
+ }
459
+ function B(e) {
460
+ if (e.type === "group") return e.changeType ?? z(e.children);
461
+ switch (e.type) {
462
+ case "added": return "added";
463
+ case "removed": return "removed";
464
+ case "updated":
465
+ case "moved": return "updated";
466
+ case "unchanged": return "unchanged";
467
+ default: return "updated";
468
+ }
469
+ }
470
+ function V(e) {
471
+ return e.type === "group" && e.changeType != null ? H(e.changeType) : e.type === "group" ? e.children.length === 0 ? 1 : Math.min(...e.children.map(V)) : U(e);
472
+ }
473
+ function H(e) {
474
+ switch (e) {
475
+ case "added": return 0;
476
+ case "updated": return 1;
477
+ case "removed": return 2;
478
+ case "unchanged": return 3;
479
+ default: return 1;
480
+ }
481
+ }
482
+ function U(e) {
483
+ switch (e.type) {
484
+ case "added": return 0;
485
+ case "updated":
486
+ case "moved": return 1;
487
+ case "removed": return 2;
488
+ case "unchanged": return 3;
489
+ default: return 1;
490
+ }
491
+ }
492
+ function W(e, t) {
493
+ let n = !s(e), r = !s(t);
494
+ return n && r ? null : n && !r ? "added" : !n && r ? "removed" : u(e, t) ? null : "updated";
495
+ }
496
+ function G(e, t) {
497
+ if (!(typeof e != "object" || !e)) return e[t];
498
+ }
499
+ function K(e) {
500
+ let { config: t, value: n, parent: r, side: i, path: a } = e;
501
+ return c(n, t.format, {
502
+ parent: r,
503
+ side: i,
504
+ path: a
505
+ });
506
+ }
507
+ function q(e, t, n, r, i) {
508
+ if (e.format != null) return c(t, e.format, {
509
+ parent: n,
510
+ side: i,
511
+ path: r
512
+ });
513
+ }
514
+ function J(e, t, n, r) {
515
+ return e.options.format == null ? Y(t, e.options.label) : c(t, e.options.format, {
516
+ parent: t,
517
+ side: r,
518
+ path: n
519
+ });
520
+ }
521
+ function Y(e, t) {
522
+ return {
523
+ raw: e,
524
+ formatted: t
525
+ };
526
+ }
527
+ //#endregion
528
+ //#region src/records/historyRecord.ts
529
+ var X = e.record(e.string(), e.unknown()), Z = e.union([e.number().finite(), e.string().datetime({ offset: !0 })]), Q = e.object({
530
+ id: e.string().min(1).nullable().optional(),
531
+ label: e.string().min(1).refine((e) => e.trim().length > 0, "History actor label cannot be blank.")
532
+ });
533
+ function $(t = {}) {
534
+ let n = t.entityKind ?? e.string().min(1), r = t.snapshot ?? X, i = t.timestamp ?? Z;
535
+ return e.object({
536
+ id: e.string().min(1),
537
+ timestamp: i,
538
+ actor: Q.nullable(),
539
+ entity: n,
540
+ entityId: e.string().min(1),
541
+ snapshotPrevious: r.nullable(),
542
+ snapshotCurrent: r.nullable()
543
+ });
544
+ }
545
+ var re = $();
546
+ //#endregion
547
+ export { Q as HistoryActorSchema, re as HistoryRecordSchema, X as HistorySnapshotSchema, Z as HistoryTimestampSchema, t as createHistoryDefinition, v as createHistoryNodes, $ as createHistoryRecordSchema };
548
+
549
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/definitions/createHistoryDefinition.ts","../src/diff/historyValue.ts","../src/diff/createHistoryNodes.ts","../src/records/historyRecord.ts"],"sourcesContent":["import type {\n HistoryDefinition,\n HistoryDefinitionFields,\n HistoryDefinitionOptions,\n HistoryObjectForSchema,\n} from \"./historyDefinition.types\";\nimport type { z } from \"zod\";\n\nexport function createHistoryDefinition<TSchema extends z.ZodTypeAny>(\n schema: TSchema,\n options: HistoryDefinitionOptions<HistoryObjectForSchema<TSchema>>,\n fields: HistoryDefinitionFields<HistoryObjectForSchema<TSchema>>,\n): HistoryDefinition<HistoryObjectForSchema<TSchema>, TSchema> {\n assertDefinitionSchema(schema);\n assertNonEmptyLabel(options?.label, \"History definition label\");\n if (typeof options?.key !== \"function\") throw new TypeError(\"History definition key must be a function.\");\n assertOptionalFunction(options.format, \"History definition format\");\n if (fields == null || typeof fields !== \"object\" || Array.isArray(fields)) {\n throw new TypeError(\"History definition fields must be an object.\");\n }\n\n Object.entries(fields).forEach(([fieldName, config]) => validateFieldConfig(config, `fields.${fieldName}`));\n\n return { schema, options, fields };\n}\n\nfunction validateFieldConfig(config: unknown, location: string): void {\n if (config === false) return;\n if (config == null || typeof config !== \"object\" || Array.isArray(config)) {\n throw new TypeError(`History ${location} must be false or a field configuration object.`);\n }\n\n const record = config as Record<string, unknown>;\n switch (record.kind) {\n case \"field\":\n assertNonEmptyLabel(record.label, `History ${location} label`);\n assertOptionalFunction(record.format, `History ${location} format`);\n assertOptionalFunction(record.resolveChange, `History ${location} resolveChange`);\n return;\n case \"array\":\n assertNonEmptyLabel(record.label, `History ${location} label`);\n assertOptionalFunction(record.format, `History ${location} format`);\n if (record.mode !== undefined && record.mode !== \"set\" && record.mode !== \"ordered\") {\n throw new TypeError(`History ${location} mode must be \"set\" or \"ordered\".`);\n }\n validateFieldConfig(record.item, `${location}.item`);\n if (record.item === false) throw new TypeError(`History ${location}.item cannot be ignored.`);\n return;\n case \"object\":\n assertHistoryDefinition(record.definition, `History ${location} definition`);\n return;\n default:\n throw new TypeError(`History ${location} has unsupported kind \"${String(record.kind)}\".`);\n }\n}\n\nfunction assertDefinitionSchema(schema: unknown): void {\n if (schema == null || typeof schema !== \"object\" || typeof (schema as { parse?: unknown }).parse !== \"function\") {\n throw new TypeError(\"History definition schema must be a Zod schema.\");\n }\n}\n\nfunction assertHistoryDefinition(value: unknown, location: string): void {\n if (value == null || typeof value !== \"object\") throw new TypeError(`${location} must be a history definition.`);\n const definition = value as Record<string, unknown>;\n assertDefinitionSchema(definition.schema);\n if (definition.options == null || typeof definition.options !== \"object\") {\n throw new TypeError(`${location} must include definition options.`);\n }\n assertNonEmptyLabel((definition.options as Record<string, unknown>).label, `${location} label`);\n if (typeof (definition.options as Record<string, unknown>).key !== \"function\") {\n throw new TypeError(`${location} key must be a function.`);\n }\n if (definition.fields == null || typeof definition.fields !== \"object\" || Array.isArray(definition.fields)) {\n throw new TypeError(`${location} fields must be an object.`);\n }\n}\n\nfunction assertNonEmptyLabel(value: unknown, location: string): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0)\n throw new TypeError(`${location} must be a non-empty string.`);\n}\n\nfunction assertOptionalFunction(value: unknown, location: string): void {\n if (value !== undefined && typeof value !== \"function\") throw new TypeError(`${location} must be a function.`);\n}\n","import type { HistoryFormatContext } from \"../definitions/historyDefinition.types\";\nimport type { HistoryValue } from \"./historyNode.types\";\n\nexport function isHistoryValuePresent(value: unknown): boolean {\n return value !== null && value !== undefined;\n}\n\nexport function formatHistoryValue<TParent>(\n raw: unknown,\n format: ((value: never, context: HistoryFormatContext<TParent>) => string) | undefined,\n context: HistoryFormatContext<TParent>,\n): HistoryValue {\n const formatted = format == null ? formatDefaultHistoryValue(raw) : format(raw as never, context);\n\n if (typeof formatted !== \"string\") {\n throw new TypeError(`History formatter at \"${context.path.join(\".\") || \"$root\"}\" must return a string.`);\n }\n\n return { raw, formatted };\n}\n\nexport function formatDefaultHistoryValue(value: unknown): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") return String(value);\n if (value instanceof Date) return value.toISOString();\n\n return stringifyHistoryValueForDisplay(value);\n}\n\nexport function areHistoryValuesEqual(previous: unknown, current: unknown): boolean {\n if (Object.is(previous, current)) return true;\n if (typeof previous !== typeof current || previous == null || current == null) return false;\n if (typeof previous !== \"object\") return false;\n\n return stableStringify(previous) === stableStringify(current);\n}\n\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(createCanonicalHistoryValue(value, new Set<object>()));\n}\n\ntype CanonicalHistoryValue = readonly [type: string, value?: unknown];\n\nfunction createCanonicalHistoryValue(value: unknown, ancestors: Set<object>): CanonicalHistoryValue {\n if (value === null) return [\"null\"];\n if (value === undefined) return [\"undefined\"];\n\n switch (typeof value) {\n case \"string\":\n return [\"string\", value];\n case \"boolean\":\n return [\"boolean\", value];\n case \"bigint\":\n return [\"bigint\", value.toString()];\n case \"number\":\n return [\"number\", serializeNumber(value)];\n case \"symbol\":\n case \"function\":\n throw new TypeError(`History values do not support ${typeof value} values.`);\n case \"object\":\n break;\n default:\n return [\"unknown\", String(value)];\n }\n\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) throw new TypeError(\"History values do not support invalid Date values.\");\n return [\"date\", value.toISOString()];\n }\n\n assertSupportedObject(value);\n if (ancestors.has(value)) throw new TypeError(\"History values must not contain cyclic references.\");\n\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n return [\"array\", value.map(entry => createCanonicalHistoryValue(entry, ancestors))];\n }\n\n return [\n \"object\",\n Object.entries(value as Record<string, unknown>)\n .sort(([leftKey], [rightKey]) => compareKeys(leftKey, rightKey))\n .map(([key, entryValue]) => [key, createCanonicalHistoryValue(entryValue, ancestors)]),\n ];\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction stringifyHistoryValueForDisplay(value: unknown): string {\n return JSON.stringify(createDisplayHistoryValue(value, new Set<object>()));\n}\n\nfunction createDisplayHistoryValue(value: unknown, ancestors: Set<object>): unknown {\n if (value == null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\") return Number.isFinite(value) ? value : String(value);\n if (typeof value === \"bigint\") return value.toString();\n if (typeof value === \"symbol\" || typeof value === \"function\") {\n throw new TypeError(`History values do not support ${typeof value} values.`);\n }\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) throw new TypeError(\"History values do not support invalid Date values.\");\n return value.toISOString();\n }\n\n assertSupportedObject(value);\n if (ancestors.has(value)) throw new TypeError(\"History values must not contain cyclic references.\");\n\n ancestors.add(value);\n try {\n if (Array.isArray(value)) return value.map(entry => createDisplayHistoryValue(entry, ancestors));\n\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([leftKey], [rightKey]) => compareKeys(leftKey, rightKey))\n .map(([key, entryValue]) => [key, createDisplayHistoryValue(entryValue, ancestors)]),\n );\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction serializeNumber(value: number): number | string {\n if (Number.isNaN(value)) return \"NaN\";\n if (value === Number.POSITIVE_INFINITY) return \"Infinity\";\n if (value === Number.NEGATIVE_INFINITY) return \"-Infinity\";\n if (Object.is(value, -0)) return \"-0\";\n return value;\n}\n\nfunction assertSupportedObject(value: object): void {\n if (Array.isArray(value)) return;\n const prototype = Object.getPrototypeOf(value);\n if (prototype === Object.prototype || prototype === null) return;\n\n const constructorName = value.constructor?.name ?? \"unknown\";\n throw new TypeError(`History values do not support object type \"${constructorName}\".`);\n}\n\nfunction compareKeys(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n","import type {\n HistoryArrayFieldConfig,\n HistoryArrayItemConfig,\n HistoryAtomicFieldConfig,\n HistoryDefinition,\n HistoryEntityKey,\n HistoryFieldConfig,\n HistoryObjectFieldConfig,\n HistoryPathSegment,\n} from \"../definitions/historyDefinition.types\";\nimport { areHistoryValuesEqual, formatHistoryValue, isHistoryValuePresent, stableStringify } from \"./historyValue\";\nimport type {\n HistoryEngineOptions,\n HistoryFieldRow,\n HistoryGroupChangeType,\n HistoryGroupNode,\n HistoryNode,\n HistoryValue,\n} from \"./historyNode.types\";\nimport type { z } from \"zod\";\n\nconst DEFAULT_POSITION_LABEL = \"Position\";\n\n// These erased forms are implementation details; consumers use the typed\n// definition/config contracts exported from the package root.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InternalHistoryDefinition = HistoryDefinition<any, any>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InternalFieldConfig = HistoryFieldConfig<any, any>;\ntype InternalNonIgnoredFieldConfig = Exclude<InternalFieldConfig, false>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InternalAtomicFieldConfig = HistoryAtomicFieldConfig<any, any>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InternalArrayFieldConfig = HistoryArrayFieldConfig<any, any>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InternalArrayItemConfig = HistoryArrayItemConfig<any>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InternalObjectFieldConfig = HistoryObjectFieldConfig<any>;\n\nexport function createHistoryNodes<TEntity extends object, TSchema extends z.ZodTypeAny>(\n definition: HistoryDefinition<TEntity, TSchema>,\n previous: NoInfer<TEntity> | null | undefined,\n current: NoInfer<TEntity> | null | undefined,\n options: HistoryEngineOptions = {},\n): HistoryNode[] {\n const previousParsed = parseOptionalSnapshot(definition, previous);\n const currentParsed = parseOptionalSnapshot(definition, current);\n\n const group = createHistoryGroup(definition, previousParsed, currentParsed, [], options);\n\n return group == null ? [] : [group];\n}\n\nfunction createHistoryGroup(\n definition: InternalHistoryDefinition,\n previous: unknown,\n current: unknown,\n path: HistoryPathSegment[],\n options: HistoryEngineOptions = {},\n changeType?: HistoryGroupChangeType,\n): HistoryGroupNode | null {\n const children = createFieldNodesForDefinition(definition, previous, current, path, options);\n\n if (children.length === 0 && changeType == null) {\n return null;\n }\n\n return {\n type: \"group\",\n path,\n label: definition.options.label,\n value: formatDefinitionValue(\n definition,\n isHistoryValuePresent(current) ? current : previous,\n path,\n isHistoryValuePresent(current) ? \"current\" : \"previous\",\n ),\n changeType: changeType ?? resolveDefaultGroupChangeType(children),\n children,\n };\n}\n\nfunction parseOptionalSnapshot(definition: InternalHistoryDefinition, value: unknown): unknown {\n if (!isHistoryValuePresent(value)) {\n return undefined;\n }\n\n return definition.schema.parse(value);\n}\n\nfunction createFieldNodesForDefinition(\n definition: InternalHistoryDefinition,\n previous: unknown,\n current: unknown,\n path: HistoryPathSegment[],\n options: HistoryEngineOptions,\n): HistoryNode[] {\n const directNodes: HistoryNode[] = [];\n const nestedNodes: HistoryNode[] = [];\n\n for (const fieldName of Object.keys(definition.fields)) {\n const fieldConfig = definition.fields[fieldName] as InternalFieldConfig;\n\n if (fieldConfig === false) {\n continue;\n }\n\n const fieldPath = [...path, fieldName];\n const previousValue = getObjectFieldValue(previous, fieldName);\n const currentValue = getObjectFieldValue(current, fieldName);\n\n const nodes = createFieldNodes({\n config: fieldConfig,\n previous: previousValue,\n current: currentValue,\n previousParent: previous,\n currentParent: current,\n path: fieldPath,\n options,\n });\n\n if (fieldConfig.kind === \"field\") {\n directNodes.push(...nodes);\n continue;\n }\n\n nestedNodes.push(...nodes);\n }\n\n return [...sortHistoryNodesByChangeType(directNodes), ...sortHistoryNodesByChangeType(nestedNodes)];\n}\n\nfunction createFieldNodes(args: {\n config: InternalNonIgnoredFieldConfig;\n previous: unknown;\n current: unknown;\n previousParent: unknown;\n currentParent: unknown;\n path: HistoryPathSegment[];\n options: HistoryEngineOptions;\n}): HistoryNode[] {\n const { config } = args;\n\n switch (config.kind) {\n case \"field\": {\n const row = createAtomicFieldRow({\n ...args,\n config,\n });\n\n return row == null ? [] : [row];\n }\n\n case \"array\": {\n return createArrayGroup({\n ...args,\n config,\n });\n }\n\n case \"object\": {\n return createObjectGroup({\n ...args,\n config,\n });\n }\n\n default: {\n return [];\n }\n }\n}\n\nfunction createAtomicFieldRow(args: {\n config: InternalAtomicFieldConfig;\n previous: unknown;\n current: unknown;\n previousParent: unknown;\n currentParent: unknown;\n path: HistoryPathSegment[];\n options: HistoryEngineOptions;\n}): HistoryFieldRow | null {\n const { config, previous, current, previousParent, currentParent, path, options } = args;\n\n const changeType =\n config.resolveChange == null\n ? resolveDefaultFieldChange(previous, current)\n : validateResolvedChange(config.resolveChange(previous, current), path);\n\n if (changeType == null) {\n return createUnchangedFieldRow({\n config,\n previous,\n current,\n previousParent,\n currentParent,\n path,\n options,\n });\n }\n\n if (changeType === \"removed\") {\n return {\n type: \"removed\",\n path,\n label: config.label,\n previous: formatFieldValue({\n config,\n value: previous,\n parent: previousParent,\n side: \"previous\",\n path,\n options,\n }),\n };\n }\n\n if (changeType === \"added\") {\n return {\n type: \"added\",\n path,\n label: config.label,\n current: formatFieldValue({\n config,\n value: current,\n parent: currentParent,\n side: \"current\",\n path,\n options,\n }),\n };\n }\n\n return {\n type: \"updated\",\n path,\n label: config.label,\n previous: formatFieldValue({\n config,\n value: previous,\n parent: previousParent,\n side: \"previous\",\n path,\n options,\n }),\n current: formatFieldValue({\n config,\n value: current,\n parent: currentParent,\n side: \"current\",\n path,\n options,\n }),\n };\n}\n\nfunction validateResolvedChange(\n value: unknown,\n path: readonly HistoryPathSegment[],\n): \"added\" | \"removed\" | \"updated\" | null {\n if (value === null || value === \"added\" || value === \"removed\" || value === \"updated\") return value;\n throw new TypeError(`History change resolver at \"${path.join(\".\")}\" returned unsupported type \"${String(value)}\".`);\n}\n\nfunction createUnchangedFieldRow(args: {\n config: InternalAtomicFieldConfig;\n previous: unknown;\n current: unknown;\n previousParent: unknown;\n currentParent: unknown;\n path: HistoryPathSegment[];\n options: HistoryEngineOptions;\n}): HistoryFieldRow | null {\n const { config, previous, current, previousParent, currentParent, path, options } = args;\n\n if (options.showUnchanged !== true) {\n return null;\n }\n\n const value = isHistoryValuePresent(current) ? current : previous;\n\n if (!isHistoryValuePresent(value)) {\n return null;\n }\n\n const parent = isHistoryValuePresent(current) ? currentParent : previousParent;\n const side = isHistoryValuePresent(current) ? \"current\" : \"previous\";\n\n return {\n type: \"unchanged\",\n path,\n label: config.label,\n current: formatFieldValue({\n config,\n value,\n parent,\n side,\n path,\n options,\n }),\n };\n}\n\nfunction createObjectGroup(args: {\n config: InternalObjectFieldConfig;\n previous: unknown;\n current: unknown;\n path: HistoryPathSegment[];\n options: HistoryEngineOptions;\n}): HistoryNode[] {\n const { config, previous, current, path, options } = args;\n\n const group = createHistoryGroup(\n config.definition,\n previous,\n current,\n path,\n options,\n resolveContainerChangeType(previous, current),\n );\n\n return group == null ? [] : [group];\n}\n\nfunction resolveContainerChangeType(previous: unknown, current: unknown): HistoryGroupChangeType | undefined {\n const previousEmpty = !isHistoryValuePresent(previous);\n const currentEmpty = !isHistoryValuePresent(current);\n\n if (previousEmpty && !currentEmpty) {\n return \"added\";\n }\n\n if (!previousEmpty && currentEmpty) {\n return \"removed\";\n }\n\n return undefined;\n}\n\nfunction createArrayGroup(args: {\n config: InternalArrayFieldConfig;\n previous: unknown;\n current: unknown;\n previousParent: unknown;\n currentParent: unknown;\n path: HistoryPathSegment[];\n options: HistoryEngineOptions;\n}): HistoryNode[] {\n const { config, previous, current, previousParent, currentParent, path, options } = args;\n\n const previousArray = Array.isArray(previous) ? previous : [];\n const currentArray = Array.isArray(current) ? current : [];\n\n const mode = config.mode ?? \"set\";\n const containerChangeType = resolveContainerChangeType(previous, current);\n\n const children =\n mode === \"ordered\"\n ? createOrderedArrayChildren(config, previousArray, currentArray, path, options)\n : createSetArrayChildren(config, previousArray, currentArray, path, options);\n\n if (children.length === 0 && containerChangeType == null) {\n return [];\n }\n\n return [\n {\n type: \"group\",\n path,\n label: config.label,\n value: formatArrayValue(\n config,\n isHistoryValuePresent(current) ? currentArray : previousArray,\n isHistoryValuePresent(current) ? currentParent : previousParent,\n path,\n isHistoryValuePresent(current) ? \"current\" : \"previous\",\n ),\n changeType: containerChangeType ?? resolveDefaultGroupChangeType(children),\n children,\n },\n ];\n}\n\nfunction createSetArrayChildren(\n config: InternalArrayFieldConfig,\n previousArray: unknown[],\n currentArray: unknown[],\n path: HistoryPathSegment[],\n options: HistoryEngineOptions,\n): HistoryNode[] {\n const previousItems = createArrayItemMap(config, previousArray, path, \"previous\");\n const currentItems = createArrayItemMap(config, currentArray, path, \"current\");\n\n const addedChildren: HistoryNode[] = [];\n const updatedChildren: HistoryNode[] = [];\n const removedChildren: HistoryNode[] = [];\n\n for (const [key, currentEntry] of currentItems) {\n const previousEntry = previousItems.get(key);\n const itemPath = [...path, key];\n\n if (previousEntry == null) {\n addedChildren.push(...createAddedArrayItemNodes(config, currentEntry.value, itemPath, options));\n continue;\n }\n\n updatedChildren.push(\n ...createMatchedArrayItemNodes({\n config,\n previous: previousEntry.value,\n current: currentEntry.value,\n path: itemPath,\n movedRow: null,\n options,\n }),\n );\n }\n\n for (const [key, previousEntry] of previousItems) {\n if (currentItems.has(key)) {\n continue;\n }\n\n removedChildren.push(...createRemovedArrayItemNodes(config, previousEntry.value, [...path, key], options));\n }\n\n return sortHistoryNodesByChangeType([...addedChildren, ...updatedChildren, ...removedChildren]);\n}\n\nfunction createOrderedArrayChildren(\n config: InternalArrayFieldConfig,\n previousArray: unknown[],\n currentArray: unknown[],\n path: HistoryPathSegment[],\n options: HistoryEngineOptions,\n): HistoryNode[] {\n const previousItems = createArrayItemMap(config, previousArray, path, \"previous\");\n const currentItems = createArrayItemMap(config, currentArray, path, \"current\");\n const stableKeys = new Set(\n findLongestStableKeySequence(\n [...previousItems.keys()].filter(key => currentItems.has(key)),\n [...currentItems.keys()].filter(key => previousItems.has(key)),\n ),\n );\n\n const addedChildren: HistoryNode[] = [];\n const updatedChildren: HistoryNode[] = [];\n const removedChildren: HistoryNode[] = [];\n\n for (const [key, currentEntry] of currentItems) {\n const previousEntry = previousItems.get(key);\n const itemPath = [...path, key];\n\n if (previousEntry == null) {\n addedChildren.push(...createAddedArrayItemNodes(config, currentEntry.value, itemPath, options));\n continue;\n }\n\n const movedRow = stableKeys.has(key)\n ? null\n : createMovedRow(itemPath, previousEntry.index, currentEntry.index, options);\n\n updatedChildren.push(\n ...createMatchedArrayItemNodes({\n config,\n previous: previousEntry.value,\n current: currentEntry.value,\n path: itemPath,\n movedRow,\n options,\n }),\n );\n }\n\n for (const [key, previousEntry] of previousItems) {\n if (currentItems.has(key)) {\n continue;\n }\n\n removedChildren.push(...createRemovedArrayItemNodes(config, previousEntry.value, [...path, key], options));\n }\n\n return [\n ...sortHistoryNodesByChangeType(addedChildren),\n ...sortHistoryNodesByChangeType(updatedChildren),\n ...sortHistoryNodesByChangeType(removedChildren),\n ];\n}\n\nfunction findLongestStableKeySequence(\n previousKeys: readonly HistoryEntityKey[],\n currentKeys: readonly HistoryEntityKey[],\n): HistoryEntityKey[] {\n const lengths = Array.from({ length: previousKeys.length + 1 }, () => Array<number>(currentKeys.length + 1).fill(0));\n\n for (let previousIndex = previousKeys.length - 1; previousIndex >= 0; previousIndex -= 1) {\n for (let currentIndex = currentKeys.length - 1; currentIndex >= 0; currentIndex -= 1) {\n lengths[previousIndex]![currentIndex] = areHistoryKeysEqual(\n previousKeys[previousIndex],\n currentKeys[currentIndex],\n )\n ? 1 + lengths[previousIndex + 1]![currentIndex + 1]!\n : Math.max(lengths[previousIndex + 1]![currentIndex]!, lengths[previousIndex]![currentIndex + 1]!);\n }\n }\n\n const stableKeys: HistoryEntityKey[] = [];\n let previousIndex = 0;\n let currentIndex = 0;\n\n while (previousIndex < previousKeys.length && currentIndex < currentKeys.length) {\n const previousKey = previousKeys[previousIndex]!;\n const currentKey = currentKeys[currentIndex]!;\n\n if (areHistoryKeysEqual(previousKey, currentKey)) {\n stableKeys.push(previousKey);\n previousIndex += 1;\n currentIndex += 1;\n continue;\n }\n\n const skipPreviousLength = lengths[previousIndex + 1]![currentIndex]!;\n const skipCurrentLength = lengths[previousIndex]![currentIndex + 1]!;\n if (skipPreviousLength > skipCurrentLength) {\n previousIndex += 1;\n } else {\n currentIndex += 1;\n }\n }\n\n return stableKeys;\n}\n\nfunction areHistoryKeysEqual(left: HistoryEntityKey | undefined, right: HistoryEntityKey | undefined): boolean {\n return (\n left === right ||\n (typeof left === \"number\" && typeof right === \"number\" && Number.isNaN(left) && Number.isNaN(right))\n );\n}\n\nfunction createMatchedArrayItemNodes(args: {\n config: InternalArrayFieldConfig;\n previous: unknown;\n current: unknown;\n path: HistoryPathSegment[];\n movedRow: HistoryFieldRow | null;\n options: HistoryEngineOptions;\n}): HistoryNode[] {\n const { config, previous, current, path, movedRow, options } = args;\n const item = config.item as InternalArrayItemConfig;\n\n if (item.kind === \"object\") {\n const group = createHistoryGroup(item.definition, previous, current, path, options);\n\n if (group == null) {\n return movedRow == null ? [] : [createMovedOnlyGroup(item, current, path, movedRow)];\n }\n\n return [\n {\n ...group,\n children: movedRow == null ? group.children : [movedRow, ...group.children],\n },\n ];\n }\n\n const nodes = createFieldNodes({\n config: item,\n previous,\n current,\n previousParent: previous,\n currentParent: current,\n path,\n options,\n });\n\n return movedRow == null ? nodes : [movedRow, ...nodes];\n}\n\nfunction createAddedArrayItemNodes(\n config: InternalArrayFieldConfig,\n current: unknown,\n path: HistoryPathSegment[],\n options: HistoryEngineOptions,\n): HistoryNode[] {\n const item = config.item as InternalArrayItemConfig;\n\n if (item.kind === \"object\") {\n const group = createHistoryGroup(item.definition, undefined, current, path, options, \"added\");\n\n return group == null\n ? [\n {\n type: \"added\",\n path,\n label: item.definition.options.label,\n current: formatDefinitionValue(item.definition, current, path, \"current\"),\n },\n ]\n : [group];\n }\n\n return createFieldNodes({\n config: item,\n previous: undefined,\n current,\n previousParent: undefined,\n currentParent: current,\n path,\n options,\n });\n}\n\nfunction createRemovedArrayItemNodes(\n config: InternalArrayFieldConfig,\n previous: unknown,\n path: HistoryPathSegment[],\n options: HistoryEngineOptions,\n): HistoryNode[] {\n const item = config.item as InternalArrayItemConfig;\n\n if (item.kind === \"object\") {\n const group = createHistoryGroup(item.definition, previous, undefined, path, options, \"removed\");\n\n return group == null\n ? [\n {\n type: \"removed\",\n path,\n label: item.definition.options.label,\n previous: formatDefinitionValue(item.definition, previous, path, \"previous\"),\n },\n ]\n : [group];\n }\n\n return createFieldNodes({\n config: item,\n previous,\n current: undefined,\n previousParent: previous,\n currentParent: undefined,\n path,\n options,\n });\n}\n\nfunction createMovedOnlyGroup(\n item: Extract<InternalArrayItemConfig, { kind: \"object\" }>,\n current: unknown,\n path: HistoryPathSegment[],\n movedRow: HistoryFieldRow,\n): HistoryGroupNode {\n return {\n type: \"group\",\n path,\n label: item.definition.options.label,\n value: formatDefinitionValue(item.definition, current, path, \"current\"),\n changeType: \"updated\",\n children: [movedRow],\n };\n}\n\nfunction createMovedRow(\n path: HistoryPathSegment[],\n previousIndex: number,\n currentIndex: number,\n options: HistoryEngineOptions,\n): HistoryFieldRow {\n return {\n type: \"moved\",\n path: [...path, \"$position\"],\n label: options.positionLabel ?? DEFAULT_POSITION_LABEL,\n previous: createHistoryValue(previousIndex, String(previousIndex + 1)),\n current: createHistoryValue(currentIndex, String(currentIndex + 1)),\n };\n}\n\nfunction createArrayItemMap(\n config: InternalArrayFieldConfig,\n array: unknown[],\n path: readonly HistoryPathSegment[],\n side: \"previous\" | \"current\",\n): Map<HistoryEntityKey, { value: unknown; index: number }> {\n const map = new Map<HistoryEntityKey, { value: unknown; index: number }>();\n\n array.forEach((value, index) => {\n const key = createArrayItemKey(config, value);\n if ((typeof key !== \"string\" && typeof key !== \"number\") || (typeof key === \"number\" && !Number.isFinite(key))) {\n throw new TypeError(\n `History array identity in the ${side} snapshot at \"${path.join(\".\")}\" must be a string or finite number.`,\n );\n }\n if (map.has(key)) {\n throw new Error(\n `Duplicate history array identity \"${String(key)}\" in the ${side} snapshot at \"${path.join(\".\")}\".`,\n );\n }\n map.set(key, { value, index });\n });\n\n return map;\n}\n\nfunction createArrayItemKey(config: InternalArrayFieldConfig, value: unknown): HistoryEntityKey {\n const item = config.item as InternalArrayItemConfig;\n\n if (item.kind === \"object\") {\n return item.definition.options.key(value);\n }\n\n if (typeof value === \"string\" || typeof value === \"number\") {\n return value;\n }\n\n return stableStringify(value);\n}\n\nfunction sortHistoryNodesByChangeType(nodes: HistoryNode[]): HistoryNode[] {\n return [...nodes].sort((left, right) => getHistoryNodeChangeOrder(left) - getHistoryNodeChangeOrder(right));\n}\n\nfunction resolveDefaultGroupChangeType(children: HistoryNode[]): HistoryGroupChangeType {\n const hasChangedChild = children.some(child => getHistoryNodeChangeType(child) !== \"unchanged\");\n\n return hasChangedChild ? \"updated\" : \"unchanged\";\n}\n\nfunction getHistoryNodeChangeType(node: HistoryNode): HistoryGroupChangeType {\n if (node.type === \"group\") {\n return node.changeType ?? resolveDefaultGroupChangeType(node.children);\n }\n\n switch (node.type) {\n case \"added\":\n return \"added\";\n\n case \"removed\":\n return \"removed\";\n\n case \"updated\":\n case \"moved\":\n return \"updated\";\n\n case \"unchanged\":\n return \"unchanged\";\n\n default:\n return \"updated\";\n }\n}\n\nfunction getHistoryNodeChangeOrder(node: HistoryNode): number {\n if (node.type === \"group\" && node.changeType != null) {\n return getHistoryChangeOrder(node.changeType);\n }\n\n if (node.type !== \"group\") {\n return getHistoryFieldRowChangeOrder(node);\n }\n\n if (node.children.length === 0) {\n return 1;\n }\n\n return Math.min(...node.children.map(getHistoryNodeChangeOrder));\n}\n\nfunction getHistoryChangeOrder(changeType: HistoryGroupChangeType): number {\n switch (changeType) {\n case \"added\":\n return 0;\n\n case \"updated\":\n return 1;\n\n case \"removed\":\n return 2;\n\n case \"unchanged\":\n return 3;\n\n default:\n return 1;\n }\n}\n\nfunction getHistoryFieldRowChangeOrder(row: HistoryFieldRow): number {\n switch (row.type) {\n case \"added\":\n return 0;\n\n case \"updated\":\n case \"moved\":\n return 1;\n\n case \"removed\":\n return 2;\n\n case \"unchanged\":\n return 3;\n\n default:\n return 1;\n }\n}\n\nfunction resolveDefaultFieldChange(previous: unknown, current: unknown): \"added\" | \"removed\" | \"updated\" | null {\n const previousEmpty = !isHistoryValuePresent(previous);\n const currentEmpty = !isHistoryValuePresent(current);\n\n if (previousEmpty && currentEmpty) {\n return null;\n }\n\n if (previousEmpty && !currentEmpty) {\n return \"added\";\n }\n\n if (!previousEmpty && currentEmpty) {\n return \"removed\";\n }\n\n if (areHistoryValuesEqual(previous, current)) {\n return null;\n }\n\n return \"updated\";\n}\n\nfunction getObjectFieldValue(value: unknown, fieldName: string): unknown {\n if (value == null || typeof value !== \"object\") return undefined;\n return (value as Record<string, unknown>)[fieldName];\n}\n\nfunction formatFieldValue(args: {\n config: InternalAtomicFieldConfig;\n value: unknown;\n parent: unknown;\n side: \"previous\" | \"current\";\n path: HistoryPathSegment[];\n options: HistoryEngineOptions;\n}): HistoryValue {\n const { config, value, parent, side, path } = args;\n return formatHistoryValue(value, config.format, { parent, side, path });\n}\n\nfunction formatArrayValue(\n config: InternalArrayFieldConfig,\n value: unknown[],\n parent: unknown,\n path: HistoryPathSegment[],\n side: \"previous\" | \"current\",\n): HistoryValue | undefined {\n if (config.format == null) return undefined;\n return formatHistoryValue(value, config.format, { parent, side, path });\n}\n\nfunction formatDefinitionValue(\n definition: InternalHistoryDefinition,\n value: unknown,\n path: HistoryPathSegment[],\n side: \"previous\" | \"current\",\n): HistoryValue {\n if (definition.options.format == null) {\n return createHistoryValue(value, definition.options.label);\n }\n\n return formatHistoryValue(value, definition.options.format, { parent: value, side, path });\n}\n\nfunction createHistoryValue(raw: unknown, formatted: string): HistoryValue {\n return { raw, formatted };\n}\n","import { z } from \"zod\";\n\nexport type HistoryEntityKind = string;\nexport type HistoryTimestamp = number | string;\n\nexport const HistorySnapshotSchema = z.record(z.string(), z.unknown());\nexport type HistorySnapshot = z.infer<typeof HistorySnapshotSchema>;\n\nexport const HistoryTimestampSchema = z.union([z.number().finite(), z.string().datetime({ offset: true })]);\n\nexport const HistoryActorSchema = z.object({\n id: z.string().min(1).nullable().optional(),\n label: z\n .string()\n .min(1)\n .refine(label => label.trim().length > 0, \"History actor label cannot be blank.\"),\n});\nexport type HistoryActor = z.infer<typeof HistoryActorSchema>;\n\nexport interface HistoryRecord<\n TSnapshot extends HistorySnapshot = HistorySnapshot,\n TEntityKind extends HistoryEntityKind = HistoryEntityKind,\n TTimestamp extends HistoryTimestamp = HistoryTimestamp,\n> {\n id: string;\n timestamp: TTimestamp;\n actor: HistoryActor | null;\n entity: TEntityKind;\n entityId: string;\n snapshotPrevious: TSnapshot | null;\n snapshotCurrent: TSnapshot | null;\n}\n\nexport type HistoryRecordSchemaOptions<\n TEntityKind extends HistoryEntityKind = HistoryEntityKind,\n TSnapshot extends HistorySnapshot = HistorySnapshot,\n TTimestamp extends HistoryTimestamp = HistoryTimestamp,\n> = {\n entityKind?: z.ZodType<TEntityKind>;\n snapshot?: z.ZodType<TSnapshot>;\n timestamp?: z.ZodType<TTimestamp>;\n};\n\nexport function createHistoryRecordSchema<\n TEntityKind extends HistoryEntityKind = HistoryEntityKind,\n TSnapshot extends HistorySnapshot = HistorySnapshot,\n TTimestamp extends HistoryTimestamp = HistoryTimestamp,\n>(\n options: HistoryRecordSchemaOptions<TEntityKind, TSnapshot, TTimestamp> = {},\n): z.ZodType<HistoryRecord<TSnapshot, TEntityKind, TTimestamp>> {\n const entityKindSchema = options.entityKind ?? (z.string().min(1) as unknown as z.ZodType<TEntityKind>);\n const snapshotSchema = options.snapshot ?? (HistorySnapshotSchema as z.ZodType<TSnapshot>);\n const timestampSchema = options.timestamp ?? (HistoryTimestampSchema as unknown as z.ZodType<TTimestamp>);\n\n return z.object({\n id: z.string().min(1),\n timestamp: timestampSchema,\n actor: HistoryActorSchema.nullable(),\n entity: entityKindSchema,\n entityId: z.string().min(1),\n snapshotPrevious: snapshotSchema.nullable(),\n snapshotCurrent: snapshotSchema.nullable(),\n }) as z.ZodType<HistoryRecord<TSnapshot, TEntityKind, TTimestamp>>;\n}\n\nexport const HistoryRecordSchema = createHistoryRecordSchema();\n"],"mappings":";;AAQA,SAAgB,EACd,GACA,GACA,GAC6D;CAG7D,IAFA,EAAuB,CAAM,GAC7B,EAAoB,GAAS,OAAO,0BAA0B,GAC1D,OAAO,GAAS,OAAQ,YAAY,MAAU,UAAU,4CAA4C;CAExG,IADA,EAAuB,EAAQ,QAAQ,2BAA2B,GAC5C,OAAO,KAAW,aAApC,KAAgD,MAAM,QAAQ,CAAM,GACtE,MAAU,UAAU,8CAA8C;CAKpE,OAFA,OAAO,QAAQ,CAAM,CAAC,CAAC,SAAS,CAAC,GAAW,OAAY,EAAoB,GAAQ,UAAU,GAAW,CAAC,GAEnG;EAAE;EAAQ;EAAS;CAAO;AACnC;AAEA,SAAS,EAAoB,GAAiB,GAAwB;CACpE,IAAI,MAAW,IAAO;CACtB,IAAsB,OAAO,KAAW,aAApC,KAAgD,MAAM,QAAQ,CAAM,GACtE,MAAU,UAAU,WAAW,EAAS,gDAAgD;CAG1F,IAAM,IAAS;CACf,QAAQ,EAAO,MAAf;EACE,KAAK;GAGH,AAFA,EAAoB,EAAO,OAAO,WAAW,EAAS,OAAO,GAC7D,EAAuB,EAAO,QAAQ,WAAW,EAAS,QAAQ,GAClE,EAAuB,EAAO,eAAe,WAAW,EAAS,eAAe;GAChF;EACF,KAAK;GAGH,IAFA,EAAoB,EAAO,OAAO,WAAW,EAAS,OAAO,GAC7D,EAAuB,EAAO,QAAQ,WAAW,EAAS,QAAQ,GAC9D,EAAO,SAAS,KAAA,KAAa,EAAO,SAAS,SAAS,EAAO,SAAS,WACxE,MAAU,UAAU,WAAW,EAAS,kCAAkC;GAG5E,IADA,EAAoB,EAAO,MAAM,GAAG,EAAS,MAAM,GAC/C,EAAO,SAAS,IAAO,MAAU,UAAU,WAAW,EAAS,yBAAyB;GAC5F;EACF,KAAK;GACH,EAAwB,EAAO,YAAY,WAAW,EAAS,YAAY;GAC3E;EACF,SACE,MAAU,UAAU,WAAW,EAAS,yBAAyB,OAAO,EAAO,IAAI,EAAE,GAAG;CAC5F;AACF;AAEA,SAAS,EAAuB,GAAuB;CACrD,IAAsB,OAAO,KAAW,aAApC,KAAgD,OAAQ,EAA+B,SAAU,YACnG,MAAU,UAAU,iDAAiD;AAEzE;AAEA,SAAS,EAAwB,GAAgB,GAAwB;CACvE,IAAqB,OAAO,KAAU,aAAlC,GAA4C,MAAU,UAAU,GAAG,EAAS,+BAA+B;CAC/G,IAAM,IAAa;CAEnB,IADA,EAAuB,EAAW,MAAM,GACpC,EAAW,WAAW,QAAQ,OAAO,EAAW,WAAY,UAC9D,MAAU,UAAU,GAAG,EAAS,kCAAkC;CAGpE,IADA,EAAqB,EAAW,QAAoC,OAAO,GAAG,EAAS,OAAO,GAC1F,OAAQ,EAAW,QAAoC,OAAQ,YACjE,MAAU,UAAU,GAAG,EAAS,yBAAyB;CAE3D,IAAI,EAAW,UAAU,QAAQ,OAAO,EAAW,UAAW,YAAY,MAAM,QAAQ,EAAW,MAAM,GACvG,MAAU,UAAU,GAAG,EAAS,2BAA2B;AAE/D;AAEA,SAAS,EAAoB,GAAgB,GAA2C;CACtF,IAAI,OAAO,KAAU,YAAY,EAAM,KAAK,CAAC,CAAC,WAAW,GACvD,MAAU,UAAU,GAAG,EAAS,6BAA6B;AACjE;AAEA,SAAS,EAAuB,GAAgB,GAAwB;CACtE,IAAI,MAAU,KAAA,KAAa,OAAO,KAAU,YAAY,MAAU,UAAU,GAAG,EAAS,qBAAqB;AAC/G;;;AClFA,SAAgB,EAAsB,GAAyB;CAC7D,OAAO,KAAU;AACnB;AAEA,SAAgB,EACd,GACA,GACA,GACc;CACd,IAAM,IAAY,KAAU,OAAO,EAA0B,CAAG,IAAI,EAAO,GAAc,CAAO;CAEhG,IAAI,OAAO,KAAc,UACvB,MAAU,UAAU,yBAAyB,EAAQ,KAAK,KAAK,GAAG,KAAK,QAAQ,wBAAwB;CAGzG,OAAO;EAAE;EAAK;CAAU;AAC1B;AAEA,SAAgB,EAA0B,GAAwB;CAKhE,OAJI,OAAO,KAAU,WAAiB,IAClC,OAAO,KAAU,YAAY,OAAO,KAAU,aAAa,OAAO,KAAU,WAAiB,OAAO,CAAK,IACzG,aAAiB,OAAa,EAAM,YAAY,IAE7C,EAAgC,CAAK;AAC9C;AAEA,SAAgB,EAAsB,GAAmB,GAA2B;CAKlF,OAJI,OAAO,GAAG,GAAU,CAAO,IAAU,KACrC,OAAO,KAAa,OAAO,KAAW,KAAY,QAAQ,KAAW,QACrE,OAAO,KAAa,WAAiB,KAElC,EAAgB,CAAQ,MAAM,EAAgB,CAAO;AAC9D;AAEA,SAAgB,EAAgB,GAAwB;CACtD,OAAO,KAAK,UAAU,EAA4B,mBAAO,IAAI,IAAY,CAAC,CAAC;AAC7E;AAIA,SAAS,EAA4B,GAAgB,GAA+C;CAClG,IAAI,MAAU,MAAM,OAAO,CAAC,MAAM;CAClC,IAAI,MAAU,KAAA,GAAW,OAAO,CAAC,WAAW;CAE5C,QAAQ,OAAO,GAAf;EACE,KAAK,UACH,OAAO,CAAC,UAAU,CAAK;EACzB,KAAK,WACH,OAAO,CAAC,WAAW,CAAK;EAC1B,KAAK,UACH,OAAO,CAAC,UAAU,EAAM,SAAS,CAAC;EACpC,KAAK,UACH,OAAO,CAAC,UAAU,GAAgB,CAAK,CAAC;EAC1C,KAAK;EACL,KAAK,YACH,MAAU,UAAU,iCAAiC,OAAO,EAAM,SAAS;EAC7E,KAAK,UACH;EACF,SACE,OAAO,CAAC,WAAW,OAAO,CAAK,CAAC;CACpC;CAEA,IAAI,aAAiB,MAAM;EACzB,IAAI,OAAO,MAAM,EAAM,QAAQ,CAAC,GAAG,MAAU,UAAU,oDAAoD;EAC3G,OAAO,CAAC,QAAQ,EAAM,YAAY,CAAC;CACrC;CAGA,IADA,EAAsB,CAAK,GACvB,EAAU,IAAI,CAAK,GAAG,MAAU,UAAU,oDAAoD;CAElG,EAAU,IAAI,CAAK;CACnB,IAAI;EAKF,OAJI,MAAM,QAAQ,CAAK,IACd,CAAC,SAAS,EAAM,KAAI,MAAS,EAA4B,GAAO,CAAS,CAAC,CAAC,IAG7E,CACL,UACA,OAAO,QAAQ,CAAgC,CAAC,CAC7C,MAAM,CAAC,IAAU,CAAC,OAAc,EAAY,GAAS,CAAQ,CAAC,CAAC,CAC/D,KAAK,CAAC,GAAK,OAAgB,CAAC,GAAK,EAA4B,GAAY,CAAS,CAAC,CAAC,CACzF;CACF,UAAU;EACR,EAAU,OAAO,CAAK;CACxB;AACF;AAEA,SAAS,EAAgC,GAAwB;CAC/D,OAAO,KAAK,UAAU,EAA0B,mBAAO,IAAI,IAAY,CAAC,CAAC;AAC3E;AAEA,SAAS,EAA0B,GAAgB,GAAiC;CAClF,IAAI,KAAS,QAAQ,OAAO,KAAU,YAAY,OAAO,KAAU,WAAW,OAAO;CACrF,IAAI,OAAO,KAAU,UAAU,OAAO,OAAO,SAAS,CAAK,IAAI,IAAQ,OAAO,CAAK;CACnF,IAAI,OAAO,KAAU,UAAU,OAAO,EAAM,SAAS;CACrD,IAAI,OAAO,KAAU,YAAY,OAAO,KAAU,YAChD,MAAU,UAAU,iCAAiC,OAAO,EAAM,SAAS;CAE7E,IAAI,aAAiB,MAAM;EACzB,IAAI,OAAO,MAAM,EAAM,QAAQ,CAAC,GAAG,MAAU,UAAU,oDAAoD;EAC3G,OAAO,EAAM,YAAY;CAC3B;CAGA,IADA,EAAsB,CAAK,GACvB,EAAU,IAAI,CAAK,GAAG,MAAU,UAAU,oDAAoD;CAElG,EAAU,IAAI,CAAK;CACnB,IAAI;EAGF,OAFI,MAAM,QAAQ,CAAK,IAAU,EAAM,KAAI,MAAS,EAA0B,GAAO,CAAS,CAAC,IAExF,OAAO,YACZ,OAAO,QAAQ,CAAgC,CAAC,CAC7C,MAAM,CAAC,IAAU,CAAC,OAAc,EAAY,GAAS,CAAQ,CAAC,CAAC,CAC/D,KAAK,CAAC,GAAK,OAAgB,CAAC,GAAK,EAA0B,GAAY,CAAS,CAAC,CAAC,CACvF;CACF,UAAU;EACR,EAAU,OAAO,CAAK;CACxB;AACF;AAEA,SAAS,GAAgB,GAAgC;CAKvD,OAJI,OAAO,MAAM,CAAK,IAAU,QAC5B,MAAU,WAAiC,aAC3C,MAAU,YAAiC,cAC3C,OAAO,GAAG,GAAO,EAAE,IAAU,OAC1B;AACT;AAEA,SAAS,EAAsB,GAAqB;CAClD,IAAI,MAAM,QAAQ,CAAK,GAAG;CAC1B,IAAM,IAAY,OAAO,eAAe,CAAK;CAC7C,IAAI,MAAc,OAAO,aAAa,MAAc,MAAM;CAE1D,IAAM,IAAkB,EAAM,aAAa,QAAQ;CACnD,MAAU,UAAU,8CAA8C,EAAgB,GAAG;AACvF;AAEA,SAAS,EAAY,GAAc,GAAuB;CAGxD,OAFI,IAAO,IAAc,KACzB,EAAI,IAAO;AAEb;;;AC3HA,IAAM,IAAyB;AAkB/B,SAAgB,EACd,GACA,GACA,GACA,IAAgC,CAAC,GAClB;CAIf,IAAM,IAAQ,EAAmB,GAHV,EAAsB,GAAY,CAGZ,GAFvB,EAAsB,GAAY,CAEK,GAAe,CAAC,GAAG,CAAO;CAEvF,OAAO,KAAS,OAAO,CAAC,IAAI,CAAC,CAAK;AACpC;AAEA,SAAS,EACP,GACA,GACA,GACA,GACA,IAAgC,CAAC,GACjC,GACyB;CACzB,IAAM,IAAW,EAA8B,GAAY,GAAU,GAAS,GAAM,CAAO;CAM3F,OAJI,EAAS,WAAW,KAAK,KAAc,OAClC,OAGF;EACL,MAAM;EACN;EACA,OAAO,EAAW,QAAQ;EAC1B,OAAO,EACL,GACA,EAAsB,CAAO,IAAI,IAAU,GAC3C,GACA,EAAsB,CAAO,IAAI,YAAY,UAC/C;EACA,YAAY,KAAc,EAA8B,CAAQ;EAChE;CACF;AACF;AAEA,SAAS,EAAsB,GAAuC,GAAyB;CACxF,MAAsB,CAAK,GAIhC,OAAO,EAAW,OAAO,MAAM,CAAK;AACtC;AAEA,SAAS,EACP,GACA,GACA,GACA,GACA,GACe;CACf,IAAM,IAA6B,CAAC,GAC9B,IAA6B,CAAC;CAEpC,KAAK,IAAM,KAAa,OAAO,KAAK,EAAW,MAAM,GAAG;EACtD,IAAM,IAAc,EAAW,OAAO;EAEtC,IAAI,MAAgB,IAClB;EAGF,IAAM,IAAY,CAAC,GAAG,GAAM,CAAS,GAI/B,IAAQ,EAAiB;GAC7B,QAAQ;GACR,UALoB,EAAoB,GAAU,CAKxC;GACV,SALmB,EAAoB,GAAS,CAKvC;GACT,gBAAgB;GAChB,eAAe;GACf,MAAM;GACN;EACF,CAAC;EAED,IAAI,EAAY,SAAS,SAAS;GAChC,EAAY,KAAK,GAAG,CAAK;GACzB;EACF;EAEA,EAAY,KAAK,GAAG,CAAK;CAC3B;CAEA,OAAO,CAAC,GAAG,EAA6B,CAAW,GAAG,GAAG,EAA6B,CAAW,CAAC;AACpG;AAEA,SAAS,EAAiB,GAQR;CAChB,IAAM,EAAE,cAAW;CAEnB,QAAQ,EAAO,MAAf;EACE,KAAK,SAAS;GACZ,IAAM,IAAM,GAAqB;IAC/B,GAAG;IACH;GACF,CAAC;GAED,OAAO,KAAO,OAAO,CAAC,IAAI,CAAC,CAAG;EAChC;EAEA,KAAK,SACH,OAAO,EAAiB;GACtB,GAAG;GACH;EACF,CAAC;EAGH,KAAK,UACH,OAAO,EAAkB;GACvB,GAAG;GACH;EACF,CAAC;EAGH,SACE,OAAO,CAAC;CAEZ;AACF;AAEA,SAAS,GAAqB,GAQH;CACzB,IAAM,EAAE,WAAQ,aAAU,YAAS,mBAAgB,kBAAe,SAAM,eAAY,GAE9E,IACJ,EAAO,iBAAiB,OACpB,EAA0B,GAAU,CAAO,IAC3C,EAAuB,EAAO,cAAc,GAAU,CAAO,GAAG,CAAI;CA8C1E,OA5CI,KAAc,OACT,EAAwB;EAC7B;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,IAGC,MAAe,YACV;EACL,MAAM;EACN;EACA,OAAO,EAAO;EACd,UAAU,EAAiB;GACzB;GACA,OAAO;GACP,QAAQ;GACR,MAAM;GACN;GACA;EACF,CAAC;CACH,IAGE,MAAe,UACV;EACL,MAAM;EACN;EACA,OAAO,EAAO;EACd,SAAS,EAAiB;GACxB;GACA,OAAO;GACP,QAAQ;GACR,MAAM;GACN;GACA;EACF,CAAC;CACH,IAGK;EACL,MAAM;EACN;EACA,OAAO,EAAO;EACd,UAAU,EAAiB;GACzB;GACA,OAAO;GACP,QAAQ;GACR,MAAM;GACN;GACA;EACF,CAAC;EACD,SAAS,EAAiB;GACxB;GACA,OAAO;GACP,QAAQ;GACR,MAAM;GACN;GACA;EACF,CAAC;CACH;AACF;AAEA,SAAS,EACP,GACA,GACwC;CACxC,IAAI,MAAU,QAAQ,MAAU,WAAW,MAAU,aAAa,MAAU,WAAW,OAAO;CAC9F,MAAU,UAAU,+BAA+B,EAAK,KAAK,GAAG,EAAE,+BAA+B,OAAO,CAAK,EAAE,GAAG;AACpH;AAEA,SAAS,EAAwB,GAQN;CACzB,IAAM,EAAE,WAAQ,aAAU,YAAS,mBAAgB,kBAAe,SAAM,eAAY;CAEpF,IAAI,EAAQ,kBAAkB,IAC5B,OAAO;CAGT,IAAM,IAAQ,EAAsB,CAAO,IAAI,IAAU;CAEzD,IAAI,CAAC,EAAsB,CAAK,GAC9B,OAAO;CAGT,IAAM,IAAS,EAAsB,CAAO,IAAI,IAAgB,GAC1D,IAAO,EAAsB,CAAO,IAAI,YAAY;CAE1D,OAAO;EACL,MAAM;EACN;EACA,OAAO,EAAO;EACd,SAAS,EAAiB;GACxB;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;CACH;AACF;AAEA,SAAS,EAAkB,GAMT;CAChB,IAAM,EAAE,WAAQ,aAAU,YAAS,SAAM,eAAY,GAE/C,IAAQ,EACZ,EAAO,YACP,GACA,GACA,GACA,GACA,EAA2B,GAAU,CAAO,CAC9C;CAEA,OAAO,KAAS,OAAO,CAAC,IAAI,CAAC,CAAK;AACpC;AAEA,SAAS,EAA2B,GAAmB,GAAsD;CAC3G,IAAM,IAAgB,CAAC,EAAsB,CAAQ,GAC/C,IAAe,CAAC,EAAsB,CAAO;CAEnD,IAAI,KAAiB,CAAC,GACpB,OAAO;CAGT,IAAI,CAAC,KAAiB,GACpB,OAAO;AAIX;AAEA,SAAS,EAAiB,GAQR;CAChB,IAAM,EAAE,WAAQ,aAAU,YAAS,mBAAgB,kBAAe,SAAM,eAAY,GAE9E,IAAgB,MAAM,QAAQ,CAAQ,IAAI,IAAW,CAAC,GACtD,IAAe,MAAM,QAAQ,CAAO,IAAI,IAAU,CAAC,GAEnD,IAAO,EAAO,QAAQ,OACtB,IAAsB,EAA2B,GAAU,CAAO,GAElE,IACJ,MAAS,YACL,EAA2B,GAAQ,GAAe,GAAc,GAAM,CAAO,IAC7E,EAAuB,GAAQ,GAAe,GAAc,GAAM,CAAO;CAM/E,OAJI,EAAS,WAAW,KAAK,KAAuB,OAC3C,CAAC,IAGH,CACL;EACE,MAAM;EACN;EACA,OAAO,EAAO;EACd,OAAO,EACL,GACA,EAAsB,CAAO,IAAI,IAAe,GAChD,EAAsB,CAAO,IAAI,IAAgB,GACjD,GACA,EAAsB,CAAO,IAAI,YAAY,UAC/C;EACA,YAAY,KAAuB,EAA8B,CAAQ;EACzE;CACF,CACF;AACF;AAEA,SAAS,EACP,GACA,GACA,GACA,GACA,GACe;CACf,IAAM,IAAgB,EAAmB,GAAQ,GAAe,GAAM,UAAU,GAC1E,IAAe,EAAmB,GAAQ,GAAc,GAAM,SAAS,GAEvE,IAA+B,CAAC,GAChC,IAAiC,CAAC,GAClC,IAAiC,CAAC;CAExC,KAAK,IAAM,CAAC,GAAK,MAAiB,GAAc;EAC9C,IAAM,IAAgB,EAAc,IAAI,CAAG,GACrC,IAAW,CAAC,GAAG,GAAM,CAAG;EAE9B,IAAI,KAAiB,MAAM;GACzB,EAAc,KAAK,GAAG,EAA0B,GAAQ,EAAa,OAAO,GAAU,CAAO,CAAC;GAC9F;EACF;EAEA,EAAgB,KACd,GAAG,EAA4B;GAC7B;GACA,UAAU,EAAc;GACxB,SAAS,EAAa;GACtB,MAAM;GACN,UAAU;GACV;EACF,CAAC,CACH;CACF;CAEA,KAAK,IAAM,CAAC,GAAK,MAAkB,GAC7B,EAAa,IAAI,CAAG,KAIxB,EAAgB,KAAK,GAAG,EAA4B,GAAQ,EAAc,OAAO,CAAC,GAAG,GAAM,CAAG,GAAG,CAAO,CAAC;CAG3G,OAAO,EAA6B;EAAC,GAAG;EAAe,GAAG;EAAiB,GAAG;CAAe,CAAC;AAChG;AAEA,SAAS,EACP,GACA,GACA,GACA,GACA,GACe;CACf,IAAM,IAAgB,EAAmB,GAAQ,GAAe,GAAM,UAAU,GAC1E,IAAe,EAAmB,GAAQ,GAAc,GAAM,SAAS,GACvE,IAAa,IAAI,IACrB,EACE,CAAC,GAAG,EAAc,KAAK,CAAC,CAAC,CAAC,QAAO,MAAO,EAAa,IAAI,CAAG,CAAC,GAC7D,CAAC,GAAG,EAAa,KAAK,CAAC,CAAC,CAAC,QAAO,MAAO,EAAc,IAAI,CAAG,CAAC,CAC/D,CACF,GAEM,IAA+B,CAAC,GAChC,IAAiC,CAAC,GAClC,IAAiC,CAAC;CAExC,KAAK,IAAM,CAAC,GAAK,MAAiB,GAAc;EAC9C,IAAM,IAAgB,EAAc,IAAI,CAAG,GACrC,IAAW,CAAC,GAAG,GAAM,CAAG;EAE9B,IAAI,KAAiB,MAAM;GACzB,EAAc,KAAK,GAAG,EAA0B,GAAQ,EAAa,OAAO,GAAU,CAAO,CAAC;GAC9F;EACF;EAEA,IAAM,IAAW,EAAW,IAAI,CAAG,IAC/B,OACA,GAAe,GAAU,EAAc,OAAO,EAAa,OAAO,CAAO;EAE7E,EAAgB,KACd,GAAG,EAA4B;GAC7B;GACA,UAAU,EAAc;GACxB,SAAS,EAAa;GACtB,MAAM;GACN;GACA;EACF,CAAC,CACH;CACF;CAEA,KAAK,IAAM,CAAC,GAAK,MAAkB,GAC7B,EAAa,IAAI,CAAG,KAIxB,EAAgB,KAAK,GAAG,EAA4B,GAAQ,EAAc,OAAO,CAAC,GAAG,GAAM,CAAG,GAAG,CAAO,CAAC;CAG3G,OAAO;EACL,GAAG,EAA6B,CAAa;EAC7C,GAAG,EAA6B,CAAe;EAC/C,GAAG,EAA6B,CAAe;CACjD;AACF;AAEA,SAAS,EACP,GACA,GACoB;CACpB,IAAM,IAAU,MAAM,KAAK,EAAE,QAAQ,EAAa,SAAS,EAAE,SAAS,MAAc,EAAY,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;CAEnH,KAAK,IAAI,IAAgB,EAAa,SAAS,GAAG,KAAiB,GAAG,KACpE,KAAK,IAAI,IAAe,EAAY,SAAS,GAAG,KAAgB,GAAG,KACjE,EAAQ,EAAc,CAAE,KAAgB,EACtC,EAAa,IACb,EAAY,EACd,IACI,IAAI,EAAQ,IAAgB,EAAE,CAAE,IAAe,KAC/C,KAAK,IAAI,EAAQ,IAAgB,EAAE,CAAE,IAAgB,EAAQ,EAAc,CAAE,IAAe,EAAG;CAIvG,IAAM,IAAiC,CAAC,GACpC,IAAgB,GAChB,IAAe;CAEnB,OAAO,IAAgB,EAAa,UAAU,IAAe,EAAY,SAAQ;EAC/E,IAAM,IAAc,EAAa,IAC3B,IAAa,EAAY;EAE/B,IAAI,EAAoB,GAAa,CAAU,GAAG;GAGhD,AAFA,EAAW,KAAK,CAAW,GAC3B,KAAiB,GACjB,KAAgB;GAChB;EACF;EAIA,AAF2B,EAAQ,IAAgB,EAAE,CAAE,KAC7B,EAAQ,EAAc,CAAE,IAAe,KAE/D,KAAiB,IAEjB,KAAgB;CAEpB;CAEA,OAAO;AACT;AAEA,SAAS,EAAoB,GAAoC,GAA8C;CAC7G,OACE,MAAS,KACR,OAAO,KAAS,YAAY,OAAO,KAAU,YAAY,OAAO,MAAM,CAAI,KAAK,OAAO,MAAM,CAAK;AAEtG;AAEA,SAAS,EAA4B,GAOnB;CAChB,IAAM,EAAE,WAAQ,aAAU,YAAS,SAAM,aAAU,eAAY,GACzD,IAAO,EAAO;CAEpB,IAAI,EAAK,SAAS,UAAU;EAC1B,IAAM,IAAQ,EAAmB,EAAK,YAAY,GAAU,GAAS,GAAM,CAAO;EAMlF,OAJI,KAAS,OACJ,KAAY,OAAO,CAAC,IAAI,CAAC,EAAqB,GAAM,GAAS,GAAM,CAAQ,CAAC,IAG9E,CACL;GACE,GAAG;GACH,UAAU,KAAY,OAAO,EAAM,WAAW,CAAC,GAAU,GAAG,EAAM,QAAQ;EAC5E,CACF;CACF;CAEA,IAAM,IAAQ,EAAiB;EAC7B,QAAQ;EACR;EACA;EACA,gBAAgB;EAChB,eAAe;EACf;EACA;CACF,CAAC;CAED,OAAO,KAAY,OAAO,IAAQ,CAAC,GAAU,GAAG,CAAK;AACvD;AAEA,SAAS,EACP,GACA,GACA,GACA,GACe;CACf,IAAM,IAAO,EAAO;CAEpB,IAAI,EAAK,SAAS,UAAU;EAC1B,IAAM,IAAQ,EAAmB,EAAK,YAAY,KAAA,GAAW,GAAS,GAAM,GAAS,OAAO;EAE5F,OAAO,KAAS,OACZ,CACE;GACE,MAAM;GACN;GACA,OAAO,EAAK,WAAW,QAAQ;GAC/B,SAAS,EAAsB,EAAK,YAAY,GAAS,GAAM,SAAS;EAC1E,CACF,IACA,CAAC,CAAK;CACZ;CAEA,OAAO,EAAiB;EACtB,QAAQ;EACR,UAAU,KAAA;EACV;EACA,gBAAgB,KAAA;EAChB,eAAe;EACf;EACA;CACF,CAAC;AACH;AAEA,SAAS,EACP,GACA,GACA,GACA,GACe;CACf,IAAM,IAAO,EAAO;CAEpB,IAAI,EAAK,SAAS,UAAU;EAC1B,IAAM,IAAQ,EAAmB,EAAK,YAAY,GAAU,KAAA,GAAW,GAAM,GAAS,SAAS;EAE/F,OAAO,KAAS,OACZ,CACE;GACE,MAAM;GACN;GACA,OAAO,EAAK,WAAW,QAAQ;GAC/B,UAAU,EAAsB,EAAK,YAAY,GAAU,GAAM,UAAU;EAC7E,CACF,IACA,CAAC,CAAK;CACZ;CAEA,OAAO,EAAiB;EACtB,QAAQ;EACR;EACA,SAAS,KAAA;EACT,gBAAgB;EAChB,eAAe,KAAA;EACf;EACA;CACF,CAAC;AACH;AAEA,SAAS,EACP,GACA,GACA,GACA,GACkB;CAClB,OAAO;EACL,MAAM;EACN;EACA,OAAO,EAAK,WAAW,QAAQ;EAC/B,OAAO,EAAsB,EAAK,YAAY,GAAS,GAAM,SAAS;EACtE,YAAY;EACZ,UAAU,CAAC,CAAQ;CACrB;AACF;AAEA,SAAS,GACP,GACA,GACA,GACA,GACiB;CACjB,OAAO;EACL,MAAM;EACN,MAAM,CAAC,GAAG,GAAM,WAAW;EAC3B,OAAO,EAAQ,iBAAiB;EAChC,UAAU,EAAmB,GAAe,OAAO,IAAgB,CAAC,CAAC;EACrE,SAAS,EAAmB,GAAc,OAAO,IAAe,CAAC,CAAC;CACpE;AACF;AAEA,SAAS,EACP,GACA,GACA,GACA,GAC0D;CAC1D,IAAM,oBAAM,IAAI,IAAyD;CAiBzE,OAfA,EAAM,SAAS,GAAO,MAAU;EAC9B,IAAM,IAAM,EAAmB,GAAQ,CAAK;EAC5C,IAAK,OAAO,KAAQ,YAAY,OAAO,KAAQ,YAAc,OAAO,KAAQ,YAAY,CAAC,OAAO,SAAS,CAAG,GAC1G,MAAU,UACR,iCAAiC,EAAK,gBAAgB,EAAK,KAAK,GAAG,EAAE,qCACvE;EAEF,IAAI,EAAI,IAAI,CAAG,GACb,MAAU,MACR,qCAAqC,OAAO,CAAG,EAAE,WAAW,EAAK,gBAAgB,EAAK,KAAK,GAAG,EAAE,GAClG;EAEF,EAAI,IAAI,GAAK;GAAE;GAAO;EAAM,CAAC;CAC/B,CAAC,GAEM;AACT;AAEA,SAAS,EAAmB,GAAkC,GAAkC;CAC9F,IAAM,IAAO,EAAO;CAUpB,OARI,EAAK,SAAS,WACT,EAAK,WAAW,QAAQ,IAAI,CAAK,IAGtC,OAAO,KAAU,YAAY,OAAO,KAAU,WACzC,IAGF,EAAgB,CAAK;AAC9B;AAEA,SAAS,EAA6B,GAAqC;CACzE,OAAO,CAAC,GAAG,CAAK,CAAC,CAAC,MAAM,GAAM,MAAU,EAA0B,CAAI,IAAI,EAA0B,CAAK,CAAC;AAC5G;AAEA,SAAS,EAA8B,GAAiD;CAGtF,OAFwB,EAAS,MAAK,MAAS,EAAyB,CAAK,MAAM,WAE5E,IAAkB,YAAY;AACvC;AAEA,SAAS,EAAyB,GAA2C;CAC3E,IAAI,EAAK,SAAS,SAChB,OAAO,EAAK,cAAc,EAA8B,EAAK,QAAQ;CAGvE,QAAQ,EAAK,MAAb;EACE,KAAK,SACH,OAAO;EAET,KAAK,WACH,OAAO;EAET,KAAK;EACL,KAAK,SACH,OAAO;EAET,KAAK,aACH,OAAO;EAET,SACE,OAAO;CACX;AACF;AAEA,SAAS,EAA0B,GAA2B;CAa5D,OAZI,EAAK,SAAS,WAAW,EAAK,cAAc,OACvC,EAAsB,EAAK,UAAU,IAG1C,EAAK,SAAS,UAId,EAAK,SAAS,WAAW,IACpB,IAGF,KAAK,IAAI,GAAG,EAAK,SAAS,IAAI,CAAyB,CAAC,IAPtD,EAA8B,CAAI;AAQ7C;AAEA,SAAS,EAAsB,GAA4C;CACzE,QAAQ,GAAR;EACE,KAAK,SACH,OAAO;EAET,KAAK,WACH,OAAO;EAET,KAAK,WACH,OAAO;EAET,KAAK,aACH,OAAO;EAET,SACE,OAAO;CACX;AACF;AAEA,SAAS,EAA8B,GAA8B;CACnE,QAAQ,EAAI,MAAZ;EACE,KAAK,SACH,OAAO;EAET,KAAK;EACL,KAAK,SACH,OAAO;EAET,KAAK,WACH,OAAO;EAET,KAAK,aACH,OAAO;EAET,SACE,OAAO;CACX;AACF;AAEA,SAAS,EAA0B,GAAmB,GAA0D;CAC9G,IAAM,IAAgB,CAAC,EAAsB,CAAQ,GAC/C,IAAe,CAAC,EAAsB,CAAO;CAkBnD,OAhBI,KAAiB,IACZ,OAGL,KAAiB,CAAC,IACb,UAGL,CAAC,KAAiB,IACb,YAGL,EAAsB,GAAU,CAAO,IAClC,OAGF;AACT;AAEA,SAAS,EAAoB,GAAgB,GAA4B;CACnE,MAAiB,OAAO,KAAU,aAAlC,IACJ,OAAQ,EAAkC;AAC5C;AAEA,SAAS,EAAiB,GAOT;CACf,IAAM,EAAE,WAAQ,UAAO,WAAQ,SAAM,YAAS;CAC9C,OAAO,EAAmB,GAAO,EAAO,QAAQ;EAAE;EAAQ;EAAM;CAAK,CAAC;AACxE;AAEA,SAAS,EACP,GACA,GACA,GACA,GACA,GAC0B;CACtB,MAAO,UAAU,MACrB,OAAO,EAAmB,GAAO,EAAO,QAAQ;EAAE;EAAQ;EAAM;CAAK,CAAC;AACxE;AAEA,SAAS,EACP,GACA,GACA,GACA,GACc;CAKd,OAJI,EAAW,QAAQ,UAAU,OACxB,EAAmB,GAAO,EAAW,QAAQ,KAAK,IAGpD,EAAmB,GAAO,EAAW,QAAQ,QAAQ;EAAE,QAAQ;EAAO;EAAM;CAAK,CAAC;AAC3F;AAEA,SAAS,EAAmB,GAAc,GAAiC;CACzE,OAAO;EAAE;EAAK;CAAU;AAC1B;;;ACp2BA,IAAa,IAAwB,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,GAGxD,IAAyB,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,QAAQ,GAAK,CAAC,CAAC,CAAC,GAE7F,IAAqB,EAAE,OAAO;CACzC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAC1C,OAAO,EACJ,OAAO,CAAC,CACR,IAAI,CAAC,CAAC,CACN,QAAO,MAAS,EAAM,KAAK,CAAC,CAAC,SAAS,GAAG,sCAAsC;AACpF,CAAC;AA2BD,SAAgB,EAKd,IAA0E,CAAC,GACb;CAC9D,IAAM,IAAmB,EAAQ,cAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAC1D,IAAiB,EAAQ,YAAa,GACtC,IAAkB,EAAQ,aAAc;CAE9C,OAAO,EAAE,OAAO;EACd,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;EACpB,WAAW;EACX,OAAO,EAAmB,SAAS;EACnC,QAAQ;EACR,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;EAC1B,kBAAkB,EAAe,SAAS;EAC1C,iBAAiB,EAAe,SAAS;CAC3C,CAAC;AACH;AAEA,IAAa,KAAsB,EAA0B"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ export type HistoryEntityKind = string;
3
+ export type HistoryTimestamp = number | string;
4
+ export declare const HistorySnapshotSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
5
+ export type HistorySnapshot = z.infer<typeof HistorySnapshotSchema>;
6
+ export declare const HistoryTimestampSchema: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
7
+ export declare const HistoryActorSchema: z.ZodObject<{
8
+ id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
9
+ label: z.ZodString;
10
+ }, z.core.$strip>;
11
+ export type HistoryActor = z.infer<typeof HistoryActorSchema>;
12
+ export interface HistoryRecord<TSnapshot extends HistorySnapshot = HistorySnapshot, TEntityKind extends HistoryEntityKind = HistoryEntityKind, TTimestamp extends HistoryTimestamp = HistoryTimestamp> {
13
+ id: string;
14
+ timestamp: TTimestamp;
15
+ actor: HistoryActor | null;
16
+ entity: TEntityKind;
17
+ entityId: string;
18
+ snapshotPrevious: TSnapshot | null;
19
+ snapshotCurrent: TSnapshot | null;
20
+ }
21
+ export type HistoryRecordSchemaOptions<TEntityKind extends HistoryEntityKind = HistoryEntityKind, TSnapshot extends HistorySnapshot = HistorySnapshot, TTimestamp extends HistoryTimestamp = HistoryTimestamp> = {
22
+ entityKind?: z.ZodType<TEntityKind>;
23
+ snapshot?: z.ZodType<TSnapshot>;
24
+ timestamp?: z.ZodType<TTimestamp>;
25
+ };
26
+ export declare function createHistoryRecordSchema<TEntityKind extends HistoryEntityKind = HistoryEntityKind, TSnapshot extends HistorySnapshot = HistorySnapshot, TTimestamp extends HistoryTimestamp = HistoryTimestamp>(options?: HistoryRecordSchemaOptions<TEntityKind, TSnapshot, TTimestamp>): z.ZodType<HistoryRecord<TSnapshot, TEntityKind, TTimestamp>>;
27
+ export declare const HistoryRecordSchema: z.ZodType<HistoryRecord<Record<string, unknown>, string, HistoryTimestamp>, unknown, z.core.$ZodTypeInternals<HistoryRecord<Record<string, unknown>, string, HistoryTimestamp>, unknown>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vireocodedev/history",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Framework-free entity history definitions, diff nodes, and transport-neutral record schemas for the vireocodedev starter product.",
5
5
  "type": "module",
6
6
  "sideEffects": false,