@openpkg-ts/sdk 0.38.0 → 0.40.0

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.d.ts CHANGED
@@ -1551,7 +1551,7 @@ interface ProgramResult {
1551
1551
  /** Resolved project references (workspace packages) */
1552
1552
  projectReferences?: ts7.ResolvedProjectReference[];
1553
1553
  }
1554
- declare function createProgram({ entryFile, baseDir, content }: ProgramOptions): ProgramResult;
1554
+ declare function createProgram(options: ProgramOptions): ProgramResult;
1555
1555
  import * as TS from "typescript";
1556
1556
  /**
1557
1557
  * A schema adapter can detect and extract output types from a specific
@@ -1675,6 +1675,14 @@ declare function ensureNonEmptySchema(schema: SpecSchema2, type: ts15.Type, chec
1675
1675
  */
1676
1676
  declare function buildSchema(type: ts15.Type, checker: ts15.TypeChecker, ctx?: SerializerContext): SpecSchema2;
1677
1677
  /**
1678
+ * Build schema for function types
1679
+ */
1680
+ declare function buildFunctionSchema(callSignatures: readonly ts15.Signature[], checker: ts15.TypeChecker, ctx: SerializerContext | undefined): SpecSchema2;
1681
+ /**
1682
+ * Build schema for object types with properties
1683
+ */
1684
+ declare function buildObjectSchema(properties: ts15.Symbol[], checker: ts15.TypeChecker, ctx: SerializerContext | undefined, originalType?: ts15.Type): SpecSchema2;
1685
+ /**
1678
1686
  * Check if a schema is a pure $ref (only has $ref property)
1679
1687
  */
