@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/index.js
CHANGED
|
@@ -1141,12 +1141,80 @@ function createExtensionRegistry(extensions) {
|
|
|
1141
1141
|
};
|
|
1142
1142
|
}
|
|
1143
1143
|
|
|
1144
|
+
// src/json-schema/schema.ts
|
|
1145
|
+
import { z as z3 } from "zod";
|
|
1146
|
+
var jsonSchemaTypeSchema = z3.enum([
|
|
1147
|
+
"string",
|
|
1148
|
+
"number",
|
|
1149
|
+
"integer",
|
|
1150
|
+
"boolean",
|
|
1151
|
+
"object",
|
|
1152
|
+
"array",
|
|
1153
|
+
"null"
|
|
1154
|
+
]);
|
|
1155
|
+
var jsonSchema7Schema = z3.lazy(
|
|
1156
|
+
() => z3.object({
|
|
1157
|
+
$schema: z3.string().optional(),
|
|
1158
|
+
$id: z3.string().optional(),
|
|
1159
|
+
$ref: z3.string().optional(),
|
|
1160
|
+
// Metadata
|
|
1161
|
+
title: z3.string().optional(),
|
|
1162
|
+
description: z3.string().optional(),
|
|
1163
|
+
deprecated: z3.boolean().optional(),
|
|
1164
|
+
// Type
|
|
1165
|
+
type: z3.union([jsonSchemaTypeSchema, z3.array(jsonSchemaTypeSchema)]).optional(),
|
|
1166
|
+
// String validation
|
|
1167
|
+
minLength: z3.number().optional(),
|
|
1168
|
+
maxLength: z3.number().optional(),
|
|
1169
|
+
pattern: z3.string().optional(),
|
|
1170
|
+
// Number validation
|
|
1171
|
+
minimum: z3.number().optional(),
|
|
1172
|
+
maximum: z3.number().optional(),
|
|
1173
|
+
exclusiveMinimum: z3.number().optional(),
|
|
1174
|
+
exclusiveMaximum: z3.number().optional(),
|
|
1175
|
+
// Enum
|
|
1176
|
+
enum: z3.array(z3.union([z3.string(), z3.number(), z3.boolean(), z3.null()])).readonly().optional(),
|
|
1177
|
+
const: z3.union([z3.string(), z3.number(), z3.boolean(), z3.null()]).optional(),
|
|
1178
|
+
// Object
|
|
1179
|
+
properties: z3.record(z3.string(), jsonSchema7Schema).optional(),
|
|
1180
|
+
required: z3.array(z3.string()).optional(),
|
|
1181
|
+
additionalProperties: z3.union([z3.boolean(), jsonSchema7Schema]).optional(),
|
|
1182
|
+
// Array
|
|
1183
|
+
items: z3.union([jsonSchema7Schema, z3.array(jsonSchema7Schema)]).optional(),
|
|
1184
|
+
minItems: z3.number().optional(),
|
|
1185
|
+
maxItems: z3.number().optional(),
|
|
1186
|
+
// Composition
|
|
1187
|
+
allOf: z3.array(jsonSchema7Schema).optional(),
|
|
1188
|
+
anyOf: z3.array(jsonSchema7Schema).optional(),
|
|
1189
|
+
oneOf: z3.array(jsonSchema7Schema).optional(),
|
|
1190
|
+
not: jsonSchema7Schema.optional(),
|
|
1191
|
+
// Conditional
|
|
1192
|
+
if: jsonSchema7Schema.optional(),
|
|
1193
|
+
then: jsonSchema7Schema.optional(),
|
|
1194
|
+
else: jsonSchema7Schema.optional(),
|
|
1195
|
+
// Format
|
|
1196
|
+
format: z3.string().optional(),
|
|
1197
|
+
// Default
|
|
1198
|
+
default: z3.unknown().optional(),
|
|
1199
|
+
// FormSpec extensions
|
|
1200
|
+
"x-formspec-source": z3.string().optional(),
|
|
1201
|
+
"x-formspec-params": z3.array(z3.string()).readonly().optional(),
|
|
1202
|
+
"x-formspec-schemaSource": z3.string().optional()
|
|
1203
|
+
}).passthrough()
|
|
1204
|
+
);
|
|
1205
|
+
|
|
1206
|
+
// src/generators/class-schema.ts
|
|
1207
|
+
import "typescript";
|
|
1208
|
+
|
|
1144
1209
|
// src/analyzer/program.ts
|
|
1145
1210
|
import * as ts4 from "typescript";
|
|
1146
1211
|
import * as path from "path";
|
|
1147
1212
|
|
|
1148
1213
|
// src/analyzer/class-analyzer.ts
|
|
1149
1214
|
import * as ts3 from "typescript";
|
|
1215
|
+
import {
|
|
1216
|
+
parseCommentBlock as parseCommentBlock2
|
|
1217
|
+
} from "@formspec/analysis/internal";
|
|
1150
1218
|
|
|
1151
1219
|
// src/analyzer/jsdoc-constraints.ts
|
|
1152
1220
|
import * as ts2 from "typescript";
|
|
@@ -2094,9 +2162,17 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2094
2162
|
}
|
|
2095
2163
|
}
|
|
2096
2164
|
}
|
|
2165
|
+
const specializedFields = applyDeclarationDiscriminatorToFields(
|
|
2166
|
+
fields,
|
|
2167
|
+
classDecl,
|
|
2168
|
+
classType,
|
|
2169
|
+
checker,
|
|
2170
|
+
file,
|
|
2171
|
+
diagnostics
|
|
2172
|
+
);
|
|
2097
2173
|
return {
|
|
2098
2174
|
name,
|
|
2099
|
-
fields,
|
|
2175
|
+
fields: specializedFields,
|
|
2100
2176
|
fieldLayouts,
|
|
2101
2177
|
typeRegistry,
|
|
2102
2178
|
...annotations.length > 0 && { annotations },
|
|
@@ -2136,10 +2212,18 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2136
2212
|
}
|
|
2137
2213
|
}
|
|
2138
2214
|
}
|
|
2139
|
-
const
|
|
2215
|
+
const specializedFields = applyDeclarationDiscriminatorToFields(
|
|
2216
|
+
fields,
|
|
2217
|
+
interfaceDecl,
|
|
2218
|
+
interfaceType,
|
|
2219
|
+
checker,
|
|
2220
|
+
file,
|
|
2221
|
+
diagnostics
|
|
2222
|
+
);
|
|
2223
|
+
const fieldLayouts = specializedFields.map(() => ({}));
|
|
2140
2224
|
return {
|
|
2141
2225
|
name,
|
|
2142
|
-
fields,
|
|
2226
|
+
fields: specializedFields,
|
|
2143
2227
|
fieldLayouts,
|
|
2144
2228
|
typeRegistry,
|
|
2145
2229
|
...annotations.length > 0 && { annotations },
|
|
@@ -2188,12 +2272,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2188
2272
|
}
|
|
2189
2273
|
}
|
|
2190
2274
|
}
|
|
2275
|
+
const specializedFields = applyDeclarationDiscriminatorToFields(
|
|
2276
|
+
fields,
|
|
2277
|
+
typeAlias,
|
|
2278
|
+
aliasType,
|
|
2279
|
+
checker,
|
|
2280
|
+
file,
|
|
2281
|
+
diagnostics
|
|
2282
|
+
);
|
|
2191
2283
|
return {
|
|
2192
2284
|
ok: true,
|
|
2193
2285
|
analysis: {
|
|
2194
2286
|
name,
|
|
2195
|
-
fields,
|
|
2196
|
-
fieldLayouts:
|
|
2287
|
+
fields: specializedFields,
|
|
2288
|
+
fieldLayouts: specializedFields.map(() => ({})),
|
|
2197
2289
|
typeRegistry,
|
|
2198
2290
|
...annotations.length > 0 && { annotations },
|
|
2199
2291
|
...diagnostics.length > 0 && { diagnostics },
|
|
@@ -2202,6 +2294,396 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2202
2294
|
}
|
|
2203
2295
|
};
|
|
2204
2296
|
}
|
|
2297
|
+
function makeAnalysisDiagnostic(code, message, primaryLocation, relatedLocations = []) {
|
|
2298
|
+
return {
|
|
2299
|
+
code,
|
|
2300
|
+
message,
|
|
2301
|
+
severity: "error",
|
|
2302
|
+
primaryLocation,
|
|
2303
|
+
relatedLocations
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
function getLeadingParsedTags(node) {
|
|
2307
|
+
const sourceFile = node.getSourceFile();
|
|
2308
|
+
const sourceText = sourceFile.getFullText();
|
|
2309
|
+
const commentRanges = ts3.getLeadingCommentRanges(sourceText, node.getFullStart());
|
|
2310
|
+
if (commentRanges === void 0) {
|
|
2311
|
+
return [];
|
|
2312
|
+
}
|
|
2313
|
+
const parsedTags = [];
|
|
2314
|
+
for (const range of commentRanges) {
|
|
2315
|
+
if (range.kind !== ts3.SyntaxKind.MultiLineCommentTrivia) {
|
|
2316
|
+
continue;
|
|
2317
|
+
}
|
|
2318
|
+
const commentText = sourceText.slice(range.pos, range.end);
|
|
2319
|
+
if (!commentText.startsWith("/**")) {
|
|
2320
|
+
continue;
|
|
2321
|
+
}
|
|
2322
|
+
parsedTags.push(...parseCommentBlock2(commentText, { offset: range.pos }).tags);
|
|
2323
|
+
}
|
|
2324
|
+
return parsedTags;
|
|
2325
|
+
}
|
|
2326
|
+
function findDiscriminatorProperty(node, fieldName) {
|
|
2327
|
+
if (ts3.isClassDeclaration(node)) {
|
|
2328
|
+
for (const member of node.members) {
|
|
2329
|
+
if (ts3.isPropertyDeclaration(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2330
|
+
return member;
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
return null;
|
|
2334
|
+
}
|
|
2335
|
+
if (ts3.isInterfaceDeclaration(node)) {
|
|
2336
|
+
for (const member of node.members) {
|
|
2337
|
+
if (ts3.isPropertySignature(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2338
|
+
return member;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
return null;
|
|
2342
|
+
}
|
|
2343
|
+
if (ts3.isTypeLiteralNode(node.type)) {
|
|
2344
|
+
for (const member of node.type.members) {
|
|
2345
|
+
if (ts3.isPropertySignature(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2346
|
+
return member;
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
return null;
|
|
2351
|
+
}
|
|
2352
|
+
function isLocalTypeParameterName(node, typeParameterName) {
|
|
2353
|
+
return node.typeParameters?.some((typeParameter) => typeParameter.name.text === typeParameterName) ?? false;
|
|
2354
|
+
}
|
|
2355
|
+
function isNullishSemanticType(type) {
|
|
2356
|
+
if (type.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined | ts3.TypeFlags.Void | ts3.TypeFlags.Unknown | ts3.TypeFlags.Any)) {
|
|
2357
|
+
return true;
|
|
2358
|
+
}
|
|
2359
|
+
return type.isUnion() && type.types.some((member) => isNullishSemanticType(member));
|
|
2360
|
+
}
|
|
2361
|
+
function isStringLikeSemanticType(type) {
|
|
2362
|
+
if (type.flags & ts3.TypeFlags.StringLike) {
|
|
2363
|
+
return true;
|
|
2364
|
+
}
|
|
2365
|
+
if (type.isUnion()) {
|
|
2366
|
+
return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member));
|
|
2367
|
+
}
|
|
2368
|
+
return false;
|
|
2369
|
+
}
|
|
2370
|
+
function extractDiscriminatorDirective(node, file, diagnostics) {
|
|
2371
|
+
const discriminatorTags = getLeadingParsedTags(node).filter(
|
|
2372
|
+
(tag) => tag.normalizedTagName === "discriminator"
|
|
2373
|
+
);
|
|
2374
|
+
if (discriminatorTags.length === 0) {
|
|
2375
|
+
return null;
|
|
2376
|
+
}
|
|
2377
|
+
const [firstTag, ...duplicateTags] = discriminatorTags;
|
|
2378
|
+
for (const _duplicateTag of duplicateTags) {
|
|
2379
|
+
diagnostics.push(
|
|
2380
|
+
makeAnalysisDiagnostic(
|
|
2381
|
+
"DUPLICATE_TAG",
|
|
2382
|
+
'Duplicate "@discriminator" tag. Only one discriminator declaration is allowed per declaration.',
|
|
2383
|
+
provenanceForNode(node, file)
|
|
2384
|
+
)
|
|
2385
|
+
);
|
|
2386
|
+
}
|
|
2387
|
+
if (firstTag === void 0) {
|
|
2388
|
+
return null;
|
|
2389
|
+
}
|
|
2390
|
+
const firstTarget = firstTag.target;
|
|
2391
|
+
if (firstTarget?.path === null || firstTarget?.valid !== true) {
|
|
2392
|
+
diagnostics.push(
|
|
2393
|
+
makeAnalysisDiagnostic(
|
|
2394
|
+
"INVALID_TAG_ARGUMENT",
|
|
2395
|
+
'Tag "@discriminator" requires a direct path target like ":kind".',
|
|
2396
|
+
provenanceForNode(node, file)
|
|
2397
|
+
)
|
|
2398
|
+
);
|
|
2399
|
+
return null;
|
|
2400
|
+
}
|
|
2401
|
+
if (firstTarget.path.segments.length !== 1) {
|
|
2402
|
+
diagnostics.push(
|
|
2403
|
+
makeAnalysisDiagnostic(
|
|
2404
|
+
"INVALID_TAG_ARGUMENT",
|
|
2405
|
+
'Tag "@discriminator" only supports direct property targets in v1; nested paths are out of scope.',
|
|
2406
|
+
provenanceForNode(node, file)
|
|
2407
|
+
)
|
|
2408
|
+
);
|
|
2409
|
+
return null;
|
|
2410
|
+
}
|
|
2411
|
+
const typeParameterName = firstTag.argumentText.trim();
|
|
2412
|
+
if (!/^[A-Za-z_$][\w$]*$/u.test(typeParameterName)) {
|
|
2413
|
+
diagnostics.push(
|
|
2414
|
+
makeAnalysisDiagnostic(
|
|
2415
|
+
"INVALID_TAG_ARGUMENT",
|
|
2416
|
+
'Tag "@discriminator" requires a local type parameter name as its source operand.',
|
|
2417
|
+
provenanceForNode(node, file)
|
|
2418
|
+
)
|
|
2419
|
+
);
|
|
2420
|
+
return null;
|
|
2421
|
+
}
|
|
2422
|
+
return {
|
|
2423
|
+
fieldName: firstTarget.path.segments[0] ?? firstTarget.rawText,
|
|
2424
|
+
typeParameterName,
|
|
2425
|
+
provenance: provenanceForNode(node, file)
|
|
2426
|
+
};
|
|
2427
|
+
}
|
|
2428
|
+
function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
2429
|
+
const directive = extractDiscriminatorDirective(node, file, diagnostics);
|
|
2430
|
+
if (directive === null) {
|
|
2431
|
+
return null;
|
|
2432
|
+
}
|
|
2433
|
+
if (!isLocalTypeParameterName(node, directive.typeParameterName)) {
|
|
2434
|
+
diagnostics.push(
|
|
2435
|
+
makeAnalysisDiagnostic(
|
|
2436
|
+
"INVALID_TAG_ARGUMENT",
|
|
2437
|
+
`Tag "@discriminator" references "${directive.typeParameterName}", but the source operand must be a type parameter declared on the same declaration.`,
|
|
2438
|
+
directive.provenance
|
|
2439
|
+
)
|
|
2440
|
+
);
|
|
2441
|
+
return null;
|
|
2442
|
+
}
|
|
2443
|
+
const propertyDecl = findDiscriminatorProperty(node, directive.fieldName);
|
|
2444
|
+
if (propertyDecl === null) {
|
|
2445
|
+
diagnostics.push(
|
|
2446
|
+
makeAnalysisDiagnostic(
|
|
2447
|
+
"UNKNOWN_PATH_TARGET",
|
|
2448
|
+
`Tag "@discriminator" targets "${directive.fieldName}", but no direct property with that name exists on this declaration.`,
|
|
2449
|
+
directive.provenance
|
|
2450
|
+
)
|
|
2451
|
+
);
|
|
2452
|
+
return null;
|
|
2453
|
+
}
|
|
2454
|
+
if (propertyDecl.questionToken !== void 0) {
|
|
2455
|
+
diagnostics.push(
|
|
2456
|
+
makeAnalysisDiagnostic(
|
|
2457
|
+
"TYPE_MISMATCH",
|
|
2458
|
+
`Discriminator field "${directive.fieldName}" must be required; optional discriminator fields are not supported.`,
|
|
2459
|
+
directive.provenance,
|
|
2460
|
+
[provenanceForNode(propertyDecl, file)]
|
|
2461
|
+
)
|
|
2462
|
+
);
|
|
2463
|
+
return null;
|
|
2464
|
+
}
|
|
2465
|
+
const propertyType = checker.getTypeAtLocation(propertyDecl);
|
|
2466
|
+
if (isNullishSemanticType(propertyType)) {
|
|
2467
|
+
diagnostics.push(
|
|
2468
|
+
makeAnalysisDiagnostic(
|
|
2469
|
+
"TYPE_MISMATCH",
|
|
2470
|
+
`Discriminator field "${directive.fieldName}" must not be nullable.`,
|
|
2471
|
+
directive.provenance,
|
|
2472
|
+
[provenanceForNode(propertyDecl, file)]
|
|
2473
|
+
)
|
|
2474
|
+
);
|
|
2475
|
+
return null;
|
|
2476
|
+
}
|
|
2477
|
+
if (!isStringLikeSemanticType(propertyType)) {
|
|
2478
|
+
diagnostics.push(
|
|
2479
|
+
makeAnalysisDiagnostic(
|
|
2480
|
+
"TYPE_MISMATCH",
|
|
2481
|
+
`Discriminator field "${directive.fieldName}" must be string-like.`,
|
|
2482
|
+
directive.provenance,
|
|
2483
|
+
[provenanceForNode(propertyDecl, file)]
|
|
2484
|
+
)
|
|
2485
|
+
);
|
|
2486
|
+
return null;
|
|
2487
|
+
}
|
|
2488
|
+
return directive;
|
|
2489
|
+
}
|
|
2490
|
+
function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typeParameterName) {
|
|
2491
|
+
const typeParameterIndex = node.typeParameters?.findIndex(
|
|
2492
|
+
(typeParameter) => typeParameter.name.text === typeParameterName
|
|
2493
|
+
) ?? -1;
|
|
2494
|
+
if (typeParameterIndex < 0) {
|
|
2495
|
+
return null;
|
|
2496
|
+
}
|
|
2497
|
+
const referenceTypeArguments = (isTypeReference(subjectType) ? subjectType.typeArguments : void 0) ?? subjectType.aliasTypeArguments;
|
|
2498
|
+
if (referenceTypeArguments?.[typeParameterIndex] !== void 0) {
|
|
2499
|
+
return referenceTypeArguments[typeParameterIndex] ?? null;
|
|
2500
|
+
}
|
|
2501
|
+
const localTypeParameter = node.typeParameters?.[typeParameterIndex];
|
|
2502
|
+
return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
|
|
2503
|
+
}
|
|
2504
|
+
function extractDeclarationApiName(node) {
|
|
2505
|
+
for (const tag of getLeadingParsedTags(node)) {
|
|
2506
|
+
if (tag.normalizedTagName !== "apiName") {
|
|
2507
|
+
continue;
|
|
2508
|
+
}
|
|
2509
|
+
if (tag.target === null && tag.argumentText.trim() !== "") {
|
|
2510
|
+
return tag.argumentText.trim();
|
|
2511
|
+
}
|
|
2512
|
+
if (tag.target?.kind === "variant" && tag.target.rawText === "singular") {
|
|
2513
|
+
const value = tag.argumentText.trim();
|
|
2514
|
+
if (value !== "") {
|
|
2515
|
+
return value;
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
return null;
|
|
2520
|
+
}
|
|
2521
|
+
function inferJsonFacingName(name) {
|
|
2522
|
+
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();
|
|
2523
|
+
}
|
|
2524
|
+
function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
2525
|
+
if (seen.has(type)) {
|
|
2526
|
+
return null;
|
|
2527
|
+
}
|
|
2528
|
+
seen.add(type);
|
|
2529
|
+
const symbol = type.aliasSymbol ?? type.getSymbol();
|
|
2530
|
+
if (symbol !== void 0) {
|
|
2531
|
+
const aliased = symbol.flags & ts3.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : void 0;
|
|
2532
|
+
const targetSymbol = aliased ?? symbol;
|
|
2533
|
+
const declaration = targetSymbol.declarations?.find(
|
|
2534
|
+
(candidate) => ts3.isClassDeclaration(candidate) || ts3.isInterfaceDeclaration(candidate) || ts3.isTypeAliasDeclaration(candidate) || ts3.isEnumDeclaration(candidate)
|
|
2535
|
+
);
|
|
2536
|
+
if (declaration !== void 0) {
|
|
2537
|
+
if (ts3.isTypeAliasDeclaration(declaration) && ts3.isTypeReferenceNode(declaration.type) && checker.getTypeFromTypeNode(declaration.type) !== type) {
|
|
2538
|
+
return resolveNamedDiscriminatorDeclaration(
|
|
2539
|
+
checker.getTypeFromTypeNode(declaration.type),
|
|
2540
|
+
checker,
|
|
2541
|
+
seen
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
return declaration;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
return null;
|
|
2548
|
+
}
|
|
2549
|
+
function resolveDiscriminatorValue(boundType, checker, provenance, diagnostics) {
|
|
2550
|
+
if (boundType === null) {
|
|
2551
|
+
diagnostics.push(
|
|
2552
|
+
makeAnalysisDiagnostic(
|
|
2553
|
+
"INVALID_TAG_ARGUMENT",
|
|
2554
|
+
"Discriminator resolution failed because no concrete type argument is available for the referenced type parameter.",
|
|
2555
|
+
provenance
|
|
2556
|
+
)
|
|
2557
|
+
);
|
|
2558
|
+
return null;
|
|
2559
|
+
}
|
|
2560
|
+
if (boundType.isStringLiteral()) {
|
|
2561
|
+
return boundType.value;
|
|
2562
|
+
}
|
|
2563
|
+
if (boundType.isUnion()) {
|
|
2564
|
+
const nonNullMembers = boundType.types.filter(
|
|
2565
|
+
(member) => !(member.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined))
|
|
2566
|
+
);
|
|
2567
|
+
if (nonNullMembers.every((member) => member.isStringLiteral())) {
|
|
2568
|
+
diagnostics.push(
|
|
2569
|
+
makeAnalysisDiagnostic(
|
|
2570
|
+
"INVALID_TAG_ARGUMENT",
|
|
2571
|
+
"Discriminator resolution for unions of string literals is out of scope for v1.",
|
|
2572
|
+
provenance
|
|
2573
|
+
)
|
|
2574
|
+
);
|
|
2575
|
+
return null;
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
2579
|
+
if (declaration !== null) {
|
|
2580
|
+
return extractDeclarationApiName(declaration) ?? inferJsonFacingName(getDeclarationName(declaration));
|
|
2581
|
+
}
|
|
2582
|
+
diagnostics.push(
|
|
2583
|
+
makeAnalysisDiagnostic(
|
|
2584
|
+
"INVALID_TAG_ARGUMENT",
|
|
2585
|
+
"Discriminator resolution could not derive a JSON-facing discriminator value from the referenced type argument.",
|
|
2586
|
+
provenance
|
|
2587
|
+
)
|
|
2588
|
+
);
|
|
2589
|
+
return null;
|
|
2590
|
+
}
|
|
2591
|
+
function getDeclarationName(node) {
|
|
2592
|
+
if (ts3.isClassDeclaration(node) || ts3.isInterfaceDeclaration(node) || ts3.isTypeAliasDeclaration(node) || ts3.isEnumDeclaration(node)) {
|
|
2593
|
+
return node.name?.text ?? "anonymous";
|
|
2594
|
+
}
|
|
2595
|
+
return "anonymous";
|
|
2596
|
+
}
|
|
2597
|
+
function applyDeclarationDiscriminatorToFields(fields, node, subjectType, checker, file, diagnostics) {
|
|
2598
|
+
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2599
|
+
if (directive === null) {
|
|
2600
|
+
return [...fields];
|
|
2601
|
+
}
|
|
2602
|
+
const discriminatorValue = resolveDiscriminatorValue(
|
|
2603
|
+
getConcreteTypeArgumentForDiscriminator(
|
|
2604
|
+
node,
|
|
2605
|
+
subjectType,
|
|
2606
|
+
checker,
|
|
2607
|
+
directive.typeParameterName
|
|
2608
|
+
),
|
|
2609
|
+
checker,
|
|
2610
|
+
directive.provenance,
|
|
2611
|
+
diagnostics
|
|
2612
|
+
);
|
|
2613
|
+
if (discriminatorValue === null) {
|
|
2614
|
+
return [...fields];
|
|
2615
|
+
}
|
|
2616
|
+
return fields.map(
|
|
2617
|
+
(field) => field.name === directive.fieldName ? {
|
|
2618
|
+
...field,
|
|
2619
|
+
type: {
|
|
2620
|
+
kind: "enum",
|
|
2621
|
+
members: [{ value: discriminatorValue }]
|
|
2622
|
+
}
|
|
2623
|
+
} : field
|
|
2624
|
+
);
|
|
2625
|
+
}
|
|
2626
|
+
function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
|
|
2627
|
+
const renderedArguments = typeArguments.map(
|
|
2628
|
+
(typeArgument) => checker.typeToString(typeArgument).replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "")
|
|
2629
|
+
).filter((value) => value !== "");
|
|
2630
|
+
return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
|
|
2631
|
+
}
|
|
2632
|
+
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
2633
|
+
const typeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
|
|
2634
|
+
if (typeNode === void 0) {
|
|
2635
|
+
return [];
|
|
2636
|
+
}
|
|
2637
|
+
const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);
|
|
2638
|
+
if (!ts3.isTypeReferenceNode(resolvedTypeNode) || resolvedTypeNode.typeArguments === void 0) {
|
|
2639
|
+
return [];
|
|
2640
|
+
}
|
|
2641
|
+
return resolvedTypeNode.typeArguments.map((argumentNode) => {
|
|
2642
|
+
const argumentType = checker.getTypeFromTypeNode(argumentNode);
|
|
2643
|
+
return {
|
|
2644
|
+
tsType: argumentType,
|
|
2645
|
+
typeNode: resolveTypeNode(
|
|
2646
|
+
argumentType,
|
|
2647
|
+
checker,
|
|
2648
|
+
file,
|
|
2649
|
+
typeRegistry,
|
|
2650
|
+
visiting,
|
|
2651
|
+
argumentNode,
|
|
2652
|
+
extensionRegistry,
|
|
2653
|
+
diagnostics
|
|
2654
|
+
)
|
|
2655
|
+
};
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
function applyDiscriminatorToObjectProperties(properties, node, subjectType, checker, file, diagnostics) {
|
|
2659
|
+
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2660
|
+
if (directive === null) {
|
|
2661
|
+
return properties;
|
|
2662
|
+
}
|
|
2663
|
+
const discriminatorValue = resolveDiscriminatorValue(
|
|
2664
|
+
getConcreteTypeArgumentForDiscriminator(
|
|
2665
|
+
node,
|
|
2666
|
+
subjectType,
|
|
2667
|
+
checker,
|
|
2668
|
+
directive.typeParameterName
|
|
2669
|
+
),
|
|
2670
|
+
checker,
|
|
2671
|
+
directive.provenance,
|
|
2672
|
+
diagnostics
|
|
2673
|
+
);
|
|
2674
|
+
if (discriminatorValue === null) {
|
|
2675
|
+
return properties;
|
|
2676
|
+
}
|
|
2677
|
+
return properties.map(
|
|
2678
|
+
(property) => property.name === directive.fieldName ? {
|
|
2679
|
+
...property,
|
|
2680
|
+
type: {
|
|
2681
|
+
kind: "enum",
|
|
2682
|
+
members: [{ value: discriminatorValue }]
|
|
2683
|
+
}
|
|
2684
|
+
} : property
|
|
2685
|
+
);
|
|
2686
|
+
}
|
|
2205
2687
|
function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, extensionRegistry) {
|
|
2206
2688
|
if (!ts3.isIdentifier(prop.name)) {
|
|
2207
2689
|
return null;
|
|
@@ -2490,6 +2972,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2490
2972
|
file,
|
|
2491
2973
|
typeRegistry,
|
|
2492
2974
|
visiting,
|
|
2975
|
+
sourceNode,
|
|
2493
2976
|
extensionRegistry,
|
|
2494
2977
|
diagnostics
|
|
2495
2978
|
);
|
|
@@ -2753,35 +3236,60 @@ function typeNodeContainsReference(type, targetName) {
|
|
|
2753
3236
|
}
|
|
2754
3237
|
}
|
|
2755
3238
|
}
|
|
2756
|
-
function resolveObjectType(type, checker, file, typeRegistry, visiting, extensionRegistry, diagnostics) {
|
|
3239
|
+
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3240
|
+
const collectedDiagnostics = diagnostics ?? [];
|
|
2757
3241
|
const typeName = getNamedTypeName(type);
|
|
2758
3242
|
const namedTypeName = typeName ?? void 0;
|
|
2759
3243
|
const namedDecl = getNamedTypeDeclaration(type);
|
|
2760
|
-
const
|
|
3244
|
+
const referenceTypeArguments = extractReferenceTypeArguments(
|
|
3245
|
+
type,
|
|
3246
|
+
checker,
|
|
3247
|
+
file,
|
|
3248
|
+
typeRegistry,
|
|
3249
|
+
visiting,
|
|
3250
|
+
sourceNode,
|
|
3251
|
+
extensionRegistry,
|
|
3252
|
+
collectedDiagnostics
|
|
3253
|
+
);
|
|
3254
|
+
const instantiatedTypeName = namedTypeName !== void 0 && referenceTypeArguments.length > 0 ? buildInstantiatedReferenceName(
|
|
3255
|
+
namedTypeName,
|
|
3256
|
+
referenceTypeArguments.map((argument) => argument.tsType),
|
|
3257
|
+
checker
|
|
3258
|
+
) : void 0;
|
|
3259
|
+
const registryTypeName = instantiatedTypeName ?? namedTypeName;
|
|
3260
|
+
const shouldRegisterNamedType = registryTypeName !== void 0 && !(registryTypeName === "Record" && namedDecl?.getSourceFile().fileName !== file);
|
|
2761
3261
|
const clearNamedTypeRegistration = () => {
|
|
2762
|
-
if (
|
|
3262
|
+
if (registryTypeName === void 0 || !shouldRegisterNamedType) {
|
|
2763
3263
|
return;
|
|
2764
3264
|
}
|
|
2765
|
-
Reflect.deleteProperty(typeRegistry,
|
|
3265
|
+
Reflect.deleteProperty(typeRegistry, registryTypeName);
|
|
2766
3266
|
};
|
|
2767
3267
|
if (visiting.has(type)) {
|
|
2768
|
-
if (
|
|
2769
|
-
return {
|
|
3268
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3269
|
+
return {
|
|
3270
|
+
kind: "reference",
|
|
3271
|
+
name: registryTypeName,
|
|
3272
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3273
|
+
};
|
|
2770
3274
|
}
|
|
2771
3275
|
return { kind: "object", properties: [], additionalProperties: false };
|
|
2772
3276
|
}
|
|
2773
|
-
if (
|
|
2774
|
-
typeRegistry[
|
|
2775
|
-
name:
|
|
3277
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType && !typeRegistry[registryTypeName]) {
|
|
3278
|
+
typeRegistry[registryTypeName] = {
|
|
3279
|
+
name: registryTypeName,
|
|
2776
3280
|
type: RESOLVING_TYPE_PLACEHOLDER,
|
|
2777
3281
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
2778
3282
|
};
|
|
2779
3283
|
}
|
|
2780
3284
|
visiting.add(type);
|
|
2781
|
-
if (
|
|
2782
|
-
if (typeRegistry[
|
|
3285
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType && typeRegistry[registryTypeName]?.type !== void 0) {
|
|
3286
|
+
if (typeRegistry[registryTypeName].type !== RESOLVING_TYPE_PLACEHOLDER) {
|
|
2783
3287
|
visiting.delete(type);
|
|
2784
|
-
return {
|
|
3288
|
+
return {
|
|
3289
|
+
kind: "reference",
|
|
3290
|
+
name: registryTypeName,
|
|
3291
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3292
|
+
};
|
|
2785
3293
|
}
|
|
2786
3294
|
}
|
|
2787
3295
|
const recordNode = tryResolveRecordType(
|
|
@@ -2791,24 +3299,28 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2791
3299
|
typeRegistry,
|
|
2792
3300
|
visiting,
|
|
2793
3301
|
extensionRegistry,
|
|
2794
|
-
|
|
3302
|
+
collectedDiagnostics
|
|
2795
3303
|
);
|
|
2796
3304
|
if (recordNode) {
|
|
2797
3305
|
visiting.delete(type);
|
|
2798
|
-
if (
|
|
2799
|
-
const isRecursiveRecord = typeNodeContainsReference(recordNode.valueType,
|
|
3306
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3307
|
+
const isRecursiveRecord = typeNodeContainsReference(recordNode.valueType, registryTypeName);
|
|
2800
3308
|
if (!isRecursiveRecord) {
|
|
2801
3309
|
clearNamedTypeRegistration();
|
|
2802
3310
|
return recordNode;
|
|
2803
3311
|
}
|
|
2804
3312
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
2805
|
-
typeRegistry[
|
|
2806
|
-
name:
|
|
3313
|
+
typeRegistry[registryTypeName] = {
|
|
3314
|
+
name: registryTypeName,
|
|
2807
3315
|
type: recordNode,
|
|
2808
3316
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
2809
3317
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
2810
3318
|
};
|
|
2811
|
-
return {
|
|
3319
|
+
return {
|
|
3320
|
+
kind: "reference",
|
|
3321
|
+
name: registryTypeName,
|
|
3322
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3323
|
+
};
|
|
2812
3324
|
}
|
|
2813
3325
|
return recordNode;
|
|
2814
3326
|
}
|
|
@@ -2819,7 +3331,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2819
3331
|
file,
|
|
2820
3332
|
typeRegistry,
|
|
2821
3333
|
visiting,
|
|
2822
|
-
|
|
3334
|
+
collectedDiagnostics,
|
|
2823
3335
|
extensionRegistry
|
|
2824
3336
|
);
|
|
2825
3337
|
for (const prop of type.getProperties()) {
|
|
@@ -2835,7 +3347,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2835
3347
|
visiting,
|
|
2836
3348
|
declaration,
|
|
2837
3349
|
extensionRegistry,
|
|
2838
|
-
|
|
3350
|
+
collectedDiagnostics
|
|
2839
3351
|
);
|
|
2840
3352
|
const fieldNodeInfo = fieldInfoMap?.get(prop.name);
|
|
2841
3353
|
properties.push({
|
|
@@ -2850,18 +3362,29 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, extensio
|
|
|
2850
3362
|
visiting.delete(type);
|
|
2851
3363
|
const objectNode = {
|
|
2852
3364
|
kind: "object",
|
|
2853
|
-
properties
|
|
3365
|
+
properties: namedDecl !== void 0 && (ts3.isClassDeclaration(namedDecl) || ts3.isInterfaceDeclaration(namedDecl) || ts3.isTypeAliasDeclaration(namedDecl)) ? applyDiscriminatorToObjectProperties(
|
|
3366
|
+
properties,
|
|
3367
|
+
namedDecl,
|
|
3368
|
+
type,
|
|
3369
|
+
checker,
|
|
3370
|
+
file,
|
|
3371
|
+
collectedDiagnostics
|
|
3372
|
+
) : properties,
|
|
2854
3373
|
additionalProperties: true
|
|
2855
3374
|
};
|
|
2856
|
-
if (
|
|
3375
|
+
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
2857
3376
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
2858
|
-
typeRegistry[
|
|
2859
|
-
name:
|
|
3377
|
+
typeRegistry[registryTypeName] = {
|
|
3378
|
+
name: registryTypeName,
|
|
2860
3379
|
type: objectNode,
|
|
2861
3380
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
2862
3381
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
2863
3382
|
};
|
|
2864
|
-
return {
|
|
3383
|
+
return {
|
|
3384
|
+
kind: "reference",
|
|
3385
|
+
name: registryTypeName,
|
|
3386
|
+
typeArguments: referenceTypeArguments.map((argument) => argument.typeNode)
|
|
3387
|
+
};
|
|
2865
3388
|
}
|
|
2866
3389
|
return objectNode;
|
|
2867
3390
|
}
|
|
@@ -3122,6 +3645,18 @@ function detectFormSpecReference(typeNode) {
|
|
|
3122
3645
|
}
|
|
3123
3646
|
|
|
3124
3647
|
// src/analyzer/program.ts
|
|
3648
|
+
function createProgramContextFromProgram(program, filePath) {
|
|
3649
|
+
const absolutePath = path.resolve(filePath);
|
|
3650
|
+
const sourceFile = program.getSourceFile(absolutePath) ?? program.getSourceFile(filePath);
|
|
3651
|
+
if (!sourceFile) {
|
|
3652
|
+
throw new Error(`Could not find source file in provided program: ${absolutePath}`);
|
|
3653
|
+
}
|
|
3654
|
+
return {
|
|
3655
|
+
program,
|
|
3656
|
+
checker: program.getTypeChecker(),
|
|
3657
|
+
sourceFile
|
|
3658
|
+
};
|
|
3659
|
+
}
|
|
3125
3660
|
function createProgramContext(filePath) {
|
|
3126
3661
|
const absolutePath = path.resolve(filePath);
|
|
3127
3662
|
const fileDir = path.dirname(absolutePath);
|
|
@@ -3192,24 +3727,33 @@ function findTypeAliasByName(sourceFile, aliasName) {
|
|
|
3192
3727
|
}
|
|
3193
3728
|
function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry) {
|
|
3194
3729
|
const ctx = createProgramContext(filePath);
|
|
3730
|
+
return analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry);
|
|
3731
|
+
}
|
|
3732
|
+
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry) {
|
|
3733
|
+
const analysisFilePath = path.resolve(filePath);
|
|
3195
3734
|
const classDecl = findClassByName(ctx.sourceFile, typeName);
|
|
3196
3735
|
if (classDecl !== null) {
|
|
3197
|
-
return analyzeClassToIR(classDecl, ctx.checker,
|
|
3736
|
+
return analyzeClassToIR(classDecl, ctx.checker, analysisFilePath, extensionRegistry);
|
|
3198
3737
|
}
|
|
3199
3738
|
const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
|
|
3200
3739
|
if (interfaceDecl !== null) {
|
|
3201
|
-
return analyzeInterfaceToIR(interfaceDecl, ctx.checker,
|
|
3740
|
+
return analyzeInterfaceToIR(interfaceDecl, ctx.checker, analysisFilePath, extensionRegistry);
|
|
3202
3741
|
}
|
|
3203
3742
|
const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
|
|
3204
3743
|
if (typeAlias !== null) {
|
|
3205
|
-
const result = analyzeTypeAliasToIR(
|
|
3744
|
+
const result = analyzeTypeAliasToIR(
|
|
3745
|
+
typeAlias,
|
|
3746
|
+
ctx.checker,
|
|
3747
|
+
analysisFilePath,
|
|
3748
|
+
extensionRegistry
|
|
3749
|
+
);
|
|
3206
3750
|
if (result.ok) {
|
|
3207
3751
|
return result.analysis;
|
|
3208
3752
|
}
|
|
3209
3753
|
throw new Error(result.error);
|
|
3210
3754
|
}
|
|
3211
3755
|
throw new Error(
|
|
3212
|
-
`Type "${typeName}" not found as a class, interface, or type alias in ${
|
|
3756
|
+
`Type "${typeName}" not found as a class, interface, or type alias in ${analysisFilePath}`
|
|
3213
3757
|
);
|
|
3214
3758
|
}
|
|
3215
3759
|
|
|
@@ -3345,12 +3889,28 @@ function generateSchemasFromClass(options) {
|
|
|
3345
3889
|
);
|
|
3346
3890
|
}
|
|
3347
3891
|
function generateSchemas(options) {
|
|
3348
|
-
const
|
|
3892
|
+
const ctx = createProgramContext(options.filePath);
|
|
3893
|
+
return generateSchemasFromProgram({
|
|
3894
|
+
...options,
|
|
3895
|
+
program: ctx.program
|
|
3896
|
+
});
|
|
3897
|
+
}
|
|
3898
|
+
function generateSchemasFromProgram(options) {
|
|
3899
|
+
const ctx = createProgramContextFromProgram(options.program, options.filePath);
|
|
3900
|
+
const analysis = analyzeNamedTypeToIRFromProgramContext(
|
|
3901
|
+
ctx,
|
|
3349
3902
|
options.filePath,
|
|
3350
3903
|
options.typeName,
|
|
3351
3904
|
options.extensionRegistry
|
|
3352
3905
|
);
|
|
3353
|
-
return generateClassSchemas(
|
|
3906
|
+
return generateClassSchemas(
|
|
3907
|
+
analysis,
|
|
3908
|
+
{ file: options.filePath },
|
|
3909
|
+
{
|
|
3910
|
+
extensionRegistry: options.extensionRegistry,
|
|
3911
|
+
vendorPrefix: options.vendorPrefix
|
|
3912
|
+
}
|
|
3913
|
+
);
|
|
3354
3914
|
}
|
|
3355
3915
|
|
|
3356
3916
|
// src/generators/mixed-authoring.ts
|
|
@@ -3556,7 +4116,10 @@ export {
|
|
|
3556
4116
|
generateJsonSchema,
|
|
3557
4117
|
generateSchemas,
|
|
3558
4118
|
generateSchemasFromClass,
|
|
4119
|
+
generateSchemasFromProgram,
|
|
3559
4120
|
generateUiSchema,
|
|
4121
|
+
jsonSchema7Schema,
|
|
4122
|
+
uiSchema as uiSchemaSchema,
|
|
3560
4123
|
writeSchemas
|
|
3561
4124
|
};
|
|
3562
4125
|
//# sourceMappingURL=index.js.map
|