@revisium/schema-toolkit 0.19.1 → 0.19.2

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.
Files changed (33) hide show
  1. package/dist/{types-EHdxfQpd.d.cts → FormulaPathBuilder-8gmUFlgu.d.cts} +27 -2
  2. package/dist/{types-Dw9ba_YE.d.ts → FormulaPathBuilder-B6RyUFN7.d.ts} +27 -2
  3. package/dist/chunk-3FJZMVWA.js +3 -0
  4. package/dist/{chunk-Y2GYABV7.js.map → chunk-3FJZMVWA.js.map} +1 -1
  5. package/dist/{chunk-45UZ3CJN.js → chunk-3V7AYFDS.js} +313 -10
  6. package/dist/chunk-3V7AYFDS.js.map +1 -0
  7. package/dist/{chunk-U7N3EEQX.cjs → chunk-HDZCCAWA.cjs} +38 -313
  8. package/dist/chunk-HDZCCAWA.cjs.map +1 -0
  9. package/dist/chunk-L6HE7QPU.cjs +4 -0
  10. package/dist/{chunk-MLNKM67U.cjs.map → chunk-L6HE7QPU.cjs.map} +1 -1
  11. package/dist/{chunk-MKDGOOBV.cjs → chunk-OMSE2HGD.cjs} +373 -66
  12. package/dist/chunk-OMSE2HGD.cjs.map +1 -0
  13. package/dist/{chunk-R6VYCHY2.js → chunk-XL4R6PSM.js} +36 -308
  14. package/dist/chunk-XL4R6PSM.js.map +1 -0
  15. package/dist/core/index.cjs +70 -58
  16. package/dist/core/index.d.cts +2 -2
  17. package/dist/core/index.d.ts +2 -2
  18. package/dist/core/index.js +2 -2
  19. package/dist/index.cjs +115 -115
  20. package/dist/index.d.cts +2 -2
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +3 -3
  23. package/dist/model/index.cjs +58 -58
  24. package/dist/model/index.d.cts +4 -28
  25. package/dist/model/index.d.ts +4 -28
  26. package/dist/model/index.js +2 -2
  27. package/package.json +1 -1
  28. package/dist/chunk-45UZ3CJN.js.map +0 -1
  29. package/dist/chunk-MKDGOOBV.cjs.map +0 -1
  30. package/dist/chunk-MLNKM67U.cjs +0 -4
  31. package/dist/chunk-R6VYCHY2.js.map +0 -1
  32. package/dist/chunk-U7N3EEQX.cjs.map +0 -1
  33. package/dist/chunk-Y2GYABV7.js +0 -3
@@ -1,5 +1,6 @@
1
- import { ASTNode } from '@revisium/formula';
2
1
  import { h as JsonPatch } from './json-patch.types-Cu0Medki.cjs';
2
+ import { ASTNode } from '@revisium/formula';
3
+ import { X as XFormula } from './schema.types-B5OgKLpV.cjs';
3
4
 