1680
1688
  declare function isPureRefSchema(schema: SpecSchema2): schema is {
@@ -1767,4 +1775,4 @@ declare function normalizeMembers(members: SpecMember3[], options?: NormalizeOpt
1767
1775
  import ts16 from "typescript";
1768
1776
  declare function isExported(node: ts16.Node): boolean;
1769
1777
  declare function getNodeName(node: ts16.Node): string | undefined;
1770
- export { zodAdapter, withDescription2 as withDescription, valibotAdapter, typeboxAdapter, toSearchIndexJSON, toSearchIndex2 as toSearchIndex, toPagefindRecords2 as toPagefindRecords, toNavigation2 as toNavigation, toMarkdown2 as toMarkdown, toJSONString, toJSON2 as toJSON, toHTML2 as toHTML, toFumadocsMetaJSON, toDocusaurusSidebarJS, toAlgoliaRecords2 as toAlgoliaRecords, sortByName, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, schemasAreEqual, schemaIsAny, resolveTypeRef, resolveExportTarget, resolveCompiledPath, registerReferencedTypes, registerAdapter, recommendSemverBump, query, normalizeType, normalizeSchema, normalizeMembers, normalizeExport, mergeConfig, loadSpec, loadConfig, listExports, isTypeReference, isTypeOnlyExport, isSymbolDeprecated, isStandardJSONSchema, isSchemaType, isPureRefSchema, isProperty, isPrimitiveName, isMethod, isExported, isBuiltinGeneric, isAnonymous, hasDeprecatedTag, groupByVisibility, getTypeOrigin, getSourceLocation, getProperties, getParamDescription, getNonNullableType, getNodeName, getMethods, getMemberBadges, getJSDocComment, getExportKind, getExport2 as getExport, getDeprecationMessage, toMarkdown2 as generateDocs, formatTypeParameters, formatSchema, formatReturnType, formatParameters, formatMappedType, formatConditionalType, formatBadges, findMissingParamDocs, findDiscriminatorProperty, findAdapter, filterSpec, extractTypeParameters, extractStandardSchemasFromTs, extractStandardSchemasFromProject, extractStandardSchemas, extractSpec, extractSchemaType, extractParameters, extract, exportToMarkdown, ensureNonEmptySchema, diffSpec2 as diffSpecs, diffSpec, detectTsRuntime, deduplicateSchemas, createProgram, createDocs, categorizeBreakingChanges, calculateNextVersion, buildSignatureString, buildSchema, arktypeAdapter, analyzeSpec, TypeRegistry, TypeReference2 as TypeReference, TsRuntime, StandardSchemaExtractionResult, StandardSchemaExtractionOutput, StandardJSONSchemaV1, StandardJSONSchemaTarget, StandardJSONSchemaOptions, SpecMappedType, SpecDiff, SpecDiagnostics, SpecConditionalType, SkippedExportDetail, SimplifiedSpec, SimplifiedSignature, SimplifiedReturn, SimplifiedParameter, SimplifiedMember, SimplifiedExport, SimplifiedExample, SerializerContext, SemverRecommendation, SemverBump, SearchRecord, SearchOptions, SearchIndex, SchemaExtractionResult, SchemaAdapter, STRING_PROTOTYPE_METHODS, QueryBuilder, ProjectExtractionOutput, ProjectExtractionInfo, ProgramResult, ProgramOptions, PagefindRecord, PRIMITIVES, OpenpkgConfig, NormalizeOptions, NavOptions, NavItem, NavGroup, NavFormat, NUMBER_PROTOTYPE_METHODS, MemberChangeInfo, MarkdownOptions, LoadOptions, ListExportsResult, ListExportsOptions, JSONSchema, JSONOptions, HTMLOptions, GroupBy, GetExportResult, GetExportOptions, GenericNav, FumadocsMetaItem, FumadocsMeta, FormatSchemaOptions, ForgottenExport, FilterResult, FilterCriteria, ExtractionWarningCode, ExtractionWarning, ExtractStandardSchemasOptions, ExtractResult, ExtractOptions, ExtractFromProjectOptions, ExternalsConfig, ExportVerification, ExportTracker, ExportMarkdownOptions, ExportItem, DocusaurusSidebarItem, DocusaurusSidebar, DocsInstance, DiagnosticItem, Diagnostic, CategorizedBreaking, CacheManagerOptions, CacheManager, CONFIG_FILENAME, BreakingSeverity, BUILTIN_TYPE_SCHEMAS, AlgoliaRecord, ARRAY_PROTOTYPE_METHODS };
1778
+ export { zodAdapter, withDescription2 as withDescription, valibotAdapter, typeboxAdapter, toSearchIndexJSON, toSearchIndex2 as toSearchIndex, toPagefindRecords2 as toPagefindRecords, toNavigation2 as toNavigation, toMarkdown2 as toMarkdown, toJSONString, toJSON2 as toJSON, toHTML2 as toHTML, toFumadocsMetaJSON, toDocusaurusSidebarJS, toAlgoliaRecords2 as toAlgoliaRecords, sortByName, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, schemasAreEqual, schemaIsAny, resolveTypeRef, resolveExportTarget, resolveCompiledPath, registerReferencedTypes, registerAdapter, recommendSemverBump, query, normalizeType, normalizeSchema, normalizeMembers, normalizeExport, mergeConfig, loadSpec, loadConfig, listExports, isTypeReference, isTypeOnlyExport, isSymbolDeprecated, isStandardJSONSchema, isSchemaType, isPureRefSchema, isProperty, isPrimitiveName, isMethod, isExported, isBuiltinGeneric, isAnonymous, hasDeprecatedTag, groupByVisibility, getTypeOrigin, getSourceLocation, getProperties, getParamDescription, getNonNullableType, getNodeName, getMethods, getMemberBadges, getJSDocComment, getExportKind, getExport2 as getExport, getDeprecationMessage, toMarkdown2 as generateDocs, formatTypeParameters, formatSchema, formatReturnType, formatParameters, formatMappedType, formatConditionalType, formatBadges, findMissingParamDocs, findDiscriminatorProperty, findAdapter, filterSpec, extractTypeParameters, extractStandardSchemasFromTs, extractStandardSchemasFromProject, extractStandardSchemas, extractSpec, extractSchemaType, extractParameters, extract, exportToMarkdown, ensureNonEmptySchema, diffSpec2 as diffSpecs, diffSpec, detectTsRuntime, deduplicateSchemas, createProgram, createDocs, categorizeBreakingChanges, calculateNextVersion, buildSignatureString, buildSchema, buildObjectSchema, buildFunctionSchema, arktypeAdapter, analyzeSpec, TypeRegistry, TypeReference2 as TypeReference, TsRuntime, StandardSchemaExtractionResult, StandardSchemaExtractionOutput, StandardJSONSchemaV1, StandardJSONSchemaTarget, StandardJSONSchemaOptions, SpecMappedType, SpecDiff, SpecDiagnostics, SpecConditionalType, SkippedExportDetail, SimplifiedSpec, SimplifiedSignature, SimplifiedReturn, SimplifiedParameter, SimplifiedMember, SimplifiedExport, SimplifiedExample, SerializerContext, SemverRecommendation, SemverBump, SearchRecord, SearchOptions, SearchIndex, SchemaExtractionResult, SchemaAdapter, STRING_PROTOTYPE_METHODS, QueryBuilder, ProjectExtractionOutput, ProjectExtractionInfo, ProgramResult, ProgramOptions, PagefindRecord, PRIMITIVES, OpenpkgConfig, NormalizeOptions, NavOptions, NavItem, NavGroup, NavFormat, NUMBER_PROTOTYPE_METHODS, MemberChangeInfo, MarkdownOptions, LoadOptions, ListExportsResult, ListExportsOptions, JSONSchema, JSONOptions, HTMLOptions, GroupBy, GetExportResult, GetExportOptions, GenericNav, FumadocsMetaItem, FumadocsMeta, FormatSchemaOptions, ForgottenExport, FilterResult, FilterCriteria, ExtractionWarningCode, ExtractionWarning, ExtractStandardSchemasOptions, ExtractResult, ExtractOptions, ExtractFromProjectOptions, ExternalsConfig, ExportVerification, ExportTracker, ExportMarkdownOptions, ExportItem, DocusaurusSidebarItem, DocusaurusSidebar, DocsInstance, DiagnosticItem, Diagnostic, CategorizedBreaking, CacheManagerOptions, CacheManager, CONFIG_FILENAME, BreakingSeverity, BUILTIN_TYPE_SCHEMAS, AlgoliaRecord, ARRAY_PROTOTYPE_METHODS };
package/dist/index.js CHANGED
@@ -1298,6 +1298,7 @@ function filterSpec(spec, criteria) {
1298
1298
  import ts11 from "typescript";
1299
1299
 
1300
1300
  // src/ast/utils.ts
1301
+ import * as path2 from "node:path";
1301
1302
  import ts from "typescript";
1302
1303
  function parseExamplesFromTags(tags) {
1303
1304
  const examples = [];
@@ -1442,8 +1443,10 @@ function getJSDocComment(node, symbol, checker) {
1442
1443
  }
1443
1444
  function getSourceLocation(node, sourceFile) {
1444
1445
  const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
1446
+ const relative2 = path2.relative(process.cwd(), sourceFile.fileName);
1447
+ const file = relative2.startsWith("..") ? sourceFile.fileName : relative2;
1445
1448
  return {
1446
- file: sourceFile.fileName,
1449
+ file,
1447
1450
  line: line + 1
1448
1451
  };
1449
1452
  }
@@ -1614,7 +1617,7 @@ function getExportKind(declaration, type) {
1614
1617
 
1615
1618
  // src/compiler/program.ts
1616
1619
  import * as fs3 from "node:fs";
1617
- import * as path2 from "node:path";
1620
+ import * as path3 from "node:path";
1618
1621
  import ts2 from "typescript";
1619
1622
  function isJsFile(file) {
1620
1623
  return /\.(js|mjs|cjs|jsx)$/.test(file);
@@ -1633,23 +1636,40 @@ var DEFAULT_COMPILER_OPTIONS = {
1633
1636
  module: ts2.ModuleKind.CommonJS,
1634
1637
  lib: ["lib.es2021.d.ts"],
1635
1638
  declaration: true,
1636
- moduleResolution: ts2.ModuleResolutionKind.NodeJs
1639
+ moduleResolution: ts2.ModuleResolutionKind.NodeJs,
1640
+ strict: true
1637
1641
  };
1642
+ function resolveWorkspaceEntry(pkgDir) {
1643
+ const candidates = [
1644
+ path3.join(pkgDir, "src", "index.ts"),
1645
+ path3.join(pkgDir, "src", "index.tsx"),
1646
+ path3.join(pkgDir, "index.ts")
1647
+ ];
1648
+ try {
1649
+ const pkg = JSON.parse(fs3.readFileSync(path3.join(pkgDir, "package.json"), "utf-8"));
1650
+ for (const field of [pkg.types, pkg.typings]) {
1651
+ if (typeof field === "string") {
1652
+ candidates.push(path3.resolve(pkgDir, field));
1653
+ }
1654
+ }
1655
+ } catch {}
1656
+ return candidates.find((c) => fs3.existsSync(c));
1657
+ }
1638
1658
  function resolveProjectReferences(configPath, parsedConfig) {
1639
1659
  const additionalFiles = [];
1640
1660
  if (!parsedConfig.projectReferences?.length) {
1641
1661
  return additionalFiles;
1642
1662
  }
1643
- const configDir = path2.dirname(configPath);
1663
+ const configDir = path3.dirname(configPath);
1644
1664
  for (const ref of parsedConfig.projectReferences) {
1645
- const refPath = path2.resolve(configDir, ref.path);
1646
- const refConfigPath = fs3.existsSync(path2.join(refPath, "tsconfig.json")) ? path2.join(refPath, "tsconfig.json") : refPath;
1665
+ const refPath = path3.resolve(configDir, ref.path);
1666
+ const refConfigPath = fs3.existsSync(path3.join(refPath, "tsconfig.json")) ? path3.join(refPath, "tsconfig.json") : refPath;
1647
1667
  if (!fs3.existsSync(refConfigPath))
1648
1668
  continue;
1649
1669
  const refConfigFile = ts2.readConfigFile(refConfigPath, ts2.sys.readFile);
1650
1670
  if (refConfigFile.error)
1651
1671
  continue;
1652
- const refParsed = ts2.parseJsonConfigFileContent(refConfigFile.config, ts2.sys, path2.dirname(refConfigPath));
1672
+ const refParsed = ts2.parseJsonConfigFileContent(refConfigFile.config, ts2.sys, path3.dirname(refConfigPath));
1653
1673
  additionalFiles.push(...refParsed.fileNames);
1654
1674
  }
1655
1675
  return additionalFiles;
@@ -1682,7 +1702,7 @@ function buildWorkspaceMap(baseDir) {
1682
1702
  let rootDir;
1683
1703
  let workspaceGlobs = [];
1684
1704
  for (let i = 0;i < 10; i++) {
1685
- const pnpmPath = path2.join(currentDir, "pnpm-workspace.yaml");
1705
+ const pnpmPath = path3.join(currentDir, "pnpm-workspace.yaml");
1686
1706
  if (fs3.existsSync(pnpmPath)) {
1687
1707
  try {
1688
1708
  const yamlContent = fs3.readFileSync(pnpmPath, "utf-8");
@@ -1693,7 +1713,7 @@ function buildWorkspaceMap(baseDir) {
1693
1713
  }
1694
1714
  } catch {}
1695
1715
  }
1696
- const pkgPath = path2.join(currentDir, "package.json");
1716
+ const pkgPath = path3.join(currentDir, "package.json");
1697
1717
  if (fs3.existsSync(pkgPath)) {
1698
1718
  try {
1699
1719
  const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
@@ -1704,7 +1724,7 @@ function buildWorkspaceMap(baseDir) {
1704
1724
  }
1705
1725
  } catch {}
1706
1726
  }
1707
- const parent = path2.dirname(currentDir);
1727
+ const parent = path3.dirname(currentDir);
1708
1728
  if (parent === currentDir)
1709
1729
  break;
1710
1730
  currentDir = parent;
@@ -1713,33 +1733,31 @@ function buildWorkspaceMap(baseDir) {
1713
1733
  return;
1714
1734
  const packages = new Map;
1715
1735
  for (const glob of workspaceGlobs) {
1716
- const globDir = path2.join(rootDir, glob.replace(/\/\*$/, ""));
1736
+ const globDir = path3.join(rootDir, glob.replace(/\/\*$/, ""));
1717
1737
  if (!fs3.existsSync(globDir) || !fs3.statSync(globDir).isDirectory())
1718
1738
  continue;
1719
1739
  const entries = fs3.readdirSync(globDir, { withFileTypes: true });
1720
1740
  for (const entry of entries) {
1721
1741
  if (!entry.isDirectory())
1722
1742
  continue;
1723
- const pkgDir = path2.join(globDir, entry.name);
1724
- const pkgJsonPath = path2.join(pkgDir, "package.json");
1743
+ const pkgDir = path3.join(globDir, entry.name);
1744
+ const pkgJsonPath = path3.join(pkgDir, "package.json");
1725
1745
  if (!fs3.existsSync(pkgJsonPath))
1726
1746
  continue;
1727
1747
  try {
1728
1748
  const pkg = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf-8"));
1729
1749
  if (pkg.name) {
1730
- const srcDir = fs3.existsSync(path2.join(pkgDir, "src")) ? path2.join(pkgDir, "src") : pkgDir;
1731
- packages.set(pkg.name, srcDir);
1750
+ packages.set(pkg.name, pkgDir);
1732
1751
  }
1733
1752
  } catch {}
1734
1753
  }
1735
1754
  }
1736
1755
  return packages.size > 0 ? { packages, rootDir } : undefined;
1737
1756
  }
1738
- function createProgram({
1739
- entryFile,
1740
- baseDir = path2.dirname(entryFile),
1741
- content
1742
- }) {
1757
+ function createProgram(options) {
1758
+ const { content } = options;
1759
+ const entryFile = path3.resolve(options.entryFile);
1760
+ const baseDir = path3.resolve(options.baseDir ?? path3.dirname(entryFile));
1743
1761
  let configPath = ts2.findConfigFile(baseDir, ts2.sys.fileExists, "tsconfig.json");
1744
1762
  if (!configPath) {
1745
1763
  configPath = ts2.findConfigFile(baseDir, ts2.sys.fileExists, "jsconfig.json");
@@ -1748,7 +1766,7 @@ function createProgram({
1748
1766
  let additionalRootFiles = [];
1749
1767
  if (configPath) {
1750
1768
  const configFile = ts2.readConfigFile(configPath, ts2.sys.readFile);
1751
- const parsedConfig = ts2.parseJsonConfigFileContent(configFile.config, ts2.sys, path2.dirname(configPath));
1769
+ const parsedConfig = ts2.parseJsonConfigFileContent(configFile.config, ts2.sys, path3.dirname(configPath));
1752
1770
  compilerOptions = { ...compilerOptions, ...parsedConfig.options };
1753
1771
  additionalRootFiles = resolveProjectReferences(configPath, parsedConfig);
1754
1772
  const sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
@@ -1772,20 +1790,20 @@ function createProgram({
1772
1790
  let inMemorySource;
1773
1791
  if (workspaceMap) {
1774
1792
  const originalResolveModuleNames = compilerHost.resolveModuleNames?.bind(compilerHost);
1775
- compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options) => {
1793
+ compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options2) => {
1776
1794
  return moduleNames.map((moduleName) => {
1777
- const srcDir = workspaceMap.packages.get(moduleName);
1778
- if (srcDir) {
1779
- const indexFile = path2.join(srcDir, "index.ts");
1780
- if (fs3.existsSync(indexFile)) {
1781
- return { resolvedFileName: indexFile, isExternalLibraryImport: false };
1795
+ const pkgDir = workspaceMap.packages.get(moduleName);
1796
+ if (pkgDir) {
1797
+ const entryPath = resolveWorkspaceEntry(pkgDir);
1798
+ if (entryPath) {
1799
+ return { resolvedFileName: entryPath, isExternalLibraryImport: false };
1782
1800
  }
1783
1801
  }
1784
1802
  if (originalResolveModuleNames) {
1785
- const result = originalResolveModuleNames([moduleName], containingFile, _reusedNames, redirectedReference, options);
1803
+ const result = originalResolveModuleNames([moduleName], containingFile, _reusedNames, redirectedReference, options2);
1786
1804
  return result[0];
1787
1805
  }
1788
- const resolved = ts2.resolveModuleName(moduleName, containingFile, options, compilerHost);
1806
+ const resolved = ts2.resolveModuleName(moduleName, containingFile, options2, compilerHost);
1789
1807
  return resolved.resolvedModule;
1790
1808
  });
1791
1809
  };
@@ -1893,6 +1911,18 @@ var BUILTIN_GENERICS = new Set([
1893
1911
  "InstanceType",
1894
1912
  "Awaited"
1895
1913
  ]);
1914
+ var RESOLVED_UTILITY_TYPES = new Set([
1915
+ "Partial",
1916
+ "Required",
1917
+ "Readonly",
1918
+ "Pick",
1919
+ "Omit",
1920
+ "Record",
1921
+ "Exclude",
1922
+ "Extract",
1923
+ "NonNullable",
1924
+ "Awaited"
1925
+ ]);
1896
1926
  var BUILTIN_TYPES = new Set([
1897
1927
  "Date",
1898
1928
  "RegExp",
@@ -2318,6 +2348,13 @@ function buildSchemaInternal(type, checker, ctx) {
2318
2348
  if (BUILTIN_TYPES.has(name)) {
2319
2349
  return { $ref: `#/types/${name}` };
2320
2350
  }
2351
+ if (RESOLVED_UTILITY_TYPES.has(name) && type.flags & ts3.TypeFlags.Object) {
2352
+ const props = type.getProperties();
2353
+ const hasIndex = checker.getIndexInfosOfType(type).length > 0;
2354
+ if (props.length > 0 || hasIndex) {
2355
+ return buildObjectSchema(props, checker, ctx, type);
2356
+ }
2357
+ }
2321
2358
  if (isBuiltinGeneric(name) || !name.startsWith("__")) {
2322
2359
  const packageOrigin = getTypeOrigin(type, checker);
2323
2360
  if (ctx) {
@@ -2432,7 +2469,11 @@ function buildObjectSchema(properties, checker, ctx, originalType) {
2432
2469
  properties: props,
2433
2470
  ...required.length > 0 ? { required } : {}
2434
2471
  };
2435
- if (Object.keys(props).length === 0 && originalType) {
2472
+ const stringIndex = originalType ? checker.getIndexInfosOfType(originalType).find((i) => i.keyType.flags & ts3.TypeFlags.String) : undefined;
2473
+ if (stringIndex) {
2474
+ schema.additionalProperties = buildSchema(stringIndex.type, checker, ctx);
2475
+ }
2476
+ if (Object.keys(props).length === 0 && originalType && !stringIndex) {
2436
2477
  setSchemaExtension(schema, "x-ts-type", checker.typeToString(originalType));
2437
2478
  }
2438
2479
  return schema;
@@ -2947,7 +2988,8 @@ class TypeRegistry {
2947
2988
  }
2948
2989
  buildObjectSchemaFromProperties(type, checker, ctx) {
2949
2990
  const properties = type.getProperties();
2950
- if (properties.length === 0) {
2991
+ const stringIndex = checker.getIndexInfosOfType(type).find((i) => i.keyType.flags & ts5.TypeFlags.String);
2992
+ if (properties.length === 0 && !stringIndex) {
2951
2993
  return { type: checker.typeToString(type) };
2952
2994
  }
2953
2995
  const props = {};
@@ -2980,7 +3022,8 @@ class TypeRegistry {
2980
3022
  return {
2981
3023
  type: "object",
2982
3024
  properties: props,
2983
- ...required.length > 0 ? { required } : {}
3025
+ ...required.length > 0 ? { required } : {},
3026
+ ...stringIndex ? { additionalProperties: buildSchema(stringIndex.type, checker, ctx) } : {}
2984
3027
  };
2985
3028
  }
2986
3029
  }
@@ -3774,8 +3817,14 @@ function serializeTypeAlias(node, ctx) {
3774
3817
  const type = ctx.typeChecker.getTypeAtLocation(node);
3775
3818
  registerReferencedTypes(type, ctx);
3776
3819
  let schema;
3820
+ let members;
3777
3821
  if (ts10.isIntersectionTypeNode(node.type)) {
3778
3822
  schema = buildIntersectionSchemaFromNode(node.type, ctx);
3823
+ } else if (isInlineFunctionAlias(node.type) && type.getCallSignatures().length > 0) {
3824
+ schema = buildFunctionSchema(type.getCallSignatures(), ctx.typeChecker, ctx);
3825
+ } else if ((ts10.isMappedTypeNode(node.type) || ts10.isConditionalTypeNode(node.type)) && type.getProperties().length > 0 && type.getCallSignatures().length === 0) {
3826
+ schema = buildObjectSchema(type.getProperties(), ctx.typeChecker, ctx, type);
3827
+ members = serializeResolvedMembers(type, node, ctx);
3779
3828
  } else {
3780
3829
  schema = buildSchema(type, ctx.typeChecker, ctx);
3781
3830
  }
@@ -3788,10 +3837,95 @@ function serializeTypeAlias(node, ctx) {
3788
3837
  source,
3789
3838
  typeParameters,
3790
3839
  schema,
3840
+ ...members && members.length > 0 ? { members } : {},
3791
3841
  ...deprecated ? { deprecated: true, deprecationReason } : {},
3792
3842
  ...examples.length > 0 ? { examples } : {}
3793
3843
  };
3794
3844
  }
3845
+ function isInlineFunctionAlias(typeNode) {
3846
+ return ts10.isFunctionTypeNode(typeNode) || ts10.isTypeLiteralNode(typeNode) && typeNode.members.some(ts10.isCallSignatureDeclaration);
3847
+ }
3848
+ function buildConditionalArmDocs(typeNode, checker) {
3849
+ const docs = new Map;
3850
+ if (!ts10.isMappedTypeNode(typeNode) || !typeNode.type)
3851
+ return docs;
3852
+ const literalKeys = (extendsType) => {
3853
+ const keys = [];
3854
+ const visit = (n) => {
3855
+ if (ts10.isUnionTypeNode(n)) {
3856
+ for (const member of n.types)
3857
+ visit(member);
3858
+ } else if (ts10.isLiteralTypeNode(n) && ts10.isStringLiteral(n.literal)) {
3859
+ keys.push(n.literal.text);
3860
+ }
3861
+ };
3862
+ visit(extendsType);
3863
+ return keys;
3864
+ };
3865
+ const armDoc = (armType) => {
3866
+ if (!ts10.isTypeReferenceNode(armType))
3867
+ return;
3868
+ const symbol = checker.getSymbolAtLocation(armType.typeName);
3869
+ if (!symbol)
3870
+ return;
3871
+ const target = symbol.flags & ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
3872
+ const { deprecated, reason } = isSymbolDeprecated(target);
3873
+ const targetDecl = target.getDeclarations()?.[0];
3874
+ const description = targetDecl ? getJSDocComment(targetDecl, target, checker).description : undefined;
3875
+ if (!deprecated && !description)
3876
+ return;
3877
+ return { deprecated, deprecationReason: reason, description };
3878
+ };
3879
+ let current = typeNode.type;
3880
+ while (current && ts10.isConditionalTypeNode(current)) {
3881
+ const doc = armDoc(current.trueType);
3882
+ if (doc) {
3883
+ for (const key of literalKeys(current.extendsType)) {
3884
+ if (!docs.has(key))
3885
+ docs.set(key, doc);
3886
+ }
3887
+ }
3888
+ current = current.falseType;
3889
+ }
3890
+ return docs;
3891
+ }
3892
+ function serializeResolvedMembers(type, node, ctx) {
3893
+ const { typeChecker: checker } = ctx;
3894
+ const members = [];
3895
+ const armDocs = buildConditionalArmDocs(node.type, checker);
3896
+ for (const prop of type.getProperties()) {
3897
+ const decl = prop.getDeclarations()?.[0] ?? node;
3898
+ const propType = checker.getTypeOfSymbolAtLocation(prop, decl);
3899
+ registerReferencedTypes(propType, ctx);
3900
+ const callSigs = propType.getCallSignatures();
3901
+ const kind = callSigs.length > 0 ? "method" : "property";
3902
+ let { description, tags } = getJSDocComment(decl, prop, checker);
3903
+ let { deprecated, reason: deprecationReason } = isSymbolDeprecated(prop);
3904
+ const arm = armDocs.get(prop.getName());
3905
+ if (arm) {
3906
+ if (!deprecated && arm.deprecated) {
3907
+ deprecated = true;
3908
+ deprecationReason = arm.deprecationReason;
3909
+ }
3910
+ if (!description)
3911
+ description = arm.description;
3912
+ }
3913
+ const armAlias = propType.aliasSymbol;
3914
+ if (!deprecated && armAlias) {
3915
+ ({ deprecated, reason: deprecationReason } = isSymbolDeprecated(armAlias));
3916
+ }
3917
+ members.push({
3918
+ name: prop.getName(),
3919
+ kind,
3920
+ description,
3921
+ tags: tags.length > 0 ? tags : undefined,
3922
+ schema: kind === "property" ? buildSchema(propType, checker, ctx) : undefined,
3923
+ signatures: kind === "method" ? buildSignatures(callSigs, checker, ctx) : undefined,
3924
+ ...deprecated ? { deprecated: true, deprecationReason } : {}
3925
+ });
3926
+ }
3927
+ return members;
3928
+ }
3795
3929
 
3796
3930
  // src/schema/registry.ts
3797
3931
  function isTypeReference(type) {
@@ -4628,7 +4762,7 @@ function detectExternalPackage(symbol, checker) {
4628
4762
  return;
4629
4763
  }
4630
4764
  // src/primitives/list.ts
4631
- import * as path3 from "node:path";
4765
+ import * as path4 from "node:path";
4632
4766
  import ts12 from "typescript";
4633
4767
  async function listExports(options) {
4634
4768
  const { entryFile, baseDir, content } = options;
@@ -4689,7 +4823,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
4689
4823
  return {
4690
4824
  name,
4691
4825
  kind: "namespace",
4692
- file: path3.relative(path3.dirname(entryFile), declaration.fileName),
4826
+ file: path4.relative(path4.dirname(entryFile), declaration.fileName),
4693
4827
  line: 1,
4694
4828
  reexport: true
4695
4829
  };
@@ -4703,7 +4837,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
4703
4837
  return {
4704
4838
  name,
4705
4839
  kind,
4706
- file: path3.relative(path3.dirname(entryFile), sourceFile.fileName),
4840
+ file: path4.relative(path4.dirname(entryFile), sourceFile.fileName),
4707
4841
  line: line + 1,
4708
4842
  ...description ? { description } : {},
4709
4843
  ...deprecated ? { deprecated: true } : {},
@@ -4725,7 +4859,7 @@ function getDescriptionPreview(symbol, checker) {
4725
4859
  }
4726
4860
  // src/builder/spec-builder.ts
4727
4861
  import * as fs6 from "node:fs";
4728
- import * as path7 from "node:path";
4862
+ import * as path8 from "node:path";
4729
4863
  import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
4730
4864
  import ts16 from "typescript";
4731
4865
 
@@ -4763,7 +4897,7 @@ function resolveExportTarget2(symbol, checker) {
4763
4897
  import { spawn, spawnSync } from "node:child_process";
4764
4898
  import * as fs4 from "node:fs";
4765
4899
  import * as os from "node:os";
4766
- import * as path4 from "node:path";
4900
+ import * as path5 from "node:path";
4767
4901
  var MAX_BUFFER_SIZE = 10 * 1024 * 1024;
4768
4902
  function isStandardJSONSchema(obj) {
4769
4903
  if (typeof obj !== "object" || obj === null)
@@ -5022,7 +5156,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5022
5156
  return result;
5023
5157
  }
5024
5158
  const tempDir = os.tmpdir();
5025
- const workerPath = path4.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
5159
+ const workerPath = path5.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
5026
5160
  try {
5027
5161
  fs4.writeFileSync(workerPath, TS_WORKER_SCRIPT);
5028
5162
  const optionsJson = JSON.stringify({ target, libraryOptions });
@@ -5031,7 +5165,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5031
5165
  const child = spawn(runtime.cmd, args, {
5032
5166
  timeout,
5033
5167
  stdio: ["ignore", "pipe", "pipe"],
5034
- cwd: path4.dirname(tsFilePath)
5168
+ cwd: path5.dirname(tsFilePath)
5035
5169
  });
5036
5170
  let stdout = "";
5037
5171
  let stderr = "";
@@ -5132,7 +5266,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5132
5266
  }
5133
5267
  }
5134
5268
  function readTsconfigOutDir(baseDir) {
5135
- const tsconfigPath = path4.join(baseDir, "tsconfig.json");
5269
+ const tsconfigPath = path5.join(baseDir, "tsconfig.json");
5136
5270
  try {
5137
5271
  if (!fs4.existsSync(tsconfigPath)) {
5138
5272
  return null;
@@ -5147,7 +5281,7 @@ function readTsconfigOutDir(baseDir) {
5147
5281
  return null;
5148
5282
  }
5149
5283
  function resolveCompiledPath(tsPath, baseDir) {
5150
- const relativePath = path4.relative(baseDir, tsPath);
5284
+ const relativePath = path5.relative(baseDir, tsPath);
5151
5285
  const withoutExt = relativePath.replace(/\.tsx?$/, "");
5152
5286
  const srcPrefix = withoutExt.replace(/^src\//, "");
5153
5287
  const tsconfigOutDir = readTsconfigOutDir(baseDir);
@@ -5155,7 +5289,7 @@ function resolveCompiledPath(tsPath, baseDir) {
5155
5289
  const candidates = [];
5156
5290
  if (tsconfigOutDir) {
5157
5291
  for (const ext of extensions) {
5158
- candidates.push(path4.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
5292
+ candidates.push(path5.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
5159
5293
  }
5160
5294
  }
5161
5295
  const commonOutDirs = ["dist", "build", "lib", "out"];
@@ -5163,17 +5297,17 @@ function resolveCompiledPath(tsPath, baseDir) {
5163
5297
  if (outDir === tsconfigOutDir)
5164
5298
  continue;
5165
5299
  for (const ext of extensions) {
5166
- candidates.push(path4.join(baseDir, outDir, `${srcPrefix}${ext}`));
5300
+ candidates.push(path5.join(baseDir, outDir, `${srcPrefix}${ext}`));
5167
5301
  }
5168
5302
  }
5169
5303
  for (const ext of extensions) {
5170
- candidates.push(path4.join(baseDir, `${withoutExt}${ext}`));
5304
+ candidates.push(path5.join(baseDir, `${withoutExt}${ext}`));
5171
5305
  }
5172
5306
  const workspaceMatch = baseDir.match(/^(.+\/packages\/[^/]+)$/);
5173
5307
  if (workspaceMatch) {
5174
5308
  const pkgRoot = workspaceMatch[1];
5175
5309
  for (const ext of extensions) {
5176
- candidates.push(path4.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
5310
+ candidates.push(path5.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
5177
5311
  }
5178
5312
  }
5179
5313
  for (const candidate of candidates) {
@@ -5307,7 +5441,7 @@ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {
5307
5441
 
5308
5442
  // src/builder/external-resolver.ts
5309
5443
  import * as fs5 from "node:fs";
5310
- import * as path5 from "node:path";
5444
+ import * as path6 from "node:path";
5311
5445
  import picomatch from "picomatch";
5312
5446
  import ts14 from "typescript";
5313
5447
  function matchesExternalPattern(packageName, include, exclude) {
@@ -5341,11 +5475,11 @@ function findPackageJson(resolvedPath, packageName) {
5341
5475
  const isScoped = packageName.startsWith("@");
5342
5476
  const packageParts = isScoped ? packageName.split("/").slice(0, 2) : [packageName.split("/")[0]];
5343
5477
  const packageDir = packageParts.join("/");
5344
- let dir = path5.dirname(resolvedPath);
5478
+ let dir = path6.dirname(resolvedPath);
5345
5479
  const maxDepth = 10;
5346
5480
  for (let i = 0;i < maxDepth; i++) {
5347
5481
  if (dir.endsWith(`node_modules/${packageDir}`)) {
5348
- const pkgPath = path5.join(dir, "package.json");
5482
+ const pkgPath = path6.join(dir, "package.json");
5349
5483
  if (fs5.existsSync(pkgPath)) {
5350
5484
  try {
5351
5485
  return JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
@@ -5354,7 +5488,7 @@ function findPackageJson(resolvedPath, packageName) {
5354
5488
  }
5355
5489
  }
5356
5490
  }
5357
- const parent = path5.dirname(dir);
5491
+ const parent = path6.dirname(dir);
5358
5492
  if (parent === dir)
5359
5493
  break;
5360
5494
  dir = parent;
@@ -5598,7 +5732,7 @@ function hasInternalTag(typeName, program, sourceFile) {
5598
5732
  }
5599
5733
 
5600
5734
  // src/builder/verification.ts
5601
- import * as path6 from "node:path";
5735
+ import * as path7 from "node:path";
5602
5736
  var BUILTIN_TYPES2 = new Set([
5603
5737
  "Array",
5604
5738
  "ArrayBuffer",
@@ -5687,8 +5821,8 @@ function isExternalType2(definedIn, baseDir) {
5687
5821
  return true;
5688
5822
  if (definedIn.includes("node_modules"))
5689
5823
  return true;
5690
- const normalizedDefined = path6.resolve(definedIn);
5691
- const normalizedBase = path6.resolve(baseDir);
5824
+ const normalizedDefined = path7.resolve(definedIn);
5825
+ const normalizedBase = path7.resolve(baseDir);
5692
5826
  return !normalizedDefined.startsWith(normalizedBase);
5693
5827
  }
5694
5828
  function shouldSkipDanglingRef(name) {
@@ -6027,7 +6161,7 @@ async function extract(options) {
6027
6161
  }
6028
6162
  }
6029
6163
  const types = ctx.typeRegistry.getAll();
6030
- const projectBaseDir = baseDir ?? path7.dirname(entryFile);
6164
+ const projectBaseDir = baseDir ?? path8.dirname(entryFile);
6031
6165
  const definedTypes = new Set(types.map((t) => t.id));
6032
6166
  const forgottenExports = collectForgottenExports(exports, types, program, sourceFile, exportedIds, projectBaseDir, definedTypes);
6033
6167
  for (const forgotten of forgottenExports) {
@@ -6060,7 +6194,7 @@ async function extract(options) {
6060
6194
  }
6061
6195
  let runtimeMetadata;
6062
6196
  if (options.schemaExtraction === "hybrid") {
6063
- const projectBaseDir2 = baseDir || path7.dirname(entryFile);
6197
+ const projectBaseDir2 = baseDir || path8.dirname(entryFile);
6064
6198
  const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
6065
6199
  target: options.schemaTarget || "draft-2020-12",
6066
6200
  timeout: 15000
@@ -6349,7 +6483,7 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
6349
6483
  return {
6350
6484
  ...includeSchema ? { $schema: SCHEMA_URL } : {},
6351
6485
  openpkg: SCHEMA_VERSION,
6352
- meta: { name: path7.basename(entryFile, path7.extname(entryFile)) },
6486
+ meta: { name: path8.basename(entryFile, path8.extname(entryFile)) },
6353
6487
  exports: [],
6354
6488
  generation: {
6355
6489
  generator: "@openpkg-ts/sdk",
@@ -6365,7 +6499,7 @@ function findTypeInProgram(name, checker, program, sourceFile, symFlags) {
6365
6499
  const localSym = checker.resolveName(name, sourceFile, symFlags, false);
6366
6500
  if (localSym)
6367
6501
  return checker.getDeclaredTypeOfSymbol(localSym);
6368
- const entryDir = path7.dirname(sourceFile.fileName);
6502
+ const entryDir = path8.dirname(sourceFile.fileName);
6369
6503
  for (const sf of program.getSourceFiles()) {
6370
6504
  const fn = sf.fileName;
6371
6505
  if (fn.includes("/typescript/lib/lib.") || fn.includes("\\typescript\\lib\\lib."))
@@ -6381,22 +6515,22 @@ function findTypeInProgram(name, checker, program, sourceFile, symFlags) {
6381
6515
  return;
6382
6516
  }
6383
6517
  async function getPackageMeta(entryFile, baseDir) {
6384
- let dir = baseDir ?? path7.dirname(entryFile);
6385
- while (dir !== path7.dirname(dir)) {
6386
- const pkgPath = path7.join(dir, "package.json");
6518
+ let dir = baseDir ?? path8.dirname(entryFile);
6519
+ while (dir !== path8.dirname(dir)) {
6520
+ const pkgPath = path8.join(dir, "package.json");
6387
6521
  try {
6388
6522
  if (fs6.existsSync(pkgPath)) {
6389
6523
  const pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
6390
6524
  return {
6391
- name: pkg.name ?? path7.basename(dir),
6525
+ name: pkg.name ?? path8.basename(dir),
6392
6526
  version: pkg.version,
6393
6527
  description: pkg.description
6394
6528
  };
6395
6529
  }
6396
6530
  } catch {}
6397
- dir = path7.dirname(dir);
6531
+ dir = path8.dirname(dir);
6398
6532
  }
6399
- return { name: path7.basename(baseDir ?? path7.dirname(entryFile)) };
6533
+ return { name: path8.basename(baseDir ?? path8.dirname(entryFile)) };
6400
6534
  }
6401
6535
 
6402
6536
  // src/primitives/spec.ts
@@ -6514,6 +6648,8 @@ export {
6514
6648
  calculateNextVersion,
6515
6649
  buildSignatureString,
6516
6650
  buildSchema,
6651
+ buildObjectSchema,
6652
+ buildFunctionSchema,
6517
6653
  arktypeAdapter,
6518
6654
  analyzeSpec,
6519
6655
  TypeRegistry,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/sdk",
3
- "version": "0.38.0",
3
+ "version": "0.40.0",
4
4
  "description": "TypeScript API extraction SDK - programmatic primitives for OpenPkg specs",
5
5
  "keywords": [
6
6
  "openpkg",