@formspec/build 0.1.0-alpha.31 → 0.1.0-alpha.33

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.js CHANGED
@@ -1765,13 +1765,35 @@ import * as fs from "fs";
1765
1765
  import * as path2 from "path";
1766
1766
 
1767
1767
  // src/extensions/registry.ts
1768
+ import {
1769
+ BUILTIN_CONSTRAINT_DEFINITIONS,
1770
+ normalizeConstraintTagName
1771
+ } from "@formspec/core/internals";
1772
+ import {
1773
+ getTagDefinition,
1774
+ normalizeFormSpecTagName
1775
+ } from "@formspec/analysis/internal";
1776
+ var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
1777
+ function buildConstraintTagSources(extensions) {
1778
+ return extensions.map((extension) => ({
1779
+ extensionId: extension.extensionId,
1780
+ ...extension.constraintTags !== void 0 ? {
1781
+ constraintTags: extension.constraintTags.map((tag) => ({
1782
+ tagName: normalizeFormSpecTagName(tag.tagName)
1783
+ }))
1784
+ } : {}
1785
+ }));
1786
+ }
1768
1787
  function createExtensionRegistry(extensions) {
1788
+ const reservedTagSources = buildConstraintTagSources(extensions);
1769
1789
  const typeMap = /* @__PURE__ */ new Map();
1770
1790
  const typeNameMap = /* @__PURE__ */ new Map();
1771
1791
  const constraintMap = /* @__PURE__ */ new Map();
1772
1792
  const constraintTagMap = /* @__PURE__ */ new Map();
1773
1793
  const builtinBroadeningMap = /* @__PURE__ */ new Map();
1774
1794
  const annotationMap = /* @__PURE__ */ new Map();
1795
+ const metadataSlotMap = /* @__PURE__ */ new Map();
1796
+ const metadataTagMap = /* @__PURE__ */ new Map();
1775
1797
  for (const ext of extensions) {
1776
1798
  if (ext.types !== void 0) {
1777
1799
  for (const type of ext.types) {
@@ -1814,10 +1836,11 @@ function createExtensionRegistry(extensions) {
1814
1836
  }
1815
1837
  if (ext.constraintTags !== void 0) {
1816
1838
  for (const tag of ext.constraintTags) {
1817
- if (constraintTagMap.has(tag.tagName)) {
1818
- throw new Error(`Duplicate custom constraint tag: "@${tag.tagName}"`);
1839
+ const canonicalTagName = normalizeFormSpecTagName(tag.tagName);
1840
+ if (constraintTagMap.has(canonicalTagName)) {
1841
+ throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
1819
1842
  }
1820
- constraintTagMap.set(tag.tagName, {
1843
+ constraintTagMap.set(canonicalTagName, {
1821
1844
  extensionId: ext.extensionId,
1822
1845
  registration: tag
1823
1846
  });
@@ -1832,13 +1855,54 @@ function createExtensionRegistry(extensions) {
1832
1855
  annotationMap.set(qualifiedId, annotation);
1833
1856
  }
1834
1857
  }
1858
+ if (ext.metadataSlots !== void 0) {
1859
+ for (const slot of ext.metadataSlots) {
1860
+ if (metadataSlotMap.has(slot.slotId)) {
1861
+ throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
1862
+ }
1863
+ metadataSlotMap.set(slot.slotId, true);
1864
+ const canonicalTagName = normalizeFormSpecTagName(slot.tagName);
1865
+ if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
1866
+ throw new Error(
1867
+ `Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
1868
+ );
1869
+ }
1870
+ if (metadataTagMap.has(canonicalTagName)) {
1871
+ throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
1872
+ }
1873
+ if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
1874
+ throw new Error(
1875
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
1876
+ );
1877
+ }
1878
+ if (constraintTagMap.has(canonicalTagName)) {
1879
+ throw new Error(
1880
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
1881
+ );
1882
+ }
1883
+ if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS, normalizeConstraintTagName(canonicalTagName))) {
1884
+ throw new Error(
1885
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName(canonicalTagName)}".`
1886
+ );
1887
+ }
1888
+ const existingTag = getTagDefinition(canonicalTagName, reservedTagSources);
1889
+ if (existingTag !== null) {
1890
+ throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
1891
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
1892
+ ) : new Error(
1893
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
1894
+ );
1895
+ }
1896
+ metadataTagMap.set(canonicalTagName, true);
1897
+ }
1898
+ }
1835
1899
  }
1836
1900
  return {
1837
1901
  extensions,
1838
1902
  findType: (typeId) => typeMap.get(typeId),
1839
1903
  findTypeByName: (typeName) => typeNameMap.get(typeName),
1840
1904
  findConstraint: (constraintId) => constraintMap.get(constraintId),
1841
- findConstraintTag: (tagName) => constraintTagMap.get(tagName),
1905
+ findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName(tagName)),
1842
1906
  findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
1843
1907
  findAnnotation: (annotationId) => annotationMap.get(annotationId)
1844
1908
  };
@@ -1916,6 +1980,7 @@ import * as path from "path";
1916
1980
  // src/analyzer/class-analyzer.ts
1917
1981
  import * as ts3 from "typescript";
1918
1982
  import {
1983
+ analyzeMetadataForNodeWithChecker,
1919
1984
  parseCommentBlock as parseCommentBlock2
1920
1985
  } from "@formspec/analysis/internal";
1921
1986
 
@@ -1927,8 +1992,9 @@ import * as ts from "typescript";
1927
1992
  import {
1928
1993
  checkSyntheticTagApplication,
1929
1994
  extractPathTarget as extractSharedPathTarget,
1930
- getTagDefinition,
1995
+ getTagDefinition as getTagDefinition2,
1931
1996
  hasTypeSemanticCapability,
1997
+ normalizeFormSpecTagName as normalizeFormSpecTagName2,
1932
1998
  parseConstraintTagValue,
1933
1999
  parseDefaultValueTagValue,
1934
2000
  resolveDeclarationPlacement,
@@ -1948,15 +2014,15 @@ import {
1948
2014
  TextRange
1949
2015
  } from "@microsoft/tsdoc";
1950
2016
  import {
1951
- BUILTIN_CONSTRAINT_DEFINITIONS,
1952
- normalizeConstraintTagName,
2017
+ BUILTIN_CONSTRAINT_DEFINITIONS as BUILTIN_CONSTRAINT_DEFINITIONS2,
2018
+ normalizeConstraintTagName as normalizeConstraintTagName2,
1953
2019
  isBuiltinConstraintName
1954
2020
  } from "@formspec/core/internals";
1955
2021
  import "@formspec/core/internals";
1956
2022
  var TAGS_REQUIRING_RAW_TEXT = /* @__PURE__ */ new Set(["pattern", "enumOptions", "defaultValue"]);
1957
2023
  function createFormSpecTSDocConfig(extensionTagNames = []) {
1958
2024
  const config = new TSDocConfiguration();
1959
- for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS)) {
2025
+ for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS2)) {
1960
2026
  config.addTagDefinition(
1961
2027
  new TSDocTagDefinition({
1962
2028
  tagName: "@" + tagName,
@@ -1965,7 +2031,7 @@ function createFormSpecTSDocConfig(extensionTagNames = []) {
1965
2031
  })
1966
2032
  );
1967
2033
  }
1968
- for (const tagName of ["displayName", "format", "placeholder"]) {
2034
+ for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
1969
2035
  config.addTagDefinition(
1970
2036
  new TSDocTagDefinition({
1971
2037
  tagName: "@" + tagName,
@@ -1999,6 +2065,16 @@ function sharedTagValueOptions(options) {
1999
2065
  };
2000
2066
  }
2001
2067
  var SYNTHETIC_TYPE_FORMAT_FLAGS = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
2068
+ function getExtensionTypeNames(registry) {
2069
+ if (registry === void 0) {
2070
+ return /* @__PURE__ */ new Set();
2071
+ }
2072
+ return new Set(
2073
+ registry.extensions.flatMap(
2074
+ (ext) => (ext.types ?? []).flatMap((t) => t.tsTypeNames ?? [t.typeName])
2075
+ )
2076
+ );
2077
+ }
2002
2078
  function collectImportedNames(sourceFile) {
2003
2079
  const importedNames = /* @__PURE__ */ new Set();
2004
2080
  for (const statement of sourceFile.statements) {
@@ -2038,6 +2114,9 @@ function isNonReferenceIdentifier(node) {
2038
2114
  return false;
2039
2115
  }
2040
2116
  function statementReferencesImportedName(statement, importedNames) {
2117
+ if (importedNames.size === 0) {
2118
+ return false;
2119
+ }
2041
2120
  let referencesImportedName = false;
2042
2121
  const visit = (node) => {
2043
2122
  if (referencesImportedName) {
@@ -2052,14 +2131,17 @@ function statementReferencesImportedName(statement, importedNames) {
2052
2131
  visit(statement);
2053
2132
  return referencesImportedName;
2054
2133
  }
2055
- function buildSupportingDeclarations(sourceFile) {
2134
+ function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
2056
2135
  const importedNames = collectImportedNames(sourceFile);
2136
+ const importedNamesToSkip = new Set(
2137
+ [...importedNames].filter((name) => !extensionTypeNames.has(name))
2138
+ );
2057
2139
  return sourceFile.statements.filter((statement) => {
2058
2140
  if (ts.isImportDeclaration(statement)) return false;
2059
2141
  if (ts.isImportEqualsDeclaration(statement)) return false;
2060
2142
  if (ts.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
2061
2143
  return false;
2062
- if (importedNames.size > 0 && statementReferencesImportedName(statement, importedNames)) {
2144
+ if (statementReferencesImportedName(statement, importedNamesToSkip)) {
2063
2145
  return false;
2064
2146
  }
2065
2147
  return true;
@@ -2212,7 +2294,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2212
2294
  if (placement === null) {
2213
2295
  return [];
2214
2296
  }
2215
- const definition = getTagDefinition(tagName, options?.extensionRegistry?.extensions);
2297
+ const definition = getTagDefinition2(tagName, options?.extensionRegistry?.extensions);
2216
2298
  if (definition === null) {
2217
2299
  return [];
2218
2300
  }
@@ -2316,6 +2398,14 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2316
2398
  extensionId: extension.extensionId,
2317
2399
  ...extension.constraintTags !== void 0 ? {
2318
2400
  constraintTags: extension.constraintTags.map((tag) => ({ tagName: tag.tagName }))
2401
+ } : {},
2402
+ ...extension.metadataSlots !== void 0 ? {
2403
+ metadataSlots: extension.metadataSlots
2404
+ } : {},
2405
+ ...extension.types !== void 0 ? {
2406
+ customTypes: extension.types.map((t) => ({
2407
+ tsTypeNames: t.tsTypeNames ?? [t.typeName]
2408
+ }))
2319
2409
  } : {}
2320
2410
  }))
2321
2411
  } : {}
@@ -2337,7 +2427,10 @@ var parseResultCache = /* @__PURE__ */ new Map();
2337
2427
  function getParser(options) {
2338
2428
  const extensionTagNames = [
2339
2429
  ...options?.extensionRegistry?.extensions.flatMap(
2340
- (extension) => (extension.constraintTags ?? []).map((tag) => tag.tagName)
2430
+ (extension) => (extension.constraintTags ?? []).map((tag) => normalizeFormSpecTagName2(tag.tagName))
2431
+ ) ?? [],
2432
+ ...options?.extensionRegistry?.extensions.flatMap(
2433
+ (extension) => (extension.metadataSlots ?? []).map((slot) => normalizeFormSpecTagName2(slot.tagName))
2341
2434
  ) ?? []
2342
2435
  ].sort();
2343
2436
  const cacheKey = extensionTagNames.join("|");
@@ -2357,7 +2450,16 @@ function getExtensionRegistryCacheKey(registry) {
2357
2450
  (extension) => JSON.stringify({
2358
2451
  extensionId: extension.extensionId,
2359
2452
  typeNames: extension.types?.map((type) => type.typeName) ?? [],
2360
- constraintTags: extension.constraintTags?.map((tag) => tag.tagName) ?? []
2453
+ constraintTags: extension.constraintTags?.map((tag) => normalizeFormSpecTagName2(tag.tagName)) ?? [],
2454
+ metadataSlots: extension.metadataSlots?.map((slot) => ({
2455
+ tagName: normalizeFormSpecTagName2(slot.tagName),
2456
+ declarationKinds: [...slot.declarationKinds].sort(),
2457
+ allowBare: slot.allowBare !== false,
2458
+ qualifiers: (slot.qualifiers ?? []).map((qualifier) => ({
2459
+ qualifier: qualifier.qualifier,
2460
+ ...qualifier.sourceQualifier !== void 0 ? { sourceQualifier: qualifier.sourceQualifier } : {}
2461
+ })).sort((left, right) => left.qualifier.localeCompare(right.qualifier))
2462
+ })) ?? []
2361
2463
  })
2362
2464
  ).join("|");
2363
2465
  }
@@ -2392,7 +2494,8 @@ function parseTSDocTags(node, file = "", options) {
2392
2494
  const rawTextTags = [];
2393
2495
  const sourceFile = node.getSourceFile();
2394
2496
  const sourceText = sourceFile.getFullText();
2395
- const supportingDeclarations = buildSupportingDeclarations(sourceFile);
2497
+ const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
2498
+ const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
2396
2499
  const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
2397
2500
  const rawTextFallbacks = collectRawTextFallbacks(node, file);
2398
2501
  if (commentRanges) {
@@ -2430,7 +2533,7 @@ function parseTSDocTags(node, file = "", options) {
2430
2533
  }
2431
2534
  }
2432
2535
  for (const block of docComment.customBlocks) {
2433
- const tagName = normalizeConstraintTagName(block.blockTag.tagName.substring(1));
2536
+ const tagName = normalizeConstraintTagName2(block.blockTag.tagName.substring(1));
2434
2537
  const parsedTag = nextParsedTag(tagName);
2435
2538
  if (tagName === "displayName" || tagName === "format" || tagName === "placeholder") {
2436
2539
  const text2 = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
@@ -2462,7 +2565,7 @@ function parseTSDocTags(node, file = "", options) {
2462
2565
  }
2463
2566
  if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2464
2567
  const text = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
2465
- const expectedType = isBuiltinConstraintName(tagName) ? BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
2568
+ const expectedType = isBuiltinConstraintName(tagName) ? BUILTIN_CONSTRAINT_DEFINITIONS2[tagName] : void 0;
2466
2569
  if (text === "" && expectedType !== "boolean") continue;
2467
2570
  const provenance = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
2468
2571
  const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
@@ -2693,7 +2796,7 @@ function getBestBlockPayloadText(tag, commentText, commentOffset, block) {
2693
2796
  function collectRawTextFallbacks(node, file) {
2694
2797
  const fallbacks = /* @__PURE__ */ new Map();
2695
2798
  for (const tag of ts.getJSDocTags(node)) {
2696
- const tagName = normalizeConstraintTagName(tag.tagName.text);
2799
+ const tagName = normalizeConstraintTagName2(tag.tagName.text);
2697
2800
  if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2698
2801
  const commentText = getTagCommentText(tag)?.trim() ?? "";
2699
2802
  if (commentText === "") continue;
@@ -2820,76 +2923,79 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
2820
2923
  ...hostType !== void 0 && { hostType }
2821
2924
  };
2822
2925
  }
2823
- function makeExplicitScalarMetadata(value) {
2824
- return value === void 0 || value === "" ? void 0 : { value, source: "explicit" };
2926
+ function createAnalyzerMetadataPolicy(input) {
2927
+ return {
2928
+ raw: input,
2929
+ normalized: normalizeMetadataPolicy(input)
2930
+ };
2825
2931
  }
2826
- function extractExplicitMetadata(node) {
2827
- let apiName;
2828
- let displayName;
2829
- let apiNamePlural;
2830
- let displayNamePlural;
2831
- for (const tag of getLeadingParsedTags(node)) {
2832
- const value = tag.argumentText.trim();
2833
- if (value === "") {
2834
- continue;
2835
- }
2836
- if (tag.normalizedTagName === "apiName") {
2837
- if (tag.target === null) {
2838
- apiName ??= value;
2839
- } else if (tag.target.kind === "variant") {
2840
- if (tag.target.rawText === "singular") {
2841
- apiName ??= value;
2842
- } else if (tag.target.rawText === "plural") {
2843
- apiNamePlural ??= value;
2844
- }
2845
- }
2846
- continue;
2847
- }
2848
- if (tag.normalizedTagName === "displayName") {
2849
- if (tag.target === null) {
2850
- displayName ??= value;
2851
- } else if (tag.target.kind === "variant") {
2852
- if (tag.target.rawText === "singular") {
2853
- displayName ??= value;
2854
- } else if (tag.target.rawText === "plural") {
2855
- displayNamePlural ??= value;
2856
- }
2857
- }
2858
- }
2932
+ function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
2933
+ const analysis = analyzeMetadataForNodeWithChecker({
2934
+ checker,
2935
+ node,
2936
+ logicalName,
2937
+ metadata: metadataPolicy.raw,
2938
+ extensions: extensionRegistry?.extensions,
2939
+ ...buildContext !== void 0 && { buildContext }
2940
+ });
2941
+ const resolvedMetadata = analysis?.resolvedMetadata;
2942
+ const declarationPolicy = getDeclarationMetadataPolicy(
2943
+ metadataPolicy.normalized,
2944
+ declarationKind
2945
+ );
2946
+ if (resolvedMetadata?.apiName === void 0 && declarationPolicy.apiName.mode === "require-explicit") {
2947
+ throw new Error(
2948
+ `Metadata policy requires explicit apiName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2949
+ );
2859
2950
  }
2860
- const resolvedApiName = makeExplicitScalarMetadata(apiName);
2861
- const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
2862
- const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
2863
- const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
2864
- const metadata = {
2865
- ...resolvedApiName !== void 0 && { apiName: resolvedApiName },
2866
- ...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
2867
- ...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
2868
- ...resolvedDisplayNamePlural !== void 0 && {
2869
- displayNamePlural: resolvedDisplayNamePlural
2870
- }
2871
- };
2872
- return Object.keys(metadata).length === 0 ? void 0 : metadata;
2951
+ if (resolvedMetadata?.displayName === void 0 && declarationPolicy.displayName.mode === "require-explicit") {
2952
+ throw new Error(
2953
+ `Metadata policy requires explicit displayName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2954
+ );
2955
+ }
2956
+ if (resolvedMetadata?.apiNamePlural === void 0 && declarationPolicy.apiName.pluralization.mode === "require-explicit") {
2957
+ throw new Error(
2958
+ `Metadata policy requires explicit apiNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2959
+ );
2960
+ }
2961
+ if (resolvedMetadata?.displayNamePlural === void 0 && declarationPolicy.displayName.pluralization.mode === "require-explicit") {
2962
+ throw new Error(
2963
+ `Metadata policy requires explicit displayNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
2964
+ );
2965
+ }
2966
+ return resolvedMetadata;
2873
2967
  }
2874
- function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
2875
- const explicit = extractExplicitMetadata(node);
2876
- return resolveMetadata(
2968
+ function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRegistry, metadataPolicy) {
2969
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
2970
+ const declarationType = checker.getTypeAtLocation(declaration);
2971
+ const logicalName = ts3.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
2972
+ const docResult = extractJSDocParseResult(
2973
+ declaration,
2974
+ file,
2975
+ makeParseOptions(extensionRegistry, void 0, checker, declarationType, declarationType)
2976
+ );
2977
+ const metadata = resolveNodeMetadata(
2978
+ normalizedMetadataPolicy,
2979
+ "type",
2980
+ logicalName,
2981
+ declaration,
2982
+ checker,
2983
+ extensionRegistry,
2877
2984
  {
2878
- ...explicit?.apiName !== void 0 && { apiName: explicit.apiName.value },
2879
- ...explicit?.displayName !== void 0 && { displayName: explicit.displayName.value },
2880
- ...explicit?.apiNamePlural !== void 0 && {
2881
- apiNamePlural: explicit.apiNamePlural.value
2882
- },
2883
- ...explicit?.displayNamePlural !== void 0 && {
2884
- displayNamePlural: explicit.displayNamePlural.value
2885
- }
2886
- },
2887
- getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
2888
- makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
2985
+ checker,
2986
+ declaration,
2987
+ subjectType: declarationType,
2988
+ hostType: declarationType
2989
+ }
2889
2990
  );
2991
+ return {
2992
+ ...metadata !== void 0 && { metadata },
2993
+ annotations: docResult.annotations,
2994
+ diagnostics: docResult.diagnostics
2995
+ };
2890
2996
  }
2891
2997
  function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
2892
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
2998
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
2893
2999
  const name = classDecl.name?.text ?? "AnonymousClass";
2894
3000
  const fields = [];
2895
3001
  const fieldLayouts = [];
@@ -2944,12 +3050,20 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2944
3050
  diagnostics,
2945
3051
  normalizedMetadataPolicy
2946
3052
  );
2947
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, classDecl, {
3053
+ const metadata = resolveNodeMetadata(
3054
+ normalizedMetadataPolicy,
3055
+ "type",
3056
+ name,
3057
+ classDecl,
2948
3058
  checker,
2949
- declaration: classDecl,
2950
- subjectType: classType,
2951
- hostType: classType
2952
- });
3059
+ extensionRegistry,
3060
+ {
3061
+ checker,
3062
+ declaration: classDecl,
3063
+ subjectType: classType,
3064
+ hostType: classType
3065
+ }
3066
+ );
2953
3067
  return {
2954
3068
  name,
2955
3069
  ...metadata !== void 0 && { metadata },
@@ -2963,7 +3077,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2963
3077
  };
2964
3078
  }
2965
3079
  function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
2966
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3080
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
2967
3081
  const name = interfaceDecl.name.text;
2968
3082
  const fields = [];
2969
3083
  const typeRegistry = {};
@@ -3005,12 +3119,20 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
3005
3119
  normalizedMetadataPolicy
3006
3120
  );
3007
3121
  const fieldLayouts = specializedFields.map(() => ({}));
3008
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, interfaceDecl, {
3122
+ const metadata = resolveNodeMetadata(
3123
+ normalizedMetadataPolicy,
3124
+ "type",
3125
+ name,
3126
+ interfaceDecl,
3009
3127
  checker,
3010
- declaration: interfaceDecl,
3011
- subjectType: interfaceType,
3012
- hostType: interfaceType
3013
- });
3128
+ extensionRegistry,
3129
+ {
3130
+ checker,
3131
+ declaration: interfaceDecl,
3132
+ subjectType: interfaceType,
3133
+ hostType: interfaceType
3134
+ }
3135
+ );
3014
3136
  return {
3015
3137
  name,
3016
3138
  ...metadata !== void 0 && { metadata },
@@ -3034,7 +3156,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3034
3156
  };
3035
3157
  }
3036
3158
  const typeLiteral = typeAlias.type;
3037
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3159
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3038
3160
  const name = typeAlias.name.text;
3039
3161
  const fields = [];
3040
3162
  const typeRegistry = {};
@@ -3075,12 +3197,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3075
3197
  diagnostics,
3076
3198
  normalizedMetadataPolicy
3077
3199
  );
3078
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, typeAlias, {
3200
+ const metadata = resolveNodeMetadata(
3201
+ normalizedMetadataPolicy,
3202
+ "type",
3203
+ name,
3204
+ typeAlias,
3079
3205
  checker,
3080
- declaration: typeAlias,
3081
- subjectType: aliasType,
3082
- hostType: aliasType
3083
- });
3206
+ extensionRegistry,
3207
+ {
3208
+ checker,
3209
+ declaration: typeAlias,
3210
+ subjectType: aliasType,
3211
+ hostType: aliasType
3212
+ }
3213
+ );
3084
3214
  return {
3085
3215
  ok: true,
3086
3216
  analysis: {
@@ -3302,10 +3432,7 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
3302
3432
  if (resolvedAnchorNode === null) {
3303
3433
  return void 0;
3304
3434
  }
3305
- const propertyType = checker.getTypeOfSymbolAtLocation(
3306
- propertySymbol,
3307
- resolvedAnchorNode
3308
- );
3435
+ const propertyType = checker.getTypeOfSymbolAtLocation(propertySymbol, resolvedAnchorNode);
3309
3436
  if (propertyType.isStringLiteral()) {
3310
3437
  return propertyType.value;
3311
3438
  }
@@ -3336,6 +3463,8 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3336
3463
  "type",
3337
3464
  getDiscriminatorLogicalName(boundType, declaration, checker),
3338
3465
  declaration,
3466
+ checker,
3467
+ void 0,
3339
3468
  {
3340
3469
  checker,
3341
3470
  declaration,
@@ -3572,12 +3701,20 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
3572
3701
  annotations.push(defaultAnnotation);
3573
3702
  }
3574
3703
  ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
3575
- const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
3704
+ const metadata = resolveNodeMetadata(
3705
+ metadataPolicy,
3706
+ "field",
3707
+ name,
3708
+ prop,
3576
3709
  checker,
3577
- declaration: prop,
3578
- subjectType: tsType,
3579
- hostType
3580
- });
3710
+ extensionRegistry,
3711
+ {
3712
+ checker,
3713
+ declaration: prop,
3714
+ subjectType: tsType,
3715
+ hostType
3716
+ }
3717
+ );
3581
3718
  return {
3582
3719
  kind: "field",
3583
3720
  name,
@@ -3624,12 +3761,20 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
3624
3761
  let annotations = [];
3625
3762
  annotations.push(...docResult.annotations);
3626
3763
  ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
3627
- const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
3764
+ const metadata = resolveNodeMetadata(
3765
+ metadataPolicy,
3766
+ "field",
3767
+ name,
3768
+ prop,
3628
3769
  checker,
3629
- declaration: prop,
3630
- subjectType: tsType,
3631
- hostType
3632
- });
3770
+ extensionRegistry,
3771
+ {
3772
+ checker,
3773
+ declaration: prop,
3774
+ subjectType: tsType,
3775
+ hostType
3776
+ }
3777
+ );
3633
3778
  return {
3634
3779
  kind: "field",
3635
3780
  name,
@@ -3758,7 +3903,7 @@ function getTypeNodeRegistrationName(typeNode) {
3758
3903
  }
3759
3904
  return null;
3760
3905
  }
3761
- function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3906
+ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3762
3907
  const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
3763
3908
  if (customType) {
3764
3909
  return customType;
@@ -3848,7 +3993,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3848
3993
  }
3849
3994
  return { kind: "primitive", primitiveKind: "string" };
3850
3995
  }
3851
- function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3996
+ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3852
3997
  if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
3853
3998
  return null;
3854
3999
  }
@@ -3868,11 +4013,19 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
3868
4013
  file,
3869
4014
  makeParseOptions(extensionRegistry)
3870
4015
  );
3871
- const metadata = resolveNodeMetadata(metadataPolicy, "type", aliasName, aliasDecl, {
4016
+ const metadata = resolveNodeMetadata(
4017
+ metadataPolicy,
4018
+ "type",
4019
+ aliasName,
4020
+ aliasDecl,
3872
4021
  checker,
3873
- declaration: aliasDecl,
3874
- subjectType: aliasType
3875
- });
4022
+ extensionRegistry,
4023
+ {
4024
+ checker,
4025
+ declaration: aliasDecl,
4026
+ subjectType: aliasType
4027
+ }
4028
+ );
3876
4029
  typeRegistry[aliasName] = {
3877
4030
  name: aliasName,
3878
4031
  ...metadata !== void 0 && { metadata },
@@ -3911,7 +4064,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
3911
4064
  const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
3912
4065
  return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
3913
4066
  }
3914
- function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4067
+ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3915
4068
  const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
3916
4069
  if (nestedAliasDecl !== void 0) {
3917
4070
  return resolveAliasedPrimitiveTarget(
@@ -3937,7 +4090,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
3937
4090
  diagnostics
3938
4091
  );
3939
4092
  }
3940
- function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4093
+ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3941
4094
  const typeName = getNamedTypeName(type);
3942
4095
  const namedDecl = getNamedTypeDeclaration(type);
3943
4096
  if (typeName && typeName in typeRegistry) {
@@ -3972,11 +4125,19 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
3972
4125
  return result;
3973
4126
  }
3974
4127
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
3975
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", typeName, namedDecl, {
4128
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4129
+ metadataPolicy,
4130
+ "type",
4131
+ typeName,
4132
+ namedDecl,
3976
4133
  checker,
3977
- declaration: namedDecl,
3978
- subjectType: type
3979
- }) : void 0;
4134
+ extensionRegistry,
4135
+ {
4136
+ checker,
4137
+ declaration: namedDecl,
4138
+ subjectType: type
4139
+ }
4140
+ ) : void 0;
3980
4141
  typeRegistry[typeName] = {
3981
4142
  name: typeName,
3982
4143
  ...metadata !== void 0 && { metadata },
@@ -4061,7 +4222,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
4061
4222
  }
4062
4223
  return registerNamed({ kind: "union", members });
4063
4224
  }
4064
- function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4225
+ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4065
4226
  const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
4066
4227
  const elementType = typeArgs?.[0];
4067
4228
  const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
@@ -4078,7 +4239,7 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
4078
4239
  ) : { kind: "primitive", primitiveKind: "string" };
4079
4240
  return { kind: "array", items };
4080
4241
  }
