x-openapi-flow 1.3.2 → 1.3.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/README.md CHANGED
@@ -30,7 +30,7 @@ npm install @tiago-marques/x-openapi-flow
30
30
  If authentication is required, include this in your `.npmrc`:
31
31
 
32
32
  ```ini
33
- //npm.pkg.github.com/:_authToken=${GH_PACKAGES_TOKEN}
33
+ //npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_TOKEN}
34
34
  ```
35
35
 
36
36
  Use a GitHub PAT with `read:packages` (install) and `write:packages` (publish).
@@ -53,6 +53,10 @@ npx x-openapi-flow graph openapi.yaml
53
53
  ## CLI Commands
54
54
 
55
55
  ```bash
56
+ npx x-openapi-flow help [command]
57
+ npx x-openapi-flow --help
58
+ npx x-openapi-flow version
59
+ npx x-openapi-flow --version
56
60
  npx x-openapi-flow validate <openapi-file> [--format pretty|json] [--profile core|relaxed|strict] [--strict-quality] [--config path]
57
61
  npx x-openapi-flow init [--flows path] [--force] [--dry-run]
58
62
  npx x-openapi-flow apply [openapi-file] [--flows path] [--out path]
@@ -66,8 +70,15 @@ npx x-openapi-flow generate-insomnia [openapi-file] [--output path]
66
70
  npx x-openapi-flow generate-redoc [openapi-file] [--output path]
67
71
  npx x-openapi-flow graph <openapi-file> [--format mermaid|json]
68
72
  npx x-openapi-flow doctor [--config path]
73
+ npx x-openapi-flow completion [bash|zsh]
69
74
  ```
70
75
 
76
+ Helpful additions:
77
+
78
+ - Command-specific help: `x-openapi-flow <command> --help` (example: `x-openapi-flow validate --help`)
79
+ - Verbose troubleshooting: `x-openapi-flow <command> --verbose`
80
+ - Shell completion output: `x-openapi-flow completion bash` or `x-openapi-flow completion zsh`
81
+
71
82
  ## Output Adapters
72
83
 
73
84
  `x-openapi-flow` now supports modular output adapters that reuse the same internal flow graph:
@@ -20,9 +20,361 @@ const {
20
20
  generateInsomniaWorkspace,
21
21
  generateRedocPackage,
22
22
  } = require("../adapters/flow-output-adapters");
23
+ const pkg = require("../package.json");
23
24
 
24
25
  const DEFAULT_CONFIG_NAME = "x-openapi-flow.config.json";
25
26
  const DEFAULT_FLOWS_FILE = "x-openapi-flow.flows.yaml";
