@spec0/cli 0.1.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.
Files changed (220) hide show
  1. package/AGENTS.md +67 -0
  2. package/LICENSE +21 -0
  3. package/README.md +235 -0
  4. package/dist/commands/api/changelog.d.ts +9 -0
  5. package/dist/commands/api/changelog.d.ts.map +1 -0
  6. package/dist/commands/api/changelog.js +144 -0
  7. package/dist/commands/api/changelog.js.map +1 -0
  8. package/dist/commands/api/index.d.ts +6 -0
  9. package/dist/commands/api/index.d.ts.map +1 -0
  10. package/dist/commands/api/index.js +13 -0
  11. package/dist/commands/api/index.js.map +1 -0
  12. package/dist/commands/api/list.d.ts +10 -0
  13. package/dist/commands/api/list.d.ts.map +1 -0
  14. package/dist/commands/api/list.js +79 -0
  15. package/dist/commands/api/list.js.map +1 -0
  16. package/dist/commands/api/show.d.ts +9 -0
  17. package/dist/commands/api/show.d.ts.map +1 -0
  18. package/dist/commands/api/show.js +88 -0
  19. package/dist/commands/api/show.js.map +1 -0
  20. package/dist/commands/auth.d.ts +6 -0
  21. package/dist/commands/auth.d.ts.map +1 -0
  22. package/dist/commands/auth.js +166 -0
  23. package/dist/commands/auth.js.map +1 -0
  24. package/dist/commands/ci/generate.d.ts +10 -0
  25. package/dist/commands/ci/generate.d.ts.map +1 -0
  26. package/dist/commands/ci/generate.js +72 -0
  27. package/dist/commands/ci/generate.js.map +1 -0
  28. package/dist/commands/ci/index.d.ts +3 -0
  29. package/dist/commands/ci/index.d.ts.map +1 -0
  30. package/dist/commands/ci/index.js +6 -0
  31. package/dist/commands/ci/index.js.map +1 -0
  32. package/dist/commands/commands.d.ts +19 -0
  33. package/dist/commands/commands.d.ts.map +1 -0
  34. package/dist/commands/commands.js +127 -0
  35. package/dist/commands/commands.js.map +1 -0
  36. package/dist/commands/diff.d.ts +6 -0
  37. package/dist/commands/diff.d.ts.map +1 -0
  38. package/dist/commands/diff.js +102 -0
  39. package/dist/commands/diff.js.map +1 -0
  40. package/dist/commands/doctor.d.ts +11 -0
  41. package/dist/commands/doctor.d.ts.map +1 -0
  42. package/dist/commands/doctor.js +54 -0
  43. package/dist/commands/doctor.js.map +1 -0
  44. package/dist/commands/init.d.ts +6 -0
  45. package/dist/commands/init.d.ts.map +1 -0
  46. package/dist/commands/init.js +67 -0
  47. package/dist/commands/init.js.map +1 -0
  48. package/dist/commands/lint.d.ts +6 -0
  49. package/dist/commands/lint.d.ts.map +1 -0
  50. package/dist/commands/lint.js +109 -0
  51. package/dist/commands/lint.js.map +1 -0
  52. package/dist/commands/log.d.ts +6 -0
  53. package/dist/commands/log.d.ts.map +1 -0
  54. package/dist/commands/log.js +95 -0
  55. package/dist/commands/log.js.map +1 -0
  56. package/dist/commands/mcp.d.ts +6 -0
  57. package/dist/commands/mcp.d.ts.map +1 -0
  58. package/dist/commands/mcp.js +59 -0
  59. package/dist/commands/mcp.js.map +1 -0
  60. package/dist/commands/mock/create.d.ts +14 -0
  61. package/dist/commands/mock/create.d.ts.map +1 -0
  62. package/dist/commands/mock/create.js +75 -0
  63. package/dist/commands/mock/create.js.map +1 -0
  64. package/dist/commands/mock/index.d.ts +9 -0
  65. package/dist/commands/mock/index.d.ts.map +1 -0
  66. package/dist/commands/mock/index.js +18 -0
  67. package/dist/commands/mock/index.js.map +1 -0
  68. package/dist/commands/mock/list.d.ts +8 -0
  69. package/dist/commands/mock/list.d.ts.map +1 -0
  70. package/dist/commands/mock/list.js +52 -0
  71. package/dist/commands/mock/list.js.map +1 -0
  72. package/dist/commands/mock/show.d.ts +9 -0
  73. package/dist/commands/mock/show.d.ts.map +1 -0
  74. package/dist/commands/mock/show.js +68 -0
  75. package/dist/commands/mock/show.js.map +1 -0
  76. package/dist/commands/mock/url.d.ts +10 -0
  77. package/dist/commands/mock/url.d.ts.map +1 -0
  78. package/dist/commands/mock/url.js +42 -0
  79. package/dist/commands/mock/url.js.map +1 -0
  80. package/dist/commands/mock.d.ts +6 -0
  81. package/dist/commands/mock.d.ts.map +1 -0
  82. package/dist/commands/mock.js +116 -0
  83. package/dist/commands/mock.js.map +1 -0
  84. package/dist/commands/publish.d.ts +11 -0
  85. package/dist/commands/publish.d.ts.map +1 -0
  86. package/dist/commands/publish.js +242 -0
  87. package/dist/commands/publish.js.map +1 -0
  88. package/dist/commands/pull.d.ts +6 -0
  89. package/dist/commands/pull.d.ts.map +1 -0
  90. package/dist/commands/pull.js +62 -0
  91. package/dist/commands/pull.js.map +1 -0
  92. package/dist/commands/push.d.ts +18 -0
  93. package/dist/commands/push.d.ts.map +1 -0
  94. package/dist/commands/push.js +302 -0
  95. package/dist/commands/push.js.map +1 -0
  96. package/dist/commands/register.d.ts +6 -0
  97. package/dist/commands/register.d.ts.map +1 -0
  98. package/dist/commands/register.js +213 -0
  99. package/dist/commands/register.js.map +1 -0
  100. package/dist/commands/search.d.ts +6 -0
  101. package/dist/commands/search.d.ts.map +1 -0
  102. package/dist/commands/search.js +58 -0
  103. package/dist/commands/search.js.map +1 -0
  104. package/dist/commands/status.d.ts +6 -0
  105. package/dist/commands/status.d.ts.map +1 -0
  106. package/dist/commands/status.js +86 -0
  107. package/dist/commands/status.js.map +1 -0
  108. package/dist/commands/sync-status.d.ts +14 -0
  109. package/dist/commands/sync-status.d.ts.map +1 -0
  110. package/dist/commands/sync-status.js +119 -0
  111. package/dist/commands/sync-status.js.map +1 -0
  112. package/dist/commands/team.d.ts +6 -0
  113. package/dist/commands/team.d.ts.map +1 -0
  114. package/dist/commands/team.js +30 -0
  115. package/dist/commands/team.js.map +1 -0
  116. package/dist/commands/version.d.ts +6 -0
  117. package/dist/commands/version.d.ts.map +1 -0
  118. package/dist/commands/version.js +31 -0
  119. package/dist/commands/version.js.map +1 -0
  120. package/dist/index.d.ts +3 -0
  121. package/dist/index.d.ts.map +1 -0
  122. package/dist/index.js +61 -0
  123. package/dist/index.js.map +1 -0
  124. package/dist/lib/agent-mode.d.ts +25 -0
  125. package/dist/lib/agent-mode.d.ts.map +1 -0
  126. package/dist/lib/agent-mode.js +36 -0
  127. package/dist/lib/agent-mode.js.map +1 -0
  128. package/dist/lib/api-client.d.ts +37 -0
  129. package/dist/lib/api-client.d.ts.map +1 -0
  130. package/dist/lib/api-client.js +144 -0
  131. package/dist/lib/api-client.js.map +1 -0
  132. package/dist/lib/auth-context.d.ts +18 -0
  133. package/dist/lib/auth-context.d.ts.map +1 -0
  134. package/dist/lib/auth-context.js +48 -0
  135. package/dist/lib/auth-context.js.map +1 -0
  136. package/dist/lib/breaking-change.d.ts +12 -0
  137. package/dist/lib/breaking-change.d.ts.map +1 -0
  138. package/dist/lib/breaking-change.js +10 -0
  139. package/dist/lib/breaking-change.js.map +1 -0
  140. package/dist/lib/ci-detect.d.ts +33 -0
  141. package/dist/lib/ci-detect.d.ts.map +1 -0
  142. package/dist/lib/ci-detect.js +136 -0
  143. package/dist/lib/ci-detect.js.map +1 -0
  144. package/dist/lib/cli-spec-path.d.ts +6 -0
  145. package/dist/lib/cli-spec-path.d.ts.map +1 -0
  146. package/dist/lib/cli-spec-path.js +34 -0
  147. package/dist/lib/cli-spec-path.js.map +1 -0
  148. package/dist/lib/codeowners.d.ts +11 -0
  149. package/dist/lib/codeowners.d.ts.map +1 -0
  150. package/dist/lib/codeowners.js +43 -0
  151. package/dist/lib/codeowners.js.map +1 -0
  152. package/dist/lib/config.d.ts +24 -0
  153. package/dist/lib/config.d.ts.map +1 -0
  154. package/dist/lib/config.js +49 -0
  155. package/dist/lib/config.js.map +1 -0
  156. package/dist/lib/deprecation.d.ts +17 -0
  157. package/dist/lib/deprecation.d.ts.map +1 -0
  158. package/dist/lib/deprecation.js +22 -0
  159. package/dist/lib/deprecation.js.map +1 -0
  160. package/dist/lib/doctor.d.ts +40 -0
  161. package/dist/lib/doctor.d.ts.map +1 -0
  162. package/dist/lib/doctor.js +107 -0
  163. package/dist/lib/doctor.js.map +1 -0
  164. package/dist/lib/exit-codes.d.ts +51 -0
  165. package/dist/lib/exit-codes.d.ts.map +1 -0
  166. package/dist/lib/exit-codes.js +78 -0
  167. package/dist/lib/exit-codes.js.map +1 -0
  168. package/dist/lib/lint.d.ts +18 -0
  169. package/dist/lib/lint.d.ts.map +1 -0
  170. package/dist/lib/lint.js +41 -0
  171. package/dist/lib/lint.js.map +1 -0
  172. package/dist/lib/local-config-yaml.d.ts +14 -0
  173. package/dist/lib/local-config-yaml.d.ts.map +1 -0
  174. package/dist/lib/local-config-yaml.js +29 -0
  175. package/dist/lib/local-config-yaml.js.map +1 -0
  176. package/dist/lib/output/index.d.ts +69 -0
  177. package/dist/lib/output/index.d.ts.map +1 -0
  178. package/dist/lib/output/index.js +120 -0
  179. package/dist/lib/output/index.js.map +1 -0
  180. package/dist/lib/output/table.d.ts +19 -0
  181. package/dist/lib/output/table.d.ts.map +1 -0
  182. package/dist/lib/output/table.js +48 -0
  183. package/dist/lib/output/table.js.map +1 -0
  184. package/dist/lib/output.d.ts +32 -0
  185. package/dist/lib/output.d.ts.map +1 -0
  186. package/dist/lib/output.js +64 -0
  187. package/dist/lib/output.js.map +1 -0
  188. package/dist/lib/platform-defaults.d.ts +27 -0
  189. package/dist/lib/platform-defaults.d.ts.map +1 -0
  190. package/dist/lib/platform-defaults.js +36 -0
  191. package/dist/lib/platform-defaults.js.map +1 -0
  192. package/dist/lib/ref-resolver.d.ts +37 -0
  193. package/dist/lib/ref-resolver.d.ts.map +1 -0
  194. package/dist/lib/ref-resolver.js +56 -0
  195. package/dist/lib/ref-resolver.js.map +1 -0
  196. package/dist/lib/registry-ref.d.ts +10 -0
  197. package/dist/lib/registry-ref.d.ts.map +1 -0
  198. package/dist/lib/registry-ref.js +18 -0
  199. package/dist/lib/registry-ref.js.map +1 -0
  200. package/dist/lib/spec-finder.d.ts +6 -0
  201. package/dist/lib/spec-finder.d.ts.map +1 -0
  202. package/dist/lib/spec-finder.js +42 -0
  203. package/dist/lib/spec-finder.js.map +1 -0
  204. package/dist/lib/update-check.d.ts +12 -0
  205. package/dist/lib/update-check.d.ts.map +1 -0
  206. package/dist/lib/update-check.js +62 -0
  207. package/dist/lib/update-check.js.map +1 -0
  208. package/dist/lib/version.d.ts +17 -0
  209. package/dist/lib/version.d.ts.map +1 -0
  210. package/dist/lib/version.js +33 -0
  211. package/dist/lib/version.js.map +1 -0
  212. package/dist/lib/winspect-yaml.d.ts +14 -0
  213. package/dist/lib/winspect-yaml.d.ts.map +1 -0
  214. package/dist/lib/winspect-yaml.js +28 -0
  215. package/dist/lib/winspect-yaml.js.map +1 -0
  216. package/dist/types.d.ts +664 -0
  217. package/dist/types.d.ts.map +1 -0
  218. package/dist/types.js +6 -0
  219. package/dist/types.js.map +1 -0
  220. package/package.json +87 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * spec0 diff — compare two OpenAPI specs (registry refs and/or local files)
