@openpkg-ts/cli 0.2.3 → 0.3.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/README.md +133 -0
- package/dist/bin/openpkg.js +701 -0
- package/dist/shared/chunk-1dqs11h6.js +20 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/{index.js → src/index.js} +2 -0
- package/package.json +9 -3
- package/CHANGELOG.md +0 -32
- package/bin/openpkg.ts +0 -61
- package/dist/index.d.ts +0 -2
- package/src/commands/diff.ts +0 -175
- package/src/commands/docs.ts +0 -125
- package/src/commands/snapshot.ts +0 -122
- package/src/index.ts +0 -2
- package/test/diff.test.ts +0 -336
- package/test/docs.test.ts +0 -599
- package/test/get.test.ts +0 -413
- package/test/spec.test.ts +0 -469
- package/tsconfig.json +0 -15
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
export { __toESM, __require };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getExport, listExports } from "@openpkg-ts/sdk";
|
|
2
|
+
import { OpenPkg } from "@openpkg-ts/spec";
|
|
3
|
+
type FilterResult = {
|
|
4
|
+
spec: OpenPkg;
|
|
5
|
+
matched: number;
|
|
6
|
+
total: number;
|
|
7
|
+
};
|
|
8
|
+
type FilterSummaryResult = {
|
|
9
|
+
matched: number;
|
|
10
|
+
total: number;
|
|
11
|
+
};
|
|
12
|
+
export { listExports, getExport, FilterSummaryResult, FilterResult };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openpkg-ts/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "CLI for OpenPkg TypeScript API extraction and documentation generation",
|
|
5
5
|
"homepage": "https://github.com/ryanwaits/openpkg-ts#readme",
|
|
6
6
|
"repository": {
|
|
@@ -9,16 +9,22 @@
|
|
|
9
9
|
"directory": "packages/cli"
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
12
|
+
"main": "./dist/src/index.js",
|
|
13
|
+
"types": "./dist/src/index.d.ts",
|
|
12
14
|
"bin": {
|
|
13
|
-
"openpkg": "./bin/openpkg.
|
|
15
|
+
"openpkg": "./dist/bin/openpkg.js"
|
|
14
16
|
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
15
20
|
"scripts": {
|
|
16
21
|
"build": "bunup",
|
|
17
22
|
"dev": "bunup --watch",
|
|
18
23
|
"test": "bun test"
|
|
19
24
|
},
|
|
20
25
|
"dependencies": {
|
|
21
|
-
"@openpkg-ts/
|
|
26
|
+
"@openpkg-ts/adapters": "^0.3.0",
|
|
27
|
+
"@openpkg-ts/sdk": "^0.31.0",
|
|
22
28
|
"commander": "^14.0.0"
|
|
23
29
|
},
|
|
24
30
|
"devDependencies": {
|
package/CHANGELOG.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# @openpkg-ts/cli
|
|
2
|
-
|
|
3
|
-
## 0.2.3
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- update @openpkg-ts/sdk dependency to ^0.30.2
|
|
8
|
-
|
|
9
|
-
## 0.2.2
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
12
|
-
|
|
13
|
-
- pull version from package.json instead of hardcoding
|
|
14
|
-
|
|
15
|
-
## 0.2.1
|
|
16
|
-
|
|
17
|
-
### Patch Changes
|
|
18
|
-
|
|
19
|
-
- fix workspace:\* deps to use published versions for npm compatibility
|
|
20
|
-
- Updated dependencies
|
|
21
|
-
- @openpkg-ts/sdk@0.30.1
|
|
22
|
-
|
|
23
|
-
## 0.2.0
|
|
24
|
-
|
|
25
|
-
### Minor Changes
|
|
26
|
-
|
|
27
|
-
- Major monorepo restructure: extract → sdk, doc-generator split into sdk/react/adapters, fumadocs-adapter deleted (use @openpkg-ts/adapters/fumadocs)
|
|
28
|
-
|
|
29
|
-
### Patch Changes
|
|
30
|
-
|
|
31
|
-
- Updated dependencies
|
|
32
|
-
- @openpkg-ts/sdk@0.30.0
|
package/bin/openpkg.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { getExport, listExports } from '@openpkg-ts/sdk';
|
|
4
|
-
import { Command } from 'commander';
|
|
5
|
-
import { createDiffCommand } from '../src/commands/diff';
|
|
6
|
-
import { createDocsCommand } from '../src/commands/docs';
|
|
7
|
-
import { createSnapshotCommand } from '../src/commands/snapshot';
|
|
8
|
-
import pkg from '../package.json';
|
|
9
|
-
|
|
10
|
-
const program = new Command();
|
|
11
|
-
|
|
12
|
-
program
|
|
13
|
-
.name('openpkg')
|
|
14
|
-
.description('OpenPkg CLI - TypeScript API extraction primitives')
|
|
15
|
-
.version(pkg.version);
|
|
16
|
-
|
|
17
|
-
program
|
|
18
|
-
.command('list')
|
|
19
|
-
.description('List exports from a TypeScript entry point')
|
|
20
|
-
.argument('<entry>', 'Entry point file path')
|
|
21
|
-
.action(async (entry: string) => {
|
|
22
|
-
const entryFile = path.resolve(entry);
|
|
23
|
-
const result = await listExports({ entryFile });
|
|
24
|
-
|
|
25
|
-
if (result.errors.length > 0) {
|
|
26
|
-
console.error(JSON.stringify({ errors: result.errors }, null, 2));
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
console.log(JSON.stringify(result.exports, null, 2));
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
program
|
|
34
|
-
.command('get')
|
|
35
|
-
.description('Get detailed spec for a single export')
|
|
36
|
-
.argument('<entry>', 'Entry point file path')
|
|
37
|
-
.argument('<name>', 'Export name')
|
|
38
|
-
.action(async (entry: string, name: string) => {
|
|
39
|
-
const entryFile = path.resolve(entry);
|
|
40
|
-
const result = await getExport({ entryFile, exportName: name });
|
|
41
|
-
|
|
42
|
-
if (!result.export) {
|
|
43
|
-
const errorMsg =
|
|
44
|
-
result.errors.length > 0 ? result.errors.join('; ') : `Export '${name}' not found`;
|
|
45
|
-
console.error(JSON.stringify({ error: errorMsg }, null, 2));
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Output export with related types if any
|
|
50
|
-
const output: Record<string, unknown> = { export: result.export };
|
|
51
|
-
if (result.types.length > 0) {
|
|
52
|
-
output.types = result.types;
|
|
53
|
-
}
|
|
54
|
-
console.log(JSON.stringify(output, null, 2));
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
program.addCommand(createSnapshotCommand());
|
|
58
|
-
program.addCommand(createDiffCommand());
|
|
59
|
-
program.addCommand(createDocsCommand());
|
|
60
|
-
|
|
61
|
-
program.parse();
|
package/dist/index.d.ts
DELETED
package/src/commands/diff.ts
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
type CategorizedBreaking,
|
|
5
|
-
categorizeBreakingChanges,
|
|
6
|
-
diffSpec,
|
|
7
|
-
type OpenPkg,
|
|
8
|
-
recommendSemverBump,
|
|
9
|
-
type SemverBump,
|
|
10
|
-
type SpecExportKind,
|
|
11
|
-
} from '@openpkg-ts/spec';
|
|
12
|
-
import { Command } from 'commander';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A changed export with details about what changed
|
|
16
|
-
*/
|
|
17
|
-
export interface ChangedExport {
|
|
18
|
-
id: string;
|
|
19
|
-
name: string;
|
|
20
|
-
kind: SpecExportKind;
|
|
21
|
-
description: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Enriched diff result with categorized changes
|
|
26
|
-
*/
|
|
27
|
-
export interface DiffResult {
|
|
28
|
-
breaking: CategorizedBreaking[];
|
|
29
|
-
added: string[];
|
|
30
|
-
removed: RemovedExport[];
|
|
31
|
-
changed: ChangedExport[];
|
|
32
|
-
docsOnly: string[];
|
|
33
|
-
summary: {
|
|
34
|
-
breakingCount: number;
|
|
35
|
-
addedCount: number;
|
|
36
|
-
removedCount: number;
|
|
37
|
-
changedCount: number;
|
|
38
|
-
docsOnlyCount: number;
|
|
39
|
-
semverBump: SemverBump;
|
|
40
|
-
semverReason: string;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface RemovedExport {
|
|
45
|
-
id: string;
|
|
46
|
-
name: string;
|
|
47
|
-
kind: SpecExportKind;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function loadSpec(filePath: string): OpenPkg {
|
|
51
|
-
const resolved = path.resolve(filePath);
|
|
52
|
-
const content = fs.readFileSync(resolved, 'utf-8');
|
|
53
|
-
return JSON.parse(content) as OpenPkg;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function toExportMap(spec: OpenPkg): Map<string, { name: string; kind: SpecExportKind }> {
|
|
57
|
-
const map = new Map<string, { name: string; kind: SpecExportKind }>();
|
|
58
|
-
for (const exp of spec.exports) {
|
|
59
|
-
map.set(exp.id, { name: exp.name, kind: exp.kind });
|
|
60
|
-
}
|
|
61
|
-
if (spec.types) {
|
|
62
|
-
for (const t of spec.types) {
|
|
63
|
-
map.set(t.id, { name: t.name, kind: t.kind as SpecExportKind });
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return map;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Enriches basic diffSpec output with categorization
|
|
71
|
-
*/
|
|
72
|
-
export function enrichDiff(oldSpec: OpenPkg, newSpec: OpenPkg): DiffResult {
|
|
73
|
-
const rawDiff = diffSpec(oldSpec, newSpec);
|
|
74
|
-
const categorized = categorizeBreakingChanges(rawDiff.breaking, oldSpec, newSpec);
|
|
75
|
-
const semver = recommendSemverBump(rawDiff);
|
|
76
|
-
|
|
77
|
-
const oldExports = toExportMap(oldSpec);
|
|
78
|
-
const _newExports = toExportMap(newSpec);
|
|
79
|
-
|
|
80
|
-
// Separate removed from changed
|
|
81
|
-
const removed: RemovedExport[] = [];
|
|
82
|
-
const changed: ChangedExport[] = [];
|
|
83
|
-
const breaking: CategorizedBreaking[] = [];
|
|
84
|
-
|
|
85
|
-
for (const cat of categorized) {
|
|
86
|
-
if (cat.reason === 'removed') {
|
|
87
|
-
const info = oldExports.get(cat.id);
|
|
88
|
-
removed.push({
|
|
89
|
-
id: cat.id,
|
|
90
|
-
name: cat.name,
|
|
91
|
-
kind: info?.kind ?? cat.kind,
|
|
92
|
-
});
|
|
93
|
-
} else {
|
|
94
|
-
// It's a change, not a removal
|
|
95
|
-
changed.push({
|
|
96
|
-
id: cat.id,
|
|
97
|
-
name: cat.name,
|
|
98
|
-
kind: cat.kind,
|
|
99
|
-
description: describeChange(cat),
|
|
100
|
-
});
|
|
101
|
-
breaking.push(cat);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Added exports
|
|
106
|
-
const added = rawDiff.nonBreaking;
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
breaking,
|
|
110
|
-
added,
|
|
111
|
-
removed,
|
|
112
|
-
changed,
|
|
113
|
-
docsOnly: rawDiff.docsOnly,
|
|
114
|
-
summary: {
|
|
115
|
-
breakingCount: breaking.length,
|
|
116
|
-
addedCount: added.length,
|
|
117
|
-
removedCount: removed.length,
|
|
118
|
-
changedCount: changed.length,
|
|
119
|
-
docsOnlyCount: rawDiff.docsOnly.length,
|
|
120
|
-
semverBump: semver.bump,
|
|
121
|
-
semverReason: semver.reason,
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Generate human-readable description for a change
|
|
128
|
-
*/
|
|
129
|
-
function describeChange(cat: CategorizedBreaking): string {
|
|
130
|
-
switch (cat.reason) {
|
|
131
|
-
case 'signature changed':
|
|
132
|
-
return `Function signature changed`;
|
|
133
|
-
case 'type definition changed':
|
|
134
|
-
return `Type definition changed`;
|
|
135
|
-
case 'constructor changed':
|
|
136
|
-
return `Class constructor signature changed`;
|
|
137
|
-
case 'methods removed':
|
|
138
|
-
return `Class methods removed`;
|
|
139
|
-
case 'methods changed':
|
|
140
|
-
return `Class methods changed`;
|
|
141
|
-
case 'changed':
|
|
142
|
-
return `${cat.kind} changed`;
|
|
143
|
-
default:
|
|
144
|
-
return cat.reason;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function createDiffCommand(): Command {
|
|
149
|
-
return new Command('diff')
|
|
150
|
-
.description('Compare two OpenPkg specs and show differences')
|
|
151
|
-
.argument('<old>', 'Path to old spec file (JSON)')
|
|
152
|
-
.argument('<new>', 'Path to new spec file (JSON)')
|
|
153
|
-
.option('--json', 'Output as JSON (default)')
|
|
154
|
-
.option('--summary', 'Only show summary')
|
|
155
|
-
.action(
|
|
156
|
-
async (oldPath: string, newPath: string, options: { json?: boolean; summary?: boolean }) => {
|
|
157
|
-
try {
|
|
158
|
-
const oldSpec = loadSpec(oldPath);
|
|
159
|
-
const newSpec = loadSpec(newPath);
|
|
160
|
-
|
|
161
|
-
const result = enrichDiff(oldSpec, newSpec);
|
|
162
|
-
|
|
163
|
-
if (options.summary) {
|
|
164
|
-
console.log(JSON.stringify(result.summary, null, 2));
|
|
165
|
-
} else {
|
|
166
|
-
console.log(JSON.stringify(result, null, 2));
|
|
167
|
-
}
|
|
168
|
-
} catch (err) {
|
|
169
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
170
|
-
console.error(JSON.stringify({ error: error.message }, null, 2));
|
|
171
|
-
process.exit(1);
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
);
|
|
175
|
-
}
|
package/src/commands/docs.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { createDocs, type DocsInstance, loadSpec } from '@openpkg-ts/sdk';
|
|
4
|
-
import type { OpenPkg } from '@openpkg-ts/spec';
|
|
5
|
-
import { Command } from 'commander';
|
|
6
|
-
|
|
7
|
-
type OutputFormat = 'md' | 'json' | 'html';
|
|
8
|
-
|
|
9
|
-
interface DocsCommandOptions {
|
|
10
|
-
output?: string;
|
|
11
|
-
format?: OutputFormat;
|
|
12
|
-
split?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function readStdin(): Promise<string> {
|
|
16
|
-
const chunks: Buffer[] = [];
|
|
17
|
-
for await (const chunk of process.stdin) {
|
|
18
|
-
chunks.push(chunk);
|
|
19
|
-
}
|
|
20
|
-
return Buffer.concat(chunks).toString('utf-8');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function getExtension(format: OutputFormat): string {
|
|
24
|
-
switch (format) {
|
|
25
|
-
case 'json':
|
|
26
|
-
return '.json';
|
|
27
|
-
case 'html':
|
|
28
|
-
return '.html';
|
|
29
|
-
default:
|
|
30
|
-
return '.md';
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function renderExport(docs: DocsInstance, exportId: string, format: OutputFormat): string {
|
|
35
|
-
const exp = docs.getExport(exportId);
|
|
36
|
-
if (!exp) throw new Error(`Export not found: ${exportId}`);
|
|
37
|
-
|
|
38
|
-
switch (format) {
|
|
39
|
-
case 'json':
|
|
40
|
-
return JSON.stringify(docs.toJSON({ exportId }), null, 2);
|
|
41
|
-
case 'html':
|
|
42
|
-
return docs.toHTML({ exportId });
|
|
43
|
-
default:
|
|
44
|
-
return docs.toMarkdown({ exportId, frontmatter: true, codeSignatures: true });
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function renderFull(docs: DocsInstance, format: OutputFormat): string {
|
|
49
|
-
switch (format) {
|
|
50
|
-
case 'json':
|
|
51
|
-
return JSON.stringify(docs.toJSON(), null, 2);
|
|
52
|
-
case 'html':
|
|
53
|
-
return docs.toHTML();
|
|
54
|
-
default:
|
|
55
|
-
return docs.toMarkdown({ frontmatter: true, codeSignatures: true });
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function createDocsCommand(): Command {
|
|
60
|
-
return new Command('docs')
|
|
61
|
-
.description('Generate documentation from OpenPkg spec')
|
|
62
|
-
.argument('<spec>', 'Path to openpkg.json spec file (use - for stdin)')
|
|
63
|
-
.option('-o, --output <path>', 'Output file or directory (default: stdout)')
|
|
64
|
-
.option('-f, --format <format>', 'Output format: md, json, html (default: md)', 'md')
|
|
65
|
-
.option('--split', 'Output one file per export (requires --output as directory)')
|
|
66
|
-
.action(async (specPath: string, options: DocsCommandOptions) => {
|
|
67
|
-
const format = (options.format || 'md') as OutputFormat;
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
let docs: DocsInstance;
|
|
71
|
-
|
|
72
|
-
// Handle stdin
|
|
73
|
-
if (specPath === '-') {
|
|
74
|
-
const input = await readStdin();
|
|
75
|
-
const spec: OpenPkg = JSON.parse(input);
|
|
76
|
-
docs = loadSpec(spec);
|
|
77
|
-
} else {
|
|
78
|
-
const specFile = path.resolve(specPath);
|
|
79
|
-
if (!fs.existsSync(specFile)) {
|
|
80
|
-
console.error(JSON.stringify({ error: `Spec file not found: ${specFile}` }));
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
docs = createDocs(specFile);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Split mode: one file per export
|
|
87
|
-
if (options.split) {
|
|
88
|
-
if (!options.output) {
|
|
89
|
-
console.error(JSON.stringify({ error: '--split requires --output <directory>' }));
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const outDir = path.resolve(options.output);
|
|
94
|
-
if (!fs.existsSync(outDir)) {
|
|
95
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const exports = docs.getAllExports();
|
|
99
|
-
for (const exp of exports) {
|
|
100
|
-
const filename = `${exp.name}${getExtension(format)}`;
|
|
101
|
-
const filePath = path.join(outDir, filename);
|
|
102
|
-
const content = renderExport(docs, exp.id, format);
|
|
103
|
-
fs.writeFileSync(filePath, content);
|
|
104
|
-
}
|
|
105
|
-
console.error(`Wrote ${exports.length} files to ${outDir}`);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Single output mode
|
|
110
|
-
const output = renderFull(docs, format);
|
|
111
|
-
|
|
112
|
-
if (options.output && options.output !== '-') {
|
|
113
|
-
const outputPath = path.resolve(options.output);
|
|
114
|
-
fs.writeFileSync(outputPath, output);
|
|
115
|
-
console.error(`Wrote ${outputPath}`);
|
|
116
|
-
} else {
|
|
117
|
-
console.log(output);
|
|
118
|
-
}
|
|
119
|
-
} catch (err) {
|
|
120
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
121
|
-
console.error(JSON.stringify({ error: error.message }));
|
|
122
|
-
process.exit(1);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}
|
package/src/commands/snapshot.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { type Diagnostic, type ExtractOptions, extractSpec } from '@openpkg-ts/sdk';
|
|
4
|
-
import { Command } from 'commander';
|
|
5
|
-
|
|
6
|
-
interface SnapshotCommandOptions {
|
|
7
|
-
output?: string;
|
|
8
|
-
maxDepth?: string;
|
|
9
|
-
skipResolve?: boolean;
|
|
10
|
-
runtime?: boolean;
|
|
11
|
-
only?: string;
|
|
12
|
-
ignore?: string;
|
|
13
|
-
verify?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function parseFilter(value: string | undefined): string[] | undefined {
|
|
17
|
-
if (!value) return undefined;
|
|
18
|
-
return value
|
|
19
|
-
.split(',')
|
|
20
|
-
.map((s) => s.trim())
|
|
21
|
-
.filter(Boolean);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function formatDiagnostics(diagnostics: Diagnostic[]): object[] {
|
|
25
|
-
return diagnostics.map((d) => ({
|
|
26
|
-
message: d.message,
|
|
27
|
-
severity: d.severity,
|
|
28
|
-
...(d.code && { code: d.code }),
|
|
29
|
-
...(d.suggestion && { suggestion: d.suggestion }),
|
|
30
|
-
...(d.location && { location: d.location }),
|
|
31
|
-
}));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function createSnapshotCommand(): Command {
|
|
35
|
-
return new Command('snapshot')
|
|
36
|
-
.description('Generate full OpenPkg spec from TypeScript entry point')
|
|
37
|
-
.argument('<entry>', 'Entry point file path')
|
|
38
|
-
.option(
|
|
39
|
-
'-o, --output <file>',
|
|
40
|
-
'Output file (default: openpkg.json, use - for stdout)',
|
|
41
|
-
'openpkg.json',
|
|
42
|
-
)
|
|
43
|
-
.option('--max-depth <n>', 'Max type depth (default: 4)', '4')
|
|
44
|
-
.option('--skip-resolve', 'Skip external type resolution')
|
|
45
|
-
.option('--runtime', 'Enable Standard Schema runtime extraction')
|
|
46
|
-
.option('--only <exports>', 'Filter exports (comma-separated, wildcards supported)')
|
|
47
|
-
.option('--ignore <exports>', 'Ignore exports (comma-separated, wildcards supported)')
|
|
48
|
-
.option('--verify', 'Exit 1 if any exports fail')
|
|
49
|
-
.action(async (entry: string, options: SnapshotCommandOptions) => {
|
|
50
|
-
const entryFile = path.resolve(entry);
|
|
51
|
-
|
|
52
|
-
const extractOptions: ExtractOptions = {
|
|
53
|
-
entryFile,
|
|
54
|
-
maxTypeDepth: parseInt(options.maxDepth ?? '4', 10),
|
|
55
|
-
resolveExternalTypes: !options.skipResolve,
|
|
56
|
-
schemaExtraction: options.runtime ? 'hybrid' : 'static',
|
|
57
|
-
only: parseFilter(options.only),
|
|
58
|
-
ignore: parseFilter(options.ignore),
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
const result = await extractSpec(extractOptions);
|
|
63
|
-
|
|
64
|
-
// Build summary for stderr
|
|
65
|
-
const summary = {
|
|
66
|
-
exports: result.spec.exports.length,
|
|
67
|
-
types: result.spec.types?.length ?? 0,
|
|
68
|
-
diagnostics: result.diagnostics.length,
|
|
69
|
-
...(result.verification && {
|
|
70
|
-
verification: {
|
|
71
|
-
discovered: result.verification.discovered,
|
|
72
|
-
extracted: result.verification.extracted,
|
|
73
|
-
skipped: result.verification.skipped,
|
|
74
|
-
failed: result.verification.failed,
|
|
75
|
-
},
|
|
76
|
-
}),
|
|
77
|
-
...(result.runtimeSchemas && {
|
|
78
|
-
runtime: {
|
|
79
|
-
extracted: result.runtimeSchemas.extracted,
|
|
80
|
-
merged: result.runtimeSchemas.merged,
|
|
81
|
-
vendors: result.runtimeSchemas.vendors,
|
|
82
|
-
},
|
|
83
|
-
}),
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
// Write summary to stderr
|
|
87
|
-
console.error(JSON.stringify(summary, null, 2));
|
|
88
|
-
|
|
89
|
-
// Check for failures if --verify
|
|
90
|
-
if (options.verify && result.verification && result.verification.failed > 0) {
|
|
91
|
-
const errorOutput = {
|
|
92
|
-
error: 'Export verification failed',
|
|
93
|
-
failed: result.verification.details.failed,
|
|
94
|
-
diagnostics: formatDiagnostics(result.diagnostics),
|
|
95
|
-
};
|
|
96
|
-
console.error(JSON.stringify(errorOutput, null, 2));
|
|
97
|
-
process.exit(1);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Output spec
|
|
101
|
-
const specJson = JSON.stringify(result.spec, null, 2);
|
|
102
|
-
|
|
103
|
-
if (options.output === '-') {
|
|
104
|
-
// Stdout mode
|
|
105
|
-
console.log(specJson);
|
|
106
|
-
} else {
|
|
107
|
-
// File mode
|
|
108
|
-
const outputPath = path.resolve(options.output ?? 'openpkg.json');
|
|
109
|
-
fs.writeFileSync(outputPath, specJson);
|
|
110
|
-
console.error(`Wrote ${outputPath}`);
|
|
111
|
-
}
|
|
112
|
-
} catch (err) {
|
|
113
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
114
|
-
const errorOutput = {
|
|
115
|
-
error: error.message,
|
|
116
|
-
...(error.stack && { stack: error.stack }),
|
|
117
|
-
};
|
|
118
|
-
console.error(JSON.stringify(errorOutput, null, 2));
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}
|
package/src/index.ts
DELETED