27
+ const KNOWN_COMMANDS = [
28
+ "validate",
29
+ "init",
30
+ "apply",
31
+ "diff",
32
+ "lint",
33
+ "analyze",
34
+ "generate-sdk",
35
+ "export-doc-flows",
36
+ "generate-postman",
37
+ "generate-insomnia",
38
+ "generate-redoc",
39
+ "graph",
40
+ "doctor",
41
+ "completion",
42
+ ];
43
+
44
+ const COMMAND_SNIPPETS = {
45
+ validate: {
46
+ usage: "x-openapi-flow validate <openapi-file> [--format pretty|json] [--profile core|relaxed|strict] [--strict-quality] [--config path]",
47
+ examples: [
48
+ "x-openapi-flow validate examples/order-api.yaml",
49
+ "x-openapi-flow validate examples/order-api.yaml --profile relaxed",
50
+ "x-openapi-flow validate examples/order-api.yaml --strict-quality",
51
+ ],
52
+ },
53
+ init: {
54
+ usage: "x-openapi-flow init [openapi-file] [--flows path] [--force] [--dry-run]",
55
+ examples: [
56
+ "x-openapi-flow init",
57
+ "x-openapi-flow init openapi.yaml --flows openapi.x.yaml",
58
+ "x-openapi-flow init openapi.yaml --force",
59
+ "x-openapi-flow init openapi.yaml --dry-run",
60
+ ],
61
+ },
62
+ apply: {
63
+ usage: "x-openapi-flow apply [openapi-file] [--flows path] [--out path] [--in-place]",
64
+ examples: [
65
+ "x-openapi-flow apply openapi.yaml",
66
+ "x-openapi-flow apply openapi.yaml --in-place",
67
+ "x-openapi-flow apply openapi.yaml --out openapi.flow.yaml",
68
+ ],
69
+ },
70
+ diff: {
71
+ usage: "x-openapi-flow diff [openapi-file] [--flows path] [--format pretty|json]",
72
+ examples: [
73
+ "x-openapi-flow diff openapi.yaml",
74
+ "x-openapi-flow diff openapi.yaml --format json",
75
+ ],
76
+ },
77
+ lint: {
78
+ usage: "x-openapi-flow lint [openapi-file] [--format pretty|json] [--config path]",
79
+ examples: [
80
+ "x-openapi-flow lint openapi.yaml",
81
+ "x-openapi-flow lint openapi.yaml --format json",
82
+ ],
83
+ },
84
+ analyze: {
85
+ usage: "x-openapi-flow analyze [openapi-file] [--format pretty|json] [--out path] [--merge] [--flows path]",
86
+ examples: [
87
+ "x-openapi-flow analyze openapi.yaml",
88
+ "x-openapi-flow analyze openapi.yaml --out openapi.x.yaml",
89
+ "x-openapi-flow analyze openapi.yaml --merge --flows openapi.x.yaml",
90
+ ],
91
+ },
92
+ "generate-sdk": {
93
+ usage: "x-openapi-flow generate-sdk [openapi-file] --lang typescript [--output path]",
94
+ examples: [
95
+ "x-openapi-flow generate-sdk openapi.yaml --lang typescript --output ./sdk",
96
+ ],
97
+ },
98
+ "export-doc-flows": {
99
+ usage: "x-openapi-flow export-doc-flows [openapi-file] [--output path] [--format markdown|json]",
100
+ examples: [
101
+ "x-openapi-flow export-doc-flows openapi.yaml --output ./docs/api-flows.md",
102
+ ],
103
+ },
104
+ "generate-postman": {
105
+ usage: "x-openapi-flow generate-postman [openapi-file] [--output path] [--with-scripts]",
106
+ examples: [
107
+ "x-openapi-flow generate-postman openapi.yaml --output ./x-openapi-flow.postman_collection.json --with-scripts",
108
+ ],
109
+ },
110
+ "generate-insomnia": {
111
+ usage: "x-openapi-flow generate-insomnia [openapi-file] [--output path]",
112
+ examples: [
113
+ "x-openapi-flow generate-insomnia openapi.yaml --output ./x-openapi-flow.insomnia.json",
114
+ ],
115
+ },
116
+ "generate-redoc": {
117
+ usage: "x-openapi-flow generate-redoc [openapi-file] [--output path]",
118
+ examples: [
119
+ "x-openapi-flow generate-redoc openapi.yaml --output ./redoc-flow",
120
+ ],
121
+ },
122
+ graph: {
123
+ usage: "x-openapi-flow graph <openapi-file> [--format mermaid|json]",
124
+ examples: [
125
+ "x-openapi-flow graph examples/order-api.yaml",
126
+ ],
127
+ },
128
+ doctor: {
129
+ usage: "x-openapi-flow doctor [--config path]",
130
+ examples: [
131
+ "x-openapi-flow doctor",
132
+ ],
133
+ },
134
+ completion: {
135
+ usage: "x-openapi-flow completion [bash|zsh]",
136
+ examples: [
137
+ "x-openapi-flow completion bash > ~/.x-openapi-flow-completion.bash",
138
+ "x-openapi-flow completion zsh > ~/.x-openapi-flow-completion.zsh",
139
+ ],
140
+ },
141
+ };
142
+
143
+ function stripGlobalFlags(args) {
144
+ const cleaned = [];
145
+ let verbose = false;
146
+
147
+ for (const token of args) {
148
+ if (token === "--verbose") {
149
+ verbose = true;
150
+ continue;
151
+ }
152
+ cleaned.push(token);
153
+ }
154
+
155
+ return { args: cleaned, verbose };
156
+ }
157
+
158
+ function printVerbose(parsed) {
159
+ if (!parsed || !parsed.verbose) {
160
+ return;
161
+ }
162
+
163
+ const printable = { ...parsed };
164
+ console.error("[verbose] Parsed CLI arguments:");
165
+ console.error(JSON.stringify(printable, null, 2));
166
+ }
167
+
168
+ function buildCompletionScript(shell) {
169
+ const commands = [...KNOWN_COMMANDS, "help", "version"].join(" ");
170
+
171
+ if (shell === "zsh") {
172
+ return `#compdef x-openapi-flow
173
+ _x_openapi_flow() {
174
+ local -a commands
175
+ commands=(${commands})
176
+ local -a global_opts
177
+ global_opts=(--help --version --verbose)
178
+
179
+ if (( CURRENT == 2 )); then
180
+ _describe 'command' commands
181
+ return
182
+ fi
183
+
184
+ case "$words[2]" in
185
+ validate)
186
+ _values 'options' --format --profile --strict-quality --config --help
187
+ ;;
188
+ init)
189
+ _values 'options' --flows --force --dry-run --help
190
+ ;;
191
+ apply)
192
+ _values 'options' --flows --out --in-place --help
193
+ ;;
194
+ diff)
195
+ _values 'options' --flows --format --help
196
+ ;;
197
+ lint)
198
+ _values 'options' --format --config --help
199
+ ;;
200
+ analyze)
201
+ _values 'options' --format --out --merge --flows --help
202
+ ;;
203
+ generate-sdk)
204
+ _values 'options' --lang --output --help
205
+ ;;
206
+ export-doc-flows)
207
+ _values 'options' --output --format --help
208
+ ;;
209
+ generate-postman)
210
+ _values 'options' --output --with-scripts --help
211
+ ;;
212
+ generate-insomnia)
213
+ _values 'options' --output --help
214
+ ;;
215
+ generate-redoc)
216
+ _values 'options' --output --help
217
+ ;;
218
+ graph)
219
+ _values 'options' --format --help
220
+ ;;
221
+ doctor)
222
+ _values 'options' --config --help
223
+ ;;
224
+ completion)
225
+ _values 'shell' bash zsh
226
+ ;;
227
+ *)
228
+ _values 'global options' $global_opts
229
+ ;;
230
+ esac
231
+ }
232
+ compdef _x_openapi_flow x-openapi-flow
233
+ `;
234
+ }
235
+
236
+ return `_x_openapi_flow()
237
+ {
238
+ local cur prev opts
239
+ COMPREPLY=()
240
+ cur="\${COMP_WORDS[COMP_CWORD]}"
241
+ prev="\${COMP_WORDS[COMP_CWORD-1]}"
242
+ opts="${commands}"
243
+
244
+ if [[ \${COMP_CWORD} -eq 1 ]]; then
245
+ COMPREPLY=( $(compgen -W "${commands} --help --version --verbose" -- "\$cur") )
246
+ return 0
247
+ fi
248
+
249
+ case "\${COMP_WORDS[1]}" in
250
+ validate)
251
+ COMPREPLY=( $(compgen -W "--format --profile --strict-quality --config --help --verbose" -- "\$cur") )
252
+ ;;
253
+ init)
254
+ COMPREPLY=( $(compgen -W "--flows --force --dry-run --help --verbose" -- "\$cur") )
255
+ ;;
256
+ apply)
257
+ COMPREPLY=( $(compgen -W "--flows --out --in-place --help --verbose" -- "\$cur") )
258
+ ;;
259
+ diff)
260
+ COMPREPLY=( $(compgen -W "--flows --format --help --verbose" -- "\$cur") )
261
+ ;;
262
+ lint)
263
+ COMPREPLY=( $(compgen -W "--format --config --help --verbose" -- "\$cur") )
264
+ ;;
265
+ analyze)
266
+ COMPREPLY=( $(compgen -W "--format --out --merge --flows --help --verbose" -- "\$cur") )
267
+ ;;
268
+ generate-sdk)
269
+ COMPREPLY=( $(compgen -W "--lang --output --help --verbose" -- "\$cur") )
270
+ ;;
271
+ export-doc-flows)
272
+ COMPREPLY=( $(compgen -W "--output --format --help --verbose" -- "\$cur") )
273
+ ;;
274
+ generate-postman)
275
+ COMPREPLY=( $(compgen -W "--output --with-scripts --help --verbose" -- "\$cur") )
276
+ ;;
277
+ generate-insomnia)
278
+ COMPREPLY=( $(compgen -W "--output --help --verbose" -- "\$cur") )
279
+ ;;
280
+ generate-redoc)
281
+ COMPREPLY=( $(compgen -W "--output --help --verbose" -- "\$cur") )
282
+ ;;
283
+ graph)
284
+ COMPREPLY=( $(compgen -W "--format --help --verbose" -- "\$cur") )
285
+ ;;
286
+ doctor)
287
+ COMPREPLY=( $(compgen -W "--config --help --verbose" -- "\$cur") )
288
+ ;;
289
+ completion)
290
+ COMPREPLY=( $(compgen -W "bash zsh --help --verbose" -- "\$cur") )
291
+ ;;
292
+ *)
293
+ COMPREPLY=( $(compgen -W "--help --version --verbose" -- "\$cur") )
294
+ ;;
295
+ esac
296
+ }
297
+ complete -F _x_openapi_flow x-openapi-flow
298
+ `;
299
+ }
300
+
301
+ function parseCompletionArgs(args) {
302
+ const positional = args.filter((token) => !token.startsWith("--"));
303
+ if (positional.length > 1) {
304
+ return { error: `Unexpected argument: ${positional[1]}` };
305
+ }
306
+
307
+ const shell = positional[0] || "bash";
308
+ if (![
309
+ "bash",
310
+ "zsh",
311
+ ].includes(shell)) {
312
+ return { error: `Invalid shell '${shell}'. Use 'bash' or 'zsh'.` };
313
+ }
314
+
315
+ return { shell };
316
+ }
317
+
318
+ function suggestCommand(input) {
319
+ if (!input) return null;
320
+ const normalized = input.toLowerCase();
321
+ const prefix = KNOWN_COMMANDS.find((cmd) => cmd.startsWith(normalized));
322
+ if (prefix) {
323
+ return prefix;
324
+ }
325
+
326
+ const includes = KNOWN_COMMANDS.find((cmd) => cmd.includes(normalized));
327
+ if (includes) {
328
+ return includes;
329
+ }
330
+
331
+ function levenshtein(a, b) {
332
+ const rows = a.length + 1;
333
+ const cols = b.length + 1;
334
+ const matrix = Array.from({ length: rows }, () => Array(cols).fill(0));
335
+
336
+ for (let i = 0; i < rows; i += 1) {
337
+ matrix[i][0] = i;
338
+ }
339
+ for (let j = 0; j < cols; j += 1) {
340
+ matrix[0][j] = j;
341
+ }
342
+
343
+ for (let i = 1; i < rows; i += 1) {
344
+ for (let j = 1; j < cols; j += 1) {
345
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
346
+ matrix[i][j] = Math.min(
347
+ matrix[i - 1][j] + 1,
348
+ matrix[i][j - 1] + 1,
349
+ matrix[i - 1][j - 1] + cost
350
+ );
351
+ }
352
+ }
353
+
354
+ return matrix[a.length][b.length];
355
+ }
356
+
357
+ let best = null;
358
+ let bestScore = Number.POSITIVE_INFINITY;
359
+ for (const candidate of KNOWN_COMMANDS) {
360
+ const score = levenshtein(normalized, candidate);
361
+ if (score < bestScore) {
362
+ bestScore = score;
363
+ best = candidate;
364
+ }
365
+ }
366
+
367
+ return bestScore <= 3 ? best : null;
368
+ }
369
+
370
+ function buildUnknownCommandError(command) {
371
+ const suggestion = suggestCommand(command);
372
+ if (!suggestion) {
373
+ return `Unknown command: ${command}`;
374
+ }
375
+
376
+ return `Unknown command: ${command}. Did you mean '${suggestion}'?`;
377
+ }
26
378
 
