@formspec/build 0.1.0-alpha.12 → 0.1.0-alpha.14

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 (42) hide show
  1. package/README.md +20 -20
  2. package/dist/__tests__/alias-chain-propagation.test.d.ts +9 -0
  3. package/dist/__tests__/alias-chain-propagation.test.d.ts.map +1 -0
  4. package/dist/__tests__/fixtures/alias-chains.d.ts +37 -0
  5. package/dist/__tests__/fixtures/alias-chains.d.ts.map +1 -0
  6. package/dist/__tests__/fixtures/example-a-builtins.d.ts +7 -7
  7. package/dist/__tests__/fixtures/example-interface-types.d.ts +17 -17
  8. package/dist/__tests__/guards.test.d.ts +2 -0
  9. package/dist/__tests__/guards.test.d.ts.map +1 -0
  10. package/dist/__tests__/json-utils.test.d.ts +5 -0
  11. package/dist/__tests__/json-utils.test.d.ts.map +1 -0
  12. package/dist/__tests__/path-target-parser.test.d.ts +9 -0
  13. package/dist/__tests__/path-target-parser.test.d.ts.map +1 -0
  14. package/dist/analyzer/class-analyzer.d.ts.map +1 -1
  15. package/dist/analyzer/jsdoc-constraints.d.ts +2 -2
  16. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -1
  17. package/dist/analyzer/json-utils.d.ts +22 -0
  18. package/dist/analyzer/json-utils.d.ts.map +1 -0
  19. package/dist/analyzer/tsdoc-parser.d.ts +18 -4
  20. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
  21. package/dist/browser.cjs +115 -8
  22. package/dist/browser.cjs.map +1 -1
  23. package/dist/browser.js +115 -8
  24. package/dist/browser.js.map +1 -1
  25. package/dist/build.d.ts +1 -0
  26. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -1
  27. package/dist/cli.cjs +179 -42
  28. package/dist/cli.cjs.map +1 -1
  29. package/dist/cli.js +184 -42
  30. package/dist/cli.js.map +1 -1
  31. package/dist/index.cjs +173 -41
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.js +178 -42
  34. package/dist/index.js.map +1 -1
  35. package/dist/internals.cjs +186 -47
  36. package/dist/internals.cjs.map +1 -1
  37. package/dist/internals.js +191 -48
  38. package/dist/internals.js.map +1 -1
  39. package/dist/json-schema/ir-generator.d.ts +1 -0
  40. package/dist/json-schema/ir-generator.d.ts.map +1 -1
  41. package/dist/validate/constraint-validator.d.ts.map +1 -1
  42. package/package.json +3 -3
package/dist/browser.js CHANGED
@@ -66,11 +66,40 @@ function canonicalizeField(field) {
66
66
  }
67
67
  function canonicalizeTextField(field) {
68
68
  const type = { kind: "primitive", primitiveKind: "string" };
69
+ const constraints = [];
70
+ if (field.minLength !== void 0) {
71
+ const c = {
72
+ kind: "constraint",
73
+ constraintKind: "minLength",
74
+ value: field.minLength,
75
+ provenance: CHAIN_DSL_PROVENANCE
76
+ };
77
+ constraints.push(c);
78
+ }
79
+ if (field.maxLength !== void 0) {
80
+ const c = {
81
+ kind: "constraint",
82
+ constraintKind: "maxLength",
83
+ value: field.maxLength,
84
+ provenance: CHAIN_DSL_PROVENANCE
85
+ };
86
+ constraints.push(c);
87
+ }
88
+ if (field.pattern !== void 0) {
89
+ const c = {
90
+ kind: "constraint",
91
+ constraintKind: "pattern",
92
+ pattern: field.pattern,
93
+ provenance: CHAIN_DSL_PROVENANCE
94
+ };
95
+ constraints.push(c);
96
+ }
69
97
  return buildFieldNode(
70
98
  field.name,
71
99
  type,
72
100
  field.required,
73
- buildAnnotations(field.label, field.placeholder)
101
+ buildAnnotations(field.label, field.placeholder),
102
+ constraints
74
103
  );
75
104
  }
76
105
  function canonicalizeNumberField(field) {
@@ -94,6 +123,15 @@ function canonicalizeNumberField(field) {
94
123
  };
95
124
  constraints.push(c);
96
125
  }
