@scalar/cli 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/chunks/action-45OGQB2M.js +138 -0
- package/chunks/action-5R5FDF6S.js +2097 -0
- package/chunks/action-ANU5HGC4.js +34 -0
- package/chunks/action-BMFXENMX.js +176 -0
- package/chunks/action-BNEGJBUH.js +38 -0
- package/chunks/action-BYZUBXVB.js +82 -0
- package/chunks/action-C5VB4ITT.js +132 -0
- package/chunks/action-CCW66QJN.js +72 -0
- package/chunks/action-CLSD7O2R.js +60 -0
- package/chunks/action-CQ56FVES.js +65 -0
- package/chunks/action-CYP4VDK3.js +148 -0
- package/chunks/action-DFKHSDFV.js +36 -0
- package/chunks/action-F4Y6Q2VB.js +92 -0
- package/chunks/action-GB6DM53B.js +70 -0
- package/chunks/action-GEBRPNRT.js +87 -0
- package/chunks/action-H5OHT2GV.js +56 -0
- package/chunks/action-HD2T6BFJ.js +54 -0
- package/chunks/action-HNKM3Q65.js +65 -0
- package/chunks/action-JOSVV6YA.js +71 -0
- package/chunks/action-MENXFJH3.js +204 -0
- package/chunks/action-P7LN6FGY.js +13 -0
- package/chunks/action-PVDDRIM6.js +130 -0
- package/chunks/action-Q5UJ32D6.js +46 -0
- package/chunks/action-R6ZZO26F.js +299 -0
- package/chunks/action-STIEAXOE.js +53 -0
- package/chunks/action-TPBKPHNS.js +110 -0
- package/chunks/action-TWFJNQ2R.js +95 -0
- package/chunks/action-TZ5KGAQT.js +64 -0
- package/chunks/action-UDZUUJSI.js +49 -0
- package/chunks/action-W5BATF4Q.js +197 -0
- package/chunks/agent-XGLOHXNA.js +112 -0
- package/chunks/build.action-LKOILPA6.js +108 -0
- package/chunks/chunk-23I5PKZZ.js +78 -0
- package/chunks/chunk-2BSG2QHO.js +455 -0
- package/chunks/chunk-3MZYUBJ6.js +49 -0
- package/chunks/chunk-47Y4L5IT.js +63361 -0
- package/chunks/chunk-4DGQIAJX.js +359 -0
- package/chunks/chunk-4QS7SJTG.js +138 -0
- package/chunks/chunk-5BISXQX4.js +447 -0
- package/chunks/chunk-5BPPGTUU.js +463 -0
- package/chunks/chunk-AEFPCC4U.js +16 -0
- package/chunks/chunk-AHWWJ3MD.js +32 -0
- package/chunks/chunk-ASMHW5AY.js +19 -0
- package/chunks/chunk-B6QZJWCQ.js +92 -0
- package/chunks/chunk-DOVIWNKQ.js +108 -0
- package/chunks/chunk-H2WRMLYY.js +13780 -0
- package/chunks/chunk-HQKBZOYU.js +34 -0
- package/chunks/chunk-ISGLWBXZ.js +4265 -0
- package/chunks/chunk-IX7LJ3AD.js +17 -0
- package/chunks/chunk-JFIXNSPP.js +26 -0
- package/chunks/chunk-K74E42RV.js +7311 -0
- package/chunks/chunk-KHDYYVYF.js +16 -0
- package/chunks/chunk-KWOL7A6J.js +23 -0
- package/chunks/chunk-NUXPNUSS.js +38 -0
- package/chunks/chunk-OAXFCOJV.js +25 -0
- package/chunks/chunk-P2VH7DOC.js +107 -0
- package/chunks/chunk-P646T2WH.js +1608 -0
- package/chunks/chunk-SHSHFGA7.js +297 -0
- package/chunks/chunk-SXYALPYK.js +2709 -0
- package/chunks/chunk-T7B6WNZC.js +18 -0
- package/chunks/chunk-T7MDADON.js +17 -0
- package/chunks/chunk-TLFMATXR.js +344 -0
- package/chunks/chunk-TQ5XC2E3.js +284 -0
- package/chunks/chunk-UPUTMFD4.js +465 -0
- package/chunks/chunk-VTYTPSXO.js +161 -0
- package/chunks/chunk-X4QLDBB5.js +221 -0
- package/chunks/chunk-ZTVWAKNJ.js +21 -0
- package/chunks/create.action-FFQLBSJH.js +108 -0
- package/chunks/delete.action-QNN3LC2F.js +96 -0
- package/chunks/delete.action-STHQHP4F.js +88 -0
- package/chunks/get.action-OTKYOP3Z.js +87 -0
- package/chunks/list.action-6I5EZAVB.js +95 -0
- package/chunks/list.action-KDM5RHEH.js +116 -0
- package/chunks/publish.action-PODTVRXS.js +182 -0
- package/chunks/update.action-4F6STTEQ.js +101 -0
- package/chunks/update.action-KMD4ZM75.js +95 -0
- package/docs.html +310 -209
- package/index.js +645 -99061
- package/package.json +13 -11
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
openBrowser
|
|
4
|
+
} from "./chunk-JFIXNSPP.js";
|
|
5
|
+
import {
|
|
6
|
+
accessTokenPayloadSchema,
|
|
7
|
+
decode,
|
|
8
|
+
generateAccessByPersonalToken,
|
|
9
|
+
setAuthData,
|
|
10
|
+
tokenResponseSchema
|
|
11
|
+
} from "./chunk-5BISXQX4.js";
|
|
12
|
+
import {
|
|
13
|
+
config
|
|
14
|
+
} from "./chunk-OAXFCOJV.js";
|
|
15
|
+
import "./chunk-4DGQIAJX.js";
|
|
16
|
+
import "./chunk-ISGLWBXZ.js";
|
|
17
|
+
import {
|
|
18
|
+
external_exports
|
|
19
|
+
} from "./chunk-H2WRMLYY.js";
|
|
20
|
+
import "./chunk-IX7LJ3AD.js";
|
|
21
|
+
import {
|
|
22
|
+
output
|
|
23
|
+
} from "./chunk-X4QLDBB5.js";
|
|
24
|
+
import "./chunk-3MZYUBJ6.js";
|
|
25
|
+
|
|
26
|
+
// src/domains/auth/login/action.ts
|
|
27
|
+
import as2 from "ansis";
|
|
28
|
+
|
|
29
|
+
// ../../packages/mongobase-client/dist/auth/node/exchange-callback-server.js
|
|
30
|
+
import getPort from "get-port";
|
|
31
|
+
var generateTokenCallbackEndpoint = async (exchangeUrl) => {
|
|
32
|
+
const http = await import("node:http");
|
|
33
|
+
const port = await getPort();
|
|
34
|
+
const server = http.createServer();
|
|
35
|
+
server.listen({ port, host: "127.0.0.1" });
|
|
36
|
+
const getTokens = async () => {
|
|
37
|
+
const resultPromise = new Promise((resolve) => {
|
|
38
|
+
server.on("request", async (req, res) => {
|
|
39
|
+
const corsOrigin = `http://127.0.0.1:${port}`;
|
|
40
|
+
const errorResponse = (message, code) => {
|
|
41
|
+
res.writeHead(code, {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
"Access-Control-Allow-Origin": corsOrigin
|
|
44
|
+
});
|
|
45
|
+
res.end(JSON.stringify({
|
|
46
|
+
success: false,
|
|
47
|
+
error: true,
|
|
48
|
+
message
|
|
49
|
+
}));
|
|
50
|
+
server.close();
|
|
51
|
+
return resolve({ data: null, error: true });
|
|
52
|
+
};
|
|
53
|
+
if (req.method !== "POST") {
|
|
54
|
+
return errorResponse("Method not allowed", 405);
|
|
55
|
+
}
|
|
56
|
+
const url = new URL(`http://localhost:${port}${req.url}`);
|
|
57
|
+
const exchangeToken = url.searchParams.get("exchangeToken");
|
|
58
|
+
if (!exchangeToken) {
|
|
59
|
+
return errorResponse("Missing exchange token", 400);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const tokens = await exchangeTokenForAccess(exchangeUrl, exchangeToken);
|
|
63
|
+
if (tokens) {
|
|
64
|
+
res.writeHead(200, {
|
|
65
|
+
"Content-Type": "application/json",
|
|
66
|
+
"Access-Control-Allow-Origin": corsOrigin
|
|
67
|
+
});
|
|
68
|
+
res.end(JSON.stringify({
|
|
69
|
+
success: true,
|
|
70
|
+
error: false,
|
|
71
|
+
message: "Token exchanged. "
|
|
72
|
+
}));
|
|
73
|
+
server.close();
|
|
74
|
+
return resolve({ data: tokens, error: false });
|
|
75
|
+
}
|
|
76
|
+
return errorResponse("Failed to exchange token", 400);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.error(err);
|
|
79
|
+
return errorResponse("Internal server error", 500);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
server.close();
|
|
86
|
+
resolve({ data: null, error: true });
|
|
87
|
+
}, 3 * 60 * 1e3);
|
|
88
|
+
});
|
|
89
|
+
return Promise.race([resultPromise, timeoutPromise]);
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
port,
|
|
93
|
+
cancel: () => server.close(),
|
|
94
|
+
getTokens
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
var exchangeTokenForAccess = async (serverUrl, exchangeToken) => {
|
|
98
|
+
const result = await fetch(serverUrl, {
|
|
99
|
+
method: "POST",
|
|
100
|
+
headers: {
|
|
101
|
+
"Content-Type": "application/json"
|
|
102
|
+
},
|
|
103
|
+
body: JSON.stringify({
|
|
104
|
+
exchangeToken
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
if (result.ok) {
|
|
108
|
+
return tokenResponseSchema.parse(await result.json());
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/domains/auth/login/helpers/messages.ts
|
|
114
|
+
import as from "ansis";
|
|
115
|
+
function loggedInMessage(userIdentifier) {
|
|
116
|
+
if (process.env.CI || !userIdentifier)
|
|
117
|
+
return "Successfully authenticated to Scalar CLI";
|
|
118
|
+
return `Successfully authenticated to Scalar CLI as ${as.cyan(userIdentifier)}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/domains/auth/login/helpers/email-pass-auth.ts
|
|
122
|
+
var tokenResponseSchema2 = external_exports.object({
|
|
123
|
+
accessToken: external_exports.string(),
|
|
124
|
+
refreshToken: external_exports.string()
|
|
125
|
+
});
|
|
126
|
+
var emailPasswordAuth = async ({
|
|
127
|
+
email,
|
|
128
|
+
password
|
|
129
|
+
}) => {
|
|
130
|
+
const result = await fetch(`${config.services.api}/core/login/email`, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers: {
|
|
133
|
+
"Content-Type": "application/json"
|
|
134
|
+
},
|
|
135
|
+
credentials: "include",
|
|
136
|
+
body: JSON.stringify({
|
|
137
|
+
email,
|
|
138
|
+
password
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
if (!result.ok) {
|
|
142
|
+
const data = await result.json();
|
|
143
|
+
throw new Error(data.message ?? "Could not login with email");
|
|
144
|
+
}
|
|
145
|
+
return tokenResponseSchema2.parse(await result.json());
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/domains/auth/login/action.ts
|
|
149
|
+
async function loginAction({
|
|
150
|
+
email,
|
|
151
|
+
password,
|
|
152
|
+
token: _token
|
|
153
|
+
}) {
|
|
154
|
+
const token = process.env.SCALAR_API_KEY || _token;
|
|
155
|
+
if (token) {
|
|
156
|
+
try {
|
|
157
|
+
const { accessToken } = await generateAccessByPersonalToken({
|
|
158
|
+
personalToken: token
|
|
159
|
+
});
|
|
160
|
+
const { email: userEmail } = decode(accessToken, accessTokenPayloadSchema);
|
|
161
|
+
output.info().message(loggedInMessage(userEmail)).print();
|
|
162
|
+
} catch (err) {
|
|
163
|
+
return output.error().title("Invalid token").message(err.message ?? "Please provide a valid personal token").exit("error");
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (email || password) {
|
|
168
|
+
if (!email || !password) {
|
|
169
|
+
return output.error().title("Please provide both email and password combination").message().exit("error");
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const { accessToken, refreshToken } = await emailPasswordAuth({
|
|
173
|
+
email,
|
|
174
|
+
password
|
|
175
|
+
});
|
|
176
|
+
await setAuthData({ accessToken, refreshToken });
|
|
177
|
+
output.info().message(loggedInMessage(email)).print();
|
|
178
|
+
} catch (err) {
|
|
179
|
+
output.error().title(err.message).print();
|
|
180
|
+
}
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const { port, getTokens } = await generateTokenCallbackEndpoint(
|
|
184
|
+
`${config.services.api}/core/login/exchange`
|
|
185
|
+
);
|
|
186
|
+
const loginUrl = `${config.projects.dashboard}/login?externalRedirect=local&port=${port}`;
|
|
187
|
+
output.info().message(`Please follow the link to login: ${as2.cyan(loginUrl)}`).print();
|
|
188
|
+
openBrowser(loginUrl);
|
|
189
|
+
try {
|
|
190
|
+
const tokenResult = await getTokens();
|
|
191
|
+
if (tokenResult.error) throw Error("Unable to exchange token");
|
|
192
|
+
await setAuthData(tokenResult.data);
|
|
193
|
+
const { email: userEmail } = decode(
|
|
194
|
+
tokenResult.data.accessToken,
|
|
195
|
+
accessTokenPayloadSchema
|
|
196
|
+
);
|
|
197
|
+
return output.info().message(loggedInMessage(userEmail)).exit("success");
|
|
198
|
+
} catch {
|
|
199
|
+
return output.error().title("Something went wrong. Please try again.").exit("error");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export {
|
|
203
|
+
loginAction
|
|
204
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
downloadIsolate,
|
|
4
|
+
updateIsolate
|
|
5
|
+
} from "./chunk-TQ5XC2E3.js";
|
|
6
|
+
import "./chunk-KWOL7A6J.js";
|
|
7
|
+
import "./chunk-OAXFCOJV.js";
|
|
8
|
+
import "./chunk-X4QLDBB5.js";
|
|
9
|
+
import "./chunk-3MZYUBJ6.js";
|
|
10
|
+
export {
|
|
11
|
+
downloadIsolate,
|
|
12
|
+
updateIsolate
|
|
13
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
loadOpenApiFile,
|
|
4
|
+
printSpecificationBanner
|
|
5
|
+
} from "./chunk-23I5PKZZ.js";
|
|
6
|
+
import {
|
|
7
|
+
watchFile
|
|
8
|
+
} from "./chunk-5BISXQX4.js";
|
|
9
|
+
import "./chunk-OAXFCOJV.js";
|
|
10
|
+
import "./chunk-4DGQIAJX.js";
|
|
11
|
+
import "./chunk-ISGLWBXZ.js";
|
|
12
|
+
import "./chunk-H2WRMLYY.js";
|
|
13
|
+
import "./chunk-IX7LJ3AD.js";
|
|
14
|
+
import {
|
|
15
|
+
output
|
|
16
|
+
} from "./chunk-X4QLDBB5.js";
|
|
17
|
+
import "./chunk-3MZYUBJ6.js";
|
|
18
|
+
|
|
19
|
+
// src/domains/document/serve/action.ts
|
|
20
|
+
import { serve } from "@hono/node-server";
|
|
21
|
+
import as from "ansis";
|
|
22
|
+
import { Hono } from "hono";
|
|
23
|
+
import { stream } from "hono/streaming";
|
|
24
|
+
async function serveAction(inputArgument, { watch, once, port }) {
|
|
25
|
+
if (!inputArgument) {
|
|
26
|
+
return output.error().title("Invalid argument").message("Please provide a file path").exit("error");
|
|
27
|
+
}
|
|
28
|
+
const result = await loadOpenApiFile(inputArgument);
|
|
29
|
+
if (!result.valid) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let { specification } = result;
|
|
33
|
+
printSpecificationBanner({
|
|
34
|
+
version: result.version,
|
|
35
|
+
schema: result.schema
|
|
36
|
+
});
|
|
37
|
+
if (specification?.paths === void 0 || Object.keys(specification?.paths).length === 0) {
|
|
38
|
+
output.warn().title("Could not find any paths in the OpenAPI file.").print();
|
|
39
|
+
}
|
|
40
|
+
const app = new Hono();
|
|
41
|
+
app.get("/", (c) => {
|
|
42
|
+
return c.html(getHtmlDocument(specification ?? {}, watch));
|
|
43
|
+
});
|
|
44
|
+
app.use("/__watcher", async (c, next) => {
|
|
45
|
+
c.header("Content-Type", "text/event-stream");
|
|
46
|
+
c.header("Cache-Control", "no-cache");
|
|
47
|
+
c.header("Connection", "keep-alive");
|
|
48
|
+
await next();
|
|
49
|
+
});
|
|
50
|
+
app.get("/__watcher", (c) => {
|
|
51
|
+
return stream(c, async (s) => {
|
|
52
|
+
if (watch) {
|
|
53
|
+
const subscription = await watchFile(inputArgument, async () => {
|
|
54
|
+
const newResult = await loadOpenApiFile(inputArgument);
|
|
55
|
+
const specificationHasChanged = newResult?.specification && JSON.stringify(specification) !== JSON.stringify(newResult.specification);
|
|
56
|
+
if (specificationHasChanged && newResult.valid) {
|
|
57
|
+
output.info().title(as.grey("OpenAPI file modified")).print();
|
|
58
|
+
printSpecificationBanner({
|
|
59
|
+
version: newResult.version,
|
|
60
|
+
schema: newResult.schema
|
|
61
|
+
});
|
|
62
|
+
specification = newResult.specification;
|
|
63
|
+
s.write("data: file modified\n\n");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
if (subscription) {
|
|
67
|
+
s.onAbort(() => subscription.unsubscribe());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
while (true) {
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
const server = serve(
|
|
76
|
+
{
|
|
77
|
+
fetch: app.fetch,
|
|
78
|
+
port: port ?? 3e3
|
|
79
|
+
},
|
|
80
|
+
(info) => {
|
|
81
|
+
output.info().line(
|
|
82
|
+
`${as.green.bold("\u279C API Reference Server")} ${as.white(
|
|
83
|
+
"listening on"
|
|
84
|
+
)} ${as.cyan(`http://localhost:${info.port}`)}`
|
|
85
|
+
).print();
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
if (once) {
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
server.close();
|
|
91
|
+
}, 2e3);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
var getHtmlDocument = (specification, watch = false) => {
|
|
95
|
+
return `<!doctype html>
|
|
96
|
+
<html>
|
|
97
|
+
<head>
|
|
98
|
+
<title>Scalar API Reference</title>
|
|
99
|
+
<meta charset="utf-8" />
|
|
100
|
+
<meta
|
|
101
|
+
name="viewport"
|
|
102
|
+
content="width=device-width, initial-scale=1" />
|
|
103
|
+
<style>
|
|
104
|
+
body {
|
|
105
|
+
margin: 0;
|
|
106
|
+
}
|
|
107
|
+
</style>
|
|
108
|
+
${watch ? `
|
|
109
|
+
<script>
|
|
110
|
+
const evtSource = new EventSource('__watcher');
|
|
111
|
+
evtSource.onmessage = (event) => {
|
|
112
|
+
console.log(\`message: \${event.data}\`);
|
|
113
|
+
window.location.reload();
|
|
114
|
+
};
|
|
115
|
+
</script>
|
|
116
|
+
` : ""}
|
|
117
|
+
</head>
|
|
118
|
+
<body>
|
|
119
|
+
<script
|
|
120
|
+
id="api-reference"
|
|
121
|
+
type="application/json"
|
|
122
|
+
data-proxy-url="https://proxy.scalar.com">${JSON.stringify(specification)}</script>
|
|
123
|
+
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
|
124
|
+
</body>
|
|
125
|
+
</html>`;
|
|
126
|
+
};
|
|
127
|
+
export {
|
|
128
|
+
getHtmlDocument,
|
|
129
|
+
serveAction
|
|
130
|
+
};
|
|
@@ -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-X4QLDBB5.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,299 @@
|
|
|
1
|
+
import { createRequire as $$cR } from "node:module"; const require = $$cR(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
getPublishDeploymentUrl
|
|
4
|
+
} from "./chunk-ZTVWAKNJ.js";
|
|
5
|
+
import {
|
|
6
|
+
readAndParseConfig,
|
|
7
|
+
renderConfigError
|
|
8
|
+
} from "./chunk-P2VH7DOC.js";
|
|
9
|
+
import {
|
|
10
|
+
resolveProject
|
|
11
|
+
} from "./chunk-T7B6WNZC.js";
|
|
12
|
+
import "./chunk-47Y4L5IT.js";
|
|
13
|
+
import "./chunk-DOVIWNKQ.js";
|
|
14
|
+
import {
|
|
15
|
+
apiService
|
|
16
|
+
} from "./chunk-SXYALPYK.js";
|
|
17
|
+
import {
|
|
18
|
+
getDatabaseClient
|
|
19
|
+
} from "./chunk-SHSHFGA7.js";
|
|
20
|
+
import "./chunk-UPUTMFD4.js";
|
|
21
|
+
import "./chunk-B6QZJWCQ.js";
|
|
22
|
+
import "./chunk-5BPPGTUU.js";
|
|
23
|
+
import "./chunk-P646T2WH.js";
|
|
24
|
+
import "./chunk-4QS7SJTG.js";
|
|
25
|
+
import "./chunk-VTYTPSXO.js";
|
|
26
|
+
import {
|
|
27
|
+
getAuthData
|
|
28
|
+
} from "./chunk-5BISXQX4.js";
|
|
29
|
+
import "./chunk-OAXFCOJV.js";
|
|
30
|
+
import "./chunk-TLFMATXR.js";
|
|
31
|
+
import "./chunk-4DGQIAJX.js";
|
|
32
|
+
import {
|
|
33
|
+
isGithubBackedDocsProject,
|
|
34
|
+
publishRecordSchema,
|
|
35
|
+
slugSchema
|
|
36
|
+
} from "./chunk-ISGLWBXZ.js";
|
|
37
|
+
import {
|
|
38
|
+
zod_default
|
|
39
|
+
} from "./chunk-H2WRMLYY.js";
|
|
40
|
+
import "./chunk-K74E42RV.js";
|
|
41
|
+
import "./chunk-IX7LJ3AD.js";
|
|
42
|
+
import {
|
|
43
|
+
output
|
|
44
|
+
} from "./chunk-X4QLDBB5.js";
|
|
45
|
+
import "./chunk-3MZYUBJ6.js";
|
|
46
|
+
|
|
47
|
+
// src/domains/project/publish/action.ts
|
|
48
|
+
import { dirname } from "node:path";
|
|
49
|
+
|
|
50
|
+
// src/domains/project/publish/publish.ts
|
|
51
|
+
import fs from "node:fs";
|
|
52
|
+
import path from "node:path";
|
|
53
|
+
import { Readable } from "node:stream";
|
|
54
|
+
import ignore from "ignore";
|
|
55
|
+
import tar from "tar-fs";
|
|
56
|
+
var DEFAULT_IGNORED_FILES = ["node_modules", ".git"];
|
|
57
|
+
function isErrnoException(error) {
|
|
58
|
+
return error instanceof Error && "code" in error;
|
|
59
|
+
}
|
|
60
|
+
async function readGitIgnore(configDir) {
|
|
61
|
+
try {
|
|
62
|
+
const gitignore = await fs.promises.readFile(
|
|
63
|
+
path.resolve(configDir, ".gitignore"),
|
|
64
|
+
"utf8"
|
|
65
|
+
);
|
|
66
|
+
return gitignore;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
if (isErrnoException(err) && err.code === "ENOENT") return null;
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function createProjectTar(configDir) {
|
|
73
|
+
const ignorer = ignore({ allowRelativePaths: true });
|
|
74
|
+
const gitignore = await readGitIgnore(configDir);
|
|
75
|
+
if (gitignore) ignorer.add(gitignore);
|
|
76
|
+
ignorer.add(DEFAULT_IGNORED_FILES);
|
|
77
|
+
return Readable.from(
|
|
78
|
+
tar.pack(configDir, {
|
|
79
|
+
ignore: (name) => ignorer.ignores(name),
|
|
80
|
+
dereference: true
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
async function publishGithub({
|
|
85
|
+
slug,
|
|
86
|
+
preview,
|
|
87
|
+
apiClient
|
|
88
|
+
}) {
|
|
89
|
+
const publishGithubResult = await apiClient.publish.publishGithub({
|
|
90
|
+
slug,
|
|
91
|
+
preview
|
|
92
|
+
});
|
|
93
|
+
if (publishGithubResult.error) {
|
|
94
|
+
return {
|
|
95
|
+
success: false,
|
|
96
|
+
error: publishGithubResult.message
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
publishUid: publishGithubResult.data.publishUid
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
async function publishProject({
|
|
105
|
+
configDir,
|
|
106
|
+
configPath,
|
|
107
|
+
config,
|
|
108
|
+
slug,
|
|
109
|
+
mode
|
|
110
|
+
}) {
|
|
111
|
+
try {
|
|
112
|
+
const root = path.join(configDir, config.root ?? "./");
|
|
113
|
+
const relativeConfigPath = path.relative(root, configPath);
|
|
114
|
+
const apiClient = await apiService();
|
|
115
|
+
const projectTar = await createProjectTar(root);
|
|
116
|
+
const result = await apiClient.publish.publishCli({
|
|
117
|
+
tarStream: Readable.toWeb(projectTar),
|
|
118
|
+
slug,
|
|
119
|
+
configPath: relativeConfigPath,
|
|
120
|
+
mode
|
|
121
|
+
});
|
|
122
|
+
if (result.error)
|
|
123
|
+
return {
|
|
124
|
+
success: false,
|
|
125
|
+
error: result.originalError ?? result.message
|
|
126
|
+
};
|
|
127
|
+
return { success: true, publishUid: result.data.publishUid };
|
|
128
|
+
} catch (e) {
|
|
129
|
+
return { success: false, error: e };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function publishUnifiedDocsProjectFromGithub({
|
|
133
|
+
slug,
|
|
134
|
+
preview,
|
|
135
|
+
apiClient
|
|
136
|
+
}) {
|
|
137
|
+
const result = await apiClient.publish.publishDocsProject({
|
|
138
|
+
slug,
|
|
139
|
+
preview
|
|
140
|
+
});
|
|
141
|
+
if (result.error) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
error: result.message
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
publishUid: result.data.publishUid
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/helpers/utils.ts
|
|
154
|
+
var sleep = (ms) => {
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
setTimeout(resolve, ms);
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// src/domains/project/publish/action.ts
|
|
161
|
+
async function publishAction(args) {
|
|
162
|
+
const argsParseResult = zod_default.object({
|
|
163
|
+
slug: slugSchema,
|
|
164
|
+
config: zod_default.string().optional(),
|
|
165
|
+
preview: zod_default.coerce.boolean().default(false),
|
|
166
|
+
github: zod_default.coerce.boolean().default(false)
|
|
167
|
+
}).safeParse(args);
|
|
168
|
+
if (argsParseResult.error)
|
|
169
|
+
return output.error().title("Invalid Arguments").message(argsParseResult.error.issues[0].message).exit("error");
|
|
170
|
+
const {
|
|
171
|
+
config: configPathOption,
|
|
172
|
+
slug,
|
|
173
|
+
preview,
|
|
174
|
+
github
|
|
175
|
+
} = argsParseResult.data;
|
|
176
|
+
const apiClient = await apiService();
|
|
177
|
+
const auth = await getAuthData();
|
|
178
|
+
auth.addEventListener((state) => Object.assign(auth, state));
|
|
179
|
+
if (!slug) {
|
|
180
|
+
return output.error().title("Invalid argument").message("Slug is required. Try passing --slug flag.").exit("error");
|
|
181
|
+
}
|
|
182
|
+
if (github) {
|
|
183
|
+
const resolved = await resolveProject(slug, apiClient);
|
|
184
|
+
if (resolved.kind === "not-found") {
|
|
185
|
+
return output.error().title("Project not found").message(`No project with slug "${slug}" was found for your team.`).exit("error");
|
|
186
|
+
}
|
|
187
|
+
if (resolved.kind === "github") {
|
|
188
|
+
if (!resolved.project.repository) {
|
|
189
|
+
return output.error().title("Your project is not linked to a GitHub repository").message(
|
|
190
|
+
"For a sync publish, please configure your GitHub connection through the dashboard."
|
|
191
|
+
).exit("error");
|
|
192
|
+
}
|
|
193
|
+
if (resolved.project.repository.expired) {
|
|
194
|
+
return output.error().title("Your GitHub repository access is expired.").message(
|
|
195
|
+
"Please reconnect your project through the Scalar Dashboard to publish via sync."
|
|
196
|
+
).exit("error");
|
|
197
|
+
}
|
|
198
|
+
const publishResult3 = await publishGithub({ apiClient, slug, preview });
|
|
199
|
+
if (!publishResult3.success) {
|
|
200
|
+
return output.error().title("Could not publish sync project.").message(publishResult3.error).exit("error");
|
|
201
|
+
}
|
|
202
|
+
return await waitForPublish({
|
|
203
|
+
teamUid: auth.teamUid,
|
|
204
|
+
publishUid: publishResult3.publishUid
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (!isGithubBackedDocsProject(resolved.project)) {
|
|
208
|
+
return output.error().title("Your project is not linked to a GitHub repository").message(
|
|
209
|
+
"For a sync publish, please configure your GitHub connection through the dashboard."
|
|
210
|
+
).exit("error");
|
|
211
|
+
}
|
|
212
|
+
if (resolved.project.repository.expired) {
|
|
213
|
+
return output.error().title("Your GitHub repository access is expired.").message(
|
|
214
|
+
"Please reconnect your project through the Scalar Dashboard to publish via sync."
|
|
215
|
+
).exit("error");
|
|
216
|
+
}
|
|
217
|
+
const publishResult2 = await publishUnifiedDocsProjectFromGithub({
|
|
218
|
+
apiClient,
|
|
219
|
+
slug,
|
|
220
|
+
preview
|
|
221
|
+
});
|
|
222
|
+
if (!publishResult2.success) {
|
|
223
|
+
return output.error().title("Could not publish sync project.").message(publishResult2.error).exit("error");
|
|
224
|
+
}
|
|
225
|
+
return await waitForPublish({
|
|
226
|
+
teamUid: auth.teamUid,
|
|
227
|
+
publishUid: publishResult2.publishUid
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const configResult = readAndParseConfig(configPathOption ?? "");
|
|
231
|
+
if (!configResult.success) {
|
|
232
|
+
renderConfigError(configResult.error);
|
|
233
|
+
}
|
|
234
|
+
const { config, filePath: configPath } = configResult;
|
|
235
|
+
const publishResult = await publishProject({
|
|
236
|
+
config,
|
|
237
|
+
slug,
|
|
238
|
+
configDir: dirname(configPath),
|
|
239
|
+
configPath,
|
|
240
|
+
...preview && { mode: "preview" }
|
|
241
|
+
});
|
|
242
|
+
if (!publishResult.success) {
|
|
243
|
+
return output.error().title("Something went wrong while deploying the project").message(
|
|
244
|
+
publishResult.error instanceof Error ? publishResult.error.message : publishResult.error
|
|
245
|
+
).exit("error");
|
|
246
|
+
}
|
|
247
|
+
return await waitForPublish({
|
|
248
|
+
teamUid: auth.teamUid,
|
|
249
|
+
publishUid: publishResult.publishUid
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async function waitForPublish({
|
|
253
|
+
teamUid,
|
|
254
|
+
publishUid
|
|
255
|
+
}) {
|
|
256
|
+
const dbClient = await getDatabaseClient();
|
|
257
|
+
const logger = output.info({ animate: true }).loader("Deployment in progress");
|
|
258
|
+
while (true) {
|
|
259
|
+
const deployStatus = await getDeployStatus({
|
|
260
|
+
client: dbClient,
|
|
261
|
+
publishUid,
|
|
262
|
+
teamUid
|
|
263
|
+
});
|
|
264
|
+
if (deployStatus.error === true) {
|
|
265
|
+
return output.error().title(
|
|
266
|
+
"Something went wrong while getting information about the deployment"
|
|
267
|
+
).exit("error");
|
|
268
|
+
}
|
|
269
|
+
logger.update("loader", 0, { content: deployStatus.data.message });
|
|
270
|
+
if (deployStatus.data.status === "deployed") {
|
|
271
|
+
const deploymentUrl = getPublishDeploymentUrl(deployStatus.data);
|
|
272
|
+
if (deploymentUrl) {
|
|
273
|
+
output.info().line(
|
|
274
|
+
`${deployStatus.data.preview ? "Preview URL" : "Deployment URL"}: ${deploymentUrl}`
|
|
275
|
+
).print();
|
|
276
|
+
}
|
|
277
|
+
logger.exit("success");
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (deployStatus.data.status === "error") {
|
|
281
|
+
logger.exit("error");
|
|
282
|
+
}
|
|
283
|
+
await sleep(3e3);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
async function getDeployStatus({
|
|
287
|
+
client,
|
|
288
|
+
publishUid,
|
|
289
|
+
teamUid
|
|
290
|
+
}) {
|
|
291
|
+
return client.getOne({
|
|
292
|
+
collectionPath: `team/${teamUid}/publish`,
|
|
293
|
+
schema: publishRecordSchema,
|
|
294
|
+
query: { uid: publishUid }
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
export {
|
|
298
|
+
publishAction
|
|
299
|
+
};
|