4081
- function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4242
+ function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4082
4243
  if (type.getProperties().length > 0) {
4083
4244
  return null;
4084
4245
  }
@@ -4139,7 +4300,7 @@ function shouldEmitResolvedObjectProperty(property, declaration) {
4139
4300
  }
4140
4301
  return true;
4141
4302
  }
4142
- function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4303
+ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4143
4304
  const collectedDiagnostics = diagnostics ?? [];
4144
4305
  const typeName = getNamedTypeName(type);
4145
4306
  const namedTypeName = typeName ?? void 0;
@@ -4215,11 +4376,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4215
4376
  return recordNode;
4216
4377
  }
4217
4378
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4218
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
4379
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4380
+ metadataPolicy,
4381
+ "type",
4382
+ registryTypeName,
4383
+ namedDecl,
4219
4384
  checker,
4220
- declaration: namedDecl,
4221
- subjectType: type
4222
- }) : void 0;
4385
+ extensionRegistry,
4386
+ {
4387
+ checker,
4388
+ declaration: namedDecl,
4389
+ subjectType: type
4390
+ }
4391
+ ) : void 0;
4223
4392
  typeRegistry[registryTypeName] = {
4224
4393
  name: registryTypeName,
4225
4394
  ...metadata !== void 0 && { metadata },
@@ -4264,14 +4433,39 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4264
4433
  collectedDiagnostics
4265
4434
  );
