@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/cli.js CHANGED
@@ -1854,13 +1854,34 @@ var init_generator2 = __esm({
1854
1854
  });
1855
1855
 
1856
1856
  // src/extensions/registry.ts
1857
+ import {
1858
+ BUILTIN_CONSTRAINT_DEFINITIONS,
1859
+ normalizeConstraintTagName
1860
+ } from "@formspec/core/internals";
1861
+ import {
1862
+ getTagDefinition,
1863
+ normalizeFormSpecTagName
1864
+ } from "@formspec/analysis/internal";
1865
+ function buildConstraintTagSources(extensions) {
1866
+ return extensions.map((extension) => ({
1867
+ extensionId: extension.extensionId,
1868
+ ...extension.constraintTags !== void 0 ? {
1869
+ constraintTags: extension.constraintTags.map((tag) => ({
1870
+ tagName: normalizeFormSpecTagName(tag.tagName)
1871
+ }))
1872
+ } : {}
1873
+ }));
1874
+ }
1857
1875
  function createExtensionRegistry(extensions) {
1876
+ const reservedTagSources = buildConstraintTagSources(extensions);
1858
1877
  const typeMap = /* @__PURE__ */ new Map();
1859
1878
  const typeNameMap = /* @__PURE__ */ new Map();
1860
1879
  const constraintMap = /* @__PURE__ */ new Map();
1861
1880
  const constraintTagMap = /* @__PURE__ */ new Map();
1862
1881
  const builtinBroadeningMap = /* @__PURE__ */ new Map();
1863
1882
  const annotationMap = /* @__PURE__ */ new Map();
1883
+ const metadataSlotMap = /* @__PURE__ */ new Map();
1884
+ const metadataTagMap = /* @__PURE__ */ new Map();
1864
1885
  for (const ext of extensions) {
1865
1886
  if (ext.types !== void 0) {
1866
1887
  for (const type of ext.types) {
@@ -1903,10 +1924,11 @@ function createExtensionRegistry(extensions) {
1903
1924
  }
1904
1925
  if (ext.constraintTags !== void 0) {
1905
1926
  for (const tag of ext.constraintTags) {
1906
- if (constraintTagMap.has(tag.tagName)) {
1907
- throw new Error(`Duplicate custom constraint tag: "@${tag.tagName}"`);
1927
+ const canonicalTagName = normalizeFormSpecTagName(tag.tagName);
1928
+ if (constraintTagMap.has(canonicalTagName)) {
1929
+ throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
1908
1930
  }
1909
- constraintTagMap.set(tag.tagName, {
1931
+ constraintTagMap.set(canonicalTagName, {
1910
1932
  extensionId: ext.extensionId,
1911
1933
  registration: tag
1912
1934
  });
@@ -1921,20 +1943,63 @@ function createExtensionRegistry(extensions) {
1921
1943
  annotationMap.set(qualifiedId, annotation);
1922
1944
  }
1923
1945
  }
1946
+ if (ext.metadataSlots !== void 0) {
1947
+ for (const slot of ext.metadataSlots) {
1948
+ if (metadataSlotMap.has(slot.slotId)) {
1949
+ throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
1950
+ }
1951
+ metadataSlotMap.set(slot.slotId, true);
1952
+ const canonicalTagName = normalizeFormSpecTagName(slot.tagName);
1953
+ if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
1954
+ throw new Error(
1955
+ `Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
1956
+ );
1957
+ }
1958
+ if (metadataTagMap.has(canonicalTagName)) {
1959
+ throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
1960
+ }
1961
+ if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
1962
+ throw new Error(
1963
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
1964
+ );
1965
+ }
1966
+ if (constraintTagMap.has(canonicalTagName)) {
1967
+ throw new Error(
1968
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
1969
+ );
1970
+ }
1971
+ if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS, normalizeConstraintTagName(canonicalTagName))) {
1972
+ throw new Error(
1973
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName(canonicalTagName)}".`
1974
+ );
1975
+ }
1976
+ const existingTag = getTagDefinition(canonicalTagName, reservedTagSources);
1977
+ if (existingTag !== null) {
1978
+ throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
1979
+ `Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
1980
+ ) : new Error(
1981
+ `Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
1982
+ );
1983
+ }
1984
+ metadataTagMap.set(canonicalTagName, true);
1985
+ }
1986
+ }
1924
1987
  }
1925
1988
  return {
1926
1989
  extensions,
1927
1990
  findType: (typeId) => typeMap.get(typeId),
1928
1991
  findTypeByName: (typeName) => typeNameMap.get(typeName),
1929
1992
  findConstraint: (constraintId) => constraintMap.get(constraintId),
1930
- findConstraintTag: (tagName) => constraintTagMap.get(tagName),
1993
+ findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName(tagName)),
1931
1994
  findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
1932
1995
  findAnnotation: (annotationId) => annotationMap.get(annotationId)
1933
1996
  };
1934
1997
  }
1998
+ var BUILTIN_METADATA_TAGS;
1935
1999
  var init_registry = __esm({
1936
2000
  "src/extensions/registry.ts"() {
1937
2001
  "use strict";
2002
+ BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
1938
2003
  }
1939
2004
  });
1940
2005
 
@@ -2019,8 +2084,9 @@ import * as ts from "typescript";
2019
2084
  import {
2020
2085
  checkSyntheticTagApplication,
2021
2086
  extractPathTarget as extractSharedPathTarget,
2022
- getTagDefinition,
2087
+ getTagDefinition as getTagDefinition2,
2023
2088
  hasTypeSemanticCapability,
2089
+ normalizeFormSpecTagName as normalizeFormSpecTagName2,
2024
2090
  parseConstraintTagValue,
2025
2091
  parseDefaultValueTagValue,
2026
2092
  resolveDeclarationPlacement,
@@ -2040,14 +2106,14 @@ import {
2040
2106
  TextRange
2041
2107
  } from "@microsoft/tsdoc";
2042
2108
  import {
2043
- BUILTIN_CONSTRAINT_DEFINITIONS,
2044
- normalizeConstraintTagName,
2109
+ BUILTIN_CONSTRAINT_DEFINITIONS as BUILTIN_CONSTRAINT_DEFINITIONS2,
2110
+ normalizeConstraintTagName as normalizeConstraintTagName2,
2045
2111
  isBuiltinConstraintName
2046
2112
  } from "@formspec/core/internals";
2047
2113
  import "@formspec/core/internals";
2048
2114
  function createFormSpecTSDocConfig(extensionTagNames = []) {
2049
2115
  const config = new TSDocConfiguration();
2050
- for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS)) {
2116
+ for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS2)) {
2051
2117
  config.addTagDefinition(
2052
2118
  new TSDocTagDefinition({
2053
2119
  tagName: "@" + tagName,
@@ -2056,7 +2122,7 @@ function createFormSpecTSDocConfig(extensionTagNames = []) {
2056
2122
  })
2057
2123
  );
2058
2124
  }
2059
- for (const tagName of ["displayName", "format", "placeholder"]) {
2125
+ for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
2060
2126
  config.addTagDefinition(
2061
2127
  new TSDocTagDefinition({
2062
2128
  tagName: "@" + tagName,
@@ -2089,6 +2155,16 @@ function sharedTagValueOptions(options) {
2089
2155
  ...options?.fieldType !== void 0 ? { fieldType: options.fieldType } : {}
2090
2156
  };
2091
2157
  }
2158
+ function getExtensionTypeNames(registry) {
2159
+ if (registry === void 0) {
2160
+ return /* @__PURE__ */ new Set();
2161
+ }
2162
+ return new Set(
2163
+ registry.extensions.flatMap(
2164
+ (ext) => (ext.types ?? []).flatMap((t) => t.tsTypeNames ?? [t.typeName])
2165
+ )
2166
+ );
2167
+ }
2092
2168
  function collectImportedNames(sourceFile) {
2093
2169
  const importedNames = /* @__PURE__ */ new Set();
2094
2170
  for (const statement of sourceFile.statements) {
@@ -2128,6 +2204,9 @@ function isNonReferenceIdentifier(node) {
2128
2204
  return false;
2129
2205
  }
2130
2206
  function statementReferencesImportedName(statement, importedNames) {
2207
+ if (importedNames.size === 0) {
2208
+ return false;
2209
+ }
2131
2210
  let referencesImportedName = false;
2132
2211
  const visit = (node) => {
2133
2212
  if (referencesImportedName) {
@@ -2142,14 +2221,17 @@ function statementReferencesImportedName(statement, importedNames) {
2142
2221
  visit(statement);
2143
2222
  return referencesImportedName;
2144
2223
  }
2145
- function buildSupportingDeclarations(sourceFile) {
2224
+ function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
2146
2225
  const importedNames = collectImportedNames(sourceFile);
2226
+ const importedNamesToSkip = new Set(
2227
+ [...importedNames].filter((name) => !extensionTypeNames.has(name))
2228
+ );
2147
2229
  return sourceFile.statements.filter((statement) => {
2148
2230
  if (ts.isImportDeclaration(statement)) return false;
2149
2231
  if (ts.isImportEqualsDeclaration(statement)) return false;
2150
2232
  if (ts.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
2151
2233
  return false;
2152
- if (importedNames.size > 0 && statementReferencesImportedName(statement, importedNames)) {
2234
+ if (statementReferencesImportedName(statement, importedNamesToSkip)) {
2153
2235
  return false;
2154
2236
  }
2155
2237
  return true;
@@ -2302,7 +2384,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2302
2384
  if (placement === null) {
2303
2385
  return [];
2304
2386
  }
2305
- const definition = getTagDefinition(tagName, options?.extensionRegistry?.extensions);
2387
+ const definition = getTagDefinition2(tagName, options?.extensionRegistry?.extensions);
2306
2388
  if (definition === null) {
2307
2389
  return [];
2308
2390
  }
@@ -2406,6 +2488,14 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2406
2488
  extensionId: extension.extensionId,
2407
2489
  ...extension.constraintTags !== void 0 ? {
2408
2490
  constraintTags: extension.constraintTags.map((tag) => ({ tagName: tag.tagName }))
2491
+ } : {},
2492
+ ...extension.metadataSlots !== void 0 ? {
2493
+ metadataSlots: extension.metadataSlots
2494
+ } : {},
2495
+ ...extension.types !== void 0 ? {
2496
+ customTypes: extension.types.map((t) => ({
2497
+ tsTypeNames: t.tsTypeNames ?? [t.typeName]
2498
+ }))
2409
2499
  } : {}
2410
2500
  }))
2411
2501
  } : {}
@@ -2425,7 +2515,10 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2425
2515
  function getParser(options) {
2426
2516
  const extensionTagNames = [
2427
2517
  ...options?.extensionRegistry?.extensions.flatMap(
2428
- (extension) => (extension.constraintTags ?? []).map((tag) => tag.tagName)
2518
+ (extension) => (extension.constraintTags ?? []).map((tag) => normalizeFormSpecTagName2(tag.tagName))
2519
+ ) ?? [],
2520
+ ...options?.extensionRegistry?.extensions.flatMap(
2521
+ (extension) => (extension.metadataSlots ?? []).map((slot) => normalizeFormSpecTagName2(slot.tagName))
2429
2522
  ) ?? []
2430
2523
  ].sort();
2431
2524
  const cacheKey = extensionTagNames.join("|");
@@ -2445,7 +2538,16 @@ function getExtensionRegistryCacheKey(registry) {
2445
2538
  (extension) => JSON.stringify({
2446
2539
  extensionId: extension.extensionId,
2447
2540
  typeNames: extension.types?.map((type) => type.typeName) ?? [],
2448
- constraintTags: extension.constraintTags?.map((tag) => tag.tagName) ?? []
2541
+ constraintTags: extension.constraintTags?.map((tag) => normalizeFormSpecTagName2(tag.tagName)) ?? [],
2542
+ metadataSlots: extension.metadataSlots?.map((slot) => ({
2543
+ tagName: normalizeFormSpecTagName2(slot.tagName),
2544
+ declarationKinds: [...slot.declarationKinds].sort(),
2545
+ allowBare: slot.allowBare !== false,
2546
+ qualifiers: (slot.qualifiers ?? []).map((qualifier) => ({
2547
+ qualifier: qualifier.qualifier,
2548
+ ...qualifier.sourceQualifier !== void 0 ? { sourceQualifier: qualifier.sourceQualifier } : {}
2549
+ })).sort((left, right) => left.qualifier.localeCompare(right.qualifier))
2550
+ })) ?? []
2449
2551
  })
2450
2552
  ).join("|");
2451
2553
  }
@@ -2480,7 +2582,8 @@ function parseTSDocTags(node, file = "", options) {
2480
2582
  const rawTextTags = [];
2481
2583
  const sourceFile = node.getSourceFile();
2482
2584
  const sourceText = sourceFile.getFullText();
2483
- const supportingDeclarations = buildSupportingDeclarations(sourceFile);
2585
+ const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
2586
+ const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
2484
2587
  const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
2485
2588
  const rawTextFallbacks = collectRawTextFallbacks(node, file);
2486
2589
  if (commentRanges) {
@@ -2518,7 +2621,7 @@ function parseTSDocTags(node, file = "", options) {
2518
2621
  }
2519
2622
  }
2520
2623
  for (const block of docComment.customBlocks) {
2521
- const tagName = normalizeConstraintTagName(block.blockTag.tagName.substring(1));
2624
+ const tagName = normalizeConstraintTagName2(block.blockTag.tagName.substring(1));
2522
2625
  const parsedTag = nextParsedTag(tagName);
2523
2626
  if (tagName === "displayName" || tagName === "format" || tagName === "placeholder") {
2524
2627
  const text2 = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
@@ -2550,7 +2653,7 @@ function parseTSDocTags(node, file = "", options) {
2550
2653
  }
2551
2654
  if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2552
2655
  const text = getBestBlockPayloadText(parsedTag, commentText, range.pos, block);
2553
- const expectedType = isBuiltinConstraintName(tagName) ? BUILTIN_CONSTRAINT_DEFINITIONS[tagName] : void 0;
2656
+ const expectedType = isBuiltinConstraintName(tagName) ? BUILTIN_CONSTRAINT_DEFINITIONS2[tagName] : void 0;
2554
2657
  if (text === "" && expectedType !== "boolean") continue;
2555
2658
  const provenance = parsedTag !== null ? provenanceForParsedTag(parsedTag, sourceFile, file) : provenanceForComment(range, sourceFile, file, tagName);
2556
2659
  const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
@@ -2781,7 +2884,7 @@ function getBestBlockPayloadText(tag, commentText, commentOffset, block) {
2781
2884
  function collectRawTextFallbacks(node, file) {
2782
2885
  const fallbacks = /* @__PURE__ */ new Map();
2783
2886
  for (const tag of ts.getJSDocTags(node)) {
2784
- const tagName = normalizeConstraintTagName(tag.tagName.text);
2887
+ const tagName = normalizeConstraintTagName2(tag.tagName.text);
2785
2888
  if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
2786
2889
  const commentText = getTagCommentText(tag)?.trim() ?? "";
2787
2890
  if (commentText === "") continue;
@@ -2904,6 +3007,7 @@ var init_jsdoc_constraints = __esm({
2904
3007
  // src/analyzer/class-analyzer.ts
2905
3008
  import * as ts3 from "typescript";
2906
3009
  import {
3010
+ analyzeMetadataForNodeWithChecker,
2907
3011
  parseCommentBlock as parseCommentBlock2
2908
3012
  } from "@formspec/analysis/internal";
2909
3013
  function isObjectType(type) {
@@ -2924,76 +3028,79 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
2924
3028
  ...hostType !== void 0 && { hostType }
2925
3029
  };
2926
3030
  }
2927
- function makeExplicitScalarMetadata(value) {
2928
- return value === void 0 || value === "" ? void 0 : { value, source: "explicit" };
3031
+ function createAnalyzerMetadataPolicy(input) {
3032
+ return {
3033
+ raw: input,
3034
+ normalized: normalizeMetadataPolicy(input)
3035
+ };
2929
3036
  }
2930
- function extractExplicitMetadata(node) {
2931
- let apiName;
2932
- let displayName;
2933
- let apiNamePlural;
2934
- let displayNamePlural;
2935
- for (const tag of getLeadingParsedTags(node)) {
2936
- const value = tag.argumentText.trim();
2937
- if (value === "") {
2938
- continue;
2939
- }
2940
- if (tag.normalizedTagName === "apiName") {
2941
- if (tag.target === null) {
2942
- apiName ??= value;
2943
- } else if (tag.target.kind === "variant") {
2944
- if (tag.target.rawText === "singular") {
2945
- apiName ??= value;
2946
- } else if (tag.target.rawText === "plural") {
2947
- apiNamePlural ??= value;
2948
- }
2949
- }
2950
- continue;
2951
- }
2952
- if (tag.normalizedTagName === "displayName") {
2953
- if (tag.target === null) {
2954
- displayName ??= value;
2955
- } else if (tag.target.kind === "variant") {
2956
- if (tag.target.rawText === "singular") {
2957
- displayName ??= value;
2958
- } else if (tag.target.rawText === "plural") {
2959
- displayNamePlural ??= value;
2960
- }
2961
- }
2962
- }
3037
+ function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
3038
+ const analysis = analyzeMetadataForNodeWithChecker({
3039
+ checker,
3040
+ node,
3041
+ logicalName,
3042
+ metadata: metadataPolicy.raw,
3043
+ extensions: extensionRegistry?.extensions,
3044
+ ...buildContext !== void 0 && { buildContext }
3045
+ });
3046
+ const resolvedMetadata = analysis?.resolvedMetadata;
3047
+ const declarationPolicy = getDeclarationMetadataPolicy(
3048
+ metadataPolicy.normalized,
3049
+ declarationKind
3050
+ );
3051
+ if (resolvedMetadata?.apiName === void 0 && declarationPolicy.apiName.mode === "require-explicit") {
3052
+ throw new Error(
3053
+ `Metadata policy requires explicit apiName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
3054
+ );
2963
3055
  }
2964
- const resolvedApiName = makeExplicitScalarMetadata(apiName);
2965
- const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
2966
- const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
2967
- const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
2968
- const metadata = {
2969
- ...resolvedApiName !== void 0 && { apiName: resolvedApiName },
2970
- ...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
2971
- ...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
2972
- ...resolvedDisplayNamePlural !== void 0 && {
2973
- displayNamePlural: resolvedDisplayNamePlural
2974
- }
2975
- };
2976
- return Object.keys(metadata).length === 0 ? void 0 : metadata;
3056
+ if (resolvedMetadata?.displayName === void 0 && declarationPolicy.displayName.mode === "require-explicit") {
3057
+ throw new Error(
3058
+ `Metadata policy requires explicit displayName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
3059
+ );
3060
+ }
3061
+ if (resolvedMetadata?.apiNamePlural === void 0 && declarationPolicy.apiName.pluralization.mode === "require-explicit") {
3062
+ throw new Error(
3063
+ `Metadata policy requires explicit apiNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
3064
+ );
3065
+ }
3066
+ if (resolvedMetadata?.displayNamePlural === void 0 && declarationPolicy.displayName.pluralization.mode === "require-explicit") {
3067
+ throw new Error(
3068
+ `Metadata policy requires explicit displayNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
3069
+ );
3070
+ }
3071
+ return resolvedMetadata;
2977
3072
  }
2978
- function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
2979
- const explicit = extractExplicitMetadata(node);
2980
- return resolveMetadata(
3073
+ function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRegistry, metadataPolicy) {
3074
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3075
+ const declarationType = checker.getTypeAtLocation(declaration);
3076
+ const logicalName = ts3.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
3077
+ const docResult = extractJSDocParseResult(
3078
+ declaration,
3079
+ file,
3080
+ makeParseOptions(extensionRegistry, void 0, checker, declarationType, declarationType)
3081
+ );
3082
+ const metadata = resolveNodeMetadata(
3083
+ normalizedMetadataPolicy,
3084
+ "type",
3085
+ logicalName,
3086
+ declaration,
3087
+ checker,
3088
+ extensionRegistry,
2981
3089
  {
2982
- ...explicit?.apiName !== void 0 && { apiName: explicit.apiName.value },
2983
- ...explicit?.displayName !== void 0 && { displayName: explicit.displayName.value },
2984
- ...explicit?.apiNamePlural !== void 0 && {
2985
- apiNamePlural: explicit.apiNamePlural.value
2986
- },
2987
- ...explicit?.displayNamePlural !== void 0 && {
2988
- displayNamePlural: explicit.displayNamePlural.value
2989
- }
2990
- },
2991
- getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
2992
- makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
3090
+ checker,
3091
+ declaration,
3092
+ subjectType: declarationType,
3093
+ hostType: declarationType
3094
+ }
2993
3095
  );
3096
+ return {
3097
+ ...metadata !== void 0 && { metadata },
3098
+ annotations: docResult.annotations,
3099
+ diagnostics: docResult.diagnostics
3100
+ };
2994
3101
  }
2995
3102
  function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
2996
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3103
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
2997
3104
  const name = classDecl.name?.text ?? "AnonymousClass";
2998
3105
  const fields = [];
2999
3106
  const fieldLayouts = [];
@@ -3048,12 +3155,20 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
3048
3155
  diagnostics,
3049
3156
  normalizedMetadataPolicy
3050
3157
  );
3051
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, classDecl, {
3158
+ const metadata = resolveNodeMetadata(
3159
+ normalizedMetadataPolicy,
3160
+ "type",
3161
+ name,
3162
+ classDecl,
3052
3163
  checker,
3053
- declaration: classDecl,
3054
- subjectType: classType,
3055
- hostType: classType
3056
- });
3164
+ extensionRegistry,
3165
+ {
3166
+ checker,
3167
+ declaration: classDecl,
3168
+ subjectType: classType,
3169
+ hostType: classType
3170
+ }
3171
+ );
3057
3172
  return {
3058
3173
  name,
3059
3174
  ...metadata !== void 0 && { metadata },
@@ -3067,7 +3182,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
3067
3182
  };
3068
3183
  }
3069
3184
  function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
3070
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3185
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3071
3186
  const name = interfaceDecl.name.text;
3072
3187
  const fields = [];
3073
3188
  const typeRegistry = {};
@@ -3109,12 +3224,20 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
3109
3224
  normalizedMetadataPolicy
3110
3225
  );
3111
3226
  const fieldLayouts = specializedFields.map(() => ({}));
3112
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, interfaceDecl, {
3227
+ const metadata = resolveNodeMetadata(
3228
+ normalizedMetadataPolicy,
3229
+ "type",
3230
+ name,
3231
+ interfaceDecl,
3113
3232
  checker,
3114
- declaration: interfaceDecl,
3115
- subjectType: interfaceType,
3116
- hostType: interfaceType
3117
- });
3233
+ extensionRegistry,
3234
+ {
3235
+ checker,
3236
+ declaration: interfaceDecl,
3237
+ subjectType: interfaceType,
3238
+ hostType: interfaceType
3239
+ }
3240
+ );
3118
3241
  return {
3119
3242
  name,
3120
3243
  ...metadata !== void 0 && { metadata },
@@ -3138,7 +3261,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3138
3261
  };
3139
3262
  }
3140
3263
  const typeLiteral = typeAlias.type;
3141
- const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
3264
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3142
3265
  const name = typeAlias.name.text;
3143
3266
  const fields = [];
3144
3267
  const typeRegistry = {};
@@ -3179,12 +3302,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3179
3302
  diagnostics,
3180
3303
  normalizedMetadataPolicy
3181
3304
  );
3182
- const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, typeAlias, {
3305
+ const metadata = resolveNodeMetadata(
3306
+ normalizedMetadataPolicy,
3307
+ "type",
3308
+ name,
3309
+ typeAlias,
3183
3310
  checker,
3184
- declaration: typeAlias,
3185
- subjectType: aliasType,
3186
- hostType: aliasType
3187
- });
3311
+ extensionRegistry,
3312
+ {
3313
+ checker,
3314
+ declaration: typeAlias,
3315
+ subjectType: aliasType,
3316
+ hostType: aliasType
3317
+ }
3318
+ );
3188
3319
  return {
3189
3320
  ok: true,
3190
3321
  analysis: {
@@ -3406,10 +3537,7 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
3406
3537
  if (resolvedAnchorNode === null) {
3407
3538
  return void 0;
3408
3539
  }
3409
- const propertyType = checker.getTypeOfSymbolAtLocation(
3410
- propertySymbol,
3411
- resolvedAnchorNode
3412
- );
3540
+ const propertyType = checker.getTypeOfSymbolAtLocation(propertySymbol, resolvedAnchorNode);
3413
3541
  if (propertyType.isStringLiteral()) {
3414
3542
  return propertyType.value;
3415
3543
  }
@@ -3440,6 +3568,8 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3440
3568
  "type",
3441
3569
  getDiscriminatorLogicalName(boundType, declaration, checker),
3442
3570
  declaration,
3571
+ checker,
3572
+ void 0,
3443
3573
  {
3444
3574
  checker,
3445
3575
  declaration,
@@ -3676,12 +3806,20 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
3676
3806
  annotations.push(defaultAnnotation);
3677
3807
  }
3678
3808
  ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
3679
- const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
3809
+ const metadata = resolveNodeMetadata(
3810
+ metadataPolicy,
3811
+ "field",
3812
+ name,
3813
+ prop,
3680
3814
  checker,
3681
- declaration: prop,
3682
- subjectType: tsType,
3683
- hostType
3684
- });
3815
+ extensionRegistry,
3816
+ {
3817
+ checker,
3818
+ declaration: prop,
3819
+ subjectType: tsType,
3820
+ hostType
3821
+ }
3822
+ );
3685
3823
  return {
3686
3824
  kind: "field",
3687
3825
  name,
@@ -3728,12 +3866,20 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
3728
3866
  let annotations = [];
3729
3867
  annotations.push(...docResult.annotations);
3730
3868
  ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
3731
- const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
3869
+ const metadata = resolveNodeMetadata(
3870
+ metadataPolicy,
3871
+ "field",
3872
+ name,
3873
+ prop,
3732
3874
  checker,
3733
- declaration: prop,
3734
- subjectType: tsType,
3735
- hostType
3736
- });
3875
+ extensionRegistry,
3876
+ {
3877
+ checker,
3878
+ declaration: prop,
3879
+ subjectType: tsType,
3880
+ hostType
3881
+ }
3882
+ );
3737
3883
  return {
3738
3884
  kind: "field",
3739
3885
  name,
@@ -3862,7 +4008,7 @@ function getTypeNodeRegistrationName(typeNode) {
3862
4008
  }
3863
4009
  return null;
3864
4010
  }
3865
- function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4011
+ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3866
4012
  const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
3867
4013
  if (customType) {
3868
4014
  return customType;
@@ -3952,7 +4098,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3952
4098
  }
3953
4099
  return { kind: "primitive", primitiveKind: "string" };
3954
4100
  }
3955
- function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4101
+ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3956
4102
  if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
3957
4103
  return null;
3958
4104
  }
@@ -3972,11 +4118,19 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
3972
4118
  file,
3973
4119
  makeParseOptions(extensionRegistry)
3974
4120
  );
3975
- const metadata = resolveNodeMetadata(metadataPolicy, "type", aliasName, aliasDecl, {
4121
+ const metadata = resolveNodeMetadata(
4122
+ metadataPolicy,
4123
+ "type",
4124
+ aliasName,
4125
+ aliasDecl,
3976
4126
  checker,
3977
- declaration: aliasDecl,
3978
- subjectType: aliasType
3979
- });
4127
+ extensionRegistry,
4128
+ {
4129
+ checker,
4130
+ declaration: aliasDecl,
4131
+ subjectType: aliasType
4132
+ }
4133
+ );
3980
4134
  typeRegistry[aliasName] = {
3981
4135
  name: aliasName,
3982
4136
  ...metadata !== void 0 && { metadata },
@@ -4015,7 +4169,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
4015
4169
  const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
4016
4170
  return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
4017
4171
  }
4018
- function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4172
+ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4019
4173
  const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
4020
4174
  if (nestedAliasDecl !== void 0) {
4021
4175
  return resolveAliasedPrimitiveTarget(
@@ -4041,7 +4195,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
4041
4195
  diagnostics
4042
4196
  );
4043
4197
  }
4044
- function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4198
+ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4045
4199
  const typeName = getNamedTypeName(type);
4046
4200
  const namedDecl = getNamedTypeDeclaration(type);
4047
4201
  if (typeName && typeName in typeRegistry) {
@@ -4076,11 +4230,19 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
4076
4230
  return result;
4077
4231
  }
4078
4232
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4079
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", typeName, namedDecl, {
4233
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4234
+ metadataPolicy,
4235
+ "type",
4236
+ typeName,
4237
+ namedDecl,
4080
4238
  checker,
4081
- declaration: namedDecl,
4082
- subjectType: type
4083
- }) : void 0;
4239
+ extensionRegistry,
4240
+ {
4241
+ checker,
4242
+ declaration: namedDecl,
4243
+ subjectType: type
4244
+ }
4245
+ ) : void 0;
4084
4246
  typeRegistry[typeName] = {
4085
4247
  name: typeName,
4086
4248
  ...metadata !== void 0 && { metadata },
@@ -4165,7 +4327,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
4165
4327
  }
4166
4328
  return registerNamed({ kind: "union", members });
4167
4329
  }
4168
- function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4330
+ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4169
4331
  const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
4170
4332
  const elementType = typeArgs?.[0];
4171
4333
  const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
@@ -4182,7 +4344,7 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
4182
4344
  ) : { kind: "primitive", primitiveKind: "string" };
4183
4345
  return { kind: "array", items };
4184
4346
  }
4185
- function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4347
+ function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4186
4348
  if (type.getProperties().length > 0) {
4187
4349
  return null;
4188
4350
  }
@@ -4243,7 +4405,7 @@ function shouldEmitResolvedObjectProperty(property, declaration) {
4243
4405
  }
4244
4406
  return true;
4245
4407
  }
4246
- function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4408
+ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
4247
4409
  const collectedDiagnostics = diagnostics ?? [];
4248
4410
  const typeName = getNamedTypeName(type);
4249
4411
  const namedTypeName = typeName ?? void 0;
@@ -4319,11 +4481,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4319
4481
  return recordNode;
4320
4482
  }
