@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.js
CHANGED
|
@@ -243,7 +243,9 @@ function resolveTypeNodeMetadata(type, options) {
|
|
|
243
243
|
case "object":
|
|
244
244
|
return {
|
|
245
245
|
...type,
|
|
246
|
-
properties: type.properties.map(
|
|
246
|
+
properties: type.properties.map(
|
|
247
|
+
(property) => resolveObjectPropertyMetadata(property, options)
|
|
248
|
+
)
|
|
247
249
|
};
|
|
248
250
|
case "record":
|
|
249
251
|
return {
|
|
@@ -1721,10 +1723,7 @@ function generateJsonSchema(form, options) {
|
|
|
1721
1723
|
const metadata = options?.metadata;
|
|
1722
1724
|
const vendorPrefix = options?.vendorPrefix;
|
|
1723
1725
|
const enumSerialization = options?.enumSerialization;
|
|
1724
|
-
const ir = canonicalizeChainDSL(
|
|
1725
|
-
form,
|
|
1726
|
-
metadata !== void 0 ? { metadata } : void 0
|
|
1727
|
-
);
|
|
1726
|
+
const ir = canonicalizeChainDSL(form, metadata !== void 0 ? { metadata } : void 0);
|
|
1728
1727
|
const internalOptions = vendorPrefix === void 0 && enumSerialization === void 0 ? void 0 : {
|
|
1729
1728
|
...vendorPrefix !== void 0 && { vendorPrefix },
|
|
1730
1729
|
...enumSerialization !== void 0 && { enumSerialization }
|
|
@@ -1953,7 +1952,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
|
1953
1952
|
break;
|
|
1954
1953
|
}
|
|
1955
1954
|
case "conditional": {
|
|
1956
|
-
const newRule = createShowRule(
|
|
1955
|
+
const newRule = createShowRule(
|
|
1956
|
+
fieldNameMap.get(element.fieldName) ?? element.fieldName,
|
|
1957
|
+
element.value
|
|
1958
|
+
);
|
|
1957
1959
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
1958
1960
|
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
1959
1961
|
result.push(...childElements);
|
|
@@ -2044,8 +2046,10 @@ function buildConstraintTagSources(extensions) {
|
|
|
2044
2046
|
}
|
|
2045
2047
|
function createExtensionRegistry(extensions) {
|
|
2046
2048
|
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
2049
|
+
let symbolMap = /* @__PURE__ */ new Map();
|
|
2047
2050
|
const typeMap = /* @__PURE__ */ new Map();
|
|
2048
2051
|
const typeNameMap = /* @__PURE__ */ new Map();
|
|
2052
|
+
const brandMap = /* @__PURE__ */ new Map();
|
|
2049
2053
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
2050
2054
|
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
2051
2055
|
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
@@ -2069,6 +2073,20 @@ function createExtensionRegistry(extensions) {
|
|
|
2069
2073
|
registration: type
|
|
2070
2074
|
});
|
|
2071
2075
|
}
|
|
2076
|
+
if (type.brand !== void 0) {
|
|
2077
|
+
if (type.brand === "__integerBrand") {
|
|
2078
|
+
throw new Error(
|
|
2079
|
+
`Brand "__integerBrand" is reserved for the builtin Integer type and cannot be registered by extensions`
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
if (brandMap.has(type.brand)) {
|
|
2083
|
+
throw new Error(`Duplicate custom type brand: "${type.brand}"`);
|
|
2084
|
+
}
|
|
2085
|
+
brandMap.set(type.brand, {
|
|
2086
|
+
extensionId: ext.extensionId,
|
|
2087
|
+
registration: type
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2072
2090
|
if (type.builtinConstraintBroadenings !== void 0) {
|
|
2073
2091
|
for (const broadening of type.builtinConstraintBroadenings) {
|
|
2074
2092
|
const key = `${qualifiedId}:${broadening.tagName}`;
|
|
@@ -2138,7 +2156,10 @@ function createExtensionRegistry(extensions) {
|
|
|
2138
2156
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
|
|
2139
2157
|
);
|
|
2140
2158
|
}
|
|
2141
|
-
if (Object.hasOwn(
|
|
2159
|
+
if (Object.hasOwn(
|
|
2160
|
+
BUILTIN_CONSTRAINT_DEFINITIONS,
|
|
2161
|
+
normalizeConstraintTagName(canonicalTagName)
|
|
2162
|
+
)) {
|
|
2142
2163
|
throw new Error(
|
|
2143
2164
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName(canonicalTagName)}".`
|
|
2144
2165
|
);
|
|
@@ -2159,6 +2180,11 @@ function createExtensionRegistry(extensions) {
|
|
|
2159
2180
|
extensions,
|
|
2160
2181
|
findType: (typeId) => typeMap.get(typeId),
|
|
2161
2182
|
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
2183
|
+
findTypeByBrand: (brand) => brandMap.get(brand),
|
|
2184
|
+
findTypeBySymbol: (symbol) => symbolMap.get(symbol),
|
|
2185
|
+
setSymbolMap: (map) => {
|
|
2186
|
+
symbolMap = map;
|
|
2187
|
+
},
|
|
2162
2188
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
2163
2189
|
findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName(tagName)),
|
|
2164
2190
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
@@ -3063,30 +3089,70 @@ function isObjectType(type) {
|
|
|
3063
3089
|
function isIntersectionType(type) {
|
|
3064
3090
|
return !!(type.flags & ts3.TypeFlags.Intersection);
|
|
3065
3091
|
}
|
|
3092
|
+
function collectBrandIdentifiers(type) {
|
|
3093
|
+
if (!type.isIntersection()) {
|
|
3094
|
+
return [];
|
|
3095
|
+
}
|
|
3096
|
+
const brands = [];
|
|
3097
|
+
for (const prop of type.getProperties()) {
|
|
3098
|
+
const decl = prop.valueDeclaration ?? prop.declarations?.[0];
|
|
3099
|
+
if (decl === void 0) continue;
|
|
3100
|
+
if (!ts3.isPropertySignature(decl) && !ts3.isPropertyDeclaration(decl)) continue;
|
|
3101
|
+
if (!ts3.isComputedPropertyName(decl.name)) continue;
|
|
3102
|
+
if (!ts3.isIdentifier(decl.name.expression)) continue;
|
|
3103
|
+
brands.push(decl.name.expression.text);
|
|
3104
|
+
}
|
|
3105
|
+
return brands;
|
|
3106
|
+
}
|
|
3107
|
+
function resolveCanonicalSymbol(type, checker) {
|
|
3108
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
3109
|
+
if (raw === void 0) return void 0;
|
|
3110
|
+
return raw.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
3111
|
+
}
|
|
3112
|
+
function resolveSymbolBasedCustomType(type, extensionRegistry, checker) {
|
|
3113
|
+
if (extensionRegistry === void 0) {
|
|
3114
|
+
return null;
|
|
3115
|
+
}
|
|
3116
|
+
const canonical = resolveCanonicalSymbol(type, checker);
|
|
3117
|
+
if (canonical === void 0) {
|
|
3118
|
+
return null;
|
|
3119
|
+
}
|
|
3120
|
+
const registration = extensionRegistry.findTypeBySymbol(canonical);
|
|
3121
|
+
if (registration === void 0) {
|
|
3122
|
+
return null;
|
|
3123
|
+
}
|
|
3124
|
+
return {
|
|
3125
|
+
kind: "custom",
|
|
3126
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
3127
|
+
payload: null
|
|
3128
|
+
};
|
|
3129
|
+
}
|
|
3066
3130
|
function isIntegerBrandedType(type) {
|
|
3067
3131
|
if (!type.isIntersection()) {
|
|
3068
3132
|
return false;
|
|
3069
3133
|
}
|
|
3070
|
-
const hasNumberBase = type.types.some(
|
|
3071
|
-
(member) => !!(member.flags & ts3.TypeFlags.Number)
|
|
3072
|
-
);
|
|
3134
|
+
const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
|
|
3073
3135
|
if (!hasNumberBase) {
|
|
3074
3136
|
return false;
|
|
3075
3137
|
}
|
|
3076
|
-
return type
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
return false;
|
|
3138
|
+
return collectBrandIdentifiers(type).includes("__integerBrand");
|
|
3139
|
+
}
|
|
3140
|
+
function resolveBrandedCustomType(type, extensionRegistry) {
|
|
3141
|
+
if (extensionRegistry === void 0) {
|
|
3142
|
+
return null;
|
|
3143
|
+
}
|
|
3144
|
+
for (const brand of collectBrandIdentifiers(type)) {
|
|
3145
|
+
const registration = extensionRegistry.findTypeByBrand(brand);
|
|
3146
|
+
if (registration === void 0) {
|
|
3147
|
+
continue;
|
|
3087
3148
|
}
|
|
3088
|
-
return
|
|
3089
|
-
|
|
3149
|
+
return {
|
|
3150
|
+
kind: "custom",
|
|
3151
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
3152
|
+
payload: null
|
|
3153
|
+
};
|
|
3154
|
+
}
|
|
3155
|
+
return null;
|
|
3090
3156
|
}
|
|
3091
3157
|
function isResolvableObjectLikeAliasTypeNode(typeNode) {
|
|
3092
3158
|
if (ts3.isParenthesizedTypeNode(typeNode)) {
|
|
@@ -4194,6 +4260,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
4194
4260
|
if (customType) {
|
|
4195
4261
|
return customType;
|
|
4196
4262
|
}
|
|
4263
|
+
const symbolCustomType = resolveSymbolBasedCustomType(type, extensionRegistry, checker);
|
|
4264
|
+
if (symbolCustomType) {
|
|
4265
|
+
return symbolCustomType;
|
|
4266
|
+
}
|
|
4267
|
+
const brandedCustomType = resolveBrandedCustomType(type, extensionRegistry);
|
|
4268
|
+
if (brandedCustomType) {
|
|
4269
|
+
return brandedCustomType;
|
|
4270
|
+
}
|
|
4197
4271
|
const primitiveAlias = tryResolveNamedPrimitiveAlias(
|
|
4198
4272
|
type,
|
|
4199
4273
|
checker,
|
|
@@ -5154,7 +5228,7 @@ function createProgramContextFromProgram(program, filePath) {
|
|
|
5154
5228
|
sourceFile
|
|
5155
5229
|
};
|
|
5156
5230
|
}
|
|
5157
|
-
function createProgramContext(filePath) {
|
|
5231
|
+
function createProgramContext(filePath, additionalFiles) {
|
|
5158
5232
|
const absolutePath = path.resolve(filePath);
|
|
5159
5233
|
const fileDir = path.dirname(absolutePath);
|
|
5160
5234
|
const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
|
|
@@ -5177,7 +5251,8 @@ function createProgramContext(filePath) {
|
|
|
5177
5251
|
throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
|
|
5178
5252
|
}
|
|
5179
5253
|
compilerOptions = parsed.options;
|
|
5180
|
-
|
|
5254
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
5255
|
+
fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
|
|
5181
5256
|
} else {
|
|
5182
5257
|
compilerOptions = {
|
|
5183
5258
|
target: ts4.ScriptTarget.ES2022,
|
|
@@ -5187,7 +5262,8 @@ function createProgramContext(filePath) {
|
|
|
5187
5262
|
skipLibCheck: true,
|
|
5188
5263
|
declaration: true
|
|
5189
5264
|
};
|
|
5190
|
-
|
|
5265
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
5266
|
+
fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
|
|
5191
5267
|
}
|
|
5192
5268
|
const program = ts4.createProgram(fileNames, compilerOptions);
|
|
5193
5269
|
const sourceFile = program.getSourceFile(absolutePath);
|
|
@@ -5497,10 +5573,139 @@ var init_program = __esm({
|
|
|
5497
5573
|
}
|
|
5498
5574
|
});
|
|
5499
5575
|
|
|
5576
|
+
// src/extensions/symbol-registry.ts
|
|
5577
|
+
import * as ts5 from "typescript";
|
|
5578
|
+
import * as path2 from "path";
|
|
5579
|
+
function buildSymbolMapFromConfig(configPath, program, checker, extensionRegistry) {
|
|
5580
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
5581
|
+
const normalizedPath = path2.resolve(configPath);
|
|
5582
|
+
const configFile = program.getSourceFile(normalizedPath);
|
|
5583
|
+
if (configFile === void 0) {
|
|
5584
|
+
return symbolMap;
|
|
5585
|
+
}
|
|
5586
|
+
function visit(node) {
|
|
5587
|
+
if (ts5.isCallExpression(node) && isDefineCustomTypeCall(node, checker)) {
|
|
5588
|
+
processDefineCustomTypeCall(node);
|
|
5589
|
+
}
|
|
5590
|
+
ts5.forEachChild(node, visit);
|
|
5591
|
+
}
|
|
5592
|
+
function processDefineCustomTypeCall(call) {
|
|
5593
|
+
const typeArgNode = call.typeArguments?.[0];
|
|
5594
|
+
if (typeArgNode === void 0) {
|
|
5595
|
+
return;
|
|
5596
|
+
}
|
|
5597
|
+
const resolvedType = checker.getTypeFromTypeNode(typeArgNode);
|
|
5598
|
+
const canonical = resolveCanonicalSymbol2(resolvedType, checker);
|
|
5599
|
+
if (canonical === void 0) {
|
|
5600
|
+
return;
|
|
5601
|
+
}
|
|
5602
|
+
const typeName = extractTypeNameFromCallArg(call);
|
|
5603
|
+
if (typeName === null) {
|
|
5604
|
+
return;
|
|
5605
|
+
}
|
|
5606
|
+
let entry;
|
|
5607
|
+
const extensionId = extractEnclosingExtensionId(call, checker);
|
|
5608
|
+
if (extensionId !== null) {
|
|
5609
|
+
const reg = extensionRegistry.findType(`${extensionId}/${typeName}`);
|
|
5610
|
+
if (reg !== void 0) {
|
|
5611
|
+
entry = { extensionId, registration: reg };
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
entry ??= findRegistrationByTypeName(extensionRegistry, typeName);
|
|
5615
|
+
if (entry === void 0) {
|
|
5616
|
+
return;
|
|
5617
|
+
}
|
|
5618
|
+
symbolMap.set(canonical, entry);
|
|
5619
|
+
}
|
|
5620
|
+
visit(configFile);
|
|
5621
|
+
return symbolMap;
|
|
5622
|
+
}
|
|
5623
|
+
function isDefineCustomTypeCall(node, checker) {
|
|
5624
|
+
if (node.typeArguments === void 0 || node.typeArguments.length === 0) return false;
|
|
5625
|
+
const callSymbol = checker.getSymbolAtLocation(node.expression);
|
|
5626
|
+
if (callSymbol !== void 0) {
|
|
5627
|
+
const resolved = callSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(callSymbol) : callSymbol;
|
|
5628
|
+
const decl = resolved.declarations?.[0];
|
|
5629
|
+
if (decl !== void 0) {
|
|
5630
|
+
const sourceFile = decl.getSourceFile().fileName.replace(/\\/g, "/");
|
|
5631
|
+
return resolved.name === "defineCustomType" && // Match whether in node_modules/@formspec/core or monorepo packages/core.
|
|
5632
|
+
(sourceFile.includes("@formspec/core") || sourceFile.includes("/packages/core/"));
|
|
5633
|
+
}
|
|
5634
|
+
}
|
|
5635
|
+
return ts5.isIdentifier(node.expression) && node.expression.text === "defineCustomType";
|
|
5636
|
+
}
|
|
5637
|
+
function resolveCanonicalSymbol2(type, checker) {
|
|
5638
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
5639
|
+
if (raw === void 0) return void 0;
|
|
5640
|
+
return raw.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
5641
|
+
}
|
|
5642
|
+
function extractTypeNameFromCallArg(call) {
|
|
5643
|
+
const arg = call.arguments[0];
|
|
5644
|
+
if (arg === void 0 || !ts5.isObjectLiteralExpression(arg)) {
|
|
5645
|
+
return null;
|
|
5646
|
+
}
|
|
5647
|
+
const typeNameProp = arg.properties.find(
|
|
5648
|
+
(p) => ts5.isPropertyAssignment(p) && ts5.isIdentifier(p.name) && p.name.text === "typeName"
|
|
5649
|
+
);
|
|
5650
|
+
if (typeNameProp === void 0 || !ts5.isStringLiteral(typeNameProp.initializer)) {
|
|
5651
|
+
return null;
|
|
5652
|
+
}
|
|
5653
|
+
return typeNameProp.initializer.text;
|
|
5654
|
+
}
|
|
5655
|
+
function extractEnclosingExtensionId(call, checker) {
|
|
5656
|
+
for (let node = call.parent; !ts5.isSourceFile(node); node = node.parent) {
|
|
5657
|
+
if (ts5.isCallExpression(node) && isDefineExtensionCall(node, checker)) {
|
|
5658
|
+
return extractExtensionIdFromCallArg(node);
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
return null;
|
|
5662
|
+
}
|
|
5663
|
+
function isDefineExtensionCall(node, checker) {
|
|
5664
|
+
const callSymbol = checker.getSymbolAtLocation(node.expression);
|
|
5665
|
+
if (callSymbol !== void 0) {
|
|
5666
|
+
const resolved = callSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(callSymbol) : callSymbol;
|
|
5667
|
+
const decl = resolved.declarations?.[0];
|
|
5668
|
+
if (decl !== void 0) {
|
|
5669
|
+
const sourceFile = decl.getSourceFile().fileName.replace(/\\/g, "/");
|
|
5670
|
+
return resolved.name === "defineExtension" && (sourceFile.includes("@formspec/core") || sourceFile.includes("/packages/core/"));
|
|
5671
|
+
}
|
|
5672
|
+
}
|
|
5673
|
+
return ts5.isIdentifier(node.expression) && node.expression.text === "defineExtension";
|
|
5674
|
+
}
|
|
5675
|
+
function extractExtensionIdFromCallArg(call) {
|
|
5676
|
+
const arg = call.arguments[0];
|
|
5677
|
+
if (arg === void 0 || !ts5.isObjectLiteralExpression(arg)) {
|
|
5678
|
+
return null;
|
|
5679
|
+
}
|
|
5680
|
+
const prop = arg.properties.find(
|
|
5681
|
+
(p) => ts5.isPropertyAssignment(p) && ts5.isIdentifier(p.name) && p.name.text === "extensionId"
|
|
5682
|
+
);
|
|
5683
|
+
if (prop === void 0 || !ts5.isStringLiteral(prop.initializer)) {
|
|
5684
|
+
return null;
|
|
5685
|
+
}
|
|
5686
|
+
return prop.initializer.text;
|
|
5687
|
+
}
|
|
5688
|
+
function findRegistrationByTypeName(registry, typeName) {
|
|
5689
|
+
for (const ext of registry.extensions) {
|
|
5690
|
+
if (ext.types === void 0) {
|
|
5691
|
+
continue;
|
|
5692
|
+
}
|
|
5693
|
+
for (const type of ext.types) {
|
|
5694
|
+
if (type.typeName === typeName) {
|
|
5695
|
+
return { extensionId: ext.extensionId, registration: type };
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
5698
|
+
}
|
|
5699
|
+
return void 0;
|
|
5700
|
+
}
|
|
5701
|
+
var init_symbol_registry = __esm({
|
|
5702
|
+
"src/extensions/symbol-registry.ts"() {
|
|
5703
|
+
"use strict";
|
|
5704
|
+
}
|
|
5705
|
+
});
|
|
5706
|
+
|
|
5500
5707
|
// src/validate/constraint-validator.ts
|
|
5501
|
-
import {
|
|
5502
|
-
analyzeConstraintTargets
|
|
5503
|
-
} from "@formspec/analysis/internal";
|
|
5708
|
+
import { analyzeConstraintTargets } from "@formspec/analysis/internal";
|
|
5504
5709
|
function validateFieldNode(ctx, field) {
|
|
5505
5710
|
const analysis = analyzeConstraintTargets(
|
|
5506
5711
|
field.name,
|
|
@@ -5586,7 +5791,7 @@ var init_validate = __esm({
|
|
|
5586
5791
|
});
|
|
5587
5792
|
|
|
5588
5793
|
// src/generators/class-schema.ts
|
|
5589
|
-
import * as
|
|
5794
|
+
import * as ts6 from "typescript";
|
|
5590
5795
|
function generateClassSchemas(analysis, source, options) {
|
|
5591
5796
|
const result = generateClassSchemasDetailed(analysis, source, options);
|
|
5592
5797
|
if (!result.ok || result.jsonSchema === void 0 || result.uiSchema === void 0) {
|
|
@@ -5645,7 +5850,8 @@ function formatLocation(location) {
|
|
|
5645
5850
|
return `${location.file}:${String(location.line)}:${String(location.column)}`;
|
|
5646
5851
|
}
|
|
5647
5852
|
function generateSchemasFromClass(options) {
|
|
5648
|
-
const
|
|
5853
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5854
|
+
const ctx = createProgramContext(options.filePath, additionalFiles);
|
|
5649
5855
|
const classDecl = findClassByName(ctx.sourceFile, options.className);
|
|
5650
5856
|
if (!classDecl) {
|
|
5651
5857
|
throw new Error(`Class "${options.className}" not found in ${options.filePath}`);
|
|
@@ -5710,7 +5916,8 @@ function generateSchemasDetailed(options) {
|
|
|
5710
5916
|
function generateSchemasDetailedInternal(options) {
|
|
5711
5917
|
let ctx;
|
|
5712
5918
|
try {
|
|
5713
|
-
|
|
5919
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5920
|
+
ctx = createProgramContext(options.filePath, additionalFiles);
|
|
5714
5921
|
} catch (error) {
|
|
5715
5922
|
return {
|
|
5716
5923
|
ok: false,
|
|
@@ -5749,13 +5956,16 @@ function generateSchemasFromProgramDetailedInternal(options) {
|
|
|
5749
5956
|
}
|
|
5750
5957
|
function generateSchemasBatch(options) {
|
|
5751
5958
|
const contextCache = /* @__PURE__ */ new Map();
|
|
5959
|
+
const resolved = resolveOptions(options);
|
|
5960
|
+
let symbolMapProgram;
|
|
5752
5961
|
return options.targets.map((target) => {
|
|
5753
5962
|
let ctx;
|
|
5754
5963
|
try {
|
|
5755
|
-
const cacheKey =
|
|
5964
|
+
const cacheKey = ts6.sys.useCaseSensitiveFileNames ? target.filePath : target.filePath.toLowerCase();
|
|
5756
5965
|
const cachedContext = contextCache.get(cacheKey);
|
|
5757
5966
|
if (cachedContext === void 0) {
|
|
5758
|
-
|
|
5967
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5968
|
+
ctx = createProgramContext(target.filePath, additionalFiles);
|
|
5759
5969
|
contextCache.set(cacheKey, ctx);
|
|
5760
5970
|
} else {
|
|
5761
5971
|
ctx = cachedContext;
|
|
@@ -5766,9 +5976,25 @@ function generateSchemasBatch(options) {
|
|
|
5766
5976
|
diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
|
|
5767
5977
|
});
|
|
5768
5978
|
}
|
|
5979
|
+
if (options.configPath !== void 0 && resolved.extensionRegistry !== void 0 && isMutableRegistry(resolved.extensionRegistry) && ctx.program !== symbolMapProgram) {
|
|
5980
|
+
const symbolMap = buildSymbolMapFromConfig(
|
|
5981
|
+
options.configPath,
|
|
5982
|
+
ctx.program,
|
|
5983
|
+
ctx.checker,
|
|
5984
|
+
resolved.extensionRegistry
|
|
5985
|
+
);
|
|
5986
|
+
resolved.extensionRegistry.setSymbolMap(symbolMap);
|
|
5987
|
+
symbolMapProgram = ctx.program;
|
|
5988
|
+
}
|
|
5769
5989
|
return withTarget(
|
|
5770
5990
|
target,
|
|
5771
|
-
|
|
5991
|
+
generateSchemasFromResolvedOptions(
|
|
5992
|
+
ctx,
|
|
5993
|
+
target.filePath,
|
|
5994
|
+
target.typeName,
|
|
5995
|
+
resolved,
|
|
5996
|
+
options.discriminator
|
|
5997
|
+
)
|
|
5772
5998
|
);
|
|
5773
5999
|
});
|
|
5774
6000
|
}
|
|
@@ -5789,11 +6015,19 @@ function generateSchemasBatchFromProgram(options) {
|
|
|
5789
6015
|
);
|
|
5790
6016
|
});
|
|
5791
6017
|
}
|
|
6018
|
+
function isMutableRegistry(reg) {
|
|
6019
|
+
return "setSymbolMap" in reg && typeof reg.setSymbolMap === "function";
|
|
6020
|
+
}
|
|
5792
6021
|
function resolveOptions(options) {
|
|
5793
6022
|
const configRegistry = options.config?.extensions !== void 0 ? createExtensionRegistry(options.config.extensions) : void 0;
|
|
6023
|
+
const legacyRegistry = options.extensionRegistry;
|
|
5794
6024
|
return {
|
|
5795
|
-
//
|
|
5796
|
-
|
|
6025
|
+
// When the caller provides the deprecated extensionRegistry field directly,
|
|
6026
|
+
// it is typed as the read-only ExtensionRegistry interface. We cast here
|
|
6027
|
+
// because the legacy path was introduced before MutableExtensionRegistry was
|
|
6028
|
+
// split out; callers using createExtensionRegistry() always get a mutable
|
|
6029
|
+
// registry, and this cast is safe for all registries produced by this module.
|
|
6030
|
+
extensionRegistry: legacyRegistry ?? configRegistry,
|
|
5797
6031
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
5798
6032
|
vendorPrefix: options.vendorPrefix ?? options.config?.vendorPrefix,
|
|
5799
6033
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
@@ -5804,13 +6038,31 @@ function resolveOptions(options) {
|
|
|
5804
6038
|
}
|
|
5805
6039
|
function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, options) {
|
|
5806
6040
|
const resolved = resolveOptions(options);
|
|
6041
|
+
if (options.configPath !== void 0 && resolved.extensionRegistry !== void 0 && isMutableRegistry(resolved.extensionRegistry)) {
|
|
6042
|
+
const symbolMap = buildSymbolMapFromConfig(
|
|
6043
|
+
options.configPath,
|
|
6044
|
+
ctx.program,
|
|
6045
|
+
ctx.checker,
|
|
6046
|
+
resolved.extensionRegistry
|
|
6047
|
+
);
|
|
6048
|
+
resolved.extensionRegistry.setSymbolMap(symbolMap);
|
|
6049
|
+
}
|
|
6050
|
+
return generateSchemasFromResolvedOptions(
|
|
6051
|
+
ctx,
|
|
6052
|
+
filePath,
|
|
6053
|
+
typeName,
|
|
6054
|
+
resolved,
|
|
6055
|
+
options.discriminator
|
|
6056
|
+
);
|
|
6057
|
+
}
|
|
6058
|
+
function generateSchemasFromResolvedOptions(ctx, filePath, typeName, resolved, discriminator) {
|
|
5807
6059
|
const analysisResult = analyzeNamedTypeToIRFromProgramContextDetailed(
|
|
5808
6060
|
ctx,
|
|
5809
6061
|
filePath,
|
|
5810
6062
|
typeName,
|
|
5811
6063
|
resolved.extensionRegistry,
|
|
5812
6064
|
resolved.metadata,
|
|
5813
|
-
|
|
6065
|
+
discriminator
|
|
5814
6066
|
);
|
|
5815
6067
|
if (!analysisResult.ok) {
|
|
5816
6068
|
return {
|
|
@@ -5858,13 +6110,14 @@ var init_class_schema = __esm({
|
|
|
5858
6110
|
init_canonicalize();
|
|
5859
6111
|
init_ir_generator();
|
|
5860
6112
|
init_extensions();
|
|
6113
|
+
init_symbol_registry();
|
|
5861
6114
|
init_ir_generator2();
|
|
5862
6115
|
init_validate();
|
|
5863
6116
|
}
|
|
5864
6117
|
});
|
|
5865
6118
|
|
|
5866
6119
|
// src/static-build.ts
|
|
5867
|
-
import * as
|
|
6120
|
+
import * as ts7 from "typescript";
|
|
5868
6121
|
function toStaticBuildContext(context) {
|
|
5869
6122
|
return context;
|
|
5870
6123
|
}
|
|
@@ -5879,7 +6132,7 @@ function getModuleSymbol(context) {
|
|
|
5879
6132
|
return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
|
|
5880
6133
|
}
|
|
5881
6134
|
function isSchemaSourceDeclaration(declaration) {
|
|
5882
|
-
return
|
|
6135
|
+
return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
|
|
5883
6136
|
}
|
|
5884
6137
|
function resolveModuleExport(context, exportName = "default") {
|
|
5885
6138
|
const moduleSymbol = getModuleSymbol(context);
|
|
@@ -5890,7 +6143,7 @@ function resolveModuleExport(context, exportName = "default") {
|
|
|
5890
6143
|
if (exportSymbol === null) {
|
|
5891
6144
|
return null;
|
|
5892
6145
|
}
|
|
5893
|
-
return exportSymbol.flags &
|
|
6146
|
+
return exportSymbol.flags & ts7.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
|
|
5894
6147
|
}
|
|
5895
6148
|
function resolveModuleExportDeclaration(context, exportName = "default") {
|
|
5896
6149
|
return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
|
|
@@ -5903,7 +6156,7 @@ var init_static_build = __esm({
|
|
|
5903
6156
|
});
|
|
5904
6157
|
|
|
5905
6158
|
// src/generators/discovered-schema.ts
|
|
5906
|
-
import * as
|
|
6159
|
+
import * as ts8 from "typescript";
|
|
5907
6160
|
import { analyzeMetadataForNodeWithChecker as analyzeMetadataForNodeWithChecker2 } from "@formspec/analysis/internal";
|
|
5908
6161
|
import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
|
|
5909
6162
|
function toDiscoveredTypeSchemas(result, resolvedMetadata) {
|
|
@@ -5913,17 +6166,17 @@ function toDiscoveredTypeSchemas(result, resolvedMetadata) {
|
|
|
5913
6166
|
};
|
|
5914
6167
|
}
|
|
5915
6168
|
function isNamedTypeDeclaration(declaration) {
|
|
5916
|
-
return
|
|
6169
|
+
return ts8.isClassDeclaration(declaration) || ts8.isInterfaceDeclaration(declaration) || ts8.isTypeAliasDeclaration(declaration);
|
|
5917
6170
|
}
|
|
5918
6171
|
function hasConcreteTypeArguments(type, checker) {
|
|
5919
6172
|
if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
|
|
5920
6173
|
return true;
|
|
5921
6174
|
}
|
|
5922
|
-
if ((type.flags &
|
|
6175
|
+
if ((type.flags & ts8.TypeFlags.Object) === 0) {
|
|
5923
6176
|
return false;
|
|
5924
6177
|
}
|
|
5925
6178
|
const objectType = type;
|
|
5926
|
-
if ((objectType.objectFlags &
|
|
6179
|
+
if ((objectType.objectFlags & ts8.ObjectFlags.Reference) === 0) {
|
|
5927
6180
|
return false;
|
|
5928
6181
|
}
|
|
5929
6182
|
return checker.getTypeArguments(objectType).length > 0;
|
|
@@ -5936,13 +6189,13 @@ function getNamedTypeDeclaration2(type) {
|
|
|
5936
6189
|
return declaration;
|
|
5937
6190
|
}
|
|
5938
6191
|
}
|
|
5939
|
-
const aliasDeclaration = type.aliasSymbol?.declarations?.find(
|
|
6192
|
+
const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts8.isTypeAliasDeclaration);
|
|
5940
6193
|
return aliasDeclaration;
|
|
5941
6194
|
}
|
|
5942
6195
|
function getFallbackName(sourceNode, fallback = "AnonymousType") {
|
|
5943
6196
|
if (sourceNode !== void 0 && "name" in sourceNode) {
|
|
5944
6197
|
const namedNode = sourceNode;
|
|
5945
|
-
if (namedNode.name !== void 0 &&
|
|
6198
|
+
if (namedNode.name !== void 0 && ts8.isIdentifier(namedNode.name)) {
|
|
5946
6199
|
return namedNode.name.text;
|
|
5947
6200
|
}
|
|
5948
6201
|
}
|
|
@@ -6061,17 +6314,14 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
|
|
|
6061
6314
|
rootLogicalName: root.name
|
|
6062
6315
|
}
|
|
6063
6316
|
);
|
|
6064
|
-
const schema = generateJsonSchemaFromIR(
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
vendorPrefix: options?.vendorPrefix
|
|
6073
|
-
}
|
|
6074
|
-
);
|
|
6317
|
+
const schema = generateJsonSchemaFromIR(ir, {
|
|
6318
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6319
|
+
extensionRegistry: options?.extensionRegistry,
|
|
6320
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6321
|
+
enumSerialization: options?.enumSerialization,
|
|
6322
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6323
|
+
vendorPrefix: options?.vendorPrefix
|
|
6324
|
+
});
|
|
6075
6325
|
const result = schema.properties?.["__result"];
|
|
6076
6326
|
if (result === void 0) {
|
|
6077
6327
|
throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
|
|
@@ -6170,7 +6420,7 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
|
|
|
6170
6420
|
}
|
|
6171
6421
|
function generateSchemasFromDeclaration(options) {
|
|
6172
6422
|
const filePath = options.declaration.getSourceFile().fileName;
|
|
6173
|
-
if (
|
|
6423
|
+
if (ts8.isClassDeclaration(options.declaration)) {
|
|
6174
6424
|
return generateSchemasFromAnalysis(
|
|
6175
6425
|
analyzeClassToIR(
|
|
6176
6426
|
options.declaration,
|
|
@@ -6186,7 +6436,7 @@ function generateSchemasFromDeclaration(options) {
|
|
|
6186
6436
|
options
|
|
6187
6437
|
);
|
|
6188
6438
|
}
|
|
6189
|
-
if (
|
|
6439
|
+
if (ts8.isInterfaceDeclaration(options.declaration)) {
|
|
6190
6440
|
return generateSchemasFromAnalysis(
|
|
6191
6441
|
analyzeInterfaceToIR(
|
|
6192
6442
|
options.declaration,
|
|
@@ -6202,7 +6452,7 @@ function generateSchemasFromDeclaration(options) {
|
|
|
6202
6452
|
options
|
|
6203
6453
|
);
|
|
6204
6454
|
}
|
|
6205
|
-
if (
|
|
6455
|
+
if (ts8.isTypeAliasDeclaration(options.declaration)) {
|
|
6206
6456
|
const analyzedAlias = analyzeTypeAliasToIR(
|
|
6207
6457
|
options.declaration,
|
|
6208
6458
|
options.context.checker,
|
|
@@ -6265,7 +6515,7 @@ function generateSchemasFromReturnType(options) {
|
|
|
6265
6515
|
const returnType = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
|
|
6266
6516
|
const type = unwrapPromiseType(options.context.checker, returnType);
|
|
6267
6517
|
const sourceNode = type !== returnType ? unwrapPromiseTypeNode(options.declaration.type) ?? options.declaration.type ?? options.declaration : options.declaration.type ?? options.declaration;
|
|
6268
|
-
const fallbackName = options.declaration.name !== void 0 &&
|
|
6518
|
+
const fallbackName = options.declaration.name !== void 0 && ts8.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
|
|
6269
6519
|
return generateSchemasFromResolvedType({
|
|
6270
6520
|
...options,
|
|
6271
6521
|
type,
|
|
@@ -6300,14 +6550,14 @@ function unwrapPromiseTypeNode(typeNode) {
|
|
|
6300
6550
|
if (typeNode === void 0) {
|
|
6301
6551
|
return void 0;
|
|
6302
6552
|
}
|
|
6303
|
-
if (
|
|
6553
|
+
if (ts8.isParenthesizedTypeNode(typeNode)) {
|
|
6304
6554
|
const unwrapped = unwrapPromiseTypeNode(typeNode.type);
|
|
6305
6555
|
return unwrapped ?? typeNode;
|
|
6306
6556
|
}
|
|
6307
6557
|
return isPromiseTypeReferenceNode(typeNode) ? typeNode.typeArguments[0] : typeNode;
|
|
6308
6558
|
}
|
|
6309
6559
|
function isPromiseTypeReferenceNode(typeNode) {
|
|
6310
|
-
return
|
|
6560
|
+
return ts8.isTypeReferenceNode(typeNode) && ts8.isIdentifier(typeNode.typeName) && typeNode.typeName.text === "Promise" && typeNode.typeArguments !== void 0 && typeNode.typeArguments.length > 0;
|
|
6311
6561
|
}
|
|
6312
6562
|
var init_discovered_schema = __esm({
|
|
6313
6563
|
"src/generators/discovered-schema.ts"() {
|
|
@@ -6552,7 +6802,7 @@ __export(index_exports, {
|
|
|
6552
6802
|
writeSchemas: () => writeSchemas
|
|
6553
6803
|
});
|
|
6554
6804
|
import * as fs from "fs";
|
|
6555
|
-
import * as
|
|
6805
|
+
import * as path3 from "path";
|
|
6556
6806
|
function buildFormSchemas(form, options) {
|
|
6557
6807
|
return {
|
|
6558
6808
|
jsonSchema: generateJsonSchema(form, options),
|
|
@@ -6577,8 +6827,8 @@ function writeSchemas(form, options) {
|
|
|
6577
6827
|
if (!fs.existsSync(outDir)) {
|
|
6578
6828
|
fs.mkdirSync(outDir, { recursive: true });
|
|
6579
6829
|
}
|
|
6580
|
-
const jsonSchemaPath =
|
|
6581
|
-
const uiSchemaPath =
|
|
6830
|
+
const jsonSchemaPath = path3.join(outDir, `${name}-schema.json`);
|
|
6831
|
+
const uiSchemaPath = path3.join(outDir, `${name}-uischema.json`);
|
|
6582
6832
|
fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));
|
|
6583
6833
|
fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema2, null, indent));
|
|
6584
6834
|
return { jsonSchemaPath, uiSchemaPath };
|
|
@@ -6605,7 +6855,7 @@ var init_index = __esm({
|
|
|
6605
6855
|
});
|
|
6606
6856
|
|
|
6607
6857
|
// src/cli.ts
|
|
6608
|
-
import * as
|
|
6858
|
+
import * as path4 from "path";
|
|
6609
6859
|
import { pathToFileURL } from "url";
|
|
6610
6860
|
function printHelp() {
|
|
6611
6861
|
console.log(`
|
|
@@ -6694,7 +6944,7 @@ function parseArgs(args) {
|
|
|
6694
6944
|
return null;
|
|
6695
6945
|
}
|
|
6696
6946
|
if (!name) {
|
|
6697
|
-
name =
|
|
6947
|
+
name = path4.basename(inputFile, path4.extname(inputFile));
|
|
6698
6948
|
}
|
|
6699
6949
|
return { inputFile, outDir, name, enumSerialization };
|
|
6700
6950
|
}
|
|
@@ -6705,7 +6955,7 @@ async function main() {
|
|
|
6705
6955
|
process.exit(1);
|
|
6706
6956
|
}
|
|
6707
6957
|
const { inputFile, outDir, name, enumSerialization } = options;
|
|
6708
|
-
const absoluteInput =
|
|
6958
|
+
const absoluteInput = path4.resolve(process.cwd(), inputFile);
|
|
6709
6959
|
try {
|
|
6710
6960
|
const fileUrl = pathToFileURL(absoluteInput).href;
|
|
6711
6961
|
const module = await import(fileUrl);
|