@formspec/build 0.1.0-alpha.44 → 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 +33 -7
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +34 -10
- 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 +324 -71
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +320 -70
- 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 +310 -64
- 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 +311 -67
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +106 -23
- 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 +107 -26
- 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/cli.cjs
CHANGED
|
@@ -264,7 +264,9 @@ function resolveTypeNodeMetadata(type, options) {
|
|
|
264
264
|
case "object":
|
|
265
265
|
return {
|
|
266
266
|
...type,
|
|
267
|
-
properties: type.properties.map(
|
|
267
|
+
properties: type.properties.map(
|
|
268
|
+
(property) => resolveObjectPropertyMetadata(property, options)
|
|
269
|
+
)
|
|
268
270
|
};
|
|
269
271
|
case "record":
|
|
270
272
|
return {
|
|
@@ -1743,10 +1745,7 @@ function generateJsonSchema(form, options) {
|
|
|
1743
1745
|
const metadata = options?.metadata;
|
|
1744
1746
|
const vendorPrefix = options?.vendorPrefix;
|
|
1745
1747
|
const enumSerialization = options?.enumSerialization;
|
|
1746
|
-
const ir = canonicalizeChainDSL(
|
|
1747
|
-
form,
|
|
1748
|
-
metadata !== void 0 ? { metadata } : void 0
|
|
1749
|
-
);
|
|
1748
|
+
const ir = canonicalizeChainDSL(form, metadata !== void 0 ? { metadata } : void 0);
|
|
1750
1749
|
const internalOptions = vendorPrefix === void 0 && enumSerialization === void 0 ? void 0 : {
|
|
1751
1750
|
...vendorPrefix !== void 0 && { vendorPrefix },
|
|
1752
1751
|
...enumSerialization !== void 0 && { enumSerialization }
|
|
@@ -1974,7 +1973,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
|
1974
1973
|
break;
|
|
1975
1974
|
}
|
|
1976
1975
|
case "conditional": {
|
|
1977
|
-
const newRule = createShowRule(
|
|
1976
|
+
const newRule = createShowRule(
|
|
1977
|
+
fieldNameMap.get(element.fieldName) ?? element.fieldName,
|
|
1978
|
+
element.value
|
|
1979
|
+
);
|
|
1978
1980
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
1979
1981
|
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
1980
1982
|
result.push(...childElements);
|
|
@@ -2059,8 +2061,10 @@ function buildConstraintTagSources(extensions) {
|
|
|
2059
2061
|
}
|
|
2060
2062
|
function createExtensionRegistry(extensions) {
|
|
2061
2063
|
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
2064
|
+
let symbolMap = /* @__PURE__ */ new Map();
|
|
2062
2065
|
const typeMap = /* @__PURE__ */ new Map();
|
|
2063
2066
|
const typeNameMap = /* @__PURE__ */ new Map();
|
|
2067
|
+
const brandMap = /* @__PURE__ */ new Map();
|
|
2064
2068
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
2065
2069
|
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
2066
2070
|
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
@@ -2084,6 +2088,20 @@ function createExtensionRegistry(extensions) {
|
|
|
2084
2088
|
registration: type
|
|
2085
2089
|
});
|
|
2086
2090
|
}
|
|
2091
|
+
if (type.brand !== void 0) {
|
|
2092
|
+
if (type.brand === "__integerBrand") {
|
|
2093
|
+
throw new Error(
|
|
2094
|
+
`Brand "__integerBrand" is reserved for the builtin Integer type and cannot be registered by extensions`
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
if (brandMap.has(type.brand)) {
|
|
2098
|
+
throw new Error(`Duplicate custom type brand: "${type.brand}"`);
|
|
2099
|
+
}
|
|
2100
|
+
brandMap.set(type.brand, {
|
|
2101
|
+
extensionId: ext.extensionId,
|
|
2102
|
+
registration: type
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2087
2105
|
if (type.builtinConstraintBroadenings !== void 0) {
|
|
2088
2106
|
for (const broadening of type.builtinConstraintBroadenings) {
|
|
2089
2107
|
const key = `${qualifiedId}:${broadening.tagName}`;
|
|
@@ -2153,7 +2171,10 @@ function createExtensionRegistry(extensions) {
|
|
|
2153
2171
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
|
|
2154
2172
|
);
|
|
2155
2173
|
}
|
|
2156
|
-
if (Object.hasOwn(
|
|
2174
|
+
if (Object.hasOwn(
|
|
2175
|
+
import_internals3.BUILTIN_CONSTRAINT_DEFINITIONS,
|
|
2176
|
+
(0, import_internals3.normalizeConstraintTagName)(canonicalTagName)
|
|
2177
|
+
)) {
|
|
2157
2178
|
throw new Error(
|
|
2158
2179
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals3.normalizeConstraintTagName)(canonicalTagName)}".`
|
|
2159
2180
|
);
|
|
@@ -2174,6 +2195,11 @@ function createExtensionRegistry(extensions) {
|
|
|
2174
2195
|
extensions,
|
|
2175
2196
|
findType: (typeId) => typeMap.get(typeId),
|
|
2176
2197
|
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
2198
|
+
findTypeByBrand: (brand) => brandMap.get(brand),
|
|
2199
|
+
findTypeBySymbol: (symbol) => symbolMap.get(symbol),
|
|
2200
|
+
setSymbolMap: (map) => {
|
|
2201
|
+
symbolMap = map;
|
|
2202
|
+
},
|
|
2177
2203
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
2178
2204
|
findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal.normalizeFormSpecTagName)(tagName)),
|
|
2179
2205
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
@@ -3058,30 +3084,70 @@ function isObjectType(type) {
|
|
|
3058
3084
|
function isIntersectionType(type) {
|
|
3059
3085
|
return !!(type.flags & ts3.TypeFlags.Intersection);
|
|
3060
3086
|
}
|
|
3087
|
+
function collectBrandIdentifiers(type) {
|
|
3088
|
+
if (!type.isIntersection()) {
|
|
3089
|
+
return [];
|
|
3090
|
+
}
|
|
3091
|
+
const brands = [];
|
|
3092
|
+
for (const prop of type.getProperties()) {
|
|
3093
|
+
const decl = prop.valueDeclaration ?? prop.declarations?.[0];
|
|
3094
|
+
if (decl === void 0) continue;
|
|
3095
|
+
if (!ts3.isPropertySignature(decl) && !ts3.isPropertyDeclaration(decl)) continue;
|
|
3096
|
+
if (!ts3.isComputedPropertyName(decl.name)) continue;
|
|
3097
|
+
if (!ts3.isIdentifier(decl.name.expression)) continue;
|
|
3098
|
+
brands.push(decl.name.expression.text);
|
|
3099
|
+
}
|
|
3100
|
+
return brands;
|
|
3101
|
+
}
|
|
3102
|
+
function resolveCanonicalSymbol(type, checker) {
|
|
3103
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
3104
|
+
if (raw === void 0) return void 0;
|
|
3105
|
+
return raw.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
3106
|
+
}
|
|
3107
|
+
function resolveSymbolBasedCustomType(type, extensionRegistry, checker) {
|
|
3108
|
+
if (extensionRegistry === void 0) {
|
|
3109
|
+
return null;
|
|
3110
|
+
}
|
|
3111
|
+
const canonical = resolveCanonicalSymbol(type, checker);
|
|
3112
|
+
if (canonical === void 0) {
|
|
3113
|
+
return null;
|
|
3114
|
+
}
|
|
3115
|
+
const registration = extensionRegistry.findTypeBySymbol(canonical);
|
|
3116
|
+
if (registration === void 0) {
|
|
3117
|
+
return null;
|
|
3118
|
+
}
|
|
3119
|
+
return {
|
|
3120
|
+
kind: "custom",
|
|
3121
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
3122
|
+
payload: null
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3061
3125
|
function isIntegerBrandedType(type) {
|
|
3062
3126
|
if (!type.isIntersection()) {
|
|
3063
3127
|
return false;
|
|
3064
3128
|
}
|
|
3065
|
-
const hasNumberBase = type.types.some(
|
|
3066
|
-
(member) => !!(member.flags & ts3.TypeFlags.Number)
|
|
3067
|
-
);
|
|
3129
|
+
const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
|
|
3068
3130
|
if (!hasNumberBase) {
|
|
3069
3131
|
return false;
|
|
3070
3132
|
}
|
|
3071
|
-
return type
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
return false;
|
|
3133
|
+
return collectBrandIdentifiers(type).includes("__integerBrand");
|
|
3134
|
+
}
|
|
3135
|
+
function resolveBrandedCustomType(type, extensionRegistry) {
|
|
3136
|
+
if (extensionRegistry === void 0) {
|
|
3137
|
+
return null;
|
|
3138
|
+
}
|
|
3139
|
+
for (const brand of collectBrandIdentifiers(type)) {
|
|
3140
|
+
const registration = extensionRegistry.findTypeByBrand(brand);
|
|
3141
|
+
if (registration === void 0) {
|
|
3142
|
+
continue;
|
|
3082
3143
|
}
|
|
3083
|
-
return
|
|
3084
|
-
|
|
3144
|
+
return {
|
|
3145
|
+
kind: "custom",
|
|
3146
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
3147
|
+
payload: null
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
3150
|
+
return null;
|
|
3085
3151
|
}
|
|
3086
3152
|
function isResolvableObjectLikeAliasTypeNode(typeNode) {
|
|
3087
3153
|
if (ts3.isParenthesizedTypeNode(typeNode)) {
|
|
@@ -4189,6 +4255,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
4189
4255
|
if (customType) {
|
|
4190
4256
|
return customType;
|
|
4191
4257
|
}
|
|
4258
|
+
const symbolCustomType = resolveSymbolBasedCustomType(type, extensionRegistry, checker);
|
|
4259
|
+
if (symbolCustomType) {
|
|
4260
|
+
return symbolCustomType;
|
|
4261
|
+
}
|
|
4262
|
+
const brandedCustomType = resolveBrandedCustomType(type, extensionRegistry);
|
|
4263
|
+
if (brandedCustomType) {
|
|
4264
|
+
return brandedCustomType;
|
|
4265
|
+
}
|
|
4192
4266
|
const primitiveAlias = tryResolveNamedPrimitiveAlias(
|
|
4193
4267
|
type,
|
|
4194
4268
|
checker,
|
|
@@ -5149,7 +5223,7 @@ function createProgramContextFromProgram(program, filePath) {
|
|
|
5149
5223
|
sourceFile
|
|
5150
5224
|
};
|
|
5151
5225
|
}
|
|
5152
|
-
function createProgramContext(filePath) {
|
|
5226
|
+
function createProgramContext(filePath, additionalFiles) {
|
|
5153
5227
|
const absolutePath = path.resolve(filePath);
|
|
5154
5228
|
const fileDir = path.dirname(absolutePath);
|
|
5155
5229
|
const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
|
|
@@ -5172,7 +5246,8 @@ function createProgramContext(filePath) {
|
|
|
5172
5246
|
throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
|
|
5173
5247
|
}
|
|
5174
5248
|
compilerOptions = parsed.options;
|
|
5175
|
-
|
|
5249
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
5250
|
+
fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
|
|
5176
5251
|
} else {
|
|
5177
5252
|
compilerOptions = {
|
|
5178
5253
|
target: ts4.ScriptTarget.ES2022,
|
|
@@ -5182,7 +5257,8 @@ function createProgramContext(filePath) {
|
|
|
5182
5257
|
skipLibCheck: true,
|
|
5183
5258
|
declaration: true
|
|
5184
5259
|
};
|
|
5185
|
-
|
|
5260
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
5261
|
+
fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
|
|
5186
5262
|
}
|
|
5187
5263
|
const program = ts4.createProgram(fileNames, compilerOptions);
|
|
5188
5264
|
const sourceFile = program.getSourceFile(absolutePath);
|
|
@@ -5495,6 +5571,138 @@ var init_program = __esm({
|
|
|
5495
5571
|
}
|
|
5496
5572
|
});
|
|
5497
5573
|
|
|
5574
|
+
// src/extensions/symbol-registry.ts
|
|
5575
|
+
function buildSymbolMapFromConfig(configPath, program, checker, extensionRegistry) {
|
|
5576
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
5577
|
+
const normalizedPath = path2.resolve(configPath);
|
|
5578
|
+
const configFile = program.getSourceFile(normalizedPath);
|
|
5579
|
+
if (configFile === void 0) {
|
|
5580
|
+
return symbolMap;
|
|
5581
|
+
}
|
|
5582
|
+
function visit(node) {
|
|
5583
|
+
if (ts5.isCallExpression(node) && isDefineCustomTypeCall(node, checker)) {
|
|
5584
|
+
processDefineCustomTypeCall(node);
|
|
5585
|
+
}
|
|
5586
|
+
ts5.forEachChild(node, visit);
|
|
5587
|
+
}
|
|
5588
|
+
function processDefineCustomTypeCall(call) {
|
|
5589
|
+
const typeArgNode = call.typeArguments?.[0];
|
|
5590
|
+
if (typeArgNode === void 0) {
|
|
5591
|
+
return;
|
|
5592
|
+
}
|
|
5593
|
+
const resolvedType = checker.getTypeFromTypeNode(typeArgNode);
|
|
5594
|
+
const canonical = resolveCanonicalSymbol2(resolvedType, checker);
|
|
5595
|
+
if (canonical === void 0) {
|
|
5596
|
+
return;
|
|
5597
|
+
}
|
|
5598
|
+
const typeName = extractTypeNameFromCallArg(call);
|
|
5599
|
+
if (typeName === null) {
|
|
5600
|
+
return;
|
|
5601
|
+
}
|
|
5602
|
+
let entry;
|
|
5603
|
+
const extensionId = extractEnclosingExtensionId(call, checker);
|
|
5604
|
+
if (extensionId !== null) {
|
|
5605
|
+
const reg = extensionRegistry.findType(`${extensionId}/${typeName}`);
|
|
5606
|
+
if (reg !== void 0) {
|
|
5607
|
+
entry = { extensionId, registration: reg };
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
entry ??= findRegistrationByTypeName(extensionRegistry, typeName);
|
|
5611
|
+
if (entry === void 0) {
|
|
5612
|
+
return;
|
|
5613
|
+
}
|
|
5614
|
+
symbolMap.set(canonical, entry);
|
|
5615
|
+
}
|
|
5616
|
+
visit(configFile);
|
|
5617
|
+
return symbolMap;
|
|
5618
|
+
}
|
|
5619
|
+
function isDefineCustomTypeCall(node, checker) {
|
|
5620
|
+
if (node.typeArguments === void 0 || node.typeArguments.length === 0) return false;
|
|
5621
|
+
const callSymbol = checker.getSymbolAtLocation(node.expression);
|
|
5622
|
+
if (callSymbol !== void 0) {
|
|
5623
|
+
const resolved = callSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(callSymbol) : callSymbol;
|
|
5624
|
+
const decl = resolved.declarations?.[0];
|
|
5625
|
+
if (decl !== void 0) {
|
|
5626
|
+
const sourceFile = decl.getSourceFile().fileName.replace(/\\/g, "/");
|
|
5627
|
+
return resolved.name === "defineCustomType" && // Match whether in node_modules/@formspec/core or monorepo packages/core.
|
|
5628
|
+
(sourceFile.includes("@formspec/core") || sourceFile.includes("/packages/core/"));
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5631
|
+
return ts5.isIdentifier(node.expression) && node.expression.text === "defineCustomType";
|
|
5632
|
+
}
|
|
5633
|
+
function resolveCanonicalSymbol2(type, checker) {
|
|
5634
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
5635
|
+
if (raw === void 0) return void 0;
|
|
5636
|
+
return raw.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
5637
|
+
}
|
|
5638
|
+
function extractTypeNameFromCallArg(call) {
|
|
5639
|
+
const arg = call.arguments[0];
|
|
5640
|
+
if (arg === void 0 || !ts5.isObjectLiteralExpression(arg)) {
|
|
5641
|
+
return null;
|
|
5642
|
+
}
|
|
5643
|
+
const typeNameProp = arg.properties.find(
|
|
5644
|
+
(p) => ts5.isPropertyAssignment(p) && ts5.isIdentifier(p.name) && p.name.text === "typeName"
|
|
5645
|
+
);
|
|
5646
|
+
if (typeNameProp === void 0 || !ts5.isStringLiteral(typeNameProp.initializer)) {
|
|
5647
|
+
return null;
|
|
5648
|
+
}
|
|
5649
|
+
return typeNameProp.initializer.text;
|
|
5650
|
+
}
|
|
5651
|
+
function extractEnclosingExtensionId(call, checker) {
|
|
5652
|
+
for (let node = call.parent; !ts5.isSourceFile(node); node = node.parent) {
|
|
5653
|
+
if (ts5.isCallExpression(node) && isDefineExtensionCall(node, checker)) {
|
|
5654
|
+
return extractExtensionIdFromCallArg(node);
|
|
5655
|
+
}
|
|
5656
|
+
}
|
|
5657
|
+
return null;
|
|
5658
|
+
}
|
|
5659
|
+
function isDefineExtensionCall(node, checker) {
|
|
5660
|
+
const callSymbol = checker.getSymbolAtLocation(node.expression);
|
|
5661
|
+
if (callSymbol !== void 0) {
|
|
5662
|
+
const resolved = callSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(callSymbol) : callSymbol;
|
|
5663
|
+
const decl = resolved.declarations?.[0];
|
|
5664
|
+
if (decl !== void 0) {
|
|
5665
|
+
const sourceFile = decl.getSourceFile().fileName.replace(/\\/g, "/");
|
|
5666
|
+
return resolved.name === "defineExtension" && (sourceFile.includes("@formspec/core") || sourceFile.includes("/packages/core/"));
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
return ts5.isIdentifier(node.expression) && node.expression.text === "defineExtension";
|
|
5670
|
+
}
|
|
5671
|
+
function extractExtensionIdFromCallArg(call) {
|
|
5672
|
+
const arg = call.arguments[0];
|
|
5673
|
+
if (arg === void 0 || !ts5.isObjectLiteralExpression(arg)) {
|
|
5674
|
+
return null;
|
|
5675
|
+
}
|
|
5676
|
+
const prop = arg.properties.find(
|
|
5677
|
+
(p) => ts5.isPropertyAssignment(p) && ts5.isIdentifier(p.name) && p.name.text === "extensionId"
|
|
5678
|
+
);
|
|
5679
|
+
if (prop === void 0 || !ts5.isStringLiteral(prop.initializer)) {
|
|
5680
|
+
return null;
|
|
5681
|
+
}
|
|
5682
|
+
return prop.initializer.text;
|
|
5683
|
+
}
|
|
5684
|
+
function findRegistrationByTypeName(registry, typeName) {
|
|
5685
|
+
for (const ext of registry.extensions) {
|
|
5686
|
+
if (ext.types === void 0) {
|
|
5687
|
+
continue;
|
|
5688
|
+
}
|
|
5689
|
+
for (const type of ext.types) {
|
|
5690
|
+
if (type.typeName === typeName) {
|
|
5691
|
+
return { extensionId: ext.extensionId, registration: type };
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
return void 0;
|
|
5696
|
+
}
|
|
5697
|
+
var ts5, path2;
|
|
5698
|
+
var init_symbol_registry = __esm({
|
|
5699
|
+
"src/extensions/symbol-registry.ts"() {
|
|
5700
|
+
"use strict";
|
|
5701
|
+
ts5 = __toESM(require("typescript"), 1);
|
|
5702
|
+
path2 = __toESM(require("path"), 1);
|
|
5703
|
+
}
|
|
5704
|
+
});
|
|
5705
|
+
|
|
5498
5706
|
// src/validate/constraint-validator.ts
|
|
5499
5707
|
function validateFieldNode(ctx, field) {
|
|
5500
5708
|
const analysis = (0, import_internal4.analyzeConstraintTargets)(
|
|
@@ -5641,7 +5849,8 @@ function formatLocation(location) {
|
|
|
5641
5849
|
return `${location.file}:${String(location.line)}:${String(location.column)}`;
|
|
5642
5850
|
}
|
|
5643
5851
|
function generateSchemasFromClass(options) {
|
|
5644
|
-
const
|
|
5852
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5853
|
+
const ctx = createProgramContext(options.filePath, additionalFiles);
|
|
5645
5854
|
const classDecl = findClassByName(ctx.sourceFile, options.className);
|
|
5646
5855
|
if (!classDecl) {
|
|
5647
5856
|
throw new Error(`Class "${options.className}" not found in ${options.filePath}`);
|
|
@@ -5706,7 +5915,8 @@ function generateSchemasDetailed(options) {
|
|
|
5706
5915
|
function generateSchemasDetailedInternal(options) {
|
|
5707
5916
|
let ctx;
|
|
5708
5917
|
try {
|
|
5709
|
-
|
|
5918
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5919
|
+
ctx = createProgramContext(options.filePath, additionalFiles);
|
|
5710
5920
|
} catch (error) {
|
|
5711
5921
|
return {
|
|
5712
5922
|
ok: false,
|
|
@@ -5745,13 +5955,16 @@ function generateSchemasFromProgramDetailedInternal(options) {
|
|
|
5745
5955
|
}
|
|
5746
5956
|
function generateSchemasBatch(options) {
|
|
5747
5957
|
const contextCache = /* @__PURE__ */ new Map();
|
|
5958
|
+
const resolved = resolveOptions(options);
|
|
5959
|
+
let symbolMapProgram;
|
|
5748
5960
|
return options.targets.map((target) => {
|
|
5749
5961
|
let ctx;
|
|
5750
5962
|
try {
|
|
5751
|
-
const cacheKey =
|
|
5963
|
+
const cacheKey = ts6.sys.useCaseSensitiveFileNames ? target.filePath : target.filePath.toLowerCase();
|
|
5752
5964
|
const cachedContext = contextCache.get(cacheKey);
|
|
5753
5965
|
if (cachedContext === void 0) {
|
|
5754
|
-
|
|
5966
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5967
|
+
ctx = createProgramContext(target.filePath, additionalFiles);
|
|
5755
5968
|
contextCache.set(cacheKey, ctx);
|
|
5756
5969
|
} else {
|
|
5757
5970
|
ctx = cachedContext;
|
|
@@ -5762,9 +5975,25 @@ function generateSchemasBatch(options) {
|
|
|
5762
5975
|
diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
|
|
5763
5976
|
});
|
|
5764
5977
|
}
|
|
5978
|
+
if (options.configPath !== void 0 && resolved.extensionRegistry !== void 0 && isMutableRegistry(resolved.extensionRegistry) && ctx.program !== symbolMapProgram) {
|
|
5979
|
+
const symbolMap = buildSymbolMapFromConfig(
|
|
5980
|
+
options.configPath,
|
|
5981
|
+
ctx.program,
|
|
5982
|
+
ctx.checker,
|
|
5983
|
+
resolved.extensionRegistry
|
|
5984
|
+
);
|
|
5985
|
+
resolved.extensionRegistry.setSymbolMap(symbolMap);
|
|
5986
|
+
symbolMapProgram = ctx.program;
|
|
5987
|
+
}
|
|
5765
5988
|
return withTarget(
|
|
5766
5989
|
target,
|
|
5767
|
-
|
|
5990
|
+
generateSchemasFromResolvedOptions(
|
|
5991
|
+
ctx,
|
|
5992
|
+
target.filePath,
|
|
5993
|
+
target.typeName,
|
|
5994
|
+
resolved,
|
|
5995
|
+
options.discriminator
|
|
5996
|
+
)
|
|
5768
5997
|
);
|
|
5769
5998
|
});
|
|
5770
5999
|
}
|
|
@@ -5785,11 +6014,19 @@ function generateSchemasBatchFromProgram(options) {
|
|
|
5785
6014
|
);
|
|
5786
6015
|
});
|
|
5787
6016
|
}
|
|
6017
|
+
function isMutableRegistry(reg) {
|
|
6018
|
+
return "setSymbolMap" in reg && typeof reg.setSymbolMap === "function";
|
|
6019
|
+
}
|
|
5788
6020
|
function resolveOptions(options) {
|
|
5789
6021
|
const configRegistry = options.config?.extensions !== void 0 ? createExtensionRegistry(options.config.extensions) : void 0;
|
|
6022
|
+
const legacyRegistry = options.extensionRegistry;
|
|
5790
6023
|
return {
|
|
5791
|
-
//
|
|
5792
|
-
|
|
6024
|
+
// When the caller provides the deprecated extensionRegistry field directly,
|
|
6025
|
+
// it is typed as the read-only ExtensionRegistry interface. We cast here
|
|
6026
|
+
// because the legacy path was introduced before MutableExtensionRegistry was
|
|
6027
|
+
// split out; callers using createExtensionRegistry() always get a mutable
|
|
6028
|
+
// registry, and this cast is safe for all registries produced by this module.
|
|
6029
|
+
extensionRegistry: legacyRegistry ?? configRegistry,
|
|
5793
6030
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
5794
6031
|
vendorPrefix: options.vendorPrefix ?? options.config?.vendorPrefix,
|
|
5795
6032
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
@@ -5800,13 +6037,31 @@ function resolveOptions(options) {
|
|
|
5800
6037
|
}
|
|
5801
6038
|
function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, options) {
|
|
5802
6039
|
const resolved = resolveOptions(options);
|
|
6040
|
+
if (options.configPath !== void 0 && resolved.extensionRegistry !== void 0 && isMutableRegistry(resolved.extensionRegistry)) {
|
|
6041
|
+
const symbolMap = buildSymbolMapFromConfig(
|
|
6042
|
+
options.configPath,
|
|
6043
|
+
ctx.program,
|
|
6044
|
+
ctx.checker,
|
|
6045
|
+
resolved.extensionRegistry
|
|
6046
|
+
);
|
|
6047
|
+
resolved.extensionRegistry.setSymbolMap(symbolMap);
|
|
6048
|
+
}
|
|
6049
|
+
return generateSchemasFromResolvedOptions(
|
|
6050
|
+
ctx,
|
|
6051
|
+
filePath,
|
|
6052
|
+
typeName,
|
|
6053
|
+
resolved,
|
|
6054
|
+
options.discriminator
|
|
6055
|
+
);
|
|
6056
|
+
}
|
|
6057
|
+
function generateSchemasFromResolvedOptions(ctx, filePath, typeName, resolved, discriminator) {
|
|
5803
6058
|
const analysisResult = analyzeNamedTypeToIRFromProgramContextDetailed(
|
|
5804
6059
|
ctx,
|
|
5805
6060
|
filePath,
|
|
5806
6061
|
typeName,
|
|
5807
6062
|
resolved.extensionRegistry,
|
|
5808
6063
|
resolved.metadata,
|
|
5809
|
-
|
|
6064
|
+
discriminator
|
|
5810
6065
|
);
|
|
5811
6066
|
if (!analysisResult.ok) {
|
|
5812
6067
|
return {
|
|
@@ -5846,16 +6101,17 @@ function createProgramContextFailureDiagnostic(filePath, error) {
|
|
|
5846
6101
|
relatedLocations: []
|
|
5847
6102
|
};
|
|
5848
6103
|
}
|
|
5849
|
-
var
|
|
6104
|
+
var ts6;
|
|
5850
6105
|
var init_class_schema = __esm({
|
|
5851
6106
|
"src/generators/class-schema.ts"() {
|
|
5852
6107
|
"use strict";
|
|
5853
|
-
|
|
6108
|
+
ts6 = __toESM(require("typescript"), 1);
|
|
5854
6109
|
init_program();
|
|
5855
6110
|
init_class_analyzer();
|
|
5856
6111
|
init_canonicalize();
|
|
5857
6112
|
init_ir_generator();
|
|
5858
6113
|
init_extensions();
|
|
6114
|
+
init_symbol_registry();
|
|
5859
6115
|
init_ir_generator2();
|
|
5860
6116
|
init_validate();
|
|
5861
6117
|
}
|
|
@@ -5876,7 +6132,7 @@ function getModuleSymbol(context) {
|
|
|
5876
6132
|
return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
|
|
5877
6133
|
}
|
|
5878
6134
|
function isSchemaSourceDeclaration(declaration) {
|
|
5879
|
-
return
|
|
6135
|
+
return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
|
|
5880
6136
|
}
|
|
5881
6137
|
function resolveModuleExport(context, exportName = "default") {
|
|
5882
6138
|
const moduleSymbol = getModuleSymbol(context);
|
|
@@ -5887,16 +6143,16 @@ function resolveModuleExport(context, exportName = "default") {
|
|
|
5887
6143
|
if (exportSymbol === null) {
|
|
5888
6144
|
return null;
|
|
5889
6145
|
}
|
|
5890
|
-
return exportSymbol.flags &
|
|
6146
|
+
return exportSymbol.flags & ts7.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
|
|
5891
6147
|
}
|
|
5892
6148
|
function resolveModuleExportDeclaration(context, exportName = "default") {
|
|
5893
6149
|
return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
|
|
5894
6150
|
}
|
|
5895
|
-
var
|
|
6151
|
+
var ts7;
|
|
5896
6152
|
var init_static_build = __esm({
|
|
5897
6153
|
"src/static-build.ts"() {
|
|
5898
6154
|
"use strict";
|
|
5899
|
-
|
|
6155
|
+
ts7 = __toESM(require("typescript"), 1);
|
|
5900
6156
|
init_program();
|
|
5901
6157
|
}
|
|
5902
6158
|
});
|
|
@@ -5909,17 +6165,17 @@ function toDiscoveredTypeSchemas(result, resolvedMetadata) {
|
|
|
5909
6165
|
};
|
|
5910
6166
|
}
|
|
5911
6167
|
function isNamedTypeDeclaration(declaration) {
|
|
5912
|
-
return
|
|
6168
|
+
return ts8.isClassDeclaration(declaration) || ts8.isInterfaceDeclaration(declaration) || ts8.isTypeAliasDeclaration(declaration);
|
|
5913
6169
|
}
|
|
5914
6170
|
function hasConcreteTypeArguments(type, checker) {
|
|
5915
6171
|
if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
|
|
5916
6172
|
return true;
|
|
5917
6173
|
}
|
|
5918
|
-
if ((type.flags &
|
|
6174
|
+
if ((type.flags & ts8.TypeFlags.Object) === 0) {
|
|
5919
6175
|
return false;
|
|
5920
6176
|
}
|
|
5921
6177
|
const objectType = type;
|
|
5922
|
-
if ((objectType.objectFlags &
|
|
6178
|
+
if ((objectType.objectFlags & ts8.ObjectFlags.Reference) === 0) {
|
|
5923
6179
|
return false;
|
|
5924
6180
|
}
|
|
5925
6181
|
return checker.getTypeArguments(objectType).length > 0;
|
|
@@ -5932,13 +6188,13 @@ function getNamedTypeDeclaration2(type) {
|
|
|
5932
6188
|
return declaration;
|
|
5933
6189
|
}
|
|
5934
6190
|
}
|
|
5935
|
-
const aliasDeclaration = type.aliasSymbol?.declarations?.find(
|
|
6191
|
+
const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts8.isTypeAliasDeclaration);
|
|
5936
6192
|
return aliasDeclaration;
|
|
5937
6193
|
}
|
|
5938
6194
|
function getFallbackName(sourceNode, fallback = "AnonymousType") {
|
|
5939
6195
|
if (sourceNode !== void 0 && "name" in sourceNode) {
|
|
5940
6196
|
const namedNode = sourceNode;
|
|
5941
|
-
if (namedNode.name !== void 0 &&
|
|
6197
|
+
if (namedNode.name !== void 0 && ts8.isIdentifier(namedNode.name)) {
|
|
5942
6198
|
return namedNode.name.text;
|
|
5943
6199
|
}
|
|
5944
6200
|
}
|
|
@@ -6057,17 +6313,14 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
|
|
|
6057
6313
|
rootLogicalName: root.name
|
|
6058
6314
|
}
|
|
6059
6315
|
);
|
|
6060
|
-
const schema = generateJsonSchemaFromIR(
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
vendorPrefix: options?.vendorPrefix
|
|
6069
|
-
}
|
|
6070
|
-
);
|
|
6316
|
+
const schema = generateJsonSchemaFromIR(ir, {
|
|
6317
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6318
|
+
extensionRegistry: options?.extensionRegistry,
|
|
6319
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6320
|
+
enumSerialization: options?.enumSerialization,
|
|
6321
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6322
|
+
vendorPrefix: options?.vendorPrefix
|
|
6323
|
+
});
|
|
6071
6324
|
const result = schema.properties?.["__result"];
|
|
6072
6325
|
if (result === void 0) {
|
|
6073
6326
|
throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
|
|
@@ -6166,7 +6419,7 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
|
|
|
6166
6419
|
}
|
|
6167
6420
|
function generateSchemasFromDeclaration(options) {
|
|
6168
6421
|
const filePath = options.declaration.getSourceFile().fileName;
|
|
6169
|
-
if (
|
|
6422
|
+
if (ts8.isClassDeclaration(options.declaration)) {
|
|
6170
6423
|
return generateSchemasFromAnalysis(
|
|
6171
6424
|
analyzeClassToIR(
|
|
6172
6425
|
options.declaration,
|
|
@@ -6182,7 +6435,7 @@ function generateSchemasFromDeclaration(options) {
|
|
|
6182
6435
|
options
|
|
6183
6436
|
);
|
|
6184
6437
|
}
|
|
6185
|
-
if (
|
|
6438
|
+
if (ts8.isInterfaceDeclaration(options.declaration)) {
|
|
6186
6439
|
return generateSchemasFromAnalysis(
|
|
6187
6440
|
analyzeInterfaceToIR(
|
|
6188
6441
|
options.declaration,
|
|
@@ -6198,7 +6451,7 @@ function generateSchemasFromDeclaration(options) {
|
|
|
6198
6451
|
options
|
|
6199
6452
|
);
|
|
6200
6453
|
}
|
|
6201
|
-
if (
|
|
6454
|
+
if (ts8.isTypeAliasDeclaration(options.declaration)) {
|
|
6202
6455
|
const analyzedAlias = analyzeTypeAliasToIR(
|
|
6203
6456
|
options.declaration,
|
|
6204
6457
|
options.context.checker,
|
|
@@ -6261,7 +6514,7 @@ function generateSchemasFromReturnType(options) {
|
|
|
6261
6514
|
const returnType = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
|
|
6262
6515
|
const type = unwrapPromiseType(options.context.checker, returnType);
|
|
6263
6516
|
const sourceNode = type !== returnType ? unwrapPromiseTypeNode(options.declaration.type) ?? options.declaration.type ?? options.declaration : options.declaration.type ?? options.declaration;
|
|
6264
|
-
const fallbackName = options.declaration.name !== void 0 &&
|
|
6517
|
+
const fallbackName = options.declaration.name !== void 0 && ts8.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
|
|
6265
6518
|
return generateSchemasFromResolvedType({
|
|
6266
6519
|
...options,
|
|
6267
6520
|
type,
|
|
@@ -6296,20 +6549,20 @@ function unwrapPromiseTypeNode(typeNode) {
|
|
|
6296
6549
|
if (typeNode === void 0) {
|
|
6297
6550
|
return void 0;
|
|
6298
6551
|
}
|
|
6299
|
-
if (
|
|
6552
|
+
if (ts8.isParenthesizedTypeNode(typeNode)) {
|
|
6300
6553
|
const unwrapped = unwrapPromiseTypeNode(typeNode.type);
|
|
6301
6554
|
return unwrapped ?? typeNode;
|
|
6302
6555
|
}
|
|
6303
6556
|
return isPromiseTypeReferenceNode(typeNode) ? typeNode.typeArguments[0] : typeNode;
|
|
6304
6557
|
}
|
|
6305
6558
|
function isPromiseTypeReferenceNode(typeNode) {
|
|
6306
|
-
return
|
|
6559
|
+
return ts8.isTypeReferenceNode(typeNode) && ts8.isIdentifier(typeNode.typeName) && typeNode.typeName.text === "Promise" && typeNode.typeArguments !== void 0 && typeNode.typeArguments.length > 0;
|
|
6307
6560
|
}
|
|
6308
|
-
var
|
|
6561
|
+
var ts8, import_internal5, import_internals6;
|
|
6309
6562
|
var init_discovered_schema = __esm({
|
|
6310
6563
|
"src/generators/discovered-schema.ts"() {
|
|
6311
6564
|
"use strict";
|
|
6312
|
-
|
|
6565
|
+
ts8 = __toESM(require("typescript"), 1);
|
|
6313
6566
|
import_internal5 = require("@formspec/analysis/internal");
|
|
6314
6567
|
init_class_analyzer();
|
|
6315
6568
|
init_class_schema();
|
|
@@ -6575,13 +6828,13 @@ function writeSchemas(form, options) {
|
|
|
6575
6828
|
if (!fs.existsSync(outDir)) {
|
|
6576
6829
|
fs.mkdirSync(outDir, { recursive: true });
|
|
6577
6830
|
}
|
|
6578
|
-
const jsonSchemaPath =
|
|
6579
|
-
const uiSchemaPath =
|
|
6831
|
+
const jsonSchemaPath = path3.join(outDir, `${name}-schema.json`);
|
|
6832
|
+
const uiSchemaPath = path3.join(outDir, `${name}-uischema.json`);
|
|
6580
6833
|
fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));
|
|
6581
6834
|
fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema2, null, indent));
|
|
6582
6835
|
return { jsonSchemaPath, uiSchemaPath };
|
|
6583
6836
|
}
|
|
6584
|
-
var fs,
|
|
6837
|
+
var fs, path3;
|
|
6585
6838
|
var init_index = __esm({
|
|
6586
6839
|
"src/index.ts"() {
|
|
6587
6840
|
"use strict";
|
|
@@ -6589,7 +6842,7 @@ var init_index = __esm({
|
|
|
6589
6842
|
init_generator2();
|
|
6590
6843
|
init_ir_generator();
|
|
6591
6844
|
fs = __toESM(require("fs"), 1);
|
|
6592
|
-
|
|
6845
|
+
path3 = __toESM(require("path"), 1);
|
|
6593
6846
|
init_extensions();
|
|
6594
6847
|
init_schema2();
|
|
6595
6848
|
init_schema();
|
|
@@ -6606,7 +6859,7 @@ var init_index = __esm({
|
|
|
6606
6859
|
});
|
|
6607
6860
|
|
|
6608
6861
|
// src/cli.ts
|
|
6609
|
-
var
|
|
6862
|
+
var path4 = __toESM(require("path"), 1);
|
|
6610
6863
|
var import_node_url = require("url");
|
|
6611
6864
|
function printHelp() {
|
|
6612
6865
|
console.log(`
|
|
@@ -6695,7 +6948,7 @@ function parseArgs(args) {
|
|
|
6695
6948
|
return null;
|
|
6696
6949
|
}
|
|
6697
6950
|
if (!name) {
|
|
6698
|
-
name =
|
|
6951
|
+
name = path4.basename(inputFile, path4.extname(inputFile));
|
|
6699
6952
|
}
|
|
6700
6953
|
return { inputFile, outDir, name, enumSerialization };
|
|
6701
6954
|
}
|
|
@@ -6706,7 +6959,7 @@ async function main() {
|
|
|
6706
6959
|
process.exit(1);
|
|
6707
6960
|
}
|
|
6708
6961
|
const { inputFile, outDir, name, enumSerialization } = options;
|
|
6709
|
-
const absoluteInput =
|
|
6962
|
+
const absoluteInput = path4.resolve(process.cwd(), inputFile);
|
|
6710
6963
|
try {
|
|
6711
6964
|
const fileUrl = (0, import_node_url.pathToFileURL)(absoluteInput).href;
|
|
6712
6965
|
const module2 = await import(fileUrl);
|