4321
4483
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4322
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
4484
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4485
+ metadataPolicy,
4486
+ "type",
4487
+ registryTypeName,
4488
+ namedDecl,
4323
4489
  checker,
4324
- declaration: namedDecl,
4325
- subjectType: type
4326
- }) : void 0;
4490
+ extensionRegistry,
4491
+ {
4492
+ checker,
4493
+ declaration: namedDecl,
4494
+ subjectType: type
4495
+ }
4496
+ ) : void 0;
4327
4497
  typeRegistry[registryTypeName] = {
4328
4498
  name: registryTypeName,
4329
4499
  ...metadata !== void 0 && { metadata },
@@ -4368,14 +4538,39 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4368
4538
  collectedDiagnostics
4369
4539
  );
4370
4540
  const fieldNodeInfo = fieldInfoMap?.get(prop.name);
4541
+ const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts3.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
4542
+ declaration,
4543
+ checker,
4544
+ file,
4545
+ typeRegistry,
4546
+ visiting,
4547
+ collectedDiagnostics,
4548
+ type,
4549
+ metadataPolicy,
4550
+ extensionRegistry
4551
+ ) : ts3.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
4552
+ declaration,
4553
+ checker,
4554
+ file,
4555
+ typeRegistry,
4556
+ visiting,
4557
+ collectedDiagnostics,
4558
+ type,
4559
+ metadataPolicy,
4560
+ extensionRegistry
4561
+ ) : null : null;
4562
+ const resolvedFieldNodeInfo = fieldNodeInfo ?? inlineFieldNodeInfo;
4563
+ const resolvedPropertyType = inlineFieldNodeInfo?.type ?? propTypeNode;
4371
4564
  properties.push({
4372
4565
  name: prop.name,
4373
- ...fieldNodeInfo?.metadata !== void 0 && { metadata: fieldNodeInfo.metadata },
4374
- type: propTypeNode,
4566
+ ...resolvedFieldNodeInfo?.metadata !== void 0 && {
4567
+ metadata: resolvedFieldNodeInfo.metadata
4568
+ },
4569
+ type: resolvedPropertyType,
4375
4570
  optional,
4376
- constraints: fieldNodeInfo?.constraints ?? [],
4377
- annotations: fieldNodeInfo?.annotations ?? [],
4378
- provenance: fieldNodeInfo?.provenance ?? provenanceForFile(file)
4571
+ constraints: resolvedFieldNodeInfo?.constraints ?? [],
4572
+ annotations: resolvedFieldNodeInfo?.annotations ?? [],
4573
+ provenance: resolvedFieldNodeInfo?.provenance ?? provenanceForFile(file)
4379
4574
  });
