@formspec/build 0.1.0-alpha.42 → 0.1.0-alpha.43

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/internals.js CHANGED
@@ -796,7 +796,7 @@ import * as path from "path";
796
796
  import * as ts3 from "typescript";
797
797
  import {
798
798
  analyzeMetadataForNodeWithChecker,
799
- parseCommentBlock as parseCommentBlock2
799
+ parseCommentBlock
800
800
  } from "@formspec/analysis/internal";
801
801
 
802
802
  // src/analyzer/jsdoc-constraints.ts
@@ -806,73 +806,25 @@ import * as ts2 from "typescript";
806
806
  import * as ts from "typescript";
807
807
  import {
808
808
  checkSyntheticTagApplication,
809
+ choosePreferredPayloadText,
809
810
  extractPathTarget as extractSharedPathTarget,
810
811
  getTagDefinition,
811
812
  hasTypeSemanticCapability,
812
813
  normalizeFormSpecTagName,
813
814
  parseConstraintTagValue,
814
815
  parseDefaultValueTagValue,
816
+ parseTagSyntax,
817
+ parseUnifiedComment,
815
818
  resolveDeclarationPlacement,
816
819
  resolvePathTargetType,
817
- sliceCommentSpan,
818
- parseCommentBlock,
819
- parseTagSyntax
820
+ TAGS_REQUIRING_RAW_TEXT
820
821
  } from "@formspec/analysis/internal";
821
- import {
822
- TSDocParser,
823
- TSDocConfiguration,
824
- TSDocTagDefinition,
825
- TSDocTagSyntaxKind,
826
- DocExcerpt,
827
- DocPlainText,
828
- DocSoftBreak,
829
- TextRange
830
- } from "@microsoft/tsdoc";
831
822
  import {
832
823
  BUILTIN_CONSTRAINT_DEFINITIONS,
833
824
  normalizeConstraintTagName,
834
825
  isBuiltinConstraintName
835
826
  } from "@formspec/core/internals";
836
827
  import "@formspec/core/internals";
837
- var TAGS_REQUIRING_RAW_TEXT = /* @__PURE__ */ new Set(["pattern", "enumOptions", "defaultValue"]);
838
- function createFormSpecTSDocConfig(extensionTagNames = []) {
839
- const config = new TSDocConfiguration();
840
- for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS)) {
841
- config.addTagDefinition(
842
- new TSDocTagDefinition({
843
- tagName: "@" + tagName,
844
- syntaxKind: TSDocTagSyntaxKind.BlockTag,
845
- allowMultiple: true
846
- })
847
- );
848
- }
849
- for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
850
- config.addTagDefinition(
851
- new TSDocTagDefinition({
852
- tagName: "@" + tagName,
853
- syntaxKind: TSDocTagSyntaxKind.BlockTag,
854
- allowMultiple: true
855
- })
856
- );
857
- }
858
- for (const tagName of extensionTagNames) {
859
- config.addTagDefinition(
860
- new TSDocTagDefinition({
861
- tagName: "@" + tagName,
862
- syntaxKind: TSDocTagSyntaxKind.BlockTag,
863
- allowMultiple: true
864
- })
865
- );
866
- }
867
- return config;
868
- }
869
- function sharedCommentSyntaxOptions(options, offset) {
870
- const extensions = options?.extensionRegistry?.extensions;
871
- return {
872
- ...offset !== void 0 ? { offset } : {},
873
- ...extensions !== void 0 ? { extensions } : {}
874
- };
875
- }
876
828
  function sharedTagValueOptions(options) {
877
829
  return {
878
830
  ...options?.extensionRegistry !== void 0 ? { registry: options.extensionRegistry } : {},
@@ -972,6 +924,30 @@ function pushUniqueCompilerDiagnostics(target, additions) {
972
924
  target.push(diagnostic);
973
925
  }
974
926
  }
927
+ function processConstraintTag(tagName, text, parsedTag, provenance, node, sourceFile, supportingDeclarations, options, constraints, diagnostics) {
928
+ const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
929
+ node,
930
+ sourceFile,
931
+ tagName,
932
+ parsedTag,
933
+ provenance,
934
+ supportingDeclarations,
935
+ options
936
+ );
937
+ if (compilerDiagnostics.length > 0) {
938
+ pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
939
+ return;
940
+ }
941
+ const constraintNode = parseConstraintTagValue(
942
+ tagName,
943
+ text,
944
+ provenance,
945
+ sharedTagValueOptions(options)
946
+ );
947
+ if (constraintNode) {
948
+ constraints.push(constraintNode);
949
+ }
950
+ }
975
951
  function renderSyntheticArgumentExpression(valueKind, argumentText) {
976
952
  const trimmed = argumentText.trim();
977
953
  if (trimmed === "") {
@@ -1257,10 +1233,9 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1257
1233
  )
1258
1234
  ];
