@formspec/build 0.1.0-alpha.16 → 0.1.0-alpha.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/fixtures/example-numeric-extension.d.ts +20 -0
- package/dist/__tests__/fixtures/example-numeric-extension.d.ts.map +1 -0
- package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts +1 -0
- package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts.map +1 -1
- package/dist/__tests__/numeric-extension.integration.test.d.ts +2 -0
- package/dist/__tests__/numeric-extension.integration.test.d.ts.map +1 -0
- package/dist/analyzer/class-analyzer.d.ts +5 -4
- package/dist/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/analyzer/jsdoc-constraints.d.ts +3 -2
- package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -1
- package/dist/analyzer/tsdoc-parser.d.ts +18 -2
- package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
- package/dist/browser.cjs +199 -4
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +199 -4
- package/dist/browser.js.map +1 -1
- package/dist/build.d.ts +28 -2
- package/dist/cli.cjs +547 -84
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +547 -84
- package/dist/cli.js.map +1 -1
- package/dist/extensions/registry.d.ts +25 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/generators/class-schema.d.ts +4 -4
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/index.cjs +546 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +546 -84
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +645 -73
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.js +643 -71
- package/dist/internals.js.map +1 -1
- package/dist/validate/constraint-validator.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ConstraintTagRegistration, type CustomTypeRegistration } from "@formspec/core";
|
|
2
|
+
export declare const NUMERIC_EXTENSION_ID = "x-formspec/example-numeric";
|
|
3
|
+
export declare const DECIMAL_TYPE_ID = "x-formspec/example-numeric/Decimal";
|
|
4
|
+
export declare const BIGINT_TYPE_ID = "x-formspec/example-numeric/BigInt";
|
|
5
|
+
export interface DecimalValue {
|
|
6
|
+
readonly coefficient: bigint;
|
|
7
|
+
readonly scale: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseDecimal(raw: string): DecimalValue;
|
|
10
|
+
export declare function formatDecimal(value: DecimalValue): string;
|
|
11
|
+
export declare function compareDecimal(left: DecimalValue, right: DecimalValue): -1 | 0 | 1;
|
|
12
|
+
export declare function addDecimal(left: DecimalValue, right: DecimalValue): DecimalValue;
|
|
13
|
+
export declare function subtractDecimal(left: DecimalValue, right: DecimalValue): DecimalValue;
|
|
14
|
+
export declare const decimalType: CustomTypeRegistration;
|
|
15
|
+
export declare const bigIntType: CustomTypeRegistration;
|
|
16
|
+
export declare const maxSigFigTag: ConstraintTagRegistration;
|
|
17
|
+
export declare const maxDecimalPlacesTag: ConstraintTagRegistration;
|
|
18
|
+
export declare const numericExtension: import("@formspec/core").ExtensionDefinition;
|
|
19
|
+
export declare function createNumericExtensionRegistry(): import("../../extensions/registry.js").ExtensionRegistry;
|
|
20
|
+
//# sourceMappingURL=example-numeric-extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-numeric-extension.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/example-numeric-extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,yBAAyB,EAE9B,KAAK,sBAAsB,EAG5B,MAAM,gBAAgB,CAAC;AAGxB,eAAO,MAAM,oBAAoB,+BAA+B,CAAC;AACjE,eAAO,MAAM,eAAe,uCAAoC,CAAC;AACjE,eAAO,MAAM,cAAc,sCAAmC,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAMD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAetD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAazD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CASlF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAQhF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAQrF;AAgDD,eAAO,MAAM,WAAW,EAAE,sBAkCxB,CAAC;AAEH,eAAO,MAAM,UAAU,EAAE,sBAOvB,CAAC;AA6FH,eAAO,MAAM,YAAY,EAAE,yBAKzB,CAAC;AAEH,eAAO,MAAM,mBAAmB,EAAE,yBAKhC,CAAC;AAEH,eAAO,MAAM,gBAAgB,8CAa3B,CAAC;AAEH,wBAAgB,8BAA8B,6DAE7C"}
|
|
@@ -27,4 +27,5 @@ export declare const duplicateShippingAddressOverlays: import("@formspec/core").
|
|
|
27
27
|
export declare const unknownShippingAddressOverlays: import("@formspec/core").FormSpec<readonly [import("@formspec/core").DynamicEnumField<"region", "regions">]>;
|
|
28
28
|
export declare const constrainedShippingAddressOverlays: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"city">]>;
|
|
29
29
|
export declare const requiredShippingAddressOverlays: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"postalCode">]>;
|
|
30
|
+
export declare const requiredCountryShippingAddressOverlays: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"country">]>;
|
|
30
31
|
//# sourceMappingURL=mixed-authoring-shipping-address.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mixed-authoring-shipping-address.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/mixed-authoring-shipping-address.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,2BAA2B;IAC3B,OAAO,EAAG,MAAM,CAAC;IAEjB,wBAAwB;IACxB,IAAI,EAAG,MAAM,CAAC;IAEd,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,2GAInC,CAAC;AAEF,qBAAa,2BAA2B;IACtC,QAAQ,EAAG,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,mCAAmC,+GAE/C,CAAC;AAEF,qBAAa,0BAA0B;IACrC,OAAO,EAAG;QACR,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,eAAO,MAAM,6BAA6B,uKAEzC,CAAC;AAEF,eAAO,MAAM,gCAAgC,+KAG5C,CAAC;AAEF,eAAO,MAAM,8BAA8B,8GAAmD,CAAC;AAE/F,eAAO,MAAM,kCAAkC,0FAE9C,CAAC;AAEF,eAAO,MAAM,+BAA+B,gGAE3C,CAAC"}
|
|
1
|
+
{"version":3,"file":"mixed-authoring-shipping-address.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/mixed-authoring-shipping-address.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,2BAA2B;IAC3B,OAAO,EAAG,MAAM,CAAC;IAEjB,wBAAwB;IACxB,IAAI,EAAG,MAAM,CAAC;IAEd,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,2GAInC,CAAC;AAEF,qBAAa,2BAA2B;IACtC,QAAQ,EAAG,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,mCAAmC,+GAE/C,CAAC;AAEF,qBAAa,0BAA0B;IACrC,OAAO,EAAG;QACR,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,eAAO,MAAM,6BAA6B,uKAEzC,CAAC;AAEF,eAAO,MAAM,gCAAgC,+KAG5C,CAAC;AAEF,eAAO,MAAM,8BAA8B,8GAAmD,CAAC;AAE/F,eAAO,MAAM,kCAAkC,0FAE9C,CAAC;AAEF,eAAO,MAAM,+BAA+B,gGAE3C,CAAC;AAEF,eAAO,MAAM,sCAAsC,6FAElD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numeric-extension.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/numeric-extension.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import * as ts from "typescript";
|
|
9
9
|
import type { FieldNode, TypeNode, AnnotationNode, TypeDefinition, JsonValue } from "@formspec/core";
|
|
10
|
+
import type { ExtensionRegistry } from "../extensions/index.js";
|
|
10
11
|
/**
|
|
11
12
|
* Layout metadata extracted from `@Group` and `@ShowWhen` TSDoc tags.
|
|
12
13
|
* One entry per field, in the same order as `fields`.
|
|
@@ -52,19 +53,19 @@ export type AnalyzeTypeAliasToIRResult = {
|
|
|
52
53
|
/**
|
|
53
54
|
* Analyzes a class declaration and produces canonical IR FieldNodes.
|
|
54
55
|
*/
|
|
55
|
-
export declare function analyzeClassToIR(classDecl: ts.ClassDeclaration, checker: ts.TypeChecker, file?: string): IRClassAnalysis;
|
|
56
|
+
export declare function analyzeClassToIR(classDecl: ts.ClassDeclaration, checker: ts.TypeChecker, file?: string, extensionRegistry?: ExtensionRegistry): IRClassAnalysis;
|
|
56
57
|
/**
|
|
57
58
|
* Analyzes an interface declaration and produces canonical IR FieldNodes.
|
|
58
59
|
*/
|
|
59
|
-
export declare function analyzeInterfaceToIR(interfaceDecl: ts.InterfaceDeclaration, checker: ts.TypeChecker, file?: string): IRClassAnalysis;
|
|
60
|
+
export declare function analyzeInterfaceToIR(interfaceDecl: ts.InterfaceDeclaration, checker: ts.TypeChecker, file?: string, extensionRegistry?: ExtensionRegistry): IRClassAnalysis;
|
|
60
61
|
/**
|
|
61
62
|
* Analyzes a type alias declaration and produces canonical IR FieldNodes.
|
|
62
63
|
*/
|
|
63
|
-
export declare function analyzeTypeAliasToIR(typeAlias: ts.TypeAliasDeclaration, checker: ts.TypeChecker, file?: string): AnalyzeTypeAliasToIRResult;
|
|
64
|
+
export declare function analyzeTypeAliasToIR(typeAlias: ts.TypeAliasDeclaration, checker: ts.TypeChecker, file?: string, extensionRegistry?: ExtensionRegistry): AnalyzeTypeAliasToIRResult;
|
|
64
65
|
/**
|
|
65
66
|
* Resolves a TypeScript type to a canonical IR TypeNode.
|
|
66
67
|
*/
|
|
67
|
-
export declare function resolveTypeNode(type: ts.Type, checker: ts.TypeChecker, file: string, typeRegistry: Record<string, TypeDefinition>, visiting: Set<ts.Type>, sourceNode?: ts.Node): TypeNode;
|
|
68
|
+
export declare function resolveTypeNode(type: ts.Type, checker: ts.TypeChecker, file: string, typeRegistry: Record<string, TypeDefinition>, visiting: Set<ts.Type>, sourceNode?: ts.Node, extensionRegistry?: ExtensionRegistry): TypeNode;
|
|
68
69
|
/**
|
|
69
70
|
* Analyzed method information.
|
|
70
71
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"class-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/class-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EAIR,cAAc,EAId,cAAc,EACd,SAAS,EACV,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"class-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/class-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import * as ts from "typescript";
|
|
16
16
|
import type { ConstraintNode, AnnotationNode } from "@formspec/core";
|
|
17
|
+
import { type ParseTSDocOptions } from "./tsdoc-parser.js";
|
|
17
18
|
/**
|
|
18
19
|
* Extracts constraints from JSDoc comments on a TypeScript AST node and returns
|
|
19
20
|
* canonical {@link ConstraintNode} objects.
|
|
@@ -25,7 +26,7 @@ import type { ConstraintNode, AnnotationNode } from "@formspec/core";
|
|
|
25
26
|
* @param file - Absolute path to the source file for provenance
|
|
26
27
|
* @returns Canonical constraint nodes for each valid constraint tag
|
|
27
28
|
*/
|
|
28
|
-
export declare function extractJSDocConstraintNodes(node: ts.Node, file?: string): ConstraintNode[];
|
|
29
|
+
export declare function extractJSDocConstraintNodes(node: ts.Node, file?: string, options?: ParseTSDocOptions): ConstraintNode[];
|
|
29
30
|
/**
|
|
30
31
|
* Extracts canonical annotation tags from a node and returns
|
|
31
32
|
* {@link AnnotationNode} objects.
|
|
@@ -34,7 +35,7 @@ export declare function extractJSDocConstraintNodes(node: ts.Node, file?: string
|
|
|
34
35
|
* @param file - Absolute path to the source file for provenance
|
|
35
36
|
* @returns Canonical annotation nodes
|
|
36
37
|
*/
|
|
37
|
-
export declare function extractJSDocAnnotationNodes(node: ts.Node, file?: string): AnnotationNode[];
|
|
38
|
+
export declare function extractJSDocAnnotationNodes(node: ts.Node, file?: string, options?: ParseTSDocOptions): AnnotationNode[];
|
|
38
39
|
/**
|
|
39
40
|
* Checks if a node has a TSDoc `@deprecated` tag.
|
|
40
41
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsdoc-constraints.d.ts","sourceRoot":"","sources":["../../src/analyzer/jsdoc-constraints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAa,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"jsdoc-constraints.d.ts","sourceRoot":"","sources":["../../src/analyzer/jsdoc-constraints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAa,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAM3B;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,IAAI,SAAK,EACT,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,EAAE,CAGlB;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,IAAI,SAAK,EACT,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,EAAE,CAGlB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,EAAE,CAAC,UAAU,GAAG,SAAS,EACtC,IAAI,SAAK,GACR,cAAc,GAAG,IAAI,CAwCvB"}
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* verbatim.
|
|
29
29
|
*/
|
|
30
30
|
import * as ts from "typescript";
|
|
31
|
-
import { type ConstraintNode, type AnnotationNode, type PathTarget } from "@formspec/core";
|
|
31
|
+
import { type ConstraintNode, type AnnotationNode, type PathTarget, type TypeNode } from "@formspec/core";
|
|
32
|
+
import type { ExtensionRegistry } from "../extensions/index.js";
|
|
32
33
|
/**
|
|
33
34
|
* Result of parsing a single JSDoc comment attached to a TS AST node.
|
|
34
35
|
*/
|
|
@@ -38,6 +39,21 @@ export interface TSDocParseResult {
|
|
|
38
39
|
/** Annotation IR nodes extracted from canonical TSDoc block tags. */
|
|
39
40
|
readonly annotations: readonly AnnotationNode[];
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Optional extension-aware parsing inputs for TSDoc extraction.
|
|
44
|
+
*/
|
|
45
|
+
export interface ParseTSDocOptions {
|
|
46
|
+
/**
|
|
47
|
+
* Extension registry used to resolve custom tags and custom-type-specific
|
|
48
|
+
* broadening of built-in constraint tags.
|
|
49
|
+
*/
|
|
50
|
+
readonly extensionRegistry?: ExtensionRegistry;
|
|
51
|
+
/**
|
|
52
|
+
* Effective field/type node for the declaration being parsed. Required when
|
|
53
|
+
* built-in tags may broaden onto a custom type.
|
|
54
|
+
*/
|
|
55
|
+
readonly fieldType?: TypeNode;
|
|
56
|
+
}
|
|
41
57
|
/**
|
|
42
58
|
* Display-name metadata extracted from a node's JSDoc tags.
|
|
43
59
|
*
|
|
@@ -62,7 +78,7 @@ export interface DisplayNameMetadata {
|
|
|
62
78
|
* @param file - Absolute source file path for provenance
|
|
63
79
|
* @returns Parsed constraint and annotation nodes
|
|
64
80
|
*/
|
|
65
|
-
export declare function parseTSDocTags(node: ts.Node, file?: string): TSDocParseResult;
|
|
81
|
+
export declare function parseTSDocTags(node: ts.Node, file?: string, options?: ParseTSDocOptions): TSDocParseResult;
|
|
66
82
|
/**
|
|
67
83
|
* Checks if a TS AST node has a `@deprecated` tag using the TSDoc parser.
|
|
68
84
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsdoc-parser.d.ts","sourceRoot":"","sources":["../../src/analyzer/tsdoc-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAYjC,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EAInB,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"tsdoc-parser.d.ts","sourceRoot":"","sources":["../../src/analyzer/tsdoc-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAYjC,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EAInB,KAAK,UAAU,EAEf,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AA+GhE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;IAChD,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,IAAI,SAAK,EACT,OAAO,CAAC,EAAE,iBAAiB,GAC1B,gBAAgB,CAiKlB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAsB5D;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,mBAAmB,CA2B7E;AAMD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAQpD"}
|
package/dist/browser.cjs
CHANGED
|
@@ -754,7 +754,12 @@ function applyCustomConstraint(schema, constraint, ctx) {
|
|
|
754
754
|
`Cannot generate JSON Schema for custom constraint "${constraint.constraintId}" without a matching extension registration`
|
|
755
755
|
);
|
|
756
756
|
}
|
|
757
|
-
|
|
757
|
+
assignVendorPrefixedExtensionKeywords(
|
|
758
|
+
schema,
|
|
759
|
+
registration.toJsonSchema(constraint.payload, ctx.vendorPrefix),
|
|
760
|
+
ctx.vendorPrefix,
|
|
761
|
+
`custom constraint "${constraint.constraintId}"`
|
|
762
|
+
);
|
|
758
763
|
}
|
|
759
764
|
function applyCustomAnnotation(schema, annotation, ctx) {
|
|
760
765
|
const registration = ctx.extensionRegistry?.findAnnotation(annotation.annotationId);
|
|
@@ -766,7 +771,22 @@ function applyCustomAnnotation(schema, annotation, ctx) {
|
|
|
766
771
|
if (registration.toJsonSchema === void 0) {
|
|
767
772
|
return;
|
|
768
773
|
}
|
|
769
|
-
|
|
774
|
+
assignVendorPrefixedExtensionKeywords(
|
|
775
|
+
schema,
|
|
776
|
+
registration.toJsonSchema(annotation.value, ctx.vendorPrefix),
|
|
777
|
+
ctx.vendorPrefix,
|
|
778
|
+
`custom annotation "${annotation.annotationId}"`
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPrefix, source) {
|
|
782
|
+
for (const [key, value] of Object.entries(extensionSchema)) {
|
|
783
|
+
if (!key.startsWith(`${vendorPrefix}-`)) {
|
|
784
|
+
throw new Error(
|
|
785
|
+
`Cannot apply ${source}: extension hooks may only emit "${vendorPrefix}-*" JSON Schema keywords`
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
schema[key] = value;
|
|
789
|
+
}
|
|
770
790
|
}
|
|
771
791
|
|
|
772
792
|
// src/json-schema/generator.ts
|
|
@@ -1015,7 +1035,10 @@ function getSchemaExtension(schema, key) {
|
|
|
1015
1035
|
// src/extensions/registry.ts
|
|
1016
1036
|
function createExtensionRegistry(extensions) {
|
|
1017
1037
|
const typeMap = /* @__PURE__ */ new Map();
|
|
1038
|
+
const typeNameMap = /* @__PURE__ */ new Map();
|
|
1018
1039
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
1040
|
+
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
1041
|
+
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
1019
1042
|
const annotationMap = /* @__PURE__ */ new Map();
|
|
1020
1043
|
for (const ext of extensions) {
|
|
1021
1044
|
if (ext.types !== void 0) {
|
|
@@ -1025,6 +1048,27 @@ function createExtensionRegistry(extensions) {
|
|
|
1025
1048
|
throw new Error(`Duplicate custom type ID: "${qualifiedId}"`);
|
|
1026
1049
|
}
|
|
1027
1050
|
typeMap.set(qualifiedId, type);
|
|
1051
|
+
for (const sourceTypeName of type.tsTypeNames ?? [type.typeName]) {
|
|
1052
|
+
if (typeNameMap.has(sourceTypeName)) {
|
|
1053
|
+
throw new Error(`Duplicate custom type source name: "${sourceTypeName}"`);
|
|
1054
|
+
}
|
|
1055
|
+
typeNameMap.set(sourceTypeName, {
|
|
1056
|
+
extensionId: ext.extensionId,
|
|
1057
|
+
registration: type
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
if (type.builtinConstraintBroadenings !== void 0) {
|
|
1061
|
+
for (const broadening of type.builtinConstraintBroadenings) {
|
|
1062
|
+
const key = `${qualifiedId}:${broadening.tagName}`;
|
|
1063
|
+
if (builtinBroadeningMap.has(key)) {
|
|
1064
|
+
throw new Error(`Duplicate built-in constraint broadening: "${key}"`);
|
|
1065
|
+
}
|
|
1066
|
+
builtinBroadeningMap.set(key, {
|
|
1067
|
+
extensionId: ext.extensionId,
|
|
1068
|
+
registration: broadening
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1028
1072
|
}
|
|
1029
1073
|
}
|
|
1030
1074
|
if (ext.constraints !== void 0) {
|
|
@@ -1036,6 +1080,17 @@ function createExtensionRegistry(extensions) {
|
|
|
1036
1080
|
constraintMap.set(qualifiedId, constraint);
|
|
1037
1081
|
}
|
|
1038
1082
|
}
|
|
1083
|
+
if (ext.constraintTags !== void 0) {
|
|
1084
|
+
for (const tag of ext.constraintTags) {
|
|
1085
|
+
if (constraintTagMap.has(tag.tagName)) {
|
|
1086
|
+
throw new Error(`Duplicate custom constraint tag: "@${tag.tagName}"`);
|
|
1087
|
+
}
|
|
1088
|
+
constraintTagMap.set(tag.tagName, {
|
|
1089
|
+
extensionId: ext.extensionId,
|
|
1090
|
+
registration: tag
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1039
1094
|
if (ext.annotations !== void 0) {
|
|
1040
1095
|
for (const annotation of ext.annotations) {
|
|
1041
1096
|
const qualifiedId = `${ext.extensionId}/${annotation.annotationName}`;
|
|
@@ -1049,7 +1104,10 @@ function createExtensionRegistry(extensions) {
|
|
|
1049
1104
|
return {
|
|
1050
1105
|
extensions,
|
|
1051
1106
|
findType: (typeId) => typeMap.get(typeId),
|
|
1107
|
+
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
1052
1108
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
1109
|
+
findConstraintTag: (tagName) => constraintTagMap.get(tagName),
|
|
1110
|
+
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
1053
1111
|
findAnnotation: (annotationId) => annotationMap.get(annotationId)
|
|
1054
1112
|
};
|
|
1055
1113
|
}
|
|
@@ -1117,6 +1175,7 @@ var jsonSchema7Schema = import_zod3.z.lazy(
|
|
|
1117
1175
|
);
|
|
1118
1176
|
|
|
1119
1177
|
// src/validate/constraint-validator.ts
|
|
1178
|
+
var import_core3 = require("@formspec/core");
|
|
1120
1179
|
function addContradiction(ctx, message, primary, related) {
|
|
1121
1180
|
ctx.diagnostics.push({
|
|
1122
1181
|
code: "CONTRADICTING_CONSTRAINTS",
|
|
@@ -1162,6 +1221,13 @@ function addConstraintBroadening(ctx, message, primary, related) {
|
|
|
1162
1221
|
relatedLocations: [related]
|
|
1163
1222
|
});
|
|
1164
1223
|
}
|
|
1224
|
+
function getExtensionIdFromConstraintId(constraintId) {
|
|
1225
|
+
const separator = constraintId.lastIndexOf("/");
|
|
1226
|
+
if (separator <= 0) {
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
return constraintId.slice(0, separator);
|
|
1230
|
+
}
|
|
1165
1231
|
function findNumeric(constraints, constraintKind) {
|
|
1166
1232
|
return constraints.find((c) => c.constraintKind === constraintKind);
|
|
1167
1233
|
}
|
|
@@ -1332,6 +1398,112 @@ function checkConstraintBroadening(ctx, fieldName, constraints) {
|
|
|
1332
1398
|
strongestByKey.set(key, constraint);
|
|
1333
1399
|
}
|
|
1334
1400
|
}
|
|
1401
|
+
function compareCustomConstraintStrength(current, previous) {
|
|
1402
|
+
const order = current.comparePayloads(current.constraint.payload, previous.constraint.payload);
|
|
1403
|
+
const equalPayloadTiebreaker = order === 0 ? compareSemanticInclusivity(current.role.inclusive, previous.role.inclusive) : order;
|
|
1404
|
+
switch (current.role.bound) {
|
|
1405
|
+
case "lower":
|
|
1406
|
+
return equalPayloadTiebreaker;
|
|
1407
|
+
case "upper":
|
|
1408
|
+
return equalPayloadTiebreaker === 0 ? 0 : -equalPayloadTiebreaker;
|
|
1409
|
+
case "exact":
|
|
1410
|
+
return order === 0 ? 0 : Number.NaN;
|
|
1411
|
+
default: {
|
|
1412
|
+
const _exhaustive = current.role.bound;
|
|
1413
|
+
return _exhaustive;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
function compareSemanticInclusivity(currentInclusive, previousInclusive) {
|
|
1418
|
+
if (currentInclusive === previousInclusive) {
|
|
1419
|
+
return 0;
|
|
1420
|
+
}
|
|
1421
|
+
return currentInclusive ? -1 : 1;
|
|
1422
|
+
}
|
|
1423
|
+
function customConstraintsContradict(lower, upper) {
|
|
1424
|
+
const order = lower.comparePayloads(lower.constraint.payload, upper.constraint.payload);
|
|
1425
|
+
if (order > 0) {
|
|
1426
|
+
return true;
|
|
1427
|
+
}
|
|
1428
|
+
if (order < 0) {
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
return !lower.role.inclusive || !upper.role.inclusive;
|
|
1432
|
+
}
|
|
1433
|
+
function describeCustomConstraintTag(constraint) {
|
|
1434
|
+
return constraint.provenance.tagName ?? constraint.constraintId;
|
|
1435
|
+
}
|
|
1436
|
+
function checkCustomConstraintSemantics(ctx, fieldName, constraints) {
|
|
1437
|
+
if (ctx.extensionRegistry === void 0) {
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
const strongestByKey = /* @__PURE__ */ new Map();
|
|
1441
|
+
const lowerByFamily = /* @__PURE__ */ new Map();
|
|
1442
|
+
const upperByFamily = /* @__PURE__ */ new Map();
|
|
1443
|
+
for (const constraint of constraints) {
|
|
1444
|
+
if (constraint.constraintKind !== "custom") {
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
const registration = ctx.extensionRegistry.findConstraint(constraint.constraintId);
|
|
1448
|
+
if (registration?.comparePayloads === void 0 || registration.semanticRole === void 0) {
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
const entry = {
|
|
1452
|
+
constraint,
|
|
1453
|
+
comparePayloads: registration.comparePayloads,
|
|
1454
|
+
role: registration.semanticRole
|
|
1455
|
+
};
|
|
1456
|
+
const familyKey = `${registration.semanticRole.family}:${pathKey(constraint)}`;
|
|
1457
|
+
const boundKey = `${familyKey}:${registration.semanticRole.bound}`;
|
|
1458
|
+
const previous = strongestByKey.get(boundKey);
|
|
1459
|
+
if (previous !== void 0) {
|
|
1460
|
+
const strength = compareCustomConstraintStrength(entry, previous);
|
|
1461
|
+
if (Number.isNaN(strength)) {
|
|
1462
|
+
addContradiction(
|
|
1463
|
+
ctx,
|
|
1464
|
+
`Field "${formatPathTargetFieldName(fieldName, constraint.path?.segments ?? [])}": ${describeCustomConstraintTag(constraint)} conflicts with ${describeCustomConstraintTag(previous.constraint)}`,
|
|
1465
|
+
constraint.provenance,
|
|
1466
|
+
previous.constraint.provenance
|
|
1467
|
+
);
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1470
|
+
if (strength < 0) {
|
|
1471
|
+
addConstraintBroadening(
|
|
1472
|
+
ctx,
|
|
1473
|
+
`Field "${formatPathTargetFieldName(fieldName, constraint.path?.segments ?? [])}": ${describeCustomConstraintTag(constraint)} is broader than earlier ${describeCustomConstraintTag(previous.constraint)}. Constraints can only narrow.`,
|
|
1474
|
+
constraint.provenance,
|
|
1475
|
+
previous.constraint.provenance
|
|
1476
|
+
);
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
if (strength > 0) {
|
|
1480
|
+
strongestByKey.set(boundKey, entry);
|
|
1481
|
+
}
|
|
1482
|
+
} else {
|
|
1483
|
+
strongestByKey.set(boundKey, entry);
|
|
1484
|
+
}
|
|
1485
|
+
if (registration.semanticRole.bound === "lower") {
|
|
1486
|
+
lowerByFamily.set(familyKey, strongestByKey.get(boundKey) ?? entry);
|
|
1487
|
+
} else if (registration.semanticRole.bound === "upper") {
|
|
1488
|
+
upperByFamily.set(familyKey, strongestByKey.get(boundKey) ?? entry);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
for (const [familyKey, lower] of lowerByFamily) {
|
|
1492
|
+
const upper = upperByFamily.get(familyKey);
|
|
1493
|
+
if (upper === void 0) {
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
if (!customConstraintsContradict(lower, upper)) {
|
|
1497
|
+
continue;
|
|
1498
|
+
}
|
|
1499
|
+
addContradiction(
|
|
1500
|
+
ctx,
|
|
1501
|
+
`Field "${formatPathTargetFieldName(fieldName, lower.constraint.path?.segments ?? [])}": ${describeCustomConstraintTag(lower.constraint)} contradicts ${describeCustomConstraintTag(upper.constraint)}`,
|
|
1502
|
+
lower.constraint.provenance,
|
|
1503
|
+
upper.constraint.provenance
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1335
1507
|
function checkNumericContradictions(ctx, fieldName, constraints) {
|
|
1336
1508
|
const min = findNumeric(constraints, "minimum");
|
|
1337
1509
|
const max = findNumeric(constraints, "maximum");
|
|
@@ -1643,8 +1815,30 @@ function checkCustomConstraint(ctx, fieldName, type, constraint) {
|
|
|
1643
1815
|
);
|
|
1644
1816
|
return;
|
|
1645
1817
|
}
|
|
1646
|
-
|
|
1647
|
-
if (
|
|
1818
|
+
const normalizedTagName = constraint.provenance.tagName === void 0 ? void 0 : (0, import_core3.normalizeConstraintTagName)(constraint.provenance.tagName.replace(/^@/, ""));
|
|
1819
|
+
if (normalizedTagName !== void 0) {
|
|
1820
|
+
const tagRegistration = ctx.extensionRegistry.findConstraintTag(normalizedTagName);
|
|
1821
|
+
const extensionId = getExtensionIdFromConstraintId(constraint.constraintId);
|
|
1822
|
+
if (extensionId !== null && tagRegistration?.extensionId === extensionId && tagRegistration.registration.constraintName === registration.constraintName && tagRegistration.registration.isApplicableToType?.(type) === false) {
|
|
1823
|
+
addTypeMismatch(
|
|
1824
|
+
ctx,
|
|
1825
|
+
`Field "${fieldName}": custom constraint "${constraint.constraintId}" is not applicable to type "${typeLabel(type)}"`,
|
|
1826
|
+
constraint.provenance
|
|
1827
|
+
);
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
if (registration.applicableTypes === null) {
|
|
1832
|
+
if (registration.isApplicableToType?.(type) === false) {
|
|
1833
|
+
addTypeMismatch(
|
|
1834
|
+
ctx,
|
|
1835
|
+
`Field "${fieldName}": custom constraint "${constraint.constraintId}" is not applicable to type "${typeLabel(type)}"`,
|
|
1836
|
+
constraint.provenance
|
|
1837
|
+
);
|
|
1838
|
+
}
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
if (!registration.applicableTypes.includes(type.kind) || registration.isApplicableToType?.(type) === false) {
|
|
1648
1842
|
addTypeMismatch(
|
|
1649
1843
|
ctx,
|
|
1650
1844
|
`Field "${fieldName}": custom constraint "${constraint.constraintId}" is not applicable to type "${typeLabel(type)}"`,
|
|
@@ -1675,6 +1869,7 @@ function validateConstraints(ctx, name, type, constraints) {
|
|
|
1675
1869
|
checkAllowedMembersContradiction(ctx, name, constraints);
|
|
1676
1870
|
checkConstContradictions(ctx, name, constraints);
|
|
1677
1871
|
checkConstraintBroadening(ctx, name, constraints);
|
|
1872
|
+
checkCustomConstraintSemantics(ctx, name, constraints);
|
|
1678
1873
|
checkTypeApplicability(ctx, name, type, constraints);
|
|
1679
1874
|
}
|
|
1680
1875
|
function validateElement(ctx, element) {
|