@openpkg-ts/cli 0.2.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @openpkg-ts/cli
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - fix workspace:\* deps to use published versions for npm compatibility
8
+ - Updated dependencies
9
+ - @openpkg-ts/sdk@0.30.1
10
+
3
11
  ## 0.2.0
4
12
 
5
13
  ### Minor Changes
package/README.md CHANGED
@@ -120,7 +120,7 @@ openpkg diff baseline.json new.json --summary
120
120
  ## Programmatic Use
121
121
 
122
122
  ```typescript
123
- import { getExport, listExports } from '@openpkg-ts/cli';
123
+ import { getExport, listExports } from '@openpkg-ts/sdk';
124
124
 
125
125
  // Same primitives as CLI
126
126
  const { exports } = await listExports({ entryFile: './src/index.ts' });
package/bin/openpkg.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env bun
2
- import { Command } from 'commander';
2
+ import * as path from 'node:path';
3
3
  import { getExport, listExports } from '@openpkg-ts/sdk';
4
- import { createSnapshotCommand } from '../src/commands/snapshot';
4
+ import { Command } from 'commander';
5
5
  import { createDiffCommand } from '../src/commands/diff';
6
6
  import { createDocsCommand } from '../src/commands/docs';
7
- import * as path from 'node:path';
7
+ import { createSnapshotCommand } from '../src/commands/snapshot';
8
8
 
9
9
  const program = new Command();
10
10
 
@@ -39,9 +39,8 @@ program
39
39
  const result = await getExport({ entryFile, exportName: name });
40
40
 
41
41
  if (!result.export) {
42
- const errorMsg = result.errors.length > 0
43
- ? result.errors.join('; ')
44
- : `Export '${name}' not found`;
42
+ const errorMsg =
43
+ result.errors.length > 0 ? result.errors.join('; ') : `Export '${name}' not found`;
45
44
  console.error(JSON.stringify({ error: errorMsg }, null, 2));
46
45
  process.exit(1);
47
46
  }
package/package.json CHANGED
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "name": "@openpkg-ts/cli",
3
- "version": "0.2.0",
4
- "description": "CLI for OpenPkg TypeScript API extraction",
3
+ "version": "0.2.1",
4
+ "description": "CLI for OpenPkg TypeScript API extraction and documentation generation",
5
+ "homepage": "https://github.com/ryanwaits/openpkg-ts#readme",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ryanwaits/openpkg-ts.git",
9
+ "directory": "packages/cli"
10
+ },
5
11
  "type": "module",
6
12
  "bin": {
7
13
  "openpkg": "./bin/openpkg.ts"
@@ -12,7 +18,7 @@
12
18
  "test": "bun test"
13
19
  },
14
20
  "dependencies": {
15
- "@openpkg-ts/sdk": "workspace:*",
21
+ "@openpkg-ts/sdk": "^0.30.1",
16
22
  "commander": "^14.0.0"
17
23
  },
18
24
  "devDependencies": {
@@ -1,15 +1,15 @@
1
- import { Command } from 'commander';
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
2
3
  import {
3
- diffSpec,
4
+ type CategorizedBreaking,
4
5
  categorizeBreakingChanges,
5
- recommendSemverBump,
6
+ diffSpec,
6
7
  type OpenPkg,
7
- type CategorizedBreaking,
8
+ recommendSemverBump,
8
9
  type SemverBump,
9
10
  type SpecExportKind,
10
11
  } from '@openpkg-ts/spec';
11
- import * as fs from 'node:fs';
12
- import * as path from 'node:path';
12
+ import { Command } from 'commander';
13
13
 
14
14
  /**
15
15
  * A changed export with details about what changed
@@ -75,7 +75,7 @@ export function enrichDiff(oldSpec: OpenPkg, newSpec: OpenPkg): DiffResult {
75
75
  const semver = recommendSemverBump(rawDiff);
76
76
 
77
77
  const oldExports = toExportMap(oldSpec);
78
- const newExports = toExportMap(newSpec);
78
+ const _newExports = toExportMap(newSpec);
79
79
 
80
80
  // Separate removed from changed
81
81
  const removed: RemovedExport[] = [];
@@ -152,22 +152,24 @@ export function createDiffCommand(): Command {
152
152
  .argument('<new>', 'Path to new spec file (JSON)')
153
153
  .option('--json', 'Output as JSON (default)')
154
154
  .option('--summary', 'Only show summary')
155
- .action(async (oldPath: string, newPath: string, options: { json?: boolean; summary?: boolean }) => {
156
- try {
157
- const oldSpec = loadSpec(oldPath);
158
- const newSpec = loadSpec(newPath);
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);
159
160
 
160
- const result = enrichDiff(oldSpec, newSpec);
161
+ const result = enrichDiff(oldSpec, newSpec);
161
162
 
162
- if (options.summary) {
163
- console.log(JSON.stringify(result.summary, null, 2));
164
- } else {
165
- console.log(JSON.stringify(result, null, 2));
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);
166
172
  }
167
- } catch (err) {
168
- const error = err instanceof Error ? err : new Error(String(err));
169
- console.error(JSON.stringify({ error: error.message }, null, 2));
170
- process.exit(1);
171
- }
172
- });
173
+ },
174
+ );
173
175
  }
@@ -1,8 +1,8 @@
1
- import { Command } from 'commander';
2
- import { createDocs, loadSpec, type DocsInstance } from '@openpkg-ts/sdk';
3
- import type { OpenPkg } from '@openpkg-ts/spec';
4
- import * as path from 'node:path';
5
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
6
 
7
7
  type OutputFormat = 'md' | 'json' | 'html';
8
8
 
@@ -22,9 +22,12 @@ async function readStdin(): Promise<string> {
22
22
 
23
23
  function getExtension(format: OutputFormat): string {
24
24
  switch (format) {
25
- case 'json': return '.json';
26
- case 'html': return '.html';
27
- default: return '.md';
25
+ case 'json':
26
+ return '.json';
27
+ case 'html':
28
+ return '.html';
29
+ default:
30
+ return '.md';
28
31
  }
29
32
  }
30
33
 
@@ -1,7 +1,7 @@
1
- import { Command } from 'commander';
2
- import { extractSpec, type ExtractOptions, type Diagnostic } from '@openpkg-ts/sdk';
3
- import * as path from 'node:path';
4
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
5
 
6
6
  interface SnapshotCommandOptions {
7
7
  output?: string;
@@ -15,11 +15,14 @@ interface SnapshotCommandOptions {
15
15
 
16
16
  function parseFilter(value: string | undefined): string[] | undefined {
17
17
  if (!value) return undefined;
18
- return value.split(',').map(s => s.trim()).filter(Boolean);
18
+ return value
19
+ .split(',')
20
+ .map((s) => s.trim())
21
+ .filter(Boolean);
19
22
  }
20
23
 
21
24
  function formatDiagnostics(diagnostics: Diagnostic[]): object[] {
22
- return diagnostics.map(d => ({
25
+ return diagnostics.map((d) => ({
23
26
  message: d.message,
24
27
  severity: d.severity,
25
28
  ...(d.code && { code: d.code }),
@@ -32,7 +35,11 @@ export function createSnapshotCommand(): Command {
32
35
  return new Command('snapshot')
33
36
  .description('Generate full OpenPkg spec from TypeScript entry point')
34
37
  .argument('<entry>', 'Entry point file path')
35
- .option('-o, --output <file>', 'Output file (default: openpkg.json, use - for stdout)', 'openpkg.json')
38
+ .option(
39
+ '-o, --output <file>',
40
+ 'Output file (default: openpkg.json, use - for stdout)',
41
+ 'openpkg.json',
42
+ )
36
43
  .option('--max-depth <n>', 'Max type depth (default: 4)', '4')
37
44
  .option('--skip-resolve', 'Skip external type resolution')
38
45
  .option('--runtime', 'Enable Standard Schema runtime extraction')
@@ -65,14 +72,14 @@ export function createSnapshotCommand(): Command {
65
72
  extracted: result.verification.extracted,
66
73
  skipped: result.verification.skipped,
67
74
  failed: result.verification.failed,
68
- }
75
+ },
69
76
  }),
70
77
  ...(result.runtimeSchemas && {
71
78
  runtime: {
72
79
  extracted: result.runtimeSchemas.extracted,
73
80
  merged: result.runtimeSchemas.merged,
74
81
  vendors: result.runtimeSchemas.vendors,
75
- }
82
+ },
76
83
  }),
77
84
  };
78
85
 
@@ -102,7 +109,6 @@ export function createSnapshotCommand(): Command {
102
109
  fs.writeFileSync(outputPath, specJson);
103
110
  console.error(`Wrote ${outputPath}`);
104
111
  }
105
-
106
112
  } catch (err) {
107
113
  const error = err instanceof Error ? err : new Error(String(err));
108
114
  const errorOutput = {
package/test/diff.test.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from 'bun:test';
2
- import { enrichDiff, type DiffResult } from '../src/commands/diff';
3
2
  import type { OpenPkg, SpecExport } from '@openpkg-ts/spec';
3
+ import { enrichDiff } from '../src/commands/diff';
4
4
 
5
5
  // Helper to create minimal spec
6
6
  function makeSpec(exports: SpecExport[], types: OpenPkg['types'] = []): OpenPkg {
package/test/docs.test.ts CHANGED
@@ -1,19 +1,19 @@
1
- import { describe, expect, test, beforeAll, afterAll } from 'bun:test';
1
+ import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
2
5
  import {
3
6
  createDocs,
7
+ exportToMarkdown,
4
8
  loadSpec,
5
- toMarkdown,
9
+ type SimplifiedExport,
10
+ type SimplifiedSpec,
6
11
  toHTML,
7
12
  toJSON,
8
13
  toJSONString,
9
- exportToMarkdown,
10
- type SimplifiedSpec,
11
- type SimplifiedExport,
14
+ toMarkdown,
12
15
  } from '@openpkg-ts/sdk';
13
16
  import type { OpenPkg } from '@openpkg-ts/spec';
14
- import * as fs from 'node:fs';
15
- import * as path from 'node:path';
16
- import * as os from 'node:os';
17
17
 
18
18
  // Test fixture spec
19
19
  const testSpec: OpenPkg = {
package/test/get.test.ts CHANGED
@@ -13,7 +13,11 @@ describe('getExport', () => {
13
13
  interface Client { fetch(): void; }
14
14
  `;