4380
4575
  }
4381
4576
  visiting.delete(type);
@@ -4394,11 +4589,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4394
4589
  };
4395
4590
  if (registryTypeName !== void 0 && shouldRegisterNamedType) {
4396
4591
  const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
4397
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
4592
+ const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
4593
+ metadataPolicy,
4594
+ "type",
4595
+ registryTypeName,
4596
+ namedDecl,
4398
4597
  checker,
4399
- declaration: namedDecl,
4400
- subjectType: type
4401
- }) : void 0;
4598
+ extensionRegistry,
4599
+ {
4600
+ checker,
4601
+ declaration: namedDecl,
4602
+ subjectType: type
4603
+ }
4604
+ ) : void 0;
4402
4605
  typeRegistry[registryTypeName] = {
4403
4606
  name: registryTypeName,
4404
4607
  ...metadata !== void 0 && { metadata },
@@ -5020,6 +5223,360 @@ var init_class_schema = __esm({
5020
5223
  }
5021
5224
  });
5022
5225
 
5226
+ // src/static-build.ts
5227
+ import * as ts6 from "typescript";
5228
+ function toStaticBuildContext(context) {
5229
+ return context;
5230
+ }
5231
+ function createStaticBuildContext(filePath) {
5232
+ return toStaticBuildContext(createProgramContext(filePath));
5233
+ }
5234
+ function createStaticBuildContextFromProgram(program, filePath) {
5235
+ return toStaticBuildContext(createProgramContextFromProgram(program, filePath));
5236
+ }
5237
+ function getModuleSymbol(context) {
5238
+ const sourceFileWithSymbol = context.sourceFile;
5239
+ return context.checker.getSymbolAtLocation(context.sourceFile) ?? sourceFileWithSymbol.symbol;
5240
+ }
5241
+ function isSchemaSourceDeclaration(declaration) {
5242
+ return ts6.isClassDeclaration(declaration) || ts6.isInterfaceDeclaration(declaration) || ts6.isTypeAliasDeclaration(declaration);
5243
+ }
5244
+ function resolveModuleExport(context, exportName = "default") {
5245
+ const moduleSymbol = getModuleSymbol(context);
5246
+ if (moduleSymbol === void 0) {
5247
+ return null;
5248
+ }
5249
+ const exportSymbol = context.checker.getExportsOfModule(moduleSymbol).find((candidate) => candidate.name === exportName) ?? null;
5250
+ if (exportSymbol === null) {
5251
+ return null;
5252
+ }
5253
+ return exportSymbol.flags & ts6.SymbolFlags.Alias ? context.checker.getAliasedSymbol(exportSymbol) : exportSymbol;
5254
+ }
5255
+ function resolveModuleExportDeclaration(context, exportName = "default") {
5256
+ return resolveModuleExport(context, exportName)?.declarations?.find(isSchemaSourceDeclaration) ?? null;
5257
+ }
5258
+ var init_static_build = __esm({
5259
+ "src/static-build.ts"() {
5260
+ "use strict";
5261
+ init_program();
5262
+ }
5263
+ });
5264
+
5265
+ // src/generators/discovered-schema.ts
5266
+ import * as ts7 from "typescript";
5267
+ import { IR_VERSION as IR_VERSION3 } from "@formspec/core/internals";
5268
+ function toDiscoveredTypeSchemas(result) {
5269
+ return result;
5270
+ }
5271
+ function isNamedTypeDeclaration(declaration) {
5272
+ return ts7.isClassDeclaration(declaration) || ts7.isInterfaceDeclaration(declaration) || ts7.isTypeAliasDeclaration(declaration);
5273
+ }
5274
+ function hasConcreteTypeArguments(type, checker) {
5275
+ if ("aliasTypeArguments" in type && Array.isArray(type.aliasTypeArguments) && type.aliasTypeArguments.length > 0) {
5276
+ return true;
5277
+ }
5278
+ if ((type.flags & ts7.TypeFlags.Object) === 0) {
5279
+ return false;
5280
+ }
5281
+ const objectType = type;
5282
+ if ((objectType.objectFlags & ts7.ObjectFlags.Reference) === 0) {
5283
+ return false;
5284
+ }
5285
+ return checker.getTypeArguments(objectType).length > 0;
5286
+ }
5287
+ function getNamedTypeDeclaration2(type) {
5288
+ const symbol = type.getSymbol();
5289
+ if (symbol?.declarations !== void 0) {
5290
+ const declaration = symbol.declarations[0];
5291
+ if (declaration !== void 0 && isNamedTypeDeclaration(declaration)) {
5292
+ return declaration;
5293
+ }
5294
+ }
5295
+ const aliasDeclaration = type.aliasSymbol?.declarations?.find(ts7.isTypeAliasDeclaration);
5296
+ return aliasDeclaration;
5297
+ }
5298
+ function getFallbackName(sourceNode, fallback = "AnonymousType") {
5299
+ if (sourceNode !== void 0 && "name" in sourceNode) {
5300
+ const namedNode = sourceNode;
5301
+ if (namedNode.name !== void 0 && ts7.isIdentifier(namedNode.name)) {
5302
+ return namedNode.name.text;
5303
+ }
5304
+ }
5305
+ return fallback;
5306
+ }
5307
+ function createObjectRootAnalysis(name, properties, typeRegistry, metadata, annotations) {
5308
+ const fields = properties.map((property) => ({
5309
+ kind: "field",
5310
+ name: property.name,
5311
+ ...property.metadata !== void 0 && { metadata: property.metadata },
5312
+ type: property.type,
5313
+ required: !property.optional,
5314
+ constraints: property.constraints,
5315
+ annotations: property.annotations,
5316
+ provenance: property.provenance
5317
+ }));
5318
+ return {
5319
+ name,
5320
+ ...metadata !== void 0 && { metadata },
5321
+ fields,
5322
+ fieldLayouts: fields.map(() => ({})),
5323
+ typeRegistry,
5324
+ ...annotations !== void 0 && annotations.length > 0 && { annotations },
5325
+ instanceMethods: [],
5326
+ staticMethods: [],
5327
+ diagnostics: []
5328
+ };
5329
+ }
5330
+ function omitApiName(metadata) {
5331
+ if (metadata?.apiName === void 0) {
5332
+ return metadata;
5333
+ }
5334
+ const { apiName: _apiName, ...rest } = metadata;
5335
+ return Object.keys(rest).length > 0 ? rest : void 0;
5336
+ }
5337
+ function describeRootType(rootType, typeRegistry, fallbackName) {
5338
+ if (rootType.kind !== "reference") {
5339
+ return {
5340
+ name: fallbackName,
5341
+ type: rootType
5342
+ };
5343
+ }
5344
+ const definition = typeRegistry[rootType.name];
5345
+ if (definition === void 0) {
5346
+ return {
5347
+ name: rootType.name,
5348
+ type: rootType
5349
+ };
5350
+ }
5351
+ return {
5352
+ name: definition.name,
5353
+ ...definition.metadata !== void 0 && { metadata: definition.metadata },
5354
+ ...definition.annotations !== void 0 && definition.annotations.length > 0 && { annotations: definition.annotations },
5355
+ type: definition.type
5356
+ };
5357
+ }
5358
+ function toStandaloneJsonSchema(root, typeRegistry, options) {
5359
+ const syntheticFieldMetadata = omitApiName(root.metadata);
5360
+ const syntheticField = {
5361
+ kind: "field",
5362
+ name: "__result",
5363
+ ...syntheticFieldMetadata !== void 0 && { metadata: syntheticFieldMetadata },
5364
+ type: root.type,
5365
+ required: true,
5366
+ constraints: [],
5367
+ annotations: [...root.annotations ?? []],
5368
+ provenance: {
5369
+ surface: "tsdoc",
5370
+ file: "",
5371
+ line: 1,
5372
+ column: 0
5373
+ }
5374
+ };
5375
+ const schema = generateJsonSchemaFromIR(
5376
+ {
5377
+ kind: "form-ir",
5378
+ name: root.name,
5379
+ irVersion: IR_VERSION3,
5380
+ elements: [syntheticField],
5381
+ ...root.metadata !== void 0 && { metadata: root.metadata },
5382
+ ...root.annotations !== void 0 && root.annotations.length > 0 && { rootAnnotations: root.annotations },
5383
+ typeRegistry,
5384
+ provenance: syntheticField.provenance
5385
+ },
5386
+ {
5387
+ extensionRegistry: options?.extensionRegistry,
5388
+ vendorPrefix: options?.vendorPrefix
5389
+ }
5390
+ );
5391
+ const result = schema.properties?.["__result"];
5392
+ if (result === void 0) {
5393
+ throw new Error("FormSpec failed to extract the standalone schema root from the synthetic IR.");
5394
+ }
5395
+ if (schema.$defs === void 0 || Object.keys(schema.$defs).length === 0) {
5396
+ return {
5397
+ ...schema.$schema !== void 0 && { $schema: schema.$schema },
5398
+ ...result
5399
+ };
5400
+ }
5401
+ return {
5402
+ ...schema.$schema !== void 0 && { $schema: schema.$schema },
5403
+ ...result,
5404
+ $defs: schema.$defs
5405
+ };
5406
+ }
5407
+ function generateSchemasFromAnalysis(analysis, filePath, options) {
5408
+ return toDiscoveredTypeSchemas(
5409
+ generateClassSchemas(
5410
+ analysis,
5411
+ { file: filePath },
5412
+ {
5413
+ extensionRegistry: options?.extensionRegistry,
5414
+ metadata: options?.metadata,
5415
+ vendorPrefix: options?.vendorPrefix
5416
+ }
5417
+ )
5418
+ );
5419
+ }
5420
+ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false, rootOverride) {
5421
+ const namedDeclaration = skipNamedDeclaration || hasConcreteTypeArguments(options.type, options.context.checker) ? void 0 : getNamedTypeDeclaration2(options.type);
5422
+ if (namedDeclaration !== void 0) {
5423
+ return generateSchemasFromDeclaration({
5424
+ ...options,
5425
+ declaration: namedDeclaration
5426
+ });
5427
+ }
5428
+ const filePath = options.sourceNode?.getSourceFile().fileName ?? options.context.sourceFile.fileName;
5429
+ const typeRegistry = {};
5430
+ const diagnostics = [];
5431
+ const rootType = resolveTypeNode(
5432
+ options.type,
5433
+ options.context.checker,
5434
+ filePath,
5435
+ typeRegistry,
5436
+ /* @__PURE__ */ new Set(),
5437
+ options.sourceNode,
5438
+ createAnalyzerMetadataPolicy(options.metadata),
5439
+ options.extensionRegistry,
5440
+ diagnostics
5441
+ );
5442
+ if (diagnostics.length > 0) {
5443
+ const diagnosticDetails = diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
5444
+ throw new Error(
5445
+ `FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
5446
+ );
5447
+ }
5448
+ const describedRoot = describeRootType(
5449
+ rootType,
5450
+ typeRegistry,
5451
+ options.name ?? getFallbackName(options.sourceNode)
5452
+ );
5453
+ const mergedMetadata = mergeResolvedMetadata(describedRoot.metadata, rootOverride?.metadata);
5454
+ const root = {
5455
+ ...describedRoot,
5456
+ ...rootOverride?.name !== void 0 && { name: rootOverride.name },
5457
+ ...mergedMetadata !== void 0 && { metadata: mergedMetadata },
5458
+ ...rootOverride?.annotations !== void 0 && { annotations: rootOverride.annotations }
5459
+ };
5460
+ if (root.type.kind === "object") {
5461
+ return generateSchemasFromAnalysis(
5462
+ createObjectRootAnalysis(
5463
+ options.name ?? root.name,
5464
+ root.type.properties,
5465
+ typeRegistry,
5466
+ root.metadata,
5467
+ root.annotations
5468
+ ),
5469
+ filePath,
5470
+ options
5471
+ );
5472
+ }
5473
+ return {
5474
+ jsonSchema: toStandaloneJsonSchema(root, typeRegistry, options),
5475
+ uiSchema: null
5476
+ };
5477
+ }
5478
+ function generateSchemasFromDeclaration(options) {
5479
+ const filePath = options.declaration.getSourceFile().fileName;
5480
+ if (ts7.isClassDeclaration(options.declaration)) {
5481
+ return generateSchemasFromAnalysis(
5482
+ analyzeClassToIR(
5483
+ options.declaration,
5484
+ options.context.checker,
5485
+ filePath,
5486
+ options.extensionRegistry,
5487
+ options.metadata
5488
+ ),
5489
+ filePath,
5490
+ options
5491
+ );
5492
+ }
5493
+ if (ts7.isInterfaceDeclaration(options.declaration)) {
5494
+ return generateSchemasFromAnalysis(
5495
+ analyzeInterfaceToIR(
5496
+ options.declaration,
5497
+ options.context.checker,
5498
+ filePath,
5499
+ options.extensionRegistry,
5500
+ options.metadata
5501
+ ),
5502
+ filePath,
5503
+ options
5504
+ );
5505
+ }
5506
+ if (ts7.isTypeAliasDeclaration(options.declaration)) {
5507
+ const analyzedAlias = analyzeTypeAliasToIR(
5508
+ options.declaration,
5509
+ options.context.checker,
5510
+ filePath,
5511
+ options.extensionRegistry,
5512
+ options.metadata
5513
+ );
5514
+ if (analyzedAlias.ok) {
5515
+ return generateSchemasFromAnalysis(analyzedAlias.analysis, filePath, options);
5516
+ }
5517
+ const aliasRootInfo = analyzeDeclarationRootInfo(
5518
+ options.declaration,
5519
+ options.context.checker,
5520
+ filePath,
5521
+ options.extensionRegistry,
5522
+ options.metadata
5523
+ );
5524
+ if (aliasRootInfo.diagnostics.length > 0) {
5525
+ const diagnosticDetails = aliasRootInfo.diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("; ");
5526
+ throw new Error(
5527
+ `FormSpec validation failed while generating discovered type schemas. ${diagnosticDetails}`
5528
+ );
5529
+ }
5530
+ return generateSchemasFromResolvedType(
5531
+ {
5532
+ ...options,
5533
+ type: options.context.checker.getTypeAtLocation(options.declaration),
5534
+ sourceNode: options.declaration,
5535
+ name: options.declaration.name.text
5536
+ },
5537
+ true,
5538
+ {
5539
+ name: options.declaration.name.text,
5540
+ ...aliasRootInfo.metadata !== void 0 && { metadata: aliasRootInfo.metadata },
5541
+ ...aliasRootInfo.annotations.length > 0 && { annotations: aliasRootInfo.annotations }
5542
+ }
5543
+ );
5544
+ }
5545
+ const _exhaustive = options.declaration;
5546
+ return _exhaustive;
5547
+ }
5548
+ function generateSchemasFromType(options) {
5549
+ return generateSchemasFromResolvedType(options);
5550
+ }
5551
+ function generateSchemasFromParameter(options) {
5552
+ return generateSchemasFromResolvedType({
5553
+ ...options,
5554
+ type: options.context.checker.getTypeAtLocation(options.parameter),
5555
+ sourceNode: options.parameter,
5556
+ name: getFallbackName(options.parameter, "Parameter")
5557
+ });
5558
+ }
5559
+ function generateSchemasFromReturnType(options) {
5560
+ const signature = options.context.checker.getSignatureFromDeclaration(options.declaration);
5561
+ const type = signature !== void 0 ? options.context.checker.getReturnTypeOfSignature(signature) : options.context.checker.getTypeAtLocation(options.declaration);
5562
+ const fallbackName = options.declaration.name !== void 0 && ts7.isIdentifier(options.declaration.name) ? `${options.declaration.name.text}ReturnType` : "ReturnType";
5563
+ return generateSchemasFromResolvedType({
5564
+ ...options,
5565
+ type,
5566
+ sourceNode: options.declaration.type ?? options.declaration,
5567
+ name: fallbackName
5568
+ });
5569
+ }
5570
+ var init_discovered_schema = __esm({
5571
+ "src/generators/discovered-schema.ts"() {
5572
+ "use strict";
5573
+ init_class_analyzer();
5574
+ init_class_schema();
5575
+ init_ir_generator();
5576
+ init_metadata();
5577
+ }
5578
+ });
5579
+
5023
5580
  // src/generators/mixed-authoring.ts
5024
5581
  function buildMixedAuthoringSchemas(options) {
5025
5582
  const { filePath, typeName, overlays, ...schemaOptions } = options;
@@ -5226,12 +5783,20 @@ __export(index_exports, {
5226
5783
  buildFormSchemas: () => buildFormSchemas,
5227
5784
  buildMixedAuthoringSchemas: () => buildMixedAuthoringSchemas,
5228
5785
  createExtensionRegistry: () => createExtensionRegistry,
5786
+ createStaticBuildContext: () => createStaticBuildContext,
5787
+ createStaticBuildContextFromProgram: () => createStaticBuildContextFromProgram,
5229
5788
  generateJsonSchema: () => generateJsonSchema,
5230
5789
  generateSchemas: () => generateSchemas,
5231
5790
  generateSchemasFromClass: () => generateSchemasFromClass,
5791
+ generateSchemasFromDeclaration: () => generateSchemasFromDeclaration,
5792
+ generateSchemasFromParameter: () => generateSchemasFromParameter,
5232
5793
  generateSchemasFromProgram: () => generateSchemasFromProgram,
5794
+ generateSchemasFromReturnType: () => generateSchemasFromReturnType,
5795
+ generateSchemasFromType: () => generateSchemasFromType,
5233
5796
  generateUiSchema: () => generateUiSchema,
5234
5797
  jsonSchema7Schema: () => jsonSchema7Schema,
5798
+ resolveModuleExport: () => resolveModuleExport,
5799
+ resolveModuleExportDeclaration: () => resolveModuleExportDeclaration,
5235
5800
  uiSchemaSchema: () => uiSchema,
5236
5801
  writeSchemas: () => writeSchemas
5237
5802
  });
@@ -5268,6 +5833,8 @@ var init_index = __esm({
5268
5833
  init_generator();
5269
5834
  init_generator2();
5270
5835
  init_class_schema();
5836
+ init_static_build();
5837
+ init_discovered_schema();
5271
5838
  init_mixed_authoring();
5272
5839
  }
5273
5840
  });