@scalar/cli 2.1.0 → 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.
- package/README.md +28 -24
- package/chunks/{action-CYP4VDK3.js → action-37EV4UHW.js} +12 -35
- package/chunks/{action-MENXFJH3.js → action-4XI7XJR4.js} +9 -9
- package/chunks/{action-H5OHT2GV.js → action-5IU77OII.js} +7 -3
- package/chunks/{action-STIEAXOE.js → action-B3KKREWQ.js} +16 -5
- package/chunks/{action-BYZUBXVB.js → action-CH24QGTE.js} +8 -4
- package/chunks/action-F3UX5E3M.js +522 -0
- package/chunks/{action-GB6DM53B.js → action-FDB7NEOK.js} +21 -10
- package/chunks/action-FIXBOJEW.js +244 -0
- package/chunks/{action-DFKHSDFV.js → action-G26LSVZ7.js} +7 -3
- package/chunks/{action-Q5UJ32D6.js → action-H3RTILLM.js} +1 -1
- package/chunks/{action-GEBRPNRT.js → action-HGBBV353.js} +15 -16
- package/chunks/{action-5R5FDF6S.js → action-IUE4IOWO.js} +67 -22
- package/chunks/{action-TPBKPHNS.js → action-JZLZ7ZAD.js} +22 -22
- package/chunks/action-LA6KVAXQ.js +374 -0
- package/chunks/{action-PVDDRIM6.js → action-M7RQKBSB.js} +65 -26
- package/chunks/{action-F4Y6Q2VB.js → action-MSLBC2SO.js} +21 -21
- package/chunks/{action-BNEGJBUH.js → action-NVSZT2ZD.js} +8 -9
- package/chunks/{action-ANU5HGC4.js → action-OGQSTRMX.js} +17 -14
- package/chunks/{action-CLSD7O2R.js → action-PAGJ5PWC.js} +10 -10
- package/chunks/action-QE2ZQQX7.js +250 -0
- package/chunks/{action-HD2T6BFJ.js → action-QPUSPD5M.js} +10 -10
- package/chunks/{action-45OGQB2M.js → action-R7IMFHQ5.js} +17 -8
- package/chunks/{action-UDZUUJSI.js → action-SH4UUXPL.js} +18 -7
- package/chunks/action-SNLCIBQC.js +84 -0
- package/chunks/{action-C5VB4ITT.js → action-SQG3JAII.js} +36 -18
- package/chunks/action-UZQJNYK4.js +18 -0
- package/chunks/{action-HNKM3Q65.js → action-VC4DCVST.js} +17 -14
- package/chunks/{action-BMFXENMX.js → action-VTVFY2MP.js} +39 -34
- package/chunks/{action-TZ5KGAQT.js → action-WFWYGY7O.js} +17 -14
- package/chunks/{action-W5BATF4Q.js → action-XMNX5ZYT.js} +24 -24
- package/chunks/{agent-XGLOHXNA.js → agent-HCQRMHQ5.js} +25 -5
- package/chunks/asyncapi-QM76O55R.js +105 -0
- package/chunks/{build.action-LKOILPA6.js → build.action-P7FCIMYU.js} +22 -22
- package/chunks/{chunk-23I5PKZZ.js → chunk-24WAOKGG.js} +32 -5
- package/chunks/chunk-3L6DLIXJ.js +25530 -0
- package/chunks/chunk-3ZJYGGAA.js +30 -0
- package/chunks/{chunk-ZTVWAKNJ.js → chunk-4NHMAG6F.js} +1 -1
- package/chunks/{chunk-IX7LJ3AD.js → chunk-4ORL4MST.js} +2 -3
- package/chunks/{chunk-OAXFCOJV.js → chunk-4ZDQXWBT.js} +2 -1
- package/chunks/{chunk-ASMHW5AY.js → chunk-6ZMT63IV.js} +1 -1
- package/chunks/{chunk-P2VH7DOC.js → chunk-7AGLC7WV.js} +6 -6
- package/chunks/{chunk-SXYALPYK.js → chunk-AO3F5XWR.js} +498 -60
- package/chunks/{chunk-B6QZJWCQ.js → chunk-B2MHTD3R.js} +4 -6
- package/chunks/{chunk-4QS7SJTG.js → chunk-CISTON3A.js} +51 -36
- package/chunks/chunk-COBPBRQF.js +25 -0
- package/chunks/{chunk-2BSG2QHO.js → chunk-F467BYYR.js} +133 -20
- package/chunks/{chunk-TLFMATXR.js → chunk-GSGZHE26.js} +33 -25
- package/chunks/{chunk-UPUTMFD4.js → chunk-HCPN3KNF.js} +185 -13
- package/chunks/{chunk-P646T2WH.js → chunk-HPL3ZZ2P.js} +131 -13
- package/chunks/{chunk-H2WRMLYY.js → chunk-IKT5F47M.js} +3571 -7
- package/chunks/{chunk-AHWWJ3MD.js → chunk-K4DTP5TV.js} +1 -1
- package/chunks/{chunk-TQ5XC2E3.js → chunk-LFU5ZUAP.js} +77 -11
- package/chunks/{chunk-5BISXQX4.js → chunk-M37TP6U2.js} +11 -13
- package/chunks/chunk-OQKDBLOZ.js +741 -0
- package/chunks/chunk-P7H7GY5A.js +14 -0
- package/chunks/{chunk-47Y4L5IT.js → chunk-PBXZN65A.js} +1031 -481
- package/chunks/{chunk-HQKBZOYU.js → chunk-PT5TI77I.js} +3 -3
- package/chunks/chunk-Q7DOQHZN.js +404 -0
- package/chunks/{chunk-X4QLDBB5.js → chunk-T5HJUAWB.js} +24 -3
- package/chunks/{chunk-NUXPNUSS.js → chunk-UGGNHILG.js} +1 -1
- package/chunks/{chunk-4DGQIAJX.js → chunk-VNYE4R7N.js} +154 -14
- package/chunks/{chunk-KWOL7A6J.js → chunk-X5T526CE.js} +2 -2
- package/chunks/chunk-XCSR4RIT.js +210 -0
- package/chunks/{chunk-SHSHFGA7.js → chunk-Z2KMGFE6.js} +4 -6
- package/chunks/{create.action-FFQLBSJH.js → create.action-HDD2WUON.js} +22 -22
- package/chunks/{delete.action-STHQHP4F.js → delete.action-7GOZY7ID.js} +22 -22
- package/chunks/{delete.action-QNN3LC2F.js → delete.action-VE66JFDS.js} +22 -22
- package/chunks/{get.action-OTKYOP3Z.js → get.action-2745EB4N.js} +15 -16
- package/chunks/{list.action-KDM5RHEH.js → list.action-3VTXQJRA.js} +19 -19
- package/chunks/{list.action-6I5EZAVB.js → list.action-4QDCZLSZ.js} +22 -22
- package/chunks/{publish.action-PODTVRXS.js → publish.action-ULQLZKWU.js} +44 -36
- package/chunks/{update.action-KMD4ZM75.js → update.action-6QEFP7NA.js} +22 -22
- package/chunks/{update.action-4F6STTEQ.js → update.action-OROQSP2S.js} +22 -22
- package/docs.html +104 -103
- package/index.js +84 -68
- package/package.json +16 -12
- package/chunks/action-CCW66QJN.js +0 -72
- package/chunks/action-CQ56FVES.js +0 -65
- package/chunks/action-JOSVV6YA.js +0 -71
- package/chunks/action-P7LN6FGY.js +0 -13
- package/chunks/action-R6ZZO26F.js +0 -299
- package/chunks/action-TWFJNQ2R.js +0 -95
- package/chunks/chunk-5BPPGTUU.js +0 -463
- package/chunks/chunk-DOVIWNKQ.js +0 -108
- package/chunks/chunk-ISGLWBXZ.js +0 -4265
- package/chunks/chunk-T7MDADON.js +0 -17
- package/chunks/chunk-VTYTPSXO.js +0 -161
|
@@ -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
|
+
};
|
|
@@ -3,18 +3,25 @@ import {
|
|
|
3
3
|
measureTime
|
|
4
4
|
} from "./chunk-KHDYYVYF.js";
|
|
5
5
|
import {
|
|
6
|
-
getFileOrUrl
|
|
7
|
-
|
|
6
|
+
getFileOrUrl,
|
|
7
|
+
isAsyncApiDocument,
|
|
8
|
+
isDocument,
|
|
9
|
+
safeNormalize
|
|
10
|
+
} from "./chunk-24WAOKGG.js";
|
|
8
11
|
import {
|
|
9
12
|
require_dist
|
|
10
13
|
} from "./chunk-K74E42RV.js";
|
|
14
|
+
import "./chunk-CISTON3A.js";
|
|
15
|
+
import "./chunk-Q7DOQHZN.js";
|
|
11
16
|
import {
|
|
12
17
|
isUrl,
|
|
13
18
|
isYamlFileName
|
|
14
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-4ORL4MST.js";
|
|
15
20
|
import {
|
|
16
21
|
output
|
|
17
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-T5HJUAWB.js";
|
|
23
|
+
import "./chunk-GSGZHE26.js";
|
|
24
|
+
import "./chunk-IKT5F47M.js";
|
|
18
25
|
import {
|
|
19
26
|
__toESM
|
|
20
27
|
} from "./chunk-3MZYUBJ6.js";
|
|
@@ -24,9 +31,8 @@ var import_yaml = __toESM(require_dist(), 1);
|
|
|
24
31
|
import fs from "node:fs/promises";
|
|
25
32
|
import { confirm } from "@clack/prompts";
|
|
26
33
|
import as from "ansis";
|
|
27
|
-
import {
|
|
34
|
+
import { upgrade as upgradeAsyncApi } from "@scalar/asyncapi-upgrader";
|
|
28
35
|
import { upgrade } from "@scalar/openapi-upgrader";
|
|
29
|
-
var isDocument = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30
36
|
async function upgradeAction(input, { output: outputFilePath }) {
|
|
31
37
|
if (!input) {
|
|
32
38
|
return output.error().title("Missing input").message("Please provide a file path or URL to upgrade").exit("error");
|
|
@@ -47,22 +53,27 @@ async function upgradeAction(input, { output: outputFilePath }) {
|
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
const outputFileName = outputFilePath ?? input;
|
|
50
|
-
const
|
|
56
|
+
const content = await getFileOrUrl(input);
|
|
57
|
+
const document = safeNormalize(content);
|
|
51
58
|
if (!isDocument(document)) {
|
|
52
59
|
return output.error().title("Invalid input").message(
|
|
53
|
-
"Could not read
|
|
60
|
+
"Could not read a document from the input. Please provide a valid JSON or YAML file."
|
|
54
61
|
).exit("error");
|
|
55
62
|
}
|
|
63
|
+
const isAsyncApi = isAsyncApiDocument(document);
|
|
56
64
|
const { result: upgraded, executionTimeMs } = await measureTime(
|
|
57
|
-
() => upgrade(document, "3.1")
|
|
65
|
+
() => isAsyncApi ? upgradeAsyncApi(document) : upgrade(document, "3.1")
|
|
58
66
|
);
|
|
59
67
|
const isYaml = isYamlFileName(outputFileName);
|
|
60
68
|
await fs.writeFile(
|
|
61
69
|
outputFileName,
|
|
62
70
|
isYaml ? import_yaml.default.stringify(upgraded) : JSON.stringify(upgraded, null, 2)
|
|
63
71
|
);
|
|
72
|
+
const specification = isAsyncApi ? "AsyncAPI" : "OpenAPI";
|
|
73
|
+
const version = upgraded[isAsyncApi ? "asyncapi" : "openapi"];
|
|
74
|
+
const versionSuffix = typeof version === "string" ? ` to version ${version}` : "";
|
|
64
75
|
output.info().message(
|
|
65
|
-
`${as.green(`\u2728
|
|
76
|
+
`${as.green(`\u2728 ${specification} Schema upgraded${versionSuffix}`)} in ${as.white(`${as.bold(`${executionTimeMs.toFixed(2)}`)} ms`)}`
|
|
66
77
|
).print();
|
|
67
78
|
}
|
|
68
79
|
export {
|