@openpkg-ts/sdk 0.36.0 → 0.37.1

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
@@ -29,7 +29,7 @@ import {
29
29
  toPagefindRecords,
30
30
  toSearchIndex,
31
31
  toSearchIndexJSON
32
- } from "./shared/chunk-hnajr1tb.js";
32
+ } from "./shared/chunk-zrx9s0n4.js";
33
33
 
34
34
  // src/primitives/diff.ts
35
35
  import {
@@ -86,6 +86,9 @@ import * as fs2 from "node:fs";
86
86
  import { validateSpec } from "@openpkg-ts/spec";
87
87
 
88
88
  // src/render/html.ts
89
+ import {
90
+ KIND_LABELS
91
+ } from "@openpkg-ts/spec";
89
92
  var defaultCSS = `
90
93
  :root {
91
94
  --text: #1a1a1a;
@@ -381,14 +384,14 @@ function toHTML(spec, options = {}) {
381
384
  const byKind = groupByKind(specExports);
382
385
  const navItems = Object.entries(byKind).map(([kind, exports]) => {
383
386
  const links = exports.map((e) => `<a href="#${e.id}">${escapeHTML(e.name)}</a>`).join("");
384
- return `<li><strong>${kind}s:</strong> ${links}</li>`;
387
+ return `<li><strong>${KIND_LABELS[kind] ?? kind}:</strong> ${links}</li>`;
385
388
  }).join("");
386
389
  const nav = `<nav><ul>${navItems}</ul></nav>`;
387
390
  const sections = KIND_ORDER.filter((kind) => byKind[kind]?.length).map((kind) => {
388
391
  const exports = byKind[kind].map(renderExport).join("");
389
392
  return `
390
393
  <section class="kind-section">
391
- <h2>${kind.charAt(0).toUpperCase() + kind.slice(1)}s</h2>
394
+ <h2>${KIND_LABELS[kind]}</h2>
392
395
  ${exports}
393
396
  </section>`;
394
397
  }).join("");
@@ -533,6 +536,9 @@ function toJSONString(spec, options = {}) {
533
536
  }
534
537
 
535
538
  // src/render/markdown.ts
539
+ import {
540
+ KIND_LABELS as KIND_LABELS2
541
+ } from "@openpkg-ts/spec";
536
542
  var defaultSections = {
537
543
  signature: true,
538
544
  description: true,
@@ -898,7 +904,7 @@ function toMarkdown(spec, options = {}) {
898
904
  const exports = byKind[kind];
899
905
  if (!exports?.length)
900
906
  continue;
901
- parts.push(`## ${kind.charAt(0).toUpperCase() + kind.slice(1)}s`);
907
+ parts.push(`## ${KIND_LABELS2[kind]}`);
902
908
  parts.push("");
903
909
  for (const exp of exports) {
904
910
  const content = exportToMarkdown(exp, {
@@ -915,18 +921,7 @@ function toMarkdown(spec, options = {}) {
915
921
  }
916
922
 
917
923
  // src/render/nav.ts
918
- var defaultKindLabels = {
919
- function: "Functions",
920
- class: "Classes",
921
- interface: "Interfaces",
922
- type: "Types",
923
- enum: "Enums",
924
- variable: "Variables",
925
- namespace: "Namespaces",
926
- module: "Modules",
927
- reference: "References",
928
- external: "External"
929
- };
924
+ import { KIND_LABELS as KIND_LABELS3 } from "@openpkg-ts/spec";
930
925
  var defaultSlugify = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
931
926
  function getModuleName(exp) {
932
927
  if (exp.source?.file) {
@@ -980,9 +975,9 @@ function toGenericNav(spec, options) {
980
975
  sortAlphabetically = true,
981
976
  includeGroupIndex = false
982
977
  } = options;
983
- const labels = { ...defaultKindLabels, ...kindLabels };
978
+ const labels = { ...KIND_LABELS3, ...kindLabels };
984
979
  const grouped = groupExports(spec.exports, groupBy);
985
- const groups = [];
980
+ const keyedGroups = [];
986
981
  for (const [key, exports] of grouped) {
987
982
  const sortedExports = sortAlphabetically ? sortByName(exports) : exports;
988
983
  const items = sortedExports.map((exp) => ({
@@ -990,19 +985,19 @@ function toGenericNav(spec, options) {
990
985
  href: `${basePath}/${slugify(exp.name)}`
991
986
  }));
992
987
  const title = groupBy === "kind" ? labels[key] || key : key;
993
- groups.push({
994
- title,
995
- items,
996
- index: includeGroupIndex ? `${basePath}/${slugify(key)}` : undefined
988
+ keyedGroups.push({
989
+ key,
990
+ group: {
991
+ title,
992
+ items,
993
+ index: includeGroupIndex ? `${basePath}/${slugify(key)}` : undefined
994
+ }
997
995
  });
998
996
  }
999
997
  if (groupBy === "kind") {
1000
- groups.sort((a, b) => {
1001
- const aIdx = KIND_ORDER.indexOf(a.title.toLowerCase().replace(/s$/, ""));
1002
- const bIdx = KIND_ORDER.indexOf(b.title.toLowerCase().replace(/s$/, ""));
1003
- return aIdx - bIdx;
1004
- });
998
+ keyedGroups.sort((a, b) => KIND_ORDER.indexOf(a.key) - KIND_ORDER.indexOf(b.key));
1005
999
  }
1000
+ const groups = keyedGroups.map((g) => g.group);
1006
1001
  const flatItems = groupBy === "none" ? groups.flatMap((g) => g.items) : groups.map((g) => ({
1007
1002
  title: g.title,
1008
1003
  items: g.items
@@ -1517,211 +1512,8 @@ function filterSpec(spec, criteria) {
1517
1512
  // src/primitives/get.ts
1518
1513
  import ts11 from "typescript";
1519
1514
 
1520
- // src/compiler/program.ts
1521
- import * as fs4 from "node:fs";
1522
- import * as path3 from "node:path";
1523
- import ts from "typescript";
1524
- function isJsFile(file) {
1525
- return /\.(js|mjs|cjs|jsx)$/.test(file);
1526
- }
1527
- function getScriptKind(file) {
1528
- if (/\.tsx$/.test(file))
1529
- return ts.ScriptKind.TSX;
1530
- if (/\.jsx$/.test(file))
1531
- return ts.ScriptKind.JSX;
1532
- if (/\.(js|mjs|cjs)$/.test(file))
1533
- return ts.ScriptKind.JS;
1534
- return ts.ScriptKind.TS;
1535
- }
1536
- var DEFAULT_COMPILER_OPTIONS = {
1537
- target: ts.ScriptTarget.Latest,
1538
- module: ts.ModuleKind.CommonJS,
1539
- lib: ["lib.es2021.d.ts"],
1540
- declaration: true,
1541
- moduleResolution: ts.ModuleResolutionKind.NodeJs
1542
- };
1543
- function resolveProjectReferences(configPath, parsedConfig) {
1544
- const additionalFiles = [];
1545
- if (!parsedConfig.projectReferences?.length) {
1546
- return additionalFiles;
1547
- }
1548
- const configDir = path3.dirname(configPath);
1549
- for (const ref of parsedConfig.projectReferences) {
1550
- const refPath = path3.resolve(configDir, ref.path);
1551
- const refConfigPath = fs4.existsSync(path3.join(refPath, "tsconfig.json")) ? path3.join(refPath, "tsconfig.json") : refPath;
1552
- if (!fs4.existsSync(refConfigPath))
1553
- continue;
1554
- const refConfigFile = ts.readConfigFile(refConfigPath, ts.sys.readFile);
1555
- if (refConfigFile.error)
1556
- continue;
1557
- const refParsed = ts.parseJsonConfigFileContent(refConfigFile.config, ts.sys, path3.dirname(refConfigPath));
1558
- additionalFiles.push(...refParsed.fileNames);
1559
- }
1560
- return additionalFiles;
1561
- }
1562
- function parsePnpmWorkspace(yamlContent) {
1563
- const globs = [];
1564
- const lines = yamlContent.split(`
1565
- `);
1566
- let inPackages = false;
1567
- for (const line of lines) {
1568
- const trimmed = line.trim();
1569
- if (trimmed === "packages:") {
1570
- inPackages = true;
1571
- continue;
1572
- }
1573
- if (inPackages) {
1574
- if (!line.startsWith(" ") && !line.startsWith("-") && trimmed) {
1575
- break;
1576
- }
1577
- const match = trimmed.match(/^-\s*['"]?([^'"]+)['"]?$/);
1578
- if (match) {
1579
- globs.push(match[1]);
1580
- }
1581
- }
1582
- }
1583
- return globs;
1584
- }
1585
- function buildWorkspaceMap(baseDir) {
1586
- let currentDir = baseDir;
1587
- let rootDir;
1588
- let workspaceGlobs = [];
1589
- for (let i = 0;i < 10; i++) {
1590
- const pnpmPath = path3.join(currentDir, "pnpm-workspace.yaml");
1591
- if (fs4.existsSync(pnpmPath)) {
1592
- try {
1593
- const yamlContent = fs4.readFileSync(pnpmPath, "utf-8");
1594
- workspaceGlobs = parsePnpmWorkspace(yamlContent);
1595
- if (workspaceGlobs.length > 0) {
1596
- rootDir = currentDir;
1597
- break;
1598
- }
1599
- } catch {}
1600
- }
1601
- const pkgPath = path3.join(currentDir, "package.json");
1602
- if (fs4.existsSync(pkgPath)) {
1603
- try {
1604
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
1605
- if (pkg.workspaces) {
1606
- rootDir = currentDir;
1607
- workspaceGlobs = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages || [];
1608
- break;
1609
- }
1610
- } catch {}
1611
- }
1612
- const parent = path3.dirname(currentDir);
1613
- if (parent === currentDir)
1614
- break;
1615
- currentDir = parent;
1616
- }
1617
- if (!rootDir || workspaceGlobs.length === 0)
1618
- return;
1619
- const packages = new Map;
1620
- for (const glob of workspaceGlobs) {
1621
- const globDir = path3.join(rootDir, glob.replace(/\/\*$/, ""));
1622
- if (!fs4.existsSync(globDir) || !fs4.statSync(globDir).isDirectory())
1623
- continue;
1624
- const entries = fs4.readdirSync(globDir, { withFileTypes: true });
1625
- for (const entry of entries) {
1626
- if (!entry.isDirectory())
1627
- continue;
1628
- const pkgDir = path3.join(globDir, entry.name);
1629
- const pkgJsonPath = path3.join(pkgDir, "package.json");
1630
- if (!fs4.existsSync(pkgJsonPath))
1631
- continue;
1632
- try {
1633
- const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
1634
- if (pkg.name) {
1635
- const srcDir = fs4.existsSync(path3.join(pkgDir, "src")) ? path3.join(pkgDir, "src") : pkgDir;
1636
- packages.set(pkg.name, srcDir);
1637
- }
1638
- } catch {}
1639
- }
1640
- }
1641
- return packages.size > 0 ? { packages, rootDir } : undefined;
1642
- }
1643
- function createProgram({
1644
- entryFile,
1645
- baseDir = path3.dirname(entryFile),
1646
- content
1647
- }) {
1648
- let configPath = ts.findConfigFile(baseDir, ts.sys.fileExists, "tsconfig.json");
1649
- if (!configPath) {
1650
- configPath = ts.findConfigFile(baseDir, ts.sys.fileExists, "jsconfig.json");
1651
- }
1652
- let compilerOptions = { ...DEFAULT_COMPILER_OPTIONS };
1653
- let additionalRootFiles = [];
1654
- if (configPath) {
1655
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
1656
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path3.dirname(configPath));
1657
- compilerOptions = { ...compilerOptions, ...parsedConfig.options };
1658
- additionalRootFiles = resolveProjectReferences(configPath, parsedConfig);
1659
- const sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
1660
- additionalRootFiles.push(...sourceFiles);
1661
- }
1662
- if (isJsFile(entryFile)) {
1663
- compilerOptions = {
1664
- ...compilerOptions,
1665
- allowJs: true,
1666
- checkJs: true,
1667
- isolatedDeclarations: false
1668
- };
1669
- } else {
1670
- const allowJsVal = compilerOptions.allowJs;
1671
- if (typeof allowJsVal === "boolean" && allowJsVal) {
1672
- compilerOptions = { ...compilerOptions, allowJs: false, checkJs: false };
1673
- }
1674
- }
1675
- const workspaceMap = buildWorkspaceMap(baseDir);
1676
- const compilerHost = ts.createCompilerHost(compilerOptions, true);
1677
- let inMemorySource;
1678
- if (workspaceMap) {
1679
- const originalResolveModuleNames = compilerHost.resolveModuleNames?.bind(compilerHost);
1680
- compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options) => {
1681
- return moduleNames.map((moduleName) => {
1682
- const srcDir = workspaceMap.packages.get(moduleName);
1683
- if (srcDir) {
1684
- const indexFile = path3.join(srcDir, "index.ts");
1685
- if (fs4.existsSync(indexFile)) {
1686
- return { resolvedFileName: indexFile, isExternalLibraryImport: false };
1687
- }
1688
- }
1689
- if (originalResolveModuleNames) {
1690
- const result = originalResolveModuleNames([moduleName], containingFile, _reusedNames, redirectedReference, options);
1691
- return result[0];
1692
- }
1693
- const resolved = ts.resolveModuleName(moduleName, containingFile, options, compilerHost);
1694
- return resolved.resolvedModule;
1695
- });
1696
- };
1697
- }
1698
- if (content !== undefined) {
1699
- inMemorySource = ts.createSourceFile(entryFile, content, ts.ScriptTarget.Latest, true, getScriptKind(entryFile));
1700
- const originalGetSourceFile = compilerHost.getSourceFile.bind(compilerHost);
1701
- compilerHost.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
1702
- if (fileName === entryFile) {
1703
- return inMemorySource;
1704
- }
1705
- return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
1706
- };
1707
- }
1708
- const rootFiles = [entryFile, ...additionalRootFiles];
1709
- const program = ts.createProgram(rootFiles, compilerOptions, compilerHost);
1710
- const sourceFile = inMemorySource ?? program.getSourceFile(entryFile);
1711
- return {
1712
- program,
1713
- compilerHost,
1714
- compilerOptions,
1715
- sourceFile,
1716
- configPath
1717
- };
1718
- }
1719
-
1720
- // src/serializers/classes.ts
1721
- import ts7 from "typescript";
1722
-
1723
1515
  // src/ast/utils.ts
1724
- import ts2 from "typescript";
1516
+ import ts from "typescript";
1725
1517
  function parseExamplesFromTags(tags) {
1726
1518
  const examples = [];
1727
1519
  for (const tag of tags) {
@@ -1783,12 +1575,12 @@ function extractSeeTagText(tag) {
1783
1575
  if (Array.isArray(tag.comment)) {
1784
1576
  const parts = [];
1785
1577
  for (const part of tag.comment) {
1786
- if (ts2.isJSDocLink(part) || ts2.isJSDocLinkCode(part) || ts2.isJSDocLinkPlain(part)) {
1578
+ if (ts.isJSDocLink(part) || ts.isJSDocLinkCode(part) || ts.isJSDocLinkPlain(part)) {
1787
1579
  if (part.name) {
1788
1580
  try {
1789
1581
  parts.push(part.name.getText());
1790
1582
  } catch {
1791
- if (ts2.isIdentifier(part.name)) {
1583
+ if (ts.isIdentifier(part.name)) {
1792
1584
  parts.push(part.name.text);
1793
1585
  }
1794
1586
  }
@@ -1796,7 +1588,7 @@ function extractSeeTagText(tag) {
1796
1588
  if (part.text) {
1797
1589
  parts.push(part.text);
1798
1590
  }
1799
- } else if (part.kind === ts2.SyntaxKind.JSDocText) {
1591
+ } else if (part.kind === ts.SyntaxKind.JSDocText) {
1800
1592
  parts.push(part.text);
1801
1593
  }
1802
1594
  }
@@ -1805,12 +1597,12 @@ function extractSeeTagText(tag) {
1805
1597
  return result;
1806
1598
  }
1807
1599
  }
1808
- return typeof tag.comment === "string" ? tag.comment : ts2.getTextOfJSDocComment(tag.comment) ?? "";
1600
+ return typeof tag.comment === "string" ? tag.comment : ts.getTextOfJSDocComment(tag.comment) ?? "";
1809
1601
  }
1810
1602
  function getJSDocComment(node, symbol, checker) {
1811
- const jsDocTags = ts2.getJSDocTags(node);
1603
+ const jsDocTags = ts.getJSDocTags(node);
1812
1604
  const tags = jsDocTags.map((tag) => {
1813
- const rawText = typeof tag.comment === "string" ? tag.comment : ts2.getTextOfJSDocComment(tag.comment) ?? "";
1605
+ const rawText = typeof tag.comment === "string" ? tag.comment : ts.getTextOfJSDocComment(tag.comment) ?? "";
1814
1606
  if (tag.tagName.text === "param") {
1815
1607
  const paramTag = tag;
1816
1608
  let paramName = "";
@@ -1845,12 +1637,12 @@ function getJSDocComment(node, symbol, checker) {
1845
1637
  }
1846
1638
  return { name: tag.tagName.text, text: rawText };
1847
1639
  });
1848
- const jsDocComments = ts2.getJSDocCommentsAndTags(node).filter(ts2.isJSDoc);
1640
+ const jsDocComments = ts.getJSDocCommentsAndTags(node).filter(ts.isJSDoc);
1849
1641
  let description;
1850
1642
  if (jsDocComments.length > 0) {
1851
1643
  const firstDoc = jsDocComments[0];
1852
1644
  if (firstDoc.comment) {
1853
- description = typeof firstDoc.comment === "string" ? firstDoc.comment : ts2.getTextOfJSDocComment(firstDoc.comment);
1645
+ description = typeof firstDoc.comment === "string" ? firstDoc.comment : ts.getTextOfJSDocComment(firstDoc.comment);
1854
1646
  }
1855
1647
  }
1856
1648
  if (!description && symbol && checker) {
@@ -1883,7 +1675,7 @@ function getParamDescription(propertyName, jsdocTags, inferredAlias) {
1883
1675
  }
1884
1676
  const isMatch = tagParamName === propertyName || inferredAlias && tagParamName === `${inferredAlias}.${propertyName}` || tagParamName.endsWith(`.${propertyName}`);
1885
1677
  if (isMatch) {
1886
- const comment = typeof tag.comment === "string" ? tag.comment : ts2.getTextOfJSDocComment(tag.comment);
1678
+ const comment = typeof tag.comment === "string" ? tag.comment : ts.getTextOfJSDocComment(tag.comment);
1887
1679
  return stripParamSeparator(comment);
1888
1680
  }
1889
1681
  }
@@ -1896,11 +1688,11 @@ function extractVarianceModifiers(modifiers) {
1896
1688
  let hasOut = false;
1897
1689
  let isConst;
1898
1690
  for (const mod of modifiers) {
1899
- if (mod.kind === ts2.SyntaxKind.InKeyword)
1691
+ if (mod.kind === ts.SyntaxKind.InKeyword)
1900
1692
  hasIn = true;
1901
- if (mod.kind === ts2.SyntaxKind.OutKeyword)
1693
+ if (mod.kind === ts.SyntaxKind.OutKeyword)
1902
1694
  hasOut = true;
1903
- if (mod.kind === ts2.SyntaxKind.ConstKeyword)
1695
+ if (mod.kind === ts.SyntaxKind.ConstKeyword)
1904
1696
  isConst = true;
1905
1697
  }
1906
1698
  const variance = hasIn && hasOut ? "inout" : hasIn ? "in" : hasOut ? "out" : undefined;
@@ -1922,7 +1714,7 @@ function extractTypeParameters(node, checker) {
1922
1714
  const defType = checker.getTypeAtLocation(tp.default);
1923
1715
  defaultType = checker.typeToString(defType);
1924
1716
  }
1925
- const { variance, isConst } = extractVarianceModifiers(ts2.getModifiers(tp));
1717
+ const { variance, isConst } = extractVarianceModifiers(ts.getModifiers(tp));
1926
1718
  return {
1927
1719
  name,
1928
1720
  ...constraint ? { constraint } : {},
@@ -1943,7 +1735,7 @@ function isSymbolDeprecated(symbol) {
1943
1735
  return { deprecated: true, reason };
1944
1736
  }
1945
1737
  for (const declaration of symbol.getDeclarations() ?? []) {
1946
- const tag = ts2.getJSDocDeprecatedTag(declaration);
1738
+ const tag = ts.getJSDocDeprecatedTag(declaration);
1947
1739
  if (tag) {
1948
1740
  let reason;
1949
1741
  if (typeof tag.comment === "string") {
@@ -1953,6 +1745,21 @@ function isSymbolDeprecated(symbol) {
1953
1745
  }
1954
1746
  return { deprecated: true, reason };
1955
1747
  }
1748
+ if (ts.isExportSpecifier(declaration)) {
1749
+ const exportDecl = declaration.parent?.parent;
1750
+ if (exportDecl && ts.isExportDeclaration(exportDecl)) {
1751
+ const parentTag = ts.getJSDocDeprecatedTag(exportDecl);
1752
+ if (parentTag) {
1753
+ let reason;
1754
+ if (typeof parentTag.comment === "string") {
1755
+ reason = parentTag.comment;
1756
+ } else if (Array.isArray(parentTag.comment)) {
1757
+ reason = parentTag.comment.map((c) => typeof c === "string" ? c : c.text).join("");
1758
+ }
1759
+ return { deprecated: true, reason };
1760
+ }
1761
+ }
1762
+ }
1956
1763
  }
1957
1764
  return { deprecated: false };
1958
1765
  }
@@ -1986,8 +1793,8 @@ function extractTypeParametersFromSignature(signature, checker) {
1986
1793
  const tpSymbol = tp.getSymbol();
1987
1794
  const declarations = tpSymbol?.getDeclarations() ?? [];
1988
1795
  for (const decl of declarations) {
1989
- if (ts2.isTypeParameterDeclaration(decl)) {
1990
- ({ variance, isConst } = extractVarianceModifiers(ts2.getModifiers(decl)));
1796
+ if (ts.isTypeParameterDeclaration(decl)) {
1797
+ ({ variance, isConst } = extractVarianceModifiers(ts.getModifiers(decl)));
1991
1798
  break;
1992
1799
  }
1993
1800
  }
@@ -2001,23 +1808,228 @@ function extractTypeParametersFromSignature(signature, checker) {
2001
1808
  });
2002
1809
  }
2003
1810
  function getExportKind(declaration, type) {
2004
- if (ts2.isFunctionDeclaration(declaration) || ts2.isFunctionExpression(declaration))
1811
+ if (ts.isFunctionDeclaration(declaration) || ts.isFunctionExpression(declaration))
2005
1812
  return "function";
2006
- if (ts2.isClassDeclaration(declaration))
1813
+ if (ts.isClassDeclaration(declaration))
2007
1814
  return "class";
2008
- if (ts2.isInterfaceDeclaration(declaration))
1815
+ if (ts.isInterfaceDeclaration(declaration))
2009
1816
  return "interface";
2010
- if (ts2.isTypeAliasDeclaration(declaration))
1817
+ if (ts.isTypeAliasDeclaration(declaration))
2011
1818
  return "type";
2012
- if (ts2.isEnumDeclaration(declaration))
1819
+ if (ts.isEnumDeclaration(declaration))
2013
1820
  return "enum";
2014
- if (ts2.isModuleDeclaration(declaration) || ts2.isNamespaceExport(declaration))
1821
+ if (ts.isModuleDeclaration(declaration) || ts.isNamespaceExport(declaration))
2015
1822
  return "namespace";
2016
- if (ts2.isVariableDeclaration(declaration) && type.getCallSignatures().length > 0)
1823
+ if (ts.isVariableDeclaration(declaration) && type.getConstructSignatures().length > 0)
1824
+ return "class";
1825
+ if (ts.isVariableDeclaration(declaration) && type.getCallSignatures().length > 0)
2017
1826
  return "function";
2018
1827
  return "variable";
2019
1828
  }
2020
1829
 
1830
+ // src/compiler/program.ts
1831
+ import * as fs4 from "node:fs";
1832
+ import * as path3 from "node:path";
1833
+ import ts2 from "typescript";
1834
+ function isJsFile(file) {
1835
+ return /\.(js|mjs|cjs|jsx)$/.test(file);
1836
+ }
1837
+ function getScriptKind(file) {
1838
+ if (/\.tsx$/.test(file))
1839
+ return ts2.ScriptKind.TSX;
1840
+ if (/\.jsx$/.test(file))
1841
+ return ts2.ScriptKind.JSX;
1842
+ if (/\.(js|mjs|cjs)$/.test(file))
1843
+ return ts2.ScriptKind.JS;
1844
+ return ts2.ScriptKind.TS;
1845
+ }
1846
+ var DEFAULT_COMPILER_OPTIONS = {
1847
+ target: ts2.ScriptTarget.Latest,
1848
+ module: ts2.ModuleKind.CommonJS,
1849
+ lib: ["lib.es2021.d.ts"],
1850
+ declaration: true,
1851
+ moduleResolution: ts2.ModuleResolutionKind.NodeJs
1852
+ };
1853
+ function resolveProjectReferences(configPath, parsedConfig) {
1854
+ const additionalFiles = [];
1855
+ if (!parsedConfig.projectReferences?.length) {
1856
+ return additionalFiles;
1857
+ }
1858
+ const configDir = path3.dirname(configPath);
1859
+ for (const ref of parsedConfig.projectReferences) {
1860
+ const refPath = path3.resolve(configDir, ref.path);
1861
+ const refConfigPath = fs4.existsSync(path3.join(refPath, "tsconfig.json")) ? path3.join(refPath, "tsconfig.json") : refPath;
1862
+ if (!fs4.existsSync(refConfigPath))
1863
+ continue;
1864
+ const refConfigFile = ts2.readConfigFile(refConfigPath, ts2.sys.readFile);
1865
+ if (refConfigFile.error)
1866
+ continue;
1867
+ const refParsed = ts2.parseJsonConfigFileContent(refConfigFile.config, ts2.sys, path3.dirname(refConfigPath));
1868
+ additionalFiles.push(...refParsed.fileNames);
1869
+ }
1870
+ return additionalFiles;
1871
+ }
1872
+ function parsePnpmWorkspace(yamlContent) {
1873
+ const globs = [];
1874
+ const lines = yamlContent.split(`
1875
+ `);
1876
+ let inPackages = false;
1877
+ for (const line of lines) {
1878
+ const trimmed = line.trim();
1879
+ if (trimmed === "packages:") {
1880
+ inPackages = true;
1881
+ continue;
1882
+ }
1883
+ if (inPackages) {
1884
+ if (!line.startsWith(" ") && !line.startsWith("-") && trimmed) {
1885
+ break;
1886
+ }
1887
+ const match = trimmed.match(/^-\s*['"]?([^'"]+)['"]?$/);
1888
+ if (match) {
1889
+ globs.push(match[1]);
1890
+ }
1891
+ }
1892
+ }
1893
+ return globs;
1894
+ }
1895
+ function buildWorkspaceMap(baseDir) {
1896
+ let currentDir = baseDir;
1897
+ let rootDir;
1898
+ let workspaceGlobs = [];
1899
+ for (let i = 0;i < 10; i++) {
1900
+ const pnpmPath = path3.join(currentDir, "pnpm-workspace.yaml");
1901
+ if (fs4.existsSync(pnpmPath)) {
1902
+ try {
1903
+ const yamlContent = fs4.readFileSync(pnpmPath, "utf-8");
1904
+ workspaceGlobs = parsePnpmWorkspace(yamlContent);
1905
+ if (workspaceGlobs.length > 0) {
1906
+ rootDir = currentDir;
1907
+ break;
1908
+ }
1909
+ } catch {}
1910
+ }
1911
+ const pkgPath = path3.join(currentDir, "package.json");
1912
+ if (fs4.existsSync(pkgPath)) {
1913
+ try {
1914
+ const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
1915
+ if (pkg.workspaces) {
1916
+ rootDir = currentDir;
1917
+ workspaceGlobs = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages || [];
1918
+ break;
1919
+ }
1920
+ } catch {}
1921
+ }
1922
+ const parent = path3.dirname(currentDir);
1923
+ if (parent === currentDir)
1924
+ break;
1925
+ currentDir = parent;
1926
+ }
1927
+ if (!rootDir || workspaceGlobs.length === 0)
1928
+ return;
1929
+ const packages = new Map;
1930
+ for (const glob of workspaceGlobs) {
1931
+ const globDir = path3.join(rootDir, glob.replace(/\/\*$/, ""));
1932
+ if (!fs4.existsSync(globDir) || !fs4.statSync(globDir).isDirectory())
1933
+ continue;
1934
+ const entries = fs4.readdirSync(globDir, { withFileTypes: true });
1935
+ for (const entry of entries) {
1936
+ if (!entry.isDirectory())
1937
+ continue;
1938
+ const pkgDir = path3.join(globDir, entry.name);
1939
+ const pkgJsonPath = path3.join(pkgDir, "package.json");
1940
+ if (!fs4.existsSync(pkgJsonPath))
1941
+ continue;
1942
+ try {
1943
+ const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
1944
+ if (pkg.name) {
1945
+ const srcDir = fs4.existsSync(path3.join(pkgDir, "src")) ? path3.join(pkgDir, "src") : pkgDir;
1946
+ packages.set(pkg.name, srcDir);
1947
+ }
1948
+ } catch {}
1949
+ }
1950
+ }
1951
+ return packages.size > 0 ? { packages, rootDir } : undefined;
1952
+ }
1953
+ function createProgram({
1954
+ entryFile,
1955
+ baseDir = path3.dirname(entryFile),
1956
+ content
1957
+ }) {
1958
+ let configPath = ts2.findConfigFile(baseDir, ts2.sys.fileExists, "tsconfig.json");
1959
+ if (!configPath) {
1960
+ configPath = ts2.findConfigFile(baseDir, ts2.sys.fileExists, "jsconfig.json");
1961
+ }
1962
+ let compilerOptions = { ...DEFAULT_COMPILER_OPTIONS };
1963
+ let additionalRootFiles = [];
1964
+ if (configPath) {
1965
+ const configFile = ts2.readConfigFile(configPath, ts2.sys.readFile);
1966
+ const parsedConfig = ts2.parseJsonConfigFileContent(configFile.config, ts2.sys, path3.dirname(configPath));
1967
+ compilerOptions = { ...compilerOptions, ...parsedConfig.options };
1968
+ additionalRootFiles = resolveProjectReferences(configPath, parsedConfig);
1969
+ const sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
1970
+ additionalRootFiles.push(...sourceFiles);
1971
+ }
1972
+ if (isJsFile(entryFile)) {
1973
+ compilerOptions = {
1974
+ ...compilerOptions,
1975
+ allowJs: true,
1976
+ checkJs: true,
1977
+ isolatedDeclarations: false
1978
+ };
1979
+ } else {
1980
+ const allowJsVal = compilerOptions.allowJs;
1981
+ if (typeof allowJsVal === "boolean" && allowJsVal) {
1982
+ compilerOptions = { ...compilerOptions, allowJs: false, checkJs: false };
1983
+ }
1984
+ }
1985
+ const workspaceMap = buildWorkspaceMap(baseDir);
1986
+ const compilerHost = ts2.createCompilerHost(compilerOptions, true);
1987
+ let inMemorySource;
1988
+ if (workspaceMap) {
1989
+ const originalResolveModuleNames = compilerHost.resolveModuleNames?.bind(compilerHost);
1990
+ compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, options) => {
1991
+ return moduleNames.map((moduleName) => {
1992
+ const srcDir = workspaceMap.packages.get(moduleName);
1993
+ if (srcDir) {
1994
+ const indexFile = path3.join(srcDir, "index.ts");
1995
+ if (fs4.existsSync(indexFile)) {
1996
+ return { resolvedFileName: indexFile, isExternalLibraryImport: false };
1997
+ }
1998
+ }
1999
+ if (originalResolveModuleNames) {
2000
+ const result = originalResolveModuleNames([moduleName], containingFile, _reusedNames, redirectedReference, options);
2001
+ return result[0];
2002
+ }
2003
+ const resolved = ts2.resolveModuleName(moduleName, containingFile, options, compilerHost);
2004
+ return resolved.resolvedModule;
2005
+ });
2006
+ };
2007
+ }
2008
+ if (content !== undefined) {
2009
+ inMemorySource = ts2.createSourceFile(entryFile, content, ts2.ScriptTarget.Latest, true, getScriptKind(entryFile));
2010
+ const originalGetSourceFile = compilerHost.getSourceFile.bind(compilerHost);
2011
+ compilerHost.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
2012
+ if (fileName === entryFile) {
2013
+ return inMemorySource;
2014
+ }
2015
+ return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
2016
+ };
2017
+ }
2018
+ const rootFiles = [entryFile, ...additionalRootFiles];
2019
+ const program = ts2.createProgram(rootFiles, compilerOptions, compilerHost);
2020
+ const sourceFile = inMemorySource ?? program.getSourceFile(entryFile);
2021
+ return {
2022
+ program,
2023
+ compilerHost,
2024
+ compilerOptions,
2025
+ sourceFile,
2026
+ configPath
2027
+ };
2028
+ }
2029
+
2030
+ // src/serializers/classes.ts
2031
+ import ts7 from "typescript";
2032
+
2021
2033
  // src/types/parameters.ts
2022
2034
  import ts4 from "typescript";
2023
2035
 
@@ -2157,6 +2169,63 @@ var ARRAY_PROTOTYPE_METHODS = new Set([
2157
2169
  "toString",
2158
2170
  "toLocaleString"
2159
2171
  ]);
2172
+ var STRING_PROTOTYPE_METHODS = new Set([
2173
+ "charAt",
2174
+ "charCodeAt",
2175
+ "codePointAt",
2176
+ "concat",
2177
+ "endsWith",
2178
+ "includes",
2179
+ "indexOf",
2180
+ "lastIndexOf",
2181
+ "localeCompare",
2182
+ "match",
2183
+ "matchAll",
2184
+ "normalize",
2185
+ "padEnd",
2186
+ "padStart",
2187
+ "repeat",
2188
+ "replace",
2189
+ "replaceAll",
2190
+ "search",
2191
+ "slice",
2192
+ "split",
2193
+ "startsWith",
2194
+ "substring",
2195
+ "toLocaleLowerCase",
2196
+ "toLocaleUpperCase",
2197
+ "toLowerCase",
2198
+ "toUpperCase",
2199
+ "trim",
2200
+ "trimEnd",
2201
+ "trimStart",
2202
+ "at",
2203
+ "bold",
2204
+ "fixed",
2205
+ "italics",
2206
+ "link",
2207
+ "small",
2208
+ "strike",
2209
+ "sub",
2210
+ "sup",
2211
+ "anchor",
2212
+ "big",
2213
+ "blink",
2214
+ "fontcolor",
2215
+ "fontsize",
2216
+ "substr",
2217
+ "toString",
2218
+ "valueOf",
2219
+ "length"
2220
+ ]);
2221
+ var NUMBER_PROTOTYPE_METHODS = new Set([
2222
+ "toFixed",
2223
+ "toExponential",
2224
+ "toPrecision",
2225
+ "toString",
2226
+ "valueOf",
2227
+ "toLocaleString"
2228
+ ]);
2160
2229
  function isPrimitiveName(name) {
2161
2230
  return PRIMITIVES.has(name);
2162
2231
  }
@@ -2301,7 +2370,7 @@ function buildSchemaInternal(type, checker, ctx) {
2301
2370
  return { type: "bigint" };
2302
2371
  if (type.flags & ts3.TypeFlags.ESSymbol)
2303
2372
  return { type: "symbol" };
2304
- if (type.isThisType?.()) {
2373
+ if (type.isThisType === true) {
2305
2374
  const constraint = type.getConstraint?.();
2306
2375
  const symbol2 = constraint?.getSymbol() ?? type.getSymbol();
2307
2376
  if (symbol2 && !isAnonymous(type)) {
@@ -2521,7 +2590,7 @@ function buildSchemaInternal(type, checker, ctx) {
2521
2590
  return { type: checker.typeToString(type) };
2522
2591
  } finally {
2523
2592
  if (addedToVisited) {
2524
- ctx.visitedTypes.delete(type);
2593
+ ctx?.visitedTypes.delete(type);
2525
2594
  }
2526
2595
  }
2527
2596
  }
@@ -2556,6 +2625,7 @@ function buildFunctionSchema(callSignatures, checker, ctx) {
2556
2625
  return { type: "function", signatures: buildSignatures() };
2557
2626
  }
2558
2627
  function buildObjectSchema(properties, checker, ctx, originalType) {
2628
+ const isArrayLikeType = originalType ? checker.isArrayType(originalType) || checker.isTupleType(originalType) || originalType.symbol?.getName() === "Array" && isBuiltinSymbol(originalType.symbol) : false;
2559
2629
  const buildProps = () => {
2560
2630
  const props = {};
2561
2631
  const required = [];
@@ -2563,7 +2633,7 @@ function buildObjectSchema(properties, checker, ctx, originalType) {
2563
2633
  const propName = prop.getName();
2564
2634
  if (propName.startsWith("_"))
2565
2635
  continue;
2566
- if (ARRAY_PROTOTYPE_METHODS.has(propName)) {
2636
+ if (isArrayLikeType && ARRAY_PROTOTYPE_METHODS.has(propName)) {
2567
2637
  continue;
2568
2638
  }
2569
2639
  const propType = checker.getTypeOfSymbol(prop);
@@ -2945,8 +3015,6 @@ function isGenericTypeParameter(name) {
2945
3015
  return true;
2946
3016
  if (/^T[A-Z]/.test(name))
2947
3017
  return true;
2948
- if (["Key", "Value", "Item", "Element"].includes(name))
2949
- return true;
2950
3018
  return false;
2951
3019
  }
2952
3020
  function isExternalType(decl) {
@@ -2972,7 +3040,7 @@ class TypeRegistry {
2972
3040
  return Array.from(this.types.values());
2973
3041
  }
2974
3042
  registerType(type, ctx) {
2975
- const symbol = type.getSymbol() || type.aliasSymbol;
3043
+ const symbol = type.aliasSymbol || type.getSymbol();
2976
3044
  if (!symbol)
2977
3045
  return;
2978
3046
  const name = symbol.getName();
@@ -3027,7 +3095,7 @@ class TypeRegistry {
3027
3095
  }
3028
3096
  let schema = buildSchema(type, checker, ctx);
3029
3097
  if (this.isSelfRef(schema, name)) {
3030
- schema = this.buildObjectSchemaFromType(type, checker, ctx);
3098
+ schema = this.resolveSelRefSchema(type, checker, ctx);
3031
3099
  }
3032
3100
  return {
3033
3101
  id: name,
@@ -3043,7 +3111,56 @@ class TypeRegistry {
3043
3111
  const obj = schema;
3044
3112
  return obj.$ref === `#/types/${typeName}`;
3045
3113
  }
3046
- buildObjectSchemaFromType(type, checker, ctx) {
3114
+ resolveSelRefSchema(type, checker, ctx) {
3115
+ if (type.isUnion()) {
3116
+ const types = type.types;
3117
+ const allStringLiterals = types.every((t) => t.flags & ts5.TypeFlags.StringLiteral);
3118
+ if (allStringLiterals) {
3119
+ return {
3120
+ type: "string",
3121
+ enum: types.map((t) => t.value)
3122
+ };
3123
+ }
3124
+ const allNumberLiterals = types.every((t) => t.flags & ts5.TypeFlags.NumberLiteral);
3125
+ if (allNumberLiterals) {
3126
+ return {
3127
+ type: "number",
3128
+ enum: types.map((t) => t.value)
3129
+ };
3130
+ }
3131
+ return {
3132
+ anyOf: types.map((t) => buildSchema(t, checker, ctx))
3133
+ };
3134
+ }
3135
+ const symbol = type.getSymbol() ?? type.aliasSymbol;
3136
+ if (symbol) {
3137
+ const decl = symbol.declarations?.find(ts5.isEnumDeclaration);
3138
+ if (decl) {
3139
+ const members = [];
3140
+ for (const member of decl.members) {
3141
+ const memberSymbol = checker.getSymbolAtLocation(member.name);
3142
+ if (memberSymbol) {
3143
+ const constantValue = checker.getConstantValue(member);
3144
+ if (constantValue !== undefined) {
3145
+ members.push({
3146
+ name: memberSymbol.getName(),
3147
+ value: constantValue
3148
+ });
3149
+ }
3150
+ }
3151
+ }
3152
+ if (members.length > 0) {
3153
+ return {
3154
+ type: typeof members[0].value === "string" ? "string" : "number",
3155
+ enum: members.map((m) => m.value),
3156
+ "x-enum-members": members
3157
+ };
3158
+ }
3159
+ }
3160
+ }
3161
+ return this.buildObjectSchemaFromProperties(type, checker, ctx);
3162
+ }
3163
+ buildObjectSchemaFromProperties(type, checker, ctx) {
3047
3164
  const properties = type.getProperties();
3048
3165
  if (properties.length === 0) {
3049
3166
  return { type: checker.typeToString(type) };
@@ -3055,11 +3172,18 @@ class TypeRegistry {
3055
3172
  const typeName = type.getSymbol()?.getName() ?? "anonymous";
3056
3173
  ctx.onTruncation(typeName, properties.length, limit);
3057
3174
  }
3175
+ const isArrayLike = checker.isArrayType(type) || checker.isTupleType(type) || type.symbol?.getName() === "Array" && type.symbol?.getDeclarations()?.[0]?.getSourceFile()?.fileName?.includes("/typescript/lib/lib.");
3176
+ const isStringLike = type.flags & ts5.TypeFlags.StringLike;
3177
+ const isNumberLike = type.flags & ts5.TypeFlags.NumberLike;
3058
3178
  for (const prop of properties.slice(0, limit)) {
3059
3179
  const propName = prop.getName();
3060
3180
  if (propName.startsWith("_"))
3061
3181
  continue;
3062
- if (ARRAY_PROTOTYPE_METHODS.has(propName))
3182
+ if (isArrayLike && ARRAY_PROTOTYPE_METHODS.has(propName))
3183
+ continue;
3184
+ if (isStringLike && STRING_PROTOTYPE_METHODS.has(propName))
3185
+ continue;
3186
+ if (isNumberLike && NUMBER_PROTOTYPE_METHODS.has(propName))
3063
3187
  continue;
3064
3188
  const propType = checker.getTypeOfSymbol(prop);
3065
3189
  this.registerType(propType, ctx);
@@ -3091,7 +3215,7 @@ function createContext(program, sourceFile, options = {}) {
3091
3215
  visitedTypes: new Set,
3092
3216
  registeredTypes: new Set,
3093
3217
  includePrivate: options.includePrivate ?? false,
3094
- maxProperties: options.maxProperties ?? 20,
3218
+ maxProperties: options.maxProperties ?? 100,
3095
3219
  onTruncation: options.onTruncation
3096
3220
  };
3097
3221
  }
@@ -3388,6 +3512,8 @@ function serializeProperty(node, ctx) {
3388
3512
  flags.readonly = true;
3389
3513
  if (node.questionToken)
3390
3514
  flags.optional = true;
3515
+ const symbol = checker.getSymbolAtLocation(node.name ?? node);
3516
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3391
3517
  return {
3392
3518
  name,
3393
3519
  kind: "property",
@@ -3395,7 +3521,8 @@ function serializeProperty(node, ctx) {
3395
3521
  tags: tags.length > 0 ? tags : undefined,
3396
3522
  visibility,
3397
3523
  schema,
3398
- flags: Object.keys(flags).length > 0 ? flags : undefined
3524
+ flags: Object.keys(flags).length > 0 ? flags : undefined,
3525
+ ...deprecated ? { deprecated: true, deprecationReason } : {}
3399
3526
  };
3400
3527
  }
3401
3528
  function serializeMethod(node, ctx) {
@@ -3423,6 +3550,8 @@ function serializeMethod(node, ctx) {
3423
3550
  if (modifiers?.some((m) => m.kind === ts7.SyntaxKind.AbstractKeyword)) {
3424
3551
  flags.abstract = true;
3425
3552
  }
3553
+ const symbol = checker.getSymbolAtLocation(node.name ?? node);
3554
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3426
3555
  return {
3427
3556
  name,
3428
3557
  kind: "method",
@@ -3430,7 +3559,8 @@ function serializeMethod(node, ctx) {
3430
3559
  tags: tags.length > 0 ? tags : undefined,
3431
3560
  visibility,
3432
3561
  signatures: signatures.length > 0 ? signatures : undefined,
3433
- flags: Object.keys(flags).length > 0 ? flags : undefined
3562
+ flags: Object.keys(flags).length > 0 ? flags : undefined,
3563
+ ...deprecated ? { deprecated: true, deprecationReason } : {}
3434
3564
  };
3435
3565
  }
3436
3566
  function serializeConstructor(node, ctx) {
@@ -3616,6 +3746,14 @@ function serializeFunctionExport(node, ctx, nameOverride) {
3616
3746
  ...callSignatures.length > 1 ? { overloadIndex: index } : {}
3617
3747
  };
3618
3748
  });
3749
+ const flags = {};
3750
+ const modifiers = ts8.getModifiers(node);
3751
+ if (modifiers?.some((m) => m.kind === ts8.SyntaxKind.AsyncKeyword)) {
3752
+ flags.async = true;
3753
+ }
3754
+ if (node.asteriskToken) {
3755
+ flags.generator = true;
3756
+ }
3619
3757
  return {
3620
3758
  id: name,
3621
3759
  name,
@@ -3625,6 +3763,7 @@ function serializeFunctionExport(node, ctx, nameOverride) {
3625
3763
  source,
3626
3764
  typeParameters,
3627
3765
  signatures,
3766
+ ...Object.keys(flags).length > 0 ? { flags } : {},
3628
3767
  ...deprecated ? { deprecated: true, deprecationReason } : {},
3629
3768
  ...examples.length > 0 ? { examples } : {}
3630
3769
  };
@@ -3732,13 +3871,16 @@ function serializePropertySignature(node, ctx) {
3732
3871
  if (node.modifiers?.some((m) => m.kind === ts9.SyntaxKind.ReadonlyKeyword)) {
3733
3872
  flags.readonly = true;
3734
3873
  }
3874
+ const symbol = checker.getSymbolAtLocation(node.name);
3875
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3735
3876
  return {
3736
3877
  name,
3737
3878
  kind: "property",
3738
3879
  description,
3739
3880
  tags: tags.length > 0 ? tags : undefined,
3740
3881
  schema,
3741
- flags: Object.keys(flags).length > 0 ? flags : undefined
3882
+ flags: Object.keys(flags).length > 0 ? flags : undefined,
3883
+ ...deprecated ? { deprecated: true, deprecationReason } : {}
3742
3884
  };
3743
3885
  }
3744
3886
  function serializeMethodSignature(node, ctx) {
@@ -3751,13 +3893,16 @@ function serializeMethodSignature(node, ctx) {
3751
3893
  const flags = {};
3752
3894
  if (node.questionToken)
3753
3895
  flags.optional = true;
3896
+ const symbol = checker.getSymbolAtLocation(node.name);
3897
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(symbol);
3754
3898
  return {
3755
3899
  name,
3756
3900
  kind: "method",
3757
3901
  description,
3758
3902
  tags: tags.length > 0 ? tags : undefined,
3759
3903
  signatures: signatures.length > 0 ? signatures : undefined,
3760
- flags: Object.keys(flags).length > 0 ? flags : undefined
3904
+ flags: Object.keys(flags).length > 0 ? flags : undefined,
3905
+ ...deprecated ? { deprecated: true, deprecationReason } : {}
3761
3906
  };
3762
3907
  }
3763
3908
  function serializeCallSignature(node, ctx) {
@@ -4497,12 +4642,20 @@ async function getExport(options) {
4497
4642
  const result = createProgram({ entryFile, baseDir, content });
4498
4643
  const { program, sourceFile } = result;
4499
4644
  if (!sourceFile) {
4500
- return { export: null, types: [], errors: [`Could not load source file: ${entryFile}`] };
4645
+ return {
4646
+ export: null,
4647
+ types: [],
4648
+ errors: [`Entry file not found: ${entryFile}. Specify with: drift get src/index.ts <name>`]
4649
+ };
4501
4650
  }
4502
4651
  const checker = program.getTypeChecker();
4503
4652
  const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
4504
4653
  if (!moduleSymbol) {
4505
- return { export: null, types: [], errors: ["Could not get module symbol"] };
4654
+ return {
4655
+ export: null,
4656
+ types: [],
4657
+ errors: [`No exports found in ${entryFile}. Is this the right entry point?`]
4658
+ };
4506
4659
  }
4507
4660
  const exportedSymbols = checker.getExportsOfModule(moduleSymbol);
4508
4661
  const targetSymbol = exportedSymbols.find((s) => s.getName() === exportName);
@@ -4516,12 +4669,43 @@ async function getExport(options) {
4516
4669
  const ctx = createContext(program, sourceFile, { maxTypeDepth });
4517
4670
  ctx.exportedIds = exportedIds;
4518
4671
  try {
4672
+ const originalDecls = targetSymbol.declarations ?? [];
4673
+ const isNamespaceExportDecl = originalDecls.some((d) => ts11.isNamespaceExport(d) || ts11.isNamespaceImport(d));
4674
+ if (isNamespaceExportDecl) {
4675
+ const spec2 = serializeNamespaceForGet(targetSymbol, exportName, ctx);
4676
+ const types2 = ctx.typeRegistry.getAll().map((t) => normalizeType(t, { dialect: "draft-2020-12" }));
4677
+ return {
4678
+ export: normalizeExport(spec2, { dialect: "draft-2020-12" }),
4679
+ types: types2,
4680
+ errors
4681
+ };
4682
+ }
4519
4683
  const { declaration, resolvedSymbol, isTypeOnly } = resolveExportTarget(targetSymbol, checker);
4520
4684
  if (!declaration) {
4685
+ const externalPackage = detectExternalPackage(targetSymbol, checker);
4686
+ if (externalPackage) {
4687
+ const stub = {
4688
+ id: exportName,
4689
+ name: exportName,
4690
+ kind: "external",
4691
+ source: { package: externalPackage }
4692
+ };
4693
+ return { export: stub, types: [], errors };
4694
+ }
4521
4695
  return { export: null, types: [], errors: [`No declaration found for '${exportName}'`] };
4522
4696
  }
4523
4697
  let spec = serializeDeclaration(declaration, targetSymbol, resolvedSymbol, exportName, ctx, isTypeOnly);
4524
4698
  if (!spec) {
4699
+ const externalPackage = detectExternalPackage(targetSymbol, checker);
4700
+ if (externalPackage) {
4701
+ const stub = {
4702
+ id: exportName,
4703
+ name: exportName,
4704
+ kind: "external",
4705
+ source: { package: externalPackage }
4706
+ };
4707
+ return { export: stub, types: [], errors };
4708
+ }
4525
4709
  return { export: null, types: [], errors: [`Could not serialize '${exportName}'`] };
4526
4710
  }
4527
4711
  spec = normalizeExport(spec, { dialect: "draft-2020-12" });
@@ -4571,17 +4755,27 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
4571
4755
  } else if (ts11.isVariableDeclaration(declaration)) {
4572
4756
  const varStatement = declaration.parent?.parent;
4573
4757
  if (varStatement && ts11.isVariableStatement(varStatement)) {
4574
- if (declaration.initializer && ts11.isArrowFunction(declaration.initializer)) {
4758
+ if (declaration.initializer && (ts11.isArrowFunction(declaration.initializer) || ts11.isFunctionExpression(declaration.initializer))) {
4575
4759
  const varName = ts11.isIdentifier(declaration.name) ? declaration.name.text : declaration.name.getText();
4576
4760
  result = serializeFunctionExport(declaration.initializer, ctx, varName);
4577
4761
  } else {
4578
- result = serializeVariable(declaration, varStatement, ctx);
4762
+ const checker = ctx.program.getTypeChecker();
4763
+ const varType = checker.getTypeAtLocation(declaration);
4764
+ if (varType.getCallSignatures().length > 0) {
4765
+ result = serializeVariable(declaration, varStatement, ctx);
4766
+ if (result)
4767
+ result = { ...result, kind: "function" };
4768
+ } else {
4769
+ result = serializeVariable(declaration, varStatement, ctx);
4770
+ }
4579
4771
  }
4580
4772
  }
4773
+ } else if (ts11.isNamespaceExport(declaration) || ts11.isModuleDeclaration(declaration) || ts11.isNamespaceImport(declaration) || ts11.isSourceFile(declaration)) {
4774
+ result = serializeNamespaceForGet(_exportSymbol, exportName, ctx);
4581
4775
  }
4582
4776
  if (result) {
4583
4777
  if (result.name !== exportName) {
4584
- result = { ...result, id: exportName, name: result.name };
4778
+ result = { ...result, id: exportName, name: exportName };
4585
4779
  }
4586
4780
  if (isTypeOnly) {
4587
4781
  result = { ...result, flags: { ...result.flags ?? {}, typeOnly: true } };
@@ -4589,6 +4783,65 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
4589
4783
  }
4590
4784
  return result;
4591
4785
  }
4786
+ function serializeNamespaceForGet(symbol, exportName, ctx) {
4787
+ const checker = ctx.program.getTypeChecker();
4788
+ let targetSymbol = symbol;
4789
+ if (symbol.flags & ts11.SymbolFlags.Alias) {
4790
+ const aliased = checker.getAliasedSymbol(symbol);
4791
+ if (aliased && aliased !== symbol) {
4792
+ targetSymbol = aliased;
4793
+ }
4794
+ }
4795
+ const members = [];
4796
+ try {
4797
+ const nsExports = checker.getExportsOfModule(targetSymbol);
4798
+ for (const memberSymbol of nsExports) {
4799
+ const memberName = memberSymbol.getName();
4800
+ const memberDecls = memberSymbol.declarations ?? [];
4801
+ const memberDecl = memberSymbol.valueDeclaration || memberDecls[0];
4802
+ if (memberDecl) {
4803
+ const type = checker.getTypeAtLocation(memberDecl);
4804
+ const kind = getExportKind(memberDecl, type);
4805
+ members.push({ name: memberName, kind });
4806
+ }
4807
+ }
4808
+ } catch {}
4809
+ return {
4810
+ id: exportName,
4811
+ name: exportName,
4812
+ kind: "namespace",
4813
+ tags: [],
4814
+ ...members.length > 0 ? { members } : {}
4815
+ };
4816
+ }
4817
+ function detectExternalPackage(symbol, checker) {
4818
+ let targetSymbol = symbol;
4819
+ if (symbol.flags & ts11.SymbolFlags.Alias) {
4820
+ const aliased = checker.getAliasedSymbol(symbol);
4821
+ if (aliased && aliased !== symbol) {
4822
+ targetSymbol = aliased;
4823
+ }
4824
+ }
4825
+ const allDecls = [...targetSymbol.declarations ?? [], ...symbol.declarations ?? []];
4826
+ for (const decl of allDecls) {
4827
+ const sf = decl.getSourceFile();
4828
+ if (sf?.fileName.includes("node_modules")) {
4829
+ const match = sf.fileName.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/);
4830
+ if (match)
4831
+ return match[1];
4832
+ }
4833
+ if (ts11.isExportSpecifier(decl)) {
4834
+ const exportDecl = decl.parent?.parent;
4835
+ if (exportDecl && ts11.isExportDeclaration(exportDecl) && exportDecl.moduleSpecifier) {
4836
+ const moduleText = exportDecl.moduleSpecifier.text;
4837
+ if (!moduleText.startsWith(".") && !moduleText.startsWith("/")) {
4838
+ return moduleText;
4839
+ }
4840
+ }
4841
+ }
4842
+ }
4843
+ return;
4844
+ }
4592
4845
  // src/primitives/list.ts
4593
4846
  import * as path4 from "node:path";
4594
4847
  import ts12 from "typescript";
@@ -4599,12 +4852,18 @@ async function listExports(options) {
4599
4852
  const result = createProgram({ entryFile, baseDir, content });
4600
4853
  const { program, sourceFile } = result;
4601
4854
  if (!sourceFile) {
4602
- return { exports: [], errors: [`Could not load source file: ${entryFile}`] };
4855
+ return {
4856
+ exports: [],
4857
+ errors: [`Entry file not found: ${entryFile}. Specify with: drift list src/index.ts`]
4858
+ };
4603
4859
  }
4604
4860
  const checker = program.getTypeChecker();
4605
4861
  const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
4606
4862
  if (!moduleSymbol) {
4607
- return { exports: [], errors: ["Could not get module symbol"] };
4863
+ return {
4864
+ exports: [],
4865
+ errors: [`No exports found in ${entryFile}. Is this the right entry point?`]
4866
+ };
4608
4867
  }
4609
4868
  const exportedSymbols = checker.getExportsOfModule(moduleSymbol);
4610
4869
  for (const symbol of exportedSymbols) {
@@ -4632,8 +4891,15 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
4632
4891
  }
4633
4892
  const declarations = targetSymbol.declarations ?? [];
4634
4893
  const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !== ts12.SyntaxKind.ExportSpecifier) || declarations[0];
4635
- if (!declaration)
4636
- return null;
4894
+ if (!declaration) {
4895
+ return {
4896
+ name,
4897
+ kind: "external",
4898
+ file: "<external>",
4899
+ line: 0,
4900
+ reexport: true
4901
+ };
4902
+ }
4637
4903
  if (ts12.isSourceFile(declaration)) {
4638
4904
  return {
4639
4905
  name,
@@ -5803,7 +6069,12 @@ async function extract(options) {
5803
6069
  if (!sourceFile) {
5804
6070
  return {
5805
6071
  spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
5806
- diagnostics: [{ message: `Could not load source file: ${entryFile}`, severity: "error" }]
6072
+ diagnostics: [
6073
+ {
6074
+ message: `Entry file not found: ${entryFile}. Specify with: drift list src/index.ts`,
6075
+ severity: "error"
6076
+ }
6077
+ ]
5807
6078
  };
5808
6079
  }
5809
6080
  const typeChecker = program.getTypeChecker();
@@ -5811,7 +6082,12 @@ async function extract(options) {
5811
6082
  if (!moduleSymbol) {
5812
6083
  return {
5813
6084
  spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
5814
- diagnostics: [{ message: "Could not get module symbol", severity: "warning" }]
6085
+ diagnostics: [
6086
+ {
6087
+ message: `No exports found in ${entryFile}. Is this the right entry point?`,
6088
+ severity: "warning"
6089
+ }
6090
+ ]
5815
6091
  };
5816
6092
  }
5817
6093
  const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
@@ -6091,11 +6367,17 @@ function serializeDeclaration2(declaration, exportSymbol, exportName, ctx, isTyp
6091
6367
  } else if (ts16.isVariableDeclaration(declaration)) {
6092
6368
  const varStatement = declaration.parent?.parent;
6093
6369
  if (varStatement && ts16.isVariableStatement(varStatement)) {
6094
- if (declaration.initializer && ts16.isArrowFunction(declaration.initializer)) {
6370
+ if (declaration.initializer && (ts16.isArrowFunction(declaration.initializer) || ts16.isFunctionExpression(declaration.initializer))) {
6095
6371
  const varName = ts16.isIdentifier(declaration.name) ? declaration.name.text : declaration.name.getText();
6096
6372
  result = serializeFunctionExport(declaration.initializer, ctx, varName);
6097
6373
  } else {
6098
6374
  result = serializeVariable(declaration, varStatement, ctx);
6375
+ if (result?.kind === "variable") {
6376
+ const type = ctx.typeChecker.getTypeAtLocation(declaration);
6377
+ if (type.getConstructSignatures().length > 0) {
6378
+ result = { ...result, kind: "class" };
6379
+ }
6380
+ }
6099
6381
  }
6100
6382
  }
6101
6383
  } else if (ts16.isNamespaceExport(declaration) || ts16.isModuleDeclaration(declaration) || ts16.isNamespaceImport(declaration) || ts16.isSourceFile(declaration)) {
@@ -6120,6 +6402,12 @@ function serializeDeclaration2(declaration, exportSymbol, exportName, ctx, isTyp
6120
6402
  flags: { ...result.flags ?? {}, typeOnly: true }
6121
6403
  };
6122
6404
  }
6405
+ if (!result.deprecated) {
6406
+ const { deprecated, reason: deprecationReason } = isSymbolDeprecated(exportSymbol);
6407
+ if (deprecated) {
6408
+ result = { ...result, deprecated: true, deprecationReason };
6409
+ }
6410
+ }
6123
6411
  }
6124
6412
  return result;
6125
6413
  }
@@ -6167,7 +6455,7 @@ function serializeNamespaceMember(symbol, memberName, ctx) {
6167
6455
  return null;
6168
6456
  const type = checker.getTypeAtLocation(declaration);
6169
6457
  const callSignatures = type.getCallSignatures();
6170
- const deprecated = isSymbolDeprecated(targetSymbol);
6458
+ const { deprecated } = isSymbolDeprecated(targetSymbol);
6171
6459
  let kind = "variable";
6172
6460
  if (ts16.isFunctionDeclaration(declaration) || ts16.isFunctionExpression(declaration)) {
6173
6461
  kind = "function";
@@ -6446,8 +6734,10 @@ export {
6446
6734
  arktypeAdapter,
6447
6735
  analyzeSpec,
6448
6736
  TypeRegistry,
6737
+ STRING_PROTOTYPE_METHODS,
6449
6738
  QueryBuilder,
6450
6739
  PRIMITIVES,
6740
+ NUMBER_PROTOTYPE_METHODS,
6451
6741
  CacheManager,
6452
6742
  CONFIG_FILENAME,
6453
6743
  BUILTIN_TYPE_SCHEMAS,