@scalar/cli 2.0.1 → 2.5.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.
Files changed (83) hide show
  1. package/README.md +68 -24
  2. package/chunks/action-37EV4UHW.js +125 -0
  3. package/chunks/action-4XI7XJR4.js +204 -0
  4. package/chunks/action-5IU77OII.js +60 -0
  5. package/chunks/action-B3KKREWQ.js +64 -0
  6. package/chunks/action-CH24QGTE.js +86 -0
  7. package/chunks/action-F3UX5E3M.js +522 -0
  8. package/chunks/action-FDB7NEOK.js +81 -0
  9. package/chunks/action-FIXBOJEW.js +244 -0
  10. package/chunks/action-G26LSVZ7.js +40 -0
  11. package/chunks/action-H3RTILLM.js +46 -0
  12. package/chunks/action-HGBBV353.js +86 -0
  13. package/chunks/action-IUE4IOWO.js +2142 -0
  14. package/chunks/action-JZLZ7ZAD.js +110 -0
  15. package/chunks/action-LA6KVAXQ.js +374 -0
  16. package/chunks/action-M7RQKBSB.js +169 -0
  17. package/chunks/action-MSLBC2SO.js +92 -0
  18. package/chunks/action-NVSZT2ZD.js +37 -0
  19. package/chunks/action-OGQSTRMX.js +37 -0
  20. package/chunks/action-PAGJ5PWC.js +60 -0
  21. package/chunks/action-QE2ZQQX7.js +250 -0
  22. package/chunks/action-QPUSPD5M.js +54 -0
  23. package/chunks/action-R7IMFHQ5.js +147 -0
  24. package/chunks/action-SH4UUXPL.js +60 -0
  25. package/chunks/action-SNLCIBQC.js +84 -0
  26. package/chunks/action-SQG3JAII.js +150 -0
  27. package/chunks/action-UZQJNYK4.js +18 -0
  28. package/chunks/action-VC4DCVST.js +68 -0
  29. package/chunks/action-VTVFY2MP.js +181 -0
  30. package/chunks/action-WFWYGY7O.js +67 -0
  31. package/chunks/action-XMNX5ZYT.js +197 -0
  32. package/chunks/agent-HCQRMHQ5.js +132 -0
  33. package/chunks/asyncapi-QM76O55R.js +105 -0
  34. package/chunks/build.action-P7FCIMYU.js +108 -0
  35. package/chunks/chunk-24WAOKGG.js +105 -0
  36. package/chunks/chunk-3L6DLIXJ.js +25530 -0
  37. package/chunks/chunk-3MZYUBJ6.js +49 -0
  38. package/chunks/chunk-3ZJYGGAA.js +30 -0
  39. package/chunks/chunk-4NHMAG6F.js +21 -0
  40. package/chunks/chunk-4ORL4MST.js +16 -0
  41. package/chunks/chunk-4ZDQXWBT.js +26 -0
  42. package/chunks/chunk-6ZMT63IV.js +19 -0
  43. package/chunks/chunk-7AGLC7WV.js +107 -0
  44. package/chunks/chunk-AEFPCC4U.js +16 -0
  45. package/chunks/chunk-AO3F5XWR.js +3147 -0
  46. package/chunks/chunk-B2MHTD3R.js +90 -0
  47. package/chunks/chunk-CISTON3A.js +153 -0
  48. package/chunks/chunk-COBPBRQF.js +25 -0
  49. package/chunks/chunk-F467BYYR.js +568 -0
  50. package/chunks/chunk-GSGZHE26.js +352 -0
  51. package/chunks/chunk-HCPN3KNF.js +637 -0
  52. package/chunks/chunk-HPL3ZZ2P.js +1726 -0
  53. package/chunks/chunk-IKT5F47M.js +17344 -0
  54. package/chunks/chunk-JFIXNSPP.js +26 -0
  55. package/chunks/chunk-K4DTP5TV.js +32 -0
  56. package/chunks/chunk-K74E42RV.js +7311 -0
  57. package/chunks/chunk-KHDYYVYF.js +16 -0
  58. package/chunks/chunk-LFU5ZUAP.js +350 -0
  59. package/chunks/chunk-M37TP6U2.js +445 -0
  60. package/chunks/chunk-OQKDBLOZ.js +741 -0
  61. package/chunks/chunk-P7H7GY5A.js +14 -0
  62. package/chunks/chunk-PBXZN65A.js +63911 -0
  63. package/chunks/chunk-PT5TI77I.js +34 -0
  64. package/chunks/chunk-Q7DOQHZN.js +404 -0
  65. package/chunks/chunk-T5HJUAWB.js +242 -0
  66. package/chunks/chunk-T7B6WNZC.js +18 -0
  67. package/chunks/chunk-UGGNHILG.js +38 -0
  68. package/chunks/chunk-VNYE4R7N.js +499 -0
  69. package/chunks/chunk-X5T526CE.js +23 -0
  70. package/chunks/chunk-XCSR4RIT.js +210 -0
  71. package/chunks/chunk-Z2KMGFE6.js +295 -0
  72. package/chunks/create.action-HDD2WUON.js +108 -0
  73. package/chunks/delete.action-7GOZY7ID.js +88 -0
  74. package/chunks/delete.action-VE66JFDS.js +96 -0
  75. package/chunks/get.action-2745EB4N.js +86 -0
  76. package/chunks/list.action-3VTXQJRA.js +116 -0
  77. package/chunks/list.action-4QDCZLSZ.js +95 -0
  78. package/chunks/publish.action-ULQLZKWU.js +190 -0
  79. package/chunks/update.action-6QEFP7NA.js +95 -0
  80. package/chunks/update.action-OROQSP2S.js +101 -0
  81. package/docs.html +352 -250
  82. package/index.js +664 -99064
  83. package/package.json +17 -11
