@formspec/build 0.1.0-alpha.54 → 0.1.0-alpha.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
- package/dist/browser.cjs +44 -12
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +46 -13
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +7 -46
- package/dist/build-beta.d.ts +7 -46
- package/dist/build-internal.d.ts +7 -46
- package/dist/build.d.ts +7 -46
- package/dist/cli.cjs +175 -66
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +172 -54
- package/dist/cli.js.map +1 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/generators/class-schema.d.ts +2 -2
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/index.cjs +165 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +167 -51
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +166 -59
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.js +164 -48
- package/dist/internals.js.map +1 -1
- package/dist/json-schema/generator.d.ts +1 -1
- package/dist/json-schema/generator.d.ts.map +1 -1
- package/dist/json-schema/ir-generator.d.ts +1 -1
- package/dist/json-schema/ir-generator.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/internals.cjs
CHANGED
|
@@ -852,7 +852,7 @@ var path = __toESM(require("path"), 1);
|
|
|
852
852
|
|
|
853
853
|
// src/analyzer/class-analyzer.ts
|
|
854
854
|
var ts6 = __toESM(require("typescript"), 1);
|
|
855
|
-
var
|
|
855
|
+
var import_internal4 = require("@formspec/analysis/internal");
|
|
856
856
|
|
|
857
857
|
// src/analyzer/jsdoc-constraints.ts
|
|
858
858
|
var ts5 = __toESM(require("typescript"), 1);
|
|
@@ -862,6 +862,7 @@ var ts4 = __toESM(require("typescript"), 1);
|
|
|
862
862
|
var import_internal2 = require("@formspec/analysis/internal");
|
|
863
863
|
var import_internals3 = require("@formspec/core/internals");
|
|
864
864
|
var import_internals4 = require("@formspec/core/internals");
|
|
865
|
+
var import_core = require("@formspec/core");
|
|
865
866
|
|
|
866
867
|
// src/extensions/resolve-custom-type.ts
|
|
867
868
|
var ts2 = __toESM(require("typescript"), 1);
|
|
@@ -989,6 +990,7 @@ function isIntegerBrandedType(type) {
|
|
|
989
990
|
}
|
|
990
991
|
|
|
991
992
|
// src/analyzer/tsdoc-parser.ts
|
|
993
|
+
var import_internal3 = require("@formspec/analysis/internal");
|
|
992
994
|
function sharedTagValueOptions(options) {
|
|
993
995
|
return {
|
|
994
996
|
...options?.extensionRegistry !== void 0 ? { registry: options.extensionRegistry } : {},
|
|
@@ -1395,56 +1397,82 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
|
|
|
1395
1397
|
if (definition === null) {
|
|
1396
1398
|
return [];
|
|
1397
1399
|
}
|
|
1400
|
+
const nonNullPlacement = placement;
|
|
1401
|
+
const log = (0, import_internal3.getBuildLogger)();
|
|
1402
|
+
const broadeningLog = (0, import_internal3.getBroadeningLogger)();
|
|
1403
|
+
const syntheticLog = (0, import_internal3.getSyntheticLogger)();
|
|
1404
|
+
const logsEnabled = log !== import_core.noopLogger || broadeningLog !== import_core.noopLogger;
|
|
1405
|
+
const syntheticTraceEnabled = syntheticLog !== import_core.noopLogger;
|
|
1406
|
+
const logStart = logsEnabled ? (0, import_internal3.nowMicros)() : 0;
|
|
1407
|
+
const subjectTypeKind = logsEnabled ? (0, import_internal3.describeTypeKind)(subjectType, checker) : "";
|
|
1408
|
+
function emit(outcome, result2) {
|
|
1409
|
+
if (!logsEnabled) {
|
|
1410
|
+
return result2;
|
|
1411
|
+
}
|
|
1412
|
+
const entry = {
|
|
1413
|
+
consumer: "build",
|
|
1414
|
+
tag: tagName,
|
|
1415
|
+
placement: nonNullPlacement,
|
|
1416
|
+
subjectTypeKind,
|
|
1417
|
+
roleOutcome: outcome,
|
|
1418
|
+
elapsedMicros: (0, import_internal3.elapsedMicros)(logStart)
|
|
1419
|
+
};
|
|
1420
|
+
(0, import_internal3.logTagApplication)(log, entry);
|
|
1421
|
+
if (outcome === "bypass" || outcome === "D1" || outcome === "D2") {
|
|
1422
|
+
(0, import_internal3.logTagApplication)(broadeningLog, entry);
|
|
1423
|
+
}
|
|
1424
|
+
return result2;
|
|
1425
|
+
}
|
|
1398
1426
|
if (!definition.placements.includes(placement)) {
|
|
1399
|
-
return [
|
|
1427
|
+
return emit("A-reject", [
|
|
1400
1428
|
makeDiagnostic(
|
|
1401
1429
|
"INVALID_TAG_PLACEMENT",
|
|
1402
1430
|
`Tag "@${tagName}" is not allowed on ${placementLabel(placement)}.`,
|
|
1403
1431
|
provenance
|
|
1404
1432
|
)
|
|
1405
|
-
];
|
|
1433
|
+
]);
|
|
1406
1434
|
}
|
|
1407
1435
|
const target = parsedTag?.target ?? null;
|
|
1408
1436
|
let evaluatedType = subjectType;
|
|
1409
1437
|
let targetLabel = node.getText(sourceFile);
|
|
1410
1438
|
if (target !== null) {
|
|
1411
1439
|
if (target.kind !== "path") {
|
|
1412
|
-
return [
|
|
1440
|
+
return emit("B-reject", [
|
|
1413
1441
|
makeDiagnostic(
|
|
1414
1442
|
"UNSUPPORTED_TARGETING_SYNTAX",
|
|
1415
1443
|
`Tag "@${tagName}" does not support ${target.kind} targeting syntax.`,
|
|
1416
1444
|
provenance
|
|
1417
1445
|
)
|
|
1418
|
-
];
|
|
1446
|
+
]);
|
|
1419
1447
|
}
|
|
1420
1448
|
if (!target.valid || target.path === null) {
|
|
1421
|
-
return [
|
|
1449
|
+
return emit("B-reject", [
|
|
1422
1450
|
makeDiagnostic(
|
|
1423
1451
|
"UNSUPPORTED_TARGETING_SYNTAX",
|
|
1424
1452
|
`Tag "@${tagName}" has invalid path targeting syntax.`,
|
|
1425
1453
|
provenance
|
|
1426
1454
|
)
|
|
1427
|
-
];
|
|
1455
|
+
]);
|
|
1428
1456
|
}
|
|
1429
1457
|
const resolution = (0, import_internal2.resolvePathTargetType)(subjectType, checker, target.path.segments);
|
|
1430
1458
|
if (resolution.kind === "missing-property") {
|
|
1431
|
-
return [
|
|
1459
|
+
return emit("B-reject", [
|
|
1432
1460
|
makeDiagnostic(
|
|
1433
1461
|
"UNKNOWN_PATH_TARGET",
|
|
1434
1462
|
`Target "${target.rawText}": path-targeted constraint "${tagName}" references unknown path segment "${resolution.segment}"`,
|
|
1435
1463
|
provenance
|
|
1436
1464
|
)
|
|
1437
|
-
];
|
|
1465
|
+
]);
|
|
1438
1466
|
}
|
|
1439
1467
|
if (resolution.kind === "unresolvable") {
|
|
1440
1468
|
const actualType = checker.typeToString(resolution.type, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
|
|
1441
|
-
return [
|
|
1469
|
+
return emit("B-reject", [
|
|
1442
1470
|
makeDiagnostic(
|
|
1443
1471
|
"TYPE_MISMATCH",
|
|
1444
1472
|
`Target "${target.rawText}": path-targeted constraint "${tagName}" is invalid because type "${actualType}" cannot be traversed`,
|
|
1445
1473
|
provenance
|
|
1446
1474
|
)
|
|
1447
|
-
];
|
|
1475
|
+
]);
|
|
1448
1476
|
}
|
|
1449
1477
|
evaluatedType = resolution.type;
|
|
1450
1478
|
targetLabel = target.rawText;
|
|
@@ -1473,13 +1501,13 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
|
|
|
1473
1501
|
tagName,
|
|
1474
1502
|
parsedTag?.argumentText
|
|
1475
1503
|
) : null;
|
|
1476
|
-
return [
|
|
1504
|
+
return emit("B-reject", [
|
|
1477
1505
|
makeDiagnostic(
|
|
1478
1506
|
"TYPE_MISMATCH",
|
|
1479
1507
|
hint === null ? baseMessage : `${baseMessage}. ${hint}`,
|
|
1480
1508
|
provenance
|
|
1481
1509
|
)
|
|
1482
|
-
];
|
|
1510
|
+
]);
|
|
1483
1511
|
}
|
|
1484
1512
|
}
|
|
1485
1513
|
const argumentExpression = renderSyntheticArgumentExpression(
|
|
@@ -1487,14 +1515,23 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
|
|
|
1487
1515
|
parsedTag?.argumentText ?? ""
|
|
1488
1516
|
);
|
|
1489
1517
|
if (definition.requiresArgument && argumentExpression === null) {
|
|
1490
|
-
return [];
|
|
1518
|
+
return emit("A-pass", []);
|
|
1491
1519
|
}
|
|
1492
1520
|
if (hasBroadening) {
|
|
1493
|
-
return [];
|
|
1521
|
+
return emit("bypass", []);
|
|
1494
1522
|
}
|
|
1495
1523
|
const subjectTypeText = checker.typeToString(subjectType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
|
|
1496
1524
|
const hostType = options?.hostType ?? subjectType;
|
|
1497
1525
|
const hostTypeText = checker.typeToString(hostType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
|
|
1526
|
+
if (syntheticTraceEnabled) {
|
|
1527
|
+
syntheticLog.trace("invoking synthetic checker", {
|
|
1528
|
+
consumer: "build",
|
|
1529
|
+
tag: tagName,
|
|
1530
|
+
placement,
|
|
1531
|
+
subjectTypeKind,
|
|
1532
|
+
subjectTypeText
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1498
1535
|
const result = (0, import_internal2.checkSyntheticTagApplication)({
|
|
1499
1536
|
tagName,
|
|
1500
1537
|
placement,
|
|
@@ -1521,26 +1558,26 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
|
|
|
1521
1558
|
} : {}
|
|
1522
1559
|
});
|
|
1523
1560
|
if (result.diagnostics.length === 0) {
|
|
1524
|
-
return [];
|
|
1561
|
+
return emit("C-pass", []);
|
|
1525
1562
|
}
|
|
1526
1563
|
const setupDiagnostic = result.diagnostics.find((diagnostic) => diagnostic.kind !== "typescript");
|
|
1527
1564
|
if (setupDiagnostic !== void 0) {
|
|
1528
|
-
return [
|
|
1565
|
+
return emit("C-reject", [
|
|
1529
1566
|
makeDiagnostic(
|
|
1530
1567
|
setupDiagnostic.kind === "unsupported-custom-type-override" ? "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" : "SYNTHETIC_SETUP_FAILURE",
|
|
1531
1568
|
setupDiagnostic.message,
|
|
1532
1569
|
provenance
|
|
1533
1570
|
)
|
|
1534
|
-
];
|
|
1571
|
+
]);
|
|
1535
1572
|
}
|
|
1536
1573
|
const expectedLabel = definition.valueKind === null ? "compatible argument" : capabilityLabel(definition.valueKind);
|
|
1537
|
-
return [
|
|
1574
|
+
return emit("C-reject", [
|
|
1538
1575
|
makeDiagnostic(
|
|
1539
1576
|
"TYPE_MISMATCH",
|
|
1540
1577
|
`Tag "@${tagName}" received an invalid argument for ${expectedLabel}.`,
|
|
1541
1578
|
provenance
|
|
1542
1579
|
)
|
|
1543
|
-
];
|
|
1580
|
+
]);
|
|
1544
1581
|
}
|
|
1545
1582
|
var parseResultCache = /* @__PURE__ */ new Map();
|
|
1546
1583
|
function getExtensionTagNames(options) {
|
|
@@ -1950,7 +1987,7 @@ function createAnalyzerMetadataPolicy(input, discriminator) {
|
|
|
1950
1987
|
};
|
|
1951
1988
|
}
|
|
1952
1989
|
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
|
|
1953
|
-
const analysis = (0,
|
|
1990
|
+
const analysis = (0, import_internal4.analyzeMetadataForNodeWithChecker)({
|
|
1954
1991
|
checker,
|
|
1955
1992
|
node,
|
|
1956
1993
|
logicalName,
|
|
@@ -2291,7 +2328,7 @@ function getLeadingParsedTags(node) {
|
|
|
2291
2328
|
if (!commentText.startsWith("/**")) {
|
|
2292
2329
|
continue;
|
|
2293
2330
|
}
|
|
2294
|
-
parsedTags.push(...(0,
|
|
2331
|
+
parsedTags.push(...(0, import_internal4.parseCommentBlock)(commentText, { offset: range.pos }).tags);
|
|
2295
2332
|
}
|
|
2296
2333
|
return parsedTags;
|
|
2297
2334
|
}
|
|
@@ -2700,6 +2737,22 @@ function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiti
|
|
|
2700
2737
|
}
|
|
2701
2738
|
return referenceTypeNode.typeArguments.map((argumentNode) => {
|
|
2702
2739
|
const argumentType = checker.getTypeFromTypeNode(argumentNode);
|
|
2740
|
+
const baseSymbol = argumentType.aliasSymbol ?? argumentType.getSymbol();
|
|
2741
|
+
const argumentSymbol = baseSymbol !== void 0 && baseSymbol.flags & ts6.SymbolFlags.Alias ? checker.getAliasedSymbol(baseSymbol) : baseSymbol;
|
|
2742
|
+
const argumentDecl = argumentSymbol?.declarations?.[0];
|
|
2743
|
+
if (argumentDecl !== void 0 && argumentDecl.getSourceFile().fileName !== file) {
|
|
2744
|
+
const argumentName = argumentSymbol?.getName() ?? baseSymbol?.getName();
|
|
2745
|
+
if (argumentName !== void 0) {
|
|
2746
|
+
return {
|
|
2747
|
+
tsType: argumentType,
|
|
2748
|
+
typeNode: {
|
|
2749
|
+
kind: "reference",
|
|
2750
|
+
name: argumentName,
|
|
2751
|
+
typeArguments: []
|
|
2752
|
+
}
|
|
2753
|
+
};
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2703
2756
|
return {
|
|
2704
2757
|
tsType: argumentType,
|
|
2705
2758
|
typeNode: resolveTypeNode(
|
|
@@ -2966,22 +3019,10 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2966
3019
|
sourceNode
|
|
2967
3020
|
);
|
|
2968
3021
|
if (customTypeLookup !== null) {
|
|
2969
|
-
const typeId = customTypeIdFromLookup(customTypeLookup);
|
|
2970
|
-
let payload = null;
|
|
2971
|
-
if (customTypeLookup.registration.extractPayload !== void 0) {
|
|
2972
|
-
try {
|
|
2973
|
-
payload = customTypeLookup.registration.extractPayload(type, checker) ?? null;
|
|
2974
|
-
} catch (cause) {
|
|
2975
|
-
throw new Error(
|
|
2976
|
-
`extractPayload for custom type "${customTypeLookup.registration.typeName}" in extension "${customTypeLookup.extensionId}" threw`,
|
|
2977
|
-
{ cause }
|
|
2978
|
-
);
|
|
2979
|
-
}
|
|
2980
|
-
}
|
|
2981
3022
|
return {
|
|
2982
3023
|
kind: "custom",
|
|
2983
|
-
typeId,
|
|
2984
|
-
payload
|
|
3024
|
+
typeId: customTypeIdFromLookup(customTypeLookup),
|
|
3025
|
+
payload: null
|
|
2985
3026
|
};
|
|
2986
3027
|
}
|
|
2987
3028
|
const primitiveAlias = tryResolveNamedPrimitiveAlias(
|
|
@@ -3165,6 +3206,21 @@ function getReferencedTypeAliasDeclaration(sourceNode, checker) {
|
|
|
3165
3206
|
}
|
|
3166
3207
|
return getTypeAliasDeclarationFromTypeReference(typeNode, checker);
|
|
3167
3208
|
}
|
|
3209
|
+
function resolveNamedTypeWithSourceRecovery(type, sourceNode, checker) {
|
|
3210
|
+
const typeName = getNamedTypeName(type);
|
|
3211
|
+
const namedDecl = getNamedTypeDeclaration(type);
|
|
3212
|
+
if (typeName !== null && namedDecl !== void 0) {
|
|
3213
|
+
return { typeName, namedDecl };
|
|
3214
|
+
}
|
|
3215
|
+
if (sourceNode === void 0) {
|
|
3216
|
+
return null;
|
|
3217
|
+
}
|
|
3218
|
+
const refAliasDecl = getReferencedTypeAliasDeclaration(sourceNode, checker);
|
|
3219
|
+
if (refAliasDecl === void 0) {
|
|
3220
|
+
return null;
|
|
3221
|
+
}
|
|
3222
|
+
return { typeName: refAliasDecl.name.text, namedDecl: refAliasDecl };
|
|
3223
|
+
}
|
|
3168
3224
|
function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
|
|
3169
3225
|
if (!ts6.isTypeReferenceNode(typeNode)) {
|
|
3170
3226
|
return false;
|
|
@@ -3223,8 +3279,23 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
3223
3279
|
);
|
|
3224
3280
|
}
|
|
3225
3281
|
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3226
|
-
const
|
|
3227
|
-
|
|
3282
|
+
const recovered = resolveNamedTypeWithSourceRecovery(type, sourceNode, checker);
|
|
3283
|
+
let typeName = null;
|
|
3284
|
+
let namedDecl;
|
|
3285
|
+
if (recovered !== null) {
|
|
3286
|
+
const recoveredAliasDecl = ts6.isTypeAliasDeclaration(recovered.namedDecl) ? recovered.namedDecl : void 0;
|
|
3287
|
+
if (recoveredAliasDecl !== void 0) {
|
|
3288
|
+
const aliasUnderlyingType = checker.getTypeFromTypeNode(recoveredAliasDecl.type);
|
|
3289
|
+
const isNonGeneric = recoveredAliasDecl.typeParameters === void 0 || recoveredAliasDecl.typeParameters.length === 0;
|
|
3290
|
+
if (isNonGeneric && (aliasUnderlyingType.isUnion() || isObjectType(aliasUnderlyingType))) {
|
|
3291
|
+
typeName = recovered.typeName;
|
|
3292
|
+
namedDecl = recovered.namedDecl;
|
|
3293
|
+
}
|
|
3294
|
+
} else {
|
|
3295
|
+
typeName = recovered.typeName;
|
|
3296
|
+
namedDecl = recovered.namedDecl;
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3228
3299
|
if (typeName && typeName in typeRegistry) {
|
|
3229
3300
|
return { kind: "reference", name: typeName, typeArguments: [] };
|
|
3230
3301
|
}
|
|
@@ -3256,6 +3327,10 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3256
3327
|
if (!typeName) {
|
|
3257
3328
|
return result;
|
|
3258
3329
|
}
|
|
3330
|
+
const existing = typeRegistry[typeName];
|
|
3331
|
+
if (existing !== void 0 && existing.type !== RESOLVING_TYPE_PLACEHOLDER) {
|
|
3332
|
+
return { kind: "reference", name: typeName, typeArguments: [] };
|
|
3333
|
+
}
|
|
3259
3334
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3260
3335
|
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3261
3336
|
metadataPolicy,
|
|
@@ -4364,20 +4439,29 @@ function assertNoSerializedNameCollisions(ir) {
|
|
|
4364
4439
|
}
|
|
4365
4440
|
|
|
4366
4441
|
// src/json-schema/ir-generator.ts
|
|
4442
|
+
function parseEnumSerialization(value) {
|
|
4443
|
+
switch (value) {
|
|
4444
|
+
case void 0:
|
|
4445
|
+
case "enum":
|
|
4446
|
+
return "enum";
|
|
4447
|
+
case "oneOf":
|
|
4448
|
+
return "oneOf";
|
|
4449
|
+
case "smart-size":
|
|
4450
|
+
return "smart-size";
|
|
4451
|
+
default:
|
|
4452
|
+
throw new Error(
|
|
4453
|
+
`Invalid enumSerialization "${String(value)}". Expected "enum", "oneOf", or "smart-size".`
|
|
4454
|
+
);
|
|
4455
|
+
}
|
|
4456
|
+
}
|
|
4367
4457
|
function makeContext(options) {
|
|
4368
4458
|
const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
|
|
4369
|
-
const
|
|
4459
|
+
const enumSerialization = parseEnumSerialization(options?.enumSerialization);
|
|
4370
4460
|
if (!vendorPrefix.startsWith("x-")) {
|
|
4371
4461
|
throw new Error(
|
|
4372
4462
|
`Invalid vendorPrefix "${vendorPrefix}". Extension JSON Schema keywords must start with "x-".`
|
|
4373
4463
|
);
|
|
4374
4464
|
}
|
|
4375
|
-
if (rawEnumSerialization !== void 0 && rawEnumSerialization !== "enum" && rawEnumSerialization !== "oneOf") {
|
|
4376
|
-
throw new Error(
|
|
4377
|
-
`Invalid enumSerialization "${rawEnumSerialization}". Expected "enum" or "oneOf".`
|
|
4378
|
-
);
|
|
4379
|
-
}
|
|
4380
|
-
const enumSerialization = rawEnumSerialization ?? "enum";
|
|
4381
4465
|
return {
|
|
4382
4466
|
defs: {},
|
|
4383
4467
|
typeNameMap: {},
|
|
@@ -4585,21 +4669,31 @@ function generatePrimitiveType(type) {
|
|
|
4585
4669
|
};
|
|
4586
4670
|
}
|
|
4587
4671
|
function generateEnumType(type, ctx) {
|
|
4588
|
-
if (ctx.enumSerialization === "oneOf") {
|
|
4672
|
+
if (ctx.enumSerialization === "oneOf" || ctx.enumSerialization === "smart-size" && shouldSerializeEnumAsOneOf(type)) {
|
|
4589
4673
|
return {
|
|
4590
|
-
oneOf: type.members.map((m) =>
|
|
4591
|
-
const
|
|
4592
|
-
title
|
|
4593
|
-
|
|
4674
|
+
oneOf: type.members.map((m) => {
|
|
4675
|
+
const stringValue = String(m.value);
|
|
4676
|
+
const title = m.displayName !== void 0 && m.displayName !== stringValue ? m.displayName : void 0;
|
|
4677
|
+
return title !== void 0 ? { const: m.value, title } : { const: m.value };
|
|
4678
|
+
})
|
|
4594
4679
|
};
|
|
4595
4680
|
}
|
|
4596
4681
|
const schema = { enum: type.members.map((m) => m.value) };
|
|
4682
|
+
if (ctx.enumSerialization === "smart-size") {
|
|
4683
|
+
return schema;
|
|
4684
|
+
}
|
|
4597
4685
|
const displayNames = buildEnumDisplayNameExtension(type);
|
|
4598
4686
|
if (displayNames !== void 0) {
|
|
4599
4687
|
schema[`${ctx.vendorPrefix}-display-names`] = displayNames;
|
|
4600
4688
|
}
|
|
4601
4689
|
return schema;
|
|
4602
4690
|
}
|
|
4691
|
+
function shouldSerializeEnumAsOneOf(type) {
|
|
4692
|
+
return type.members.some((member) => {
|
|
4693
|
+
const title = member.displayName ?? String(member.value);
|
|
4694
|
+
return title !== String(member.value);
|
|
4695
|
+
});
|
|
4696
|
+
}
|
|
4603
4697
|
function buildEnumDisplayNameExtension(type) {
|
|
4604
4698
|
if (!type.members.some((member) => member.displayName !== void 0)) {
|
|
4605
4699
|
return void 0;
|
|
@@ -5080,19 +5174,24 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
|
|
|
5080
5174
|
|
|
5081
5175
|
// src/extensions/registry.ts
|
|
5082
5176
|
var import_internals5 = require("@formspec/core/internals");
|
|
5083
|
-
var
|
|
5177
|
+
var import_internal5 = require("@formspec/analysis/internal");
|
|
5084
5178
|
var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
|
|
5085
5179
|
function buildConstraintTagSources(extensions) {
|
|
5086
5180
|
return extensions.map((extension) => ({
|
|
5087
5181
|
extensionId: extension.extensionId,
|
|
5088
5182
|
...extension.constraintTags !== void 0 ? {
|
|
5089
5183
|
constraintTags: extension.constraintTags.map((tag) => ({
|
|
5090
|
-
tagName: (0,
|
|
5184
|
+
tagName: (0, import_internal5.normalizeFormSpecTagName)(tag.tagName)
|
|
5091
5185
|
}))
|
|
5092
5186
|
} : {}
|
|
5093
5187
|
}));
|
|
5094
5188
|
}
|
|
5095
5189
|
function createExtensionRegistry(extensions) {
|
|
5190
|
+
const registryLog = (0, import_internal5.getSyntheticLogger)();
|
|
5191
|
+
registryLog.debug("createExtensionRegistry: constructing", {
|
|
5192
|
+
extensionCount: extensions.length,
|
|
5193
|
+
extensionIds: extensions.map((e) => e.extensionId)
|
|
5194
|
+
});
|
|
5096
5195
|
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
5097
5196
|
let symbolMap = /* @__PURE__ */ new Map();
|
|
5098
5197
|
const typeMap = /* @__PURE__ */ new Map();
|
|
@@ -5160,7 +5259,7 @@ function createExtensionRegistry(extensions) {
|
|
|
5160
5259
|
}
|
|
5161
5260
|
if (ext.constraintTags !== void 0) {
|
|
5162
5261
|
for (const tag of ext.constraintTags) {
|
|
5163
|
-
const canonicalTagName = (0,
|
|
5262
|
+
const canonicalTagName = (0, import_internal5.normalizeFormSpecTagName)(tag.tagName);
|
|
5164
5263
|
if (constraintTagMap.has(canonicalTagName)) {
|
|
5165
5264
|
throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
|
|
5166
5265
|
}
|
|
@@ -5185,7 +5284,7 @@ function createExtensionRegistry(extensions) {
|
|
|
5185
5284
|
throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
|
|
5186
5285
|
}
|
|
5187
5286
|
metadataSlotMap.set(slot.slotId, true);
|
|
5188
|
-
const canonicalTagName = (0,
|
|
5287
|
+
const canonicalTagName = (0, import_internal5.normalizeFormSpecTagName)(slot.tagName);
|
|
5189
5288
|
if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
|
|
5190
5289
|
throw new Error(
|
|
5191
5290
|
`Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
|
|
@@ -5212,7 +5311,7 @@ function createExtensionRegistry(extensions) {
|
|
|
5212
5311
|
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals5.normalizeConstraintTagName)(canonicalTagName)}".`
|
|
5213
5312
|
);
|
|
5214
5313
|
}
|
|
5215
|
-
const existingTag = (0,
|
|
5314
|
+
const existingTag = (0, import_internal5.getTagDefinition)(canonicalTagName, reservedTagSources);
|
|
5216
5315
|
if (existingTag !== null) {
|
|
5217
5316
|
throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
|
|
5218
5317
|
`Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
|
|
@@ -5224,6 +5323,14 @@ function createExtensionRegistry(extensions) {
|
|
|
5224
5323
|
}
|
|
5225
5324
|
}
|
|
5226
5325
|
}
|
|
5326
|
+
registryLog.debug("createExtensionRegistry: complete", {
|
|
5327
|
+
typeCount: typeMap.size,
|
|
5328
|
+
constraintCount: constraintMap.size,
|
|
5329
|
+
constraintTagCount: constraintTagMap.size,
|
|
5330
|
+
broadeningCount: builtinBroadeningMap.size,
|
|
5331
|
+
annotationCount: annotationMap.size,
|
|
5332
|
+
metadataSlotCount: metadataSlotMap.size
|
|
5333
|
+
});
|
|
5227
5334
|
return {
|
|
5228
5335
|
extensions,
|
|
5229
5336
|
findType: (typeId) => typeMap.get(typeId),
|
|
@@ -5234,7 +5341,7 @@ function createExtensionRegistry(extensions) {
|
|
|
5234
5341
|
symbolMap = map;
|
|
5235
5342
|
},
|
|
5236
5343
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
5237
|
-
findConstraintTag: (tagName) => constraintTagMap.get((0,
|
|
5344
|
+
findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal5.normalizeFormSpecTagName)(tagName)),
|
|
5238
5345
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
5239
5346
|
findAnnotation: (annotationId) => annotationMap.get(annotationId)
|
|
5240
5347
|
};
|
|
@@ -5502,9 +5609,9 @@ function collectFieldNameMap(elements) {
|
|
|
5502
5609
|
}
|
|
5503
5610
|
|
|
5504
5611
|
// src/validate/constraint-validator.ts
|
|
5505
|
-
var
|
|
5612
|
+
var import_internal6 = require("@formspec/analysis/internal");
|
|
5506
5613
|
function validateFieldNode(ctx, field) {
|
|
5507
|
-
const analysis = (0,
|
|
5614
|
+
const analysis = (0, import_internal6.analyzeConstraintTargets)(
|
|
5508
5615
|
field.name,
|
|
5509
5616
|
field.type,
|
|
5510
5617
|
field.constraints,
|
|
@@ -5522,7 +5629,7 @@ function validateFieldNode(ctx, field) {
|
|
|
5522
5629
|
}
|
|
5523
5630
|
function validateObjectProperty(ctx, parentName, property) {
|
|
5524
5631
|
const qualifiedName = `${parentName}.${property.name}`;
|
|
5525
|
-
const analysis = (0,
|
|
5632
|
+
const analysis = (0, import_internal6.analyzeConstraintTargets)(
|
|
5526
5633
|
qualifiedName,
|
|
5527
5634
|
property.type,
|
|
5528
5635
|
property.constraints,
|