@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,86 @@
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 "./chunk-24WAOKGG.js";
6
+ import {
7
+ DEFAULT_FETCH_CONCURRENCY
8
+ } from "./chunk-K4DTP5TV.js";
9
+ import {
10
+ require_dist
11
+ } from "./chunk-K74E42RV.js";
12
+ import "./chunk-CISTON3A.js";
13
+ import "./chunk-Q7DOQHZN.js";
14
+ import {
15
+ isUrl,
16
+ isYamlFileName
17
+ } from "./chunk-4ORL4MST.js";
18
+ import {
19
+ output
20
+ } from "./chunk-T5HJUAWB.js";
21
+ import "./chunk-GSGZHE26.js";
22
+ import "./chunk-IKT5F47M.js";
23
+ import {
24
+ __toESM
25
+ } from "./chunk-3MZYUBJ6.js";
26
+
27
+ // src/domains/document/bundle/action.ts
28
+ var import_yaml = __toESM(require_dist(), 1);
29
+ import fs from "node:fs/promises";
30
+ import path from "node:path";
31
+ import { cwd } from "node:process";
32
+ import { confirm } from "@clack/prompts";
33
+ import as from "ansis";
34
+ import { bundle } from "@scalar/json-magic/bundle";
35
+ import { fetchUrls, readFiles } from "@scalar/json-magic/bundle/plugins/node";
36
+ async function bundleAction(input, {
37
+ output: outputFilePath,
38
+ treeShake,
39
+ urlMap,
40
+ fetchLimit
41
+ }) {
42
+ if (!input) {
43
+ return output.error().title("Missing input").message("Please provide a file path or URL to bundle").exit("error");
44
+ }
45
+ const isUrlInput = isUrl(input);
46
+ if (!outputFilePath) {
47
+ if (isUrlInput) {
48
+ return output.error().message(
49
+ "Please provide an output file using the -o flag when bundling from a URL."
50
+ ).exit("error");
51
+ }
52
+ const shouldContinue = await confirm({
53
+ message: "No output file specified - this will overwrite the input file. Continue?",
54
+ initialValue: false
55
+ });
56
+ if (shouldContinue !== true) {
57
+ return output.error().message("Operation cancelled by user").exit("error");
58
+ }
59
+ }
60
+ const outputFileName = outputFilePath ?? input;
61
+ const isYaml = isYamlFileName(outputFileName);
62
+ const resolvedInput = isUrlInput ? input : path.resolve(cwd(), input);
63
+ const { result, executionTimeMs } = await measureTime(
64
+ () => bundle(resolvedInput, {
65
+ plugins: [
66
+ readFiles(),
67
+ fetchUrls({
68
+ limit: fetchLimit ?? DEFAULT_FETCH_CONCURRENCY
69
+ })
70
+ ],
71
+ treeShake: !!treeShake,
72
+ urlMap: !!urlMap
73
+ })
74
+ );
75
+ await fs.writeFile(
76
+ outputFilePath ?? input,
77
+ isYaml ? import_yaml.default.stringify(result) : JSON.stringify(result),
78
+ "utf8"
79
+ );
80
+ output.info().message(
81
+ `${as.green("\u{1F4E6} OpenAPI Schema bundled")} in ${as.white(`${as.bold(`${Math.round(executionTimeMs)}`)} ms`)}`
82
+ ).print();
83
+ }
84
+ export {
85
+ bundleAction
86
+ };
@@ -0,0 +1,522 @@
1
+ import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
2
+ import {
3
+ getPublishDeploymentUrl
4
+ } from "./chunk-4NHMAG6F.js";
5
+ import {
6
+ readAndParseConfig,
7
+ renderConfigError
8
+ } from "./chunk-7AGLC7WV.js";
9
+ import {
10
+ DEFAULT_ASSETS_DIR
11
+ } from "./chunk-PBXZN65A.js";
12
+ import {
13
+ resolveProject
14
+ } from "./chunk-T7B6WNZC.js";
15
+ import "./chunk-XCSR4RIT.js";
16
+ import {
17
+ apiService
18
+ } from "./chunk-AO3F5XWR.js";
19
+ import {
20
+ getDatabaseClient
21
+ } from "./chunk-Z2KMGFE6.js";
22
+ import "./chunk-HCPN3KNF.js";
23
+ import "./chunk-B2MHTD3R.js";
24
+ import "./chunk-3L6DLIXJ.js";
25
+ import "./chunk-P7H7GY5A.js";
26
+ import "./chunk-HPL3ZZ2P.js";
27
+ import {
28
+ getAuthData
29
+ } from "./chunk-M37TP6U2.js";
30
+ import "./chunk-4ZDQXWBT.js";
31
+ import "./chunk-VNYE4R7N.js";
32
+ import {
33
+ ConfigVersion,
34
+ isGithubBackedDocsProject,
35
+ publishRecordSchema
36
+ } from "./chunk-OQKDBLOZ.js";
37
+ import "./chunk-K74E42RV.js";
38
+ import "./chunk-CISTON3A.js";
39
+ import "./chunk-Q7DOQHZN.js";
40
+ import "./chunk-4ORL4MST.js";
41
+ import {
42
+ output
43
+ } from "./chunk-T5HJUAWB.js";
44
+ import "./chunk-GSGZHE26.js";
45
+ import {
46
+ slugSchema,
47
+ zod_default
48
+ } from "./chunk-IKT5F47M.js";
49
+ import "./chunk-3MZYUBJ6.js";
50
+
51
+ // src/domains/project/publish/action.ts
52
+ import { dirname } from "node:path";
53
+
54
+ // src/domains/project/publish/publish.ts
55
+ import fs from "node:fs";
56
+ import path from "node:path";
57
+ import { Readable } from "node:stream";
58
+ import ignore from "ignore";
59
+ import tar from "tar-fs";
60
+ var DEFAULT_IGNORED_FILES = ["node_modules", ".git"];
61
+ var toPosix = (value) => value.split(path.sep).join("/");
62
+ function isErrnoException(error) {
63
+ return error instanceof Error && "code" in error;
64
+ }
65
+ async function readGitIgnore(configDir) {
66
+ try {
67
+ const gitignore = await fs.promises.readFile(
68
+ path.resolve(configDir, ".gitignore"),
69
+ "utf8"
70
+ );
71
+ return gitignore.replace(/^\uFEFF/, "");
72
+ } catch (err) {
73
+ if (isErrnoException(err) && err.code === "ENOENT") return null;
74
+ throw err;
75
+ }
76
+ }
77
+ async function createGitIgnorer(root) {
78
+ const directories = [root];
79
+ let repositoryRoot = root;
80
+ while (!fs.existsSync(path.join(repositoryRoot, ".git"))) {
81
+ const parent = path.dirname(repositoryRoot);
82
+ if (parent === repositoryRoot) {
83
+ repositoryRoot = root;
84
+ directories.splice(0, directories.length, root);
85
+ break;
86
+ }
87
+ repositoryRoot = parent;
88
+ directories.unshift(parent);
89
+ }
90
+ const matcher = ignore();
91
+ for (const directory of directories) {
92
+ const contents = await readGitIgnore(directory);
93
+ if (!contents) continue;
94
+ const prefix = toPosix(path.relative(repositoryRoot, directory)).replace(
95
+ /[\\*?[\]]/g,
96
+ "\\$&"
97
+ );
98
+ if (!prefix) {
99
+ matcher.add(contents);
100
+ continue;
101
+ }
102
+ for (const line of contents.split(/\r?\n/)) {
103
+ if (!line.trim() || line.startsWith("#")) continue;
104
+ const negative = line.startsWith("!");
105
+ const pattern = (negative ? line.slice(1) : line).replace(
106
+ /(?<!\\) +$/,
107
+ ""
108
+ );
109
+ if (!pattern || pattern === "/") continue;
110
+ const anchored = pattern.replace(/\/$/, "").includes("/");
111
+ const scopedPattern = /^\/?(?:\*\*\/)+$/.test(pattern) ? pattern.replace(/\*\*\/$/, "*/") : pattern;
112
+ matcher.add(
113
+ `${negative ? "!" : ""}/${prefix}/${anchored ? "" : "**/"}${scopedPattern.replace(/^\//, "")}`
114
+ );
115
+ }
116
+ }
117
+ return (name) => matcher.ignores(toPosix(path.relative(repositoryRoot, name)));
118
+ }
119
+ var REMOTE_REFERENCE = /^(https?:)?\/\//i;
120
+ function isLocalReference(value) {
121
+ return typeof value === "string" && value.length > 0 && !REMOTE_REFERENCE.test(value) && !value.includes("://");
122
+ }
123
+ var FILE_BEARING_CONFIG_KEYS = /* @__PURE__ */ new Set([
124
+ "filepath",
125
+ "routes",
126
+ "children",
127
+ "page",
128
+ "path",
129
+ "cssFiles",
130
+ "theme",
131
+ "logo",
132
+ "icon",
133
+ "backgroundImage",
134
+ "assetsDir"
135
+ ]);
136
+ function collectConfigReferences(config) {
137
+ const references = [];
138
+ const isLegacyConfig = config.version === ConfigVersion.V1;
139
+ const add = (value, key) => {
140
+ if (isLocalReference(value)) references.push({ value, key });
141
+ };
142
+ const visit = (node) => {
143
+ if (Array.isArray(node)) {
144
+ node.forEach(visit);
145
+ return;
146
+ }
147
+ if (!node || typeof node !== "object") return;
148
+ const record = node;
149
+ const keys = Object.keys(record);
150
+ for (const [key, value] of Object.entries(record)) {
151
+ if (!FILE_BEARING_CONFIG_KEYS.has(key)) {
152
+ visit(value);
153
+ continue;
154
+ }
155
+ switch (key) {
156
+ // Page/OpenAPI/footer/ruleset sources.
157
+ case "filepath":
158
+ add(value, key);
159
+ break;
160
+ // Navigation records allow a string shorthand: a `routes`/`children`
161
+ // value that is just the page's filepath instead of a page object.
162
+ case "routes":
163
+ case "children":
164
+ if (value && typeof value === "object" && !Array.isArray(value)) {
165
+ for (const entry of Object.values(value)) {
166
+ if (typeof entry === "string") {
167
+ add(entry, key);
168
+ } else {
169
+ visit(entry);
170
+ }
171
+ }
172
+ } else {
173
+ visit(value);
174
+ }
175
+ break;
176
+ // A folder group's root page can also use the string shorthand.
177
+ case "page":
178
+ if (typeof value === "string") {
179
+ add(value, key);
180
+ } else {
181
+ visit(value);
182
+ }
183
+ break;
184
+ // Head styles/scripts are `{ path, tagPosition? }`. A bare `path` on a
185
+ // v2 navigation entry is a URL route, not a file, so match on the
186
+ // shape — but in a legacy config every `path` is a local file.
187
+ case "path":
188
+ if (isLegacyConfig || keys.every((k) => k === "path" || k === "tagPosition"))
189
+ add(value, key);
190
+ break;
191
+ // Legacy theme CSS files are read from disk at build time.
192
+ case "cssFiles":
193
+ if (Array.isArray(value)) {
194
+ for (const entry of value) add(entry, key);
195
+ }
196
+ break;
197
+ // A `.css` value is a local file; anything else is a platform slug.
198
+ case "theme":
199
+ if (typeof value === "string" && value.endsWith(".css"))
200
+ add(value, key);
201
+ break;
202
+ // A logo is a single reference or `{ darkMode, lightMode }`.
203
+ case "logo":
204
+ if (typeof value === "string") {
205
+ add(value, key);
206
+ } else if (value && typeof value === "object") {
207
+ const logo = value;
208
+ add(logo.darkMode, key);
209
+ add(logo.lightMode, key);
210
+ }
211
+ break;
212
+ // An icon can be a slug, a URL, or a local file path.
213
+ case "icon":
214
+ add(value, key);
215
+ break;
216
+ // A page's cover image is resolved as a local asset by preprocess.
217
+ case "backgroundImage":
218
+ add(value, key);
219
+ break;
220
+ // The assets directory ships wholesale — preprocess reads every file
221
+ // under it and fails with ASSET_DIRECTORY_MISSING if it is absent.
222
+ case "assetsDir":
223
+ add(value, key);
224
+ break;
225
+ }
226
+ }
227
+ };
228
+ visit(config);
229
+ return references;
230
+ }
231
+ function collectConfigFilepaths(config) {
232
+ return collectConfigReferences(config).map((reference) => reference.value);
233
+ }
234
+ function getIncludedPaths(root, config) {
235
+ const references = /* @__PURE__ */ new Set();
236
+ const ancestors = /* @__PURE__ */ new Set();
237
+ const resolvedRoot = path.resolve(root);
238
+ const filepaths = collectConfigFilepaths(config);
239
+ if (!isLocalReference(config.assetsDir)) filepaths.push(DEFAULT_ASSETS_DIR);
240
+ for (const filepath of filepaths) {
241
+ const absolute = path.resolve(resolvedRoot, filepath);
242
+ if (absolute !== resolvedRoot && !absolute.startsWith(resolvedRoot + path.sep))
243
+ continue;
244
+ const relative = toPosix(path.relative(resolvedRoot, absolute));
245
+ if (relative === "") continue;
246
+ references.add(relative);
247
+ let parent = path.dirname(relative);
248
+ while (parent && parent !== ".") {
249
+ ancestors.add(parent);
250
+ parent = path.dirname(parent);
251
+ }
252
+ }
253
+ return { references, ancestors };
254
+ }
255
+ function findMissingReferences(root, config) {
256
+ const resolvedRoot = path.resolve(root);
257
+ const missing = [];
258
+ for (const { value: filepath, key } of collectConfigReferences(config)) {
259
+ if (key === "icon" && !path.extname(filepath)) continue;
260
+ const absolute = path.resolve(resolvedRoot, filepath);
261
+ if (absolute !== resolvedRoot && !absolute.startsWith(resolvedRoot + path.sep))
262
+ continue;
263
+ if (!fs.existsSync(absolute)) missing.push(filepath);
264
+ }
265
+ return missing;
266
+ }
267
+ async function createProjectTar(configDir, config) {
268
+ const root = path.resolve(configDir);
269
+ const isGitIgnored = await createGitIgnorer(root);
270
+ const defaultIgnorer = ignore({ allowRelativePaths: true }).add(
271
+ DEFAULT_IGNORED_FILES
272
+ );
273
+ const { references, ancestors } = getIncludedPaths(root, config);
274
+ const isIncluded = (relativeName) => {
275
+ if (ancestors.has(relativeName)) return true;
276
+ for (const reference of references) {
277
+ if (relativeName === reference || relativeName.startsWith(`${reference}/`))
278
+ return true;
279
+ }
280
+ return false;
281
+ };
282
+ return Readable.from(
283
+ tar.pack(root, {
284
+ // tar-fs hands the ignore callback absolute paths, but gitignore rules
285
+ // only match relative POSIX ones — so relativize and normalize first.
286
+ // Matching the relativized path also lets a bare `node_modules` rule swallow
287
+ // every file whenever the packed root itself sits under a `node_modules`
288
+ // directory, as it does in the deployed pnpm isolate.
289
+ ignore: (name) => {
290
+ const relativeName = toPosix(path.relative(root, name));
291
+ if (relativeName === "") return false;
292
+ if (defaultIgnorer.ignores(relativeName)) return true;
293
+ if (isIncluded(relativeName)) return false;
294
+ return isGitIgnored(name);
295
+ },
296
+ dereference: true
297
+ })
298
+ );
299
+ }
300
+ async function publishGithub({
301
+ slug,
302
+ preview,
303
+ apiClient
304
+ }) {
305
+ const publishGithubResult = await apiClient.publish.publishGithub({
306
+ slug,
307
+ preview
308
+ });
309
+ if (publishGithubResult.error) {
310
+ return {
311
+ success: false,
312
+ error: publishGithubResult.message
313
+ };
314
+ }
315
+ return {
316
+ success: true,
317
+ publishUid: publishGithubResult.data.publishUid
318
+ };
319
+ }
320
+ async function publishProject({
321
+ configDir,
322
+ configPath,
323
+ config,
324
+ slug,
325
+ mode
326
+ }) {
327
+ try {
328
+ const root = path.join(configDir, config.root ?? "./");
329
+ const missingReferences = findMissingReferences(root, config);
330
+ if (missingReferences.length > 0) {
331
+ output.warn().title("Some files referenced by your config were not found").message(
332
+ `The build may fail because these paths do not exist:
333
+ ${missingReferences.map((reference) => ` - ${reference}`).join("\n")}`
334
+ ).print();
335
+ }
336
+ const relativeConfigPath = path.relative(root, configPath);
337
+ const apiClient = await apiService();
338
+ const projectTar = await createProjectTar(root, config);
339
+ const result = await apiClient.publish.publishCli({
340
+ tarStream: Readable.toWeb(projectTar),
341
+ slug,
342
+ configPath: relativeConfigPath,
343
+ mode
344
+ });
345
+ if (result.error)
346
+ return {
347
+ success: false,
348
+ error: result.originalError ?? result.message
349
+ };
350
+ return { success: true, publishUid: result.data.publishUid };
351
+ } catch (e) {
352
+ return { success: false, error: e };
353
+ }
354
+ }
355
+ async function publishUnifiedDocsProjectFromGithub({
356
+ slug,
357
+ preview,
358
+ apiClient
359
+ }) {
360
+ const result = await apiClient.publish.publishDocsProject({
361
+ slug,
362
+ preview
363
+ });
364
+ if (result.error) {
365
+ return {
366
+ success: false,
367
+ error: result.message
368
+ };
369
+ }
370
+ return {
371
+ success: true,
372
+ publishUid: result.data.publishUid
373
+ };
374
+ }
375
+
376
+ // src/helpers/utils.ts
377
+ var sleep = (ms) => {
378
+ return new Promise((resolve) => {
379
+ setTimeout(resolve, ms);
380
+ });
381
+ };
382
+
383
+ // src/domains/project/publish/action.ts
384
+ async function publishAction(args) {
385
+ const argsParseResult = zod_default.object({
386
+ slug: slugSchema,
387
+ config: zod_default.string().optional(),
388
+ preview: zod_default.coerce.boolean().default(false),
389
+ github: zod_default.coerce.boolean().default(false)
390
+ }).safeParse(args);
391
+ if (argsParseResult.error)
392
+ return output.error().title("Invalid Arguments").message(argsParseResult.error.issues[0].message).exit("error");
393
+ const {
394
+ config: configPathOption,
395
+ slug,
396
+ preview,
397
+ github
398
+ } = argsParseResult.data;
399
+ const apiClient = await apiService();
400
+ const auth = await getAuthData();
401
+ auth.addEventListener((state) => Object.assign(auth, state));
402
+ if (!slug) {
403
+ return output.error().title("Invalid argument").message("Slug is required. Try passing --slug flag.").exit("error");
404
+ }
405
+ if (github) {
406
+ const resolved = await resolveProject(slug, apiClient);
407
+ if (resolved.kind === "not-found") {
408
+ return output.error().title("Project not found").message(`No project with slug "${slug}" was found for your team.`).exit("error");
409
+ }
410
+ if (resolved.kind === "github") {
411
+ if (!resolved.project.repository) {
412
+ return output.error().title("Your project is not linked to a GitHub repository").message(
413
+ "For a sync publish, please configure your GitHub connection through the dashboard."
414
+ ).exit("error");
415
+ }
416
+ if (resolved.project.repository.expired) {
417
+ return output.error().title("Your GitHub repository access is expired.").message(
418
+ "Please reconnect your project through the Scalar Dashboard to publish via sync."
419
+ ).exit("error");
420
+ }
421
+ const publishResult3 = await publishGithub({ apiClient, slug, preview });
422
+ if (!publishResult3.success) {
423
+ return output.error().title("Could not publish sync project.").message(publishResult3.error).exit("error");
424
+ }
425
+ return await waitForPublish({
426
+ teamUid: auth.teamUid,
427
+ publishUid: publishResult3.publishUid
428
+ });
429
+ }
430
+ if (!isGithubBackedDocsProject(resolved.project)) {
431
+ return output.error().title("Your project is not linked to a GitHub repository").message(
432
+ "For a sync publish, please configure your GitHub connection through the dashboard."
433
+ ).exit("error");
434
+ }
435
+ if (resolved.project.repository.expired) {
436
+ return output.error().title("Your GitHub repository access is expired.").message(
437
+ "Please reconnect your project through the Scalar Dashboard to publish via sync."
438
+ ).exit("error");
439
+ }
440
+ const publishResult2 = await publishUnifiedDocsProjectFromGithub({
441
+ apiClient,
442
+ slug,
443
+ preview
444
+ });
445
+ if (!publishResult2.success) {
446
+ return output.error().title("Could not publish sync project.").message(publishResult2.error).exit("error");
447
+ }
448
+ return await waitForPublish({
449
+ teamUid: auth.teamUid,
450
+ publishUid: publishResult2.publishUid
451
+ });
452
+ }
453
+ const configResult = readAndParseConfig(configPathOption ?? "");
454
+ if (!configResult.success) {
455
+ renderConfigError(configResult.error);
456
+ }
457
+ const { config, filePath: configPath } = configResult;
458
+ const publishResult = await publishProject({
459
+ config,
460
+ slug,
461
+ configDir: dirname(configPath),
462
+ configPath,
463
+ ...preview && { mode: "preview" }
464
+ });
465
+ if (!publishResult.success) {
466
+ return output.error().title("Something went wrong while deploying the project").message(
467
+ publishResult.error instanceof Error ? publishResult.error.message : publishResult.error
468
+ ).exit("error");
469
+ }
470
+ return await waitForPublish({
471
+ teamUid: auth.teamUid,
472
+ publishUid: publishResult.publishUid
473
+ });
474
+ }
475
+ async function waitForPublish({
476
+ teamUid,
477
+ publishUid
478
+ }) {
479
+ const dbClient = await getDatabaseClient();
480
+ const logger = output.info({ animate: true }).loader("Deployment in progress");
481
+ while (true) {
482
+ const deployStatus = await getDeployStatus({
483
+ client: dbClient,
484
+ publishUid,
485
+ teamUid
486
+ });
487
+ if (deployStatus.error === true) {
488
+ return output.error().title(
489
+ "Something went wrong while getting information about the deployment"
490
+ ).exit("error");
491
+ }
492
+ logger.update("loader", 0, { content: deployStatus.data.message });
493
+ if (deployStatus.data.status === "deployed") {
494
+ const deploymentUrl = getPublishDeploymentUrl(deployStatus.data);
495
+ if (deploymentUrl) {
496
+ output.info().line(
497
+ `${deployStatus.data.preview ? "Preview URL" : "Deployment URL"}: ${deploymentUrl}`
498
+ ).print();
499
+ }
500
+ logger.exit("success");
501
+ return;
502
+ }
503
+ if (deployStatus.data.status === "error") {
504
+ logger.exit("error");
505
+ }
506
+ await sleep(3e3);
507
+ }
508
+ }
509
+ async function getDeployStatus({
510
+ client,
511
+ publishUid,
512
+ teamUid
513
+ }) {
514
+ return client.getOne({
515
+ collectionPath: `team/${teamUid}/publish`,
516
+ schema: publishRecordSchema,
517
+ query: { uid: publishUid }
518
+ });
519
+ }
520
+ export {
521
+ publishAction
522
+ };
@@ -0,0 +1,81 @@
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
+ getFileOrUrl,
7
+ isAsyncApiDocument,
8
+ isDocument,
9
+ safeNormalize
10
+ } from "./chunk-24WAOKGG.js";
11
+ import {
12
+ require_dist
13
+ } from "./chunk-K74E42RV.js";
14
+ import "./chunk-CISTON3A.js";
15
+ import "./chunk-Q7DOQHZN.js";
16
+ import {
17
+ isUrl,
18
+ isYamlFileName
19
+ } from "./chunk-4ORL4MST.js";
20
+ import {
21
+ output
22
+ } from "./chunk-T5HJUAWB.js";
23
+ import "./chunk-GSGZHE26.js";
24
+ import "./chunk-IKT5F47M.js";
25
+ import {
26
+ __toESM
27
+ } from "./chunk-3MZYUBJ6.js";
28
+
29
+ // src/domains/document/upgrade/action.ts
30
+ var import_yaml = __toESM(require_dist(), 1);
31
+ import fs from "node:fs/promises";
32
+ import { confirm } from "@clack/prompts";
33
+ import as from "ansis";
34
+ import { upgrade as upgradeAsyncApi } from "@scalar/asyncapi-upgrader";
35
+ import { upgrade } from "@scalar/openapi-upgrader";
36
+ async function upgradeAction(input, { output: outputFilePath }) {
37
+ if (!input) {
38
+ return output.error().title("Missing input").message("Please provide a file path or URL to upgrade").exit("error");
39
+ }
40
+ const isUrlInput = isUrl(input);
41
+ if (!outputFilePath) {
42
+ if (isUrlInput) {
43
+ return output.error().message(
44
+ "Please provide an output file using the -o flag when upgrading from a URL."
45
+ ).exit("error");
46
+ }
47
+ const shouldContinue = await confirm({
48
+ message: "No output file specified - this will overwrite the input file. Continue?",
49
+ initialValue: false
50
+ });
51
+ if (shouldContinue !== true) {
52
+ return output.error().message("Operation cancelled by user").exit("error");
53
+ }
54
+ }
55
+ const outputFileName = outputFilePath ?? input;
56
+ const content = await getFileOrUrl(input);
57
+ const document = safeNormalize(content);
58
+ if (!isDocument(document)) {
59
+ return output.error().title("Invalid input").message(
60
+ "Could not read a document from the input. Please provide a valid JSON or YAML file."
61
+ ).exit("error");
62
+ }
63
+ const isAsyncApi = isAsyncApiDocument(document);
64
+ const { result: upgraded, executionTimeMs } = await measureTime(
65
+ () => isAsyncApi ? upgradeAsyncApi(document) : upgrade(document, "3.1")
66
+ );
67
+ const isYaml = isYamlFileName(outputFileName);
68
+ await fs.writeFile(
69
+ outputFileName,
70
+ isYaml ? import_yaml.default.stringify(upgraded) : JSON.stringify(upgraded, null, 2)
71
+ );
72
+ const specification = isAsyncApi ? "AsyncAPI" : "OpenAPI";
73
+ const version = upgraded[isAsyncApi ? "asyncapi" : "openapi"];
74
+ const versionSuffix = typeof version === "string" ? ` to version ${version}` : "";
75
+ output.info().message(
76
+ `${as.green(`\u2728 ${specification} Schema upgraded${versionSuffix}`)} in ${as.white(`${as.bold(`${executionTimeMs.toFixed(2)}`)} ms`)}`
77
+ ).print();
78
+ }
79
+ export {
80
+ upgradeAction
81
+ };