27
379
  function resolveConfigPath(configPathArg) {
28
380
  return configPathArg
@@ -49,10 +401,23 @@ function loadConfig(configPathArg) {
49
401
  }
50
402
  }
51
403
 
52
- function printHelp() {
404
+ function printHelp(command) {
405
+ if (command && COMMAND_SNIPPETS[command]) {
406
+ const snippet = COMMAND_SNIPPETS[command];
407
+ const examples = snippet.examples.map((item) => ` ${item}`).join("\n");
408
+ console.log(`x-openapi-flow CLI\n\nCommand: ${command}\n\nUsage:\n ${snippet.usage}\n\nExamples:\n${examples}\n`);
409
+ return;
410
+ }
411
+
53
412
  console.log(`x-openapi-flow CLI
54
413
 
414
+ Global options:
415
+ --help, -h Show help
416
+ --version, -v Show CLI version
417
+ --verbose Print parsed arguments for troubleshooting
418
+
55
419
  Usage:
420
+ x-openapi-flow <command> [options]
56
421
  x-openapi-flow validate <openapi-file> [--format pretty|json] [--profile core|relaxed|strict] [--strict-quality] [--config path]
57
422
  x-openapi-flow init [openapi-file] [--flows path] [--force] [--dry-run]
58
423
  x-openapi-flow apply [openapi-file] [--flows path] [--out path] [--in-place]
@@ -66,7 +431,11 @@ Usage:
66
431
  x-openapi-flow generate-redoc [openapi-file] [--output path]
67
432
  x-openapi-flow graph <openapi-file> [--format mermaid|json]
68
433
  x-openapi-flow doctor [--config path]
434
+ x-openapi-flow completion [bash|zsh]
435
+ x-openapi-flow help [command]
436
+ x-openapi-flow version
69
437
  x-openapi-flow --help
438
+ x-openapi-flow --version
70
439
 
71
440
  Examples:
72
441
  x-openapi-flow validate examples/order-api.yaml
@@ -94,6 +463,25 @@ Examples:
94
463
  x-openapi-flow generate-redoc openapi.yaml --output ./redoc-flow
95
464
  x-openapi-flow graph examples/order-api.yaml
96
465
  x-openapi-flow doctor
466
+
467
+ Quick Start:
468
+ # 1) Initialize sidecar from your OpenAPI file
469
+ x-openapi-flow init
470
+
471
+ # 2) Apply sidecar into flow output
472
+ x-openapi-flow apply
473
+
474
+ # 3) Validate with strict profile
475
+ x-openapi-flow validate --profile strict
476
+
477
+ Autocomplete:
478
+ # Bash
479
+ x-openapi-flow completion bash > ~/.x-openapi-flow-completion.bash
480
+ echo 'source ~/.x-openapi-flow-completion.bash' >> ~/.bashrc
481
+
482
+ # Zsh
483
+ x-openapi-flow completion zsh > ~/.x-openapi-flow-completion.zsh
484
+ echo 'source ~/.x-openapi-flow-completion.zsh' >> ~/.zshrc
97
485
  `);
98
486
  }
99
487
 
@@ -828,84 +1216,113 @@ function parseGenerateRedocArgs(args) {
828
1216
  }
829
1217
 
830
1218
  function parseArgs(argv) {
831
- const args = argv.slice(2);
1219
+ const stripped = stripGlobalFlags(argv.slice(2));
1220
+ const args = stripped.args;
832
1221
  const command = args[0];
1222
+ const withVerbose = (payload) => ({ ...payload, verbose: stripped.verbose });
833
1223
 
834
1224
  if (!command || command === "--help" || command === "-h") {
835
- return { help: true };
1225
+ return withVerbose({ help: true });
1226
+ }
1227
+
1228
+ if (command === "--version" || command === "-v" || command === "version") {
1229
+ return withVerbose({ version: true });
1230
+ }
1231
+
1232
+ if (command === "help") {
1233
+ const helpTarget = args[1];
1234
+ if (!helpTarget) {
1235
+ return withVerbose({ help: true });
1236
+ }
1237
+
1238
+ if (!KNOWN_COMMANDS.includes(helpTarget)) {
1239
+ return withVerbose({ error: buildUnknownCommandError(helpTarget) });
1240
+ }
1241
+
1242
+ return withVerbose({ help: true, command: helpTarget });
836
1243
  }
837
1244
 
838
1245
  const commandArgs = args.slice(1);
839
1246
  if (commandArgs.includes("--help") || commandArgs.includes("-h")) {
840
- return { help: true, command };
1247
+ return withVerbose({ help: true, command });
841
1248
  }
842
1249
 
843
1250
  if (command === "validate") {
844
1251
  const parsed = parseValidateArgs(commandArgs);
845
- return parsed.error ? parsed : { command, ...parsed };
1252
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
846
1253
  }
847
1254
 
848
1255
  if (command === "init") {
849
1256
  const parsed = parseInitArgs(commandArgs);
850
- return parsed.error ? parsed : { command, ...parsed };
1257
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
851
1258
  }
852
1259
 
853
1260
  if (command === "graph") {
854
1261
  const parsed = parseGraphArgs(commandArgs);
855
- return parsed.error ? parsed : { command, ...parsed };
1262
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
856
1263
  }
857
1264
 
858
1265
  if (command === "analyze") {
859
1266
  const parsed = parseAnalyzeArgs(commandArgs);
860
- return parsed.error ? parsed : { command, ...parsed };
1267
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
861
1268
  }
862
1269
 
863
1270
  if (command === "apply") {
864
1271
  const parsed = parseApplyArgs(commandArgs);
865
- return parsed.error ? parsed : { command, ...parsed };
1272
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
866
1273
  }
867
1274
 
868
1275
  if (command === "diff") {
869
1276
  const parsed = parseDiffArgs(commandArgs);
870
- return parsed.error ? parsed : { command, ...parsed };
1277
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
871
1278
  }
872
1279
 
873
1280
  if (command === "lint") {
874
1281
  const parsed = parseLintArgs(commandArgs);
875
- return parsed.error ? parsed : { command, ...parsed };
1282
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
876
1283
  }
877
1284
 
878
1285
  if (command === "doctor") {
879
1286
  const parsed = parseDoctorArgs(commandArgs);
880
- return parsed.error ? parsed : { command, ...parsed };
1287
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
881
1288
  }
882
1289
 
883
1290
  if (command === "generate-sdk") {
884
1291
  const parsed = parseGenerateSdkArgs(commandArgs);
885
- return parsed.error ? parsed : { command, ...parsed };
1292
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
886
1293
  }
887
1294
 
888
1295
  if (command === "export-doc-flows") {
889
1296
  const parsed = parseExportDocFlowsArgs(commandArgs);
890
- return parsed.error ? parsed : { command, ...parsed };
1297
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
891
1298
  }
892
1299
 
893
1300
  if (command === "generate-postman") {
894
1301
  const parsed = parseGeneratePostmanArgs(commandArgs);
895
- return parsed.error ? parsed : { command, ...parsed };
1302
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
896
1303
  }
897
1304
 
898
1305
  if (command === "generate-insomnia") {
899
1306
  const parsed = parseGenerateInsomniaArgs(commandArgs);
900
- return parsed.error ? parsed : { command, ...parsed };
1307
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
901
1308
  }
902
1309
 
903
1310
  if (command === "generate-redoc") {
904
1311
  const parsed = parseGenerateRedocArgs(commandArgs);
905
- return parsed.error ? parsed : { command, ...parsed };
1312
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
906
1313
  }
907
1314
 
908
- return { error: `Unknown command: ${command}` };
1315
+ if (command === "completion") {
1316
+ const parsed = parseCompletionArgs(commandArgs);
1317
+ return withVerbose(parsed.error ? parsed : { command, ...parsed });
1318
+ }
1319
+
1320
+ return withVerbose({ error: buildUnknownCommandError(command) });
1321
+ }
1322
+
1323
+ function runCompletion(parsed) {
1324
+ console.log(buildCompletionScript(parsed.shell));
1325
+ return 0;
909
1326
  }
910
1327
 
911
1328
  function findOpenApiFile(startDirectory) {
@@ -2251,9 +2668,19 @@ function runGenerateRedoc(parsed) {
2251
2668
 
2252
2669
  function main() {
2253
2670
  const parsed = parseArgs(process.argv);
2671
+ printVerbose(parsed);
2672
+
2673
+ if (parsed.version) {
2674
+ console.log(pkg.version);
2675
+ process.exit(0);
2676
+ }
2254
2677
 
2255
2678
  if (parsed.help) {
2256
- printHelp();
2679
+ if (parsed.command && !KNOWN_COMMANDS.includes(parsed.command)) {
2680
+ console.error(`ERROR: ${buildUnknownCommandError(parsed.command)}`);
2681
+ process.exit(1);
2682
+ }
2683
+ printHelp(parsed.command);
2257
2684
  process.exit(0);
2258
2685
  }
2259
2686
 
@@ -2300,6 +2727,10 @@ function main() {
2300
2727
  process.exit(runGenerateRedoc(parsed));
2301
2728
  }
2302
2729
 
2730
+ if (parsed.command === "completion") {
2731
+ process.exit(runCompletion(parsed));
2732
+ }
2733
+
2303
2734
  if (parsed.command === "apply") {
2304
2735
  process.exit(runApply(parsed));
2305
2736
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x-openapi-flow",
3
- "version": "1.3.2",
3
+ "version": "1.3.5",
4
4
  "description": "OpenAPI extension for resource workflow and lifecycle management",
5
5
  "main": "lib/validator.js",
6
6
  "repository": {
@@ -17,7 +17,6 @@
17
17
  "adapters",
18
18
  "templates",
19
19
  "schema",
20
- "schema",
21
20
  "examples",
22
21
  "README.md",
23
22
  "LICENSE"