@openpkg-ts/cli 0.6.3 → 0.7.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/README.md CHANGED
@@ -1,233 +1,38 @@
1
1
  # @openpkg-ts/cli
2
2
 
3
- CLI for TypeScript API extraction and documentation generation.
3
+ CLI for [OpenPkg](https://github.com/ryanwaits/openpkg-ts) — extract TypeScript API specs and generate docs. Thin wrapper over [@openpkg-ts/sdk](https://www.npmjs.com/package/@openpkg-ts/sdk).
4
4
 
5
- ## Install
5
+ ## Usage
6
6
 
7
7
  ```bash
8
- npm install -g @openpkg-ts/cli
9
- # or use directly
10
- npx @openpkg-ts/cli <command>
11
- ```
12
-
13
- ## Command Structure
14
-
15
- Commands organized under `openpkg spec` and `openpkg docs`. Legacy commands work as aliases.
16
-
17
- ```bash
18
- openpkg spec snapshot ./src/index.ts -o spec.json
19
- openpkg spec validate spec.json
20
-
21
- openpkg docs init
22
- openpkg docs generate spec.json -o ./docs
23
- openpkg docs add function-section
24
- ```
25
-
26
- ---
27
-
28
- ## Spec Commands
29
-
30
- ### list
31
-
32
- ```bash
33
- openpkg list src/index.ts
34
- ```
35
-
36
- Output: JSON array of `{ name, kind, file, line, description }`
37
-
38
- ### get
39
-
40
- ```bash
41
- openpkg get src/index.ts createClient
42
- ```
43
-
44
- Output: JSON with `{ export, types }` - full spec for the export plus referenced types.
45
-
46
- ### spec snapshot
47
-
48
- ```bash
49
- openpkg spec snapshot src/index.ts -o openpkg.json
50
- openpkg spec snapshot src/index.ts -o - # stdout
51
- openpkg spec snapshot src/index.ts --max-depth 4 --runtime --verify
52
- openpkg spec snapshot src/index.ts --only "use*,create*" --ignore "*Internal"
53
- ```
54
-
55
- | Flag | Description |
56
- |------|-------------|
57
- | `-o, --output <file>` | Output file (default: openpkg.json, `-` for stdout) |
58
- | `--max-depth <n>` | Max type depth (default: 4) |
59
- | `--skip-resolve` | Skip external type resolution |
60
- | `--runtime` | Enable Standard Schema runtime extraction (Zod, Valibot) |
61
- | `--only <exports>` | Filter exports (comma-separated, wildcards) |
62
- | `--ignore <exports>` | Ignore exports (comma-separated, wildcards) |
63
- | `--verify` | Exit 1 if any exports fail |
64
-
65
- ### spec validate
66
-
67
- ```bash
68
- openpkg spec validate openpkg.json
69
- openpkg spec validate openpkg.json --version 1.0
70
- ```
71
-
72
- ### spec diagnostics
73
-
74
- ```bash
75
- openpkg spec diagnostics openpkg.json
76
- ```
77
-
78
- ### spec filter
79
-
80
- ```bash
81
- openpkg spec filter openpkg.json --kind function,class
82
- openpkg spec filter openpkg.json --has-description -o documented.json
83
- openpkg spec filter openpkg.json --search "user" --summary
84
- openpkg spec filter openpkg.json --deprecated --quiet | jq '.exports[].name'
85
- ```
86
-
87
- | Flag | Description |
88
- |------|-------------|
89
- | `--kind <kinds>` | Filter by kinds (comma-separated) |
90
- | `--name <names>` | Filter by exact names (comma-separated) |
91
- | `--id <ids>` | Filter by export IDs (comma-separated) |
92
- | `--tag <tags>` | Filter by tags (comma-separated) |
93
- | `--deprecated` | Only deprecated exports |
94
- | `--no-deprecated` | Exclude deprecated exports |
95
- | `--has-description` | Only exports with descriptions |
96
- | `--missing-description` | Only exports without descriptions |
97
- | `--search <term>` | Search name/description (case-insensitive) |
98
- | `--module <path>` | Filter by source file path (contains) |
99
- | `-o, --output <file>` | Output file (default: stdout) |
100
- | `--summary` | Only output matched/total counts |
101
- | `--quiet` | Output raw spec only (no wrapper) |
102
-
103
- ### spec diff
104
-
105
- ```bash
106
- openpkg spec diff old.json new.json
107
- openpkg spec diff old.json new.json --summary
108
- ```
109
-
110
- ### spec breaking
111
-
112
- Exit 1 if breaking changes found.
113
-
114
- ```bash
115
- openpkg spec breaking old.json new.json
116
- ```
8
+ # Extract an OpenPkg spec
9
+ bunx @openpkg-ts/cli spec src/index.ts -o openpkg.json
117
10
 
118
- ### spec semver
11
+ # Generate markdown docs (from source or an existing spec)
12
+ bunx @openpkg-ts/cli docs src/index.ts -o docs/api.md
13
+ bunx @openpkg-ts/cli docs openpkg.json -f html -o docs/api.html
119
14
 
120
- ```bash
121
- openpkg spec semver old.json new.json
122
- ```
123
-
124
- ### spec changelog
125
-
126
- ```bash
127
- openpkg spec changelog old.json new.json
128
- openpkg spec changelog old.json new.json --format json
129
- ```
130
-
131
- ---
132
-
133
- ## Docs Commands
134
-
135
- ### docs init
136
-
137
- Initialize docs configuration.
138
-
139
- ```bash
140
- openpkg docs init
141
- ```
142
-
143
- Creates `openpkg.config.json` with default settings.
144
-
145
- ### docs generate
146
-
147
- Generate documentation from spec.
148
-
149
- ```bash
150
- # Markdown (default)
151
- openpkg docs generate openpkg.json -o api.md
152
-
153
- # React layout (single layout + spec JSON, add components via registry)
154
- openpkg docs generate openpkg.json -f react -o ./app/api
155
-
156
- # HTML
157
- openpkg docs generate openpkg.json -f html -o api.html
158
-
159
- # JSON (simplified structure)
160
- openpkg docs generate openpkg.json -f json
161
-
162
- # Split: one file per export
163
- openpkg docs generate openpkg.json --split -o docs/api/
164
-
165
- # With adapter
166
- openpkg docs generate openpkg.json -a fumadocs -o docs/api/
15
+ # List exports
16
+ bunx @openpkg-ts/cli list src/index.ts
167
17
 
168
- # From stdin
169
- openpkg spec snapshot src/index.ts -o - | openpkg docs generate - -f md
18
+ # Diff two specs, get a semver recommendation
19
+ bunx @openpkg-ts/cli diff old.json new.json
170
20
  ```
171
21
 
172
- | Flag | Description |
173
- |------|-------------|
174
- | `-o, --output <path>` | Output file or directory (default: stdout) |
175
- | `-f, --format <fmt>` | Format: `md`, `json`, `html`, `react` (default: md) |
176
- | `--split` | One file per export (requires `-o` as directory) |
177
- | `-a, --adapter <name>` | Use adapter: `fumadocs`, `raw` (default: raw) |
22
+ ## Commands
178
23
 
179
- ### docs add
24
+ | Command | Description |
25
+ |---------|-------------|
26
+ | `spec <entry.ts>` | Extract an OpenPkg spec from a TypeScript entry point |
27
+ | `docs <entry.ts \| spec.json>` | Generate docs (`-f md\|html\|json`) |
28
+ | `list <entry.ts>` | List exports with kind and location (`--json`) |
29
+ | `diff <old.json> <new.json>` | Compare specs; exits 2 if breaking changes |
180
30
 
181
- Add components from shadcn-compatible registry.
31
+ `-o, --output` writes to a file instead of stdout.
182
32
 
183
- ```bash
184
- openpkg docs add function-section
185
- openpkg docs add class-section interface-section
186
- openpkg docs add export-card param-table signature
187
- ```
188
-
189
- ### docs list
190
-
191
- List available registry components.
192
-
193
- ```bash
194
- openpkg docs list
195
- ```
196
-
197
- 16 components available: layouts, sections, primitives.
198
-
199
- ### docs view
33
+ For programmatic use, richer options, and framework integrations (search indexes, nav trees), use `@openpkg-ts/sdk` directly.
200
34
 
201
- View component details and dependencies.
202
-
203
- ```bash
204
- openpkg docs view function-section
205
- ```
206
-
207
- ---
208
-
209
- ## Pipelines
210
-
211
- Commands are composable via stdin/stdout:
212
-
213
- ```bash
214
- # Extract and generate docs
215
- openpkg spec snapshot src/index.ts -o - | openpkg docs generate - -f md > api.md
216
-
217
- # Extract, verify, then diff
218
- openpkg spec snapshot src/index.ts --verify -o new.json
219
- openpkg spec diff baseline.json new.json --summary
220
- ```
221
-
222
- ## Programmatic Use
223
-
224
- ```typescript
225
- import { getExport, listExports } from '@openpkg-ts/sdk';
226
-
227
- // Same primitives as CLI
228
- const { exports } = await listExports({ entryFile: './src/index.ts' });
229
- const { export: spec } = await getExport({ entryFile: './src/index.ts', exportName: 'myFunc' });
230
- ```
35
+ > Versions 0.6.4 are broken (unresolvable dependency) and deprecated. Use 0.7.0+.
231
36
 
232
37
  ## License
233
38
 
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { parseArgs } from "node:util";
7
+ import {
8
+ createDocs,
9
+ diffSpecs,
10
+ extractSpec,
11
+ listExports,
12
+ recommendSemverBump
13
+ } from "@openpkg-ts/sdk";
14
+ var HELP = `openpkg - extract TypeScript API specs and generate docs
15
+
16
+ Usage:
17
+ openpkg spec <entry.ts> [-o spec.json]
18
+ openpkg docs <entry.ts | spec.json> [-f md|html|json] [-o out]
19
+ openpkg list <entry.ts> [--json]
20
+ openpkg diff <old.json> <new.json>
21
+
22
+ Commands:
23
+ spec Extract an OpenPkg spec from a TypeScript entry point
24
+ docs Generate docs from an entry point or an existing spec file
25
+ list List exports (name, kind, location)
26
+ diff Compare two spec files and recommend a semver bump
27
+
28
+ Options:
29
+ -o, --output Write to file instead of stdout
30
+ -f, --format docs output format: md (default), html, json
31
+ --json list output as JSON
32
+ -h, --help Show this help
33
+ -v, --version Show version
34
+ `;
35
+ function fail(message) {
36
+ console.error(`error: ${message}`);
37
+ process.exit(1);
38
+ }
39
+ function write(content, output) {
40
+ if (output) {
41
+ fs.mkdirSync(path.dirname(path.resolve(output)), { recursive: true });
42
+ fs.writeFileSync(output, content);
43
+ console.error(`wrote ${output}`);
44
+ } else {
45
+ console.log(content);
46
+ }
47
+ }
48
+ function version() {
49
+ const pkg = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
50
+ return pkg.version;
51
+ }
52
+ function reportDiagnostics(diagnostics) {
53
+ for (const d of diagnostics) {
54
+ if (d.severity === "error" || d.severity === "warning") {
55
+ console.error(`${d.severity}: ${d.message}`);
56
+ }
57
+ }
58
+ }
59
+ async function specCommand(args) {
60
+ const { values, positionals } = parseArgs({
61
+ args,
62
+ options: { output: { type: "string", short: "o" } },
63
+ allowPositionals: true
64
+ });
65
+ const entryFile = positionals[0];
66
+ if (!entryFile)
67
+ fail("spec requires an entry file (openpkg spec src/index.ts)");
68
+ const { spec, diagnostics } = await extractSpec({ entryFile });
69
+ reportDiagnostics(diagnostics);
70
+ write(JSON.stringify(spec, null, 2), values.output);
71
+ }
72
+ async function docsCommand(args) {
73
+ const { values, positionals } = parseArgs({
74
+ args,
75
+ options: {
76
+ output: { type: "string", short: "o" },
77
+ format: { type: "string", short: "f" }
78
+ },
79
+ allowPositionals: true
80
+ });
81
+ const input = positionals[0];
82
+ if (!input)
83
+ fail("docs requires an entry file or spec file (openpkg docs src/index.ts)");
84
+ const format = values.format ?? "md";
85
+ if (!["md", "html", "json"].includes(format))
86
+ fail(`unknown format "${format}" (md|html|json)`);
87
+ let docs;
88
+ if (input.endsWith(".json")) {
89
+ docs = createDocs(input);
90
+ } else {
91
+ const { spec, diagnostics } = await extractSpec({ entryFile: input });
92
+ reportDiagnostics(diagnostics);
93
+ docs = createDocs(spec);
94
+ }
95
+ const content = format === "md" ? docs.toMarkdown() : format === "html" ? docs.toHTML() : JSON.stringify(docs.toJSON(), null, 2);
96
+ write(content, values.output);
97
+ }
98
+ async function listCommand(args) {
99
+ const { values, positionals } = parseArgs({
100
+ args,
101
+ options: { json: { type: "boolean" } },
102
+ allowPositionals: true
103
+ });
104
+ const entryFile = positionals[0];
105
+ if (!entryFile)
106
+ fail("list requires an entry file (openpkg list src/index.ts)");
107
+ const { exports } = await listExports({ entryFile });
108
+ if (values.json) {
109
+ console.log(JSON.stringify(exports, null, 2));
110
+ return;
111
+ }
112
+ for (const exp of exports) {
113
+ const location = exp.file ? ` (${exp.file}:${exp.line})` : "";
114
+ console.log(`${exp.kind.padEnd(10)}${exp.name}${location}`);
115
+ }
116
+ }
117
+ function readSpecFile(file) {
118
+ try {
119
+ return JSON.parse(fs.readFileSync(file, "utf-8"));
120
+ } catch (err) {
121
+ fail(`failed to read spec file ${file}: ${err instanceof Error ? err.message : String(err)}`);
122
+ }
123
+ }
124
+ function diffCommand(args) {
125
+ const [oldFile, newFile] = args;
126
+ if (!oldFile || !newFile)
127
+ fail("diff requires two spec files (openpkg diff old.json new.json)");
128
+ const diff = diffSpecs(readSpecFile(oldFile), readSpecFile(newFile));
129
+ const recommendation = recommendSemverBump(diff);
130
+ const section = (title, items) => {
131
+ if (!items.length)
132
+ return;
133
+ console.log(`${title}:`);
134
+ for (const item of items)
135
+ console.log(` - ${item}`);
136
+ };
137
+ section("Breaking", diff.breaking);
138
+ section("Non-breaking", diff.nonBreaking);
139
+ section("Docs-only", diff.docsOnly);
140
+ if (!diff.breaking.length && !diff.nonBreaking.length && !diff.docsOnly.length) {
141
+ console.log("No changes.");
142
+ }
143
+ console.log(`
144
+ Recommended bump: ${recommendation.bump} (${recommendation.reason})`);
145
+ if (diff.breaking.length)
146
+ process.exitCode = 2;
147
+ }
148
+ async function main() {
149
+ const [command, ...rest] = process.argv.slice(2);
150
+ switch (command) {
151
+ case "spec":
152
+ await specCommand(rest);
153
+ break;
154
+ case "docs":
155
+ await docsCommand(rest);
156
+ break;
157
+ case "list":
158
+ await listCommand(rest);
159
+ break;
160
+ case "diff":
161
+ diffCommand(rest);
162
+ break;
163
+ case "-v":
164
+ case "--version":
165
+ console.log(version());
166
+ break;
167
+ case undefined:
168
+ case "-h":
169
+ case "--help":
170
+ console.log(HELP);
171
+ break;
172
+ default:
173
+ fail(`unknown command "${command}" - run openpkg --help`);
174
+ }
175
+ }
176
+ main().catch((err) => {
177
+ fail(err instanceof Error ? err.message : String(err));
178
+ });
package/package.json CHANGED
@@ -1,18 +1,25 @@
1
1
  {
2
2
  "name": "@openpkg-ts/cli",
3
- "version": "0.6.3",
4
- "description": "CLI for OpenPkg TypeScript API extraction and documentation generation",
3
+ "version": "0.7.0",
4
+ "description": "CLI for OpenPkg - extract TypeScript API specs and generate docs",
5
+ "keywords": [
6
+ "openpkg",
7
+ "typescript",
8
+ "api-extractor",
9
+ "cli",
10
+ "docs"
11
+ ],
5
12
  "homepage": "https://github.com/ryanwaits/openpkg-ts#readme",
6
13
  "repository": {
7
14
  "type": "git",
8
15
  "url": "git+https://github.com/ryanwaits/openpkg-ts.git",
9
16
  "directory": "packages/cli"
10
17
  },
18
+ "license": "MIT",
19
+ "author": "Ryan Waits",
11
20
  "type": "module",
12
- "main": "./dist/src/index.js",
13
- "types": "./dist/src/index.d.ts",
14
21
  "bin": {
15
- "openpkg": "./dist/bin/openpkg.js"
22
+ "openpkg": "./dist/index.js"
16
23
  },
17
24
  "files": [
18
25
  "dist"
@@ -20,12 +27,13 @@
20
27
  "scripts": {
21
28
  "build": "bunup",
22
29
  "dev": "bunup --watch",
30
+ "lint": "biome check src/",
31
+ "lint:fix": "biome check --write src/",
32
+ "format": "biome format --write src/",
23
33
  "test": "bun test"
24
34
  },
25
35
  "dependencies": {
26
- "@openpkg-ts/adapters": "^0.3.14",
27
- "@openpkg-ts/sdk": "^0.35.1",
28
- "commander": "^14.0.0"
36
+ "@openpkg-ts/sdk": "^0.37.1"
29
37
  },
30
38
  "devDependencies": {
31
39
  "@types/bun": "latest",