@formspec/build 0.1.0-alpha.32 → 0.1.0-alpha.34

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/index.cjs CHANGED
@@ -1819,13 +1819,29 @@ var fs = __toESM(require("fs"), 1);
1819
1819
  var path2 = __toESM(require("path"), 1);
1820
1820
 
1821
1821
  // src/extensions/registry.ts
1822
+ var import_internals3 = require("@formspec/core/internals");
1823
+ var import_internal = require("@formspec/analysis/internal");
1824
+ var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
1825
+ function buildConstraintTagSources(extensions) {
1826
+ return extensions.map((extension) => ({
1827
+ extensionId: extension.extensionId,
1828
+ ...extension.constraintTags !== void 0 ? {
1829
+ constraintTags: extension.constraintTags.map((tag) => ({
1830
+ tagName: (0, import_internal.normalizeFormSpecTagName)(tag.tagName)
1831
+ }))
1832
+ } : {}
1833
+ }));
1834
+ }
1822
1835
  function createExtensionRegistry(extensions) {
1836
+ const reservedTagSources = buildConstraintTagSources(extensions);
1823
1837
  const typeMap = /* @__PURE__ */ new Map();
1824
1838
  const typeNameMap = /* @__PURE__ */ new Map();
1825
1839
  const constraintMap = /* @__PURE__ */ new Map();
1826
1840
  const constraintTagMap = /* @__PURE__ */ new Map();
1827
1841
  const builtinBroadeningMap = /* @__PURE__ */ new Map();
1828
1842
  const annotationMap = /* @__PURE__ */ new Map();
1843
+ const metadataSlotMap = /* @__PURE__ */ new Map();
1844
+ const metadataTagMap = /* @__PURE__ */ new Map();
1829
1845
  for (const ext of extensions) {
1830
1846
  if (ext.types !== void 0) {
1831
1847
  for (const type of ext.types) {
@@ -1868,10 +1884,11 @@ function createExtensionRegistry(extensions) {
1868
1884
  }
1869
1885
  if (ext.constraintTags !== void 0) {
1870
1886
  for (const tag of ext.constraintTags) {
1871
- if (constraintTagMap.has(tag.tagName)) {
1872
- throw new Error(`Duplicate custom constraint tag: "@${tag.tagName}"`);
1887
+ const canonicalTagName = (0, import_internal.normalizeFormSpecTagName)(tag.tagName);
1888
+ if (constraintTagMap.has(canonicalTagName)) {
1889
+ throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
1873
1890
  }
1874
- constraintTagMap.set(tag.tagName, {
1891
+ constraintTagMap.set(canonicalTagName, {
1875
1892
  extensionId: ext.extensionId,
1876
1893
  registration: tag
1877
1894
  });
@@ -1886,13 +1903,54 @@ function createExtensionRegistry(extensions) {
1886
1903
  annotationMap.set(qualifiedId, annotation);
1887
1904
  }
1888
1905
  }
1906
+ if (ext.metadataSlots !== void 0) {
1907
+ for (const slot of ext.metadataSlots) {
1908
+ if (metadataSlotMap.has(slot.slotId)) {
1909
+ throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
1910
+ }
1911
+ metadataSlotMap.set(slot.slotId, true);
1912
+ const canonicalTagName = (0, import_internal.normalizeFormSpecTagName)(slot.tagName);
1913
+ if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
1914
+ throw new Error(
1915
+ `Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
1916
+ );
1917
+ }
1918
+ if (metadataTagMap.has(canonicalTagName)) {
1919
+ throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
1920
+ }
1921
+ if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
1922
+ throw new Error(
1923
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
1924
+ );
1925
+ }
1926
+ if (constraintTagMap.has(canonicalTagName)) {
1927
+ throw new Error(
1928
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
1929
+ );
1930
+ }
1931
+ if (Object.hasOwn(import_internals3.BUILTIN_CONSTRAINT_DEFINITIONS, (0, import_internals3.normalizeConstraintTagName)(canonicalTagName))) {
1932
+ throw new Error(
1933
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals3.normalizeConstraintTagName)(canonicalTagName)}".`
1934
+ );
1935
+ }
1936
+ const existingTag = (0, import_internal.getTagDefinition)(canonicalTagName, reservedTagSources);
1937
+ if (existingTag !== null) {
1938
+ throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
1939
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
1940
+ ) : new Error(
1941
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
1942
+ );
1943
+ }
1944
+ metadataTagMap.set(canonicalTagName, true);
1945
+ }
1946
+ }
1889
1947
  }
1890
1948
  return {
1891
1949
  extensions,
1892
1950
  findType: (typeId) => typeMap.get(typeId),
1893
1951
  findTypeByName: (typeName) => typeNameMap.get(typeName),
1894
1952
  findConstraint: (constraintId) => constraintMap.get(constraintId),
1895
- findConstraintTag: (tagName) => constraintTagMap.get(tagName),
1953
+ findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal.normalizeFormSpecTagName)(tagName)),
1896
1954
  findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
1897
1955
  findAnnotation: (annotationId) => annotationMap.get(annotationId)
1898
1956
  };
@@ -1969,21 +2027,21 @@ var path = __toESM(require("path"), 1);
1969
2027
 
1970
2028
  // src/analyzer/class-analyzer.ts
1971
2029
  var ts3 = __toESM(require("typescript"), 1);
1972
- var import_internal2 = require("@formspec/analysis/internal");
2030
+ var import_internal3 = require("@formspec/analysis/internal");
1973
2031
 
1974
2032
  // src/analyzer/jsdoc-constraints.ts
1975
2033
  var ts2 = __toESM(require("typescript"), 1);
1976
2034
 
1977
2035
  // src/analyzer/tsdoc-parser.ts
1978
2036
  var ts = __toESM(require("typescript"), 1);
1979
- var import_internal = require("@formspec/analysis/internal");
2037
+ var import_internal2 = require("@formspec/analysis/internal");
1980
2038
  var import_tsdoc = require("@microsoft/tsdoc");
1981
- var import_internals3 = require("@formspec/core/internals");
1982
2039
  var import_internals4 = require("@formspec/core/internals");
2040
+ var import_internals5 = require("@formspec/core/internals");
1983
2041
  var TAGS_REQUIRING_RAW_TEXT = /* @__PURE__ */ new Set(["pattern", "enumOptions", "defaultValue"]);
1984
2042
  function createFormSpecTSDocConfig(extensionTagNames = []) {
1985
2043
  const config = new import_tsdoc.TSDocConfiguration();
1986
- for (const tagName of Object.keys(import_internals3.BUILTIN_CONSTRAINT_DEFINITIONS)) {
2044
+ for (const tagName of Object.keys(import_internals4.BUILTIN_CONSTRAINT_DEFINITIONS)) {
1987
2045
  config.addTagDefinition(
1988
2046
  new import_tsdoc.TSDocTagDefinition({
1989
2047
  tagName: "@" + tagName,
@@ -1992,7 +2050,7 @@ function createFormSpecTSDocConfig(extensionTagNames = []) {
1992
2050
  })
1993
2051
  );
1994
2052
  }
1995
- for (const tagName of ["displayName", "format", "placeholder"]) {
2053
+ for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
1996
2054
  config.addTagDefinition(
1997
2055
  new import_tsdoc.TSDocTagDefinition({
1998
2056
  tagName: "@" + tagName,
@@ -2026,6 +2084,16 @@ function sharedTagValueOptions(options) {
2026
2084
  };
2027
2085
  }
2028
2086
  var SYNTHETIC_TYPE_FORMAT_FLAGS = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
2087
+ function getExtensionTypeNames(registry) {
2088
+ if (registry === void 0) {
2089
+ return /* @__PURE__ */ new Set();
2090
+ }
2091
+ return new Set(
2092
+ registry.extensions.flatMap(
2093
+ (ext) => (ext.types ?? []).flatMap((t) => t.tsTypeNames ?? [t.typeName])
2094
+ )
2095
+ );
2096
+ }
2029
2097
  function collectImportedNames(sourceFile) {
2030
2098
  const importedNames = /* @__PURE__ */ new Set();
2031
2099
  for (const statement of sourceFile.statements) {
@@ -2065,6 +2133,9 @@ function isNonReferenceIdentifier(node) {
2065
2133
  return false;
2066
2134
  }
2067
2135
  function statementReferencesImportedName(statement, importedNames) {
2136
+ if (importedNames.size === 0) {
2137
+ return false;
2138
+ }
2068
2139
  let referencesImportedName = false;
2069
2140
  const visit = (node) => {
2070
2141
  if (referencesImportedName) {
@@ -2079,14 +2150,17 @@ function statementReferencesImportedName(statement, importedNames) {
2079
2150
  visit(statement);
2080
2151
  return referencesImportedName;
2081
2152
  }
2082
- function buildSupportingDeclarations(sourceFile) {
2153
+ function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
2083
2154
  const importedNames = collectImportedNames(sourceFile);
2155
+ const importedNamesToSkip = new Set(
2156
+ [...importedNames].filter((name) => !extensionTypeNames.has(name))
2157
+ );
2084
2158
  return sourceFile.statements.filter((statement) => {
2085
2159
  if (ts.isImportDeclaration(statement)) return false;
2086
2160
  if (ts.isImportEqualsDeclaration(statement)) return false;
2087
2161
  if (ts.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
2088
2162
  return false;
2089
- if (importedNames.size > 0 && statementReferencesImportedName(statement, importedNames)) {
2163
+ if (statementReferencesImportedName(statement, importedNamesToSkip)) {
2090
2164
  return false;
2091
2165
  }
2092
2166
  return true;
@@ -2132,12 +2206,12 @@ function supportsConstraintCapability(type, checker, capability) {
2132
2206
  if (capability === void 0) {
2133
2207
  return true;
2134
2208
  }
2135
- if ((0, import_internal.hasTypeSemanticCapability)(type, checker, capability)) {
2209
+ if ((0, import_internal2.hasTypeSemanticCapability)(type, checker, capability)) {
2136
2210
  return true;
2137
2211
  }
2138
2212
  if (capability === "string-like") {
2139
2213
  const itemType = getArrayElementType(type, checker);
2140
- return itemType !== null && (0, import_internal.hasTypeSemanticCapability)(itemType, checker, capability);
2214
+ return itemType !== null && (0, import_internal2.hasTypeSemanticCapability)(itemType, checker, capability);
2141
2215
  }
2142
2216
  return false;
2143
2217
  }
@@ -2227,7 +2301,7 @@ function hasBuiltinConstraintBroadening(tagName, options) {
2227
2301
  return broadenedTypeId !== void 0 && options?.extensionRegistry?.findBuiltinConstraintBroadening(broadenedTypeId, tagName) !== void 0;
2228
2302
  }
2229
2303
  function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, parsedTag, provenance, supportingDeclarations, options) {
2230
- if (!(0, import_internals3.isBuiltinConstraintName)(tagName)) {
2304
+ if (!(0, import_internals4.isBuiltinConstraintName)(tagName)) {
2231
2305
  return [];
2232
2306
  }
2233
2307
  const checker = options?.checker;
@@ -2235,11 +2309,11 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2235
2309
  if (checker === void 0 || subjectType === void 0) {
2236
2310
  return [];
2237
2311
  }
2238
- const placement = (0, import_internal.resolveDeclarationPlacement)(node);
2312
+ const placement = (0, import_internal2.resolveDeclarationPlacement)(node);
2239
2313
  if (placement === null) {
2240
2314
  return [];
2241
2315
  }
2242
- const definition = (0, import_internal.getTagDefinition)(tagName, options?.extensionRegistry?.extensions);
2316
+ const definition = (0, import_internal2.getTagDefinition)(tagName, options?.extensionRegistry?.extensions);
2243
2317
  if (definition === null) {
2244
2318
  return [];
2245
2319
  }
@@ -2273,7 +2347,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2273
2347
  )
2274
2348
  ];
2275
2349
  }
2276
- const resolution = (0, import_internal.resolvePathTargetType)(subjectType, checker, target.path.segments);
2350
+ const resolution = (0, import_internal2.resolvePathTargetType)(subjectType, checker, target.path.segments);
2277
2351
  if (resolution.kind === "missing-property") {
2278
2352
  return [
2279
2353
  makeDiagnostic(
@@ -2330,7 +2404,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2330
2404
  const subjectTypeText = checker.typeToString(subjectType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
2331
2405
  const hostType = options?.hostType ?? subjectType;
2332
2406
  const hostTypeText = checker.typeToString(hostType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
2333
- const result = (0, import_internal.checkSyntheticTagApplication)({
2407
+ const result = (0, import_internal2.checkSyntheticTagApplication)({
2334
2408
  tagName,
2335
2409
  placement,
2336
2410
  hostType: hostTypeText,
@@ -2343,6 +2417,14 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2343
2417
  extensionId: extension.extensionId,
2344
2418
  ...extension.constraintTags !== void 0 ? {
2345
2419
  constraintTags: extension.constraintTags.map((tag) => ({ tagName: tag.tagName }))
2420
+ } : {},
2421
+ ...extension.metadataSlots !== void 0 ? {
2422
+ metadataSlots: extension.metadataSlots
2423
+ } : {},
2424
+ ...extension.types !== void 0 ? {
2425
+ customTypes: extension.types.map((t) => ({
2426
+ tsTypeNames: t.tsTypeNames ?? [t.typeName]
2427
+ }))
2346
2428
  } : {}
2347
2429
  }))
2348
2430
  } : {}
@@ -2364,7 +2446,10 @@ var parseResultCache = /* @__PURE__ */ new Map();
2364
2446
  function getParser(options) {
2365
2447
  const extensionTagNames = [
2366
2448
  ...options?.extensionRegistry?.extensions.flatMap(
2367
- (extension) => (extension.constraintTags ?? []).map((tag) => tag.tagName)
2449
+ (extension) => (extension.constraintTags ?? []).map((tag) => (0, import_internal2.normalizeFormSpecTagName)(tag.tagName))
2450
+ ) ?? [],
2451
+ ...options?.extensionRegistry?.extensions.flatMap(
2452
+ (extension) => (extension.metadataSlots ?? []).map((slot) => (0, import_internal2.normalizeFormSpecTagName)(slot.tagName))
2368
2453
  ) ?? []
2369
2454
  ].sort();
2370
2455
  const cacheKey = extensionTagNames.join("|");
@@ -2384,7 +2469,16 @@ function getExtensionRegistryCacheKey(registry) {
2384
2469
  (extension) => JSON.stringify({
2385
2470
  extensionId: extension.extensionId,
2386
2471
  typeNames: extension.types?.map((type) => type.typeName) ?? [],
2387
- constraintTags: extension.constraintTags?.map((tag) => tag.tagName) ?? []
2472
+ constraintTags: extension.constraintTags?.map((tag) => (0, import_internal2.normalizeFormSpecTagName)(tag.tagName)) ?? [],
2473
+ metadataSlots: extension.metadataSlots?.map((slot) => ({
2474
+ tagName: (0, import_internal2.normalizeFormSpecTagName)(slot.tagName),
2475
+ declarationKinds: [...slot.declarationKinds].sort(),
2476
+ allowBare: slot.allowBare !== false,
2477
+ qualifiers: (slot.qualifiers ?? []).map((qualifier) => ({
2478
+ qualifier: qualifier.qualifier,
2479
+ ...qualifier.sourceQualifier !== void 0 ? { sourceQualifier: qualifier.sourceQualifier } : {}
2480
+ })).sort((left, right) => left.qualifier.localeCompare(right.qualifier))
2481
+ })) ?? []
2388
2482
  })
2389
2483
  ).join("|");
2390
2484
  }
@@ -2419,7 +2513,8 @@ function parseTSDocTags(node, file = "", options) {
2419
2513
  const rawTextTags = [];
2420
2514
  const sourceFile = node.getSourceFile();
2421
2515
  const sourceText = sourceFile.getFullText();
2422
- const supportingDeclarations = buildSupportingDeclarations(sourceFile);
2516
+ const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
2517
+ const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
2423
2518
  const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
2424
2519
  const rawTextFallbacks = collectRawTextFallbacks(node, file);
2425
2520
  if (commentRanges) {
@@ -2436,7 +2531,7 @@ function parseTSDocTags(node, file = "", options) {
2436
2531
  import_tsdoc.TextRange.fromStringRange(sourceText, range.pos, range.end)
2437
2532
  );
2438
2533
  const docComment = parserContext.docComment;
2439
- const parsedComment = (0, import_internal.parseCommentBlock)(
2534
+ const parsedComment = (0, import_internal2.parseCommentBlock)(
2440
2535
  commentText,
2441
2536
  sharedCommentSyntaxOptions(options, range.pos)
2442
2537
  );
@@ -2457,7 +2552,7 @@ function parseTSDocTags(node, file = "", options) {
2457
2552
  }
2458
2553
  }
2459
2554
  for (const block of docComment.customBlocks) {
2460
- const tagName = (0, import_internals3.normalizeConstraintTagName)(block.blockTag.tagName.substring(1));
2555
+ const tagName = (0, import_internals4.normalizeConstraintTagName)(block.blockTag.tagName.substring(1));
2461
2556
  const parsedTag = nextParsedTag(tagName);
2462
2557
  if (tagName === "displayName" || tagName === "format" || tagName === "placeholder") {
2463
2558
  const text2 = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
@@ -2489,7 +2584,7 @@ function parseTSDocTags(node, file = "", options) {
2489
2584
  }
2490
2585
  if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2491
2586
  const text = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
2492
- const expectedType = (0, import_internals3.isBuiltinConstraintName)(tagName) ? import_internals3.BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
2587
+ const expectedType = (0, import_internals4.isBuiltinConstraintName)(tagName) ? import_internals4.BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
2493
2588
  if (text === "" && expectedType !== "boolean") continue;
2494
2589
  const provenance = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
2495
2590
  const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
@@ -2505,7 +2600,7 @@ function parseTSDocTags(node, file = "", options) {
2505
2600
  diagnostics.push(...compilerDiagnostics);
2506
2601
  continue;
2507
2602
  }
2508
- const constraintNode = (0, import_internal.parseConstraintTagValue)(
2603
+ const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2509
2604
  tagName,
2510
2605
  text,
2511
2606
  provenance,
@@ -2575,7 +2670,7 @@ function parseTSDocTags(node, file = "", options) {
2575
2670
  if (text === "") continue;
2576
2671
  const provenance = provenanceForParsedTag(rawTextTag.tag, sourceFile, file);
2577
2672
  if (rawTextTag.tag.normalizedTagName === "defaultValue") {
2578
- const defaultValueNode = (0, import_internal.parseDefaultValueTagValue)(text, provenance);
2673
+ const defaultValueNode = (0, import_internal2.parseDefaultValueTagValue)(text, provenance);
2579
2674
  annotations.push(defaultValueNode);
2580
2675
  continue;
2581
2676
  }
@@ -2592,7 +2687,7 @@ function parseTSDocTags(node, file = "", options) {
2592
2687
  diagnostics.push(...compilerDiagnostics);
2593
2688
  continue;
2594
2689
  }
2595
- const constraintNode = (0, import_internal.parseConstraintTagValue)(
2690
+ const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2596
2691
  rawTextTag.tag.normalizedTagName,
2597
2692
  text,
2598
2693
  provenance,
@@ -2609,7 +2704,7 @@ function parseTSDocTags(node, file = "", options) {
2609
2704
  if (text === "") continue;
2610
2705
  const provenance = fallback.provenance;
2611
2706
  if (tagName === "defaultValue") {
2612
- const defaultValueNode = (0, import_internal.parseDefaultValueTagValue)(text, provenance);
2707
+ const defaultValueNode = (0, import_internal2.parseDefaultValueTagValue)(text, provenance);
2613
2708
  annotations.push(defaultValueNode);
2614
2709
  continue;
2615
2710
  }
@@ -2626,7 +2721,7 @@ function parseTSDocTags(node, file = "", options) {
2626
2721
  diagnostics.push(...compilerDiagnostics);
2627
2722
  continue;
2628
2723
  }
2629
- const constraintNode = (0, import_internal.parseConstraintTagValue)(
2724
+ const constraintNode = (0, import_internal2.parseConstraintTagValue)(
2630
2725
  tagName,
2631
2726
  text,
2632
2727
  provenance,
@@ -2652,7 +2747,7 @@ function extractDisplayNameMetadata(node) {
2652
2747
  if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) continue;
2653
2748
  const commentText = sourceText.substring(range.pos, range.end);
2654
2749
  if (!commentText.startsWith("/**")) continue;
2655
- const parsed = (0, import_internal.parseCommentBlock)(commentText);
2750
+ const parsed = (0, import_internal2.parseCommentBlock)(commentText);
2656
2751
  for (const tag of parsed.tags) {
2657
2752
  if (tag.normalizedTagName !== "displayName") {
2658
2753
  continue;
@@ -2708,7 +2803,7 @@ function getSharedPayloadText(tag, commentText, commentOffset) {
2708
2803
  if (tag.payloadSpan === null) {
2709
2804
  return "";
2710
2805
  }
2711
- return (0, import_internal.sliceCommentSpan)(commentText, tag.payloadSpan, {
2806
+ return (0, import_internal2.sliceCommentSpan)(commentText, tag.payloadSpan, {
2712
2807
  offset: commentOffset
2713
2808
  }).trim();
2714
2809
  }
@@ -2720,7 +2815,7 @@ function getBestBlockPayloadText(tag, commentText, commentOffset, block) {
2720
2815
  function collectRawTextFallbacks(node, file) {
2721
2816
  const fallbacks = /* @__PURE__ */ new Map();
2722
2817
  for (const tag of ts.getJSDocTags(node)) {
2723
- const tagName = (0, import_internals3.normalizeConstraintTagName)(tag.tagName.text);
2818
+ const tagName = (0, import_internals4.normalizeConstraintTagName)(tag.tagName.text);
2724
2819
  if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2725
2820
  const commentText = getTagCommentText(tag)?.trim() ?? "";
2726
2821
  if (commentText === "") continue;
@@ -2734,7 +2829,7 @@ function collectRawTextFallbacks(node, file) {
2734
2829
  return fallbacks;
2735
2830
  }
2736
2831
  function isMemberTargetDisplayName(text) {
2737
- return (0, import_internal.parseTagSyntax)("displayName", text).target !== null;
2832
+ return (0, import_internal2.parseTagSyntax)("displayName", text).target !== null;
2738
2833
  }
2739
2834
  function provenanceForComment(range, sourceFile, file, tagName) {
2740
2835
  const { line, character } = sourceFile.getLineAndCharacterOfPosition(range.pos);
@@ -2827,6 +2922,9 @@ function extractDefaultValueAnnotation(initializer, file = "") {
2827
2922
  function isObjectType(type) {
2828
2923
  return !!(type.flags & ts3.TypeFlags.Object);
2829
2924
  }
2925
+ function isIntersectionType(type) {
2926
+ return !!(type.flags & ts3.TypeFlags.Intersection);
2927
+ }
2830
2928
  function isTypeReference(type) {
2831
2929
  return !!(type.flags & ts3.TypeFlags.Object) && !!(type.objectFlags & ts3.ObjectFlags.Reference);
2832
2930
  }
@@ -2847,76 +2945,51 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
2847
2945
  ...hostType !== void 0 && { hostType }
2848
2946
  };
2849
2947
  }
2850
- function makeExplicitScalarMetadata(value) {
2851
- return value === void 0 || value === "" ? void 0 : { value, source: "explicit" };
2852
- }
2853
- function extractExplicitMetadata(node) {
2854
- let apiName;
2855
- let displayName;
2856
- let apiNamePlural;
2857
- let displayNamePlural;
2858
- for (const tag of getLeadingParsedTags(node)) {
2859
- const value = tag.argumentText.trim();
2860
- if (value === "") {
2861
- continue;
2862
- }
2863
- if (tag.normalizedTagName === "apiName") {
2864
- if (tag.target === null) {
2865
- apiName ??= value;
2866
- } else if (tag.target.kind === "variant") {
2867
- if (tag.target.rawText === "singular") {
2868
- apiName ??= value;
2869
- } else if (tag.target.rawText === "plural") {
2870
- apiNamePlural ??= value;
2871
- }
2872
- }
2873
- continue;
2874
- }
2875
- if (tag.normalizedTagName === "displayName") {
2876
- if (tag.target === null) {
2877
- displayName ??= value;
2878
- } else if (tag.target.kind === "variant") {
2879
- if (tag.target.rawText === "singular") {
2880
- displayName ??= value;
2881
- } else if (tag.target.rawText === "plural") {
2882
- displayNamePlural ??= value;
2883
- }
2884
- }
2885
- }
2886
- }
2887
- const resolvedApiName = makeExplicitScalarMetadata(apiName);
2888
- const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
2889
- const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
2890
- const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
2891
- const metadata = {
2892
- ...resolvedApiName !== void 0 && { apiName: resolvedApiName },
2893
- ...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
2894
- ...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
2895
- ...resolvedDisplayNamePlural !== void 0 && {
2896
- displayNamePlural: resolvedDisplayNamePlural
2897
- }
2948
+ function createAnalyzerMetadataPolicy(input, discriminator) {
2949
+ return {
2950
+ raw: input,
2951
+ normalized: normalizeMetadataPolicy(input),
2952
+ discriminator
2898
2953
  };
2899
- return Object.keys(metadata).length === 0 ? void 0 : metadata;
2900
2954
  }
2901
- function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
2902
- const explicit = extractExplicitMetadata(node);
2903
- return resolveMetadata(
2904
- {
2905
- ...explicit?.apiName !== void 0 && { apiName: explicit.apiName.value },
2906
- ...explicit?.displayName !== void 0 && { displayName: explicit.displayName.value },
2907
- ...explicit?.apiNamePlural !== void 0 && {
2908
- apiNamePlural: explicit.apiNamePlural.value
2909
- },
2910
- ...explicit?.displayNamePlural !== void 0 && {
2911
- displayNamePlural: explicit.displayNamePlural.value
2912
- }
2913
- },
2914
- getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
2915
- makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
2955
+ function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
2956
+ const analysis = (0, import_internal3.analyzeMetadataForNodeWithChecker)({
2957
+ checker,
2958
+ node,
2959
+ logicalName,
2960
+ metadata: metadataPolicy.raw,
2961
+ extensions: extensionRegistry?.extensions,
2962
+ ...buildContext !== void 0 && { buildContext }
2963
+ });
2964
+ const resolvedMetadata = analysis?.resolvedMetadata;
2965
+ const declarationPolicy = getDeclarationMetadataPolicy(
2966
+ metadataPolicy.normalized,
2967
+ declarationKind
2916
2968
  );
2969
+ if (resolvedMetadata?.apiName === void 0 && declarationPolicy.apiName.mode === "require-explicit") {
2970
+ throw new Error(
2971
+ `Metadata policy requires explicit apiName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2972
+ );
2973
+ }
2974
+ if (resolvedMetadata?.displayName === void 0 && declarationPolicy.displayName.mode === "require-explicit") {
2975
+ throw new Error(
2976
+ `Metadata policy requires explicit displayName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2977
+ );
2978
+ }
2979
+ if (resolvedMetadata?.apiNamePlural === void 0 && declarationPolicy.apiName.pluralization.mode === "require-explicit") {
2980
+ throw new Error(
2981
+ `Metadata policy requires explicit apiNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2982
+ );
2983
+ }
2984
+ if (resolvedMetadata?.displayNamePlural === void 0 && declarationPolicy.displayName.pluralization.mode === "require-explicit") {
2985
+ throw new Error(
2986
+ `Metadata policy requires explicit displayNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2987
+ );
2988
+ }
2989
+ return resolvedMetadata;
2917
2990
  }
2918
2991
  function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRegistry, metadataPolicy) {
2919
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
2992
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
2920
2993
  const declarationType = checker.getTypeAtLocation(declaration);
2921
2994
  const logicalName = ts3.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
2922
2995
  const docResult = extractJSDocParseResult(
@@ -2924,20 +2997,31 @@ function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRe
2924
2997
  file,
2925
2998
  makeParseOptions(extensionRegistry, void 0, checker, declarationType, declarationType)
2926
2999
  );
2927
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", logicalName, declaration, {
2928
- checker,
3000
+ const metadata = resolveNodeMetadata(
3001
+ normalizedMetadataPolicy,
3002
+ "type",
3003
+ logicalName,
2929
3004
  declaration,
2930
- subjectType: declarationType,
2931
- hostType: declarationType
2932
- });
3005
+ checker,
3006
+ extensionRegistry,
3007
+ {
3008
+ checker,
3009
+ declaration,
3010
+ subjectType: declarationType,
3011
+ hostType: declarationType
3012
+ }
3013
+ );
2933
3014
  return {
2934
3015
  ...metadata !== void 0 && { metadata },
2935
3016
  annotations: docResult.annotations,
2936
3017
  diagnostics: docResult.diagnostics
2937
3018
  };
2938
3019
  }
2939
- function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
2940
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3020
+ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
3021
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
3022
+ metadataPolicy,
3023
+ discriminatorOptions
3024
+ );
2941
3025
  const name = classDecl.name?.text ?? "AnonymousClass";
2942
3026
  const fields = [];
2943
3027
  const fieldLayouts = [];
@@ -2992,12 +3076,20 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2992
3076
  diagnostics,
2993
3077
  normalizedMetadataPolicy
2994
3078
  );
2995
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, classDecl, {
3079
+ const metadata = resolveNodeMetadata(
3080
+ normalizedMetadataPolicy,
3081
+ "type",
3082
+ name,
3083
+ classDecl,
2996
3084
  checker,
2997
- declaration: classDecl,
2998
- subjectType: classType,
2999
- hostType: classType
3000
- });
3085
+ extensionRegistry,
3086
+ {
3087
+ checker,
3088
+ declaration: classDecl,
3089
+ subjectType: classType,
3090
+ hostType: classType
3091
+ }
3092
+ );
3001
3093
  return {
3002
3094
  name,
3003
3095
  ...metadata !== void 0 && { metadata },
@@ -3010,8 +3102,11 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
3010
3102
  staticMethods
3011
3103
  };
3012
3104
  }
3013
- function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
3014
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3105
+ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
3106
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
3107
+ metadataPolicy,
3108
+ discriminatorOptions
3109
+ );
3015
3110
  const name = interfaceDecl.name.text;
3016
3111
  const fields = [];
3017
3112
  const typeRegistry = {};
@@ -3053,12 +3148,20 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
3053
3148
  normalizedMetadataPolicy
3054
3149
  );
3055
3150
  const fieldLayouts = specializedFields.map(() => ({}));
3056
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, interfaceDecl, {
3151
+ const metadata = resolveNodeMetadata(
3152
+ normalizedMetadataPolicy,
3153
+ "type",
3154
+ name,
3155
+ interfaceDecl,
3057
3156
  checker,
3058
- declaration: interfaceDecl,
3059
- subjectType: interfaceType,
3060
- hostType: interfaceType
3061
- });
3157
+ extensionRegistry,
3158
+ {
3159
+ checker,
3160
+ declaration: interfaceDecl,
3161
+ subjectType: interfaceType,
3162
+ hostType: interfaceType
3163
+ }
3164
+ );
3062
3165
  return {
3063
3166
  name,
3064
3167
  ...metadata !== void 0 && { metadata },
@@ -3071,19 +3174,31 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
3071
3174
  staticMethods: []
3072
3175
  };
3073
3176
  }
3074
- function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy) {
3075
- if (!ts3.isTypeLiteralNode(typeAlias.type)) {
3177
+ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
3178
+ const members = getObjectLikeTypeAliasMembers(typeAlias.type);
3179
+ if (members === null) {
3076
3180
  const sourceFile = typeAlias.getSourceFile();
3077
3181
  const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
3078
3182
  const kindDesc = ts3.SyntaxKind[typeAlias.type.kind] ?? "unknown";
3079
3183
  return {
3080
3184
  ok: false,
3081
- error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object type literal (found ${kindDesc})`
3185
+ error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object-like type alias (found ${kindDesc})`
3082
3186
  };
3083
3187
  }
3084
- const typeLiteral = typeAlias.type;
3085
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3188
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
3189
+ metadataPolicy,
3190
+ discriminatorOptions
3191
+ );
3086
3192
  const name = typeAlias.name.text;
3193
+ const duplicatePropertyNames = findDuplicateObjectLikeTypeAliasPropertyNames(members);
3194
+ if (duplicatePropertyNames.length > 0) {
3195
+ const sourceFile = typeAlias.getSourceFile();
3196
+ const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
3197
+ return {
3198
+ ok: false,
3199
+ error: `Type alias "${name}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`
3200
+ };
3201
+ }
3087
3202
  const fields = [];
3088
3203
  const typeRegistry = {};
3089
3204
  const diagnostics = [];
@@ -3096,7 +3211,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3096
3211
  const annotations = [...typeAliasDoc.annotations];
3097
3212
  diagnostics.push(...typeAliasDoc.diagnostics);
3098
3213
  const visiting = /* @__PURE__ */ new Set();
3099
- for (const member of typeLiteral.members) {
3214
+ for (const member of members) {
3100
3215
  if (ts3.isPropertySignature(member)) {
3101
3216
  const fieldNode = analyzeInterfacePropertyToIR(
3102
3217
  member,
@@ -3123,12 +3238,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3123
3238
  diagnostics,
3124
3239
  normalizedMetadataPolicy
3125
3240
  );
3126
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, typeAlias, {
3241
+ const metadata = resolveNodeMetadata(
3242
+ normalizedMetadataPolicy,
3243
+ "type",
3244
+ name,
3245
+ typeAlias,
3127
3246
  checker,
3128
- declaration: typeAlias,
3129
- subjectType: aliasType,
3130
- hostType: aliasType
3131
- });
3247
+ extensionRegistry,
3248
+ {
3249
+ checker,
3250
+ declaration: typeAlias,
3251
+ subjectType: aliasType,
3252
+ hostType: aliasType
3253
+ }
3254
+ );
3132
3255
  return {
3133
3256
  ok: true,
3134
3257
  analysis: {
@@ -3169,7 +3292,7 @@ function getLeadingParsedTags(node) {
3169
3292
  if (!commentText.startsWith("/**")) {
3170
3293
  continue;
3171
3294
  }
3172
- parsedTags.push(...(0, import_internal2.parseCommentBlock)(commentText, { offset: range.pos }).tags);
3295
+ parsedTags.push(...(0, import_internal3.parseCommentBlock)(commentText, { offset: range.pos }).tags);
3173
3296
  }
3174
3297
  return parsedTags;
3175
3298
  }
@@ -3197,15 +3320,43 @@ function isNullishSemanticType(type) {
3197
3320
  }
3198
3321
  return type.isUnion() && type.types.some((member) => isNullishSemanticType(member));
3199
3322
  }
3200
- function isStringLikeSemanticType(type) {
3323
+ function isStringLikeSemanticType(type, checker, seen = /* @__PURE__ */ new Set()) {
3324
+ if (seen.has(type)) {
3325
+ return false;
3326
+ }
3327
+ seen.add(type);
3201
3328
  if (type.flags & ts3.TypeFlags.StringLike) {
3202
3329
  return true;
3203
3330
  }
3204
3331
  if (type.isUnion()) {
3205
- return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member));
3332
+ return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member, checker, seen));
3333
+ }
3334
+ const baseConstraint = checker.getBaseConstraintOfType(type);
3335
+ if (baseConstraint !== void 0 && baseConstraint !== type) {
3336
+ return isStringLikeSemanticType(baseConstraint, checker, seen);
3206
3337
  }
3207
3338
  return false;
3208
3339
  }
3340
+ function getObjectLikeTypeAliasMembers(typeNode) {
3341
+ if (ts3.isParenthesizedTypeNode(typeNode)) {
3342
+ return getObjectLikeTypeAliasMembers(typeNode.type);
3343
+ }
3344
+ if (ts3.isTypeLiteralNode(typeNode)) {
3345
+ return [...typeNode.members];
3346
+ }
3347
+ if (ts3.isIntersectionTypeNode(typeNode)) {
3348
+ const members = [];
3349
+ for (const intersectionMember of typeNode.types) {
3350
+ const resolvedMembers = getObjectLikeTypeAliasMembers(intersectionMember);
3351
+ if (resolvedMembers === null) {
3352
+ return null;
3353
+ }
3354
+ members.push(...resolvedMembers);
3355
+ }
3356
+ return members;
3357
+ }
3358
+ return null;
3359
+ }
3209
3360
  function extractDiscriminatorDirective(node, file, diagnostics) {
3210
3361
  const discriminatorTags = getLeadingParsedTags(node).filter(
3211
3362
  (tag) => tag.normalizedTagName === "discriminator"
@@ -3312,7 +3463,7 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
3312
3463
  );
3313
3464
  return null;
3314
3465
  }
3315
- if (!isStringLikeSemanticType(property.type)) {
3466
+ if (!isStringLikeSemanticType(property.type, checker)) {
3316
3467
  diagnostics.push(
3317
3468
  makeAnalysisDiagnostic(
3318
3469
  "TYPE_MISMATCH",
@@ -3339,8 +3490,8 @@ function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typ
3339
3490
  const localTypeParameter = node.typeParameters?.[typeParameterIndex];
3340
3491
  return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
3341
3492
  }
3342
- function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker, provenance, diagnostics) {
3343
- const propertySymbol = boundType.getProperty(fieldName);
3493
+ function resolveLiteralDiscriminatorPropertyValue(boundType, propertyName, checker, provenance, diagnostics) {
3494
+ const propertySymbol = boundType.getProperty(propertyName);
3344
3495
  if (propertySymbol === void 0) {
3345
3496
  return void 0;
3346
3497
  }
@@ -3371,6 +3522,9 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
3371
3522
  }
3372
3523
  return void 0;
3373
3524
  }
3525
+ function getDiscriminatorIdentityPropertyNames(fieldName) {
3526
+ return fieldName === "object" ? ["object"] : [fieldName, "object"];
3527
+ }
3374
3528
  function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3375
3529
  const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
3376
3530
  if (declaration === null) {
@@ -3381,6 +3535,8 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3381
3535
  "type",
3382
3536
  getDiscriminatorLogicalName(boundType, declaration, checker),
3383
3537
  declaration,
3538
+ checker,
3539
+ void 0,
3384
3540
  {
3385
3541
  checker,
3386
3542
  declaration,
@@ -3389,6 +3545,10 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3389
3545
  );
3390
3546
  return metadata?.apiName;
3391
3547
  }
3548
+ function applyDiscriminatorApiNamePrefix(value, discriminatorOptions) {
3549
+ const prefix = discriminatorOptions?.apiNamePrefix;
3550
+ return prefix === void 0 || prefix === "" ? value : `${prefix}${value}`;
3551
+ }
3392
3552
  function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
3393
3553
  if (seen.has(type)) {
3394
3554
  return null;
@@ -3443,22 +3603,27 @@ function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, di
3443
3603
  return null;
3444
3604
  }
3445
3605
  }
3446
- const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
3447
- boundType,
3448
- fieldName,
3449
- checker,
3450
- provenance,
3451
- diagnostics
3452
- );
3453
- if (literalIdentityValue !== void 0) {
3454
- return literalIdentityValue;
3606
+ for (const identityPropertyName of getDiscriminatorIdentityPropertyNames(fieldName)) {
3607
+ const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
3608
+ boundType,
3609
+ identityPropertyName,
3610
+ checker,
3611
+ provenance,
3612
+ diagnostics
3613
+ );
3614
+ if (literalIdentityValue === null) {
3615
+ return null;
3616
+ }
3617
+ if (literalIdentityValue !== void 0) {
3618
+ return literalIdentityValue;
3619
+ }
3455
3620
  }
3456
3621
  const apiName = resolveDiscriminatorApiName(boundType, checker, metadataPolicy);
3457
3622
  if (apiName?.source === "explicit") {
3458
- return apiName.value;
3623
+ return applyDiscriminatorApiNamePrefix(apiName.value, metadataPolicy.discriminator);
3459
3624
  }
3460
3625
  if (apiName?.source === "inferred") {
3461
- return apiName.value;
3626
+ return applyDiscriminatorApiNamePrefix(apiName.value, metadataPolicy.discriminator);
3462
3627
  }
3463
3628
  diagnostics.push(
3464
3629
  makeAnalysisDiagnostic(
@@ -3521,15 +3686,20 @@ function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
3521
3686
  return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
3522
3687
  }
3523
3688
  function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy, extensionRegistry, diagnostics) {
3524
- const typeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
3525
- if (typeNode === void 0) {
3689
+ const sourceTypeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
3690
+ if (sourceTypeNode === void 0) {
3526
3691
  return [];
3527
3692
  }
3528
- const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);
3529
- if (!ts3.isTypeReferenceNode(resolvedTypeNode) || resolvedTypeNode.typeArguments === void 0) {
3693
+ const unwrapParentheses = (typeNode) => ts3.isParenthesizedTypeNode(typeNode) ? unwrapParentheses(typeNode.type) : typeNode;
3694
+ const directTypeNode = unwrapParentheses(sourceTypeNode);
3695
+ const referenceTypeNode = ts3.isTypeReferenceNode(directTypeNode) ? directTypeNode : (() => {
3696
+ const resolvedTypeNode = resolveAliasedTypeNode(directTypeNode, checker);
3697
+ return ts3.isTypeReferenceNode(resolvedTypeNode) ? resolvedTypeNode : null;
3698
+ })();
3699
+ if (referenceTypeNode?.typeArguments === void 0) {
3530
3700
  return [];
3531
3701
  }
3532
- return resolvedTypeNode.typeArguments.map((argumentNode) => {
3702
+ return referenceTypeNode.typeArguments.map((argumentNode) => {
3533
3703
  const argumentType = checker.getTypeFromTypeNode(argumentNode);
3534
3704
  return {
3535
3705
  tsType: argumentType,
@@ -3617,12 +3787,20 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
3617
3787
  annotations.push(defaultAnnotation);
3618
3788
  }
3619
3789
  ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
3620
- const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
3790
+ const metadata = resolveNodeMetadata(
3791
+ metadataPolicy,
3792
+ "field",
3793
+ name,
3794
+ prop,
3621
3795
  checker,
3622
- declaration: prop,
3623
- subjectType: tsType,
3624
- hostType
3625
- });
3796
+ extensionRegistry,
3797
+ {
3798
+ checker,
3799
+ declaration: prop,
3800
+ subjectType: tsType,
3801
+ hostType
3802
+ }
3803
+ );
3626
3804
  return {
3627
3805
  kind: "field",
3628
3806
  name,
@@ -3635,10 +3813,10 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
3635
3813
  };
3636
3814
  }
3637
3815
  function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
3638
- if (!ts3.isIdentifier(prop.name)) {
3816
+ const name = getAnalyzableObjectLikePropertyName(prop.name);
3817
+ if (name === null) {
3639
3818
  return null;
3640
3819
  }
3641
- const name = prop.name.text;
3642
3820
  const tsType = checker.getTypeAtLocation(prop);
3643
3821
  const optional = prop.questionToken !== void 0;
3644
3822
  const provenance = provenanceForNode(prop, file);
@@ -3669,12 +3847,20 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
3669
3847
  let annotations = [];
3670
3848
  annotations.push(...docResult.annotations);
3671
3849
  ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
3672
- const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
3850
+ const metadata = resolveNodeMetadata(
3851
+ metadataPolicy,
3852
+ "field",
3853
+ name,
3854
+ prop,
3673
3855
  checker,
3674
- declaration: prop,
3675
- subjectType: tsType,
3676
- hostType
3677
- });
3856
+ extensionRegistry,
3857
+ {
3858
+ checker,
3859
+ declaration: prop,
3860
+ subjectType: tsType,
3861
+ hostType
3862
+ }
3863
+ );
3678
3864
  return {
3679
3865
  kind: "field",
3680
3866
  name,
@@ -3686,6 +3872,31 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
3686
3872
  provenance
3687
3873
  };
3688
3874
  }
3875
+ function findDuplicateObjectLikeTypeAliasPropertyNames(members) {
3876
+ const seen = /* @__PURE__ */ new Set();
3877
+ const duplicates = /* @__PURE__ */ new Set();
3878
+ for (const member of members) {
3879
+ if (!ts3.isPropertySignature(member)) {
3880
+ continue;
3881
+ }
3882
+ const name = getAnalyzableObjectLikePropertyName(member.name);
3883
+ if (name === null) {
3884
+ continue;
3885
+ }
3886
+ if (seen.has(name)) {
3887
+ duplicates.add(name);
3888
+ continue;
3889
+ }
3890
+ seen.add(name);
3891
+ }
3892
+ return [...duplicates].sort();
3893
+ }
3894
+ function getAnalyzableObjectLikePropertyName(name) {
3895
+ if (!ts3.isIdentifier(name)) {
3896
+ return null;
3897
+ }
3898
+ return name.text;
3899
+ }
3689
3900
  function applyEnumMemberDisplayNames(type, annotations) {
3690
3901
  if (!annotations.some(
3691
3902
  (annotation) => annotation.annotationKind === "displayName" && annotation.value.trim().startsWith(":")
@@ -3803,7 +4014,7 @@ function getTypeNodeRegistrationName(typeNode) {
3803
4014
  }
3804
4015
  return null;
3805
4016
  }
3806
- function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4017
+ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3807
4018
  const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
3808
4019
  if (customType) {
3809
4020
  return customType;
@@ -3878,6 +4089,23 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3878
4089
  diagnostics
3879
4090
  );
3880
4091
  }
4092
+ if (isIntersectionType(type)) {
4093
+ const sourceTypeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
4094
+ const resolvedSourceTypeNode = sourceTypeNode === void 0 ? void 0 : resolveAliasedTypeNode(sourceTypeNode, checker);
4095
+ if (resolvedSourceTypeNode !== void 0 && getObjectLikeTypeAliasMembers(resolvedSourceTypeNode) !== null) {
4096
+ return resolveObjectType(
4097
+ type,
4098
+ checker,
4099
+ file,
4100
+ typeRegistry,
4101
+ visiting,
4102
+ sourceNode,
4103
+ metadataPolicy,
4104
+ extensionRegistry,
4105
+ diagnostics
4106
+ );
4107
+ }
4108
+ }
3881
4109
  if (isObjectType(type)) {
3882
4110
  return resolveObjectType(
3883
4111
  type,
@@ -3893,7 +4121,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3893
4121
  }
3894
4122
  return { kind: "primitive", primitiveKind: "string" };
3895
4123
  }
3896
- function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4124
+ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3897
4125
  if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
3898
4126
  return null;
3899
4127
  }
@@ -3913,11 +4141,19 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
3913
4141
  file,
3914
4142
  makeParseOptions(extensionRegistry)
3915
4143
  );
3916
- const metadata = resolveNodeMetadata(metadataPolicy, "type", aliasName, aliasDecl, {
4144
+ const metadata = resolveNodeMetadata(
4145
+ metadataPolicy,
4146
+ "type",
4147
+ aliasName,
4148
+ aliasDecl,
3917
4149
  checker,
3918
- declaration: aliasDecl,
3919
- subjectType: aliasType
3920
- });
4150
+ extensionRegistry,
4151
+ {
4152
+ checker,
4153
+ declaration: aliasDecl,
4154
+ subjectType: aliasType
4155
+ }
4156
+ );
3921
4157
  typeRegistry[aliasName] = {
3922
4158
  name: aliasName,
3923
4159
  ...metadata !== void 0 && { metadata },
@@ -3956,7 +4192,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
3956
4192
  const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
3957
4193
  return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
3958
4194
  }
3959
- function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4195
+ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3960
4196
  const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
3961
4197
  if (nestedAliasDecl !== void 0) {
3962
4198
  return resolveAliasedPrimitiveTarget(
@@ -3982,7 +4218,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
3982
4218
  diagnostics
3983
4219
  );
3984
4220
  }
3985
- function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4221
+ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3986
4222
  const typeName = getNamedTypeName(type);
3987
4223
  const namedDecl = getNamedTypeDeclaration(type);
3988
4224
  if (typeName && typeName in typeRegistry) {
@@ -4017,11 +4253,19 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
4017
4253
  return result;
4018
4254
  }
4019
4255
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4020
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", typeName, namedDecl, {
4256
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4257
+ metadataPolicy,
4258
+ "type",
4259
+ typeName,
4260
+ namedDecl,
4021
4261
  checker,
4022
- declaration: namedDecl,
4023
- subjectType: type
4024
- }) : void 0;
4262
+ extensionRegistry,
4263
+ {
4264
+ checker,
4265
+ declaration: namedDecl,
4266
+ subjectType: type
4267
+ }
4268
+ ) : void 0;
4025
4269
  typeRegistry[typeName] = {
4026
4270
  name: typeName,
4027
4271
  ...metadata !== void 0 && { metadata },
@@ -4106,7 +4350,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
4106
4350
  }
4107
4351
  return registerNamed({ kind: "union", members });
4108
4352
  }
4109
- function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4353
+ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4110
4354
  const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
4111
4355
  const elementType = typeArgs?.[0];
4112
4356
  const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
@@ -4123,7 +4367,7 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
4123
4367
  ) : { kind: "primitive", primitiveKind: "string" };
4124
4368
  return { kind: "array", items };
4125
4369
  }
4126
- function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4370
+ function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4127
4371
  if (type.getProperties().length > 0) {
4128
4372
  return null;
4129
4373
  }
@@ -4184,7 +4428,7 @@ function shouldEmitResolvedObjectProperty(property, declaration) {
4184
4428
  }
4185
4429
  return true;
4186
4430
  }
4187
- function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4431
+ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4188
4432
  const collectedDiagnostics = diagnostics ?? [];
4189
4433
  const typeName = getNamedTypeName(type);
4190
4434
  const namedTypeName = typeName ?? void 0;
@@ -4241,7 +4485,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4241
4485
  };
4242
4486
  }
4243
4487
  }
4244
- const recordNode = tryResolveRecordType(
4488
+ const recordNode = isObjectType(type) ? tryResolveRecordType(
4245
4489
  type,
4246
4490
  checker,
4247
4491
  file,
@@ -4250,7 +4494,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4250
4494
  metadataPolicy,
4251
4495
  extensionRegistry,
4252
4496
  collectedDiagnostics
4253
- );
4497
+ ) : null;
4254
4498
  if (recordNode) {
4255
4499
  visiting.delete(type);
4256
4500
  if (registryTypeName !== void 0 && shouldRegisterNamedType) {
@@ -4260,11 +4504,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4260
4504
  return recordNode;
4261
4505
  }
4262
4506
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4263
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
4507
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4508
+ metadataPolicy,
4509
+ "type",
4510
+ registryTypeName,
4511
+ namedDecl,
4264
4512
  checker,
4265
- declaration: namedDecl,
4266
- subjectType: type
4267
- }) : void 0;
4513
+ extensionRegistry,
4514
+ {
4515
+ checker,
4516
+ declaration: namedDecl,
4517
+ subjectType: type
4518
+ }
4519
+ ) : void 0;
4268
4520
  typeRegistry[registryTypeName] = {
4269
4521
  name: registryTypeName,
4270
4522
  ...metadata !== void 0 && { metadata },
@@ -4360,11 +4612,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4360
4612
  };
4361
4613
  if (registryTypeName !== void 0 && shouldRegisterNamedType) {
4362
4614
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4363
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
4615
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4616
+ metadataPolicy,
4617
+ "type",
4618
+ registryTypeName,
4619
+ namedDecl,
4364
4620
  checker,
4365
- declaration: namedDecl,
4366
- subjectType: type
4367
- }) : void 0;
4621
+ extensionRegistry,
4622
+ {
4623
+ checker,
4624
+ declaration: namedDecl,
4625
+ subjectType: type
4626
+ }
4627
+ ) : void 0;
4368
4628
  typeRegistry[registryTypeName] = {
4369
4629
  name: registryTypeName,
4370
4630
  ...metadata !== void 0 && { metadata },
@@ -4431,9 +4691,10 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
4431
4691
  );
4432
4692
  }
4433
4693
  const typeAliasDecl = declarations.find(ts3.isTypeAliasDeclaration);
4434
- if (typeAliasDecl && ts3.isTypeLiteralNode(typeAliasDecl.type)) {
4694
+ const typeAliasMembers = typeAliasDecl === void 0 ? null : getObjectLikeTypeAliasMembers(typeAliasDecl.type);
4695
+ if (typeAliasDecl && typeAliasMembers !== null) {
4435
4696
  return buildFieldNodeInfoMap(
4436
- typeAliasDecl.type.members,
4697
+ typeAliasMembers,
4437
4698
  checker,
4438
4699
  file,
4439
4700
  typeRegistry,
@@ -4724,17 +4985,18 @@ function findInterfaceByName(sourceFile, interfaceName) {
4724
4985
  function findTypeAliasByName(sourceFile, aliasName) {
4725
4986
  return findNodeByName(sourceFile, aliasName, ts4.isTypeAliasDeclaration, (n) => n.name.text);
4726
4987
  }
4727
- function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPolicy) {
4988
+ function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
4728
4989
  const ctx = createProgramContext(filePath);
4729
4990
  return analyzeNamedTypeToIRFromProgramContext(
4730
4991
  ctx,
4731
4992
  filePath,
4732
4993
  typeName,
4733
4994
  extensionRegistry,
4734
- metadataPolicy
4995
+ metadataPolicy,
4996
+ discriminatorOptions
4735
4997
  );
4736
4998
  }
4737
- function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy) {
4999
+ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
4738
5000
  const analysisFilePath = path.resolve(filePath);
4739
5001
  const classDecl = findClassByName(ctx.sourceFile, typeName);
4740
5002
  if (classDecl !== null) {
@@ -4743,7 +5005,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4743
5005
  ctx.checker,
4744
5006
  analysisFilePath,
4745
5007
  extensionRegistry,
4746
- metadataPolicy
5008
+ metadataPolicy,
5009
+ discriminatorOptions
4747
5010
  );
4748
5011
  }
4749
5012
  const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
@@ -4753,7 +5016,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4753
5016
  ctx.checker,
4754
5017
  analysisFilePath,
4755
5018
  extensionRegistry,
4756
- metadataPolicy
5019
+ metadataPolicy,
5020
+ discriminatorOptions
4757
5021
  );
4758
5022
  }
4759
5023
  const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
@@ -4763,7 +5027,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4763
5027
  ctx.checker,
4764
5028
  analysisFilePath,
4765
5029
  extensionRegistry,
4766
- metadataPolicy
5030
+ metadataPolicy,
5031
+ discriminatorOptions
4767
5032
  );
4768
5033
  if (result.ok) {
4769
5034
  return result.analysis;
@@ -4776,9 +5041,9 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4776
5041
  }
4777
5042
 
4778
5043
  // src/validate/constraint-validator.ts
4779
- var import_internal3 = require("@formspec/analysis/internal");
5044
+ var import_internal4 = require("@formspec/analysis/internal");
4780
5045
  function validateFieldNode(ctx, field) {
4781
- const analysis = (0, import_internal3.analyzeConstraintTargets)(
5046
+ const analysis = (0, import_internal4.analyzeConstraintTargets)(
4782
5047
  field.name,
4783
5048
  field.type,
4784
5049
  field.constraints,
@@ -4796,7 +5061,7 @@ function validateFieldNode(ctx, field) {
4796
5061
  }
4797
5062
  function validateObjectProperty(ctx, parentName, property) {
4798
5063
  const qualifiedName = `${parentName}.${property.name}`;
4799
- const analysis = (0, import_internal3.analyzeConstraintTargets)(
5064
+ const analysis = (0, import_internal4.analyzeConstraintTargets)(
4800
5065
  qualifiedName,
4801
5066
  property.type,
4802
5067
  property.constraints,
@@ -4898,7 +5163,8 @@ function generateSchemasFromClass(options) {
4898
5163
  ctx.checker,
4899
5164
  options.filePath,
4900
5165
  options.extensionRegistry,
4901
- options.metadata
5166
+ options.metadata,
5167
+ options.discriminator
4902
5168
  );
4903
5169
  return generateClassSchemas(
4904
5170
  analysis,
@@ -4924,7 +5190,8 @@ function generateSchemasFromProgram(options) {
4924
5190
  options.filePath,
4925
5191
  options.typeName,
4926
5192
  options.extensionRegistry,
4927
- options.metadata
5193
+ options.metadata,
5194
+ options.discriminator
4928
5195
  );
4929
5196
  return generateClassSchemas(
4930
5197
  analysis,
@@ -4972,7 +5239,7 @@ function resolveModuleExportDeclaration(context, exportName = "default") {
4972
5239
 
4973
5240
  // src/generators/discovered-schema.ts
4974
5241
  var ts7 = __toESM(require("typescript"), 1);
4975
- var import_internals5 = require("@formspec/core/internals");
5242
+ var import_internals6 = require("@formspec/core/internals");
4976
5243
  function toDiscoveredTypeSchemas(result) {
4977
5244
  return result;
4978
5245
  }
@@ -5084,7 +5351,7 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
5084
5351
  {
5085
5352
  kind: "form-ir",
5086
5353
  name: root.name,
5087
- irVersion: import_internals5.IR_VERSION,
5354
+ irVersion: import_internals6.IR_VERSION,
5088
5355
  elements: [syntheticField],
5089
5356
  ...root.metadata !== void 0 && { metadata: root.metadata },
5090
5357
  ...root.annotations !== void 0 && root.annotations.length > 0 && { rootAnnotations: root.annotations },
@@ -5143,7 +5410,7 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
5143
5410
  typeRegistry,
5144
5411
  /* @__PURE__ */ new Set(),
5145
5412
  options.sourceNode,
5146
- normalizeMetadataPolicy(options.metadata),
5413
+ createAnalyzerMetadataPolicy(options.metadata, options.discriminator),
5147
5414
  options.extensionRegistry,
5148
5415
  diagnostics
5149
5416
  );
@@ -5192,7 +5459,8 @@ function generateSchemasFromDeclaration(options) {
5192
5459
  options.context.checker,
5193
5460
  filePath,
5194
5461
  options.extensionRegistry,
5195
- options.metadata
5462
+ options.metadata,
5463
+ options.discriminator
5196
5464
  ),
5197
5465
  filePath,
5198
5466
  options
@@ -5205,7 +5473,8 @@ function generateSchemasFromDeclaration(options) {
5205
5473
  options.context.checker,
5206
5474
  filePath,
5207
5475
  options.extensionRegistry,
5208
- options.metadata
5476
+ options.metadata,
5477
+ options.discriminator
5209
5478
  ),
5210
5479
  filePath,
5211
5480
  options
@@ -5217,7 +5486,8 @@ function generateSchemasFromDeclaration(options) {
5217
5486
  options.context.checker,
5218
5487
  filePath,
5219
5488
  options.extensionRegistry,
5220
- options.metadata
5489
+ options.metadata,
5490
+ options.discriminator
5221
5491
  );
5222
5492
  if (analyzedAlias.ok) {
5223
5493
  return generateSchemasFromAnalysis(analyzedAlias.analysis, filePath, options);
@@ -5283,7 +5553,8 @@ function buildMixedAuthoringSchemas(options) {
5283
5553
  filePath,
5284
5554
  typeName,
5285
5555
  schemaOptions.extensionRegistry,
5286
- schemaOptions.metadata
5556
+ schemaOptions.metadata,
5557
+ schemaOptions.discriminator
5287
5558
  );
5288
5559
  const composedAnalysis = composeAnalysisWithOverlays(analysis, overlays, schemaOptions.metadata);
5289
5560
  const ir = canonicalizeTSDoc(