4266
4435
  const fieldNodeInfo = fieldInfoMap?.get(prop.name);
4436
+ const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts3.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
4437
+ declaration,
4438
+ checker,
4439
+ file,
4440
+ typeRegistry,
4441
+ visiting,
4442
+ collectedDiagnostics,
4443
+ type,
4444
+ metadataPolicy,
4445
+ extensionRegistry
4446
+ ) : ts3.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
4447
+ declaration,
4448
+ checker,
4449
+ file,
4450
+ typeRegistry,
4451
+ visiting,
4452
+ collectedDiagnostics,
4453
+ type,
4454
+ metadataPolicy,
4455
+ extensionRegistry
4456
+ ) : null : null;
4457
+ const resolvedFieldNodeInfo = fieldNodeInfo ?? inlineFieldNodeInfo;
4458
+ const resolvedPropertyType = inlineFieldNodeInfo?.type ?? propTypeNode;
4267
4459
  properties.push({
4268
4460
  name: prop.name,
4269
- ...fieldNodeInfo?.metadata !== void 0 && { metadata: fieldNodeInfo.metadata },
4270
- type: propTypeNode,
4461
+ ...resolvedFieldNodeInfo?.metadata !== void 0 && {
4462
+ metadata: resolvedFieldNodeInfo.metadata
4463
+ },
4464
+ type: resolvedPropertyType,
4271
4465
  optional,
4272
- constraints: fieldNodeInfo?.constraints ?? [],
4273
- annotations: fieldNodeInfo?.annotations ?? [],
4274
- provenance: fieldNodeInfo?.provenance ?? provenanceForFile(file)
4466
+ constraints: resolvedFieldNodeInfo?.constraints ?? [],
4467
+ annotations: resolvedFieldNodeInfo?.annotations ?? [],
4468
+ provenance: resolvedFieldNodeInfo?.provenance ?? provenanceForFile(file)
4275
4469
  });