4
5
  interface FormulaDependency {
5
6
  targetNodeId(): string;
@@ -172,4 +173,28 @@ interface ValidatorRule {
172
173
  }
173
174
  type ValidatorFactoryFn = () => Validator;
174
175
 
175
- export { type Diagnostic as D, EMPTY_METADATA as E, type FormulaDependency as F, type NodeType as N, type Path as P, ResolvedDependency as R, type SchemaLike as S, type TreeFormulaValidationError as T, type ValidationContext as V, type PathSegment as a, type DiagnosticSeverity as b, type Validator as c, type ValidatorRule as d, type ValidatorFactoryFn as e, type SchemaValidationError as f, type SchemaValidationErrorType as g, type NodeMetadata as h, type Formula as i, type SchemaNode as j, type SchemaTree as k, type SchemaPatch as l, type DefaultValueType as m, type PropertyChange as n, type PropertyName as o, type Formula$1 as p };
176
+ interface SerializeOptions {
177
+ readonly strict?: boolean;
178
+ }
179
+ declare class FormulaSerializer {
180
+ private readonly tree;
181
+ private readonly formulaNodeId;
182
+ private readonly formula;
183
+ private readonly pathBuilder;
184
+ constructor(tree: SchemaTree, formulaNodeId: string, formula: Formula$1);
185
+ static toXFormula(tree: SchemaTree, formulaNodeId: string, formula: Formula$1): XFormula;
186
+ static serializeExpression(tree: SchemaTree, formulaNodeId: string, formula: Formula$1, options?: SerializeOptions): string;
187
+ serialize(options?: SerializeOptions): string;
188
+ private buildPathReplacements;
189
+ private needsReplacement;
190
+ private normalizeArrayNotation;
191
+ }
192
+
193
+ declare class FormulaPathBuilder {
194
+ buildWithArrayNotation(fromPath: Path, toPath: Path): string;
195
+ private findCommonPrefixLength;
196
+ private buildPartsWithArrayNotation;
197
+ private formatPartsWithArrayNotation;
198
+ }
199
+
200
+ export { type Diagnostic as D, EMPTY_METADATA as E, type FormulaDependency as F, type NodeType as N, type Path as P, ResolvedDependency as R, type SchemaLike as S, type TreeFormulaValidationError as T, type ValidationContext as V, FormulaSerializer as a, FormulaPathBuilder as b, type PathSegment as c, type DiagnosticSeverity as d, type Validator as e, type ValidatorRule as f, type ValidatorFactoryFn as g, type SchemaValidationError as h, type SchemaValidationErrorType as i, type NodeMetadata as j, type Formula as k, type SchemaNode as l, type SchemaTree as m, type SchemaPatch as n, type DefaultValueType as o, type PropertyChange as p, type PropertyName as q, type Formula$1 as r };
@@ -1,5 +1,6 @@
1
- import { ASTNode } from '@revisium/formula';
2
1
  import { h as JsonPatch } from './json-patch.types-DY7k9hxy.js';
2
+ import { ASTNode } from '@revisium/formula';
3
+ import { X as XFormula } from './schema.types-B5OgKLpV.js';
3
4
 
4
5
  interface FormulaDependency {
5
6
  targetNodeId(): string;
@@ -172,4 +173,28 @@ interface ValidatorRule {
172
173
  }
173
174
  type ValidatorFactoryFn = () => Validator;
174
175
 
175
- export { type Diagnostic as D, EMPTY_METADATA as E, type FormulaDependency as F, type NodeType as N, type Path as P, ResolvedDependency as R, type SchemaLike as S, type TreeFormulaValidationError as T, type ValidationContext as V, type PathSegment as a, type DiagnosticSeverity as b, type Validator as c, type ValidatorRule as d, type ValidatorFactoryFn as e, type SchemaValidationError as f, type SchemaValidationErrorType as g, type NodeMetadata as h, type Formula as i, type SchemaNode as j, type SchemaTree as k, type SchemaPatch as l, type DefaultValueType as m, type PropertyChange as n, type PropertyName as o, type Formula$1 as p };
176
+ interface SerializeOptions {
177
+ readonly strict?: boolean;
178
+ }
179
+ declare class FormulaSerializer {
180
+ private readonly tree;
181
+ private readonly formulaNodeId;
182
+ private readonly formula;
183
+ private readonly pathBuilder;
184
+ constructor(tree: SchemaTree, formulaNodeId: string, formula: Formula$1);
185
+ static toXFormula(tree: SchemaTree, formulaNodeId: string, formula: Formula$1): XFormula;
186
+ static serializeExpression(tree: SchemaTree, formulaNodeId: string, formula: Formula$1, options?: SerializeOptions): string;
187
+ serialize(options?: SerializeOptions): string;
188
+ private buildPathReplacements;
189
+ private needsReplacement;
190
+ private normalizeArrayNotation;
191
+ }
192
+
193
+ declare class FormulaPathBuilder {
194
+ buildWithArrayNotation(fromPath: Path, toPath: Path): string;
195
+ private findCommonPrefixLength;
196
+ private buildPartsWithArrayNotation;
197
+ private formatPartsWithArrayNotation;
198
+ }
199
+
200
+ export { type Diagnostic as D, EMPTY_METADATA as E, type FormulaDependency as F, type NodeType as N, type Path as P, ResolvedDependency as R, type SchemaLike as S, type TreeFormulaValidationError as T, type ValidationContext as V, FormulaSerializer as a, FormulaPathBuilder as b, type PathSegment as c, type DiagnosticSeverity as d, type Validator as e, type ValidatorRule as f, type ValidatorFactoryFn as g, type SchemaValidationError as h, type SchemaValidationErrorType as i, type NodeMetadata as j, type Formula as k, type SchemaNode as l, type SchemaTree as m, type SchemaPatch as n, type DefaultValueType as o, type PropertyChange as p, type PropertyName as q, type Formula$1 as r };
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-3FJZMVWA.js.map
3
+ //# sourceMappingURL=chunk-3FJZMVWA.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-Y2GYABV7.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-3FJZMVWA.js"}
@@ -1,7 +1,306 @@
1
- import { AbstractBasePath, ParsedFormula, createRefNode, createObjectNode, createArrayNode, createStringNode, createNumberNode, createBooleanNode, makeAutoObservable, observable, makeObservable, runInAction, PatchBuilder, SchemaSerializer, FormulaDependencyIndex, createSchemaTree, NULL_NODE, FormulaSerializer, validateSchema, validateFormulas } from './chunk-R6VYCHY2.js';
1
+ import { AbstractBasePath, EMPTY_PATH, FormulaError, ResolvedDependency, FormulaSerializer, createRefNode, createObjectNode, createArrayNode, createStringNode, createNumberNode, createBooleanNode, makeAutoObservable, observable, makeObservable, runInAction, PatchBuilder, SchemaSerializer, createSchemaTree, NULL_NODE, validateSchema, validateFormulas } from './chunk-XL4R6PSM.js';
2
2
  import { obj, ref } from './chunk-R4CFU33U.js';
3
3
  import { nanoid } from 'nanoid';
4
+ import { parseFormula } from '@revisium/formula';
4
5
 
6
+ var ARRAY_NOTATION_REGEX = /^([^[]+)\[(?:\d+|\*)?\]$/;
7
+ var FormulaPath = class {
8
+ constructor(basePath, relativePath) {
9
+ this.basePath = basePath;
10
+ this.relativePath = relativePath;
11
+ }
12
+ resolve() {
13
+ let ast;
14
+ try {
15
+ const parseResult = parseFormula(this.relativePath);
16
+ ast = parseResult.ast;
17
+ } catch {
18
+ return null;
19
+ }
20
+ return this.astToPath(ast, this.basePath);
21
+ }
22
+ astToPath(ast, base) {
23
+ switch (ast.type) {
24
+ case "Identifier":
25
+ return base.child(ast.name);
26
+ case "MemberExpression": {
27
+ const objectPath = this.astToPath(ast.object, base);
28
+ if (!objectPath) {
29
+ return null;
30
+ }
31
+ return objectPath.child(ast.property);
32
+ }
33
+ case "IndexExpression":
34
+ case "WildcardExpression": {
35
+ const objectPath = this.astToPath(ast.object, base);
36
+ if (!objectPath) {
37
+ return null;
38
+ }
39
+ return objectPath.childItems();
40
+ }
41
+ case "RelativePath":
42
+ return this.resolveRelativePathString(base, ast.path);
43
+ case "RootPath":
44
+ return this.resolveRootPath(ast.path);
45
+ default:
46
+ return null;
47
+ }
48
+ }
49
+ resolveRelativePathString(base, path) {
50
+ const parts = path.split("/");
51
+ let result = base;
52
+ for (const part of parts) {
53
+ if (part === "..") {
54
+ if (result.isEmpty()) {
55
+ return null;
56
+ }
57
+ result = result.parent();
58
+ } else if (part === ".") {
59
+ continue;
60
+ } else if (part) {
61
+ result = result.child(part);
62
+ }
63
+ }
64
+ return result;
65
+ }
66
+ resolveRootPath(rootPath) {
67
+ const path = rootPath.startsWith("/") ? rootPath.slice(1) : rootPath;
68
+ if (!path) {
69
+ return EMPTY_PATH;
70
+ }
71
+ try {
72
+ return this.parseFormulaPath(path);
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+ parseFormulaPath(formulaPath) {
78
+ const parts = formulaPath.split(".");
79
+ let result = EMPTY_PATH;
80
+ for (const part of parts) {
81
+ if (!part) {
82
+ throw new Error(`Invalid path: empty segment`);
83
+ }
84
+ const match = ARRAY_NOTATION_REGEX.exec(part);
85
+ if (match?.[1]) {
86
+ result = result.child(match[1]).childItems();
87
+ } else {
88
+ result = result.child(part);
89
+ }
90
+ }
91
+ return result;
92
+ }
93
+ };
94
+
95
+ // src/model/schema-formula/parsing/ParsedFormula.ts
96
+ var ParsedFormula = class {
97
+ _expression;
98
+ astNode;
99
+ deps;
100
+ astPathToNodeId;
101
+ constructor(tree, formulaNodeId, expression) {
102
+ this._expression = expression;
103
+ const parseResult = parseFormula(expression);
104
+ this.astNode = parseResult.ast;
105
+ const formulaPath = tree.pathOf(formulaNodeId);
106
+ if (formulaPath.isEmpty() && tree.root().id() !== formulaNodeId) {
107
+ throw new FormulaError("Formula node not found in tree", formulaNodeId);
108
+ }
109
+ const deps = [];
110
+ const astPathToNodeId = /* @__PURE__ */ new Map();
111
+ for (const depPath of parseResult.dependencies) {
112
+ const targetNodeId = this.resolveDependencyPath(
113
+ tree,
114
+ formulaPath,
115
+ depPath
116
+ );
117
+ if (!targetNodeId) {
118
+ throw new FormulaError(
119
+ `Cannot resolve formula dependency: ${depPath}`,
120
+ formulaNodeId,
121
+ "Path not found in schema"
122
+ );
123
+ }
124
+ if (targetNodeId === formulaNodeId) {
125
+ throw new FormulaError(
126
+ "Formula cannot reference itself",
127
+ formulaNodeId,
128
+ "Self-reference detected"
129
+ );
130
+ }
131
+ deps.push(new ResolvedDependency(targetNodeId));
132
+ astPathToNodeId.set(depPath, targetNodeId);
133
+ }
134
+ this.deps = deps;
135
+ this.astPathToNodeId = astPathToNodeId;
136
+ }
137
+ version() {
138
+ return 1;
139
+ }
140
+ expression() {
141
+ return this._expression;
142
+ }
143
+ ast() {
144
+ return this.astNode;
145
+ }
146
+ dependencies() {
147
+ return this.deps;
148
+ }
149
+ getNodeIdForAstPath(astPath) {
150
+ return this.astPathToNodeId.get(astPath) ?? null;
151
+ }
152
+ astPaths() {
153
+ return Array.from(this.astPathToNodeId.keys());
154
+ }
155
+ resolveDependencyPath(tree, formulaNodePath, depPath) {
156
+ const basePath = this.getFormulaBasePath(formulaNodePath);
157
+ const depFormulaPath = new FormulaPath(basePath, depPath);
158
+ const targetPath = depFormulaPath.resolve();
159
+ if (!targetPath) {
160
+ return null;
161
+ }
162
+ const targetNode = tree.nodeAt(targetPath);
163
+ if (targetNode.isNull()) {
164
+ return null;
165
+ }
166
+ return targetNode.id();
167
+ }
168
+ getFormulaBasePath(formulaPath) {
169
+ let basePath = formulaPath;
170
+ while (!basePath.isEmpty()) {
171
+ const segs = basePath.segments();
172
+ const lastSeg = segs[segs.length - 1];
173
+ basePath = basePath.parent();
174
+ if (!lastSeg?.isItems()) {
175
+ break;
176
+ }
177
+ }
178
+ return basePath;
179
+ }
180
+ };
181
+
182
+ // src/model/schema-formula/store/FormulaDependencyIndex.ts
183
+ var FormulaDependencyIndex = class {
184
+ dependentsMap = /* @__PURE__ */ new Map();
185
+ formulasByNodeId = /* @__PURE__ */ new Map();
186
+ registerFormula(formulaNodeId, formula) {
187
+ this.unregisterFormula(formulaNodeId);
188
+ this.formulasByNodeId.set(formulaNodeId, formula);
189
+ for (const dep of formula.dependencies()) {
190
+ const targetId = dep.targetNodeId();
191
+ let dependents = this.dependentsMap.get(targetId);
192
+ if (!dependents) {
193
+ dependents = /* @__PURE__ */ new Set();
194
+ this.dependentsMap.set(targetId, dependents);
195
+ }
196
+ dependents.add(formulaNodeId);
197
+ }
198
+ }
199
+ unregisterFormula(formulaNodeId) {
200
+ this.formulasByNodeId.delete(formulaNodeId);
201
+ for (const [targetId, dependents] of this.dependentsMap) {
202
+ dependents.delete(formulaNodeId);
203
+ if (dependents.size === 0) {
204
+ this.dependentsMap.delete(targetId);
205
+ }
206
+ }
207
+ }
208
+ getDependents(nodeId) {
209
+ const dependents = this.dependentsMap.get(nodeId);
210
+ return dependents ? Array.from(dependents) : [];
211
+ }
212
+ hasDependents(nodeId) {
213
+ const dependents = this.dependentsMap.get(nodeId);
214
+ return dependents !== void 0 && dependents.size > 0;
215
+ }
216
+ getFormula(nodeId) {
217
+ return this.formulasByNodeId.get(nodeId) ?? null;
218
+ }
219
+ hasFormula(nodeId) {
220
+ return this.formulasByNodeId.has(nodeId);
221
+ }
222
+ clear() {
223
+ this.dependentsMap.clear();
224
+ this.formulasByNodeId.clear();
225
+ }
226
+ forEachFormula(callback) {
227
+ for (const [nodeId, formula] of this.formulasByNodeId) {
228
+ callback(nodeId, formula);
229
+ }
230
+ }
231
+ size() {
232
+ return this.formulasByNodeId.size;
233
+ }
234
+ };
235
+
236
+ // src/model/schema-formula/changes/FormulaChangeDetector.ts
237
+ var FormulaChangeDetector = class {
238
+ constructor(index, currentTree, baseTree) {
239
+ this.index = index;
240
+ this.currentTree = currentTree;
241
+ this.baseTree = baseTree;
242
+ }
243
+ detectIndirectChanges(changedNodeIds) {
244
+ const result = [];
245
+ const visited = /* @__PURE__ */ new Set();
246
+ for (const changedId of changedNodeIds) {
247
+ this.collectDependentChanges(changedId, result, visited, changedNodeIds);
248
+ }
249
+ return result;
250
+ }
251
+ collectDependentChanges(nodeId, result, visited, directlyChanged) {
252
+ const dependents = this.index.getDependents(nodeId);
253
+ for (const dependentId of dependents) {
254
+ if (visited.has(dependentId)) {
255
+ continue;
256
+ }
257
+ visited.add(dependentId);
258
+ if (directlyChanged.has(dependentId)) {
259
+ continue;
260
+ }
261
+ const change = this.detectFormulaChange(dependentId);
262
+ if (change) {
263
+ result.push(change);
264
+ }
265
+ this.collectDependentChanges(dependentId, result, visited, directlyChanged);
266
+ }
267
+ }
268
+ detectFormulaChange(nodeId) {
269
+ const currentNode = this.currentTree.nodeById(nodeId);
270
+ const baseNode = this.baseTree.nodeById(nodeId);
271
+ if (currentNode.isNull() || baseNode.isNull()) {
272
+ return null;
273
+ }
274
+ const currentFormula = currentNode.formula();
275
+ const baseFormula = baseNode.formula();
276
+ if (!currentFormula || !baseFormula) {
277
+ return null;
278
+ }
279
+ const fromExpression = this.getSerializedExpression(baseFormula, this.baseTree, nodeId);
280
+ const toExpression = this.getSerializedExpression(currentFormula, this.currentTree, nodeId);
281
+ if (fromExpression === null || toExpression === null) {
282
+ return null;
283
+ }
284
+ if (fromExpression === toExpression) {
285
+ return null;
286
+ }
287
+ return {
288
+ nodeId,
289
+ fromExpression,
290
+ toExpression
291
+ };
292
+ }
293
+ getSerializedExpression(formula, tree, nodeId) {
294
+ try {
295
+ const xFormula = FormulaSerializer.toXFormula(tree, nodeId, formula);
296
+ return xFormula.expression;
297
+ } catch {
298
+ return null;
299
+ }
300
+ }
301
+ };
302
+
303
+ // src/model/schema-model/SchemaParser.ts
5
304
  var SchemaParser = class {
6
305
  pendingFormulas = [];
7
306
  _parseErrors = [];
@@ -713,12 +1012,16 @@ var SchemaModelImpl = class {
713
1012
  if (!formula) {
714
1013
  return "";
715
1014
  }
716
- return FormulaSerializer.serializeExpression(
717
- this._currentTree,
718
- nodeId,
719
- formula,
720
- { strict: false }
721
- );
1015
+ try {
1016
+ return FormulaSerializer.serializeExpression(
1017
+ this._currentTree,
1018
+ nodeId,
1019
+ formula,
1020
+ { strict: false }
1021
+ );
1022
+ } catch {
1023
+ return "";
1024
+ }
722
1025
  }
723
1026
  get validationErrors() {
724
1027
  return validateSchema(this._currentTree.root());
@@ -2469,6 +2772,6 @@ function createDataModel(options) {
2469
2772
  return new DataModelImpl(options);
2470
2773
  }
2471
2774
 
2472
- export { ArrayToItemsTypeTransformer, ArrayValueNode, BasePrimitiveValueNode, BaseValueNode, BooleanValueNode, DataModelImpl, DefaultTransformer, ForeignKeyNotFoundError, ForeignKeyResolverImpl, ForeignKeyResolverNotConfiguredError, ForeignKeyValueNodeImpl, NodeFactory, NodeFactory2, NodeFactoryRegistry, NumberValueNode, ObjectToArrayTransformer, ObjectValueNode, PrimitiveToArrayTransformer, RefTransformer, RowModelImpl, SchemaParser, StringValueNode, TableModelImpl, TypeTransformChain, ValueType, createDataModel, createDefaultRegistry, createForeignKeyResolver, createNodeFactory, createSchemaModel, createTableModel, createTypeTransformChain, extractFormulaDefinition, generateDefaultValue, generateNodeId, isForeignKeyValueNode, resetNodeIdCounter };
2473
- //# sourceMappingURL=chunk-45UZ3CJN.js.map
2474
- //# sourceMappingURL=chunk-45UZ3CJN.js.map
2775
+ export { ArrayToItemsTypeTransformer, ArrayValueNode, BasePrimitiveValueNode, BaseValueNode, BooleanValueNode, DataModelImpl, DefaultTransformer, ForeignKeyNotFoundError, ForeignKeyResolverImpl, ForeignKeyResolverNotConfiguredError, ForeignKeyValueNodeImpl, FormulaChangeDetector, FormulaDependencyIndex, FormulaPath, NodeFactory, NodeFactory2, NodeFactoryRegistry, NumberValueNode, ObjectToArrayTransformer, ObjectValueNode, ParsedFormula, PrimitiveToArrayTransformer, RefTransformer, RowModelImpl, SchemaParser, StringValueNode, TableModelImpl, TypeTransformChain, ValueType, createDataModel, createDefaultRegistry, createForeignKeyResolver, createNodeFactory, createSchemaModel, createTableModel, createTypeTransformChain, extractFormulaDefinition, generateDefaultValue, generateNodeId, isForeignKeyValueNode, resetNodeIdCounter };
2776
+ //# sourceMappingURL=chunk-3V7AYFDS.js.map
2777
+ //# sourceMappingURL=chunk-3V7AYFDS.js.map