@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/index.cjs
CHANGED
|
@@ -288,7 +288,9 @@ function resolveTypeNodeMetadata(type, options) {
|
|
|
288
288
|
case "object":
|
|
289
289
|
return {
|
|
290
290
|
...type,
|
|
291
|
-
properties: type.properties.map(
|
|
291
|
+
properties: type.properties.map(
|
|
292
|
+
(property) => resolveObjectPropertyMetadata(property, options)
|
|
293
|
+
)
|
|
292
294
|
};
|
|
293
295
|
case "record":
|
|
294
296
|
return {
|
|
@@ -1714,10 +1716,7 @@ function generateJsonSchema(form, options) {
|
|
|
1714
1716
|
const metadata = options?.metadata;
|
|
1715
1717
|
const vendorPrefix = options?.vendorPrefix;
|
|
1716
1718
|
const enumSerialization = options?.enumSerialization;
|
|
1717
|
-
const ir = canonicalizeChainDSL(
|
|
1718
|
-
form,
|
|
1719
|
-
metadata !== void 0 ? { metadata } : void 0
|
|
1720
|
-
);
|
|
1719
|
+
const ir = canonicalizeChainDSL(form, metadata !== void 0 ? { metadata } : void 0);
|
|
1721
1720
|
const internalOptions = vendorPrefix === void 0 && enumSerialization === void 0 ? void 0 : {
|
|
1722
1721
|
...vendorPrefix !== void 0 && { vendorPrefix },
|
|
1723
1722
|
...enumSerialization !== void 0 && { enumSerialization }
|
|
@@ -1933,7 +1932,10 @@ function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
|
1933
1932
|
break;
|
|
1934
1933
|
}
|
|
1935
1934
|
case "conditional": {
|
|
1936
|
-
const newRule = createShowRule(
|
|
1935
|
+
const newRule = createShowRule(
|
|
1936
|
+
fieldNameMap.get(element.fieldName) ?? element.fieldName,
|
|
1937
|
+
element.value
|
|
1938
|
+
);
|
|
1937
1939
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
1938
1940
|
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
1939
1941
|
result.push(...childElements);
|
|
@@ -1990,7 +1992,7 @@ function generateUiSchema(form, options) {
|
|
|
1990
1992
|
|
|
1991
1993
|
// src/index.ts
|
|
1992
1994
|
var fs = __toESM(require("fs"), 1);
|
|
1993
|
-
var
|
|
1995
|
+
var path3 = __toESM(require("path"), 1);
|
|
1994
1996
|
|
|
1995
1997
|
// src/extensions/registry.ts
|
|
1996
1998
|
var import_internals3 = require("@formspec/core/internals");
|
|
@@ -2008,8 +2010,10 @@ function buildConstraintTagSources(extensions) {
|
|
|
2008
2010
|
}
|
|
2009
2011
|
function createExtensionRegistry(extensions) {
|
|
2010
2012
|
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
2013
|
+
let symbolMap = /* @__PURE__ */ new Map();
|
|
2011
2014
|
const typeMap = /* @__PURE__ */ new Map();
|
|
2012
2015
|
const typeNameMap = /* @__PURE__ */ new Map();
|
|
2016
|
+
const brandMap = /* @__PURE__ */ new Map();
|
|
2013
2017
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
2014
2018
|
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
2015
2019
|
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
@@ -2033,6 +2037,20 @@ function createExtensionRegistry(extensions) {
|
|
|
2033
2037
|
registration: type
|
|
2034
2038
|
});
|
|
2035
2039
|
}
|
|
2040
|
+
if (type.brand !== void 0) {
|
|
2041
|
+
if (type.brand === "__integerBrand") {
|
|
2042
|
+
throw new Error(
|
|
2043
|
+
`Brand "__integerBrand" is reserved for the builtin Integer type and cannot be registered by extensions`
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
if (brandMap.has(type.brand)) {
|
|
2047
|
+
throw new Error(`Duplicate custom type brand: "${type.brand}"`);
|
|
2048
|
+
}
|
|
2049
|
+
brandMap.set(type.brand, {
|
|
2050
|
+
extensionId: ext.extensionId,
|
|
2051
|
+
registration: type
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2036
2054
|
if (type.builtinConstraintBroadenings !== void 0) {
|
|
2037
2055
|
for (const broadening of type.builtinConstraintBroadenings) {
|
|
2038
2056
|
const key = `${qualifiedId}:${broadening.tagName}`;
|
|
@@ -2102,7 +2120,10 @@ function createExtensionRegistry(extensions) {
|
|
|
2102
2120
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
|
|
2103
2121
|
);
|
|
2104
2122
|
}
|
|
2105
|
-
if (Object.hasOwn(
|
|
2123
|
+
if (Object.hasOwn(
|
|
2124
|
+
import_internals3.BUILTIN_CONSTRAINT_DEFINITIONS,
|
|
2125
|
+
(0, import_internals3.normalizeConstraintTagName)(canonicalTagName)
|
|
2126
|
+
)) {
|
|
2106
2127
|
throw new Error(
|
|
2107
2128
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals3.normalizeConstraintTagName)(canonicalTagName)}".`
|
|
2108
2129
|
);
|
|
@@ -2123,6 +2144,11 @@ function createExtensionRegistry(extensions) {
|
|
|
2123
2144
|
extensions,
|
|
2124
2145
|
findType: (typeId) => typeMap.get(typeId),
|
|
2125
2146
|
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
2147
|
+
findTypeByBrand: (brand) => brandMap.get(brand),
|
|
2148
|
+
findTypeBySymbol: (symbol) => symbolMap.get(symbol),
|
|
2149
|
+
setSymbolMap: (map) => {
|
|
2150
|
+
symbolMap = map;
|
|
2151
|
+
},
|
|
2126
2152
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
2127
2153
|
findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal.normalizeFormSpecTagName)(tagName)),
|
|
2128
2154
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
@@ -2193,7 +2219,7 @@ var jsonSchema7Schema = import_zod3.z.lazy(
|
|
|
2193
2219
|
);
|
|
2194
2220
|
|
|
2195
2221
|
// src/generators/class-schema.ts
|
|
2196
|
-
var
|
|
2222
|
+
var ts6 = __toESM(require("typescript"), 1);
|
|
2197
2223
|
|
|
2198
2224
|
// src/analyzer/program.ts
|
|
2199
2225
|
var ts4 = __toESM(require("typescript"), 1);
|
|
@@ -2984,30 +3010,70 @@ function isObjectType(type) {
|
|
|
2984
3010
|
function isIntersectionType(type) {
|
|
2985
3011
|
return !!(type.flags & ts3.TypeFlags.Intersection);
|
|
2986
3012
|
}
|
|
3013
|
+
function collectBrandIdentifiers(type) {
|
|
3014
|
+
if (!type.isIntersection()) {
|
|
3015
|
+
return [];
|
|
3016
|
+
}
|
|
3017
|
+
const brands = [];
|
|
3018
|
+
for (const prop of type.getProperties()) {
|
|
3019
|
+
const decl = prop.valueDeclaration ?? prop.declarations?.[0];
|
|
3020
|
+
if (decl === void 0) continue;
|
|
3021
|
+
if (!ts3.isPropertySignature(decl) && !ts3.isPropertyDeclaration(decl)) continue;
|
|
3022
|
+
if (!ts3.isComputedPropertyName(decl.name)) continue;
|
|
3023
|
+
if (!ts3.isIdentifier(decl.name.expression)) continue;
|
|
3024
|
+
brands.push(decl.name.expression.text);
|
|
3025
|
+
}
|
|
3026
|
+
return brands;
|
|
3027
|
+
}
|
|
3028
|
+
function resolveCanonicalSymbol(type, checker) {
|
|
3029
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
3030
|
+
if (raw === void 0) return void 0;
|
|
3031
|
+
return raw.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
3032
|
+
}
|
|
3033
|
+
function resolveSymbolBasedCustomType(type, extensionRegistry, checker) {
|
|
3034
|
+
if (extensionRegistry === void 0) {
|
|
3035
|
+
return null;
|
|
3036
|
+
}
|
|
3037
|
+
const canonical = resolveCanonicalSymbol(type, checker);
|
|
3038
|
+
if (canonical === void 0) {
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
const registration = extensionRegistry.findTypeBySymbol(canonical);
|
|
3042
|
+
if (registration === void 0) {
|
|
3043
|
+
return null;
|
|
3044
|
+
}
|
|
3045
|
+
return {
|
|
3046
|
+
kind: "custom",
|
|
3047
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
3048
|
+
payload: null
|
|
3049
|
+
};
|
|
3050
|
+
}
|
|
2987
3051
|
function isIntegerBrandedType(type) {
|
|
2988
3052
|
if (!type.isIntersection()) {
|
|
2989
3053
|
return false;
|
|
2990
3054
|
}
|
|
2991
|
-
const hasNumberBase = type.types.some(
|
|
2992
|
-
(member) => !!(member.flags & ts3.TypeFlags.Number)
|
|
2993
|
-
);
|
|
3055
|
+
const hasNumberBase = type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number));
|
|
2994
3056
|
if (!hasNumberBase) {
|
|
2995
3057
|
return false;
|
|
2996
3058
|
}
|
|
2997
|
-
return type
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
return false;
|
|
3059
|
+
return collectBrandIdentifiers(type).includes("__integerBrand");
|
|
3060
|
+
}
|
|
3061
|
+
function resolveBrandedCustomType(type, extensionRegistry) {
|
|
3062
|
+
if (extensionRegistry === void 0) {
|
|
3063
|
+
return null;
|
|
3064
|
+
}
|
|
3065
|
+
for (const brand of collectBrandIdentifiers(type)) {
|
|
3066
|
+
const registration = extensionRegistry.findTypeByBrand(brand);
|
|
3067
|
+
if (registration === void 0) {
|
|
3068
|
+
continue;
|
|
3008
3069
|
}
|
|
3009
|
-
return
|
|
3010
|
-
|
|
3070
|
+
return {
|
|
3071
|
+
kind: "custom",
|
|
3072
|
+
typeId: `${registration.extensionId}/${registration.registration.typeName}`,
|
|
3073
|
+
payload: null
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
return null;
|
|
3011
3077
|
}
|
|
3012
3078
|
function isResolvableObjectLikeAliasTypeNode(typeNode) {
|
|
3013
3079
|
if (ts3.isParenthesizedTypeNode(typeNode)) {
|
|
@@ -4120,6 +4186,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
4120
4186
|
if (customType) {
|
|
4121
4187
|
return customType;
|
|
4122
4188
|
}
|
|
4189
|
+
const symbolCustomType = resolveSymbolBasedCustomType(type, extensionRegistry, checker);
|
|
4190
|
+
if (symbolCustomType) {
|
|
4191
|
+
return symbolCustomType;
|
|
4192
|
+
}
|
|
4193
|
+
const brandedCustomType = resolveBrandedCustomType(type, extensionRegistry);
|
|
4194
|
+
if (brandedCustomType) {
|
|
4195
|
+
return brandedCustomType;
|
|
4196
|
+
}
|
|
4123
4197
|
const primitiveAlias = tryResolveNamedPrimitiveAlias(
|
|
4124
4198
|
type,
|
|
4125
4199
|
checker,
|
|
@@ -5064,7 +5138,7 @@ function createProgramContextFromProgram(program, filePath) {
|
|
|
5064
5138
|
sourceFile
|
|
5065
5139
|
};
|
|
5066
5140
|
}
|
|
5067
|
-
function createProgramContext(filePath) {
|
|
5141
|
+
function createProgramContext(filePath, additionalFiles) {
|
|
5068
5142
|
const absolutePath = path.resolve(filePath);
|
|
5069
5143
|
const fileDir = path.dirname(absolutePath);
|
|
5070
5144
|
const configPath = ts4.findConfigFile(fileDir, ts4.sys.fileExists.bind(ts4.sys), "tsconfig.json");
|
|
@@ -5087,7 +5161,8 @@ function createProgramContext(filePath) {
|
|
|
5087
5161
|
throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
|
|
5088
5162
|
}
|
|
5089
5163
|
compilerOptions = parsed.options;
|
|
5090
|
-
|
|
5164
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
5165
|
+
fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
|
|
5091
5166
|
} else {
|
|
5092
5167
|
compilerOptions = {
|
|
5093
5168
|
target: ts4.ScriptTarget.ES2022,
|
|
@@ -5097,7 +5172,8 @@ function createProgramContext(filePath) {
|
|
|
5097
5172
|
skipLibCheck: true,
|
|
5098
5173
|
declaration: true
|
|
5099
5174
|
};
|
|
5100
|
-
|
|
5175
|
+
const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
|
|
5176
|
+
fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
|
|
5101
5177
|
}
|
|
5102
5178
|
const program = ts4.createProgram(fileNames, compilerOptions);
|
|
5103
5179
|
const sourceFile = program.getSourceFile(absolutePath);
|
|
@@ -5401,6 +5477,132 @@ function makeFileProvenance(filePath) {
|
|
|
5401
5477
|
};
|
|
5402
5478
|
}
|
|
5403
5479
|
|
|
5480
|
+
// src/extensions/symbol-registry.ts
|
|
5481
|
+
var ts5 = __toESM(require("typescript"), 1);
|
|
5482
|
+
var path2 = __toESM(require("path"), 1);
|
|
5483
|
+
function buildSymbolMapFromConfig(configPath, program, checker, extensionRegistry) {
|
|
5484
|
+
const symbolMap = /* @__PURE__ */ new Map();
|
|
5485
|
+
const normalizedPath = path2.resolve(configPath);
|
|
5486
|
+
const configFile = program.getSourceFile(normalizedPath);
|
|
5487
|
+
if (configFile === void 0) {
|
|
5488
|
+
return symbolMap;
|
|
5489
|
+
}
|
|
5490
|
+
function visit(node) {
|
|
5491
|
+
if (ts5.isCallExpression(node) && isDefineCustomTypeCall(node, checker)) {
|
|
5492
|
+
processDefineCustomTypeCall(node);
|
|
5493
|
+
}
|
|
5494
|
+
ts5.forEachChild(node, visit);
|
|
5495
|
+
}
|
|
5496
|
+
function processDefineCustomTypeCall(call) {
|
|
5497
|
+
const typeArgNode = call.typeArguments?.[0];
|
|
5498
|
+
if (typeArgNode === void 0) {
|
|
5499
|
+
return;
|
|
5500
|
+
}
|
|
5501
|
+
const resolvedType = checker.getTypeFromTypeNode(typeArgNode);
|
|
5502
|
+
const canonical = resolveCanonicalSymbol2(resolvedType, checker);
|
|
5503
|
+
if (canonical === void 0) {
|
|
5504
|
+
return;
|
|
5505
|
+
}
|
|
5506
|
+
const typeName = extractTypeNameFromCallArg(call);
|
|
5507
|
+
if (typeName === null) {
|
|
5508
|
+
return;
|
|
5509
|
+
}
|
|
5510
|
+
let entry;
|
|
5511
|
+
const extensionId = extractEnclosingExtensionId(call, checker);
|
|
5512
|
+
if (extensionId !== null) {
|
|
5513
|
+
const reg = extensionRegistry.findType(`${extensionId}/${typeName}`);
|
|
5514
|
+
if (reg !== void 0) {
|
|
5515
|
+
entry = { extensionId, registration: reg };
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
entry ??= findRegistrationByTypeName(extensionRegistry, typeName);
|
|
5519
|
+
if (entry === void 0) {
|
|
5520
|
+
return;
|
|
5521
|
+
}
|
|
5522
|
+
symbolMap.set(canonical, entry);
|
|
5523
|
+
}
|
|
5524
|
+
visit(configFile);
|
|
5525
|
+
return symbolMap;
|
|
5526
|
+
}
|
|
5527
|
+
function isDefineCustomTypeCall(node, checker) {
|
|
5528
|
+
if (node.typeArguments === void 0 || node.typeArguments.length === 0) return false;
|
|
5529
|
+
const callSymbol = checker.getSymbolAtLocation(node.expression);
|
|
5530
|
+
if (callSymbol !== void 0) {
|
|
5531
|
+
const resolved = callSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(callSymbol) : callSymbol;
|
|
5532
|
+
const decl = resolved.declarations?.[0];
|
|
5533
|
+
if (decl !== void 0) {
|
|
5534
|
+
const sourceFile = decl.getSourceFile().fileName.replace(/\\/g, "/");
|
|
5535
|
+
return resolved.name === "defineCustomType" && // Match whether in node_modules/@formspec/core or monorepo packages/core.
|
|
5536
|
+
(sourceFile.includes("@formspec/core") || sourceFile.includes("/packages/core/"));
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5539
|
+
return ts5.isIdentifier(node.expression) && node.expression.text === "defineCustomType";
|
|
5540
|
+
}
|
|
5541
|
+
function resolveCanonicalSymbol2(type, checker) {
|
|
5542
|
+
const raw = type.aliasSymbol ?? type.getSymbol();
|
|
5543
|
+
if (raw === void 0) return void 0;
|
|
5544
|
+
return raw.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(raw) : raw;
|
|
5545
|
+
}
|
|
5546
|
+
function extractTypeNameFromCallArg(call) {
|
|
5547
|
+
const arg = call.arguments[0];
|
|
5548
|
+
if (arg === void 0 || !ts5.isObjectLiteralExpression(arg)) {
|
|
5549
|
+
return null;
|
|
5550
|
+
}
|
|
5551
|
+
const typeNameProp = arg.properties.find(
|
|
5552
|
+
(p) => ts5.isPropertyAssignment(p) && ts5.isIdentifier(p.name) && p.name.text === "typeName"
|
|
5553
|
+
);
|
|
5554
|
+
if (typeNameProp === void 0 || !ts5.isStringLiteral(typeNameProp.initializer)) {
|
|
5555
|
+
return null;
|
|
5556
|
+
}
|
|
5557
|
+
return typeNameProp.initializer.text;
|
|
5558
|
+
}
|
|
5559
|
+
function extractEnclosingExtensionId(call, checker) {
|
|
5560
|
+
for (let node = call.parent; !ts5.isSourceFile(node); node = node.parent) {
|
|
5561
|
+
if (ts5.isCallExpression(node) && isDefineExtensionCall(node, checker)) {
|
|
5562
|
+
return extractExtensionIdFromCallArg(node);
|
|
5563
|
+
}
|
|
5564
|
+
}
|
|
5565
|
+
return null;
|
|
5566
|
+
}
|
|
5567
|
+
function isDefineExtensionCall(node, checker) {
|
|
5568
|
+
const callSymbol = checker.getSymbolAtLocation(node.expression);
|
|
5569
|
+
if (callSymbol !== void 0) {
|
|
5570
|
+
const resolved = callSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(callSymbol) : callSymbol;
|
|
5571
|
+
const decl = resolved.declarations?.[0];
|
|
5572
|
+
if (decl !== void 0) {
|
|
5573
|
+
const sourceFile = decl.getSourceFile().fileName.replace(/\\/g, "/");
|
|
5574
|
+
return resolved.name === "defineExtension" && (sourceFile.includes("@formspec/core") || sourceFile.includes("/packages/core/"));
|
|
5575
|
+
}
|
|
5576
|
+
}
|
|
5577
|
+
return ts5.isIdentifier(node.expression) && node.expression.text === "defineExtension";
|
|
5578
|
+
}
|
|
5579
|
+
function extractExtensionIdFromCallArg(call) {
|
|
5580
|
+
const arg = call.arguments[0];
|
|
5581
|
+
if (arg === void 0 || !ts5.isObjectLiteralExpression(arg)) {
|
|
5582
|
+
return null;
|
|
5583
|
+
}
|
|
5584
|
+
const prop = arg.properties.find(
|
|
5585
|
+
(p) => ts5.isPropertyAssignment(p) && ts5.isIdentifier(p.name) && p.name.text === "extensionId"
|
|
5586
|
+
);
|
|
5587
|
+
if (prop === void 0 || !ts5.isStringLiteral(prop.initializer)) {
|
|
5588
|
+
return null;
|
|
5589
|
+
}
|
|
5590
|
+
return prop.initializer.text;
|
|
5591
|
+
}
|
|
5592
|
+
function findRegistrationByTypeName(registry, typeName) {
|
|
5593
|
+
for (const ext of registry.extensions) {
|
|
5594
|
+
if (ext.types === void 0) {
|
|
5595
|
+
continue;
|
|
5596
|
+
}
|
|
5597
|
+
for (const type of ext.types) {
|
|
5598
|
+
if (type.typeName === typeName) {
|
|
5599
|
+
return { extensionId: ext.extensionId, registration: type };
|
|
5600
|
+
}
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
return void 0;
|
|
5604
|
+
}
|
|
5605
|
+
|
|
5404
5606
|
// src/validate/constraint-validator.ts
|
|
5405
5607
|
var import_internal4 = require("@formspec/analysis/internal");
|
|
5406
5608
|
function validateFieldNode(ctx, field) {
|
|
@@ -5533,7 +5735,8 @@ function formatLocation(location) {
|
|
|
5533
5735
|
return `${location.file}:${String(location.line)}:${String(location.column)}`;
|
|
5534
5736
|
}
|
|
5535
5737
|
function generateSchemasFromClass(options) {
|
|
5536
|
-
const
|
|
5738
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5739
|
+
const ctx = createProgramContext(options.filePath, additionalFiles);
|
|
5537
5740
|
const classDecl = findClassByName(ctx.sourceFile, options.className);
|
|
5538
5741
|
if (!classDecl) {
|
|
5539
5742
|
throw new Error(`Class "${options.className}" not found in ${options.filePath}`);
|
|
@@ -5598,7 +5801,8 @@ function generateSchemasDetailed(options) {
|
|
|
5598
5801
|
function generateSchemasDetailedInternal(options) {
|
|
5599
5802
|
let ctx;
|
|
5600
5803
|
try {
|
|
5601
|
-
|
|
5804
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5805
|
+
ctx = createProgramContext(options.filePath, additionalFiles);
|
|
5602
5806
|
} catch (error) {
|
|
5603
5807
|
return {
|
|
5604
5808
|
ok: false,
|
|
@@ -5637,13 +5841,16 @@ function generateSchemasFromProgramDetailedInternal(options) {
|
|
|
5637
5841
|
}
|
|
5638
5842
|
function generateSchemasBatch(options) {
|
|
5639
5843
|
const contextCache = /* @__PURE__ */ new Map();
|
|
5844
|
+
const resolved = resolveOptions(options);
|
|
5845
|
+
let symbolMapProgram;
|
|
5640
5846
|
return options.targets.map((target) => {
|
|
5641
5847
|
let ctx;
|
|
5642
5848
|
try {
|
|
5643
|
-
const cacheKey =
|
|
5849
|
+
const cacheKey = ts6.sys.useCaseSensitiveFileNames ? target.filePath : target.filePath.toLowerCase();
|
|
5644
5850
|
const cachedContext = contextCache.get(cacheKey);
|
|
5645
5851
|
if (cachedContext === void 0) {
|
|
5646
|
-
|
|
5852
|
+
const additionalFiles = options.configPath !== void 0 ? [options.configPath] : void 0;
|
|
5853
|
+
ctx = createProgramContext(target.filePath, additionalFiles);
|
|
5647
5854
|
contextCache.set(cacheKey, ctx);
|
|
5648
5855
|
} else {
|
|
5649
5856
|
ctx = cachedContext;
|
|
@@ -5654,9 +5861,25 @@ function generateSchemasBatch(options) {
|
|
|
5654
5861
|
diagnostics: [createProgramContextFailureDiagnostic(target.filePath, error)]
|
|
5655
5862
|
});
|
|
5656
5863
|
}
|
|
5864
|
+
if (options.configPath !== void 0 && resolved.extensionRegistry !== void 0 && isMutableRegistry(resolved.extensionRegistry) && ctx.program !== symbolMapProgram) {
|
|
5865
|
+
const symbolMap = buildSymbolMapFromConfig(
|
|
5866
|
+
options.configPath,
|
|
5867
|
+
ctx.program,
|
|
5868
|
+
ctx.checker,
|
|
5869
|
+
resolved.extensionRegistry
|
|
5870
|
+
);
|
|
5871
|
+
resolved.extensionRegistry.setSymbolMap(symbolMap);
|
|
5872
|
+
symbolMapProgram = ctx.program;
|
|
5873
|
+
}
|
|
5657
5874
|
return withTarget(
|
|
5658
5875
|
target,
|
|
5659
|
-
|
|
5876
|
+
generateSchemasFromResolvedOptions(
|
|
5877
|
+
ctx,
|
|
5878
|
+
target.filePath,
|
|
5879
|
+
target.typeName,
|
|
5880
|
+
resolved,
|
|
5881
|
+
options.discriminator
|
|
5882
|
+
)
|
|
5660
5883
|
);
|
|
5661
5884
|
});
|
|
5662
5885
|
}
|
|
@@ -5677,11 +5900,19 @@ function generateSchemasBatchFromProgram(options) {
|
|
|
5677
5900
|
);
|
|
5678
5901
|
});
|
|
5679
5902
|
}
|
|
5903
|
+
function isMutableRegistry(reg) {
|
|
5904
|
+
return "setSymbolMap" in reg && typeof reg.setSymbolMap === "function";
|
|
5905
|
+
}
|
|
5680
5906
|
function resolveOptions(options) {
|
|
5681
5907
|
const configRegistry = options.config?.extensions !== void 0 ? createExtensionRegistry(options.config.extensions) : void 0;
|
|
5908
|
+
const legacyRegistry = options.extensionRegistry;
|
|
5682
5909
|
return {
|
|
5683
|
-
//
|
|
5684
|
-
|
|
5910
|
+
// When the caller provides the deprecated extensionRegistry field directly,
|
|
5911
|
+
// it is typed as the read-only ExtensionRegistry interface. We cast here
|
|
5912
|
+
// because the legacy path was introduced before MutableExtensionRegistry was
|
|
5913
|
+
// split out; callers using createExtensionRegistry() always get a mutable
|
|
5914
|
+
// registry, and this cast is safe for all registries produced by this module.
|
|
5915
|
+
extensionRegistry: legacyRegistry ?? configRegistry,
|
|
5685
5916
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
5686
5917
|
vendorPrefix: options.vendorPrefix ?? options.config?.vendorPrefix,
|
|
5687
5918
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
@@ -5692,13 +5923,31 @@ function resolveOptions(options) {
|
|
|
5692
5923
|
}
|
|
5693
5924
|
function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, options) {
|
|
5694
5925
|
const resolved = resolveOptions(options);
|
|
5926
|
+
if (options.configPath !== void 0 && resolved.extensionRegistry !== void 0 && isMutableRegistry(resolved.extensionRegistry)) {
|
|
5927
|
+
const symbolMap = buildSymbolMapFromConfig(
|
|
5928
|
+
options.configPath,
|
|
5929
|
+
ctx.program,
|
|
5930
|
+
ctx.checker,
|
|
5931
|
+
resolved.extensionRegistry
|
|
5932
|
+
);
|
|
5933
|
+
resolved.extensionRegistry.setSymbolMap(symbolMap);
|
|
5934
|
+
}
|
|
5935
|
+
return generateSchemasFromResolvedOptions(
|
|
5936
|
+
ctx,
|
|
5937
|
+
filePath,
|
|
5938
|
+
typeName,
|
|
5939
|
+
resolved,
|
|
5940
|
+
options.discriminator
|
|
5941
|
+
);
|
|
5942
|
+
}
|
|
5943
|
+
function generateSchemasFromResolvedOptions(ctx, filePath, typeName, resolved, discriminator) {
|
|
5695
5944
|
const analysisResult = analyzeNamedTypeToIRFromProgramContextDetailed(
|
|
5696
5945
|
ctx,
|
|
5697
5946
|
filePath,
|
|
5698
5947
|
typeName,
|
|
5699
5948
|
resolved.extensionRegistry,
|
|
5700
5949
|
resolved.metadata,
|
|
5701
|
-
|
|
5950
|
+
discriminator
|
|
5702
5951
|
);
|
|
5703
5952
|
if (!analysisResult.ok) {
|
|
5704
5953
|
return {
|
|
@@ -5740,7 +5989,7 @@ function createProgramContextFailureDiagnostic(filePath, error) {
|
|
|
5740
5989
|
}
|
|
5741
5990
|
|
|
5742
5991
|
// src/static-build.ts
|
|
5743
|
-
var
|
|
5992
|
+
var ts7 = __toESM(require("typescript"), 1);
|
|
5744
5993
|
function toStaticBuildContext(context) {
|
|
5745
5994
|
return context;
|
|
5746
5995
|
}
|
|
@@ -5755,7 +6004,7 @@ function getModuleSymbol(context) {
|
|
|
5755
6004
|
return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
|
|
5756
6005
|
}
|
|
5757
6006
|
function isSchemaSourceDeclaration(declaration) {
|
|
5758
|
-
return
|
|
6007
|
+
return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
|
|
5759
6008
|
}
|
|
5760
6009
|
function resolveModuleExport(context, exportName = "default") {
|
|
5761
6010
|
const moduleSymbol = getModuleSymbol(context);
|
|
@@ -5766,14 +6015,14 @@ function resolveModuleExport(context, exportName = "default") {
|
|
|
5766
6015
|
if (exportSymbol === null) {
|
|
5767
6016
|
return null;
|
|
5768
6017
|
}
|
|
5769
|
-
return exportSymbol.flags &
|
|
6018
|
+
return exportSymbol.flags & ts7.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
|
|
5770
6019
|
}
|
|
5771
6020
|
function resolveModuleExportDeclaration(context, exportName = "default") {
|
|
5772
6021
|
return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
|
|
5773
6022
|
}
|
|
5774
6023
|
|
|
5775
6024
|
// src/generators/discovered-schema.ts
|
|
5776
|
-
var
|
|
6025
|
+
var ts8 = __toESM(require("typescript"), 1);
|
|
5777
6026
|
var import_internal5 = require("@formspec/analysis/internal");
|
|
5778
6027
|
var import_internals6 = require("@formspec/core/internals");
|
|
5779
6028
|
function toDiscoveredTypeSchemas(result, resolvedMetadata) {
|
|
@@ -5783,17 +6032,17 @@ function toDiscoveredTypeSchemas(result, resolvedMetadata) {
|
|
|
5783
6032
|
};
|
|
5784
6033
|
}
|
|
5785
6034
|
function isNamedTypeDeclaration(declaration) {
|
|
5786
|
-
return
|
|
6035
|
+
return ts8.isClassDeclaration(declaration) || ts8.isInterfaceDeclaration(declaration) || ts8.isTypeAliasDeclaration(declaration);
|
|
5787
6036
|
}
|
|
5788
6037
|
function hasConcreteTypeArguments(type, checker) {
|
|
5789
6038
|
if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
|
|
5790
6039
|
return true;
|
|
5791
6040
|
}
|
|
5792
|
-
if ((type.flags &
|
|
6041
|
+
if ((type.flags & ts8.TypeFlags.Object) === 0) {
|
|
5793
6042
|
return false;
|
|
5794
6043
|
}
|
|
5795
6044
|
const objectType = type;
|
|
5796
|
-
if ((objectType.objectFlags &
|
|
6045
|
+
if ((objectType.objectFlags & ts8.ObjectFlags.Reference) === 0) {
|
|
5797
6046
|
return false;
|
|
5798
6047
|
}
|
|
5799
6048
|
return checker.getTypeArguments(objectType).length > 0;
|
|
@@ -5806,13 +6055,13 @@ function getNamedTypeDeclaration2(type) {
|
|
|
5806
6055
|
return declaration;
|
|
5807
6056
|
}
|
|
5808
6057
|
}
|
|
5809
|
-
const aliasDeclaration = type.aliasSymbol?.declarations?.find(
|
|
6058
|
+
const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts8.isTypeAliasDeclaration);
|
|
5810
6059
|
return aliasDeclaration;
|
|
5811
6060
|
}
|
|
5812
6061
|
function getFallbackName(sourceNode, fallback = "AnonymousType") {
|
|
5813
6062
|
if (sourceNode !== void 0 && "name" in sourceNode) {
|
|
5814
6063
|
const namedNode = sourceNode;
|
|
5815
|
-
if (namedNode.name !== void 0 &&
|
|
6064
|
+
if (namedNode.name !== void 0 && ts8.isIdentifier(namedNode.name)) {
|
|
5816
6065
|
return namedNode.name.text;
|
|
5817
6066
|
}
|
|
5818
6067
|
}
|
|
@@ -5931,17 +6180,14 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
|
|
|
5931
6180
|
rootLogicalName: root.name
|
|
5932
6181
|
}
|
|
5933
6182
|
);
|
|
5934
|
-
const schema = generateJsonSchemaFromIR(
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
vendorPrefix: options?.vendorPrefix
|
|
5943
|
-
}
|
|
5944
|
-
);
|
|
6183
|
+
const schema = generateJsonSchemaFromIR(ir, {
|
|
6184
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6185
|
+
extensionRegistry: options?.extensionRegistry,
|
|
6186
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6187
|
+
enumSerialization: options?.enumSerialization,
|
|
6188
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields
|
|
6189
|
+
vendorPrefix: options?.vendorPrefix
|
|
6190
|
+
});
|
|
5945
6191
|
const result = schema.properties?.["__result"];
|
|
5946
6192
|
if (result === void 0) {
|
|
5947
6193
|
throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
|
|
@@ -6040,7 +6286,7 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
|
|
|
6040
6286
|
}
|
|
6041
6287
|
function generateSchemasFromDeclaration(options) {
|
|
6042
6288
|
const filePath = options.declaration.getSourceFile().fileName;
|
|
6043
|
-
if (
|
|
6289
|
+
if (ts8.isClassDeclaration(options.declaration)) {
|
|
6044
6290
|
return generateSchemasFromAnalysis(
|
|
6045
6291
|
analyzeClassToIR(
|
|
6046
6292
|
options.declaration,
|
|
@@ -6056,7 +6302,7 @@ function generateSchemasFromDeclaration(options) {
|
|
|
6056
6302
|
options
|
|
6057
6303
|
);
|
|
6058
6304
|
}
|
|
6059
|
-
if (
|
|
6305
|
+
if (ts8.isInterfaceDeclaration(options.declaration)) {
|
|
6060
6306
|
return generateSchemasFromAnalysis(
|
|
6061
6307
|
analyzeInterfaceToIR(
|
|
6062
6308
|
options.declaration,
|
|
@@ -6072,7 +6318,7 @@ function generateSchemasFromDeclaration(options) {
|
|
|
6072
6318
|
options
|
|
6073
6319
|
);
|
|
6074
6320
|
}
|
|
6075
|
-
if (
|
|
6321
|
+
if (ts8.isTypeAliasDeclaration(options.declaration)) {
|
|
6076
6322
|
const analyzedAlias = analyzeTypeAliasToIR(
|
|
6077
6323
|
options.declaration,
|
|
6078
6324
|
options.context.checker,
|
|
@@ -6135,7 +6381,7 @@ function generateSchemasFromReturnType(options) {
|
|
|
6135
6381
|
const returnType = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
|
|
6136
6382
|
const type = unwrapPromiseType(options.context.checker, returnType);
|
|
6137
6383
|
const sourceNode = type !== returnType ? unwrapPromiseTypeNode(options.declaration.type) ?? options.declaration.type ?? options.declaration : options.declaration.type ?? options.declaration;
|
|
6138
|
-
const fallbackName = options.declaration.name !== void 0 &&
|
|
6384
|
+
const fallbackName = options.declaration.name !== void 0 && ts8.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
|
|
6139
6385
|
return generateSchemasFromResolvedType({
|
|
6140
6386
|
...options,
|
|
6141
6387
|
type,
|
|
@@ -6170,14 +6416,14 @@ function unwrapPromiseTypeNode(typeNode) {
|
|
|
6170
6416
|
if (typeNode === void 0) {
|
|
6171
6417
|
return void 0;
|
|
6172
6418
|
}
|
|
6173
|
-
if (
|
|
6419
|
+
if (ts8.isParenthesizedTypeNode(typeNode)) {
|
|
6174
6420
|
const unwrapped = unwrapPromiseTypeNode(typeNode.type);
|
|
6175
6421
|
return unwrapped ?? typeNode;
|
|
6176
6422
|
}
|
|
6177
6423
|
return isPromiseTypeReferenceNode(typeNode) ? typeNode.typeArguments[0] : typeNode;
|
|
6178
6424
|
}
|
|
6179
6425
|
function isPromiseTypeReferenceNode(typeNode) {
|
|
6180
|
-
return
|
|
6426
|
+
return ts8.isTypeReferenceNode(typeNode) && ts8.isIdentifier(typeNode.typeName) && typeNode.typeName.text === "Promise" && typeNode.typeArguments !== void 0 && typeNode.typeArguments.length > 0;
|
|
6181
6427
|
}
|
|
6182
6428
|
|
|
6183
6429
|
// src/generators/mixed-authoring.ts
|
|
@@ -6399,8 +6645,8 @@ function writeSchemas(form, options) {
|
|
|
6399
6645
|
if (!fs.existsSync(outDir)) {
|
|
6400
6646
|
fs.mkdirSync(outDir, { recursive: true });
|
|
6401
6647
|
}
|
|
6402
|
-
const jsonSchemaPath =
|
|
6403
|
-
const uiSchemaPath =
|
|
6648
|
+
const jsonSchemaPath = path3.join(outDir, `${name}-schema.json`);
|
|
6649
|
+
const uiSchemaPath = path3.join(outDir, `${name}-uischema.json`);
|
|
6404
6650
|
fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));
|
|
6405
6651
|
fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema2, null, indent));
|
|
6406
6652
|
return { jsonSchemaPath, uiSchemaPath };
|