126
+ if (field.multipleOf !== void 0) {
127
+ const c = {
128
+ kind: "constraint",
129
+ constraintKind: "multipleOf",
130
+ value: field.multipleOf,
131
+ provenance: CHAIN_DSL_PROVENANCE
132
+ };
133
+ constraints.push(c);
134
+ }
97
135
  return buildFieldNode(
98
136
  field.name,
99
137
  type,
@@ -322,8 +360,70 @@ function collectFields(elements, properties, required, ctx) {
322
360
  }
323
361
  function generateFieldSchema(field, ctx) {
324
362
  const schema = generateTypeNode(field.type, ctx);
325
- applyConstraints(schema, field.constraints);
363
+ const directConstraints = [];
364
+ const pathConstraints = [];
365
+ for (const c of field.constraints) {
366
+ if (c.path) {
367
+ pathConstraints.push(c);
368
+ } else {
369
+ directConstraints.push(c);
370
+ }
371
+ }
372
+ applyConstraints(schema, directConstraints);
326
373
  applyAnnotations(schema, field.annotations);
374
+ if (pathConstraints.length === 0) {
375
+ return schema;
376
+ }
377
+ return applyPathTargetedConstraints(schema, pathConstraints);
378
+ }
379
+ function applyPathTargetedConstraints(schema, pathConstraints) {
380
+ if (schema.type === "array" && schema.items) {
381
+ schema.items = applyPathTargetedConstraints(schema.items, pathConstraints);
382
+ return schema;
383
+ }
384
+ const byTarget = /* @__PURE__ */ new Map();
385
+ for (const c of pathConstraints) {
386
+ const target = c.path?.segments[0];
387
+ if (!target) continue;
388
+ const group = byTarget.get(target) ?? [];
389
+ group.push(c);
390
+ byTarget.set(target, group);
391
+ }
392
+ const propertyOverrides = {};
393
+ for (const [target, constraints] of byTarget) {
394
+ const subSchema = {};
395
+ applyConstraints(subSchema, constraints);
396
+ propertyOverrides[target] = subSchema;
397
+ }
398
+ if (schema.$ref) {
399
+ const { $ref, ...rest } = schema;
400
+ const refPart = { $ref };
401
+ const overridePart = {
402
+ properties: propertyOverrides,
403
+ ...rest
404
+ };
405
+ return { allOf: [refPart, overridePart] };
406
+ }
407
+ if (schema.type === "object" && schema.properties) {
408
+ const missingOverrides = {};
409
+ for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {
410
+ if (schema.properties[target]) {
411
+ Object.assign(schema.properties[target], overrideSchema);
412
+ } else {
413
+ missingOverrides[target] = overrideSchema;
414
+ }
415
+ }
416
+ if (Object.keys(missingOverrides).length === 0) {
417
+ return schema;
418
+ }
419
+ return {
420
+ allOf: [schema, { properties: missingOverrides }]
421
+ };
422
+ }
423
+ if (schema.allOf) {
424
+ schema.allOf = [...schema.allOf, { properties: propertyOverrides }];
425
+ return schema;
426
+ }
327
427
  return schema;
328
428
  }
329
429
  function generateTypeNode(type, ctx) {
@@ -843,14 +943,10 @@ function addUnknownExtension(ctx, message, primary) {
843
943
  });
844
944
  }
845
945
  function findNumeric(constraints, constraintKind) {
846
- return constraints.find(
847
- (c) => c.constraintKind === constraintKind
848
- );
946
+ return constraints.find((c) => c.constraintKind === constraintKind);
849
947
  }
850
948
  function findLength(constraints, constraintKind) {
851
- return constraints.find(
852
- (c) => c.constraintKind === constraintKind
853
- );
949
+ return constraints.find((c) => c.constraintKind === constraintKind);
854
950
  }
855
951
  function findAllowedMembers(constraints) {
856
952
  return constraints.filter(
@@ -974,6 +1070,17 @@ function checkTypeApplicability(ctx, fieldName, type, constraints) {
974
1070
  const isEnum = type.kind === "enum";
975
1071
  const label = typeLabel(type);
976
1072
  for (const constraint of constraints) {
1073
+ if (constraint.path) {
1074
+ const isTraversable = type.kind === "object" || type.kind === "array" || type.kind === "reference";
1075
+ if (!isTraversable) {
1076
+ addTypeMismatch(
1077
+ ctx,
1078
+ `Field "${fieldName}": path-targeted constraint "${constraint.constraintKind}" is invalid because type "${label}" cannot be traversed`,
1079
+ constraint.provenance
1080
+ );
1081
+ }
1082
+ continue;
1083
+ }
977
1084
  const ck = constraint.constraintKind;
978
1085
  switch (ck) {
979
1086
  case "minimum":