@formspec/build 0.1.0-alpha.43 → 0.1.0-alpha.45
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/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/analyzer/program.d.ts +4 -1
- package/dist/analyzer/program.d.ts.map +1 -1
- package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
- package/dist/browser.cjs +35 -9
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +36 -12
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +106 -5
- package/dist/build-beta.d.ts +106 -5
- package/dist/build-internal.d.ts +106 -5
- package/dist/build.d.ts +106 -5
- package/dist/cli.cjs +343 -59
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +339 -58
- package/dist/cli.js.map +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/registry.d.ts +64 -5
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/symbol-registry.d.ts +33 -0
- package/dist/extensions/symbol-registry.d.ts.map +1 -0
- package/dist/generators/class-schema.d.ts +16 -0
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/generators/discovered-schema.d.ts.map +1 -1
- package/dist/index.cjs +328 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +329 -54
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +124 -10
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.d.ts +1 -1
- package/dist/internals.d.ts.map +1 -1
- package/dist/internals.js +125 -13
- package/dist/internals.js.map +1 -1
- package/dist/json-schema/generator.d.ts.map +1 -1
- package/dist/metadata/collision-guards.d.ts.map +1 -1
- package/dist/metadata/policy.d.ts.map +1 -1
- package/dist/metadata/resolve.d.ts.map +1 -1
- package/dist/ui-schema/ir-generator.d.ts.map +1 -1
- package/dist/validate/constraint-validator.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/internals.cjs
CHANGED
|
@@ -275,7 +275,9 @@ function resolveTypeNodeMetadata(type, options) {
|
|
|
275
275
|
case "object":
|
|
276
276
|
return {
|
|
277
277
|
...type,
|
|
278
|
-
properties: type.properties.map(
|
|
278
|
+
properties: type.properties.map(
|
|
279
|
+
(property) => resolveObjectPropertyMetadata(property, options)
|
|
280
|
+
)
|
|
279
281
|
};
|
|
280
282
|
case "record":
|
|
281
283
|
return {
|
|
@@ -1632,6 +1634,71 @@ function isObjectType(type) {
|
|
|
1632
1634
|
function isIntersectionType(type) {
|
|
1633
1635
|
return !!(type.flags & ts3.TypeFlags.Intersection);
|
|
1634
1636
|
}
|
|
1637
|
+
function collectBrandIdentifiers(type) {
|
|
1638
|
+
if (!type.isIntersection()) {
|
|
1639
|
+
return [];
|
|
1640
|
+
}
|
|
1641
|
+
const brands = [];
|
|
1642
|
+
for (const prop of type.getProperties()) {
|
|
1643
|
+
const decl = prop.valueDeclaration ?? prop.declarations?.[0];
|
|
1644
|
+
if (decl === void 0) continue;
|
|
1645
|
+
if (!ts3.isPropertySignature(decl) && !ts3.isPropertyDeclaration(decl)) continue;
|
|
1646
|
+
if (!ts3.isComputedPropertyName(decl.name)) continue;
|
|
1647
|
+
if (!ts3.isIdentifier(decl.name.expression)) continue;
|
|
1648
|
+
brands.push(decl.name.expression.text);
|
|
1649
|
+
}
|
|
1650
|
+
return brands;
|
|
1651
|
+
}
|
|
1652
|
+
function resolveCanonicalSymbol(type, checker) {
|
|
1653
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
1654
|
+
if (raw === void 0) return void 0;
|
|
1655
|
+
return raw.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
1656
|
+
}
|
|
1657
|
+
function resolveSymbolBasedCustomType(type, extensionRegistry, checker) {
|
|
1658
|
+
if (extensionRegistry === void 0) {
|
|
1659
|
+
return null;
|
|
1660
|
+
}
|
|
1661
|
+
const canonical = resolveCanonicalSymbol(type, checker);
|
|
1662
|
+
if (canonical === void 0) {
|
|
1663
|
+
return null;
|
|
1664
|
+
}
|
|
1665
|
+
const registration = extensionRegistry.findTypeBySymbol(canonical);
|
|
1666
|
+
if (registration === void 0) {
|
|
1667
|
+
return null;
|
|
1668
|
+
}
|
|
1669
|
+
return {
|
|
1670
|
+
kind: "custom",
|
|
1671
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
1672
|
+
payload: null
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
function isIntegerBrandedType(type) {
|
|
1676
|
+
if (!type.isIntersection()) {
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
|
|
1680
|
+
if (!hasNumberBase) {
|
|
1681
|
+
return false;
|
|
1682
|
+
}
|
|
1683
|
+
return collectBrandIdentifiers(type).includes("__integerBrand");
|
|
1684
|
+
}
|
|
1685
|
+
function resolveBrandedCustomType(type, extensionRegistry) {
|
|
1686
|
+
if (extensionRegistry === void 0) {
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1689
|
+
for (const brand of collectBrandIdentifiers(type)) {
|
|
1690
|
+
const registration = extensionRegistry.findTypeByBrand(brand);
|
|
1691
|
+
if (registration === void 0) {
|
|
1692
|
+
continue;
|
|
1693
|
+
}
|
|
1694
|
+
return {
|
|
1695
|
+
kind: "custom",
|
|
1696
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
1697
|
+
payload: null
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
return null;
|
|
1701
|
+
}
|
|
1635
1702
|
function isResolvableObjectLikeAliasTypeNode(typeNode) {
|
|
1636
1703
|
if (ts3.isParenthesizedTypeNode(typeNode)) {
|
|
1637
1704
|
return isResolvableObjectLikeAliasTypeNode(typeNode.type);
|
|
@@ -2743,6 +2810,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2743
2810
|
if (customType) {
|
|
2744
2811
|
return customType;
|
|
2745
2812
|
}
|
|
2813
|
+
const symbolCustomType = resolveSymbolBasedCustomType(type, extensionRegistry, checker);
|
|
2814
|
+
if (symbolCustomType) {
|
|
2815
|
+
return symbolCustomType;
|
|
2816
|
+
}
|
|
2817
|
+
const brandedCustomType = resolveBrandedCustomType(type, extensionRegistry);
|
|
2818
|
+
if (brandedCustomType) {
|
|
2819
|
+
return brandedCustomType;
|
|
2820
|
+
}
|
|
2746
2821
|
const primitiveAlias = tryResolveNamedPrimitiveAlias(
|
|
2747
2822
|
type,
|
|
2748
2823
|
checker,
|
|
@@ -2757,6 +2832,9 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2757
2832
|
if (primitiveAlias) {
|
|
2758
2833
|
return primitiveAlias;
|
|
2759
2834
|
}
|
|
2835
|
+
if (isIntegerBrandedType(type)) {
|
|
2836
|
+
return { kind: "primitive", primitiveKind: "integer" };
|
|
2837
|
+
}
|
|
2760
2838
|
if (type.flags & ts3.TypeFlags.String) {
|
|
2761
2839
|
return { kind: "primitive", primitiveKind: "string" };
|
|
2762
2840
|
}
|
|
@@ -2859,7 +2937,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2859
2937
|
return { kind: "primitive", primitiveKind: "string" };
|
|
2860
2938
|
}
|
|
2861
2939
|
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2862
|
-
if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
|
|
2940
|
+
if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null)) && !isIntegerBrandedType(type)) {
|
|
2863
2941
|
return null;
|
|
2864
2942
|
}
|
|
2865
2943
|
const aliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration) ?? getReferencedTypeAliasDeclaration(sourceNode, checker);
|
|
@@ -2945,6 +3023,9 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
2945
3023
|
visitedAliases
|
|
2946
3024
|
);
|
|
2947
3025
|
}
|
|
3026
|
+
if (isIntegerBrandedType(type)) {
|
|
3027
|
+
return { kind: "primitive", primitiveKind: "integer" };
|
|
3028
|
+
}
|
|
2948
3029
|
if (type.flags & ts3.TypeFlags.String) {
|
|
2949
3030
|
return { kind: "primitive", primitiveKind: "string" };
|
|
2950
3031
|
}
|
|
@@ -3681,7 +3762,7 @@ function createProgramContextFromProgram(program, filePath) {
|
|
|
3681
3762
|
sourceFile
|
|
3682
3763
|
};
|
|
3683
3764
|
}
|
|
3684
|
-
function createProgramContext(filePath) {
|
|
3765
|
+
function createProgramContext(filePath, additionalFiles) {
|
|
3685
3766
|
const absolutePath = path.resolve(filePath);
|
|
3686
3767
|
const fileDir = path.dirname(absolutePath);
|
|
3687
3768
|
const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
|
|
@@ -3704,7 +3785,8 @@ function createProgramContext(filePath) {
|
|
|
3704
3785
|
throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
|
|
3705
3786
|
}
|
|
3706
3787
|
compilerOptions = parsed.options;
|
|
3707
|
-
|
|
3788
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
3789
|
+
fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
|
|
3708
3790
|
} else {
|
|
3709
3791
|
compilerOptions = {
|
|
3710
3792
|
target: ts4.ScriptTarget.ES2022,
|
|
@@ -3714,7 +3796,8 @@ function createProgramContext(filePath) {
|
|
|
3714
3796
|
skipLibCheck: true,
|
|
3715
3797
|
declaration: true
|
|
3716
3798
|
};
|
|
3717
|
-
|
|
3799
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
3800
|
+
fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
|
|
3718
3801
|
}
|
|
3719
3802
|
const program = ts4.createProgram(fileNames, compilerOptions);
|
|
3720
3803
|
const sourceFile = program.getSourceFile(absolutePath);
|
|
@@ -4008,7 +4091,7 @@ function makeFileProvenance(filePath) {
|
|
|
4008
4091
|
}
|
|
4009
4092
|
|
|
4010
4093
|
// src/generators/class-schema.ts
|
|
4011
|
-
var
|
|
4094
|
+
var ts6 = __toESM(require("typescript"), 1);
|
|
4012
4095
|
|
|
4013
4096
|
// src/metadata/collision-guards.ts
|
|
4014
4097
|
function assertUniqueSerializedNames(entries, scope) {
|
|
@@ -4724,7 +4807,7 @@ function generateCustomType(type, ctx) {
|
|
|
4724
4807
|
}
|
|
4725
4808
|
return registration.toJsonSchema(type.payload, ctx.vendorPrefix);
|
|
4726
4809
|
}
|
|
4727
|
-
var
|
|
4810
|
+
var VOCABULARY_MODE_BLOCKED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
4728
4811
|
"$schema",
|
|
4729
4812
|
"$ref",
|
|
4730
4813
|
"$defs",
|
|
@@ -4795,7 +4878,7 @@ function applyCustomConstraint(schema, constraint, ctx) {
|
|
|
4795
4878
|
if (registration.emitsVocabularyKeywords) {
|
|
4796
4879
|
const target = schema;
|
|
4797
4880
|
for (const [key, value] of Object.entries(extensionSchema)) {
|
|
4798
|
-
if (
|
|
4881
|
+
if (VOCABULARY_MODE_BLOCKED_KEYWORDS.has(key)) {
|
|
4799
4882
|
throw new Error(
|
|
4800
4883
|
`Custom constraint "${constraint.constraintId}" with emitsVocabularyKeywords must not overwrite standard JSON Schema keyword "${key}"`
|
|
4801
4884
|
);
|
|
@@ -4855,8 +4938,10 @@ function buildConstraintTagSources(extensions) {
|
|
|
4855
4938
|
}
|
|
4856
4939
|
function createExtensionRegistry(extensions) {
|
|
4857
4940
|
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
4941
|
+
let symbolMap = /* @__PURE__ */ new Map();
|
|
4858
4942
|
const typeMap = /* @__PURE__ */ new Map();
|
|
4859
4943
|
const typeNameMap = /* @__PURE__ */ new Map();
|
|
4944
|
+
const brandMap = /* @__PURE__ */ new Map();
|
|
4860
4945
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
4861
4946
|
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
4862
4947
|
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
@@ -4880,6 +4965,20 @@ function createExtensionRegistry(extensions) {
|
|
|
4880
4965
|
registration: type
|
|
4881
4966
|
});
|
|
4882
4967
|
}
|
|
4968
|
+
if (type.brand !== void 0) {
|
|
4969
|
+
if (type.brand === "__integerBrand") {
|
|
4970
|
+
throw new Error(
|
|
4971
|
+
`Brand "__integerBrand" is reserved for the builtin Integer type and cannot be registered by extensions`
|
|
4972
|
+
);
|
|
4973
|
+
}
|
|
4974
|
+
if (brandMap.has(type.brand)) {
|
|
4975
|
+
throw new Error(`Duplicate custom type brand: "${type.brand}"`);
|
|
4976
|
+
}
|
|
4977
|
+
brandMap.set(type.brand, {
|
|
4978
|
+
extensionId: ext.extensionId,
|
|
4979
|
+
registration: type
|
|
4980
|
+
});
|
|
4981
|
+
}
|
|
4883
4982
|
if (type.builtinConstraintBroadenings !== void 0) {
|
|
4884
4983
|
for (const broadening of type.builtinConstraintBroadenings) {
|
|
4885
4984
|
const key = `${qualifiedId}:${broadening.tagName}`;
|
|
@@ -4949,7 +5048,10 @@ function createExtensionRegistry(extensions) {
|
|
|
4949
5048
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
|
|
4950
5049
|
);
|
|
4951
5050
|
}
|
|
4952
|
-
if (Object.hasOwn(
|
|
5051
|
+
if (Object.hasOwn(
|
|
5052
|
+
import_internals5.BUILTIN_CONSTRAINT_DEFINITIONS,
|
|
5053
|
+
(0, import_internals5.normalizeConstraintTagName)(canonicalTagName)
|
|
5054
|
+
)) {
|
|
4953
5055
|
throw new Error(
|
|
4954
5056
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals5.normalizeConstraintTagName)(canonicalTagName)}".`
|
|
4955
5057
|
);
|
|
@@ -4970,6 +5072,11 @@ function createExtensionRegistry(extensions) {
|
|
|
4970
5072
|
extensions,
|
|
4971
5073
|
findType: (typeId) => typeMap.get(typeId),
|
|
4972
5074
|
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
5075
|
+
findTypeByBrand: (brand) => brandMap.get(brand),
|
|
5076
|
+
findTypeBySymbol: (symbol) => symbolMap.get(symbol),
|
|
5077
|
+
setSymbolMap: (map) => {
|
|
5078
|
+
symbolMap = map;
|
|
5079
|
+
},
|
|
4973
5080
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
4974
5081
|
findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal3.normalizeFormSpecTagName)(tagName)),
|
|
4975
5082
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
@@ -4977,6 +5084,10 @@ function createExtensionRegistry(extensions) {
|
|
|
4977
5084
|
};
|
|
4978
5085
|
}
|
|
4979
5086
|
|
|
5087
|
+
// src/extensions/symbol-registry.ts
|
|
5088
|
+
var ts5 = __toESM(require("typescript"), 1);
|
|
5089
|
+
var path2 = __toESM(require("path"), 1);
|
|
5090
|
+
|
|
4980
5091
|
// src/ui-schema/schema.ts
|
|
4981
5092
|
var import_zod = require("zod");
|
|
4982
5093
|
var jsonPointerSchema = import_zod.z.string();
|
|
@@ -5185,7 +5296,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
|
5185
5296
|
break;
|
|
5186
5297
|
}
|
|
5187
5298
|
case "conditional": {
|
|
5188
|
-
const newRule = createShowRule(
|
|
5299
|
+
const newRule = createShowRule(
|
|
5300
|
+
fieldNameMap.get(element.fieldName) ?? element.fieldName,
|
|
5301
|
+
element.value
|
|
5302
|
+
);
|
|
5189
5303
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
5190
5304
|
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
5191
5305
|
result.push(...childElements);
|