@formspec/build 0.1.0-alpha.30 → 0.1.0-alpha.32
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/README.md +82 -5
- package/dist/analyzer/class-analyzer.d.ts +6 -0
- package/dist/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/browser.cjs +166 -24
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +166 -24
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +180 -0
- package/dist/build-beta.d.ts +180 -0
- package/dist/build-internal.d.ts +180 -0
- package/dist/build.d.ts +180 -0
- package/dist/cli.cjs +584 -33
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +582 -33
- package/dist/cli.js.map +1 -1
- package/dist/generators/discovered-schema.d.ts +112 -0
- package/dist/generators/discovered-schema.d.ts.map +1 -0
- package/dist/index.cjs +573 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +565 -33
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +197 -33
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.js +197 -33
- package/dist/internals.js.map +1 -1
- package/dist/static-build.d.ts +61 -0
- package/dist/static-build.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -932,9 +932,9 @@ function collectFields(elements, properties, required, ctx) {
|
|
|
932
932
|
for (const element of elements) {
|
|
933
933
|
switch (element.kind) {
|
|
934
934
|
case "field":
|
|
935
|
-
properties[
|
|
935
|
+
properties[getSerializedFieldName(element)] = generateFieldSchema(element, ctx);
|
|
936
936
|
if (element.required) {
|
|
937
|
-
required.push(
|
|
937
|
+
required.push(getSerializedFieldName(element));
|
|
938
938
|
}
|
|
939
939
|
break;
|
|
940
940
|
case "group":
|
|
@@ -1005,19 +1005,21 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
|
|
|
1005
1005
|
schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx, nestedType);
|
|
1006
1006
|
return schema;
|
|
1007
1007
|
}
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1008
|
+
const propertyOverrides = buildPropertyOverrides(pathConstraints, typeNode, ctx);
|
|
1009
|
+
const nullableValueBranch = getNullableUnionValueSchema(schema);
|
|
1010
|
+
if (nullableValueBranch !== void 0) {
|
|
1011
|
+
const updatedNullableValueBranch = applyPathTargetedConstraints(
|
|
1012
|
+
nullableValueBranch,
|
|
1013
|
+
pathConstraints,
|
|
1014
|
+
ctx,
|
|
1015
|
+
resolveTraversableTypeNode(typeNode, ctx)
|
|
1016
|
+
);
|
|
1017
|
+
if (schema.oneOf !== void 0) {
|
|
1018
|
+
schema.oneOf = schema.oneOf.map(
|
|
1019
|
+
(branch) => branch === nullableValueBranch ? updatedNullableValueBranch : branch
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
return schema;
|
|
1021
1023
|
}
|
|
1022
1024
|
if (schema.$ref) {
|
|
1023
1025
|
const { $ref, ...rest } = schema;
|
|
@@ -1032,7 +1034,7 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
|
|
|
1032
1034
|
const missingOverrides = {};
|
|
1033
1035
|
for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {
|
|
1034
1036
|
if (schema.properties[target]) {
|
|
1035
|
-
|
|
1037
|
+
mergeSchemaOverride(schema.properties[target], overrideSchema);
|
|
1036
1038
|
} else {
|
|
1037
1039
|
missingOverrides[target] = overrideSchema;
|
|
1038
1040
|
}
|
|
@@ -1106,7 +1108,7 @@ function generateObjectType(type, ctx) {
|
|
|
1106
1108
|
const properties = {};
|
|
1107
1109
|
const required = [];
|
|
1108
1110
|
for (const prop of type.properties) {
|
|
1109
|
-
const propertyName =
|
|
1111
|
+
const propertyName = getSerializedObjectPropertyName(prop);
|
|
1110
1112
|
properties[propertyName] = generatePropertySchema(prop, ctx);
|
|
1111
1113
|
if (!prop.optional) {
|
|
1112
1114
|
required.push(propertyName);
|
|
@@ -1160,7 +1162,16 @@ function isNullableUnion(type) {
|
|
|
1160
1162
|
return nullCount === 1;
|
|
1161
1163
|
}
|
|
1162
1164
|
function generateReferenceType(type, ctx) {
|
|
1163
|
-
return { $ref: `#/$defs/${
|
|
1165
|
+
return { $ref: `#/$defs/${getSerializedTypeName(type.name, ctx)}` };
|
|
1166
|
+
}
|
|
1167
|
+
function getSerializedFieldName(field) {
|
|
1168
|
+
return getSerializedName(field.name, field.metadata);
|
|
1169
|
+
}
|
|
1170
|
+
function getSerializedObjectPropertyName(property) {
|
|
1171
|
+
return getSerializedName(property.name, property.metadata);
|
|
1172
|
+
}
|
|
1173
|
+
function getSerializedTypeName(logicalName, ctx) {
|
|
1174
|
+
return ctx.typeNameMap[logicalName] ?? logicalName;
|
|
1164
1175
|
}
|
|
1165
1176
|
function applyResolvedMetadata(schema, metadata) {
|
|
1166
1177
|
const displayName = getDisplayName(metadata);
|
|
@@ -1171,17 +1182,148 @@ function applyResolvedMetadata(schema, metadata) {
|
|
|
1171
1182
|
function resolveReferencedType(type, ctx) {
|
|
1172
1183
|
return ctx.typeRegistry[type.name]?.type;
|
|
1173
1184
|
}
|
|
1185
|
+
function dereferenceTypeNode(typeNode, ctx) {
|
|
1186
|
+
if (typeNode?.kind !== "reference") {
|
|
1187
|
+
return typeNode;
|
|
1188
|
+
}
|
|
1189
|
+
return resolveReferencedType(typeNode, ctx);
|
|
1190
|
+
}
|
|
1191
|
+
function unwrapNullableTypeNode(typeNode) {
|
|
1192
|
+
if (typeNode?.kind !== "union" || !isNullableUnion(typeNode)) {
|
|
1193
|
+
return typeNode;
|
|
1194
|
+
}
|
|
1195
|
+
return typeNode.members.find(
|
|
1196
|
+
(member) => !(member.kind === "primitive" && member.primitiveKind === "null")
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
function resolveTraversableTypeNode(typeNode, ctx) {
|
|
1200
|
+
const dereferenced = dereferenceTypeNode(typeNode, ctx);
|
|
1201
|
+
const unwrapped = unwrapNullableTypeNode(dereferenced);
|
|
1202
|
+
if (unwrapped !== dereferenced) {
|
|
1203
|
+
return resolveTraversableTypeNode(unwrapped, ctx);
|
|
1204
|
+
}
|
|
1205
|
+
return dereferenced;
|
|
1206
|
+
}
|
|
1174
1207
|
function resolveSerializedPropertyName(logicalName, typeNode, ctx) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
return
|
|
1208
|
+
const effectiveType = resolveTraversableTypeNode(typeNode, ctx);
|
|
1209
|
+
if (effectiveType?.kind === "array") {
|
|
1210
|
+
return resolveSerializedPropertyName(logicalName, effectiveType.items, ctx);
|
|
1178
1211
|
}
|
|
1179
|
-
if (
|
|
1180
|
-
const
|
|
1181
|
-
return
|
|
1212
|
+
if (effectiveType?.kind === "object") {
|
|
1213
|
+
const property = effectiveType.properties.find((candidate) => candidate.name === logicalName);
|
|
1214
|
+
return property === void 0 ? logicalName : getSerializedObjectPropertyName(property);
|
|
1182
1215
|
}
|
|
1183
1216
|
return logicalName;
|
|
1184
1217
|
}
|
|
1218
|
+
function resolveTargetTypeNode(logicalName, typeNode, ctx) {
|
|
1219
|
+
const effectiveType = resolveTraversableTypeNode(typeNode, ctx);
|
|
1220
|
+
if (effectiveType?.kind === "array") {
|
|
1221
|
+
return resolveTargetTypeNode(logicalName, effectiveType.items, ctx);
|
|
1222
|
+
}
|
|
1223
|
+
if (effectiveType?.kind !== "object") {
|
|
1224
|
+
return void 0;
|
|
1225
|
+
}
|
|
1226
|
+
return effectiveType.properties.find((candidate) => candidate.name === logicalName)?.type;
|
|
1227
|
+
}
|
|
1228
|
+
function buildPropertyOverrides(pathConstraints, typeNode, ctx) {
|
|
1229
|
+
const byTarget = /* @__PURE__ */ new Map();
|
|
1230
|
+
for (const constraint of pathConstraints) {
|
|
1231
|
+
const target = constraint.path?.segments[0];
|
|
1232
|
+
if (!target) {
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1235
|
+
const grouped = byTarget.get(target) ?? [];
|
|
1236
|
+
grouped.push(constraint);
|
|
1237
|
+
byTarget.set(target, grouped);
|
|
1238
|
+
}
|
|
1239
|
+
const overrides = {};
|
|
1240
|
+
for (const [target, constraints] of byTarget) {
|
|
1241
|
+
overrides[resolveSerializedPropertyName(target, typeNode, ctx)] = buildPathOverrideSchema(
|
|
1242
|
+
constraints.map(stripLeadingPathSegment),
|
|
1243
|
+
resolveTargetTypeNode(target, typeNode, ctx),
|
|
1244
|
+
ctx
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
return overrides;
|
|
1248
|
+
}
|
|
1249
|
+
function buildPathOverrideSchema(constraints, typeNode, ctx) {
|
|
1250
|
+
const schema = {};
|
|
1251
|
+
const directConstraints = [];
|
|
1252
|
+
const nestedConstraints = [];
|
|
1253
|
+
for (const constraint of constraints) {
|
|
1254
|
+
if (constraint.path === void 0 || constraint.path.segments.length === 0) {
|
|
1255
|
+
directConstraints.push(constraint);
|
|
1256
|
+
} else {
|
|
1257
|
+
nestedConstraints.push(constraint);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
applyConstraints(schema, directConstraints, ctx);
|
|
1261
|
+
if (nestedConstraints.length === 0) {
|
|
1262
|
+
return schema;
|
|
1263
|
+
}
|
|
1264
|
+
const effectiveType = resolveTraversableTypeNode(typeNode, ctx);
|
|
1265
|
+
if (effectiveType?.kind === "array") {
|
|
1266
|
+
schema.items = buildPathOverrideSchema(nestedConstraints, effectiveType.items, ctx);
|
|
1267
|
+
return schema;
|
|
1268
|
+
}
|
|
1269
|
+
schema.properties = buildPropertyOverrides(nestedConstraints, effectiveType, ctx);
|
|
1270
|
+
return schema;
|
|
1271
|
+
}
|
|
1272
|
+
function mergeSchemaOverride(target, override) {
|
|
1273
|
+
const nullableValueBranch = getNullableUnionValueSchema(target);
|
|
1274
|
+
if (nullableValueBranch !== void 0) {
|
|
1275
|
+
mergeSchemaOverride(nullableValueBranch, override);
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
if (override.properties !== void 0) {
|
|
1279
|
+
const mergedProperties = target.properties ?? {};
|
|
1280
|
+
for (const [name, propertyOverride] of Object.entries(override.properties)) {
|
|
1281
|
+
const existing = mergedProperties[name];
|
|
1282
|
+
if (existing === void 0) {
|
|
1283
|
+
mergedProperties[name] = propertyOverride;
|
|
1284
|
+
} else {
|
|
1285
|
+
mergeSchemaOverride(existing, propertyOverride);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
target.properties = mergedProperties;
|
|
1289
|
+
}
|
|
1290
|
+
if (override.items !== void 0) {
|
|
1291
|
+
if (target.items === void 0) {
|
|
1292
|
+
target.items = override.items;
|
|
1293
|
+
} else {
|
|
1294
|
+
mergeSchemaOverride(target.items, override.items);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
for (const [key, value] of Object.entries(override)) {
|
|
1298
|
+
if (key === "properties" || key === "items") {
|
|
1299
|
+
continue;
|
|
1300
|
+
}
|
|
1301
|
+
target[key] = value;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
function stripLeadingPathSegment(constraint) {
|
|
1305
|
+
const segments = constraint.path?.segments;
|
|
1306
|
+
if (segments === void 0 || segments.length === 0) {
|
|
1307
|
+
return constraint;
|
|
1308
|
+
}
|
|
1309
|
+
const [, ...rest] = segments;
|
|
1310
|
+
if (rest.length === 0) {
|
|
1311
|
+
const { path: _path, ...stripped } = constraint;
|
|
1312
|
+
return stripped;
|
|
1313
|
+
}
|
|
1314
|
+
return {
|
|
1315
|
+
...constraint,
|
|
1316
|
+
path: { segments: rest }
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
function getNullableUnionValueSchema(schema) {
|
|
1320
|
+
if (schema.oneOf?.length !== 2) {
|
|
1321
|
+
return void 0;
|
|
1322
|
+
}
|
|
1323
|
+
const valueSchema = schema.oneOf.find((branch) => branch.type !== "null");
|
|
1324
|
+
const nullSchema = schema.oneOf.find((branch) => branch.type === "null");
|
|
1325
|
+
return valueSchema !== void 0 && nullSchema !== void 0 ? valueSchema : void 0;
|
|
1326
|
+
}
|
|
1185
1327
|
function generateDynamicType(type) {
|
|
1186
1328
|
if (type.dynamicKind === "enum") {
|
|
1187
1329
|
const schema = {
|
|
@@ -2746,6 +2888,27 @@ function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node,
|
|
|
2746
2888
|
makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
|
|
2747
2889
|
);
|
|
2748
2890
|
}
|
|
2891
|
+
function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2892
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2893
|
+
const declarationType = checker.getTypeAtLocation(declaration);
|
|
2894
|
+
const logicalName = ts3.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
|
|
2895
|
+
const docResult = extractJSDocParseResult(
|
|
2896
|
+
declaration,
|
|
2897
|
+
file,
|
|
2898
|
+
makeParseOptions(extensionRegistry, void 0, checker, declarationType, declarationType)
|
|
2899
|
+
);
|
|
2900
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", logicalName, declaration, {
|
|
2901
|
+
checker,
|
|
2902
|
+
declaration,
|
|
2903
|
+
subjectType: declarationType,
|
|
2904
|
+
hostType: declarationType
|
|
2905
|
+
});
|
|
2906
|
+
return {
|
|
2907
|
+
...metadata !== void 0 && { metadata },
|
|
2908
|
+
annotations: docResult.annotations,
|
|
2909
|
+
diagnostics: docResult.diagnostics
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2749
2912
|
function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2750
2913
|
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2751
2914
|
const name = classDecl.name?.text ?? "AnonymousClass";
|
|
@@ -3160,10 +3323,7 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
|
|
|
3160
3323
|
if (resolvedAnchorNode === null) {
|
|
3161
3324
|
return void 0;
|
|
3162
3325
|
}
|
|
3163
|
-
const propertyType = checker.getTypeOfSymbolAtLocation(
|
|
3164
|
-
propertySymbol,
|
|
3165
|
-
resolvedAnchorNode
|
|
3166
|
-
);
|
|
3326
|
+
const propertyType = checker.getTypeOfSymbolAtLocation(propertySymbol, resolvedAnchorNode);
|
|
3167
3327
|
if (propertyType.isStringLiteral()) {
|
|
3168
3328
|
return propertyType.value;
|
|
3169
3329
|
}
|
|
@@ -4122,14 +4282,39 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
4122
4282
|
collectedDiagnostics
|
|
4123
4283
|
);
|
|
4124
4284
|
const fieldNodeInfo = fieldInfoMap?.get(prop.name);
|
|
4285
|
+
const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts3.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
|
|
4286
|
+
declaration,
|
|
4287
|
+
checker,
|
|
4288
|
+
file,
|
|
4289
|
+
typeRegistry,
|
|
4290
|
+
visiting,
|
|
4291
|
+
collectedDiagnostics,
|
|
4292
|
+
type,
|
|
4293
|
+
metadataPolicy,
|
|
4294
|
+
extensionRegistry
|
|
4295
|
+
) : ts3.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
|
|
4296
|
+
declaration,
|
|
4297
|
+
checker,
|
|
4298
|
+
file,
|
|
4299
|
+
typeRegistry,
|
|
4300
|
+
visiting,
|
|
4301
|
+
collectedDiagnostics,
|
|
4302
|
+
type,
|
|
4303
|
+
metadataPolicy,
|
|
4304
|
+
extensionRegistry
|
|
4305
|
+
) : null : null;
|
|
4306
|
+
const resolvedFieldNodeInfo = fieldNodeInfo ?? inlineFieldNodeInfo;
|
|
4307
|
+
const resolvedPropertyType = inlineFieldNodeInfo?.type ?? propTypeNode;
|
|
4125
4308
|
properties.push({
|
|
4126
4309
|
name: prop.name,
|
|
4127
|
-
...
|
|
4128
|
-
|
|
4310
|
+
...resolvedFieldNodeInfo?.metadata !== void 0 && {
|
|
4311
|
+
metadata: resolvedFieldNodeInfo.metadata
|
|
4312
|
+
},
|
|
4313
|
+
type: resolvedPropertyType,
|
|
4129
4314
|
optional,
|
|
4130
|
-
constraints:
|
|
4131
|
-
annotations:
|
|
4132
|
-
provenance:
|
|
4315
|
+
constraints: resolvedFieldNodeInfo?.constraints ?? [],
|
|
4316
|
+
annotations: resolvedFieldNodeInfo?.annotations ?? [],
|
|
4317
|
+
provenance: resolvedFieldNodeInfo?.provenance ?? provenanceForFile(file)
|
|
4133
4318
|
});
|
|
4134
4319
|
}
|
|
4135
4320
|
visiting.delete(type);
|
|
@@ -4727,6 +4912,345 @@ function generateSchemasFromProgram(options) {
|
|
|
4727
4912
|
);
|
|
4728
4913
|
}
|
|
4729
4914
|
|
|
4915
|
+
// src/static-build.ts
|
|
4916
|
+
import * as ts6 from "typescript";
|
|
4917
|
+
function toStaticBuildContext(context) {
|
|
4918
|
+
return context;
|
|
4919
|
+
}
|
|
4920
|
+
function createStaticBuildContext(filePath) {
|
|
4921
|
+
return toStaticBuildContext(createProgramContext(filePath));
|
|
4922
|
+
}
|
|
4923
|
+
function createStaticBuildContextFromProgram(program, filePath) {
|
|
4924
|
+
return toStaticBuildContext(createProgramContextFromProgram(program, filePath));
|
|
4925
|
+
}
|
|
4926
|
+
function getModuleSymbol(context) {
|
|
4927
|
+
const sourceFileWithSymbol = context.sourceFile;
|
|
4928
|
+
return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
|
|
4929
|
+
}
|
|
4930
|
+
function isSchemaSourceDeclaration(declaration) {
|
|
4931
|
+
return ts6.isClassDeclaration(declaration) || ts6.isInterfaceDeclaration(declaration) || ts6.isTypeAliasDeclaration(declaration);
|
|
4932
|
+
}
|
|
4933
|
+
function resolveModuleExport(context, exportName = "default") {
|
|
4934
|
+
const moduleSymbol = getModuleSymbol(context);
|
|
4935
|
+
if (moduleSymbol === void 0) {
|
|
4936
|
+
return null;
|
|
4937
|
+
}
|
|
4938
|
+
const exportSymbol = context.checker.getExportsOfModule(moduleSymbol).find((candidate) => candidate.name === exportName) ?? null;
|
|
4939
|
+
if (exportSymbol === null) {
|
|
4940
|
+
return null;
|
|
4941
|
+
}
|
|
4942
|
+
return exportSymbol.flags & ts6.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
|
|
4943
|
+
}
|
|
4944
|
+
function resolveModuleExportDeclaration(context, exportName = "default") {
|
|
4945
|
+
return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
|
|
4946
|
+
}
|
|
4947
|
+
|
|
4948
|
+
// src/generators/discovered-schema.ts
|
|
4949
|
+
import * as ts7 from "typescript";
|
|
4950
|
+
import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
|
|
4951
|
+
function toDiscoveredTypeSchemas(result) {
|
|
4952
|
+
return result;
|
|
4953
|
+
}
|
|
4954
|
+
function isNamedTypeDeclaration(declaration) {
|
|
4955
|
+
return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
|
|
4956
|
+
}
|
|
4957
|
+
function hasConcreteTypeArguments(type, checker) {
|
|
4958
|
+
if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
|
|
4959
|
+
return true;
|
|
4960
|
+
}
|
|
4961
|
+
if ((type.flags & ts7.TypeFlags.Object) === 0) {
|
|
4962
|
+
return false;
|
|
4963
|
+
}
|
|
4964
|
+
const objectType = type;
|
|
4965
|
+
if ((objectType.objectFlags & ts7.ObjectFlags.Reference) === 0) {
|
|
4966
|
+
return false;
|
|
4967
|
+
}
|
|
4968
|
+
return checker.getTypeArguments(objectType).length > 0;
|
|
4969
|
+
}
|
|
4970
|
+
function getNamedTypeDeclaration2(type) {
|
|
4971
|
+
const symbol = type.getSymbol();
|
|
4972
|
+
if (symbol?.declarations !== void 0) {
|
|
4973
|
+
const declaration = symbol.declarations[0];
|
|
4974
|
+
if (declaration !== void 0 && isNamedTypeDeclaration(declaration)) {
|
|
4975
|
+
return declaration;
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts7.isTypeAliasDeclaration);
|
|
4979
|
+
return aliasDeclaration;
|
|
4980
|
+
}
|
|
4981
|
+
function getFallbackName(sourceNode, fallback = "AnonymousType") {
|
|
4982
|
+
if (sourceNode !== void 0 && "name" in sourceNode) {
|
|
4983
|
+
const namedNode = sourceNode;
|
|
4984
|
+
if (namedNode.name !== void 0 && ts7.isIdentifier(namedNode.name)) {
|
|
4985
|
+
return namedNode.name.text;
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4988
|
+
return fallback;
|
|
4989
|
+
}
|
|
4990
|
+
function createObjectRootAnalysis(name, properties, typeRegistry, metadata, annotations) {
|
|
4991
|
+
const fields = properties.map((property) => ({
|
|
4992
|
+
kind: "field",
|
|
4993
|
+
name: property.name,
|
|
4994
|
+
...property.metadata !== void 0 && { metadata: property.metadata },
|
|
4995
|
+
type: property.type,
|
|
4996
|
+
required: !property.optional,
|
|
4997
|
+
constraints: property.constraints,
|
|
4998
|
+
annotations: property.annotations,
|
|
4999
|
+
provenance: property.provenance
|
|
5000
|
+
}));
|
|
5001
|
+
return {
|
|
5002
|
+
name,
|
|
5003
|
+
...metadata !== void 0 && { metadata },
|
|
5004
|
+
fields,
|
|
5005
|
+
fieldLayouts: fields.map(() => ({})),
|
|
5006
|
+
typeRegistry,
|
|
5007
|
+
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
5008
|
+
instanceMethods: [],
|
|
5009
|
+
staticMethods: [],
|
|
5010
|
+
diagnostics: []
|
|
5011
|
+
};
|
|
5012
|
+
}
|
|
5013
|
+
function omitApiName(metadata) {
|
|
5014
|
+
if (metadata?.apiName === void 0) {
|
|
5015
|
+
return metadata;
|
|
5016
|
+
}
|
|
5017
|
+
const { apiName: _apiName, ...rest } = metadata;
|
|
5018
|
+
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
5019
|
+
}
|
|
5020
|
+
function describeRootType(rootType, typeRegistry, fallbackName) {
|
|
5021
|
+
if (rootType.kind !== "reference") {
|
|
5022
|
+
return {
|
|
5023
|
+
name: fallbackName,
|
|
5024
|
+
type: rootType
|
|
5025
|
+
};
|
|
5026
|
+
}
|
|
5027
|
+
const definition = typeRegistry[rootType.name];
|
|
5028
|
+
if (definition === void 0) {
|
|
5029
|
+
return {
|
|
5030
|
+
name: rootType.name,
|
|
5031
|
+
type: rootType
|
|
5032
|
+
};
|
|
5033
|
+
}
|
|
5034
|
+
return {
|
|
5035
|
+
name: definition.name,
|
|
5036
|
+
...definition.metadata !== void 0 && { metadata: definition.metadata },
|
|
5037
|
+
...definition.annotations !== void 0 && definition.annotations.length > 0 && { annotations: definition.annotations },
|
|
5038
|
+
type: definition.type
|
|
5039
|
+
};
|
|
5040
|
+
}
|
|
5041
|
+
function toStandaloneJsonSchema(root, typeRegistry, options) {
|
|
5042
|
+
const syntheticFieldMetadata = omitApiName(root.metadata);
|
|
5043
|
+
const syntheticField = {
|
|
5044
|
+
kind: "field",
|
|
5045
|
+
name: "__result",
|
|
5046
|
+
...syntheticFieldMetadata !== void 0 && { metadata: syntheticFieldMetadata },
|
|
5047
|
+
type: root.type,
|
|
5048
|
+
required: true,
|
|
5049
|
+
constraints: [],
|
|
5050
|
+
annotations: [...root.annotations ?? []],
|
|
5051
|
+
provenance: {
|
|
5052
|
+
surface: "tsdoc",
|
|
5053
|
+
file: "",
|
|
5054
|
+
line: 1,
|
|
5055
|
+
column: 0
|
|
5056
|
+
}
|
|
5057
|
+
};
|
|
5058
|
+
const schema = generateJsonSchemaFromIR(
|
|
5059
|
+
{
|
|
5060
|
+
kind: "form-ir",
|
|
5061
|
+
name: root.name,
|
|
5062
|
+
irVersion: IR_VERSION3,
|
|
5063
|
+
elements: [syntheticField],
|
|
5064
|
+
...root.metadata !== void 0 && { metadata: root.metadata },
|
|
5065
|
+
...root.annotations !== void 0 && root.annotations.length > 0 && { rootAnnotations: root.annotations },
|
|
5066
|
+
typeRegistry,
|
|
5067
|
+
provenance: syntheticField.provenance
|
|
5068
|
+
},
|
|
5069
|
+
{
|
|
5070
|
+
extensionRegistry: options?.extensionRegistry,
|
|
5071
|
+
vendorPrefix: options?.vendorPrefix
|
|
5072
|
+
}
|
|
5073
|
+
);
|
|
5074
|
+
const result = schema.properties?.["__result"];
|
|
5075
|
+
if (result === void 0) {
|
|
5076
|
+
throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
|
|
5077
|
+
}
|
|
5078
|
+
if (schema.$defs === void 0 || Object.keys(schema.$defs).length === 0) {
|
|
5079
|
+
return {
|
|
5080
|
+
...schema.$schema !== void 0 && { $schema: schema.$schema },
|
|
5081
|
+
...result
|
|
5082
|
+
};
|
|
5083
|
+
}
|
|
5084
|
+
return {
|
|
5085
|
+
...schema.$schema !== void 0 && { $schema: schema.$schema },
|
|
5086
|
+
...result,
|
|
5087
|
+
$defs: schema.$defs
|
|
5088
|
+
};
|
|
5089
|
+
}
|
|
5090
|
+
function generateSchemasFromAnalysis(analysis, filePath, options) {
|
|
5091
|
+
return toDiscoveredTypeSchemas(
|
|
5092
|
+
generateClassSchemas(
|
|
5093
|
+
analysis,
|
|
5094
|
+
{ file: filePath },
|
|
5095
|
+
{
|
|
5096
|
+
extensionRegistry: options?.extensionRegistry,
|
|
5097
|
+
metadata: options?.metadata,
|
|
5098
|
+
vendorPrefix: options?.vendorPrefix
|
|
5099
|
+
}
|
|
5100
|
+
)
|
|
5101
|
+
);
|
|
5102
|
+
}
|
|
5103
|
+
function generateSchemasFromResolvedType(options, skipNamedDeclaration = false, rootOverride) {
|
|
5104
|
+
const namedDeclaration = skipNamedDeclaration || hasConcreteTypeArguments(options.type, options.context.checker) ? void 0 : getNamedTypeDeclaration2(options.type);
|
|
5105
|
+
if (namedDeclaration !== void 0) {
|
|
5106
|
+
return generateSchemasFromDeclaration({
|
|
5107
|
+
...options,
|
|
5108
|
+
declaration: namedDeclaration
|
|
5109
|
+
});
|
|
5110
|
+
}
|
|
5111
|
+
const filePath = options.sourceNode?.getSourceFile().fileName ?? options.context.sourceFile.fileName;
|
|
5112
|
+
const typeRegistry = {};
|
|
5113
|
+
const diagnostics = [];
|
|
5114
|
+
const rootType = resolveTypeNode(
|
|
5115
|
+
options.type,
|
|
5116
|
+
options.context.checker,
|
|
5117
|
+
filePath,
|
|
5118
|
+
typeRegistry,
|
|
5119
|
+
/* @__PURE__ */ new Set(),
|
|
5120
|
+
options.sourceNode,
|
|
5121
|
+
normalizeMetadataPolicy(options.metadata),
|
|
5122
|
+
options.extensionRegistry,
|
|
5123
|
+
diagnostics
|
|
5124
|
+
);
|
|
5125
|
+
if (diagnostics.length > 0) {
|
|
5126
|
+
const diagnosticDetails = diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
|
|
5127
|
+
throw new Error(
|
|
5128
|
+
`FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
|
|
5129
|
+
);
|
|
5130
|
+
}
|
|
5131
|
+
const describedRoot = describeRootType(
|
|
5132
|
+
rootType,
|
|
5133
|
+
typeRegistry,
|
|
5134
|
+
options.name ?? getFallbackName(options.sourceNode)
|
|
5135
|
+
);
|
|
5136
|
+
const mergedMetadata = mergeResolvedMetadata(describedRoot.metadata, rootOverride?.metadata);
|
|
5137
|
+
const root = {
|
|
5138
|
+
...describedRoot,
|
|
5139
|
+
...rootOverride?.name !== void 0 && { name: rootOverride.name },
|
|
5140
|
+
...mergedMetadata !== void 0 && { metadata: mergedMetadata },
|
|
5141
|
+
...rootOverride?.annotations !== void 0 && { annotations: rootOverride.annotations }
|
|
5142
|
+
};
|
|
5143
|
+
if (root.type.kind === "object") {
|
|
5144
|
+
return generateSchemasFromAnalysis(
|
|
5145
|
+
createObjectRootAnalysis(
|
|
5146
|
+
options.name ?? root.name,
|
|
5147
|
+
root.type.properties,
|
|
5148
|
+
typeRegistry,
|
|
5149
|
+
root.metadata,
|
|
5150
|
+
root.annotations
|
|
5151
|
+
),
|
|
5152
|
+
filePath,
|
|
5153
|
+
options
|
|
5154
|
+
);
|
|
5155
|
+
}
|
|
5156
|
+
return {
|
|
5157
|
+
jsonSchema: toStandaloneJsonSchema(root, typeRegistry, options),
|
|
5158
|
+
uiSchema: null
|
|
5159
|
+
};
|
|
5160
|
+
}
|
|
5161
|
+
function generateSchemasFromDeclaration(options) {
|
|
5162
|
+
const filePath = options.declaration.getSourceFile().fileName;
|
|
5163
|
+
if (ts7.isClassDeclaration(options.declaration)) {
|
|
5164
|
+
return generateSchemasFromAnalysis(
|
|
5165
|
+
analyzeClassToIR(
|
|
5166
|
+
options.declaration,
|
|
5167
|
+
options.context.checker,
|
|
5168
|
+
filePath,
|
|
5169
|
+
options.extensionRegistry,
|
|
5170
|
+
options.metadata
|
|
5171
|
+
),
|
|
5172
|
+
filePath,
|
|
5173
|
+
options
|
|
5174
|
+
);
|
|
5175
|
+
}
|
|
5176
|
+
if (ts7.isInterfaceDeclaration(options.declaration)) {
|
|
5177
|
+
return generateSchemasFromAnalysis(
|
|
5178
|
+
analyzeInterfaceToIR(
|
|
5179
|
+
options.declaration,
|
|
5180
|
+
options.context.checker,
|
|
5181
|
+
filePath,
|
|
5182
|
+
options.extensionRegistry,
|
|
5183
|
+
options.metadata
|
|
5184
|
+
),
|
|
5185
|
+
filePath,
|
|
5186
|
+
options
|
|
5187
|
+
);
|
|
5188
|
+
}
|
|
5189
|
+
if (ts7.isTypeAliasDeclaration(options.declaration)) {
|
|
5190
|
+
const analyzedAlias = analyzeTypeAliasToIR(
|
|
5191
|
+
options.declaration,
|
|
5192
|
+
options.context.checker,
|
|
5193
|
+
filePath,
|
|
5194
|
+
options.extensionRegistry,
|
|
5195
|
+
options.metadata
|
|
5196
|
+
);
|
|
5197
|
+
if (analyzedAlias.ok) {
|
|
5198
|
+
return generateSchemasFromAnalysis(analyzedAlias.analysis, filePath, options);
|
|
5199
|
+
}
|
|
5200
|
+
const aliasRootInfo = analyzeDeclarationRootInfo(
|
|
5201
|
+
options.declaration,
|
|
5202
|
+
options.context.checker,
|
|
5203
|
+
filePath,
|
|
5204
|
+
options.extensionRegistry,
|
|
5205
|
+
options.metadata
|
|
5206
|
+
);
|
|
5207
|
+
if (aliasRootInfo.diagnostics.length > 0) {
|
|
5208
|
+
const diagnosticDetails = aliasRootInfo.diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
|
|
5209
|
+
throw new Error(
|
|
5210
|
+
`FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
|
|
5211
|
+
);
|
|
5212
|
+
}
|
|
5213
|
+
return generateSchemasFromResolvedType(
|
|
5214
|
+
{
|
|
5215
|
+
...options,
|
|
5216
|
+
type: options.context.checker.getTypeAtLocation(options.declaration),
|
|
5217
|
+
sourceNode: options.declaration,
|
|
5218
|
+
name: options.declaration.name.text
|
|
5219
|
+
},
|
|
5220
|
+
true,
|
|
5221
|
+
{
|
|
5222
|
+
name: options.declaration.name.text,
|
|
5223
|
+
...aliasRootInfo.metadata !== void 0 && { metadata: aliasRootInfo.metadata },
|
|
5224
|
+
...aliasRootInfo.annotations.length > 0 && { annotations: aliasRootInfo.annotations }
|
|
5225
|
+
}
|
|
5226
|
+
);
|
|
5227
|
+
}
|
|
5228
|
+
const _exhaustive = options.declaration;
|
|
5229
|
+
return _exhaustive;
|
|
5230
|
+
}
|
|
5231
|
+
function generateSchemasFromType(options) {
|
|
5232
|
+
return generateSchemasFromResolvedType(options);
|
|
5233
|
+
}
|
|
5234
|
+
function generateSchemasFromParameter(options) {
|
|
5235
|
+
return generateSchemasFromResolvedType({
|
|
5236
|
+
...options,
|
|
5237
|
+
type: options.context.checker.getTypeAtLocation(options.parameter),
|
|
5238
|
+
sourceNode: options.parameter,
|
|
5239
|
+
name: getFallbackName(options.parameter, "Parameter")
|
|
5240
|
+
});
|
|
5241
|
+
}
|
|
5242
|
+
function generateSchemasFromReturnType(options) {
|
|
5243
|
+
const signature = options.context.checker.getSignatureFromDeclaration(options.declaration);
|
|
5244
|
+
const type = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
|
|
5245
|
+
const fallbackName = options.declaration.name !== void 0 && ts7.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
|
|
5246
|
+
return generateSchemasFromResolvedType({
|
|
5247
|
+
...options,
|
|
5248
|
+
type,
|
|
5249
|
+
sourceNode: options.declaration.type ?? options.declaration,
|
|
5250
|
+
name: fallbackName
|
|
5251
|
+
});
|
|
5252
|
+
}
|
|
5253
|
+
|
|
4730
5254
|
// src/generators/mixed-authoring.ts
|
|
4731
5255
|
function buildMixedAuthoringSchemas(options) {
|
|
4732
5256
|
const { filePath, typeName, overlays, ...schemaOptions } = options;
|
|
@@ -4941,12 +5465,20 @@ export {
|
|
|
4941
5465
|
buildFormSchemas,
|
|
4942
5466
|
buildMixedAuthoringSchemas,
|
|
4943
5467
|
createExtensionRegistry,
|
|
5468
|
+
createStaticBuildContext,
|
|
5469
|
+
createStaticBuildContextFromProgram,
|
|
4944
5470
|
generateJsonSchema,
|
|
4945
5471
|
generateSchemas,
|
|
4946
5472
|
generateSchemasFromClass,
|
|
5473
|
+
generateSchemasFromDeclaration,
|
|
5474
|
+
generateSchemasFromParameter,
|
|
4947
5475
|
generateSchemasFromProgram,
|
|
5476
|
+
generateSchemasFromReturnType,
|
|
5477
|
+
generateSchemasFromType,
|
|
4948
5478
|
generateUiSchema,
|
|
4949
5479
|
jsonSchema7Schema,
|
|
5480
|
+
resolveModuleExport,
|
|
5481
|
+
resolveModuleExportDeclaration,
|
|
4950
5482
|
uiSchema as uiSchemaSchema,
|
|
4951
5483
|
writeSchemas
|
|
4952
5484
|
};
|