@@ -0,0 +1,110 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ getProjectDeployments
4
+ } from "./chunk-PT5TI77I.js";
5
+ import {
6
+ resolveProject
7
+ } from "./chunk-T7B6WNZC.js";
8
+ import {
9
+ formatAbsoluteTime
10
+ } from "./chunk-AEFPCC4U.js";
11
+ import {
12
+ apiService
13
+ } from "./chunk-AO3F5XWR.js";
14
+ import "./chunk-F467BYYR.js";
15
+ import "./chunk-Z2KMGFE6.js";
16
+ import "./chunk-HCPN3KNF.js";
17
+ import "./chunk-B2MHTD3R.js";
18
+ import "./chunk-3L6DLIXJ.js";
19
+ import "./chunk-P7H7GY5A.js";
20
+ import "./chunk-HPL3ZZ2P.js";
21
+ import {
22
+ getAuthData
23
+ } from "./chunk-M37TP6U2.js";
24
+ import "./chunk-4ZDQXWBT.js";
25
+ import "./chunk-VNYE4R7N.js";
26
+ import "./chunk-OQKDBLOZ.js";
27
+ import "./chunk-K74E42RV.js";
28
+ import "./chunk-CISTON3A.js";
29
+ import "./chunk-Q7DOQHZN.js";
30
+ import "./chunk-4ORL4MST.js";
31
+ import {
32
+ output,
33
+ printTable
34
+ } from "./chunk-T5HJUAWB.js";
35
+ import "./chunk-GSGZHE26.js";
36
+ import {
37
+ external_exports,
38
+ slugSchema
39
+ } from "./chunk-IKT5F47M.js";
40
+ import "./chunk-3MZYUBJ6.js";
41
+
42
+ // src/domains/project/deployments/list/action.ts
43
+ import as from "ansis";
44
+ function colorStatus(status) {
45
+ switch (status) {
46
+ case "deployed":
47
+ return as.green(status);
48
+ case "error":
49
+ case "cancelled":
50
+ return as.red(status);
51
+ case "pending":
52
+ case "building":
53
+ return as.yellow(status);
54
+ default:
55
+ return as.dim(status);
56
+ }
57
+ }
58
+ async function listAction(args) {
59
+ const argsParseResult = external_exports.object({ slug: slugSchema.optional() }).safeParse(args);
60
+ if (argsParseResult.error) {
61
+ return output.error().title("Invalid Arguments").message(argsParseResult.error.issues[0].message).exit("error");
62
+ }
63
+ const { slug } = argsParseResult.data;
64
+ if (!slug) {
65
+ return output.error().title("Invalid argument").message("Slug is required. Try passing --slug flag.").exit("error");
66
+ }
67
+ const apiClient = await apiService();
68
+ const auth = await getAuthData();
69
+ auth.addEventListener((state) => Object.assign(auth, state));
70
+ const resolved = await resolveProject(slug, apiClient);
71
+ if (resolved.kind === "not-found") {
72
+ return output.error().title("Project not found").message(`No project with slug "${slug}" was found for your team.`).exit("error");
73
+ }
74
+ const { project } = resolved;
75
+ const activeUid = project.activeDeployment?.uid ?? null;
76
+ const deploymentsResult = await getProjectDeployments({
77
+ teamUid: auth.teamUid,
78
+ projectUid: project.uid
79
+ });
80
+ if (!deploymentsResult.success) {
81
+ return output.error().title("Could not load deployment history").message(deploymentsResult.error).exit("error");
82
+ }
83
+ if (deploymentsResult.deployments.length === 0) {
84
+ output.info().title(`No deployments found for project "${slug}".`).print();
85
+ return;
86
+ }
87
+ printTable(
88
+ [
89
+ { name: "current", title: " ", alignment: "center" },
90
+ { name: "id", title: "Build ID", alignment: "left" },
91
+ { name: "status", title: "Status", alignment: "left" },
92
+ { name: "deployed", title: "Deployed", alignment: "left" },
93
+ { name: "commit", title: "Commit", alignment: "left" }
94
+ ],
95
+ deploymentsResult.deployments.map((record) => {
96
+ const isLive = record.uid === activeUid;
97
+ const deployedAt = record.deployedAt ?? (record.status === "deployed" ? record.createdAt : null);
98
+ return {
99
+ current: isLive ? as.green("\u279C") : " ",
100
+ id: isLive ? as.green(record.uid) : record.uid,
101
+ status: colorStatus(record.status),
102
+ deployed: deployedAt ? formatAbsoluteTime(deployedAt * 1e3) : as.dim("\u2014"),
103
+ commit: record.commitSha ? record.commitSha.slice(0, 7) : as.dim("\u2014")
104
+ };
105
+ })
106
+ );
107
+ }
108
+ export {
109
+ listAction
110
+ };
@@ -0,0 +1,374 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ getFileOrUrl,
4
+ isAsyncApiContent
5
+ } from "./chunk-24WAOKGG.js";
6
+ import {
7
+ err,
8
+ ok
9
+ } from "./chunk-P7H7GY5A.js";
10
+ import {
11
+ require_dist
12
+ } from "./chunk-K74E42RV.js";
13
+ import "./chunk-CISTON3A.js";
14
+ import "./chunk-Q7DOQHZN.js";
15
+ import "./chunk-4ORL4MST.js";
16
+ import {
17
+ output
18
+ } from "./chunk-T5HJUAWB.js";
19
+ import "./chunk-GSGZHE26.js";
20
+ import "./chunk-IKT5F47M.js";
21
+ import {
22
+ __toESM
23
+ } from "./chunk-3MZYUBJ6.js";
24
+
25
+ // src/domains/document/lint/action.ts
26
+ import as from "ansis";
27
+
28
+ // ../../packages/api-document-lint/dist/constants.js
29
+ var DEFAULT_RULESET = `extends: spectral:oas
30
+ rules: {}`;
31
+ var ASYNCAPI_RULESET = `extends: spectral:asyncapi
32
+ rules: {}`;
33
+
34
+ // ../../packages/api-document-lint/dist/default-ruleset.js
35
+ function isAsyncApiContent2(content) {
36
+ const head = content.slice(0, 500);
37
+ if (head.includes('"asyncapi"')) {
38
+ return true;
39
+ }
40
+ return head.split("\n").some((line) => /^asyncapi\s*:/.test(line.trimStart()));
41
+ }
42
+ function defaultRulesetFor(content) {
43
+ return isAsyncApiContent2(content) ? ASYNCAPI_RULESET : DEFAULT_RULESET;
44
+ }
45
+
46
+ // ../../packages/api-document-lint/dist/run-spectral.js
47
+ import spectralCore from "@stoplight/spectral-core";
48
+ import { bundleAndLoadRuleset } from "@stoplight/spectral-ruleset-bundler/with-loader";
49
+ import "@stoplight/spectral-rulesets";
50
+ var { Spectral } = spectralCore;
51
+ async function runSpectral(input) {
52
+ const rulesetSource = input.ruleset && input.ruleset.trim().length > 0 ? input.ruleset : defaultRulesetFor(input.document);
53
+ const ruleset = await loadRuleset(rulesetSource);
54
+ if (!ruleset.ok) {
55
+ return ruleset;
56
+ }
57
+ const spectral = new Spectral();
58
+ spectral.setRuleset(ruleset.data);
59
+ const diagnostics = await spectral.run(input.document).catch((error) => error instanceof Error ? error : new Error(String(error)));
60
+ if (diagnostics instanceof Error) {
61
+ return err(`Spectral failed to lint the document \u2014 ${diagnostics.message}`);
62
+ }
63
+ return ok(diagnostics);
64
+ }
65
+ async function loadRuleset(source) {
66
+ const ruleset = await bundleAndLoadRuleset("/.spectral.yaml", {
67
+ fs: {
68
+ promises: {
69
+ // @ts-expect-error The loader only ever reads our single virtual file.
70
+ async readFile() {
71
+ return source;
72
+ }
73
+ }
74
+ },
75
+ format: "esm"
76
+ }).catch((error) => error instanceof Error ? error : new Error(String(error)));
77
+ if (ruleset instanceof Error) {
78
+ return err(`Failed to load ruleset \u2014 ${ruleset.message}`);
79
+ }
80
+ return ok(ruleset);
81
+ }
82
+
83
+ // ../../packages/api-document-lint/dist/run-vacuum.js
84
+ import { execFile } from "node:child_process";
85
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
86
+ import { tmpdir } from "node:os";
87
+ import { join as join2 } from "node:path";
88
+ import { promisify } from "node:util";
89
+
90
+ // ../../packages/api-document-lint/dist/normalize-diagnostics.js
91
+ var EMPTY_RANGE = {
92
+ start: { line: 0, character: 0 },
93
+ end: { line: 0, character: 0 }
94
+ };
95
+ function normalizeDiagnostics(raw) {
96
+ if (!Array.isArray(raw)) {
97
+ return [];
98
+ }
99
+ return raw.filter(isObject).map((item) => {
100
+ const source = item.source;
101
+ return {
102
+ code: isCode(item.code) ? item.code : "",
103
+ message: typeof item.message === "string" ? item.message : "",
104
+ severity: normalizeSeverity(item.severity),
105
+ path: Array.isArray(item.path) ? item.path.filter(isSegment) : [],
106
+ range: normalizeRange(item.range),
107
+ ...typeof source === "string" ? { source } : {}
108
+ };
109
+ });
110
+ }
111
+ function isObject(value) {
112
+ return typeof value === "object" && value !== null;
113
+ }
114
+ function isCode(value) {
115
+ return typeof value === "string" || typeof value === "number";
116
+ }
117
+ function isSegment(value) {
118
+ return typeof value === "string" || typeof value === "number";
119
+ }
120
+ function normalizeRange(range) {
121
+ if (!isObject(range)) {
122
+ return EMPTY_RANGE;
123
+ }
124
+ return {
125
+ start: normalizePosition(range.start),
126
+ end: normalizePosition(range.end)
127
+ };
128
+ }
129
+ function normalizePosition(position) {
130
+ if (!isObject(position)) {
131
+ return { line: 0, character: 0 };
132
+ }
133
+ return {
134
+ line: toCoordinate(position.line),
135
+ character: toCoordinate(position.character)
136
+ };
137
+ }
138
+ function toCoordinate(value) {
139
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : 0;
140
+ }
141
+ function normalizeSeverity(severity) {
142
+ return severity === 1 || severity === 2 || severity === 3 ? severity : 0;
143
+ }
144
+
145
+ // ../../packages/api-document-lint/dist/resolve-binary.js
146
+ import { statSync } from "node:fs";
147
+ import { createRequire } from "node:module";
148
+ import { dirname, join } from "node:path";
149
+ var binaryName = process.platform === "win32" ? "vacuum.exe" : "vacuum";
150
+ function resolveVacuumBinary(override) {
151
+ const explicit = override ?? process.env.VACUUM_BINARY;
152
+ if (explicit) {
153
+ return isFile(explicit) ? ok(explicit) : err(`vacuum binary not found at ${explicit}`);
154
+ }
155
+ const packaged = resolvePackagedBinary();
156
+ if (packaged) {
157
+ return ok(packaged);
158
+ }
159
+ return ok("vacuum");
160
+ }
161
+ function resolvePackagedBinary() {
162
+ try {
163
+ const require2 = createRequire(import.meta.url);
164
+ const packageJsonPath = require2.resolve("@quobix/vacuum/package.json");
165
+ const candidate = join(dirname(packageJsonPath), "bin", binaryName);
166
+ return isFile(candidate) ? candidate : null;
167
+ } catch {
168
+ return null;
169
+ }
170
+ }
171
+ function isFile(path) {
172
+ try {
173
+ return statSync(path, { throwIfNoEntry: false })?.isFile() ?? false;
174
+ } catch {
175
+ return false;
176
+ }
177
+ }
178
+
179
+ // ../../packages/api-document-lint/dist/run-vacuum.js
180
+ var execFileAsync = promisify(execFile);
181
+ var MAX_BUFFER = 64 * 1024 * 1024;
182
+ var TIMEOUT_MS = 6e4;
183
+ async function runVacuum(input, options = {}) {
184
+ if (input.document.trim().length === 0) {
185
+ return ok([]);
186
+ }
187
+ const binary = resolveVacuumBinary(options.binaryPath);
188
+ if (!binary.ok) {
189
+ return binary;
190
+ }
191
+ const directory = await mkdtemp(join2(tmpdir(), "scalar-lint-")).catch(() => null);
192
+ if (directory === null) {
193
+ return err("vacuum lint failed \u2014 could not create a temporary directory");
194
+ }
195
+ const documentPath = join2(directory, "document.yaml");
196
+ const reportPath = join2(directory, "report.json");
197
+ try {
198
+ const wroteDocument = await writeFile(documentPath, input.document, "utf8").then(() => true).catch(() => false);
199
+ if (!wroteDocument) {
200
+ return err("vacuum lint failed \u2014 could not write the document to a temporary file");
201
+ }
202
+ const args = [
203
+ "spectral-report",
204
+ "--no-style",
205
+ "--no-update-check",
206
+ "--skip-check",
207
+ // Match Spectral's working-directory base for document strings.
208
+ "--base",
209
+ process.cwd()
210
+ ];
211
+ if (input.ruleset && input.ruleset.trim().length > 0) {
212
+ const rulesetPath = join2(directory, "ruleset.yaml");
213
+ const wroteRuleset = await writeFile(rulesetPath, input.ruleset, "utf8").then(() => true).catch(() => false);
214
+ if (!wroteRuleset) {
215
+ return err("vacuum lint failed \u2014 could not write the ruleset to a temporary file");
216
+ }
217
+ args.push("--ruleset", rulesetPath);
218
+ }
219
+ args.push(documentPath, reportPath);
220
+ const failure = await execFileAsync(binary.data, args, {
221
+ maxBuffer: MAX_BUFFER,
222
+ timeout: TIMEOUT_MS
223
+ }).then(() => null).catch((error) => error);
224
+ const report = await readFile(reportPath, "utf8").catch(() => null);
225
+ if (report === null) {
226
+ if (failure === null) {
227
+ return err("vacuum ran but its report could not be read");
228
+ }
229
+ return err(`vacuum failed to lint the document \u2014 ${describeFailure(failure)}`);
230
+ }
231
+ const parsed = parseReport(report);
232
+ if (!parsed.ok) {
233
+ return parsed;
234
+ }
235
+ return ok(normalizeDiagnostics(parsed.data));
236
+ } finally {
237
+ await rm(directory, { recursive: true, force: true }).catch(() => void 0);
238
+ }
239
+ }
240
+ function describeFailure(failure) {
241
+ if (failure && typeof failure === "object") {
242
+ const stderr = failure.stderr;
243
+ if (typeof stderr === "string" && stderr.trim().length > 0) {
244
+ return stderr.trim();
245
+ }
246
+ if (failure instanceof Error) {
247
+ return failure.message;
248
+ }
249
+ }
250
+ return "no report was written";
251
+ }
252
+ function parseReport(report) {
253
+ try {
254
+ const parsed = JSON.parse(report);
255
+ if (!Array.isArray(parsed)) {
256
+ return err("vacuum produced a report in an unexpected shape");
257
+ }
258
+ return ok(parsed);
259
+ } catch {
260
+ return err("vacuum produced an unreadable report");
261
+ }
262
+ }
263
+
264
+ // ../../packages/api-document-lint/dist/select-engine.js
265
+ var import_yaml = __toESM(require_dist(), 1);
266
+ function selectEngine(ruleset) {
267
+ if (!ruleset || ruleset.trim().length === 0) {
268
+ return "vacuum";
269
+ }
270
+ const parsed = parseRuleset(ruleset);
271
+ if (parsed === null) {
272
+ return "spectral";
273
+ }
274
+ if (hasCustomFunctions(parsed) || hasRuleCustomizations(parsed) || extendsUninspectableRuleset(parsed) || overridesRequireSpectral(parsed)) {
275
+ return "spectral";
276
+ }
277
+ return "vacuum";
278
+ }
279
+ function overridesRequireSpectral(ruleset) {
280
+ const overrides = ruleset.overrides;
281
+ if (!Array.isArray(overrides)) {
282
+ return false;
283
+ }
284
+ return overrides.some((entry) => isRecord(entry) && (hasCustomFunctions(entry) || hasRuleCustomizations(entry) || extendsUninspectableRuleset(entry)));
285
+ }
286
+ function hasRuleCustomizations(ruleset) {
287
+ return ruleset.rules !== void 0 && (!isRecord(ruleset.rules) || Object.keys(ruleset.rules).length > 0);
288
+ }
289
+ function isRecord(value) {
290
+ return typeof value === "object" && value !== null && !Array.isArray(value);
291
+ }
292
+ function parseRuleset(ruleset) {
293
+ try {
294
+ const value = (0, import_yaml.parse)(ruleset);
295
+ if (value && typeof value === "object" && !Array.isArray(value)) {
296
+ return value;
297
+ }
298
+ return null;
299
+ } catch {
300
+ return null;
301
+ }
302
+ }
303
+ function hasCustomFunctions(ruleset) {
304
+ const functions = ruleset.functions;
305
+ if (Array.isArray(functions) && functions.length > 0) {
306
+ return true;
307
+ }
308
+ return typeof ruleset.functionsDir === "string" && ruleset.functionsDir.length > 0;
309
+ }
310
+ function extendsUninspectableRuleset(ruleset) {
311
+ const extended = ruleset.extends;
312
+ if (extended === void 0) {
313
+ return false;
314
+ }
315
+ const entries = Array.isArray(extended) ? extended : [extended];
316
+ return entries.some((entry) => !isBuiltInRuleset(entry));
317
+ }
318
+ function isBuiltInRuleset(entry) {
319
+ const source = Array.isArray(entry) ? entry[0] : entry;
320
+ return source === "spectral:oas" || source === "spectral:asyncapi";
321
+ }
322
+
323
+ // ../../packages/api-document-lint/dist/lint.js
324
+ async function lint(input, options = {}) {
325
+ const ruleset = input.ruleset && input.ruleset.trim().length > 0 ? input.ruleset : defaultRulesetFor(input.document);
326
+ const resolved = { document: input.document, ruleset };
327
+ const engine = selectEngine(ruleset);
328
+ const diagnostics = engine === "vacuum" ? await runVacuum(resolved, options) : await runSpectral(resolved);
329
+ if (!diagnostics.ok) {
330
+ return diagnostics;
331
+ }
332
+ return ok({ diagnostics: diagnostics.data, engine });
333
+ }
334
+
335
+ // src/domains/document/lint/helpers.ts
336
+ var severityToLabel = (severity) => {
337
+ return {
338
+ 0: "Error",
339
+ 1: "Warning",
340
+ 2: "Information",
341
+ 3: "Hint"
342
+ }[severity];
343
+ };
344
+
345
+ // src/domains/document/lint/action.ts
346
+ async function lintAction(inputArgument, { rule: ruleArgument }) {
347
+ if (!inputArgument) {
348
+ return output.error().title("Invalid argument").message("Please provide a file path").exit("error");
349
+ }
350
+ const specification = await getFileOrUrl(inputArgument);
351
+ const ruleset = ruleArgument ? await getFileOrUrl(ruleArgument) : isAsyncApiContent(specification) ? ASYNCAPI_RULESET : DEFAULT_RULESET;
352
+ const result = await lint({ document: specification, ruleset });
353
+ if (!result.ok) {
354
+ return output.error().title("Failed to lint the document").message(result.error).exit("error");
355
+ }
356
+ const diagnostics = result.data.diagnostics;
357
+ const hasErrors = diagnostics.some((diagnostic) => diagnostic.severity === 0);
358
+ if (!hasErrors) {
359
+ output.info().message(as.green("\u2714 No issues found!")).print();
360
+ } else {
361
+ output.warn().line(as.red("\u2716 Issues found:")).print();
362
+ }
363
+ for (const diagnostic of diagnostics) {
364
+ output.info().line(`${as.yellow("Rule:")} ${as.bold(String(diagnostic.code))}`).line(`${as.yellow("Message:")} ${diagnostic.message}`).line(`${as.yellow("Severity:")} ${severityToLabel(diagnostic.severity)}`).line(
365
+ `${as.yellow("Location:")} ${diagnostic.range.start.line}:${diagnostic.range.start.character} - ${diagnostic.range.end.line}:${diagnostic.range.end.character}`
366
+ ).line(as.gray("---")).print();
367
+ }
368
+ if (hasErrors) {
369
+ output.error().exit("error");
370
+ }
371
+ }
372
+ export {
373
+ lintAction
374
+ };
@@ -0,0 +1,169 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ getFileOrUrl,
4
+ isAsyncApiDocument,
5
+ isDocument,
6
+ loadOpenApiDocument,
7
+ printSpecificationBanner,
8
+ safeNormalize
9
+ } from "./chunk-24WAOKGG.js";
10
+ import {
11
+ watchFile
12
+ } from "./chunk-M37TP6U2.js";
13
+ import "./chunk-4ZDQXWBT.js";
14
+ import "./chunk-VNYE4R7N.js";
15
+ import "./chunk-OQKDBLOZ.js";
16
+ import "./chunk-CISTON3A.js";
17
+ import "./chunk-Q7DOQHZN.js";
18
+ import "./chunk-4ORL4MST.js";
19
+ import {
20
+ output
21
+ } from "./chunk-T5HJUAWB.js";
22
+ import "./chunk-GSGZHE26.js";
23
+ import "./chunk-IKT5F47M.js";
24
+ import "./chunk-3MZYUBJ6.js";
25
+
26
+ // src/domains/document/serve/action.ts
27
+ import { serve } from "@hono/node-server";
28
+ import as from "ansis";
29
+ import { Hono } from "hono";
30
+ import { stream } from "hono/streaming";
31
+
32
+ // src/domains/document/serve/load-document.ts
33
+ import { validate } from "@scalar/asyncapi-validator";
34
+ var loadServeDocument = async (input) => {
35
+ const content = await getFileOrUrl(input);
36
+ const document = safeNormalize(content);
37
+ if (!isDocument(document) || !isAsyncApiDocument(document)) {
38
+ return loadOpenApiDocument(content);
39
+ }
40
+ const result = validate(document);
41
+ if (!result.valid) {
42
+ output.warn().title("File does not match the AsyncAPI specification.").print();
43
+ for (const error of result.errors ?? []) {
44
+ output.warn().title(error.message ?? "Invalid AsyncAPI document").print();
45
+ }
46
+ }
47
+ return {
48
+ valid: result.valid,
49
+ version: result.version,
50
+ specification: document,
51
+ schema: void 0
52
+ };
53
+ };
54
+
55
+ // src/domains/document/serve/action.ts
56
+ async function serveAction(inputArgument, { watch, once, port }) {
57
+ if (!inputArgument) {
58
+ return output.error().title("Invalid argument").message("Please provide a file path").exit("error");
59
+ }
60
+ const result = await loadServeDocument(inputArgument);
61
+ if (result.specification === void 0) {
62
+ return;
63
+ }
64
+ let { specification } = result;
65
+ printServeBanner(result);
66
+ if (!isAsyncApiDocument(specification) && Object.keys(specification.paths ?? {}).length === 0) {
67
+ output.warn().title("Could not find any paths in the OpenAPI file.").print();
68
+ }
69
+ const app = new Hono();
70
+ app.get("/", (c) => {
71
+ return c.html(getHtmlDocument(specification, watch));
72
+ });
73
+ app.use("/__watcher", async (c, next) => {
74
+ c.header("Content-Type", "text/event-stream");
75
+ c.header("Cache-Control", "no-cache");
76
+ c.header("Connection", "keep-alive");
77
+ await next();
78
+ });
79
+ app.get("/__watcher", (c) => {
80
+ return stream(c, async (s) => {
81
+ if (watch) {
82
+ const subscription = await watchFile(inputArgument, async () => {
83
+ const newResult = await loadServeDocument(inputArgument);
84
+ if (newResult.specification && JSON.stringify(specification) !== JSON.stringify(newResult.specification)) {
85
+ output.info().title(
86
+ as.grey(
87
+ `${isAsyncApiDocument(newResult.specification) ? "AsyncAPI" : "OpenAPI"} file modified`
88
+ )
89
+ ).print();
90
+ printServeBanner(newResult);
91
+ specification = newResult.specification;
92
+ s.write("data: file modified\n\n");
93
+ }
94
+ });
95
+ if (subscription) {
96
+ s.onAbort(() => subscription.unsubscribe());
97
+ }
98
+ }
99
+ while (true) {
100
+ await new Promise((resolve) => setTimeout(resolve, 100));
101
+ }
102
+ });
103
+ });
104
+ const server = serve(
105
+ {
106
+ fetch: app.fetch,
107
+ port: port ?? 3e3
108
+ },
109
+ (info) => {
110
+ output.info().line(
111
+ `${as.green.bold("\u279C API Reference Server")} ${as.white(
112
+ "listening on"
113
+ )} ${as.cyan(`http://localhost:${info.port}`)}`
114
+ ).print();
115
+ }
116
+ );
117
+ if (once) {
118
+ setTimeout(() => {
119
+ server.close();
120
+ }, 2e3);
121
+ }
122
+ }
123
+ var getHtmlDocument = (specification, watch = false) => {
124
+ return `<!doctype html>
125
+ <html>
126
+ <head>
127
+ <title>Scalar API Reference</title>
128
+ <meta charset="utf-8" />
129
+ <meta
130
+ name="viewport"
131
+ content="width=device-width, initial-scale=1" />
132
+ <style>
133
+ body {
134
+ margin: 0;
135
+ }
136
+ </style>
137
+ ${watch ? `
138
+ <script>
139
+ const evtSource = new EventSource('__watcher');
140
+ evtSource.onmessage = (event) => {
141
+ console.log(\`message: \${event.data}\`);
142
+ window.location.reload();
143
+ };
144
+ </script>
145
+ ` : ""}
146
+ </head>
147
+ <body>
148
+ <script
149
+ id="api-reference"
150
+ type="application/json"
151
+ data-proxy-url="https://proxy.scalar.com">${JSON.stringify(specification)}</script>
152
+ <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
153
+ </body>
154
+ </html>`;
155
+ };
156
+ var printServeBanner = (result) => {
157
+ if (isAsyncApiDocument(result.specification)) {
158
+ output.info().title(`AsyncAPI${result.version ? ` v${result.version}` : ""}`).print();
159
+ return;
160
+ }
161
+ printSpecificationBanner({
162
+ version: result.version,
163
+ schema: result.valid ? result.schema : void 0
164
+ });
165
+ };
166
+ export {
167
+ getHtmlDocument,
168
+ serveAction
169
+ };