@formspec/build 0.1.0-alpha.26 → 0.1.0-alpha.28
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/LICENSE +21 -0
- package/README.md +3 -2
- package/dist/analyzer/class-analyzer.d.ts +1 -1
- package/dist/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/analyzer/program.d.ts +12 -0
- package/dist/analyzer/program.d.ts.map +1 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +1 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +48 -22
- package/dist/build-beta.d.ts +48 -22
- package/dist/build-internal.d.ts +48 -22
- package/dist/build.d.ts +151 -21
- package/dist/cli.cjs +609 -41
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +605 -36
- package/dist/cli.js.map +1 -1
- package/dist/generators/class-schema.d.ts +27 -0
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/generators/method-schema.d.ts.map +1 -1
- package/dist/generators/mixed-authoring.d.ts.map +1 -1
- package/dist/index.cjs +603 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +599 -36
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +552 -34
- 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 +549 -31
- package/dist/internals.js.map +1 -1
- package/dist/json-schema/schema.d.ts +2 -2
- package/dist/json-schema/types.d.ts +4 -4
- package/dist/ui-schema/schema.d.ts +2 -7
- package/dist/ui-schema/schema.d.ts.map +1 -1
- package/package.json +7 -6
package/dist/cli.cjs
CHANGED
|
@@ -1235,6 +1235,74 @@ var init_extensions = __esm({
|
|
|
1235
1235
|
}
|
|
1236
1236
|
});
|
|
1237
1237
|
|
|
1238
|
+
// src/json-schema/schema.ts
|
|
1239
|
+
var import_zod3, jsonSchemaTypeSchema, jsonSchema7Schema;
|
|
1240
|
+
var init_schema2 = __esm({
|
|
1241
|
+
"src/json-schema/schema.ts"() {
|
|
1242
|
+
"use strict";
|
|
1243
|
+
import_zod3 = require("zod");
|
|
1244
|
+
jsonSchemaTypeSchema = import_zod3.z.enum([
|
|
1245
|
+
"string",
|
|
1246
|
+
"number",
|
|
1247
|
+
"integer",
|
|
1248
|
+
"boolean",
|
|
1249
|
+
"object",
|
|
1250
|
+
"array",
|
|
1251
|
+
"null"
|
|
1252
|
+
]);
|
|
1253
|
+
jsonSchema7Schema = import_zod3.z.lazy(
|
|
1254
|
+
() => import_zod3.z.object({
|
|
1255
|
+
$schema: import_zod3.z.string().optional(),
|
|
1256
|
+
$id: import_zod3.z.string().optional(),
|
|
1257
|
+
$ref: import_zod3.z.string().optional(),
|
|
1258
|
+
// Metadata
|
|
1259
|
+
title: import_zod3.z.string().optional(),
|
|
1260
|
+
description: import_zod3.z.string().optional(),
|
|
1261
|
+
deprecated: import_zod3.z.boolean().optional(),
|
|
1262
|
+
// Type
|
|
1263
|
+
type: import_zod3.z.union([jsonSchemaTypeSchema, import_zod3.z.array(jsonSchemaTypeSchema)]).optional(),
|
|
1264
|
+
// String validation
|
|
1265
|
+
minLength: import_zod3.z.number().optional(),
|
|
1266
|
+
maxLength: import_zod3.z.number().optional(),
|
|
1267
|
+
pattern: import_zod3.z.string().optional(),
|
|
1268
|
+
// Number validation
|
|
1269
|
+
minimum: import_zod3.z.number().optional(),
|
|
1270
|
+
maximum: import_zod3.z.number().optional(),
|
|
1271
|
+
exclusiveMinimum: import_zod3.z.number().optional(),
|
|
1272
|
+
exclusiveMaximum: import_zod3.z.number().optional(),
|
|
1273
|
+
// Enum
|
|
1274
|
+
enum: import_zod3.z.array(import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean(), import_zod3.z.null()])).readonly().optional(),
|
|
1275
|
+
const: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean(), import_zod3.z.null()]).optional(),
|
|
1276
|
+
// Object
|
|
1277
|
+
properties: import_zod3.z.record(import_zod3.z.string(), jsonSchema7Schema).optional(),
|
|
1278
|
+
required: import_zod3.z.array(import_zod3.z.string()).optional(),
|
|
1279
|
+
additionalProperties: import_zod3.z.union([import_zod3.z.boolean(), jsonSchema7Schema]).optional(),
|
|
1280
|
+
// Array
|
|
1281
|
+
items: import_zod3.z.union([jsonSchema7Schema, import_zod3.z.array(jsonSchema7Schema)]).optional(),
|
|
1282
|
+
minItems: import_zod3.z.number().optional(),
|
|
1283
|
+
maxItems: import_zod3.z.number().optional(),
|
|
1284
|
+
// Composition
|
|
1285
|
+
allOf: import_zod3.z.array(jsonSchema7Schema).optional(),
|
|
1286
|
+
anyOf: import_zod3.z.array(jsonSchema7Schema).optional(),
|
|
1287
|
+
oneOf: import_zod3.z.array(jsonSchema7Schema).optional(),
|
|
1288
|
+
not: jsonSchema7Schema.optional(),
|
|
1289
|
+
// Conditional
|
|
1290
|
+
if: jsonSchema7Schema.optional(),
|
|
1291
|
+
then: jsonSchema7Schema.optional(),
|
|
1292
|
+
else: jsonSchema7Schema.optional(),
|
|
1293
|
+
// Format
|
|
1294
|
+
format: import_zod3.z.string().optional(),
|
|
1295
|
+
// Default
|
|
1296
|
+
default: import_zod3.z.unknown().optional(),
|
|
1297
|
+
// FormSpec extensions
|
|
1298
|
+
"x-formspec-source": import_zod3.z.string().optional(),
|
|
1299
|
+
"x-formspec-params": import_zod3.z.array(import_zod3.z.string()).readonly().optional(),
|
|
1300
|
+
"x-formspec-schemaSource": import_zod3.z.string().optional()
|
|
1301
|
+
}).passthrough()
|
|
1302
|
+
);
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
|
|
1238
1306
|
// src/analyzer/tsdoc-parser.ts
|
|
1239
1307
|
function createFormSpecTSDocConfig(extensionTagNames = []) {
|
|
1240
1308
|
const config = new import_tsdoc.TSDocConfiguration();
|
|
@@ -2162,9 +2230,17 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2162
2230
|
}
|
|
2163
2231
|
}
|
|
2164
2232
|
}
|
|
2233
|
+
const specializedFields = applyDeclarationDiscriminatorToFields(
|
|
2234
|
+
fields,
|
|
2235
|
+
classDecl,
|
|
2236
|
+
classType,
|
|
2237
|
+
checker,
|
|
2238
|
+
file,
|
|
2239
|
+
diagnostics
|
|
2240
|
+
);
|
|
2165
2241
|
return {
|
|
2166
2242
|
name,
|
|
2167
|
-
fields,
|
|
2243
|
+
fields: specializedFields,
|
|
2168
2244
|
fieldLayouts,
|
|
2169
2245
|
typeRegistry,
|
|
2170
2246
|
...annotations.length > 0 && { annotations },
|
|
@@ -2204,10 +2280,18 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2204
2280
|
}
|
|
2205
2281
|
}
|
|
2206
2282
|
}
|
|
2207
|
-
const
|
|
2283
|
+
const specializedFields = applyDeclarationDiscriminatorToFields(
|
|
2284
|
+
fields,
|
|
2285
|
+
interfaceDecl,
|
|
2286
|
+
interfaceType,
|
|
2287
|
+
checker,
|
|
2288
|
+
file,
|
|
2289
|
+
diagnostics
|
|
2290
|
+
);
|
|
2291
|
+
const fieldLayouts = specializedFields.map(() => ({}));
|
|
2208
2292
|
return {
|
|
2209
2293
|
name,
|
|
2210
|
-
fields,
|
|
2294
|
+
fields: specializedFields,
|
|
2211
2295
|
fieldLayouts,
|
|
2212
2296
|
typeRegistry,
|
|
2213
2297
|
...annotations.length > 0 && { annotations },
|
|
@@ -2256,12 +2340,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2256
2340
|
}
|
|
2257
2341
|
}
|
|
2258
2342
|
}
|
|
2343
|
+
const specializedFields = applyDeclarationDiscriminatorToFields(
|
|
2344
|
+
fields,
|
|
2345
|
+
typeAlias,
|
|
2346
|
+
aliasType,
|
|
2347
|
+
checker,
|
|
2348
|
+
file,
|
|
2349
|
+
diagnostics
|
|
2350
|
+
);
|
|
2259
2351
|
return {
|
|
2260
2352
|
ok: true,
|
|
2261
2353
|
analysis: {
|
|
2262
2354
|
name,
|
|
2263
|
-
fields,
|
|
2264
|
-
fieldLayouts:
|
|
2355
|
+
fields: specializedFields,
|
|
2356
|
+
fieldLayouts: specializedFields.map(() => ({})),
|
|
2265
2357
|
typeRegistry,
|
|
2266
2358
|
...annotations.length > 0 && { annotations },
|
|
2267
2359
|
...diagnostics.length > 0 && { diagnostics },
|
|
@@ -2270,6 +2362,396 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2270
2362
|
}
|
|
2271
2363
|
};
|
|
2272
2364
|
}
|
|
2365
|
+
function makeAnalysisDiagnostic(code, message, primaryLocation, relatedLocations = []) {
|
|
2366
|
+
return {
|
|
2367
|
+
code,
|
|
2368
|
+
message,
|
|
2369
|
+
severity: "error",
|
|
2370
|
+
primaryLocation,
|
|
2371
|
+
relatedLocations
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
function getLeadingParsedTags(node) {
|
|
2375
|
+
const sourceFile = node.getSourceFile();
|
|
2376
|
+
const sourceText = sourceFile.getFullText();
|
|
2377
|
+
const commentRanges = ts3.getLeadingCommentRanges(sourceText, node.getFullStart());
|
|
2378
|
+
if (commentRanges === void 0) {
|
|
2379
|
+
return [];
|
|
2380
|
+
}
|
|
2381
|
+
const parsedTags = [];
|
|
2382
|
+
for (const range of commentRanges) {
|
|
2383
|
+
if (range.kind !== ts3.SyntaxKind.MultiLineCommentTrivia) {
|
|
2384
|
+
continue;
|
|
2385
|
+
}
|
|
2386
|
+
const commentText = sourceText.slice(range.pos, range.end);
|
|
2387
|
+
if (!commentText.startsWith("/**")) {
|
|
2388
|
+
continue;
|
|
2389
|
+
}
|
|
2390
|
+
parsedTags.push(...(0, import_internal2.parseCommentBlock)(commentText, { offset: range.pos }).tags);
|
|
2391
|
+
}
|
|
2392
|
+
return parsedTags;
|
|
2393
|
+
}
|
|
2394
|
+
function findDiscriminatorProperty(node, fieldName) {
|
|
2395
|
+
if (ts3.isClassDeclaration(node)) {
|
|
2396
|
+
for (const member of node.members) {
|
|
2397
|
+
if (ts3.isPropertyDeclaration(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2398
|
+
return member;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
return null;
|
|
2402
|
+
}
|
|
2403
|
+
if (ts3.isInterfaceDeclaration(node)) {
|
|
2404
|
+
for (const member of node.members) {
|
|
2405
|
+
if (ts3.isPropertySignature(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2406
|
+
return member;
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
return null;
|
|
2410
|
+
}
|
|
2411
|
+
if (ts3.isTypeLiteralNode(node.type)) {
|
|
2412
|
+
for (const member of node.type.members) {
|
|
2413
|
+
if (ts3.isPropertySignature(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2414
|
+
return member;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
return null;
|
|
2419
|
+
}
|
|
2420
|
+
function isLocalTypeParameterName(node, typeParameterName) {
|
|
2421
|
+
return node.typeParameters?.some((typeParameter) => typeParameter.name.text === typeParameterName) ?? false;
|
|
2422
|
+
}
|
|
2423
|
+
function isNullishSemanticType(type) {
|
|
2424
|
+
if (type.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined | ts3.TypeFlags.Void | ts3.TypeFlags.Unknown | ts3.TypeFlags.Any)) {
|
|
2425
|
+
return true;
|
|
2426
|
+
}
|
|
2427
|
+
return type.isUnion() && type.types.some((member) => isNullishSemanticType(member));
|
|
2428
|
+
}
|
|
2429
|
+
function isStringLikeSemanticType(type) {
|
|
2430
|
+
if (type.flags & ts3.TypeFlags.StringLike) {
|
|
2431
|
+
return true;
|
|
2432
|
+
}
|
|
2433
|
+
if (type.isUnion()) {
|
|
2434
|
+
return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member));
|
|
2435
|
+
}
|
|
2436
|
+
return false;
|
|
2437
|
+
}
|
|
2438
|
+
function extractDiscriminatorDirective(node, file, diagnostics) {
|
|
2439
|
+
const discriminatorTags = getLeadingParsedTags(node).filter(
|
|
2440
|
+
(tag) => tag.normalizedTagName === "discriminator"
|
|
2441
|
+
);
|
|
2442
|
+
if (discriminatorTags.length === 0) {
|
|
2443
|
+
return null;
|
|
2444
|
+
}
|
|
2445
|
+
const [firstTag, ...duplicateTags] = discriminatorTags;
|
|
2446
|
+
for (const _duplicateTag of duplicateTags) {
|
|
2447
|
+
diagnostics.push(
|
|
2448
|
+
makeAnalysisDiagnostic(
|
|
2449
|
+
"DUPLICATE_TAG",
|
|
2450
|
+
'Duplicate "@discriminator" tag. Only one discriminator declaration is allowed per declaration.',
|
|
2451
|
+
provenanceForNode(node, file)
|
|
2452
|
+
)
|
|
2453
|
+
);
|
|
2454
|
+
}
|
|
2455
|
+
if (firstTag === void 0) {
|
|
2456
|
+
return null;
|
|
2457
|
+
}
|
|
2458
|
+
const firstTarget = firstTag.target;
|
|
2459
|
+
if (firstTarget?.path === null || firstTarget?.valid !== true) {
|
|
2460
|
+
diagnostics.push(
|
|
2461
|
+
makeAnalysisDiagnostic(
|
|
2462
|
+
"INVALID_TAG_ARGUMENT",
|
|
2463
|
+
'Tag "@discriminator" requires a direct path target like ":kind".',
|
|
2464
|
+
provenanceForNode(node, file)
|
|
2465
|
+
)
|
|
2466
|
+
);
|
|
2467
|
+
return null;
|
|
2468
|
+
}
|
|
2469
|
+
if (firstTarget.path.segments.length !== 1) {
|
|
2470
|
+
diagnostics.push(
|
|
2471
|
+
makeAnalysisDiagnostic(
|
|
2472
|
+
"INVALID_TAG_ARGUMENT",
|
|
2473
|
+
'Tag "@discriminator" only supports direct property targets in v1; nested paths are out of scope.',
|
|
2474
|
+
provenanceForNode(node, file)
|
|
2475
|
+
)
|
|
2476
|
+
);
|
|
2477
|
+
return null;
|
|
2478
|
+
}
|
|
2479
|
+
const typeParameterName = firstTag.argumentText.trim();
|
|
2480
|
+
if (!/^[A-Za-z_$][\w$]*$/u.test(typeParameterName)) {
|
|
2481
|
+
diagnostics.push(
|
|
2482
|
+
makeAnalysisDiagnostic(
|
|
2483
|
+
"INVALID_TAG_ARGUMENT",
|
|
2484
|
+
'Tag "@discriminator" requires a local type parameter name as its source operand.',
|
|
2485
|
+
provenanceForNode(node, file)
|
|
2486
|
+
)
|
|
2487
|
+
);
|
|
2488
|
+
return null;
|
|
2489
|
+
}
|
|
2490
|
+
return {
|
|
2491
|
+
fieldName: firstTarget.path.segments[0] ?? firstTarget.rawText,
|
|
2492
|
+
typeParameterName,
|
|
2493
|
+
provenance: provenanceForNode(node, file)
|
|
2494
|
+
};
|
|
2495
|
+
}
|
|
2496
|
+
function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
2497
|
+
const directive = extractDiscriminatorDirective(node, file, diagnostics);
|
|
2498
|
+
if (directive === null) {
|
|
2499
|
+
return null;
|
|
2500
|
+
}
|
|
2501
|
+
if (!isLocalTypeParameterName(node, directive.typeParameterName)) {
|
|
2502
|
+
diagnostics.push(
|
|
2503
|
+
makeAnalysisDiagnostic(
|
|
2504
|
+
"INVALID_TAG_ARGUMENT",
|
|
2505
|
+
`Tag "@discriminator" references "${directive.typeParameterName}", but the source operand must be a type parameter declared on the same declaration.`,
|
|
2506
|
+
directive.provenance
|
|
2507
|
+
)
|
|
2508
|
+
);
|
|
2509
|
+
return null;
|
|
2510
|
+
}
|
|
2511
|
+
const propertyDecl = findDiscriminatorProperty(node, directive.fieldName);
|
|
2512
|
+
if (propertyDecl === null) {
|
|
2513
|
+
diagnostics.push(
|
|
2514
|
+
makeAnalysisDiagnostic(
|
|
2515
|
+
"UNKNOWN_PATH_TARGET",
|
|
2516
|
+
`Tag "@discriminator" targets "${directive.fieldName}", but no direct property with that name exists on this declaration.`,
|
|
2517
|
+
directive.provenance
|
|
2518
|
+
)
|
|
2519
|
+
);
|
|
2520
|
+
return null;
|
|
2521
|
+
}
|
|
2522
|
+
if (propertyDecl.questionToken !== void 0) {
|
|
2523
|
+
diagnostics.push(
|
|
2524
|
+
makeAnalysisDiagnostic(
|
|
2525
|
+
"TYPE_MISMATCH",
|
|
2526
|
+
`Discriminator field "${directive.fieldName}" must be required; optional discriminator fields are not supported.`,
|
|
2527
|
+
directive.provenance,
|
|
2528
|
+
[provenanceForNode(propertyDecl, file)]
|
|
2529
|
+
)
|
|
2530
|
+
);
|
|
2531
|
+
return null;
|
|
2532
|
+
}
|
|
2533
|
+
const propertyType = checker.getTypeAtLocation(propertyDecl);
|
|
2534
|
+
if (isNullishSemanticType(propertyType)) {
|
|
2535
|
+
diagnostics.push(
|
|
2536
|
+
makeAnalysisDiagnostic(
|
|
2537
|
+
"TYPE_MISMATCH",
|
|
2538
|
+
`Discriminator field "${directive.fieldName}" must not be nullable.`,
|
|
2539
|
+
directive.provenance,
|
|
2540
|
+
[provenanceForNode(propertyDecl, file)]
|
|
2541
|
+
)
|
|
2542
|
+
);
|
|
2543
|
+
return null;
|
|
2544
|
+
}
|
|
2545
|
+
if (!isStringLikeSemanticType(propertyType)) {
|
|
2546
|
+
diagnostics.push(
|
|
2547
|
+
makeAnalysisDiagnostic(
|
|
2548
|
+
"TYPE_MISMATCH",
|
|
2549
|
+
`Discriminator field "${directive.fieldName}" must be string-like.`,
|
|
2550
|
+
directive.provenance,
|
|
2551
|
+
[provenanceForNode(propertyDecl, file)]
|
|
2552
|
+
)
|
|
2553
|
+
);
|
|
2554
|
+
return null;
|
|
2555
|
+
}
|
|
2556
|
+
return directive;
|
|
2557
|
+
}
|
|
2558
|
+
function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typeParameterName) {
|
|
2559
|
+
const typeParameterIndex = node.typeParameters?.findIndex(
|
|
2560
|
+
(typeParameter) => typeParameter.name.text === typeParameterName
|
|
2561
|
+
) ?? -1;
|
|
2562
|
+
if (typeParameterIndex < 0) {
|
|
2563
|
+
return null;
|
|
2564
|
+
}
|
|
2565
|
+
const referenceTypeArguments = (isTypeReference(subjectType) ? subjectType.typeArguments : void 0) ?? subjectType.aliasTypeArguments;
|
|
2566
|
+
if (referenceTypeArguments?.[typeParameterIndex] !== void 0) {
|
|
2567
|
+
return referenceTypeArguments[typeParameterIndex] ?? null;
|
|
2568
|
+
}
|
|
2569
|
+
const localTypeParameter = node.typeParameters?.[typeParameterIndex];
|
|
2570
|
+
return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
|
|
2571
|
+
}
|
|
2572
|
+
function extractDeclarationApiName(node) {
|
|
2573
|
+
for (const tag of getLeadingParsedTags(node)) {
|
|
2574
|
+
if (tag.normalizedTagName !== "apiName") {
|
|
2575
|
+
continue;
|
|
2576
|
+
}
|
|
2577
|
+
if (tag.target === null && tag.argumentText.trim() !== "") {
|
|
2578
|
+
return tag.argumentText.trim();
|
|
2579
|
+
}
|
|
2580
|
+
if (tag.target?.kind === "variant" && tag.target.rawText === "singular") {
|
|
2581
|
+
const value = tag.argumentText.trim();
|
|
2582
|
+
if (value !== "") {
|
|
2583
|
+
return value;
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
return null;
|
|
2588
|
+
}
|
|
2589
|
+
function inferJsonFacingName(name) {
|
|
2590
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/[-\s]+/g, "_").toLowerCase();
|
|
2591
|
+
}
|
|
2592
|
+
function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
2593
|
+
if (seen.has(type)) {
|
|
2594
|
+
return null;
|
|
2595
|
+
}
|
|
2596
|
+
seen.add(type);
|
|
2597
|
+
const symbol = type.aliasSymbol ?? type.getSymbol();
|
|
2598
|
+
if (symbol !== void 0) {
|
|
2599
|
+
const aliased = symbol.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : void 0;
|
|
2600
|
+
const targetSymbol = aliased ?? symbol;
|
|
2601
|
+
const declaration = targetSymbol.declarations?.find(
|
|
2602
|
+
(candidate) => ts3.isClassDeclaration(candidate) || ts3.isInterfaceDeclaration(candidate) || ts3.isTypeAliasDeclaration(candidate) || ts3.isEnumDeclaration(candidate)
|
|
2603
|
+
);
|
|
2604
|
+
if (declaration !== void 0) {
|
|
2605
|
+
if (ts3.isTypeAliasDeclaration(declaration) && ts3.isTypeReferenceNode(declaration.type) && checker.getTypeFromTypeNode(declaration.type) !== type) {
|
|
2606
|
+
return resolveNamedDiscriminatorDeclaration(
|
|
2607
|
+
checker.getTypeFromTypeNode(declaration.type),
|
|
2608
|
+
checker,
|
|
2609
|
+
seen
|
|
2610
|
+
);
|
|
2611
|
+
}
|
|
2612
|
+
return declaration;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
return null;
|
|
2616
|
+
}
|
|
2617
|
+
function resolveDiscriminatorValue(boundType, checker, provenance, diagnostics) {
|
|
2618
|
+
if (boundType === null) {
|
|
2619
|
+
diagnostics.push(
|
|
2620
|
+
makeAnalysisDiagnostic(
|
|
2621
|
+
"INVALID_TAG_ARGUMENT",
|
|
2622
|
+
"Discriminator resolution failed because no concrete type argument is available for the referenced type parameter.",
|
|
2623
|
+
provenance
|
|
2624
|
+
)
|
|
2625
|
+
);
|
|
2626
|
+
return null;
|
|
2627
|
+
}
|
|
2628
|
+
if (boundType.isStringLiteral()) {
|
|
2629
|
+
return boundType.value;
|
|
2630
|
+
}
|
|
2631
|
+
if (boundType.isUnion()) {
|
|
2632
|
+
const nonNullMembers = boundType.types.filter(
|
|
2633
|
+
(member) => !(member.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined))
|
|
2634
|
+
);
|
|
2635
|
+
if (nonNullMembers.every((member) => member.isStringLiteral())) {
|
|
2636
|
+
diagnostics.push(
|
|
2637
|
+
makeAnalysisDiagnostic(
|
|
2638
|
+
"INVALID_TAG_ARGUMENT",
|
|
2639
|
+
"Discriminator resolution for unions of string literals is out of scope for v1.",
|
|
2640
|
+
provenance
|
|
2641
|
+
)
|
|
2642
|
+
);
|
|
2643
|
+
return null;
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
2647
|
+
if (declaration !== null) {
|
|
2648
|
+
return extractDeclarationApiName(declaration) ?? inferJsonFacingName(getDeclarationName(declaration));
|
|
2649
|
+
}
|
|
2650
|
+
diagnostics.push(
|
|
2651
|
+
makeAnalysisDiagnostic(
|
|
2652
|
+
"INVALID_TAG_ARGUMENT",
|
|
2653
|
+
"Discriminator resolution could not derive a JSON-facing discriminator value from the referenced type argument.",
|
|
2654
|
+
provenance
|
|
2655
|
+
)
|
|
2656
|
+
);
|
|
2657
|
+
return null;
|
|
2658
|
+
}
|
|
2659
|
+
function getDeclarationName(node) {
|
|
2660
|
+
if (ts3.isClassDeclaration(node) || ts3.isInterfaceDeclaration(node) || ts3.isTypeAliasDeclaration(node) || ts3.isEnumDeclaration(node)) {
|
|
2661
|
+
return node.name?.text ?? "anonymous";
|
|
2662
|
+
}
|
|
2663
|
+
return "anonymous";
|
|
2664
|
+
}
|
|
2665
|
+
function applyDeclarationDiscriminatorToFields(fields, node, subjectType, checker, file, diagnostics) {
|
|
2666
|
+
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2667
|
+
if (directive === null) {
|
|
2668
|
+
return [...fields];
|
|
2669
|
+
}
|
|
2670
|
+
const discriminatorValue = resolveDiscriminatorValue(
|
|
2671
|
+
getConcreteTypeArgumentForDiscriminator(
|
|
2672
|
+
node,
|
|
2673
|
+
subjectType,
|
|
2674
|
+
checker,
|
|
2675
|
+
directive.typeParameterName
|
|
2676
|
+
),
|
|
2677
|
+
checker,
|
|
2678
|
+
directive.provenance,
|
|
2679
|
+
diagnostics
|
|
2680
|
+
);
|
|
2681
|
+
if (discriminatorValue === null) {
|
|
2682
|
+
return [...fields];
|
|
2683
|
+
}
|
|
2684
|
+
return fields.map(
|
|
2685
|
+
(field) => field.name === directive.fieldName ? {
|
|
2686
|
+
...field,
|
|
2687
|
+
type: {
|
|
2688
|
+
kind: "enum",
|
|
2689
|
+
members: [{ value: discriminatorValue }]
|
|
2690
|
+
}
|
|
2691
|
+
} : field
|
|
2692
|
+
);
|
|
2693
|
+
}
|
|
2694
|
+
function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
|
|
2695
|
+
const renderedArguments = typeArguments.map(
|
|
2696
|
+
(typeArgument) => checker.typeToString(typeArgument).replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "")
|
|
2697
|
+
).filter((value) => value !== "");
|
|
2698
|
+
return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
|
|
2699
|
+
}
|
|
2700
|
+
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
2701
|
+
const typeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
|
|
2702
|
+
if (typeNode === void 0) {
|
|
2703
|
+
return [];
|
|
2704
|
+
}
|
|
2705
|
+
const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);
|
|
2706
|
+
if (!ts3.isTypeReferenceNode(resolvedTypeNode) || resolvedTypeNode.typeArguments === void 0) {
|
|
2707
|
+
return [];
|
|
2708
|
+
}
|
|
2709
|
+
return resolvedTypeNode.typeArguments.map((argumentNode) => {
|
|
2710
|
+
const argumentType = checker.getTypeFromTypeNode(argumentNode);
|
|
2711
|
+
return {
|
|
2712
|
+
tsType: argumentType,
|
|
2713
|
+
typeNode: resolveTypeNode(
|
|
2714
|
+
argumentType,
|
|
2715
|
+
checker,
|
|
2716
|
+
file,
|
|
2717
|
+
typeRegistry,
|
|
2718
|
+
visiting,
|
|
2719
|
+
argumentNode,
|
|
2720
|
+
extensionRegistry,
|
|
2721
|
+
diagnostics
|
|
2722
|
+
)
|
|
2723
|
+
};
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
function applyDiscriminatorToObjectProperties(properties, node, subjectType, checker, file, diagnostics) {
|
|
2727
|
+
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2728
|
+
if (directive === null) {
|
|
2729
|
+
return properties;
|
|
2730
|
+
}
|
|
2731
|
+
const discriminatorValue = resolveDiscriminatorValue(
|
|
2732
|
+
getConcreteTypeArgumentForDiscriminator(
|
|
2733
|
+
node,
|
|
2734
|
+
subjectType,
|
|
2735
|
+
checker,
|
|
2736
|
+
directive.typeParameterName
|
|
2737
|
+
),
|
|
2738
|
+
checker,
|
|
2739
|
+
directive.provenance,
|
|
2740
|
+
diagnostics
|
|
2741
|
+
);
|
|
2742
|
+
if (discriminatorValue === null) {
|
|
2743
|
+
return properties;
|
|
2744
|
+
}
|
|
2745
|
+
return properties.map(
|
|
2746
|
+
(property) => property.name === directive.fieldName ? {
|
|
2747
|
+
...property,
|
|
2748
|
+
type: {
|
|
2749
|
+
kind: "enum",
|
|
2750
|
+
members: [{ value: discriminatorValue }]
|
|
2751
|
+
}
|
|
2752
|
+
} : property
|
|
2753
|
+
);
|
|
2754
|
+
}
|
|
2273
2755
|
function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, extensionRegistry) {
|
|
2274
2756
|
if (!ts3.isIdentifier(prop.name)) {
|
|
2275
2757
|
return null;
|
|
@@ -2558,6 +3040,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2558
3040
|
file,
|
|
2559
3041
|
typeRegistry,
|
|
2560
3042
|
visiting,
|
|
3043
|
+
sourceNode,
|
|
2561
3044
|
extensionRegistry,
|
|
2562
3045
|
diagnostics
|
|
2563
3046
|
);
|
|
@@ -2821,35 +3304,60 @@ function typeNodeContainsReference(type, targetName) {
|
|
|
2821
3304
|
}
|
|
2822
3305
|
}
|
|
2823
3306
|
}
|
|
2824
|
-
function resolveObjectType(type, checker, file, typeRegistry, visiting, extensionRegistry, diagnostics) {
|
|
3307
|
+
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3308
|
+
const collectedDiagnostics = diagnostics ?? [];
|
|
2825
3309
|
const typeName = getNamedTypeName(type);
|
|
2826
3310
|
const namedTypeName = typeName ?? void 0;
|
|
2827
3311
|
const namedDecl = getNamedTypeDeclaration(type);
|
|
2828
|
-
const
|
|
3312
|
+
const referenceTypeArguments = extractReferenceTypeArguments(
|
|
3313
|
+
type,
|
|
3314
|
+
checker,
|
|
3315
|
+
file,
|
|
3316
|
+
typeRegistry,
|
|
3317
|
+
visiting,
|
|
3318
|
+
sourceNode,
|
|
3319
|
+
extensionRegistry,
|
|
3320
|
+
collectedDiagnostics
|
|
3321
|
+
);
|
|
3322
|
+
const instantiatedTypeName = namedTypeName !== void 0 && referenceTypeArguments.length > 0 ? buildInstantiatedReferenceName(
|
|
3323
|
+
namedTypeName,
|
|
3324
|
+
referenceTypeArguments.map((argument) => argument.tsType),
|
|
3325
|
+
checker
|
|
3326
|
+
) : void 0;
|
|
3327
|
+
const registryTypeName = instantiatedTypeName ?? namedTypeName;
|
|
3328
|
+
const shouldRegisterNamedType = registryTypeName !== void 0 && !(registryTypeName === "Record" && namedDecl?.getSourceFile().fileName !== file);
|
|
2829
3329
|
const clearNamedTypeRegistration = () => {
|
|
2830
|
-
if (
|
|
3330
|
+
if (registryTypeName === void 0 || !shouldRegisterNamedType) {
|
|
2831
3331
|
return;
|
|
2832
3332
|
}
|
|
2833
|
-
Reflect.deleteProperty(typeRegistry,
|
|
3333
|
+
Reflect.deleteProperty(typeRegistry, registryTypeName);
|
|
2834
3334
|
};
|
|
2835
3335
|
if (visiting.has(type)) {
|
|
2836
|
-
if (
|
|
2837
|
-
return {
|
|
3336
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3337
|
+
return {
|
|
3338
|
+
kind: "reference",
|
|
3339
|
+
name: registryTypeName,
|
|
3340
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3341
|
+
};
|
|
2838
3342
|
}
|
|
2839
3343
|
return { kind: "object", properties: [], additionalProperties: false };
|
|
2840
3344
|
}
|
|
2841
|
-
if (
|
|
2842
|
-
typeRegistry[
|
|
2843
|
-
name:
|
|
3345
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType && !typeRegistry[registryTypeName]) {
|
|
3346
|
+
typeRegistry[registryTypeName] = {
|
|
3347
|
+
name: registryTypeName,
|
|
2844
3348
|
type: RESOLVING_TYPE_PLACEHOLDER,
|
|
2845
3349
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
2846
3350
|
};
|
|
2847
3351
|
}
|
|
2848
3352
|
visiting.add(type);
|
|
2849
|
-
if (
|
|
2850
|
-
if (typeRegistry[
|
|
3353
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType && typeRegistry[registryTypeName]?.type !== void 0) {
|
|
3354
|
+
if (typeRegistry[registryTypeName].type !== RESOLVING_TYPE_PLACEHOLDER) {
|
|
2851
3355
|
visiting.delete(type);
|
|
2852
|
-
return {
|
|
3356
|
+
return {
|
|
3357
|
+
kind: "reference",
|
|
3358
|
+
name: registryTypeName,
|
|
3359
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3360
|
+
};
|
|
2853
3361
|
}
|
|
2854
3362
|
}
|
|
2855
3363
|
const recordNode = tryResolveRecordType(
|
|
@@ -2859,24 +3367,28 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2859
3367
|
typeRegistry,
|
|
2860
3368
|
visiting,
|
|
2861
3369
|
extensionRegistry,
|
|
2862
|
-
|
|
3370
|
+
collectedDiagnostics
|
|
2863
3371
|
);
|
|
2864
3372
|
if (recordNode) {
|
|
2865
3373
|
visiting.delete(type);
|
|
2866
|
-
if (
|
|
2867
|
-
const isRecursiveRecord = typeNodeContainsReference(recordNode.valueType,
|
|
3374
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3375
|
+
const isRecursiveRecord = typeNodeContainsReference(recordNode.valueType, registryTypeName);
|
|
2868
3376
|
if (!isRecursiveRecord) {
|
|
2869
3377
|
clearNamedTypeRegistration();
|
|
2870
3378
|
return recordNode;
|
|
2871
3379
|
}
|
|
2872
3380
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
2873
|
-
typeRegistry[
|
|
2874
|
-
name:
|
|
3381
|
+
typeRegistry[registryTypeName] = {
|
|
3382
|
+
name: registryTypeName,
|
|
2875
3383
|
type: recordNode,
|
|
2876
3384
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
2877
3385
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
2878
3386
|
};
|
|
2879
|
-
return {
|
|
3387
|
+
return {
|
|
3388
|
+
kind: "reference",
|
|
3389
|
+
name: registryTypeName,
|
|
3390
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3391
|
+
};
|
|
2880
3392
|
}
|
|
2881
3393
|
return recordNode;
|
|
2882
3394
|
}
|
|
@@ -2887,7 +3399,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2887
3399
|
file,
|
|
2888
3400
|
typeRegistry,
|
|
2889
3401
|
visiting,
|
|
2890
|
-
|
|
3402
|
+
collectedDiagnostics,
|
|
2891
3403
|
extensionRegistry
|
|
2892
3404
|
);
|
|
2893
3405
|
for (const prop of type.getProperties()) {
|
|
@@ -2903,7 +3415,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2903
3415
|
visiting,
|
|
2904
3416
|
declaration,
|
|
2905
3417
|
extensionRegistry,
|
|
2906
|
-
|
|
3418
|
+
collectedDiagnostics
|
|
2907
3419
|
);
|
|
2908
3420
|
const fieldNodeInfo = fieldInfoMap?.get(prop.name);
|
|
2909
3421
|
properties.push({
|
|
@@ -2918,18 +3430,29 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2918
3430
|
visiting.delete(type);
|
|
2919
3431
|
const objectNode = {
|
|
2920
3432
|
kind: "object",
|
|
2921
|
-
properties
|
|
3433
|
+
properties: namedDecl !== void 0 && (ts3.isClassDeclaration(namedDecl) || ts3.isInterfaceDeclaration(namedDecl) || ts3.isTypeAliasDeclaration(namedDecl)) ? applyDiscriminatorToObjectProperties(
|
|
3434
|
+
properties,
|
|
3435
|
+
namedDecl,
|
|
3436
|
+
type,
|
|
3437
|
+
checker,
|
|
3438
|
+
file,
|
|
3439
|
+
collectedDiagnostics
|
|
3440
|
+
) : properties,
|
|
2922
3441
|
additionalProperties: true
|
|
2923
3442
|
};
|
|
2924
|
-
if (
|
|
3443
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
2925
3444
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
2926
|
-
typeRegistry[
|
|
2927
|
-
name:
|
|
3445
|
+
typeRegistry[registryTypeName] = {
|
|
3446
|
+
name: registryTypeName,
|
|
2928
3447
|
type: objectNode,
|
|
2929
3448
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
2930
3449
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
2931
3450
|
};
|
|
2932
|
-
return {
|
|
3451
|
+
return {
|
|
3452
|
+
kind: "reference",
|
|
3453
|
+
name: registryTypeName,
|
|
3454
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3455
|
+
};
|
|
2933
3456
|
}
|
|
2934
3457
|
return objectNode;
|
|
2935
3458
|
}
|
|
@@ -3187,11 +3710,12 @@ function detectFormSpecReference(typeNode) {
|
|
|
3187
3710
|
}
|
|
3188
3711
|
return null;
|
|
3189
3712
|
}
|
|
3190
|
-
var ts3, RESOLVING_TYPE_PLACEHOLDER, MAX_ALIAS_CHAIN_DEPTH;
|
|
3713
|
+
var ts3, import_internal2, RESOLVING_TYPE_PLACEHOLDER, MAX_ALIAS_CHAIN_DEPTH;
|
|
3191
3714
|
var init_class_analyzer = __esm({
|
|
3192
3715
|
"src/analyzer/class-analyzer.ts"() {
|
|
3193
3716
|
"use strict";
|
|
3194
3717
|
ts3 = __toESM(require("typescript"), 1);
|
|
3718
|
+
import_internal2 = require("@formspec/analysis/internal");
|
|
3195
3719
|
init_jsdoc_constraints();
|
|
3196
3720
|
init_tsdoc_parser();
|
|
3197
3721
|
RESOLVING_TYPE_PLACEHOLDER = {
|
|
@@ -3204,6 +3728,18 @@ var init_class_analyzer = __esm({
|
|
|
3204
3728
|
});
|
|
3205
3729
|
|
|
3206
3730
|
// src/analyzer/program.ts
|
|
3731
|
+
function createProgramContextFromProgram(program, filePath) {
|
|
3732
|
+
const absolutePath = path.resolve(filePath);
|
|
3733
|
+
const sourceFile = program.getSourceFile(absolutePath) ?? program.getSourceFile(filePath);
|
|
3734
|
+
if (!sourceFile) {
|
|
3735
|
+
throw new Error(`Could not find source file in provided program: ${absolutePath}`);
|
|
3736
|
+
}
|
|
3737
|
+
return {
|
|
3738
|
+
program,
|
|
3739
|
+
checker: program.getTypeChecker(),
|
|
3740
|
+
sourceFile
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3207
3743
|
function createProgramContext(filePath) {
|
|
3208
3744
|
const absolutePath = path.resolve(filePath);
|
|
3209
3745
|
const fileDir = path.dirname(absolutePath);
|
|
@@ -3274,24 +3810,33 @@ function findTypeAliasByName(sourceFile, aliasName) {
|
|
|
3274
3810
|
}
|
|
3275
3811
|
function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry) {
|
|
3276
3812
|
const ctx = createProgramContext(filePath);
|
|
3813
|
+
return analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry);
|
|
3814
|
+
}
|
|
3815
|
+
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry) {
|
|
3816
|
+
const analysisFilePath = path.resolve(filePath);
|
|
3277
3817
|
const classDecl = findClassByName(ctx.sourceFile, typeName);
|
|
3278
3818
|
if (classDecl !== null) {
|
|
3279
|
-
return analyzeClassToIR(classDecl, ctx.checker,
|
|
3819
|
+
return analyzeClassToIR(classDecl, ctx.checker, analysisFilePath, extensionRegistry);
|
|
3280
3820
|
}
|
|
3281
3821
|
const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
|
|
3282
3822
|
if (interfaceDecl !== null) {
|
|
3283
|
-
return analyzeInterfaceToIR(interfaceDecl, ctx.checker,
|
|
3823
|
+
return analyzeInterfaceToIR(interfaceDecl, ctx.checker, analysisFilePath, extensionRegistry);
|
|
3284
3824
|
}
|
|
3285
3825
|
const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
|
|
3286
3826
|
if (typeAlias !== null) {
|
|
3287
|
-
const result = analyzeTypeAliasToIR(
|
|
3827
|
+
const result = analyzeTypeAliasToIR(
|
|
3828
|
+
typeAlias,
|
|
3829
|
+
ctx.checker,
|
|
3830
|
+
analysisFilePath,
|
|
3831
|
+
extensionRegistry
|
|
3832
|
+
);
|
|
3288
3833
|
if (result.ok) {
|
|
3289
3834
|
return result.analysis;
|
|
3290
3835
|
}
|
|
3291
3836
|
throw new Error(result.error);
|
|
3292
3837
|
}
|
|
3293
3838
|
throw new Error(
|
|
3294
|
-
`Type "${typeName}" not found as a class, interface, or type alias in ${
|
|
3839
|
+
`Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`
|
|
3295
3840
|
);
|
|
3296
3841
|
}
|
|
3297
3842
|
var ts4, path;
|
|
@@ -3306,7 +3851,7 @@ var init_program = __esm({
|
|
|
3306
3851
|
|
|
3307
3852
|
// src/validate/constraint-validator.ts
|
|
3308
3853
|
function validateFieldNode(ctx, field) {
|
|
3309
|
-
const analysis = (0,
|
|
3854
|
+
const analysis = (0, import_internal3.analyzeConstraintTargets)(
|
|
3310
3855
|
field.name,
|
|
3311
3856
|
field.type,
|
|
3312
3857
|
field.constraints,
|
|
@@ -3324,7 +3869,7 @@ function validateFieldNode(ctx, field) {
|
|
|
3324
3869
|
}
|
|
3325
3870
|
function validateObjectProperty(ctx, parentName, property) {
|
|
3326
3871
|
const qualifiedName = `${parentName}.${property.name}`;
|
|
3327
|
-
const analysis = (0,
|
|
3872
|
+
const analysis = (0, import_internal3.analyzeConstraintTargets)(
|
|
3328
3873
|
qualifiedName,
|
|
3329
3874
|
property.type,
|
|
3330
3875
|
property.constraints,
|
|
@@ -3375,11 +3920,11 @@ function validateIR(ir, options) {
|
|
|
3375
3920
|
valid: ctx.diagnostics.every((diagnostic) => diagnostic.severity !== "error")
|
|
3376
3921
|
};
|
|
3377
3922
|
}
|
|
3378
|
-
var
|
|
3923
|
+
var import_internal3;
|
|
3379
3924
|
var init_constraint_validator = __esm({
|
|
3380
3925
|
"src/validate/constraint-validator.ts"() {
|
|
3381
3926
|
"use strict";
|
|
3382
|
-
|
|
3927
|
+
import_internal3 = require("@formspec/analysis/internal");
|
|
3383
3928
|
}
|
|
3384
3929
|
});
|
|
3385
3930
|
|
|
@@ -3448,16 +3993,34 @@ function generateSchemasFromClass(options) {
|
|
|
3448
3993
|
);
|
|
3449
3994
|
}
|
|
3450
3995
|
function generateSchemas(options) {
|
|
3451
|
-
const
|
|
3996
|
+
const ctx = createProgramContext(options.filePath);
|
|
3997
|
+
return generateSchemasFromProgram({
|
|
3998
|
+
...options,
|
|
3999
|
+
program: ctx.program
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
function generateSchemasFromProgram(options) {
|
|
4003
|
+
const ctx = createProgramContextFromProgram(options.program, options.filePath);
|
|
4004
|
+
const analysis = analyzeNamedTypeToIRFromProgramContext(
|
|
4005
|
+
ctx,
|
|
3452
4006
|
options.filePath,
|
|
3453
4007
|
options.typeName,
|
|
3454
4008
|
options.extensionRegistry
|
|
3455
4009
|
);
|
|
3456
|
-
return generateClassSchemas(
|
|
4010
|
+
return generateClassSchemas(
|
|
4011
|
+
analysis,
|
|
4012
|
+
{ file: options.filePath },
|
|
4013
|
+
{
|
|
4014
|
+
extensionRegistry: options.extensionRegistry,
|
|
4015
|
+
vendorPrefix: options.vendorPrefix
|
|
4016
|
+
}
|
|
4017
|
+
);
|
|
3457
4018
|
}
|
|
4019
|
+
var ts5;
|
|
3458
4020
|
var init_class_schema = __esm({
|
|
3459
4021
|
"src/generators/class-schema.ts"() {
|
|
3460
4022
|
"use strict";
|
|
4023
|
+
ts5 = require("typescript");
|
|
3461
4024
|
init_program();
|
|
3462
4025
|
init_class_analyzer();
|
|
3463
4026
|
init_canonicalize();
|
|
@@ -3661,7 +4224,10 @@ __export(index_exports, {
|
|
|
3661
4224
|
generateJsonSchema: () => generateJsonSchema,
|
|
3662
4225
|
generateSchemas: () => generateSchemas,
|
|
3663
4226
|
generateSchemasFromClass: () => generateSchemasFromClass,
|
|
4227
|
+
generateSchemasFromProgram: () => generateSchemasFromProgram,
|
|
3664
4228
|
generateUiSchema: () => generateUiSchema,
|
|
4229
|
+
jsonSchema7Schema: () => jsonSchema7Schema,
|
|
4230
|
+
uiSchemaSchema: () => uiSchema,
|
|
3665
4231
|
writeSchemas: () => writeSchemas
|
|
3666
4232
|
});
|
|
3667
4233
|
function buildFormSchemas(form, options) {
|
|
@@ -3693,6 +4259,8 @@ var init_index = __esm({
|
|
|
3693
4259
|
fs = __toESM(require("fs"), 1);
|
|
3694
4260
|
path2 = __toESM(require("path"), 1);
|
|
3695
4261
|
init_extensions();
|
|
4262
|
+
init_schema2();
|
|
4263
|
+
init_schema();
|
|
3696
4264
|
init_generator();
|
|
3697
4265
|
init_generator2();
|
|
3698
4266
|
init_class_schema();
|