@openpkg-ts/cli 0.9.2 → 0.10.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/dist/index.js +74 -8
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5,9 +5,13 @@ import fs from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
import {
|
|
8
|
+
calculateNextVersion,
|
|
9
|
+
categorizeBreakingChanges,
|
|
8
10
|
createDocs,
|
|
9
11
|
diffSpecs,
|
|
10
12
|
extractSpec,
|
|
13
|
+
getAvailableVersions,
|
|
14
|
+
getValidationErrors,
|
|
11
15
|
listExports,
|
|
12
16
|
recommendSemverBump
|
|
13
17
|
} from "@openpkg-ts/sdk";
|
|
@@ -17,18 +21,20 @@ Usage:
|
|
|
17
21
|
openpkg spec <entry.ts> [-o spec.json]
|
|
18
22
|
openpkg docs <entry.ts | spec.json> [-f md|html|json] [-o out]
|
|
19
23
|
openpkg list <entry.ts> [--json]
|
|
20
|
-
openpkg
|
|
24
|
+
openpkg validate <spec.json>
|
|
25
|
+
openpkg diff <old.json> <new.json> [--json]
|
|
21
26
|
|
|
22
27
|
Commands:
|
|
23
|
-
spec
|
|
24
|
-
docs
|
|
25
|
-
list
|
|
26
|
-
|
|
28
|
+
spec Extract an OpenPkg spec from a TypeScript entry point
|
|
29
|
+
docs Generate docs from an entry point or an existing spec file
|
|
30
|
+
list List exports (name, kind, location)
|
|
31
|
+
validate Validate a spec file against the OpenPkg meta-schema
|
|
32
|
+
diff Compare two spec files and recommend a semver bump
|
|
27
33
|
|
|
28
34
|
Options:
|
|
29
35
|
-o, --output Write to file instead of stdout
|
|
30
36
|
-f, --format docs output format: md (default), html, json
|
|
31
|
-
--json list output as JSON
|
|
37
|
+
--json list/diff output as JSON
|
|
32
38
|
-h, --help Show this help
|
|
33
39
|
-v, --version Show version
|
|
34
40
|
`;
|
|
@@ -130,12 +136,67 @@ function readSpecFile(file) {
|
|
|
130
136
|
fail(`failed to read spec file ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
131
137
|
}
|
|
132
138
|
}
|
|
139
|
+
function pickVersion(spec) {
|
|
140
|
+
const declared = spec?.openpkg;
|
|
141
|
+
if (typeof declared === "string" && getAvailableVersions().includes(declared)) {
|
|
142
|
+
return declared;
|
|
143
|
+
}
|
|
144
|
+
return "latest";
|
|
145
|
+
}
|
|
146
|
+
function readValidSpecFile(file) {
|
|
147
|
+
const parsed = readSpecFile(file);
|
|
148
|
+
const errors = getValidationErrors(parsed, pickVersion(parsed));
|
|
149
|
+
if (errors.length > 0) {
|
|
150
|
+
const details = errors.map((e) => ` ${e.instancePath || "/"} ${e.message}`).join(`
|
|
151
|
+
`);
|
|
152
|
+
fail(`invalid spec ${file}:
|
|
153
|
+
${details}`);
|
|
154
|
+
}
|
|
155
|
+
return parsed;
|
|
156
|
+
}
|
|
157
|
+
function validateCommand(args) {
|
|
158
|
+
const [file] = args;
|
|
159
|
+
if (!file)
|
|
160
|
+
fail("validate requires a spec file (openpkg validate spec.json)");
|
|
161
|
+
const spec = readSpecFile(file);
|
|
162
|
+
const errors = getValidationErrors(spec, pickVersion(spec));
|
|
163
|
+
if (errors.length === 0) {
|
|
164
|
+
console.log(`${file}: valid`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
for (const e of errors) {
|
|
168
|
+
console.error(`${e.instancePath || "/"} ${e.message}`);
|
|
169
|
+
}
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
133
172
|
function diffCommand(args) {
|
|
134
|
-
const
|
|
173
|
+
const { values, positionals } = parseArgs({
|
|
174
|
+
args,
|
|
175
|
+
options: { json: { type: "boolean" } },
|
|
176
|
+
allowPositionals: true
|
|
177
|
+
});
|
|
178
|
+
const [oldFile, newFile] = positionals;
|
|
135
179
|
if (!oldFile || !newFile)
|
|
136
180
|
fail("diff requires two spec files (openpkg diff old.json new.json)");
|
|
137
|
-
const
|
|
181
|
+
const oldSpec = readValidSpecFile(oldFile);
|
|
182
|
+
const newSpec = readValidSpecFile(newFile);
|
|
183
|
+
const diff = diffSpecs(oldSpec, newSpec);
|
|
138
184
|
const recommendation = recommendSemverBump(diff);
|
|
185
|
+
const oldVersion = newSpec?.meta?.version;
|
|
186
|
+
const nextVersion = oldVersion ? calculateNextVersion(oldVersion, recommendation.bump) : undefined;
|
|
187
|
+
if (values.json) {
|
|
188
|
+
console.log(JSON.stringify({
|
|
189
|
+
breaking: diff.breaking,
|
|
190
|
+
nonBreaking: diff.nonBreaking,
|
|
191
|
+
docsOnly: diff.docsOnly,
|
|
192
|
+
categorized: categorizeBreakingChanges(diff.breaking, oldSpec, newSpec),
|
|
193
|
+
recommendation,
|
|
194
|
+
...nextVersion ? { nextVersion } : {}
|
|
195
|
+
}, null, 2));
|
|
196
|
+
if (diff.breaking.length)
|
|
197
|
+
process.exitCode = 2;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
139
200
|
const section = (title, items) => {
|
|
140
201
|
if (!items.length)
|
|
141
202
|
return;
|
|
@@ -151,6 +212,8 @@ function diffCommand(args) {
|
|
|
151
212
|
}
|
|
152
213
|
console.log(`
|
|
153
214
|
Recommended bump: ${recommendation.bump} (${recommendation.reason})`);
|
|
215
|
+
if (nextVersion)
|
|
216
|
+
console.log(`Next version: ${nextVersion}`);
|
|
154
217
|
if (diff.breaking.length)
|
|
155
218
|
process.exitCode = 2;
|
|
156
219
|
}
|
|
@@ -166,6 +229,9 @@ async function main() {
|
|
|
166
229
|
case "list":
|
|
167
230
|
await listCommand(rest);
|
|
168
231
|
break;
|
|
232
|
+
case "validate":
|
|
233
|
+
validateCommand(rest);
|
|
234
|
+
break;
|
|
169
235
|
case "diff":
|
|
170
236
|
diffCommand(rest);
|
|
171
237
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openpkg-ts/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "CLI for OpenPkg - extract TypeScript API specs and generate docs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openpkg",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"test": "bun test"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@openpkg-ts/sdk": "^0.
|
|
38
|
+
"@openpkg-ts/sdk": "^0.47.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bun": "latest",
|