15
15
 
16
- const result = await getExport({ entryFile: 'test.ts', exportName: 'createClient', content: code });
16
+ const result = await getExport({
17
+ entryFile: 'test.ts',
18
+ exportName: 'createClient',
19
+ content: code,
20
+ });
17
21
 
18
22
  expect(result.errors).toHaveLength(0);
19
23
  expect(result.export).not.toBeNull();
@@ -127,7 +131,11 @@ describe('getExport', () => {
127
131
  export type Partial<T> = { [K in keyof T]?: T[K] };
128
132
  `;
129
133
 
130
- const result = await getExport({ entryFile: 'test.ts', exportName: 'Partial', content: code });
134
+ const result = await getExport({
135
+ entryFile: 'test.ts',
136
+ exportName: 'Partial',
137
+ content: code,
138
+ });
131
139
 
132
140
  expect(result.errors).toHaveLength(0);
133
141
  expect(result.export!.kind).toBe('type');
@@ -153,7 +161,11 @@ describe('getExport', () => {
153
161
  }
154
162
  `;
155
163
 
156
- const result = await getExport({ entryFile: 'test.ts', exportName: 'ApiClient', content: code });
164
+ const result = await getExport({
165
+ entryFile: 'test.ts',
166
+ exportName: 'ApiClient',
167
+ content: code,
168
+ });
157
169
 
158
170
  expect(result.errors).toHaveLength(0);
159
171
  expect(result.export).not.toBeNull();
@@ -200,7 +212,11 @@ describe('getExport', () => {
200
212
  }
201
213
  `;
202
214
 
203
- const result = await getExport({ entryFile: 'test.ts', exportName: 'LogLevel', content: code });
215
+ const result = await getExport({
216
+ entryFile: 'test.ts',
217
+ exportName: 'LogLevel',
218
+ content: code,
219
+ });
204
220
 
205
221
  expect(result.errors).toHaveLength(0);
206
222
  expect(result.export).not.toBeNull();
@@ -234,7 +250,11 @@ describe('getExport', () => {
234
250
  export const DEFAULT_CONFIG = { timeout: 5000, retries: 3 };
235
251
  `;
236
252
 
237
- const result = await getExport({ entryFile: 'test.ts', exportName: 'DEFAULT_CONFIG', content: code });
253
+ const result = await getExport({
254
+ entryFile: 'test.ts',
255
+ exportName: 'DEFAULT_CONFIG',
256
+ content: code,
257
+ });
238
258
 
239
259
  expect(result.errors).toHaveLength(0);
240
260
  expect(result.export).not.toBeNull();
@@ -247,7 +267,11 @@ describe('getExport', () => {
247
267
  export const VERSION: string = '1.0.0';
248
268
  `;
249
269
 
250
- const result = await getExport({ entryFile: 'test.ts', exportName: 'VERSION', content: code });
270
+ const result = await getExport({
271
+ entryFile: 'test.ts',
272
+ exportName: 'VERSION',
273
+ content: code,
274
+ });
251
275
 
252
276
  expect(result.errors).toHaveLength(0);
253
277
  expect(result.export!.kind).toBe('variable');
@@ -283,7 +307,11 @@ describe('getExport', () => {
283
307
  export function myFunc(): void {}
284
308
  `;
285
309
 
286
- const result = await getExport({ entryFile: 'test.ts', exportName: 'NonExistent', content: code });
310
+ const result = await getExport({
311
+ entryFile: 'test.ts',
312
+ exportName: 'NonExistent',
313
+ content: code,
314
+ });
287
315
 
288
316
  expect(result.export).toBeNull();
289
317
  expect(result.errors.length).toBeGreaterThan(0);
@@ -293,7 +321,11 @@ describe('getExport', () => {
293
321
  test('returns error for empty file', async () => {
294
322
  const code = `// empty file`;
295
323
 
296
- const result = await getExport({ entryFile: 'test.ts', exportName: 'anything', content: code });
324
+ const result = await getExport({
325
+ entryFile: 'test.ts',
326
+ exportName: 'anything',
327
+ content: code,
328
+ });
297
329
 
298
330
  expect(result.export).toBeNull();
299
331
  expect(result.errors.length).toBeGreaterThan(0);
@@ -311,7 +343,11 @@ describe('getExport', () => {
311
343
  }
312
344
  `;
313
345
 
314
- const result = await getExport({ entryFile: 'test.ts', exportName: 'Response', content: code });
346
+ const result = await getExport({
347
+ entryFile: 'test.ts',
348
+ exportName: 'Response',
349
+ content: code,
350
+ });
315
351
 
316
352
  expect(result.errors).toHaveLength(0);
317
353
  expect(result.export).not.toBeNull();
package/test/spec.test.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { describe, expect, test, beforeAll, afterAll } from 'bun:test';
2
- import { extractSpec, type ExtractOptions, type ExtractResult } from '@openpkg-ts/sdk';
1
+ import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
3
2
  import * as fs from 'node:fs';
4
- import * as path from 'node:path';
5
3
  import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import { extractSpec } from '@openpkg-ts/sdk';
6
6
 
7
7
  // Test fixture code samples
8
8
  const FIXTURE_CODE = {
@@ -92,7 +92,7 @@ describe('spec command (extractSpec)', () => {
92
92
  content: FIXTURE_CODE.basic,
93
93
  });
94
94
 
95
- const kinds = new Set(result.spec.exports.map(e => e.kind));
95
+ const kinds = new Set(result.spec.exports.map((e) => e.kind));
96
96
  expect(kinds.has('function')).toBe(true);
97
97
  expect(kinds.has('interface')).toBe(true);
98
98
  expect(kinds.has('variable')).toBe(true);
@@ -104,7 +104,7 @@ describe('spec command (extractSpec)', () => {
104
104
  content: FIXTURE_CODE.withClasses,
105
105
  });
106
106
 
107
- const classExport = result.spec.exports.find(e => e.kind === 'class');
107
+ const classExport = result.spec.exports.find((e) => e.kind === 'class');
108
108
  expect(classExport).toBeDefined();
109
109
  expect(classExport!.name).toBe('Service');
110
110
  });
@@ -115,7 +115,7 @@ describe('spec command (extractSpec)', () => {
115
115
  content: FIXTURE_CODE.withEnums,
116
116
  });
117
117
 
118
- const enums = result.spec.exports.filter(e => e.kind === 'enum');
118
+ const enums = result.spec.exports.filter((e) => e.kind === 'enum');
119
119
  expect(enums.length).toBe(2);
120
120
  });
121
121
 
@@ -165,8 +165,8 @@ describe('spec command (extractSpec)', () => {
165
165
  });
166
166
 
167
167
  // Export names and kinds should be consistent
168
- const names1 = result1.spec.exports.map(e => e.name).sort();
169
- const names2 = result2.spec.exports.map(e => e.name).sort();
168
+ const names1 = result1.spec.exports.map((e) => e.name).sort();
169
+ const names2 = result2.spec.exports.map((e) => e.name).sort();
170
170
  expect(names1).toEqual(names2);
171
171
  });
172
172
  });
@@ -191,7 +191,7 @@ describe('spec command (extractSpec)', () => {
191
191
  });
192
192
 
193
193
  expect(result.spec.exports.length).toBe(2);
194
- expect(result.spec.exports.every(e => e.name.startsWith('create'))).toBe(true);
194
+ expect(result.spec.exports.every((e) => e.name.startsWith('create'))).toBe(true);
195
195
  });
196
196
 
197
197
  test('filters with wildcard suffix', async () => {
@@ -201,8 +201,8 @@ describe('spec command (extractSpec)', () => {
201
201
  only: ['*User'],
202
202
  });
203
203
 
204
- const names = result.spec.exports.map(e => e.name);
205
- expect(names.every(n => n.endsWith('User'))).toBe(true);
204
+ const names = result.spec.exports.map((e) => e.name);
205
+ expect(names.every((n) => n.endsWith('User'))).toBe(true);
206
206
  });
207
207
 
208
208
  test('filters multiple patterns', async () => {
@@ -213,7 +213,7 @@ describe('spec command (extractSpec)', () => {
213
213
  });
214
214
 
215
215
  expect(result.spec.exports.length).toBe(2);
216
- const names = result.spec.exports.map(e => e.name);
216
+ const names = result.spec.exports.map((e) => e.name);
217
217
  expect(names).toContain('createUser');
218
218
  expect(names).toContain('MAX_USERS');
219
219
  });
@@ -237,7 +237,7 @@ describe('spec command (extractSpec)', () => {
237
237
  ignore: ['deleteUser'],
238
238
  });
239
239
 
240
- const names = result.spec.exports.map(e => e.name);
240
+ const names = result.spec.exports.map((e) => e.name);
241
241
  expect(names).not.toContain('deleteUser');
242
242
  });
243
243
 
@@ -248,8 +248,8 @@ describe('spec command (extractSpec)', () => {
248
248
  ignore: ['*User'],
249
249
  });
250
250
 
251
- const names = result.spec.exports.map(e => e.name);
252
- expect(names.some(n => n.endsWith('User'))).toBe(false);
251
+ const names = result.spec.exports.map((e) => e.name);
252
+ expect(names.some((n) => n.endsWith('User'))).toBe(false);
253
253
  });
254
254
 
255
255
  test('ignores multiple patterns', async () => {
@@ -259,7 +259,7 @@ describe('spec command (extractSpec)', () => {
259
259
  ignore: ['deleteUser', 'MAX_USERS'],
260
260
  });
261
261
 
262
- const names = result.spec.exports.map(e => e.name);
262
+ const names = result.spec.exports.map((e) => e.name);
263
263
  expect(names).not.toContain('deleteUser');
264
264
  expect(names).not.toContain('MAX_USERS');
265
265
  });
@@ -389,7 +389,7 @@ describe('spec command (extractSpec)', () => {
389
389
  content: FIXTURE_CODE.basic,
390
390
  });
391
391
 
392
- const fn = result.spec.exports.find(e => e.kind === 'function');
392
+ const fn = result.spec.exports.find((e) => e.kind === 'function');
393
393
  expect(fn).toBeDefined();
394
394
  expect(fn!.signatures).toBeDefined();
395
395
  });
@@ -400,7 +400,7 @@ describe('spec command (extractSpec)', () => {
400
400
  content: FIXTURE_CODE.basic,
401
401
  });
402
402
 
403
- const iface = result.spec.exports.find(e => e.kind === 'interface');
403
+ const iface = result.spec.exports.find((e) => e.kind === 'interface');
404
404
  expect(iface).toBeDefined();
405
405
  expect(iface!.members).toBeDefined();
406
406
  });