@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,244 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ measureTime
4
+ } from "./chunk-KHDYYVYF.js";
5
+ import {
6
+ isAsyncApiDocument,
7
+ isDocument
8
+ } from "./chunk-24WAOKGG.js";
9
+ import "./chunk-CISTON3A.js";
10
+ import "./chunk-Q7DOQHZN.js";
11
+ import {
12
+ isUrl
13
+ } from "./chunk-4ORL4MST.js";
14
+ import {
15
+ output
16
+ } from "./chunk-T5HJUAWB.js";
17
+ import "./chunk-GSGZHE26.js";
18
+ import "./chunk-IKT5F47M.js";
19
+ import "./chunk-3MZYUBJ6.js";
20
+
21
+ // src/domains/document/split/action.ts
22
+ import fs2 from "node:fs/promises";
23
+ import path2 from "node:path";
24
+ import { text } from "@clack/prompts";
25
+ import as from "ansis";
26
+ import { bundle } from "@scalar/json-magic/bundle";
27
+ import { fetchUrls, readFiles } from "@scalar/json-magic/bundle/plugins/node";
28
+ import {
29
+ createServerWorkspaceStore,
30
+ WORKSPACE_FILE_NAME
31
+ } from "@scalar/workspace-store/server";
32
+
33
+ // src/domains/document/split/split-asyncapi.ts
34
+ import { createHash } from "node:crypto";
35
+ import fs from "node:fs/promises";
36
+ import path from "node:path";
37
+ import { extensions } from "@scalar/json-magic/bundle";
38
+ import { escapeJsonPointer } from "@scalar/json-magic/helpers/escape-json-pointer";
39
+ async function splitAsyncApi(document, outputPath) {
40
+ const chunks = /* @__PURE__ */ new Map();
41
+ const root = structuredClone(document);
42
+ const segmentNames = /* @__PURE__ */ new Map();
43
+ const usedNames = /* @__PURE__ */ new Set();
44
+ const shorten = (name) => name.length <= 240 ? name : `${name.slice(0, 170)}~5${createHash("sha256").update(name).digest("hex")}`;
45
+ const getFilePath = (segments) => {
46
+ const names = [];
47
+ for (const segment of segments) {
48
+ const directory = names.join("/");
49
+ const key = JSON.stringify([directory, segment]);
50
+ const existing = segmentNames.get(key);
51
+ if (existing !== void 0) {
52
+ names.push(existing);
53
+ continue;
54
+ }
55
+ const escaped = shorten(
56
+ encodeURIComponent(escapeJsonPointer(segment)).replaceAll("%", "~2").replaceAll(".", "~3").replaceAll("*", "~6") || "~7"
57
+ );
58
+ const name = shorten(
59
+ usedNames.has(`${directory}/${escaped}`.toLowerCase()) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i.test(escaped) ? escaped.replace(
60
+ /[a-z]/gi,
61
+ (letter) => `~4${letter.charCodeAt(0).toString(16)}`
62
+ ) : escaped
63
+ );
64
+ segmentNames.set(key, name);
65
+ usedNames.add(`${directory}/${name}`.toLowerCase());
66
+ names.push(name);
67
+ }
68
+ return `chunks/default/${names.join("/")}.json`;
69
+ };
70
+ const extract = (parent, key, segments) => {
71
+ const pointer = `#/${segments.map(escapeJsonPointer).join("/")}`;
72
+ const file = getFilePath(segments);
73
+ chunks.set(pointer, { file, value: parent[key] });
74
+ parent[key] = {
75
+ $ref: `#/${segments.map((segment) => encodeURIComponent(escapeJsonPointer(segment))).join("/")}`
76
+ };
77
+ };
78
+ const extractMap = (value, segments) => {
79
+ if (!isDocument(value)) {
80
+ return;
81
+ }
82
+ for (const key of Object.keys(value)) {
83
+ extract(value, key, [...segments, key]);
84
+ }
85
+ };
86
+ const resolveChannel = (value, seen = /* @__PURE__ */ new Set()) => {
87
+ if (!isDocument(value) || typeof value.$ref !== "string" || !value.$ref.startsWith("#/") || seen.has(value.$ref)) {
88
+ return value;
89
+ }
90
+ seen.add(value.$ref);
91
+ const segments = decodeURIComponent(value.$ref.slice(2)).split("/").map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
92
+ const target = segments.reduce(
93
+ (node, segment) => isDocument(node) && Object.hasOwn(node, segment) ? node[segment] : void 0,
94
+ root
95
+ );
96
+ const resolved = resolveChannel(target, seen);
97
+ if (!isDocument(resolved)) {
98
+ return value;
99
+ }
100
+ const { $ref: _ref, ...siblings } = value;
101
+ return { ...resolved, ...siblings };
102
+ };
103
+ if (isDocument(root.channels)) {
104
+ for (const [name, value] of Object.entries(root.channels)) {
105
+ const channel = structuredClone(resolveChannel(value));
106
+ if (!isDocument(channel)) {
107
+ continue;
108
+ }
109
+ root.channels[name] = channel;
110
+ extractMap(channel.messages, ["channels", name, "messages"]);
111
+ for (const method of ["publish", "subscribe"]) {
112
+ if (isDocument(channel[method])) {
113
+ if (isDocument(channel[method].message)) {
114
+ extract(channel[method], "message", [
115
+ "channels",
116
+ name,
117
+ method,
118
+ "message"
119
+ ]);
120
+ }
121
+ extract(channel, method, ["channels", name, method]);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ extractMap(root.channels, ["channels"]);
127
+ extractMap(root.operations, ["operations"]);
128
+ if (isDocument(root.components)) {
129
+ for (const [type, entries] of Object.entries(root.components)) {
130
+ if (!type.startsWith("x-")) {
131
+ extractMap(entries, ["components", type]);
132
+ }
133
+ }
134
+ }
135
+ if (isDocument(root[extensions.externalDocuments])) {
136
+ extractMap(root[extensions.externalDocuments], [
137
+ extensions.externalDocuments
138
+ ]);
139
+ extract(root, extensions.externalDocuments, [extensions.externalDocuments]);
140
+ delete root[extensions.externalDocuments];
141
+ delete root[extensions.externalDocumentsMappings];
142
+ }
143
+ const pointers = [...chunks.keys()].sort((a, b) => b.length - a.length);
144
+ const rebase = (value, sourceFile) => {
145
+ if (Array.isArray(value)) {
146
+ return value.map((entry) => rebase(entry, sourceFile));
147
+ }
148
+ if (!isDocument(value)) {
149
+ return value;
150
+ }
151
+ return Object.fromEntries(
152
+ Object.entries(value).map(([key, entry]) => {
153
+ if (key !== "$ref" || typeof entry !== "string" || !entry.startsWith("#")) {
154
+ return [key, rebase(entry, sourceFile)];
155
+ }
156
+ const pointer = decodeURIComponent(entry);
157
+ const target = pointers.find(
158
+ (candidate) => pointer === candidate || pointer.startsWith(`${candidate}/`)
159
+ );
160
+ const targetFile = target && chunks.get(target)?.file || "out.json";
161
+ const fragment = target ? `#${pointer.slice(target.length)}` : pointer;
162
+ const relativeFile = path.posix.relative(
163
+ path.posix.dirname(sourceFile),
164
+ targetFile
165
+ );
166
+ return [
167
+ key,
168
+ `${relativeFile.split("/").map(encodeURIComponent).join("/")}#${fragment.slice(1).split("/").map(encodeURIComponent).join("/")}`
169
+ ];
170
+ })
171
+ );
172
+ };
173
+ for (const { file, value } of [
174
+ ...chunks.values(),
175
+ { file: "out.json", value: root }
176
+ ]) {
177
+ const destination = path.join(outputPath, file);
178
+ await fs.mkdir(path.dirname(destination), { recursive: true });
179
+ await fs.writeFile(destination, JSON.stringify(rebase(value, file)));
180
+ }
181
+ }
182
+
183
+ // src/domains/document/split/action.ts
184
+ async function splitAction(input, { output: __outputPath }) {
185
+ if (!input) {
186
+ return output.error().title("Missing input").message("Please provide a file path or URL to split").exit("error");
187
+ }
188
+ const getOutputPath = async () => {
189
+ if (__outputPath !== void 0 && typeof __outputPath === "string") {
190
+ return __outputPath;
191
+ }
192
+ const outputPath2 = await text({
193
+ message: "Where should the chunks be written?",
194
+ defaultValue: "./assets",
195
+ placeholder: "./assets"
196
+ });
197
+ if (typeof outputPath2 !== "string") {
198
+ return output.error().message("Operation cancelled by user").exit("error");
199
+ }
200
+ return outputPath2;
201
+ };
202
+ const outputPath = await getOutputPath();
203
+ const document = await bundle(isUrl(input) ? input : path2.resolve(input), {
204
+ plugins: [readFiles(), fetchUrls()],
205
+ treeShake: false,
206
+ hooks: {
207
+ onResolveError: ({ $ref }) => {
208
+ throw new Error(`Could not resolve reference: ${$ref}`);
209
+ }
210
+ }
211
+ }).catch(() => null);
212
+ if (!isDocument(document)) {
213
+ return output.error().title("Invalid input").message(
214
+ "Could not read an OpenAPI or AsyncAPI document from the input. Please provide a valid JSON or YAML file."
215
+ ).exit("error");
216
+ }
217
+ const { executionTimeMs } = await measureTime(async () => {
218
+ if (isAsyncApiDocument(document)) {
219
+ await splitAsyncApi(document, outputPath);
220
+ return;
221
+ }
222
+ const documentName = "default";
223
+ const store = await createServerWorkspaceStore({
224
+ mode: "static",
225
+ documents: [{ name: documentName, document }],
226
+ // The workspace writer prefixes its directory with cwd, including absolute paths.
227
+ directory: path2.relative(process.cwd(), path2.resolve(outputPath)) || "."
228
+ });
229
+ await store.generateWorkspaceChunks();
230
+ const workspaceFilePath = path2.join(outputPath, WORKSPACE_FILE_NAME);
231
+ const sparseDocument = JSON.parse(
232
+ await fs2.readFile(workspaceFilePath, { encoding: "utf-8" })
233
+ );
234
+ await fs2.writeFile(
235
+ path2.join(outputPath, "out.json"),
236
+ JSON.stringify(sparseDocument.documents[documentName])
237
+ );
238
+ await fs2.rm(workspaceFilePath);
239
+ });
240
+ output.info().line().title(as.green("Document Split Successfully! \u{1F389}")).line().message(`\u2728 Chunks have been generated at: ${as.blue(outputPath)}`).line(`\u23F1\uFE0F Split completed in ${as.yellow(executionTimeMs.toFixed(2))}ms`).line("").print();
241
+ }
242
+ export {
243
+ splitAction
244
+ };
@@ -0,0 +1,40 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ getFileOrUrl
4
+ } from "./chunk-24WAOKGG.js";
5
+ import "./chunk-CISTON3A.js";
6
+ import "./chunk-Q7DOQHZN.js";
7
+ import "./chunk-4ORL4MST.js";
8
+ import {
9
+ output
10
+ } from "./chunk-T5HJUAWB.js";
11
+ import "./chunk-GSGZHE26.js";
12
+ import "./chunk-IKT5F47M.js";
13
+ import "./chunk-3MZYUBJ6.js";
14
+
15
+ // src/domains/document/markdown/action.ts
16
+ import fs from "node:fs";
17
+ import as from "ansis";
18
+ import { createMarkdownFromOpenApi } from "@scalar/openapi-to-markdown";
19
+ async function markdownAction(inputArgument, { output: outputPath }) {
20
+ const startTime = performance.now();
21
+ if (!inputArgument) {
22
+ return output.error().title("Invalid argument").message("Please provide a file path or URL").exit("error");
23
+ }
24
+ const specification = await getFileOrUrl(inputArgument);
25
+ const markdown = await createMarkdownFromOpenApi(specification);
26
+ if (outputPath) {
27
+ fs.writeFileSync(outputPath, markdown, "utf8");
28
+ const endTime = performance.now();
29
+ output.info().line(
30
+ `${as.green("Markdown generated")} ${as.grey(
31
+ `in ${as.white(`${as.bold(`${Math.round(endTime - startTime)}`)} ms`)}`
32
+ )}`
33
+ ).line(`Written to ${as.cyan(outputPath)}`).print();
34
+ return;
35
+ }
36
+ process.stdout.write(markdown);
37
+ }
38
+ export {
39
+ markdownAction
40
+ };
@@ -0,0 +1,46 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ output
4
+ } from "./chunk-T5HJUAWB.js";
5
+ import "./chunk-3MZYUBJ6.js";
6
+
7
+ // src/domains/document/void/action.ts
8
+ import { serve } from "@hono/node-server";
9
+ import as from "ansis";
10
+ import { createVoidServer } from "@scalar/void-server";
11
+ async function voidAction({
12
+ once,
13
+ port
14
+ }) {
15
+ const server = await bootServer({
16
+ port
17
+ });
18
+ if (once) {
19
+ setTimeout(() => {
20
+ server.close();
21
+ }, 2e3);
22
+ }
23
+ }
24
+ var bootServer = async ({
25
+ port
26
+ }) => {
27
+ const app = await createVoidServer();
28
+ return serve(
29
+ {
30
+ fetch: app.fetch,
31
+ port: port ?? 3e3
32
+ },
33
+ (info) => {
34
+ output.info().line(
35
+ `${as.green.bold("\u279C Void Server")} ${as.white(
36
+ "listening on"
37
+ )} ${as.cyan(`http://localhost:${info.port}`)}
38
+ `
39
+ ).print();
40
+ }
41
+ );
42
+ };
43
+ export {
44
+ bootServer,
45
+ voidAction
46
+ };
@@ -0,0 +1,86 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ fetchFromRegistry
4
+ } from "./chunk-UGGNHILG.js";
5
+ import "./chunk-COBPBRQF.js";
6
+ import {
7
+ registry
8
+ } from "./chunk-XCSR4RIT.js";
9
+ import {
10
+ getAuthData
11
+ } from "./chunk-M37TP6U2.js";
12
+ import "./chunk-4ZDQXWBT.js";
13
+ import "./chunk-VNYE4R7N.js";
14
+ import "./chunk-OQKDBLOZ.js";
15
+ import "./chunk-CISTON3A.js";
16
+ import "./chunk-Q7DOQHZN.js";
17
+ import "./chunk-4ORL4MST.js";
18
+ import {
19
+ output
20
+ } from "./chunk-T5HJUAWB.js";
21
+ import "./chunk-GSGZHE26.js";
22
+ import {
23
+ docVersionSchema,
24
+ external_exports
25
+ } from "./chunk-IKT5F47M.js";
26
+ import "./chunk-3MZYUBJ6.js";
27
+
28
+ // src/domains/registry/get/action.ts
29
+ import fs from "node:fs/promises";
30
+ var versionSchema = external_exports.union([docVersionSchema, external_exports.literal("latest")]);
31
+ async function getAction(namespace, slug, args) {
32
+ if (!namespace) {
33
+ output.error().title("Invalid input").message("Please provide namespace of the document").exit("error");
34
+ return;
35
+ }
36
+ if (!slug) {
37
+ output.error().title("Invalid input").message("Please provide slug of the document").exit("error");
38
+ return;
39
+ }
40
+ const result = external_exports.object({
41
+ version: versionSchema,
42
+ format: external_exports.enum(["json", "yaml"]),
43
+ output: external_exports.string().min(1).optional()
44
+ }).safeParse({
45
+ version: args.version ?? "latest",
46
+ format: args.format,
47
+ output: args.output
48
+ });
49
+ if (result.error) {
50
+ output.error().title("Invalid input").message(result.error.issues[0].message).exit("error");
51
+ return;
52
+ }
53
+ const auth = await getAuthData();
54
+ auth.addEventListener((state) => Object.assign(auth, state));
55
+ const fetchResult = await fetchFromRegistry(
56
+ registry(namespace).apis(slug).url({
57
+ version: result.data.version,
58
+ format: result.data.format
59
+ }),
60
+ auth.accessToken
61
+ );
62
+ if (fetchResult.error) {
63
+ output.error().title("Unable to download document").message(fetchResult.message).exit("error");
64
+ return;
65
+ }
66
+ const document = fetchResult.data;
67
+ const withTrailingNewline = document.endsWith("\n") ? document : `${document}
68
+ `;
69
+ if (result.data.output) {
70
+ try {
71
+ await fs.writeFile(result.data.output, withTrailingNewline, "utf8");
72
+ } catch (error) {
73
+ const message = error instanceof Error && error.message.length > 0 ? error.message : `Could not write to ${result.data.output}.`;
74
+ output.error().title("Unable to write document to file").message(message).exit("error");
75
+ return;
76
+ }
77
+ output.info().line(
78
+ `Downloaded ${namespace}/${slug}@${result.data.version} (${result.data.format})`
79
+ ).line(`Written to ${result.data.output}`).print();
80
+ return;
81
+ }
82
+ process.stdout.write(withTrailingNewline);
83
+ }
84
+ export {
85
+ getAction
86
+ };