3
+ */
4
+ import chalk from "chalk";
5
+ import { existsSync, readFileSync } from "fs";
6
+ import { createTwoFilesPatch } from "diff";
7
+ import { createOrgApiClient, is401, extractErrorMessage } from "../lib/api-client.js";
8
+ import { requireOrgContext } from "../lib/auth-context.js";
9
+ import { resolveRef } from "../lib/ref-resolver.js";
10
+ import { ExitCode, exit, exitCodeForHttpStatus } from "../lib/exit-codes.js";
11
+ async function loadSpecContent(token, ctx) {
12
+ const trimmed = token.trim();
13
+ if (existsSync(trimmed)) {
14
+ return readFileSync(trimmed, "utf-8");
15
+ }
16
+ const client = createOrgApiClient(ctx);
17
+ const parsed = resolveRef(trimmed);
18
+ if (parsed.kind !== "name" || !parsed.org) {
19
+ throw new Error(`Diff requires '<org>/<api>[@<tag>]' or a local file. Got '${trimmed}'.`);
20
+ }
21
+ const path = parsed.tag
22
+ ? `/registry/${encodeURIComponent(parsed.org)}/${encodeURIComponent(parsed.api)}/versions/${encodeURIComponent(parsed.tag)}`
23
+ : `/registry/${encodeURIComponent(parsed.org)}/${encodeURIComponent(parsed.api)}?format=yaml`;
24
+ return client.getText(path);
25
+ }
26
+ async function breakingChangesViaBackend(ctx, leftContent, rightContent, leftLabel, rightLabel) {
27
+ const client = createOrgApiClient(ctx);
28
+ const result = await client.postMultipart("/api-management/cli/v1/diff", {
29
+ base: { content: leftContent, filename: leftLabel },
30
+ revision: { content: rightContent, filename: rightLabel },
31
+ });
32
+ if (!result.hasBreakingChanges) {
33
+ console.log(chalk.green("No breaking changes detected."));
34
+ return;
35
+ }
36
+ console.log(chalk.red(`Breaking changes detected:`));
37
+ if (result.breakingChanges?.length) {
38
+ for (const bc of result.breakingChanges) {
39
+ const id = bc["id"] ?? bc["text"] ?? JSON.stringify(bc);
40
+ const level = bc["level"] ?? "";
41
+ const msg = bc["message"] ?? bc["text"] ?? "";
42
+ console.log(chalk.red(` [${level}] ${id}${msg ? ": " + msg : ""}`));
43
+ }
44
+ }
45
+ }
46
+ export function registerDiffCommand(program) {
47
+ program
48
+ .command("diff")
49
+ .description("Diff two specs: each side is a file path or registry ref org/api[@tag] (latest if tag omitted)")
50
+ .argument("<a>", "Left: local path or org/api[@tag]")
51
+ .argument("<b>", "Right: local path or org/api[@tag]")
52
+ .option("--breaking-only", "Show breaking changes only (via backend oasdiff service)")
53
+ .option("--org <uuid>", "Org id override for registry fetches")
54
+ .action(async (a, b, opts) => {
55
+ let ctx;
56
+ try {
57
+ ctx = requireOrgContext(opts.org);
58
+ }
59
+ catch (e) {
60
+ console.error(chalk.red(e.message));
61
+ exit(ExitCode.AUTH_MISSING);
62
+ }
63
+ let left;
64
+ let right;
65
+ try {
66
+ left = await loadSpecContent(a, ctx);
67
+ right = await loadSpecContent(b, ctx);
68
+ }
69
+ catch (err) {
70
+ if (is401(err)) {
71
+ console.error(chalk.red("Token invalid. Run 'spec0 auth login'."));
72
+ exit(ExitCode.AUTH_MISSING);
73
+ }
74
+ const status = err?.response?.statusCode;
75
+ console.error(chalk.red(`Failed to load spec: ${err.message}`));
76
+ exit(status ? exitCodeForHttpStatus(status) : ExitCode.GENERIC);
77
+ }
78
+ if (opts.breakingOnly) {
79
+ try {
80
+ await breakingChangesViaBackend(ctx, left, right, a, b);
81
+ }
82
+ catch (err) {
83
+ if (is401(err)) {
84
+ console.error(chalk.red("Token invalid. Run 'spec0 auth login'."));
85
+ exit(ExitCode.AUTH_MISSING);
86
+ }
87
+ const status = err?.response?.statusCode;
88
+ const msg = extractErrorMessage(err) ?? err.message;
89
+ console.error(chalk.red(`Breaking change check failed: ${msg}`));
90
+ exit(status ? exitCodeForHttpStatus(status) : ExitCode.GENERIC);
91
+ }
92
+ return;
93
+ }
94
+ const patch = createTwoFilesPatch(a, b, left, right, "", "", { context: 3 });
95
+ if (!patch.trim()) {
96
+ console.log(chalk.green("No textual differences."));
97
+ return;
98
+ }
99
+ process.stdout.write(patch);
100
+ });
101
+ }
102
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * spec0 doctor — print which config sources are in effect.
3
+ *
4
+ * Useful when an `auth missing` or `wrong URL` error fires and the user
5
+ * wants to know "which env var or config file is the CLI actually reading?".
6
+ *
7
+ * Exits 0 when token + orgId resolve, otherwise the corresponding ExitCode.
8
+ */
9
+ import { Command } from "commander";
10
+ export declare function registerDoctorCommand(program: Command): void;
11
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAiBrD"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * spec0 doctor — print which config sources are in effect.
3
+ *
4
+ * Useful when an `auth missing` or `wrong URL` error fires and the user
5
+ * wants to know "which env var or config file is the CLI actually reading?".
6
+ *
7
+ * Exits 0 when token + orgId resolve, otherwise the corresponding ExitCode.
8
+ */
9
+ import chalk from "chalk";
10
+ import { ExitCode, exit } from "../lib/exit-codes.js";
11
+ import { emit, resolveOutputContext } from "../lib/output/index.js";
12
+ import { buildDoctorReport, describeSource } from "../lib/doctor.js";
13
+ export function registerDoctorCommand(program) {
14
+ program
15
+ .command("doctor")
16
+ .description("Diagnose CLI configuration: where each setting is being read from.")
17
+ .option("--output <format>", "Output format: text, json, or yaml (default: text)")
18
+ .action((opts) => {
19
+ const ctx = resolveOutputContext(opts);
20
+ const report = buildDoctorReport();
21
+ emit(ctx, report, renderDoctorText);
22
+ if (!report.ok) {
23
+ // No message here — emit() already printed the diagnostic.
24
+ process.exit(ExitCode.AUTH_MISSING);
25
+ }
26
+ exit(ExitCode.SUCCESS);
27
+ });
28
+ }
29
+ function renderDoctorText(report) {
30
+ const lines = [];
31
+ lines.push(chalk.bold("spec0 configuration"));
32
+ lines.push("");
33
+ const colWidth = Math.max(...report.settings.map((s) => s.name.length));
34
+ for (const s of report.settings) {
35
+ const name = s.name.padEnd(colWidth);
36
+ const src = describeSource(s.source);
37
+ const colour = s.source.kind === "missing" ? chalk.red : chalk.gray;
38
+ // describeSource for "missing" returns "(not set)" already; everything else is bare text.
39
+ const srcDisplay = s.source.kind === "missing" ? src : `(${src})`;
40
+ lines.push(` ${name} ${s.value} ${colour(srcDisplay)}`);
41
+ }
42
+ lines.push("");
43
+ lines.push(` config file: ${report.configPath}`);
44
+ lines.push("");
45
+ if (report.ok) {
46
+ lines.push(chalk.green("✓ ready to talk to the platform"));
47
+ }
48
+ else {
49
+ lines.push(chalk.red("✗ missing required settings — see above"));
50
+ lines.push(chalk.gray(" Set SPEC0_TOKEN + SPEC0_ORG_ID for non-interactive use, or run 'spec0 auth login'."));
51
+ }
52
+ return lines.join("\n");
53
+ }
54
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * spec0 init — onboarding, spec auto-detect, CODEOWNERS, .spec0.yaml, optional register
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerInitCommand(program: Command): void;
6
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QA0DnD"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * spec0 init — onboarding, spec auto-detect, CODEOWNERS, .spec0.yaml, optional register
3
+ */
4
+ import chalk from "chalk";
5
+ import { findSpecInDir } from "../lib/spec-finder.js";
6
+ import { getTeamFromCodeowners } from "../lib/codeowners.js";
7
+ import { writeFileSync } from "fs";
8
+ import { join } from "path";
9
+ import { execSync } from "child_process";
10
+ import { ExitCode, exit } from "../lib/exit-codes.js";
11
+ export function registerInitCommand(program) {
12
+ program
13
+ .command("init")
14
+ .description("Detect your OpenAPI spec and create a .spec0.yaml config file")
15
+ .option("--all", "Scan subdirectories for .spec0.yaml (monorepo)")
16
+ .option("--push", "Run spec0 push after writing config")
17
+ .action(async (opts) => {
18
+ const cwd = process.cwd();
19
+ const specPath = findSpecInDir(cwd);
20
+ if (!specPath) {
21
+ console.error(chalk.red("No OpenAPI spec found. Add openapi.yaml, openapi.json, or swagger.yaml"));
22
+ exit(ExitCode.USAGE);
23
+ }
24
+ const specName = specPath.split("/").pop() ?? "openapi.yaml";
25
+ const team = getTeamFromCodeowners(cwd, specPath);
26
+ const defaultName = specPath.split("/").slice(-2, -1)[0] ?? "api";
27
+ const suggestedName = defaultName.replace(/[^a-z0-9-]/gi, "-").toLowerCase();
28
+ console.log(chalk.blue(`Found ${specName}. Suggested API name: ${suggestedName}`));
29
+ if (team)
30
+ console.log(chalk.blue(`Team from CODEOWNERS: ${team}`));
31
+ const config = {
32
+ spec: specName,
33
+ name: suggestedName,
34
+ owner: team ?? "default",
35
+ namespace: `${team ?? "default"}/${suggestedName}`,
36
+ autoCreateTeam: false,
37
+ strict: false,
38
+ checkBreaking: true,
39
+ };
40
+ const yamlPath = join(cwd, ".spec0.yaml");
41
+ const yaml = [
42
+ `# Spec0 config — generated by spec0 init`,
43
+ `spec: ${specName}`,
44
+ `name: ${config.name}`,
45
+ `owner: ${config.owner}`,
46
+ `namespace: ${config.namespace}`,
47
+ `auto-create-team: ${config.autoCreateTeam}`,
48
+ `strict: ${config.strict}`,
49
+ `check-breaking: ${config.checkBreaking}`,
50
+ ].join("\n");
51
+ writeFileSync(yamlPath, yaml);
52
+ console.log(chalk.green("Initialized! Spec0 config written to .spec0.yaml"));
53
+ if (opts.push) {
54
+ try {
55
+ execSync("spec0 push", { stdio: "inherit", cwd });
56
+ }
57
+ catch {
58
+ console.error(chalk.red("Push failed. Run 'spec0 push' manually."));
59
+ exit(ExitCode.GENERIC);
60
+ }
61
+ }
62
+ else {
63
+ console.log(chalk.blue("Run 'spec0 push' to upload your spec (or use --push)."));
64
+ }
65
+ });
66
+ }
67
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * spec0 lint — Spectral bundled, org ruleset fetch, JSON/text/github output
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerLintCommand(program: Command): void;
6
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAiFnD"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * spec0 lint — Spectral bundled, org ruleset fetch, JSON/text/github output
3
+ */
4
+ import chalk from "chalk";
5
+ import { existsSync, readFileSync, writeFileSync } from "fs";
6
+ import { tmpdir } from "os";
7
+ import { join } from "path";
8
+ import { findSpecInDir } from "../lib/spec-finder.js";
9
+ import { resolveCliSpecPathFromFlags } from "../lib/cli-spec-path.js";
10
+ import { runSpectral } from "../lib/lint.js";
11
+ import { formatLintText, formatGitHubAnnotation } from "../lib/output.js";
12
+ import { createOrgApiClient } from "../lib/api-client.js";
13
+ import { requireOrgContext } from "../lib/auth-context.js";
14
+ import { ExitCode, exit } from "../lib/exit-codes.js";
15
+ export function registerLintCommand(program) {
16
+ program
17
+ .command("lint")
18
+ .description("Lint OpenAPI spec with Spectral")
19
+ .argument("[spec-file]", "Path to OpenAPI spec (or use --spec-file / global --spec-file)")
20
+ .option("--spec-file <path>", "Path to OpenAPI spec file")
21
+ .option("--ruleset <file>", "Use custom ruleset file")
22
+ .option("--org-ruleset", "Fetch org ruleset from server")
23
+ .option("--save-ruleset <file>", "Upload <file> as the org's stored Spectral ruleset (skips the lint step)")
24
+ .option("--format <fmt>", "Output: text, json, github, sarif", "text")
25
+ .option("--min-score <n>", "Exit 1 if score below n (0-100)", "0")
26
+ .option("--strict", "Exit 1 on any warning")
27
+ .action(async (specArg, opts, command) => {
28
+ // --save-ruleset is an upload-only mode; short-circuit the lint path.
29
+ if (typeof opts.saveRuleset === "string" && opts.saveRuleset) {
30
+ await uploadRuleset(opts.saveRuleset);
31
+ return;
32
+ }
33
+ const cwd = process.cwd();
34
+ const specPath = resolveCliSpecPathFromFlags(command, cwd, opts.specFile, specArg) ??
35
+ findSpecInDir(cwd);
36
+ if (!specPath || !existsSync(specPath)) {
37
+ console.error(chalk.red("Spec file not found."));
38
+ exit(ExitCode.USAGE);
39
+ }
40
+ let rulesetFile = opts.ruleset;
41
+ if (opts.orgRuleset) {
42
+ try {
43
+ const ctx = requireOrgContext();
44
+ const client = createOrgApiClient(ctx);
45
+ const res = (await client.getJson("/api-management/cli/v1/spectral-ruleset"));
46
+ const yaml = res.rulesetYaml?.trim() ?? "";
47
+ if (!yaml) {
48
+ console.warn(chalk.yellow("No org ruleset stored on the server; using built-in OAS ruleset."));
49
+ }
50
+ else {
51
+ rulesetFile = join(tmpdir(), `spec0-org-ruleset-${Date.now()}.yaml`);
52
+ writeFileSync(rulesetFile, yaml, "utf-8");
53
+ }
54
+ }
55
+ catch (e) {
56
+ console.error(chalk.red(e.message));
57
+ exit(ExitCode.AUTH_MISSING);
58
+ }
59
+ }
60
+ const result = await runSpectral(specPath, rulesetFile);
61
+ if (opts.format === "json") {
62
+ console.log(JSON.stringify(result, null, 2));
63
+ }
64
+ else if (opts.format === "github") {
65
+ for (const e of result.errors) {
66
+ console.log(formatGitHubAnnotation(specPath, e.line ?? 0, "error", e.message));
67
+ }
68
+ for (const w of result.warnings) {
69
+ console.log(formatGitHubAnnotation(specPath, w.line ?? 0, "warning", w.message));
70
+ }
71
+ }
72
+ else {
73
+ console.log(`Linting ${specPath}... (oas ruleset)\n`);
74
+ console.log(formatLintText(result));
75
+ }
76
+ const minScore = parseInt(String(opts.minScore ?? "0"), 10);
77
+ if (result.score < minScore)
78
+ exit(ExitCode.VALIDATION);
79
+ if (opts.strict === true && result.warnings.length > 0)
80
+ exit(ExitCode.VALIDATION);
81
+ if (result.errors.length > 0)
82
+ exit(ExitCode.VALIDATION);
83
+ });
84
+ }
85
+ async function uploadRuleset(filePath) {
86
+ if (!existsSync(filePath)) {
87
+ console.error(chalk.red(`Ruleset file not found: ${filePath}`));
88
+ exit(ExitCode.USAGE);
89
+ }
90
+ const rulesetYaml = readFileSync(filePath, "utf-8");
91
+ let ctx;
92
+ try {
93
+ ctx = requireOrgContext();
94
+ }
95
+ catch (e) {
96
+ console.error(chalk.red(e.message));
97
+ exit(ExitCode.AUTH_MISSING);
98
+ }
99
+ const client = createOrgApiClient(ctx);
100
+ try {
101
+ await client.putJson("/api-management/cli/v1/spectral-ruleset", { rulesetYaml });
102
+ console.log(chalk.green(`✓ uploaded ${filePath} as the org's Spectral ruleset`));
103
+ }
104
+ catch (err) {
105
+ console.error(chalk.red(`Failed to upload ruleset: ${err.message}`));
106
+ exit(ExitCode.GENERIC);
107
+ }
108
+ }
109
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * spec0 log — version history from registry
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerLogCommand(program: Command): void;
6
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,QAmElD"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * spec0 log — version history from registry
3
+ */
4
+ import chalk from "chalk";
5
+ import { createOrgApiClient, is401 } from "../lib/api-client.js";
6
+ import { requireOrgContext } from "../lib/auth-context.js";
7
+ import { getDefaultOrgId, getOrgConfig } from "../lib/config.js";
8
+ import { parseRegistryRef } from "../lib/registry-ref.js";
9
+ import { ExitCode, exit } from "../lib/exit-codes.js";
10
+ import { emit, resolveOutputContext } from "../lib/output/index.js";
11
+ import { renderTable } from "../lib/output/table.js";
12
+ import { warnDeprecated } from "../lib/deprecation.js";
13
+ export function registerLogCommand(program) {
14
+ program
15
+ .command("log <api-ref>")
16
+ .description("Show published version history. api-ref: api-name (default org) or org-slug/api-name")
17
+ .option("--org <uuid>", "Org id override (auth)")
18
+ .option("--org-slug <slug>", "Organisation slug/name for registry path when api-ref has no slash (default: name from spec0 auth config)")
19
+ .option("--output <format>", "Output format: text, json, or yaml (default: text)")
20
+ .option("--json", "Deprecated. Use --output=json instead.")
21
+ .action(async (apiRef, opts) => {
22
+ if (opts.json) {
23
+ warnDeprecated({
24
+ what: "the --json flag on `spec0 log`",
25
+ removeIn: "v1.0.0",
26
+ alternative: "--output=json",
27
+ });
28
+ }
29
+ const outCtx = resolveOutputContext(opts);
30
+ let orgSlug;
31
+ let apiName;
32
+ try {
33
+ if (apiRef.includes("/")) {
34
+ const p = parseRegistryRef(apiRef);
35
+ orgSlug = p.org;
36
+ apiName = p.api;
37
+ }
38
+ else {
39
+ const orgId = process.env.PLATFORM_ORG_ID ?? getDefaultOrgId();
40
+ const cfg = orgId ? getOrgConfig(orgId) : undefined;
41
+ const fallback = cfg?.name?.trim();
42
+ orgSlug = (opts.orgSlug ?? fallback ?? "").trim();
43
+ if (!orgSlug) {
44
+ exit(ExitCode.USAGE, "Set --org-slug <slug> or use org-slug/api-name, or run 'spec0 auth login'.");
45
+ }
46
+ apiName = apiRef.trim();
47
+ }
48
+ }
49
+ catch (e) {
50
+ exit(ExitCode.USAGE, e.message);
51
+ }
52
+ let authCtx;
53
+ try {
54
+ authCtx = requireOrgContext(opts.org);
55
+ }
56
+ catch (e) {
57
+ exit(ExitCode.AUTH_MISSING, e.message);
58
+ }
59
+ const client = createOrgApiClient(authCtx);
60
+ const path = `/registry/${encodeURIComponent(orgSlug)}/${encodeURIComponent(apiName)}/versions`;
61
+ try {
62
+ const rows = (await client.getJson(path));
63
+ emit(outCtx, rows, (data) => renderLogText(data, orgSlug, apiName));
64
+ }
65
+ catch (err) {
66
+ if (is401(err)) {
67
+ exit(ExitCode.AUTH_MISSING, "Token invalid or expired. Run 'spec0 auth login'.");
68
+ }
69
+ exit(ExitCode.GENERIC, `Log failed: ${err.message}`);
70
+ }
71
+ });
72
+ }
73
+ function renderLogText(rows, orgSlug, apiName) {
74
+ if (!rows.length)
75
+ return chalk.yellow("No published versions found.");
76
+ const table = renderTable(rows, [
77
+ { key: "tag", header: "Tag" },
78
+ { key: "publishedAt", header: "Published" },
79
+ { key: "gitSha", header: "Git SHA", format: (v) => String(v ?? "—").slice(0, 12) },
80
+ {
81
+ key: "breakingChangesRecorded",
82
+ header: "Breaking",
83
+ format: (v) => (v ? "yes" : "—"),
84
+ },
85
+ ]);
86
+ const lines = [chalk.blue(`${orgSlug}/${apiName} version history:`), table];
87
+ for (const r of rows) {
88
+ if (r.breakingChangeSummary) {
89
+ const prev = (r.breakingChangeSummary ?? "").slice(0, 500);
90
+ lines.push("", chalk.gray(`${r.tag}: ${prev}${prev.length >= 500 ? "…" : ""}`));
91
+ }
92
+ }
93
+ return lines.join("\n");
94
+ }
95
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * spec0 mcp url | test
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerMcpCommands(program: Command): void;
6
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAyDnD"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * spec0 mcp url | test
3
+ */
4
+ import chalk from "chalk";
5
+ import got from "got";
6
+ import { getDefaultOrgId, getOrgConfig } from "../lib/config.js";
7
+ import { ExitCode, exit, exitCodeForHttpStatus } from "../lib/exit-codes.js";
8
+ export function registerMcpCommands(program) {
9
+ const mcp = program.command("mcp").description("MCP server URL and config");
10
+ mcp
11
+ .command("url")
12
+ .description("Print MCP server URL for Cursor/Claude config")
13
+ .action(async () => {
14
+ const orgId = process.env.PLATFORM_ORG_ID ?? getDefaultOrgId();
15
+ if (!orgId || !getOrgConfig(orgId)) {
16
+ console.error(chalk.red("Not authenticated. Run 'spec0 auth login'."));
17
+ exit(ExitCode.AUTH_MISSING);
18
+ }
19
+ const org = getOrgConfig(orgId);
20
+ const mcpUrl = `https://mcp.spec0.io/org/${orgId}/mcp`;
21
+ console.log("Your MCP server URL:");
22
+ console.log(` ${mcpUrl}`);
23
+ console.log("");
24
+ console.log("Add to Cursor settings:");
25
+ console.log(JSON.stringify({
26
+ mcpServers: {
27
+ spec0: {
28
+ url: mcpUrl,
29
+ apiKey: org.apiKey,
30
+ },
31
+ },
32
+ }, null, 2));
33
+ });
34
+ mcp
35
+ .command("test")
36
+ .description("Verify MCP server is responding")
37
+ .action(async () => {
38
+ const orgId = process.env.PLATFORM_ORG_ID ?? getDefaultOrgId();
39
+ if (!orgId || !getOrgConfig(orgId)) {
40
+ console.error(chalk.red("Not authenticated. Run 'spec0 auth login'."));
41
+ exit(ExitCode.AUTH_MISSING);
42
+ }
43
+ const org = getOrgConfig(orgId);
44
+ const base = org.apiUrl.replace(/\/$/, "");
45
+ const url = `${base}/mcp/org/${orgId}/health`;
46
+ try {
47
+ const res = await got.get(url, {
48
+ headers: { Authorization: `Bearer ${org.apiKey}`, "X-Org-Id": orgId },
49
+ });
50
+ console.log(chalk.green("MCP gateway OK:"), res.body);
51
+ }
52
+ catch (e) {
53
+ const status = e?.response?.statusCode;
54
+ console.error(chalk.red("MCP health check failed:"), e.message);
55
+ exit(status ? exitCodeForHttpStatus(status) : ExitCode.NETWORK_ERROR);
56
+ }
57
+ });
58
+ }
59
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * spec0 mock create — provision (or fetch) the default mock server for an API.
3
+ *
4
+ * The backend endpoint is idempotent: POST /api-management/cli/v1/mocks either
5
+ * returns the existing mock or creates a fresh one. The API key is only ever
6
+ * returned once (on initial creation), so CI callers should capture it on the
7
+ * very first run — we surface it prominently in text mode and include it in
8
+ * the JSON payload.
9
+ */
10
+ import { Command } from "commander";
11
+ import type { components } from "../../types.js";
12
+ export declare function registerMockCreateCommand(mock: Command): void;
13
+ export type MockItem = components["schemas"]["MockItem"];
14
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/mock/create.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,OAAO,KAAK,EAAE,UAAU,EAAS,MAAM,gBAAgB,CAAC;AAexD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,QAsDtD;AAeD,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC"}