1259
1235
  }
1260
- var parserCache = /* @__PURE__ */ new Map();
1261
1236
  var parseResultCache = /* @__PURE__ */ new Map();
1262
- function getParser(options) {
1263
- const extensionTagNames = [
1237
+ function getExtensionTagNames(options) {
1238
+ return [
1264
1239
  ...options?.extensionRegistry?.extensions.flatMap(
1265
1240
  (extension) => (extension.constraintTags ?? []).map((tag) => normalizeFormSpecTagName(tag.tagName))
1266
1241
  ) ?? [],
@@ -1268,14 +1243,6 @@ function getParser(options) {
1268
1243
  (extension) => (extension.metadataSlots ?? []).map((slot) => normalizeFormSpecTagName(slot.tagName))
1269
1244
  ) ?? []
1270
1245
  ].sort();
1271
- const cacheKey = extensionTagNames.join("|");
1272
- const existing = parserCache.get(cacheKey);
1273
- if (existing) {
1274
- return existing;
1275
- }
1276
- const parser = new TSDocParser(createFormSpecTSDocConfig(extensionTagNames));
1277
- parserCache.set(cacheKey, parser);
1278
- return parser;
1279
1246
  }
1280
1247
  function getExtensionRegistryCacheKey(registry) {
1281
1248
  if (registry === void 0) {
@@ -1326,13 +1293,13 @@ function parseTSDocTags(node, file = "", options) {
1326
1293
  let placeholder;
1327
1294
  let displayNameProvenance;
1328
1295
  let placeholderProvenance;
1329
- const rawTextTags = [];
1330
1296
  const sourceFile = node.getSourceFile();
1331
1297
  const sourceText = sourceFile.getFullText();
1332
1298
  const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
1333
1299
  const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
1334
1300
  const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
1335
1301
  const rawTextFallbacks = collectRawTextFallbacks(node, file);
1302
+ const extensionTagNames = getExtensionTagNames(options);
1336
1303
  if (commentRanges) {
1337
1304
  for (const range of commentRanges) {
1338
1305
  if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
@@ -1342,38 +1309,18 @@ function parseTSDocTags(node, file = "", options) {
1342
1309
  if (!commentText.startsWith("/**")) {
1343
1310
  continue;
1344
1311
  }
1345
- const parser = getParser(options);
1346
- const parserContext = parser.parseRange(
1347
- TextRange.fromStringRange(sourceText, range.pos, range.end)
1348
- );
1349
- const docComment = parserContext.docComment;
1350
- const parsedComment = parseCommentBlock(
1351
- commentText,
1352
- sharedCommentSyntaxOptions(options, range.pos)
1353
- );
1354
- let parsedTagCursor = 0;
1355
- const nextParsedTag = (normalizedTagName) => {
1356
- while (parsedTagCursor < parsedComment.tags.length) {
1357
- const candidate = parsedComment.tags[parsedTagCursor];
1358
- parsedTagCursor += 1;
1359
- if (candidate?.normalizedTagName === normalizedTagName) {
1360
- return candidate;
1361
- }
1362
- }
1363
- return null;
1364
- };
1365
- for (const parsedTag of parsedComment.tags) {
1366
- if (TAGS_REQUIRING_RAW_TEXT.has(parsedTag.normalizedTagName)) {
1367
- rawTextTags.push({ tag: parsedTag, commentText, commentOffset: range.pos });
1368
- }
1369
- }
1370
- for (const block of docComment.customBlocks) {
1371
- const tagName = normalizeConstraintTagName(block.blockTag.tagName.substring(1));
1372
- const parsedTag = nextParsedTag(tagName);
1312
+ const extensions = options?.extensionRegistry?.extensions;
1313
+ const unified = parseUnifiedComment(commentText, {
1314
+ offset: range.pos,
1315
+ extensionTagNames,
1316
+ ...extensions !== void 0 ? { extensions } : {}
1317
+ });
1318
+ for (const tag of unified.tags) {
1319
+ const tagName = tag.normalizedTagName;
1373
1320
  if (tagName === "displayName" || tagName === "format" || tagName === "placeholder") {
1374
- const text2 = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
1321
+ const text2 = tag.resolvedPayloadText;
1375
1322
  if (text2 === "") continue;
1376
- const provenance2 = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
1323
+ const provenance2 = provenanceForParsedTag(tag, sourceFile, file);
1377
1324
  switch (tagName) {
1378
1325
  case "displayName":
1379
1326
  if (!isMemberTargetDisplayName(text2) && displayName === void 0) {
@@ -1398,64 +1345,69 @@ function parseTSDocTags(node, file = "", options) {
1398
1345
  }
1399
1346
  continue;
1400
1347
  }
1401
- if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
1402
- const text = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
1403
- const expectedType = isBuiltinConstraintName(tagName) ? BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
1404
- if (text === "" && expectedType !== "boolean") continue;
1405
- const provenance = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
1406
- const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
1407
- node,
1408
- sourceFile,
1409
- tagName,
1410
- parsedTag,
1411
- provenance,
1412
- supportingDeclarations,
1413
- options
1414
- );
1415
- if (compilerDiagnostics.length > 0) {
1416
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
1348
+ if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) {
1349
+ const fallback = rawTextFallbacks.get(tagName)?.shift();
1350
+ const text2 = choosePreferredPayloadText(tag.resolvedPayloadText, fallback?.text ?? "");
1351
+ if (text2 === "") continue;
1352
+ const provenance2 = provenanceForParsedTag(tag, sourceFile, file);
1353
+ if (tagName === "defaultValue") {
1354
+ annotations.push(parseDefaultValueTagValue(text2, provenance2));
1355
+ continue;
1356
+ }
1357
+ processConstraintTag(
1358
+ tagName,
1359
+ text2,
1360
+ tag,
1361
+ provenance2,
1362
+ node,
1363
+ sourceFile,
1364
+ supportingDeclarations,
1365
+ options,
1366
+ constraints,
1367
+ diagnostics
1368
+ );
1417
1369
  continue;
1418
1370
  }
1419
- const constraintNode = parseConstraintTagValue(
1371
+ const text = tag.resolvedPayloadText;
1372
+ const expectedType = isBuiltinConstraintName(tagName) ? BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
1373
+ if (text === "" && expectedType !== "boolean") continue;
1374
+ const provenance = provenanceForParsedTag(tag, sourceFile, file);
1375
+ processConstraintTag(
1420
1376
  tagName,
1421
1377
  text,
1378
+ tag,
1422
1379
  provenance,
1423
- sharedTagValueOptions(options)
1380
+ node,
1381
+ sourceFile,
1382
+ supportingDeclarations,
1383
+ options,
1384
+ constraints,
1385
+ diagnostics
1424
1386
  );
1425
- if (constraintNode) {
1426
- constraints.push(constraintNode);
1427
- }
1428
1387
  }
1429
- if (docComment.deprecatedBlock !== void 0) {
1430
- const message = extractBlockText(docComment.deprecatedBlock).trim();
1388
+ if (unified.isDeprecated) {
1431
1389
  annotations.push({
1432
1390
  kind: "annotation",
1433
1391
  annotationKind: "deprecated",
1434
- ...message !== "" && { message },
1392
+ ...unified.deprecationMessage !== "" && { message: unified.deprecationMessage },
1435
1393
  provenance: provenanceForComment(range, sourceFile, file, "deprecated")
1436
1394
  });
1437
1395
  }
1438
- {
1439
- const summary = extractPlainText(docComment.summarySection).trim();
1440
- if (summary !== "") {
1441
- annotations.push({
1442
- kind: "annotation",
1443
- annotationKind: "description",
1444
- value: summary,
1445
- provenance: provenanceForComment(range, sourceFile, file, "summary")
1446
- });
1447
- }
1396
+ if (unified.summaryText !== "") {
1397
+ annotations.push({
1398
+ kind: "annotation",
1399
+ annotationKind: "description",
1400
+ value: unified.summaryText,
1401
+ provenance: provenanceForComment(range, sourceFile, file, "summary")
1402
+ });
1448
1403
  }
1449
- if (docComment.remarksBlock !== void 0) {
1450
- const remarksText = extractBlockText(docComment.remarksBlock).trim();
1451
- if (remarksText !== "") {
1452
- annotations.push({
1453
- kind: "annotation",
1454
- annotationKind: "remarks",
1455
- value: remarksText,
1456
- provenance: provenanceForComment(range, sourceFile, file, "remarks")
1457
- });
1458
- }
1404
+ if (unified.remarksText !== "") {
1405
+ annotations.push({
1406
+ kind: "annotation",
1407
+ annotationKind: "remarks",
1408
+ value: unified.remarksText,
1409
+ provenance: provenanceForComment(range, sourceFile, file, "remarks")
1410
+ });
1459
1411
  }
1460
1412
  }
1461
1413
  }
@@ -1475,77 +1427,27 @@ function parseTSDocTags(node, file = "", options) {
1475
1427
  provenance: placeholderProvenance
1476
1428
  });
1477
1429
  }
1478
- if (rawTextTags.length > 0) {
1479
- for (const rawTextTag of rawTextTags) {
1480
- const fallbackQueue = rawTextFallbacks.get(rawTextTag.tag.normalizedTagName);
1481
- const fallback = fallbackQueue?.shift();
1482
- const text = choosePreferredPayloadText(
1483
- getSharedPayloadText(rawTextTag.tag, rawTextTag.commentText, rawTextTag.commentOffset),
1484
- fallback?.text ?? ""
1485
- );
1486
- if (text === "") continue;
1487
- const provenance = provenanceForParsedTag(rawTextTag.tag, sourceFile, file);
1488
- if (rawTextTag.tag.normalizedTagName === "defaultValue") {
1489
- const defaultValueNode = parseDefaultValueTagValue(text, provenance);
1490
- annotations.push(defaultValueNode);
1491
- continue;
1492
- }
1493
- const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
1494
- node,
1495
- sourceFile,
1496
- rawTextTag.tag.normalizedTagName,
1497
- rawTextTag.tag,
1498
- provenance,
1499
- supportingDeclarations,
1500
- options
1501
- );
1502
- if (compilerDiagnostics.length > 0) {
1503
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
1504
- continue;
1505
- }
1506
- const constraintNode = parseConstraintTagValue(
1507
- rawTextTag.tag.normalizedTagName,
1508
- text,
1509
- provenance,
1510
- sharedTagValueOptions(options)
1511
- );
1512
- if (constraintNode) {
1513
- constraints.push(constraintNode);
1514
- }
1515
- }
1516
- }
1517
1430
  for (const [tagName, fallbacks] of rawTextFallbacks) {
1518
1431
  for (const fallback of fallbacks) {
1519
1432
  const text = fallback.text.trim();
1520
1433
  if (text === "") continue;
1521
1434
  const provenance = fallback.provenance;
1522
1435
  if (tagName === "defaultValue") {
1523
- const defaultValueNode = parseDefaultValueTagValue(text, provenance);
1524
- annotations.push(defaultValueNode);
1436
+ annotations.push(parseDefaultValueTagValue(text, provenance));
1525
1437
  continue;
1526
1438
  }
1527
- const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
1528
- node,
1529
- sourceFile,
1439
+ processConstraintTag(
1530
1440
  tagName,
1441
+ text,
1531
1442
  null,
1532
1443
  provenance,
1444
+ node,
1445
+ sourceFile,
1533
1446
  supportingDeclarations,
1534
- options
1535
- );
1536
- if (compilerDiagnostics.length > 0) {
1537
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
1538
- continue;
1539
- }
1540
- const constraintNode = parseConstraintTagValue(
1541
- tagName,
1542
- text,
1543
- provenance,
1544
- sharedTagValueOptions(options)
1447
+ options,
1448
+ constraints,
1449
+ diagnostics
1545
1450
  );
1546
- if (constraintNode) {
1547
- constraints.push(constraintNode);
1548
- }
1549
1451
  }
1550
1452
  }
1551
1453
  const result = { constraints, annotations, diagnostics };
@@ -1563,8 +1465,8 @@ function extractDisplayNameMetadata(node) {
1563
1465
  if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) continue;
1564
1466
  const commentText = sourceText.substring(range.pos, range.end);
1565
1467
  if (!commentText.startsWith("/**")) continue;
1566
- const parsed = parseCommentBlock(commentText);
1567
- for (const tag of parsed.tags) {
1468
+ const unified = parseUnifiedComment(commentText);
1469
+ for (const tag of unified.tags) {
1568
1470
  if (tag.normalizedTagName !== "displayName") {
1569
1471
  continue;
1570
1472
  }
@@ -1583,51 +1485,6 @@ function extractDisplayNameMetadata(node) {
1583
1485
  memberDisplayNames
1584
1486
  };
1585
1487
  }
1586
- function extractBlockText(block) {
1587
- return extractPlainText(block.content);
1588
- }
1589
- function extractPlainText(node) {
1590
- let result = "";
1591
- if (node instanceof DocExcerpt) {
1592
- return node.content.toString();
1593
- }
1594
- if (node instanceof DocPlainText) {
1595
- return node.text;
1596
- }
1597
- if (node instanceof DocSoftBreak) {
1598
- return " ";
1599
- }
1600
- if (typeof node.getChildNodes === "function") {
1601
- for (const child of node.getChildNodes()) {
1602
- result += extractPlainText(child);
1603
- }
1604
- }
1605
- return result;
1606
- }
1607
- function choosePreferredPayloadText(primary, fallback) {
1608
- const preferred = primary.trim();
1609
- const alternate = fallback.trim();
1610
- if (preferred === "") return alternate;
1611
- if (alternate === "") return preferred;
1612
- if (alternate.includes("\n")) return alternate;
1613
- if (alternate.length > preferred.length && alternate.startsWith(preferred)) {
1614
- return alternate;
1615
- }
1616
- return preferred;
1617
- }
1618
- function getSharedPayloadText(tag, commentText, commentOffset) {
1619
- if (tag.payloadSpan === null) {
1620
- return "";
1621
- }
1622
- return sliceCommentSpan(commentText, tag.payloadSpan, {
1623
- offset: commentOffset
1624
- }).trim();
1625
- }
1626
- function getBestBlockPayloadText(tag, commentText, commentOffset, block) {
1627
- const sharedText = tag === null ? "" : getSharedPayloadText(tag, commentText, commentOffset);
1628
- const blockText = extractBlockText(block).replace(/\s+/g, " ").trim();
1629
- return choosePreferredPayloadText(sharedText, blockText);
1630
- }
1631
1488
  function collectRawTextFallbacks(node, file) {
1632
1489
  const fallbacks = /* @__PURE__ */ new Map();
1633
1490
  for (const tag of ts.getJSDocTags(node)) {
@@ -2125,7 +1982,7 @@ function getLeadingParsedTags(node) {
2125
1982
  if (!commentText.startsWith("/**")) {
2126
1983
  continue;
2127
1984
  }
2128
- parsedTags.push(...parseCommentBlock2(commentText, { offset: range.pos }).tags);
1985
+ parsedTags.push(...parseCommentBlock(commentText, { offset: range.pos }).tags);
2129
1986
  }
2130
1987
  return parsedTags;
2131
1988
  }
@@ -3277,7 +3134,7 @@ function typeNodeContainsReference(type, targetName) {
3277
3134
  }
3278
3135
  }
3279
3136
  function shouldEmitResolvedObjectProperty(property, declaration) {
3280
- if (property.name.startsWith("__@")) {
3137
+ if (property.name.startsWith("__")) {
3281
3138
  return false;
3282
3139
  }
3283
3140
  if (declaration !== void 0 && "name" in declaration && declaration.name !== void 0) {
@@ -4948,6 +4805,150 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
4948
4805
  }
4949
4806
  }
4950
4807
 
4808
+ // src/extensions/registry.ts
4809
+ import {
4810
+ BUILTIN_CONSTRAINT_DEFINITIONS as BUILTIN_CONSTRAINT_DEFINITIONS2,
4811
+ normalizeConstraintTagName as normalizeConstraintTagName2
4812
+ } from "@formspec/core/internals";
4813
+ import {
4814
+ getTagDefinition as getTagDefinition2,
4815
+ normalizeFormSpecTagName as normalizeFormSpecTagName2
4816
+ } from "@formspec/analysis/internal";
4817
+ var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
4818
+ function buildConstraintTagSources(extensions) {
4819
+ return extensions.map((extension) => ({
4820
+ extensionId: extension.extensionId,
4821
+ ...extension.constraintTags !== void 0 ? {
4822
+ constraintTags: extension.constraintTags.map((tag) => ({
4823
+ tagName: normalizeFormSpecTagName2(tag.tagName)
4824
+ }))
4825
+ } : {}
4826
+ }));
4827
+ }
4828
+ function createExtensionRegistry(extensions) {
4829
+ const reservedTagSources = buildConstraintTagSources(extensions);
4830
+ const typeMap = /* @__PURE__ */ new Map();
4831
+ const typeNameMap = /* @__PURE__ */ new Map();
4832
+ const constraintMap = /* @__PURE__ */ new Map();
4833
+ const constraintTagMap = /* @__PURE__ */ new Map();
4834
+ const builtinBroadeningMap = /* @__PURE__ */ new Map();
4835
+ const annotationMap = /* @__PURE__ */ new Map();
4836
+ const metadataSlotMap = /* @__PURE__ */ new Map();
4837
+ const metadataTagMap = /* @__PURE__ */ new Map();
4838
+ for (const ext of extensions) {
4839
+ if (ext.types !== void 0) {
4840
+ for (const type of ext.types) {
4841
+ const qualifiedId = `${ext.extensionId}/${type.typeName}`;
4842
+ if (typeMap.has(qualifiedId)) {
4843
+ throw new Error(`Duplicate custom type ID: "${qualifiedId}"`);
4844
+ }
4845
+ typeMap.set(qualifiedId, type);
4846
+ for (const sourceTypeName of type.tsTypeNames ?? [type.typeName]) {
4847
+ if (typeNameMap.has(sourceTypeName)) {
4848
+ throw new Error(`Duplicate custom type source name: "${sourceTypeName}"`);
4849
+ }
4850
+ typeNameMap.set(sourceTypeName, {
4851
+ extensionId: ext.extensionId,
4852
+ registration: type
4853
+ });
4854
+ }
4855
+ if (type.builtinConstraintBroadenings !== void 0) {
4856
+ for (const broadening of type.builtinConstraintBroadenings) {
4857
+ const key = `${qualifiedId}:${broadening.tagName}`;
4858
+ if (builtinBroadeningMap.has(key)) {
4859
+ throw new Error(`Duplicate built-in constraint broadening: "${key}"`);
4860
+ }
4861
+ builtinBroadeningMap.set(key, {
4862
+ extensionId: ext.extensionId,
4863
+ registration: broadening
4864
+ });
4865
+ }
4866
+ }
4867
+ }
4868
+ }
4869
+ if (ext.constraints !== void 0) {
4870
+ for (const constraint of ext.constraints) {
4871
+ const qualifiedId = `${ext.extensionId}/${constraint.constraintName}`;
4872
+ if (constraintMap.has(qualifiedId)) {
4873
+ throw new Error(`Duplicate custom constraint ID: "${qualifiedId}"`);
4874
+ }
4875
+ constraintMap.set(qualifiedId, constraint);
4876
+ }
4877
+ }
4878
+ if (ext.constraintTags !== void 0) {
4879
+ for (const tag of ext.constraintTags) {
4880
+ const canonicalTagName = normalizeFormSpecTagName2(tag.tagName);
4881
+ if (constraintTagMap.has(canonicalTagName)) {
4882
+ throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
4883
+ }
4884
+ constraintTagMap.set(canonicalTagName, {
4885
+ extensionId: ext.extensionId,
4886
+ registration: tag
4887
+ });
4888
+ }
4889
+ }
4890
+ if (ext.annotations !== void 0) {
4891
+ for (const annotation of ext.annotations) {
4892
+ const qualifiedId = `${ext.extensionId}/${annotation.annotationName}`;
4893
+ if (annotationMap.has(qualifiedId)) {
4894
+ throw new Error(`Duplicate custom annotation ID: "${qualifiedId}"`);
4895
+ }
4896
+ annotationMap.set(qualifiedId, annotation);
4897
+ }
4898
+ }
4899
+ if (ext.metadataSlots !== void 0) {
4900
+ for (const slot of ext.metadataSlots) {
4901
+ if (metadataSlotMap.has(slot.slotId)) {
4902
+ throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
4903
+ }
4904
+ metadataSlotMap.set(slot.slotId, true);
4905
+ const canonicalTagName = normalizeFormSpecTagName2(slot.tagName);
4906
+ if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
4907
+ throw new Error(
4908
+ `Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
4909
+ );
4910
+ }
4911
+ if (metadataTagMap.has(canonicalTagName)) {
4912
+ throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
4913
+ }
4914
+ if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
4915
+ throw new Error(
4916
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
4917
+ );
4918
+ }
4919
+ if (constraintTagMap.has(canonicalTagName)) {
4920
+ throw new Error(
4921
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
4922
+ );
4923
+ }
4924
+ if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS2, normalizeConstraintTagName2(canonicalTagName))) {
4925
+ throw new Error(
4926
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName2(canonicalTagName)}".`
4927
+ );
4928
+ }
4929
+ const existingTag = getTagDefinition2(canonicalTagName, reservedTagSources);
4930
+ if (existingTag !== null) {
4931
+ throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
4932
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
4933
+ ) : new Error(
4934
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
4935
+ );
4936
+ }
4937
+ metadataTagMap.set(canonicalTagName, true);
4938
+ }
4939
+ }
4940
+ }
4941
+ return {
4942
+ extensions,
4943
+ findType: (typeId) => typeMap.get(typeId),
4944
+ findTypeByName: (typeName) => typeNameMap.get(typeName),
4945
+ findConstraint: (constraintId) => constraintMap.get(constraintId),
4946
+ findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName2(tagName)),
4947
+ findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
4948
+ findAnnotation: (annotationId) => annotationMap.get(annotationId)
4949
+ };
4950
+ }
4951
+
4951
4952
  // src/ui-schema/schema.ts
4952
4953
  import { z } from "zod";
4953
4954
  var jsonPointerSchema = z.string();
@@ -5336,150 +5337,6 @@ function formatLocation(location) {
5336
5337
  return `${location.file}:${String(location.line)}:${String(location.column)}`;
5337
5338
  }
5338
5339
 
5339
- // src/extensions/registry.ts
5340
- import {
5341
- BUILTIN_CONSTRAINT_DEFINITIONS as BUILTIN_CONSTRAINT_DEFINITIONS2,
5342
- normalizeConstraintTagName as normalizeConstraintTagName2
5343
- } from "@formspec/core/internals";
5344
- import {
5345
- getTagDefinition as getTagDefinition2,
5346
- normalizeFormSpecTagName as normalizeFormSpecTagName2
5347
- } from "@formspec/analysis/internal";
5348
- var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
5349
- function buildConstraintTagSources(extensions) {
5350
- return extensions.map((extension) => ({
5351
- extensionId: extension.extensionId,
5352
- ...extension.constraintTags !== void 0 ? {
5353
- constraintTags: extension.constraintTags.map((tag) => ({
5354
- tagName: normalizeFormSpecTagName2(tag.tagName)
5355
- }))
5356
- } : {}
5357
- }));
5358
- }
5359
- function createExtensionRegistry(extensions) {
5360
- const reservedTagSources = buildConstraintTagSources(extensions);
5361
- const typeMap = /* @__PURE__ */ new Map();
5362
- const typeNameMap = /* @__PURE__ */ new Map();
5363
- const constraintMap = /* @__PURE__ */ new Map();
5364
- const constraintTagMap = /* @__PURE__ */ new Map();
5365
- const builtinBroadeningMap = /* @__PURE__ */ new Map();
5366
- const annotationMap = /* @__PURE__ */ new Map();
5367
- const metadataSlotMap = /* @__PURE__ */ new Map();
5368
- const metadataTagMap = /* @__PURE__ */ new Map();
5369
- for (const ext of extensions) {
5370
- if (ext.types !== void 0) {
5371
- for (const type of ext.types) {
5372
- const qualifiedId = `${ext.extensionId}/${type.typeName}`;
5373
- if (typeMap.has(qualifiedId)) {
5374
- throw new Error(`Duplicate custom type ID: "${qualifiedId}"`);
5375
- }
5376
- typeMap.set(qualifiedId, type);
5377
- for (const sourceTypeName of type.tsTypeNames ?? [type.typeName]) {
5378
- if (typeNameMap.has(sourceTypeName)) {
5379
- throw new Error(`Duplicate custom type source name: "${sourceTypeName}"`);
5380
- }
5381
- typeNameMap.set(sourceTypeName, {
5382
- extensionId: ext.extensionId,
5383
- registration: type
5384
- });
5385
- }
5386
- if (type.builtinConstraintBroadenings !== void 0) {
5387
- for (const broadening of type.builtinConstraintBroadenings) {
5388
- const key = `${qualifiedId}:${broadening.tagName}`;
5389
- if (builtinBroadeningMap.has(key)) {
5390
- throw new Error(`Duplicate built-in constraint broadening: "${key}"`);
5391
- }
5392
- builtinBroadeningMap.set(key, {
5393
- extensionId: ext.extensionId,
5394
- registration: broadening
5395
- });
5396
- }
5397
- }
5398
- }
5399
- }
5400
- if (ext.constraints !== void 0) {
5401
- for (const constraint of ext.constraints) {
5402
- const qualifiedId = `${ext.extensionId}/${constraint.constraintName}`;
5403
- if (constraintMap.has(qualifiedId)) {
5404
- throw new Error(`Duplicate custom constraint ID: "${qualifiedId}"`);
5405
- }
5406
- constraintMap.set(qualifiedId, constraint);
5407
- }
5408
- }
5409
- if (ext.constraintTags !== void 0) {
5410
- for (const tag of ext.constraintTags) {
5411
- const canonicalTagName = normalizeFormSpecTagName2(tag.tagName);
5412
- if (constraintTagMap.has(canonicalTagName)) {
5413
- throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
5414
- }
5415
- constraintTagMap.set(canonicalTagName, {
5416
- extensionId: ext.extensionId,
5417
- registration: tag
5418
- });
5419
- }
5420
- }
5421
- if (ext.annotations !== void 0) {
5422
- for (const annotation of ext.annotations) {
5423
- const qualifiedId = `${ext.extensionId}/${annotation.annotationName}`;
5424
- if (annotationMap.has(qualifiedId)) {
5425
- throw new Error(`Duplicate custom annotation ID: "${qualifiedId}"`);
5426
- }
5427
- annotationMap.set(qualifiedId, annotation);
5428
- }
5429
- }
5430
- if (ext.metadataSlots !== void 0) {
5431
- for (const slot of ext.metadataSlots) {
5432
- if (metadataSlotMap.has(slot.slotId)) {
5433
- throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
5434
- }
5435
- metadataSlotMap.set(slot.slotId, true);
5436
- const canonicalTagName = normalizeFormSpecTagName2(slot.tagName);
5437
- if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
5438
- throw new Error(
5439
- `Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
5440
- );
5441
- }
5442
- if (metadataTagMap.has(canonicalTagName)) {
5443
- throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
5444
- }
5445
- if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
5446
- throw new Error(
5447
- `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
5448
- );
5449
- }
5450
- if (constraintTagMap.has(canonicalTagName)) {
5451
- throw new Error(
5452
- `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
5453
- );
5454
- }
5455
- if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS2, normalizeConstraintTagName2(canonicalTagName))) {
5456
- throw new Error(
5457
- `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName2(canonicalTagName)}".`
5458
- );
5459
- }
5460
- const existingTag = getTagDefinition2(canonicalTagName, reservedTagSources);
5461
- if (existingTag !== null) {
5462
- throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
5463
- `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
5464
- ) : new Error(
5465
- `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
5466
- );
5467
- }
5468
- metadataTagMap.set(canonicalTagName, true);
5469
- }
5470
- }
5471
- }
5472
- return {
5473
- extensions,
5474
- findType: (typeId) => typeMap.get(typeId),
5475
- findTypeByName: (typeName) => typeNameMap.get(typeName),
5476
- findConstraint: (constraintId) => constraintMap.get(constraintId),
5477
- findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName2(tagName)),
5478
- findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
5479
- findAnnotation: (annotationId) => annotationMap.get(annotationId)
5480
- };
5481
- }
5482
-
5483
5340
  // src/generators/method-schema.ts
5484
5341
  import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
5485
5342
  function typeToJsonSchema(type, checker, options) {