@revisium/schema-toolkit 0.15.0 → 0.16.0

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,10 @@
1
+ import { b as SchemaNode, S as SchemaValidationError, c as SchemaTree, F as FormulaValidationError } from './types-DMzUCve0.cjs';
2
+
3
+ declare function validateSchema(root: SchemaNode): SchemaValidationError[];
4
+
5
+ declare const FIELD_NAME_ERROR_MESSAGE = "Must start with a letter or underscore, cannot start with __, and can only include letters, numbers, hyphens, and underscores (max 64 chars)";
6
+ declare function isValidFieldName(name: string): boolean;
7
+
8
+ declare function validateFormulas(tree: SchemaTree): FormulaValidationError[];
9
+
10
+ export { FIELD_NAME_ERROR_MESSAGE as F, validateFormulas as a, isValidFieldName as i, validateSchema as v };
@@ -0,0 +1,10 @@
1
+ import { b as SchemaNode, S as SchemaValidationError, c as SchemaTree, F as FormulaValidationError } from './types-Cnfj5nLO.js';
2
+
3
+ declare function validateSchema(root: SchemaNode): SchemaValidationError[];
4
+
5
+ declare const FIELD_NAME_ERROR_MESSAGE = "Must start with a letter or underscore, cannot start with __, and can only include letters, numbers, hyphens, and underscores (max 64 chars)";
6
+ declare function isValidFieldName(name: string): boolean;
7
+
8
+ declare function validateFormulas(tree: SchemaTree): FormulaValidationError[];
9
+
10
+ export { FIELD_NAME_ERROR_MESSAGE as F, validateFormulas as a, isValidFieldName as i, validateSchema as v };
@@ -70,6 +70,9 @@ var NullNodeImpl = class {
70
70
  removeChild(_name) {
71
71
  return false;
72
72
  }
73
+ replaceChild(_name, _node) {
74
+ return false;
75
+ }
73
76
  setItems(_node) {
74
77
  }
75
78
  setDefaultValue(_value) {
@@ -149,6 +152,9 @@ var BaseNode = class {
149
152
  removeChild(_name) {
150
153
  return false;
151
154
  }
155
+ replaceChild(_name, _node) {
156
+ return false;
157
+ }
152
158
  setItems(_node) {
153
159
  }
154
160
  setDefaultValue(_value) {
@@ -197,6 +203,14 @@ var ObjectNode = class _ObjectNode extends BaseNode {
197
203
  this._children.splice(index, 1);
198
204
  return true;
199
205
  }
206
+ replaceChild(name, node) {
207
+ const index = this._children.findIndex((child) => child.name() === name);
208
+ if (index === -1) {
209
+ return false;
210
+ }
211
+ this._children[index] = node;
212
+ return true;
213
+ }
200
214
  };
201
215
  function createObjectNode(id, name, children = [], metadata = EMPTY_METADATA) {
202
216
  return new ObjectNode(id, name, children, metadata);
@@ -563,14 +577,15 @@ var TreeNodeIndex = class {
563
577
 
564
578
  // src/core/schema-tree/SchemaTreeImpl.ts
565
579
  var SchemaTreeImpl = class _SchemaTreeImpl {
580
+ index = new TreeNodeIndex();
581
+ _replacements = /* @__PURE__ */ new Map();
582
+ _rootNode;
566
583
  constructor(rootNode) {
567
- this.rootNode = rootNode;
584
+ this._rootNode = rootNode;
568
585
  this.index.rebuild(rootNode);
569
586
  }
570
- index = new TreeNodeIndex();
571
- _replacements = /* @__PURE__ */ new Map();
572
587
  root() {
573
- return this.rootNode;
588
+ return this._rootNode;
574
589
  }
575
590
  nodeById(id) {
576
591
  return this.index.getNode(id);
@@ -580,9 +595,9 @@ var SchemaTreeImpl = class _SchemaTreeImpl {
580
595
  }
581
596
  nodeAt(path) {
582
597
  if (path.isEmpty()) {
583
- return this.rootNode;
598
+ return this._rootNode;
584
599
  }
585
- let current = this.rootNode;
600
+ let current = this._rootNode;
586
601
  for (const segment of path.segments()) {
587
602
  if (current.isNull()) {
588
603
  return NULL_NODE;
@@ -602,7 +617,7 @@ var SchemaTreeImpl = class _SchemaTreeImpl {
602
617
  return this.index.countNodes();
603
618
  }
604
619
  clone() {
605
- const cloned = new _SchemaTreeImpl(this.rootNode.clone());
620
+ const cloned = new _SchemaTreeImpl(this._rootNode.clone());
606
621
  for (const [oldId, newId] of this._replacements) {
607
622
  cloned._replacements.set(oldId, newId);
608
623
  }
@@ -700,14 +715,18 @@ var SchemaTreeImpl = class _SchemaTreeImpl {
700
715
  if (lastSegment.isItems()) {
701
716
  parent.setItems(node);
702
717
  } else {
703
- parent.removeChild(lastSegment.propertyName());
704
- node.setName(lastSegment.propertyName());
705
- parent.addChild(node);
718
+ const propertyName = lastSegment.propertyName();
719
+ node.setName(propertyName);
720
+ parent.replaceChild(propertyName, node);
706
721
  }
707
722
  this.rebuildIndex();
708
723
  }
724
+ replaceRoot(newRoot) {
725
+ this._rootNode = newRoot;
726
+ this.rebuildIndex();
727
+ }
709
728
  rebuildIndex() {
710
- this.index.rebuild(this.rootNode);
729
+ this.index.rebuild(this._rootNode);
711
730
  }
712
731
  };
713
732
  function createSchemaTree(root) {
@@ -2144,36 +2163,459 @@ var PatchBuilder = class {
2144
2163
  }
2145
2164
  };
2146
2165
 
2166
+ // src/core/validation/ValidatorRegistry.ts
2167
+ var ValidatorRegistry = class {
2168
+ validators = /* @__PURE__ */ new Map();
2169
+ rules = [];
2170
+ register(type, factory) {
2171
+ this.validators.set(type, factory);
2172
+ return this;
2173
+ }
2174
+ addRule(rule) {
2175
+ this.rules.push(rule);
2176
+ return this;
2177
+ }
2178
+ get(type) {
2179
+ const factory = this.validators.get(type);
2180
+ return factory ? factory() : void 0;
2181
+ }
2182
+ has(type) {
2183
+ return this.validators.has(type);
2184
+ }
2185
+ getRules() {
2186
+ return this.rules;
2187
+ }
2188
+ getValidatorTypes() {
2189
+ return Array.from(this.validators.keys());
2190
+ }
2191
+ };
2192
+
2193
+ // src/core/validation/ValidatorResolver.ts
2194
+ var ValidatorResolver = class {
2195
+ constructor(registry) {
2196
+ this.registry = registry;
2197
+ }
2198
+ resolve(context) {
2199
+ const validators = [];
2200
+ const rules = this.registry.getRules();
2201
+ for (const rule of rules) {
2202
+ if (rule.shouldApply(context)) {
2203
+ const validator = this.registry.get(rule.validatorType);
2204
+ if (validator) {
2205
+ validators.push(validator);
2206
+ }
2207
+ }
2208
+ }
2209
+ return validators;
2210
+ }
2211
+ };
2212
+
2213
+ // src/core/validation/ValidationEngine.ts
2214
+ var ValidationEngine = class {
2215
+ constructor(resolver) {
2216
+ this.resolver = resolver;
2217
+ }
2218
+ validate(context) {
2219
+ const validators = this.resolver.resolve(context);
2220
+ const diagnostics = [];
2221
+ for (const validator of validators) {
2222
+ const diagnostic = validator.validate(context);
2223
+ if (diagnostic) {
2224
+ diagnostics.push(diagnostic);
2225
+ }
2226
+ }
2227
+ return diagnostics;
2228
+ }
2229
+ };
2230
+
2231
+ // src/core/validation/rules/SchemaBasedRule.ts
2232
+ var SchemaPropertyRule = class {
2233
+ constructor(validatorType, propertyName) {
2234
+ this.validatorType = validatorType;
2235
+ this.propertyName = propertyName;
2236
+ }
2237
+ shouldApply(context) {
2238
+ const value = context.schema[this.propertyName];
2239
+ return value !== void 0 && value !== null;
2240
+ }
2241
+ };
2242
+ var SchemaTruthyRule = class {
2243
+ constructor(validatorType, propertyName) {
2244
+ this.validatorType = validatorType;
2245
+ this.propertyName = propertyName;
2246
+ }
2247
+ shouldApply(context) {
2248
+ return context.schema[this.propertyName] === true;
2249
+ }
2250
+ };
2251
+ var CompositeRule = class {
2252
+ constructor(validatorType, conditions) {
2253
+ this.validatorType = validatorType;
2254
+ this.conditions = conditions;
2255
+ }
2256
+ shouldApply(context) {
2257
+ return this.conditions.every((condition) => condition(context));
2258
+ }
2259
+ };
2260
+
2261
+ // src/core/validation/validators/RequiredValidator.ts
2262
+ var RequiredValidator = class {
2263
+ type = "required";
2264
+ validate(context) {
2265
+ const { value, nodeName } = context;
2266
+ if (value === "" || value === null || value === void 0) {
2267
+ return {
2268
+ severity: "error",
2269
+ type: this.type,
2270
+ message: "Field is required",
2271
+ path: nodeName
2272
+ };
2273
+ }
2274
+ return null;
2275
+ }
2276
+ };
2277
+
2278
+ // src/core/validation/validators/PatternValidator.ts
2279
+ var PatternValidator = class {
2280
+ type = "pattern";
2281
+ validate(context) {
2282
+ const { value, schema, nodeName } = context;
2283
+ const pattern = schema.pattern;
2284
+ if (!pattern) {
2285
+ return null;
2286
+ }
2287
+ if (typeof value !== "string") {
2288
+ return null;
2289
+ }
2290
+ if (value.length === 0) {
2291
+ return null;
2292
+ }
2293
+ try {
2294
+ if (!new RegExp(pattern).test(value)) {
2295
+ return {
2296
+ severity: "error",
2297
+ type: this.type,
2298
+ message: "Value does not match pattern",
2299
+ path: nodeName,
2300
+ params: { pattern }
2301
+ };
2302
+ }
2303
+ } catch {
2304
+ return {
2305
+ severity: "error",
2306
+ type: "invalidPattern",
2307
+ message: "Invalid regex pattern in schema",
2308
+ path: nodeName,
2309
+ params: { pattern }
2310
+ };
2311
+ }
2312
+ return null;
2313
+ }
2314
+ };
2315
+
2316
+ // src/core/validation/validators/MinLengthValidator.ts
2317
+ var MinLengthValidator = class {
2318
+ type = "minLength";
2319
+ validate(context) {
2320
+ const { value, schema, nodeName } = context;
2321
+ const minLength = schema.minLength;
2322
+ if (minLength === void 0) {
2323
+ return null;
2324
+ }
2325
+ if (typeof value !== "string") {
2326
+ return null;
2327
+ }
2328
+ if (value.length < minLength) {
2329
+ return {
2330
+ severity: "error",
2331
+ type: this.type,
2332
+ message: `Value must be at least ${minLength} characters`,
2333
+ path: nodeName,
2334
+ params: { min: minLength, actual: value.length }
2335
+ };
2336
+ }
2337
+ return null;
2338
+ }
2339
+ };
2340
+
2341
+ // src/core/validation/validators/MaxLengthValidator.ts
2342
+ var MaxLengthValidator = class {
2343
+ type = "maxLength";
2344
+ validate(context) {
2345
+ const { value, schema, nodeName } = context;
2346
+ const maxLength = schema.maxLength;
2347
+ if (maxLength === void 0) {
2348
+ return null;
2349
+ }
2350
+ if (typeof value !== "string") {
2351
+ return null;
2352
+ }
2353
+ if (value.length > maxLength) {
2354
+ return {
2355
+ severity: "error",
2356
+ type: this.type,
2357
+ message: `Value must be at most ${maxLength} characters`,
2358
+ path: nodeName,
2359
+ params: { max: maxLength, actual: value.length }
2360
+ };
2361
+ }
2362
+ return null;
2363
+ }
2364
+ };
2365
+
2366
+ // src/core/validation/validators/MinimumValidator.ts
2367
+ var MinimumValidator = class {
2368
+ type = "minimum";
2369
+ validate(context) {
2370
+ const { value, schema, nodeName } = context;
2371
+ const minimum = schema.minimum;
2372
+ if (minimum === void 0) {
2373
+ return null;
2374
+ }
2375
+ if (typeof value !== "number") {
2376
+ return null;
2377
+ }
2378
+ if (value < minimum) {
2379
+ return {
2380
+ severity: "error",
2381
+ type: this.type,
2382
+ message: `Value must be at least ${minimum}`,
2383
+ path: nodeName,
2384
+ params: { min: minimum, actual: value }
2385
+ };
2386
+ }
2387
+ return null;
2388
+ }
2389
+ };
2390
+
2391
+ // src/core/validation/validators/MaximumValidator.ts
2392
+ var MaximumValidator = class {
2393
+ type = "maximum";
2394
+ validate(context) {
2395
+ const { value, schema, nodeName } = context;
2396
+ const maximum = schema.maximum;
2397
+ if (maximum === void 0) {
2398
+ return null;
2399
+ }
2400
+ if (typeof value !== "number") {
2401
+ return null;
2402
+ }
2403
+ if (value > maximum) {
2404
+ return {
2405
+ severity: "error",
2406
+ type: this.type,
2407
+ message: `Value must be at most ${maximum}`,
2408
+ path: nodeName,
2409
+ params: { max: maximum, actual: value }
2410
+ };
2411
+ }
2412
+ return null;
2413
+ }
2414
+ };
2415
+
2416
+ // src/core/validation/validators/EnumValidator.ts
2417
+ var EnumValidator = class {
2418
+ type = "enum";
2419
+ validate(context) {
2420
+ const { value, schema, nodeName } = context;
2421
+ const enumValues = schema.enum;
2422
+ if (!enumValues || enumValues.length === 0) {
2423
+ return null;
2424
+ }
2425
+ if (!enumValues.includes(value)) {
2426
+ return {
2427
+ severity: "error",
2428
+ type: this.type,
2429
+ message: "Value must be one of the allowed values",
2430
+ path: nodeName,
2431
+ params: { allowed: [...enumValues], actual: value }
2432
+ };
2433
+ }
2434
+ return null;
2435
+ }
2436
+ };
2437
+
2438
+ // src/core/validation/validators/ForeignKeyValidator.ts
2439
+ var ForeignKeyValidator = class {
2440
+ type = "foreignKey";
2441
+ validate(context) {
2442
+ const { value, schema, nodeName } = context;
2443
+ const foreignKey = schema.foreignKey;
2444
+ if (!foreignKey) {
2445
+ return null;
2446
+ }
2447
+ if (value === "" || value === null || value === void 0) {
2448
+ return {
2449
+ severity: "error",
2450
+ type: this.type,
2451
+ message: "Foreign key reference is required",
2452
+ path: nodeName,
2453
+ params: { table: foreignKey }
2454
+ };
2455
+ }
2456
+ return null;
2457
+ }
2458
+ };
2459
+
2460
+ // src/core/validation/createValidationEngine.ts
2461
+ function createDefaultValidatorRegistry() {
2462
+ const registry = new ValidatorRegistry();
2463
+ registry.register("required", () => new RequiredValidator()).register("pattern", () => new PatternValidator()).register("minLength", () => new MinLengthValidator()).register("maxLength", () => new MaxLengthValidator()).register("minimum", () => new MinimumValidator()).register("maximum", () => new MaximumValidator()).register("enum", () => new EnumValidator()).register("foreignKey", () => new ForeignKeyValidator());
2464
+ registry.addRule(new SchemaTruthyRule("required", "required")).addRule(new SchemaPropertyRule("pattern", "pattern")).addRule(new SchemaPropertyRule("minLength", "minLength")).addRule(new SchemaPropertyRule("maxLength", "maxLength")).addRule(new SchemaPropertyRule("minimum", "minimum")).addRule(new SchemaPropertyRule("maximum", "maximum")).addRule(new SchemaPropertyRule("enum", "enum")).addRule(new SchemaPropertyRule("foreignKey", "foreignKey"));
2465
+ return registry;
2466
+ }
2467
+ function createValidationEngine(registry) {
2468
+ const validatorRegistry = registry ?? createDefaultValidatorRegistry();
2469
+ const resolver = new ValidatorResolver(validatorRegistry);
2470
+ return new ValidationEngine(resolver);
2471
+ }
2472
+
2473
+ // src/core/validation/schema/FieldNameValidator.ts
2474
+ var FIELD_NAME_PATTERN = /^(?!__)[a-zA-Z_][a-zA-Z0-9-_]*$/;
2475
+ var FIELD_NAME_MAX_LENGTH = 64;
2476
+ var FIELD_NAME_ERROR_MESSAGE = "Must start with a letter or underscore, cannot start with __, and can only include letters, numbers, hyphens, and underscores (max 64 chars)";
2477
+ function isValidFieldName(name) {
2478
+ if (name.length === 0 || name.length > FIELD_NAME_MAX_LENGTH) {
2479
+ return false;
2480
+ }
2481
+ return FIELD_NAME_PATTERN.test(name);
2482
+ }
2483
+
2484
+ // src/core/validation/schema/SchemaValidator.ts
2485
+ function validateSchema(root) {
2486
+ const errors = [];
2487
+ collectValidationErrors(root, errors);
2488
+ return errors;
2489
+ }
2490
+ function collectValidationErrors(node, errors) {
2491
+ if (node.isNull()) {
2492
+ return;
2493
+ }
2494
+ if (node.isObject()) {
2495
+ const children = node.properties();
2496
+ const nameSet = /* @__PURE__ */ new Set();
2497
+ for (const child of children) {
2498
+ const childName = child.name();
2499
+ if (childName === "") {
2500
+ errors.push(createError(child.id(), "empty-name", "Field name cannot be empty"));
2501
+ } else if (nameSet.has(childName)) {
2502
+ errors.push(
2503
+ createError(child.id(), "duplicate-name", `Duplicate field name: ${childName}`)
2504
+ );
2505
+ } else if (!isValidFieldName(childName)) {
2506
+ errors.push(createError(child.id(), "invalid-name", FIELD_NAME_ERROR_MESSAGE));
2507
+ }
2508
+ nameSet.add(childName);
2509
+ collectValidationErrors(child, errors);
2510
+ }
2511
+ } else if (node.isArray()) {
2512
+ collectValidationErrors(node.items(), errors);
2513
+ }
2514
+ }
2515
+ function createError(nodeId, type, message) {
2516
+ return { nodeId, type, message };
2517
+ }
2518
+
2519
+ // src/core/validation/formula/FormulaValidator.ts
2520
+ function validateFormulas(tree) {
2521
+ const errors = [];
2522
+ collectFormulaErrors(tree.root(), tree, errors, "");
2523
+ return errors;
2524
+ }
2525
+ function collectFormulaErrors(node, tree, errors, fieldPath) {
2526
+ if (node.isNull()) {
2527
+ return;
2528
+ }
2529
+ validateNodeFormula(node, tree, errors, fieldPath);
2530
+ collectChildErrors(node, tree, errors, fieldPath);
2531
+ }
2532
+ function validateNodeFormula(node, tree, errors, fieldPath) {
2533
+ if (!node.isPrimitive() || !node.hasFormula()) {
2534
+ return;
2535
+ }
2536
+ const formula = node.formula();
2537
+ if (!formula) {
2538
+ return;
2539
+ }
2540
+ for (const dep of formula.dependencies()) {
2541
+ const targetNode = tree.nodeById(dep.targetNodeId());
2542
+ if (targetNode.isNull()) {
2543
+ errors.push({
2544
+ nodeId: node.id(),
2545
+ message: "Cannot resolve formula dependency: target node not found",
2546
+ fieldPath: fieldPath || node.name()
2547
+ });
2548
+ }
2549
+ }
2550
+ }
2551
+ function collectChildErrors(node, tree, errors, fieldPath) {
2552
+ if (node.isObject()) {
2553
+ for (const child of node.properties()) {
2554
+ const childPath = buildChildPath(fieldPath, child.name());
2555
+ collectFormulaErrors(child, tree, errors, childPath);
2556
+ }
2557
+ } else if (node.isArray()) {
2558
+ const itemsPath = buildArrayItemsPath(fieldPath);
2559
+ collectFormulaErrors(node.items(), tree, errors, itemsPath);
2560
+ }
2561
+ }
2562
+ function buildChildPath(parentPath, childName) {
2563
+ return parentPath ? `${parentPath}.${childName}` : childName;
2564
+ }
2565
+ function buildArrayItemsPath(parentPath) {
2566
+ return parentPath ? `${parentPath}[*]` : "[*]";
2567
+ }
2568
+
2147
2569
  exports.AbstractBasePath = AbstractBasePath;
2148
2570
  exports.ChangeCoalescer = ChangeCoalescer;
2149
2571
  exports.ChangeCollector = ChangeCollector;
2572
+ exports.CompositeRule = CompositeRule;
2150
2573
  exports.EMPTY_METADATA = EMPTY_METADATA;
2151
2574
  exports.EMPTY_PATH = EMPTY_PATH;
2575
+ exports.EnumValidator = EnumValidator;
2576
+ exports.FIELD_NAME_ERROR_MESSAGE = FIELD_NAME_ERROR_MESSAGE;
2577
+ exports.ForeignKeyValidator = ForeignKeyValidator;
2152
2578
  exports.FormulaDependencyIndex = FormulaDependencyIndex;
2153
2579
  exports.ItemsSegment = ItemsSegment;
2580
+ exports.MaxLengthValidator = MaxLengthValidator;
2581
+ exports.MaximumValidator = MaximumValidator;
2582
+ exports.MinLengthValidator = MinLengthValidator;
2583
+ exports.MinimumValidator = MinimumValidator;
2154
2584
  exports.NULL_NODE = NULL_NODE;
2155
2585
  exports.NodePathIndex = NodePathIndex;
2156
2586
  exports.ParsedFormula = ParsedFormula;
2157
2587
  exports.PatchBuilder = PatchBuilder;
2158
2588
  exports.PatchEnricher = PatchEnricher;
2159
2589
  exports.PatchGenerator = PatchGenerator;
2590
+ exports.PatternValidator = PatternValidator;
2160
2591
  exports.PropertySegment = PropertySegment;
2592
+ exports.RequiredValidator = RequiredValidator;
2161
2593
  exports.SchemaDiff = SchemaDiff;
2594
+ exports.SchemaPropertyRule = SchemaPropertyRule;
2162
2595
  exports.SchemaSerializer = SchemaSerializer;
2596
+ exports.SchemaTruthyRule = SchemaTruthyRule;
2597
+ exports.ValidationEngine = ValidationEngine;
2598
+ exports.ValidatorRegistry = ValidatorRegistry;
2599
+ exports.ValidatorResolver = ValidatorResolver;
2163
2600
  exports.areNodesContentEqual = areNodesContentEqual;
2164
2601
  exports.areNodesEqual = areNodesEqual;
2165
2602
  exports.coalesceChanges = coalesceChanges;
2166
2603
  exports.collectChanges = collectChanges;
2167
2604
  exports.createArrayNode = createArrayNode;
2168
2605
  exports.createBooleanNode = createBooleanNode;
2606
+ exports.createDefaultValidatorRegistry = createDefaultValidatorRegistry;
2169
2607
  exports.createNumberNode = createNumberNode;
2170
2608
  exports.createObjectNode = createObjectNode;
2171
2609
  exports.createPath = createPath;
2172
2610
  exports.createRefNode = createRefNode;
2173
2611
  exports.createSchemaTree = createSchemaTree;
2174
2612
  exports.createStringNode = createStringNode;
2613
+ exports.createValidationEngine = createValidationEngine;
2614
+ exports.isValidFieldName = isValidFieldName;
2175
2615
  exports.jsonPointerToPath = jsonPointerToPath;
2176
2616
  exports.jsonPointerToSegments = jsonPointerToSegments;
2177
2617
  exports.jsonPointerToSimplePath = jsonPointerToSimplePath;
2178
- //# sourceMappingURL=chunk-A4E524UU.cjs.map
2179
- //# sourceMappingURL=chunk-A4E524UU.cjs.map
2618
+ exports.validateFormulas = validateFormulas;
2619
+ exports.validateSchema = validateSchema;
2620
+ //# sourceMappingURL=chunk-IWRV6QAD.cjs.map
2621
+ //# sourceMappingURL=chunk-IWRV6QAD.cjs.map