4276
4470
  }
4277
4471
  visiting.delete(type);
@@ -4290,11 +4484,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4290
4484
  };
4291
4485
  if (registryTypeName !== void 0 && shouldRegisterNamedType) {
4292
4486
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4293
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
4487
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4488
+ metadataPolicy,
4489
+ "type",
4490
+ registryTypeName,
4491
+ namedDecl,
4294
4492
  checker,
4295
- declaration: namedDecl,
4296
- subjectType: type
4297
- }) : void 0;
4493
+ extensionRegistry,
4494
+ {
4495
+ checker,
4496
+ declaration: namedDecl,
4497
+ subjectType: type
4498
+ }
4499
+ ) : void 0;
4298
4500
  typeRegistry[registryTypeName] = {
4299
4501
  name: registryTypeName,
4300
4502
  ...metadata !== void 0 && { metadata },
@@ -4869,6 +5071,345 @@ function generateSchemasFromProgram(options) {
4869
5071
  );
4870
5072
  }
4871
5073
 
5074
+ // src/static-build.ts
5075
+ import * as ts6 from "typescript";
5076
+ function toStaticBuildContext(context) {
5077
+ return context;
5078
+ }
5079
+ function createStaticBuildContext(filePath) {
5080
+ return toStaticBuildContext(createProgramContext(filePath));
5081
+ }
5082
+ function createStaticBuildContextFromProgram(program, filePath) {
5083
+ return toStaticBuildContext(createProgramContextFromProgram(program, filePath));
5084
+ }
5085
+ function getModuleSymbol(context) {
5086
+ const sourceFileWithSymbol = context.sourceFile;
5087
+ return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
5088
+ }
5089
+ function isSchemaSourceDeclaration(declaration) {
5090
+ return ts6.isClassDeclaration(declaration) || ts6.isInterfaceDeclaration(declaration) || ts6.isTypeAliasDeclaration(declaration);
5091
+ }
5092
+ function resolveModuleExport(context, exportName = "default") {
5093
+ const moduleSymbol = getModuleSymbol(context);
5094
+ if (moduleSymbol === void 0) {
5095
+ return null;
5096
+ }
5097
+ const exportSymbol = context.checker.getExportsOfModule(moduleSymbol).find((candidate) => candidate.name === exportName) ?? null;
5098
+ if (exportSymbol === null) {
5099
+ return null;
5100
+ }
5101
+ return exportSymbol.flags & ts6.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
5102
+ }
5103
+ function resolveModuleExportDeclaration(context, exportName = "default") {
5104
+ return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
5105
+ }
5106
+
5107
+ // src/generators/discovered-schema.ts
5108
+ import * as ts7 from "typescript";
5109
+ import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
5110
+ function toDiscoveredTypeSchemas(result) {
5111
+ return result;
5112
+ }
5113
+ function isNamedTypeDeclaration(declaration) {
5114
+ return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
5115
+ }
5116
+ function hasConcreteTypeArguments(type, checker) {
5117
+ if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
5118
+ return true;
5119
+ }
5120
+ if ((type.flags & ts7.TypeFlags.Object) === 0) {
5121
+ return false;
5122
+ }
5123
+ const objectType = type;
5124
+ if ((objectType.objectFlags & ts7.ObjectFlags.Reference) === 0) {
5125
+ return false;
5126
+ }
5127
+ return checker.getTypeArguments(objectType).length > 0;
5128
+ }
5129
+ function getNamedTypeDeclaration2(type) {
5130
+ const symbol = type.getSymbol();
5131
+ if (symbol?.declarations !== void 0) {
5132
+ const declaration = symbol.declarations[0];
5133
+ if (declaration !== void 0 && isNamedTypeDeclaration(declaration)) {
5134
+ return declaration;
5135
+ }
5136
+ }
5137
+ const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts7.isTypeAliasDeclaration);
5138
+ return aliasDeclaration;
5139
+ }
5140
+ function getFallbackName(sourceNode, fallback = "AnonymousType") {
5141
+ if (sourceNode !== void 0 && "name" in sourceNode) {
5142
+ const namedNode = sourceNode;
5143
+ if (namedNode.name !== void 0 && ts7.isIdentifier(namedNode.name)) {
5144
+ return namedNode.name.text;
5145
+ }
5146
+ }
5147
+ return fallback;
5148
+ }
5149
+ function createObjectRootAnalysis(name, properties, typeRegistry, metadata, annotations) {
5150
+ const fields = properties.map((property) => ({
5151
+ kind: "field",
5152
+ name: property.name,
5153
+ ...property.metadata !== void 0 && { metadata: property.metadata },
5154
+ type: property.type,
5155
+ required: !property.optional,
5156
+ constraints: property.constraints,
5157
+ annotations: property.annotations,
5158
+ provenance: property.provenance
5159
+ }));
5160
+ return {
5161
+ name,
5162
+ ...metadata !== void 0 && { metadata },
5163
+ fields,
5164
+ fieldLayouts: fields.map(() => ({})),
5165
+ typeRegistry,
5166
+ ...annotations !== void 0 && annotations.length > 0 && { annotations },
5167
+ instanceMethods: [],
5168
+ staticMethods: [],
5169
+ diagnostics: []
5170
+ };
5171
+ }
5172
+ function omitApiName(metadata) {
5173
+ if (metadata?.apiName === void 0) {
5174
+ return metadata;
5175
+ }
5176
+ const { apiName: _apiName, ...rest } = metadata;
5177
+ return Object.keys(rest).length > 0 ? rest : void 0;
5178
+ }
5179
+ function describeRootType(rootType, typeRegistry, fallbackName) {
5180
+ if (rootType.kind !== "reference") {
5181
+ return {
5182
+ name: fallbackName,
5183
+ type: rootType
5184
+ };
5185
+ }
5186
+ const definition = typeRegistry[rootType.name];
5187
+ if (definition === void 0) {
5188
+ return {
5189
+ name: rootType.name,
5190
+ type: rootType
5191
+ };
5192
+ }
5193
+ return {
5194
+ name: definition.name,
5195
+ ...definition.metadata !== void 0 && { metadata: definition.metadata },
5196
+ ...definition.annotations !== void 0 && definition.annotations.length > 0 && { annotations: definition.annotations },
5197
+ type: definition.type
5198
+ };
5199
+ }
5200
+ function toStandaloneJsonSchema(root, typeRegistry, options) {
5201
+ const syntheticFieldMetadata = omitApiName(root.metadata);
5202
+ const syntheticField = {
5203
+ kind: "field",
5204
+ name: "__result",
5205
+ ...syntheticFieldMetadata !== void 0 && { metadata: syntheticFieldMetadata },
5206
+ type: root.type,
5207
+ required: true,
5208
+ constraints: [],
5209
+ annotations: [...root.annotations ?? []],
5210
+ provenance: {
5211
+ surface: "tsdoc",
5212
+ file: "",
5213
+ line: 1,
5214
+ column: 0
5215
+ }
5216
+ };
5217
+ const schema = generateJsonSchemaFromIR(
5218
+ {
5219
+ kind: "form-ir",
5220
+ name: root.name,
5221
+ irVersion: IR_VERSION3,
5222
+ elements: [syntheticField],
5223
+ ...root.metadata !== void 0 && { metadata: root.metadata },
5224
+ ...root.annotations !== void 0 && root.annotations.length > 0 && { rootAnnotations: root.annotations },
5225
+ typeRegistry,
5226
+ provenance: syntheticField.provenance
5227
+ },
5228
+ {
5229
+ extensionRegistry: options?.extensionRegistry,
5230
+ vendorPrefix: options?.vendorPrefix
5231
+ }
5232
+ );
5233
+ const result = schema.properties?.["__result"];
5234
+ if (result === void 0) {
5235
+ throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
5236
+ }
5237
+ if (schema.$defs === void 0 || Object.keys(schema.$defs).length === 0) {
5238
+ return {
5239
+ ...schema.$schema !== void 0 && { $schema: schema.$schema },
5240
+ ...result
5241
+ };
5242
+ }
5243
+ return {
5244
+ ...schema.$schema !== void 0 && { $schema: schema.$schema },
5245
+ ...result,
5246
+ $defs: schema.$defs
5247
+ };
5248
+ }
5249
+ function generateSchemasFromAnalysis(analysis, filePath, options) {
5250
+ return toDiscoveredTypeSchemas(
5251
+ generateClassSchemas(
5252
+ analysis,
5253
+ { file: filePath },
5254
+ {
5255
+ extensionRegistry: options?.extensionRegistry,
5256
+ metadata: options?.metadata,
5257
+ vendorPrefix: options?.vendorPrefix
5258
+ }
5259
+ )
5260
+ );
5261
+ }
5262
+ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false, rootOverride) {
5263
+ const namedDeclaration = skipNamedDeclaration || hasConcreteTypeArguments(options.type, options.context.checker) ? void 0 : getNamedTypeDeclaration2(options.type);
5264
+ if (namedDeclaration !== void 0) {
5265
+ return generateSchemasFromDeclaration({
5266
+ ...options,
5267
+ declaration: namedDeclaration
5268
+ });
5269
+ }
5270
+ const filePath = options.sourceNode?.getSourceFile().fileName ?? options.context.sourceFile.fileName;
5271
+ const typeRegistry = {};
5272
+ const diagnostics = [];
5273
+ const rootType = resolveTypeNode(
5274
+ options.type,
5275
+ options.context.checker,
5276
+ filePath,
5277
+ typeRegistry,
5278
+ /* @__PURE__ */ new Set(),
5279
+ options.sourceNode,
5280
+ createAnalyzerMetadataPolicy(options.metadata),
5281
+ options.extensionRegistry,
5282
+ diagnostics
5283
+ );
5284
+ if (diagnostics.length > 0) {
5285
+ const diagnosticDetails = diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
5286
+ throw new Error(
5287
+ `FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
5288
+ );
5289
+ }
5290
+ const describedRoot = describeRootType(
5291
+ rootType,
5292
+ typeRegistry,
5293
+ options.name ?? getFallbackName(options.sourceNode)
5294
+ );
5295
+ const mergedMetadata = mergeResolvedMetadata(describedRoot.metadata, rootOverride?.metadata);
5296
+ const root = {
5297
+ ...describedRoot,
5298
+ ...rootOverride?.name !== void 0 && { name: rootOverride.name },
5299
+ ...mergedMetadata !== void 0 && { metadata: mergedMetadata },
5300
+ ...rootOverride?.annotations !== void 0 && { annotations: rootOverride.annotations }
5301
+ };
5302
+ if (root.type.kind === "object") {
5303
+ return generateSchemasFromAnalysis(
5304
+ createObjectRootAnalysis(
5305
+ options.name ?? root.name,
5306
+ root.type.properties,
5307
+ typeRegistry,
5308
+ root.metadata,
5309
+ root.annotations
5310
+ ),
5311
+ filePath,
5312
+ options
5313
+ );
5314
+ }
5315
+ return {
5316
+ jsonSchema: toStandaloneJsonSchema(root, typeRegistry, options),
5317
+ uiSchema: null
5318
+ };
5319
+ }
5320
+ function generateSchemasFromDeclaration(options) {
5321
+ const filePath = options.declaration.getSourceFile().fileName;
5322
+ if (ts7.isClassDeclaration(options.declaration)) {
5323
+ return generateSchemasFromAnalysis(
5324
+ analyzeClassToIR(
5325
+ options.declaration,
5326
+ options.context.checker,
5327
+ filePath,
5328
+ options.extensionRegistry,
5329
+ options.metadata
5330
+ ),
5331
+ filePath,
5332
+ options
5333
+ );
5334
+ }
5335
+ if (ts7.isInterfaceDeclaration(options.declaration)) {
5336
+ return generateSchemasFromAnalysis(
5337
+ analyzeInterfaceToIR(
5338
+ options.declaration,
5339
+ options.context.checker,
5340
+ filePath,
5341
+ options.extensionRegistry,
5342
+ options.metadata
5343
+ ),
5344
+ filePath,
5345
+ options
5346
+ );
5347
+ }
5348
+ if (ts7.isTypeAliasDeclaration(options.declaration)) {
5349
+ const analyzedAlias = analyzeTypeAliasToIR(
5350
+ options.declaration,
5351
+ options.context.checker,
5352
+ filePath,
5353
+ options.extensionRegistry,
5354
+ options.metadata
5355
+ );
5356
+ if (analyzedAlias.ok) {
5357
+ return generateSchemasFromAnalysis(analyzedAlias.analysis, filePath, options);
5358
+ }
5359
+ const aliasRootInfo = analyzeDeclarationRootInfo(
5360
+ options.declaration,
5361
+ options.context.checker,
5362
+ filePath,
5363
+ options.extensionRegistry,
5364
+ options.metadata
5365
+ );
5366
+ if (aliasRootInfo.diagnostics.length > 0) {
5367
+ const diagnosticDetails = aliasRootInfo.diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
5368
+ throw new Error(
5369
+ `FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
5370
+ );
5371
+ }
5372
+ return generateSchemasFromResolvedType(
5373
+ {
5374
+ ...options,
5375
+ type: options.context.checker.getTypeAtLocation(options.declaration),
5376
+ sourceNode: options.declaration,
5377
+ name: options.declaration.name.text
5378
+ },
5379
+ true,
5380
+ {
5381
+ name: options.declaration.name.text,
5382
+ ...aliasRootInfo.metadata !== void 0 && { metadata: aliasRootInfo.metadata },
5383
+ ...aliasRootInfo.annotations.length > 0 && { annotations: aliasRootInfo.annotations }
5384
+ }
5385
+ );
5386
+ }
5387
+ const _exhaustive = options.declaration;
5388
+ return _exhaustive;
5389
+ }
5390
+ function generateSchemasFromType(options) {
5391
+ return generateSchemasFromResolvedType(options);
5392
+ }
5393
+ function generateSchemasFromParameter(options) {
5394
+ return generateSchemasFromResolvedType({
5395
+ ...options,
5396
+ type: options.context.checker.getTypeAtLocation(options.parameter),
5397
+ sourceNode: options.parameter,
5398
+ name: getFallbackName(options.parameter, "Parameter")
5399
+ });
5400
+ }
5401
+ function generateSchemasFromReturnType(options) {
5402
+ const signature = options.context.checker.getSignatureFromDeclaration(options.declaration);
5403
+ const type = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
5404
+ const fallbackName = options.declaration.name !== void 0 && ts7.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
5405
+ return generateSchemasFromResolvedType({
5406
+ ...options,
5407
+ type,
5408
+ sourceNode: options.declaration.type ?? options.declaration,
5409
+ name: fallbackName
5410
+ });
5411
+ }
5412
+
4872
5413
  // src/generators/mixed-authoring.ts
4873
5414
  function buildMixedAuthoringSchemas(options) {
4874
5415
  const { filePath, typeName, overlays, ...schemaOptions } = options;
@@ -5083,12 +5624,20 @@ export {
5083
5624
  buildFormSchemas,
5084
5625
  buildMixedAuthoringSchemas,
5085
5626
  createExtensionRegistry,
5627
+ createStaticBuildContext,
5628
+ createStaticBuildContextFromProgram,
5086
5629
  generateJsonSchema,
5087
5630
  generateSchemas,
5088
5631
  generateSchemasFromClass,
5632
+ generateSchemasFromDeclaration,
5633
+ generateSchemasFromParameter,
5089
5634
  generateSchemasFromProgram,
5635
+ generateSchemasFromReturnType,
5636
+ generateSchemasFromType,
5090
5637
  generateUiSchema,
5091
5638
  jsonSchema7Schema,
5639
+ resolveModuleExport,
5640
+ resolveModuleExportDeclaration,
5092
5641
  uiSchema as uiSchemaSchema,
5093
5642
  writeSchemas
5094
5643
  };