@openpkg-ts/extract 0.14.3 → 0.14.5

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/bin/tspec.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  extract
4
- } from "../shared/chunk-axmbd6k1.js";
4
+ } from "../shared/chunk-mhaxcbzq.js";
5
5
 
6
6
  // src/cli/spec.ts
7
7
  import * as fs from "node:fs";
@@ -497,6 +497,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
497
497
  var source_default = chalk;
498
498
 
499
499
  // ../cli-utils/dist/index.js
500
+ import { Worker } from "node:worker_threads";
500
501
  var colors = {
501
502
  success: source_default.green,
502
503
  error: source_default.red,
@@ -655,8 +656,8 @@ class MultiProgress {
655
656
  hideCursor();
656
657
  this.setupSignalHandler();
657
658
  this.timer = setInterval(() => {
658
- this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
659
659
  if (this.bars.size > 0 && [...this.bars.values()].some((b) => b.status === "active")) {
660
+ this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
660
661
  this.render();
661
662
  }
662
663
  }, this.options.spinnerInterval);
@@ -1029,11 +1030,13 @@ class Spinner {
1029
1030
  symbols = getSymbols(supportsUnicode());
1030
1031
  lastRenderedLines = 0;
1031
1032
  sigintHandler = null;
1033
+ animate;
1032
1034
  constructor(options = {}) {
1033
1035
  this.label = options.label ?? "";
1034
1036
  this.detail = options.detail;
1035
1037
  this.interval = options.interval ?? 80;
1036
1038
  this.colorFn = spinnerColors[options.color ?? "cyan"];
1039
+ this.animate = options.animate ?? true;
1037
1040
  const style = options.style ?? "circle";
1038
1041
  this.frames = supportsUnicode() ? FRAME_SETS[style] : ASCII_FRAME_SET;
1039
1042
  }
@@ -1045,7 +1048,7 @@ class Spinner {
1045
1048
  this.state = "spinning";
1046
1049
  this.frameIndex = 0;
1047
1050
  this.lastRenderedLines = 0;
1048
- if (!isInteractive()) {
1051
+ if (!isInteractive() || !this.animate) {
1049
1052
  console.log(`${this.symbols.bullet} ${this.label}`);
1050
1053
  return this;
1051
1054
  }
@@ -1103,14 +1106,12 @@ class Spinner {
1103
1106
  this.timer = null;
1104
1107
  }
1105
1108
  this.state = state;
1106
- if (!isInteractive()) {
1107
- const symbol = state === "success" ? this.symbols.success : this.symbols.error;
1108
- const colorFn = state === "success" ? colors.success : colors.error;
1109
+ const symbol = state === "success" ? this.symbols.success : this.symbols.error;
1110
+ const colorFn = state === "success" ? colors.success : colors.error;
1111
+ if (!isInteractive() || !this.animate) {
1109
1112
  console.log(`${colorFn(symbol)} ${this.label}`);
1110
1113
  } else {
1111
1114
  this.clearOutput();
1112
- const symbol = state === "success" ? this.symbols.success : this.symbols.error;
1113
- const colorFn = state === "success" ? colors.success : colors.error;
1114
1115
  process.stdout.write(`${colorFn(symbol)} ${this.label}
1115
1116
  `);
1116
1117
  }
@@ -1186,8 +1187,8 @@ class StepProgress {
1186
1187
  this.setupSignalHandler();
1187
1188
  this.render();
1188
1189
  this.timer = setInterval(() => {
1189
- this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
1190
1190
  if (this.steps.some((s) => s.status === "active")) {
1191
+ this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
1191
1192
  this.render();
1192
1193
  }
1193
1194
  }, this.spinnerInterval);
@@ -1488,10 +1489,24 @@ import { normalize, validateSpec } from "@openpkg-ts/spec";
1488
1489
  import { Command } from "commander";
1489
1490
  function createProgram() {
1490
1491
  const program = new Command("tspec").description("Extract TypeScript package API to OpenPkg spec").argument("[entry]", "Entry point file").option("-o, --output <file>", "Output file", "openpkg.json").option("--max-depth <n>", "Max type depth (default: 4)").option("--skip-resolve", "Skip external type resolution").option("--runtime", "Enable Standard Schema runtime extraction").option("-v, --verbose", "Show detailed output").action(async (entry, options) => {
1491
- const entryFile = entry || findEntryPoint(process.cwd());
1492
- if (!entryFile) {
1493
- console.error("No entry point found. Please specify an entry file.");
1494
- process.exit(1);
1492
+ let entryFile;
1493
+ let fromDts = false;
1494
+ if (entry) {
1495
+ entryFile = entry;
1496
+ fromDts = entry.endsWith(".d.ts");
1497
+ } else {
1498
+ const found = findEntryPoint(process.cwd());
1499
+ if (!found) {
1500
+ console.error("No entry point found. Please specify an entry file.");
1501
+ process.exit(1);
1502
+ }
1503
+ entryFile = found.path;
1504
+ fromDts = found.fromDts;
1505
+ }
1506
+ if (fromDts) {
1507
+ console.warn("⚠ Using .d.ts file. TSDoc comments may be missing.");
1508
+ console.warn(` Consider: tspec src/index.ts
1509
+ `);
1495
1510
  }
1496
1511
  const spin = spinner("Extracting...");
1497
1512
  const result = await extract({
@@ -1523,29 +1538,36 @@ function createProgram() {
1523
1538
  return program;
1524
1539
  }
1525
1540
  function findEntryPoint(cwd) {
1541
+ const sourceEntries = ["src/index.ts", "index.ts", "lib/index.ts"];
1542
+ for (const entry of sourceEntries) {
1543
+ const fullPath = path.join(cwd, entry);
1544
+ if (fs.existsSync(fullPath))
1545
+ return { path: fullPath, fromDts: false };
1546
+ }
1526
1547
  const pkgPath = path.join(cwd, "package.json");
1527
1548
  if (fs.existsSync(pkgPath)) {
1528
1549
  try {
1529
1550
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
1530
- if (pkg.types)
1531
- return path.join(cwd, pkg.types);
1532
- if (pkg.typings)
1533
- return path.join(cwd, pkg.typings);
1534
- if (pkg.exports?.["."]?.types)
1535
- return path.join(cwd, pkg.exports["."].types);
1551
+ if (pkg.types) {
1552
+ const p = path.join(cwd, pkg.types);
1553
+ return { path: p, fromDts: pkg.types.endsWith(".d.ts") };
1554
+ }
1555
+ if (pkg.typings) {
1556
+ const p = path.join(cwd, pkg.typings);
1557
+ return { path: p, fromDts: pkg.typings.endsWith(".d.ts") };
1558
+ }
1559
+ if (pkg.exports?.["."]?.types) {
1560
+ const p = path.join(cwd, pkg.exports["."].types);
1561
+ return { path: p, fromDts: pkg.exports["."].types.endsWith(".d.ts") };
1562
+ }
1536
1563
  if (pkg.main) {
1537
1564
  const mainTs = pkg.main.replace(/\.js$/, ".ts");
1538
- if (fs.existsSync(path.join(cwd, mainTs)))
1539
- return path.join(cwd, mainTs);
1565
+ const fullPath = path.join(cwd, mainTs);
1566
+ if (fs.existsSync(fullPath))
1567
+ return { path: fullPath, fromDts: false };
1540
1568
  }
1541
1569
  } catch {}
1542
1570
  }
1543
- const fallbacks = ["src/index.ts", "index.ts", "lib/index.ts"];
1544
- for (const fallback of fallbacks) {
1545
- const fullPath = path.join(cwd, fallback);
1546
- if (fs.existsSync(fullPath))
1547
- return fullPath;
1548
- }
1549
1571
  return null;
1550
1572
  }
1551
1573
 
@@ -1673,24 +1673,82 @@ function serializeDeclaration(declaration, exportSymbol, _targetSymbol, exportNa
1673
1673
  result = serializeVariable(declaration, varStatement, ctx);
1674
1674
  }
1675
1675
  } else if (ts8.isNamespaceExport(declaration) || ts8.isModuleDeclaration(declaration)) {
1676
- result = serializeNamespaceExport(exportSymbol, exportName);
1676
+ result = serializeNamespaceExport(exportSymbol, exportName, ctx);
1677
1677
  } else if (ts8.isSourceFile(declaration)) {
1678
- result = serializeNamespaceExport(exportSymbol, exportName);
1678
+ result = serializeNamespaceExport(exportSymbol, exportName, ctx);
1679
1679
  }
1680
1680
  if (result) {
1681
1681
  result = withExportName(result, exportName);
1682
1682
  }
1683
1683
  return result;
1684
1684
  }
1685
- function serializeNamespaceExport(symbol, exportName) {
1685
+ function serializeNamespaceExport(symbol, exportName, ctx) {
1686
1686
  const { description, tags, examples } = getJSDocFromExportSymbol(symbol);
1687
+ const members = [];
1688
+ const checker = ctx.program.getTypeChecker();
1689
+ let targetSymbol = symbol;
1690
+ if (symbol.flags & ts8.SymbolFlags.Alias) {
1691
+ const aliased = checker.getAliasedSymbol(symbol);
1692
+ if (aliased && aliased !== symbol) {
1693
+ targetSymbol = aliased;
1694
+ }
1695
+ }
1696
+ const nsExports = checker.getExportsOfModule(targetSymbol);
1697
+ for (const memberSymbol of nsExports) {
1698
+ const memberName = memberSymbol.getName();
1699
+ const member = serializeNamespaceMember(memberSymbol, memberName, ctx);
1700
+ if (member) {
1701
+ members.push(member);
1702
+ }
1703
+ }
1687
1704
  return {
1688
1705
  id: exportName,
1689
1706
  name: exportName,
1690
1707
  kind: "namespace",
1691
1708
  description,
1692
1709
  tags,
1693
- ...examples.length > 0 ? { examples } : {}
1710
+ ...examples.length > 0 ? { examples } : {},
1711
+ ...members.length > 0 ? { members } : {}
1712
+ };
1713
+ }
1714
+ function serializeNamespaceMember(symbol, memberName, ctx) {
1715
+ const checker = ctx.program.getTypeChecker();
1716
+ let targetSymbol = symbol;
1717
+ if (symbol.flags & ts8.SymbolFlags.Alias) {
1718
+ const aliased = checker.getAliasedSymbol(symbol);
1719
+ if (aliased && aliased !== symbol) {
1720
+ targetSymbol = aliased;
1721
+ }
1722
+ }
1723
+ const declarations = targetSymbol.declarations ?? [];
1724
+ const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !== ts8.SyntaxKind.ExportSpecifier) || declarations[0];
1725
+ if (!declaration)
1726
+ return null;
1727
+ let kind = "variable";
1728
+ if (ts8.isFunctionDeclaration(declaration) || ts8.isFunctionExpression(declaration)) {
1729
+ kind = "function";
1730
+ } else if (ts8.isClassDeclaration(declaration)) {
1731
+ kind = "class";
1732
+ } else if (ts8.isInterfaceDeclaration(declaration)) {
1733
+ kind = "interface";
1734
+ } else if (ts8.isTypeAliasDeclaration(declaration)) {
1735
+ kind = "type";
1736
+ } else if (ts8.isEnumDeclaration(declaration)) {
1737
+ kind = "enum";
1738
+ } else if (ts8.isVariableDeclaration(declaration)) {
1739
+ const type = checker.getTypeAtLocation(declaration);
1740
+ const callSignatures = type.getCallSignatures();
1741
+ if (callSignatures.length > 0) {
1742
+ kind = "function";
1743
+ }
1744
+ }
1745
+ const docComment = targetSymbol.getDocumentationComment(checker);
1746
+ const description = docComment.map((c) => c.text).join(`
1747
+ `) || undefined;
1748
+ return {
1749
+ name: memberName,
1750
+ kind,
1751
+ ...description ? { description } : {}
1694
1752
  };
1695
1753
  }
1696
1754
  function getJSDocFromExportSymbol(symbol) {
package/dist/src/index.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  serializeTypeAlias,
27
27
  serializeVariable,
28
28
  withDescription
29
- } from "../shared/chunk-axmbd6k1.js";
29
+ } from "../shared/chunk-mhaxcbzq.js";
30
30
  // src/schema/registry.ts
31
31
  function isTypeReference(type) {
32
32
  return !!(type.flags & 524288 && type.objectFlags && type.objectFlags & 4);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/extract",
3
- "version": "0.14.3",
3
+ "version": "0.14.5",
4
4
  "description": "TypeScript export extraction to OpenPkg spec",
5
5
  "keywords": [
6
6
  "openpkg",