@picked/cli 0.0.85-next.3 → 0.0.85-next.5
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/dist/.tsbuildinfo +1 -1
- package/dist/cjs/cli.js +4 -2
- package/dist/cjs/index.js +1 -1
- package/dist/esm/cli.js +79 -50
- package/dist/esm/index.js +2 -2
- package/dist/types/commands/login.d.ts +2 -1
- package/dist/types/commands/login.d.ts.map +1 -1
- package/dist/types/commands/whoami.d.ts +1 -0
- package/dist/types/commands/whoami.d.ts.map +1 -1
- package/dist/types/commands/workspace-export.d.ts +28 -0
- package/dist/types/commands/workspace-export.d.ts.map +1 -0
- package/dist/types/commands/workspace-import.d.ts +26 -0
- package/dist/types/commands/workspace-import.d.ts.map +1 -0
- package/dist/types/commands/workspace-list.d.ts +1 -1
- package/dist/types/commands/workspace-list.d.ts.map +1 -1
- package/dist/types/commands/workspace-use.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/admin-client.d.ts +22 -0
- package/dist/types/lib/admin-client.d.ts.map +1 -0
- package/dist/types/lib/bundle.d.ts +79 -0
- package/dist/types/lib/bundle.d.ts.map +1 -0
- package/dist/types/lib/workspace-transfer.d.ts +120 -0
- package/dist/types/lib/workspace-transfer.d.ts.map +1 -0
- package/dist/types/lib/workspaces.d.ts +8 -9
- package/dist/types/lib/workspaces.d.ts.map +1 -1
- package/dist/workspace-use-Cjn8sjJj.cjs +51 -0
- package/dist/workspace-use-CnR5FkxR.js +839 -0
- package/package.json +6 -5
- package/dist/workspace-use-CT6_jewh.cjs +0 -48
- package/dist/workspace-use-Cbz1Bxse.js +0 -521
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
import { generate as e } from "@picked/typegen";
|
|
2
|
+
import { loadPickedConfig as t, loadResolvedPickedConfig as n, normalizeApiUrl as r, readActiveSelection as i, writeActiveSelection as a } from "@picked/config";
|
|
3
|
+
import { createServer as o } from "node:http";
|
|
4
|
+
import { spawn as s } from "node:child_process";
|
|
5
|
+
import { existsSync as c } from "node:fs";
|
|
6
|
+
import { chmod as l, mkdir as u, mkdtemp as d, readFile as f, readdir as p, rename as m, rm as h, rmdir as ee, writeFile as g } from "node:fs/promises";
|
|
7
|
+
import { basename as te, dirname as _, join as v, resolve as y, sep as b } from "node:path";
|
|
8
|
+
import { createHash as x, randomBytes as S } from "node:crypto";
|
|
9
|
+
import { homedir as ne } from "node:os";
|
|
10
|
+
import { AdminApiResponseError as re, AssetCommitDocument as ie, AssetDeleteDocument as ae, AssetUploadInitDocument as oe, ProjectLiveVersionDocument as se, WorkspaceExportDocument as ce, WorkspaceImportDocument as le, WorkspacePublishDocument as ue, createAdminApiClient as C, graphql as w } from "@picked/admin-api-client";
|
|
11
|
+
import { createInterface as de } from "node:readline";
|
|
12
|
+
//#region src/commands/generate-types.ts
|
|
13
|
+
async function T(t) {
|
|
14
|
+
let r = t?.cwd ?? process.cwd(), i = await n(r);
|
|
15
|
+
if (!i) return console.error("No picked.config.{ts,js,json} found in the current directory."), 1;
|
|
16
|
+
try {
|
|
17
|
+
let n = await e({
|
|
18
|
+
config: i,
|
|
19
|
+
check: t?.check ?? !1,
|
|
20
|
+
onWarn: (e) => {
|
|
21
|
+
console.warn(e);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return t?.check ? n.changed ? (console.error(`Types are out of date: ${n.typesOutput}`), 1) : (console.log(`Types are up to date (${n.typesOutput}).`), 0) : (console.log(`Generated types at ${n.typesOutput}`), 0);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
27
|
+
return console.error(t), 1;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/lib/browser.ts
|
|
32
|
+
function fe(e) {
|
|
33
|
+
return process.platform === "darwin" ? {
|
|
34
|
+
command: "open",
|
|
35
|
+
args: [e]
|
|
36
|
+
} : process.platform === "win32" ? {
|
|
37
|
+
command: "cmd",
|
|
38
|
+
args: [
|
|
39
|
+
"/c",
|
|
40
|
+
"start",
|
|
41
|
+
"\"\"",
|
|
42
|
+
e
|
|
43
|
+
]
|
|
44
|
+
} : {
|
|
45
|
+
command: "xdg-open",
|
|
46
|
+
args: [e]
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function pe(e) {
|
|
50
|
+
let { command: t, args: n } = fe(e);
|
|
51
|
+
try {
|
|
52
|
+
let e = s(t, n, {
|
|
53
|
+
detached: !0,
|
|
54
|
+
stdio: "ignore"
|
|
55
|
+
});
|
|
56
|
+
e.on("error", () => void 0), e.unref();
|
|
57
|
+
} catch {}
|
|
58
|
+
return Promise.resolve();
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/lib/paths.ts
|
|
62
|
+
var me = 8;
|
|
63
|
+
function he() {
|
|
64
|
+
return v(ne(), ".picked");
|
|
65
|
+
}
|
|
66
|
+
function ge(e) {
|
|
67
|
+
let t = r(e), { hostname: n, port: i } = new URL(t);
|
|
68
|
+
return `${(i ? `${n}-${i}` : n).replace(/[^a-z0-9.-]/gi, "_")}-${x("sha256").update(t).digest("hex").slice(0, me)}`;
|
|
69
|
+
}
|
|
70
|
+
function E(e) {
|
|
71
|
+
return v(he(), "auth", `${ge(e)}.json`);
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/auth/token-store.ts
|
|
75
|
+
var D = 384;
|
|
76
|
+
function _e(e) {
|
|
77
|
+
return typeof e == "object" && !!e && "clientId" in e && typeof e.clientId == "string" && "redirectUri" in e && typeof e.redirectUri == "string";
|
|
78
|
+
}
|
|
79
|
+
function ve(e) {
|
|
80
|
+
return !(typeof e != "object" || !e || !("accessToken" in e) || typeof e.accessToken != "string" || !("refreshToken" in e) || typeof e.refreshToken != "string" || !("expiresAt" in e) || typeof e.expiresAt != "number" || "user" in e && e.user !== void 0 && (typeof e.user != "object" || e.user === null));
|
|
81
|
+
}
|
|
82
|
+
function ye(e) {
|
|
83
|
+
return !(typeof e != "object" || !e || !("apiUrl" in e) || typeof e.apiUrl != "string" || "client" in e && e.client !== void 0 && !_e(e.client) || "session" in e && e.session !== void 0 && !ve(e.session));
|
|
84
|
+
}
|
|
85
|
+
async function O(e) {
|
|
86
|
+
let t = E(e);
|
|
87
|
+
if (!c(t)) return null;
|
|
88
|
+
try {
|
|
89
|
+
let e = JSON.parse(await f(t, "utf8"));
|
|
90
|
+
return ye(e) ? e : null;
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function be(e) {
|
|
96
|
+
let t = E(e.apiUrl);
|
|
97
|
+
await u(_(t), { recursive: !0 });
|
|
98
|
+
let n = `${t}.${process.pid.toString()}.tmp`;
|
|
99
|
+
await g(n, `${JSON.stringify(e, null, 2)}\n`, {
|
|
100
|
+
encoding: "utf8",
|
|
101
|
+
mode: D
|
|
102
|
+
}), await l(n, D), await m(n, t);
|
|
103
|
+
}
|
|
104
|
+
async function k(e, t) {
|
|
105
|
+
let n = await O(e);
|
|
106
|
+
await be({
|
|
107
|
+
apiUrl: r(e),
|
|
108
|
+
client: n?.client,
|
|
109
|
+
session: n?.session,
|
|
110
|
+
...t
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async function xe(e, t) {
|
|
114
|
+
await k(e, { client: t });
|
|
115
|
+
}
|
|
116
|
+
async function A(e, t) {
|
|
117
|
+
await k(e, { session: t });
|
|
118
|
+
}
|
|
119
|
+
async function Se(e) {
|
|
120
|
+
await h(E(e), { force: !0 });
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/auth/pkce.ts
|
|
124
|
+
var Ce = 32, we = 16;
|
|
125
|
+
function j(e) {
|
|
126
|
+
return e.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
127
|
+
}
|
|
128
|
+
function Te() {
|
|
129
|
+
return j(S(Ce));
|
|
130
|
+
}
|
|
131
|
+
function Ee(e) {
|
|
132
|
+
return j(x("sha256").update(e).digest());
|
|
133
|
+
}
|
|
134
|
+
function De() {
|
|
135
|
+
return j(S(we));
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/auth/oauth.ts
|
|
139
|
+
var M = [
|
|
140
|
+
8976,
|
|
141
|
+
8977,
|
|
142
|
+
8988
|
|
143
|
+
], Oe = 18e4, ke = "openid profile email";
|
|
144
|
+
async function N(e) {
|
|
145
|
+
let t;
|
|
146
|
+
try {
|
|
147
|
+
t = await fetch(`${e}/.well-known/oauth-authorization-server`);
|
|
148
|
+
} catch (e) {
|
|
149
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
150
|
+
throw Error(`Failed to reach the Picked OAuth discovery endpoint: ${t}`);
|
|
151
|
+
}
|
|
152
|
+
if (!t.ok) throw Error(`OAuth discovery request failed (${t.status.toString()}).`);
|
|
153
|
+
let n = await t.json();
|
|
154
|
+
if (typeof n != "object" || !n) throw Error("Malformed OAuth discovery document.");
|
|
155
|
+
if (!("authorization_endpoint" in n) || typeof n.authorization_endpoint != "string") throw Error("OAuth discovery document is missing authorization_endpoint.");
|
|
156
|
+
if (!("token_endpoint" in n) || typeof n.token_endpoint != "string") throw Error("OAuth discovery document is missing token_endpoint.");
|
|
157
|
+
let r = "registration_endpoint" in n && typeof n.registration_endpoint == "string" ? n.registration_endpoint : void 0, i = "code_challenge_methods_supported" in n && Array.isArray(n.code_challenge_methods_supported) ? n.code_challenge_methods_supported.filter((e) => typeof e == "string") : void 0;
|
|
158
|
+
return {
|
|
159
|
+
authorizationEndpoint: n.authorization_endpoint,
|
|
160
|
+
tokenEndpoint: n.token_endpoint,
|
|
161
|
+
registrationEndpoint: r,
|
|
162
|
+
codeChallengeMethods: i
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async function Ae(e, t, n) {
|
|
166
|
+
if (!t.registrationEndpoint) throw Error("OAuth client registration is not available for this Picked API.");
|
|
167
|
+
let r = await fetch(t.registrationEndpoint, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "content-type": "application/json" },
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
client_name: "Picked CLI",
|
|
172
|
+
redirect_uris: [n],
|
|
173
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
174
|
+
response_types: ["code"],
|
|
175
|
+
token_endpoint_auth_method: "none"
|
|
176
|
+
})
|
|
177
|
+
});
|
|
178
|
+
if (!r.ok) throw Error(`OAuth client registration failed (${r.status.toString()}).`);
|
|
179
|
+
let i = await r.json();
|
|
180
|
+
if (typeof i != "object" || !i || !("client_id" in i) || typeof i.client_id != "string") throw Error("OAuth client registration returned an unexpected response.");
|
|
181
|
+
return await xe(e, {
|
|
182
|
+
clientId: i.client_id,
|
|
183
|
+
redirectUri: n
|
|
184
|
+
}), i.client_id;
|
|
185
|
+
}
|
|
186
|
+
async function je(e, t, n) {
|
|
187
|
+
let r = (await O(e))?.client;
|
|
188
|
+
return r?.redirectUri === n ? r.clientId : Ae(e, t, n);
|
|
189
|
+
}
|
|
190
|
+
function Me(e, t) {
|
|
191
|
+
return new Promise((n) => {
|
|
192
|
+
let r = () => {
|
|
193
|
+
e.removeListener("error", r), n(!1);
|
|
194
|
+
};
|
|
195
|
+
e.once("error", r), e.listen(t, "127.0.0.1", () => {
|
|
196
|
+
e.removeListener("error", r), n(!0);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
async function Ne(e) {
|
|
201
|
+
for (let t of M) if (await Me(e, t)) return t;
|
|
202
|
+
throw Error(`No loopback port available for the OAuth callback (tried ${M.join(", ")}).`);
|
|
203
|
+
}
|
|
204
|
+
function Pe(e, t, n) {
|
|
205
|
+
return new Promise((r, i) => {
|
|
206
|
+
let a = () => {
|
|
207
|
+
clearTimeout(o), process.removeListener("SIGINT", s), e.close();
|
|
208
|
+
}, o = setTimeout(() => {
|
|
209
|
+
a(), i(/* @__PURE__ */ Error("Timed out waiting for the browser sign-in to complete."));
|
|
210
|
+
}, n), s = () => {
|
|
211
|
+
a(), i(/* @__PURE__ */ Error("Sign-in cancelled."));
|
|
212
|
+
};
|
|
213
|
+
process.once("SIGINT", s), e.on("request", (e, n) => {
|
|
214
|
+
let o = new URL(e.url ?? "/", "http://127.0.0.1");
|
|
215
|
+
if (o.pathname !== "/callback") {
|
|
216
|
+
n.writeHead(404), n.end();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
let s = o.searchParams.get("error");
|
|
220
|
+
if (s) {
|
|
221
|
+
n.writeHead(200, { "content-type": "text/html" }), n.end("<html><body>Sign-in failed. You can close this tab.</body></html>"), a(), i(/* @__PURE__ */ Error(`Authorization failed: ${s}`));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
let c = o.searchParams.get("code"), l = o.searchParams.get("state");
|
|
225
|
+
if (!c || l !== t) {
|
|
226
|
+
n.writeHead(400, { "content-type": "text/html" }), n.end("<html><body>Invalid sign-in response. Close this tab and try again.</body></html>"), a(), i(/* @__PURE__ */ Error("Invalid OAuth callback: missing code or state mismatch."));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
n.writeHead(200, { "content-type": "text/html" }), n.end("<html><body>Signed in. You can close this tab and return to the terminal.</body></html>"), a(), r({ code: c });
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
async function P(e) {
|
|
234
|
+
let t;
|
|
235
|
+
try {
|
|
236
|
+
t = await e.json();
|
|
237
|
+
} catch {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
if (typeof t != "object" || !t || !("access_token" in t) || typeof t.access_token != "string" || !("expires_in" in t) || typeof t.expires_in != "number") return null;
|
|
241
|
+
let n = "refresh_token" in t && typeof t.refresh_token == "string" ? t.refresh_token : void 0;
|
|
242
|
+
return {
|
|
243
|
+
accessToken: t.access_token,
|
|
244
|
+
refreshToken: n,
|
|
245
|
+
expiresIn: t.expires_in
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function Fe(e) {
|
|
249
|
+
let t = e.split("."), n = t[1];
|
|
250
|
+
if (t.length !== 3 || !n) return {};
|
|
251
|
+
try {
|
|
252
|
+
let e = JSON.parse(Buffer.from(n, "base64url").toString("utf8"));
|
|
253
|
+
return typeof e != "object" || !e ? {} : {
|
|
254
|
+
id: "sub" in e && typeof e.sub == "string" ? e.sub : void 0,
|
|
255
|
+
email: "email" in e && typeof e.email == "string" ? e.email : void 0
|
|
256
|
+
};
|
|
257
|
+
} catch {
|
|
258
|
+
return {};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async function Ie(e) {
|
|
262
|
+
let t = await N(e), n = o(), r = `http://127.0.0.1:${(await Ne(n)).toString()}/callback`, i = await je(e, t, r), a = Te(), s = Ee(a), c = De(), l = new URL(t.authorizationEndpoint);
|
|
263
|
+
l.searchParams.set("response_type", "code"), l.searchParams.set("client_id", i), l.searchParams.set("redirect_uri", r), l.searchParams.set("code_challenge", s), l.searchParams.set("code_challenge_method", "S256"), l.searchParams.set("state", c), l.searchParams.set("scope", ke), console.log(`Opening your browser to sign in...\n${l.toString()}`), await pe(l.toString());
|
|
264
|
+
let { code: u } = await Pe(n, c, Oe), d = new URLSearchParams({
|
|
265
|
+
grant_type: "authorization_code",
|
|
266
|
+
code: u,
|
|
267
|
+
redirect_uri: r,
|
|
268
|
+
client_id: i,
|
|
269
|
+
code_verifier: a
|
|
270
|
+
}), f = await fetch(t.tokenEndpoint, {
|
|
271
|
+
method: "POST",
|
|
272
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
273
|
+
body: d.toString()
|
|
274
|
+
});
|
|
275
|
+
if (!f.ok) throw Error(`Token exchange failed (${f.status.toString()}).`);
|
|
276
|
+
let p = await P(f);
|
|
277
|
+
if (!p?.refreshToken) throw Error("Token exchange did not return a refresh token.");
|
|
278
|
+
return {
|
|
279
|
+
accessToken: p.accessToken,
|
|
280
|
+
refreshToken: p.refreshToken,
|
|
281
|
+
expiresAt: Date.now() + p.expiresIn * 1e3,
|
|
282
|
+
user: Fe(p.accessToken)
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
async function Le(e) {
|
|
286
|
+
if (!e.client || !e.session) throw Error("Session expired. Run `picked login`.");
|
|
287
|
+
let t = await N(e.apiUrl), n = new URLSearchParams({
|
|
288
|
+
grant_type: "refresh_token",
|
|
289
|
+
refresh_token: e.session.refreshToken,
|
|
290
|
+
client_id: e.client.clientId
|
|
291
|
+
}), r;
|
|
292
|
+
try {
|
|
293
|
+
r = await fetch(t.tokenEndpoint, {
|
|
294
|
+
method: "POST",
|
|
295
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
296
|
+
body: n.toString()
|
|
297
|
+
});
|
|
298
|
+
} catch {
|
|
299
|
+
throw Error("Session expired. Run `picked login`.");
|
|
300
|
+
}
|
|
301
|
+
if (!r.ok) throw Error("Session expired. Run `picked login`.");
|
|
302
|
+
let i = await P(r);
|
|
303
|
+
if (!i) throw Error("Session expired. Run `picked login`.");
|
|
304
|
+
return {
|
|
305
|
+
accessToken: i.accessToken,
|
|
306
|
+
refreshToken: i.refreshToken ?? e.session.refreshToken,
|
|
307
|
+
expiresAt: Date.now() + i.expiresIn * 1e3,
|
|
308
|
+
user: e.session.user
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
//#region src/auth/session.ts
|
|
313
|
+
var Re = 6e4;
|
|
314
|
+
async function F(e) {
|
|
315
|
+
let t = await O(e);
|
|
316
|
+
if (!t?.session) throw Error(`Not logged in to ${e}. Run \`picked login\`.`);
|
|
317
|
+
if (t.session.expiresAt - Date.now() > Re) return t.session.accessToken;
|
|
318
|
+
let n = await Le(t);
|
|
319
|
+
return await A(e, n), n.accessToken;
|
|
320
|
+
}
|
|
321
|
+
//#endregion
|
|
322
|
+
//#region src/lib/admin-client.ts
|
|
323
|
+
function I() {
|
|
324
|
+
let e = process.env.PICKED_API_KEY?.trim();
|
|
325
|
+
return e === "" ? void 0 : e;
|
|
326
|
+
}
|
|
327
|
+
async function L(e) {
|
|
328
|
+
let t = I();
|
|
329
|
+
return t ? C({
|
|
330
|
+
apiUrl: e,
|
|
331
|
+
apiKey: t
|
|
332
|
+
}) : (await F(e), C({
|
|
333
|
+
apiUrl: e,
|
|
334
|
+
token: () => F(e)
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/lib/api-url.ts
|
|
339
|
+
var ze = "https://api.picked.app";
|
|
340
|
+
async function R(e = process.cwd()) {
|
|
341
|
+
let n = process.env.PICKED_API_URL;
|
|
342
|
+
if (n) return r(n);
|
|
343
|
+
let i = await t(e);
|
|
344
|
+
return r(i?.apiUrl ?? ze);
|
|
345
|
+
}
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/commands/login.ts
|
|
348
|
+
async function Be(e) {
|
|
349
|
+
let t = await R(e?.cwd);
|
|
350
|
+
if (I()) return console.error(`\`picked login\` does not apply while PICKED_API_KEY is set: every command authenticates to ${t} with that API key. Unset PICKED_API_KEY to sign in as a user.`), 1;
|
|
351
|
+
try {
|
|
352
|
+
let e = await Ie(t);
|
|
353
|
+
await A(t, e);
|
|
354
|
+
let n = e.user?.email ?? e.user?.id ?? "unknown user";
|
|
355
|
+
return console.log(`Logged in as ${n} (${t})`), 0;
|
|
356
|
+
} catch (e) {
|
|
357
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
358
|
+
return console.error(t), 1;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//#endregion
|
|
362
|
+
//#region src/commands/logout.ts
|
|
363
|
+
async function Ve(e) {
|
|
364
|
+
let t = await R(e?.cwd);
|
|
365
|
+
return await Se(t), console.log(`Logged out of ${t}.`), 0;
|
|
366
|
+
}
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region src/commands/status.ts
|
|
369
|
+
async function He(e) {
|
|
370
|
+
let n = e?.cwd ?? process.cwd(), r = await t(n);
|
|
371
|
+
if (!r) return console.error("No picked.config.{ts,js,json} found in the current directory."), 1;
|
|
372
|
+
let a = await R(n);
|
|
373
|
+
console.log(`API: ${a}`), console.log(`Config default: project ${r.projectId} (source: ${r.source ?? "published"})`);
|
|
374
|
+
let o = await i(n, a);
|
|
375
|
+
if (!o) return console.log("Active selection: none (using the config default)."), 0;
|
|
376
|
+
if (!o.workspace) return console.log(`Active selection: live (published) in project ${o.projectId}`), 0;
|
|
377
|
+
let { name: s, status: c, source: l } = o.workspace;
|
|
378
|
+
return console.log(`Active selection: ${s} [${c}] in project ${o.projectId} (source: ${l})`), 0;
|
|
379
|
+
}
|
|
380
|
+
//#endregion
|
|
381
|
+
//#region src/commands/whoami.ts
|
|
382
|
+
async function Ue(e) {
|
|
383
|
+
let t = await R(e?.cwd);
|
|
384
|
+
if (I()) return console.error(`\`picked whoami\` does not apply while PICKED_API_KEY is set: an API key authenticates to ${t} as a project or organization, not as a user.`), 1;
|
|
385
|
+
let n = await O(t);
|
|
386
|
+
if (!n?.session) return console.error(`Not logged in to ${t}. Run \`picked login\`.`), 1;
|
|
387
|
+
let { user: r } = n.session, i = r?.email ?? r?.id ?? "unknown user";
|
|
388
|
+
return console.log(`${i} (${t})`), 0;
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
//#region src/lib/bundle.ts
|
|
392
|
+
var z = "bundle.json", B = "assets", We = /^[0-9a-f]{64}$/;
|
|
393
|
+
function V(e, t, n) {
|
|
394
|
+
let r = y(e), i = y(r, t);
|
|
395
|
+
if (!i.startsWith(r.endsWith(b) ? r : r + b)) throw Error(`${n} ${t} must name a directory inside ${r}.`);
|
|
396
|
+
return i;
|
|
397
|
+
}
|
|
398
|
+
function H(e) {
|
|
399
|
+
return typeof e == "object" && !!e && !Array.isArray(e);
|
|
400
|
+
}
|
|
401
|
+
function Ge(e) {
|
|
402
|
+
return x("sha256").update(e).digest("hex");
|
|
403
|
+
}
|
|
404
|
+
function U(e, t) {
|
|
405
|
+
return v(e, B, t);
|
|
406
|
+
}
|
|
407
|
+
function Ke(e, t) {
|
|
408
|
+
let n = `bundle assets[${String(t)}]`;
|
|
409
|
+
if (!H(e)) throw Error(`${n} is not an object.`);
|
|
410
|
+
let { versionId: r, fileName: i, mimeType: a, sizeBytes: o, sha256: s, downloadUrl: c } = e;
|
|
411
|
+
if (typeof r != "string" || typeof i != "string" || typeof a != "string" || typeof c != "string" || typeof o != "number" || !Number.isInteger(o) || o < 0) throw Error(`${n} needs a string versionId, fileName, mimeType and downloadUrl, and an integer sizeBytes.`);
|
|
412
|
+
if (s === null) return {
|
|
413
|
+
versionId: r,
|
|
414
|
+
fileName: i,
|
|
415
|
+
mimeType: a,
|
|
416
|
+
sizeBytes: o,
|
|
417
|
+
sha256: s,
|
|
418
|
+
downloadUrl: c
|
|
419
|
+
};
|
|
420
|
+
let l = typeof s == "string" ? s.toLowerCase() : "";
|
|
421
|
+
if (!We.test(l)) throw Error(`${n} (${i}) has a sha256 that is not a hex SHA-256 digest.`);
|
|
422
|
+
return {
|
|
423
|
+
versionId: r,
|
|
424
|
+
fileName: i,
|
|
425
|
+
mimeType: a,
|
|
426
|
+
sizeBytes: o,
|
|
427
|
+
sha256: l,
|
|
428
|
+
downloadUrl: c
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function W(e) {
|
|
432
|
+
let { assets: t } = e;
|
|
433
|
+
if (!Array.isArray(t)) throw Error("The bundle has no assets array.");
|
|
434
|
+
return t.map((e, t) => Ke(e, t));
|
|
435
|
+
}
|
|
436
|
+
function G(e, t, n) {
|
|
437
|
+
if (t.byteLength !== e.sizeBytes) throw Error(`${e.fileName} (${n}) has size ${String(t.byteLength)} bytes; the manifest says ${String(e.sizeBytes)}.`);
|
|
438
|
+
let r = Ge(t);
|
|
439
|
+
if (e.sha256 !== null && r !== e.sha256) throw Error(`${e.fileName} (${n}) has SHA-256 ${r}; the manifest says ${e.sha256}.`);
|
|
440
|
+
return r;
|
|
441
|
+
}
|
|
442
|
+
function qe(e, t) {
|
|
443
|
+
let n = Array.isArray(e.assets) ? e.assets : [];
|
|
444
|
+
return {
|
|
445
|
+
...e,
|
|
446
|
+
assets: n.map((e, n) => H(e) ? {
|
|
447
|
+
...e,
|
|
448
|
+
sha256: t[n]
|
|
449
|
+
} : e)
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region src/lib/workspace-transfer.ts
|
|
454
|
+
var Je = 12e4, Ye = 3e5, K = class extends Error {
|
|
455
|
+
name = "PayloadUserErrorsError";
|
|
456
|
+
};
|
|
457
|
+
function q(e, t) {
|
|
458
|
+
if (t.length !== 0) throw new K(`${e} failed:\n${t.map((e) => {
|
|
459
|
+
let t = e.field?.length ? ` (${e.field.join(".")})` : "";
|
|
460
|
+
return ` ${e.code}: ${e.message}${t}`;
|
|
461
|
+
}).join("\n")}`);
|
|
462
|
+
}
|
|
463
|
+
async function Xe(e, t) {
|
|
464
|
+
let { project: n } = await e.request(se, { input: { id: t } });
|
|
465
|
+
if (!n) throw Error(`Project ${t} was not found.`);
|
|
466
|
+
let r = n.liveWorkspaceVersion;
|
|
467
|
+
if (!r) throw Error(`Project ${t} has no published version.`);
|
|
468
|
+
if (!r.snapshotWorkspaceId) throw Error(`The live version ${r.id} of project ${t} has no snapshot workspace to export. Publish the project again.`);
|
|
469
|
+
return r.snapshotWorkspaceId;
|
|
470
|
+
}
|
|
471
|
+
async function Ze(e, t) {
|
|
472
|
+
let { workspaceExport: n } = await e.request(ce, { input: { workspaceId: t } });
|
|
473
|
+
if (q(`Export of workspace ${t}`, n.userErrors), !H(n.bundle)) throw Error(`Export of workspace ${t} returned no bundle.`);
|
|
474
|
+
return n.bundle;
|
|
475
|
+
}
|
|
476
|
+
async function Qe(e, t) {
|
|
477
|
+
let { projectId: n, fileName: r, mimeType: i, sha256: a, bytes: o } = t, { assetUploadInit: s } = await e.request(oe, { input: {
|
|
478
|
+
projectId: n,
|
|
479
|
+
fileName: r,
|
|
480
|
+
contentType: i,
|
|
481
|
+
sha256: a
|
|
482
|
+
} });
|
|
483
|
+
if (s.deduplicated) return {
|
|
484
|
+
assetId: s.assetId,
|
|
485
|
+
versionId: s.versionId,
|
|
486
|
+
deduplicated: !0
|
|
487
|
+
};
|
|
488
|
+
if (!s.uploadUrl) throw Error(`The API returned no upload URL for ${r}.`);
|
|
489
|
+
let c = await fetch(s.uploadUrl, {
|
|
490
|
+
method: "PUT",
|
|
491
|
+
headers: { "Content-Type": i },
|
|
492
|
+
body: o,
|
|
493
|
+
signal: AbortSignal.timeout(Je)
|
|
494
|
+
});
|
|
495
|
+
if (!c.ok) throw Error(`Upload of ${r} failed with status ${String(c.status)}: ${await c.text()}`);
|
|
496
|
+
let { assetCommit: l } = await e.request(ie, { input: {
|
|
497
|
+
projectId: n,
|
|
498
|
+
assetId: s.assetId,
|
|
499
|
+
versionId: s.versionId,
|
|
500
|
+
fileName: r,
|
|
501
|
+
storagePath: s.storagePath,
|
|
502
|
+
sha256: a
|
|
503
|
+
} });
|
|
504
|
+
return q(`Commit of ${r}`, l.userErrors), {
|
|
505
|
+
assetId: s.assetId,
|
|
506
|
+
versionId: s.versionId,
|
|
507
|
+
deduplicated: !1
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
async function $e(e, t) {
|
|
511
|
+
await e.request(ae, { input: { id: t } });
|
|
512
|
+
}
|
|
513
|
+
async function et(e, t) {
|
|
514
|
+
let { workspaceImport: n } = await e.request(le, { input: t }, { timeoutMs: Ye });
|
|
515
|
+
if (q(`Import into project ${t.projectId}`, n.userErrors), !n.workspace) throw Error(`Import into project ${t.projectId} returned no workspace.`);
|
|
516
|
+
return n.workspace;
|
|
517
|
+
}
|
|
518
|
+
async function tt(e, t) {
|
|
519
|
+
let { workspacePublish: n } = await e.request(ue, { input: { workspaceId: t } });
|
|
520
|
+
q(`Publish of workspace ${t}`, n.userErrors);
|
|
521
|
+
}
|
|
522
|
+
//#endregion
|
|
523
|
+
//#region src/commands/workspace-export.ts
|
|
524
|
+
var nt = 12e4;
|
|
525
|
+
function rt(e, t) {
|
|
526
|
+
if (!e.project) throw Error("Missing --project <id>.");
|
|
527
|
+
if (e.workspace && e.live) throw Error("Pass --workspace <id> or --live, not both.");
|
|
528
|
+
if (!e.workspace && !e.live) throw Error("Pass --workspace <id> or --live.");
|
|
529
|
+
if (!e.out) throw Error("Missing --out <dir>.");
|
|
530
|
+
return {
|
|
531
|
+
projectId: e.project,
|
|
532
|
+
workspaceId: e.workspace ?? null,
|
|
533
|
+
outDir: V(t, e.out, "--out")
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
async function it(e) {
|
|
537
|
+
if ((await p(e).catch((e) => {
|
|
538
|
+
if (H(e) && e.code === "ENOENT") return [];
|
|
539
|
+
throw e;
|
|
540
|
+
})).length > 0) throw Error(`${e} is not empty. Export into a new or empty directory.`);
|
|
541
|
+
}
|
|
542
|
+
async function at(e) {
|
|
543
|
+
let t = await fetch(e.downloadUrl, { signal: AbortSignal.timeout(nt) });
|
|
544
|
+
if (!t.ok) throw Error(`Download of ${e.fileName} from ${e.downloadUrl} failed with status ${String(t.status)}.`);
|
|
545
|
+
let n = new Uint8Array(await t.arrayBuffer());
|
|
546
|
+
return {
|
|
547
|
+
bytes: n,
|
|
548
|
+
sha256: G(e, n, e.downloadUrl)
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
async function ot(e, t, n) {
|
|
552
|
+
await u(v(e, B));
|
|
553
|
+
let r = [];
|
|
554
|
+
for (let t of n) {
|
|
555
|
+
let { bytes: n, sha256: i } = await at(t);
|
|
556
|
+
await g(U(e, i), n), r.push(i);
|
|
557
|
+
}
|
|
558
|
+
let i = qe(t, r);
|
|
559
|
+
await g(v(e, z), `${JSON.stringify(i, null, 2)}\n`);
|
|
560
|
+
}
|
|
561
|
+
async function st(e, t, n) {
|
|
562
|
+
await u(_(e), { recursive: !0 });
|
|
563
|
+
let r = await d(v(_(e), `.${te(e)}.partial-`));
|
|
564
|
+
try {
|
|
565
|
+
await ot(r, t, n), await ee(e).catch((e) => {
|
|
566
|
+
if (!(H(e) && e.code === "ENOENT")) throw e;
|
|
567
|
+
}), await m(r, e);
|
|
568
|
+
} catch (e) {
|
|
569
|
+
throw await h(r, {
|
|
570
|
+
recursive: !0,
|
|
571
|
+
force: !0
|
|
572
|
+
}), e;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
async function ct(e, t) {
|
|
576
|
+
let n = t.workspaceId ?? await Xe(e, t.projectId), r = await Ze(e, n), i = H(r.source) ? r.source.projectId : void 0;
|
|
577
|
+
if (i !== t.projectId) throw Error(`Workspace ${n} belongs to project ${String(i)}, not ${t.projectId}.`);
|
|
578
|
+
return r;
|
|
579
|
+
}
|
|
580
|
+
async function lt(e) {
|
|
581
|
+
try {
|
|
582
|
+
let t = rt(e, e.cwd ?? process.cwd());
|
|
583
|
+
await it(t.outDir);
|
|
584
|
+
let n = await ct(await L(await R(e.cwd)), t), r = W(n);
|
|
585
|
+
await st(t.outDir, n, r);
|
|
586
|
+
let i = H(n.workspace) ? String(n.workspace.name) : "";
|
|
587
|
+
return console.log(`Exported workspace "${i}" with ${String(r.length)} assets to ${t.outDir}`), 0;
|
|
588
|
+
} catch (e) {
|
|
589
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
590
|
+
return console.error(t), 1;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
//#endregion
|
|
594
|
+
//#region src/commands/workspace-import.ts
|
|
595
|
+
async function ut(e) {
|
|
596
|
+
let t = v(e, z), n = await f(t, "utf8").catch((e) => {
|
|
597
|
+
throw Error(`Cannot read ${t}. Pass the directory \`picked workspace export\` wrote.`, { cause: e });
|
|
598
|
+
}), r = JSON.parse(n);
|
|
599
|
+
if (!H(r)) throw Error(`${t} is not a JSON object.`);
|
|
600
|
+
return r;
|
|
601
|
+
}
|
|
602
|
+
async function dt(e, t) {
|
|
603
|
+
let n = [];
|
|
604
|
+
for (let r of t) {
|
|
605
|
+
if (r.sha256 === null) throw Error(`The manifest item for ${r.fileName} has no SHA-256. Export the bundle with \`picked workspace export\`.`);
|
|
606
|
+
let t = U(e, r.sha256), i = new Uint8Array(await f(t));
|
|
607
|
+
n.push({
|
|
608
|
+
asset: r,
|
|
609
|
+
sha256: G(r, i, t),
|
|
610
|
+
bytes: i
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
return n;
|
|
614
|
+
}
|
|
615
|
+
async function ft(e, t, n, r) {
|
|
616
|
+
let i = [];
|
|
617
|
+
for (let { asset: a, sha256: o, bytes: s } of n) {
|
|
618
|
+
let n = await Qe(e, {
|
|
619
|
+
projectId: t,
|
|
620
|
+
fileName: a.fileName,
|
|
621
|
+
mimeType: a.mimeType,
|
|
622
|
+
sha256: o,
|
|
623
|
+
bytes: s
|
|
624
|
+
});
|
|
625
|
+
n.deduplicated || r.push(n.assetId), i.push({
|
|
626
|
+
sourceVersionId: a.versionId,
|
|
627
|
+
assetId: n.assetId,
|
|
628
|
+
versionId: n.versionId
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
return i;
|
|
632
|
+
}
|
|
633
|
+
async function J(e, t) {
|
|
634
|
+
let n = [], r = [];
|
|
635
|
+
for (let i of t) try {
|
|
636
|
+
await $e(e, i), n.push(i);
|
|
637
|
+
} catch (e) {
|
|
638
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
639
|
+
r.push(`Could not delete asset ${i} (${t}); delete it from the project by hand.`);
|
|
640
|
+
}
|
|
641
|
+
return [...n.length > 0 ? [`Deleted the ${String(n.length)} asset${n.length === 1 ? "" : "s"} this run uploaded: ${n.join(", ")}.`] : [], ...r].join("\n");
|
|
642
|
+
}
|
|
643
|
+
function Y(e, t) {
|
|
644
|
+
let n = e instanceof Error ? e.message : String(e);
|
|
645
|
+
return Error(t ? `${n}\n${t}` : n, { cause: e });
|
|
646
|
+
}
|
|
647
|
+
function pt(e) {
|
|
648
|
+
let t = ["The outcome of the import is unknown: the API may have created the workspace. Check the project for it before you import again."];
|
|
649
|
+
return e.length > 0 && t.push(`Kept the ${String(e.length)} asset${e.length === 1 ? "" : "s"} this run uploaded: ${e.join(", ")}. If the project has no new workspace, delete them from the project.`), t.join("\n");
|
|
650
|
+
}
|
|
651
|
+
var mt = /* @__PURE__ */ new Set([
|
|
652
|
+
"FORBIDDEN",
|
|
653
|
+
"UNAUTHENTICATED",
|
|
654
|
+
"BAD_USER_INPUT",
|
|
655
|
+
"GRAPHQL_VALIDATION_FAILED"
|
|
656
|
+
]);
|
|
657
|
+
function ht(e) {
|
|
658
|
+
return e instanceof K || e instanceof re && e.codes.length > 0 && e.codes.every((e) => e !== void 0 && mt.has(e));
|
|
659
|
+
}
|
|
660
|
+
async function gt(e, t) {
|
|
661
|
+
let n = [], r = await ft(e, t.projectId, t.assets, n).catch(async (t) => {
|
|
662
|
+
throw Y(t, await J(e, n));
|
|
663
|
+
});
|
|
664
|
+
return {
|
|
665
|
+
workspace: await et(e, {
|
|
666
|
+
projectId: t.projectId,
|
|
667
|
+
name: t.name,
|
|
668
|
+
bundle: t.bundle,
|
|
669
|
+
assetMap: r
|
|
670
|
+
}).catch(async (t) => {
|
|
671
|
+
throw Y(t, ht(t) ? await J(e, n) : pt(n));
|
|
672
|
+
}),
|
|
673
|
+
uploaded: n.length
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
async function _t(e) {
|
|
677
|
+
try {
|
|
678
|
+
if (!e.project) throw Error("Missing --project <id>.");
|
|
679
|
+
if (!e.in) throw Error("Missing --in <dir>.");
|
|
680
|
+
let t = e.project, n = V(e.cwd ?? process.cwd(), e.in, "--in"), r = await ut(n), i = await dt(n, W(r)), a = await L(await R(e.cwd)), { workspace: o, uploaded: s } = await gt(a, {
|
|
681
|
+
projectId: t,
|
|
682
|
+
name: e.name,
|
|
683
|
+
bundle: r,
|
|
684
|
+
assets: i
|
|
685
|
+
});
|
|
686
|
+
return console.log(`Imported workspace "${o.name}" as ${o.id} into project ${t} (assets: ${String(s)} uploaded, ${String(i.length - s)} already in the project).`), e.publish && (await tt(a, o.id).catch((e) => {
|
|
687
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
688
|
+
throw Error(`Workspace ${o.id} was imported, but not published. ${t}`, { cause: e });
|
|
689
|
+
}), console.log(`Published workspace ${o.id}.`)), 0;
|
|
690
|
+
} catch (e) {
|
|
691
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
692
|
+
return console.error(t), 1;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
//#endregion
|
|
696
|
+
//#region src/lib/workspaces.ts
|
|
697
|
+
var vt = w("\n query PickedWorkspaces {\n user {\n organizations(first: 50) {\n edges {\n node {\n id\n name\n slug\n projects(first: 100) {\n edges {\n node {\n id\n name\n liveWorkspace {\n id\n }\n liveWorkspaceVersion {\n id\n }\n workspaces(first: 100) {\n edges {\n node {\n id\n name\n status\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n"), yt = w("\n query PickedPreviewToken($id: ID!, $projectId: ID!) {\n workspace(id: $id, projectId: $projectId) {\n id\n name\n status\n previewToken\n }\n }\n");
|
|
698
|
+
async function X(e) {
|
|
699
|
+
let t = await e.request(vt, {});
|
|
700
|
+
if (!t.user) throw Error("Not signed in as a user, or no organizations are visible to this account. An API key has no organization list.");
|
|
701
|
+
return t.user.organizations.edges.map((e) => {
|
|
702
|
+
let t = e.node;
|
|
703
|
+
return {
|
|
704
|
+
id: t.id,
|
|
705
|
+
name: t.name,
|
|
706
|
+
slug: t.slug ?? "",
|
|
707
|
+
projects: t.projects.edges.map((e) => {
|
|
708
|
+
let t = e.node;
|
|
709
|
+
return {
|
|
710
|
+
id: t.id,
|
|
711
|
+
name: t.name,
|
|
712
|
+
liveWorkspaceId: t.liveWorkspace?.id ?? null,
|
|
713
|
+
liveVersionId: t.liveWorkspaceVersion?.id ?? null,
|
|
714
|
+
workspaces: t.workspaces.edges.map((e) => ({
|
|
715
|
+
id: e.node.id,
|
|
716
|
+
name: e.node.name,
|
|
717
|
+
status: e.node.status
|
|
718
|
+
}))
|
|
719
|
+
};
|
|
720
|
+
})
|
|
721
|
+
};
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
async function Z(e, t, n) {
|
|
725
|
+
let r = (await e.request(yt, {
|
|
726
|
+
id: n,
|
|
727
|
+
projectId: t
|
|
728
|
+
})).workspace;
|
|
729
|
+
if (!r) throw Error(`Workspace "${n}" was not found in project "${t}".`);
|
|
730
|
+
return {
|
|
731
|
+
status: r.status,
|
|
732
|
+
name: r.name,
|
|
733
|
+
previewToken: r.previewToken
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
//#endregion
|
|
737
|
+
//#region src/commands/workspace-list.ts
|
|
738
|
+
function bt(e) {
|
|
739
|
+
for (let t of e) {
|
|
740
|
+
console.log(`${t.name} (${t.slug})`);
|
|
741
|
+
for (let e of t.projects) {
|
|
742
|
+
console.log(` ${e.name} [${e.id}]`);
|
|
743
|
+
for (let t of e.workspaces) {
|
|
744
|
+
let n = t.status === "LIVE" || t.id === e.liveWorkspaceId ? " (live)" : "";
|
|
745
|
+
console.log(` ${t.name} [${t.status}]${n}`);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
async function xt(e) {
|
|
751
|
+
try {
|
|
752
|
+
let t = await X(await L(await R(e?.cwd)));
|
|
753
|
+
return e?.json ? (console.log(JSON.stringify(t, null, 2)), 0) : (bt(t), 0);
|
|
754
|
+
} catch (e) {
|
|
755
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
756
|
+
return console.error(t), 1;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
//#endregion
|
|
760
|
+
//#region src/lib/prompt.ts
|
|
761
|
+
function St(e, t) {
|
|
762
|
+
return new Promise((n) => {
|
|
763
|
+
e.question(t, n);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
async function Q(e, t) {
|
|
767
|
+
if (t.length === 0) throw Error("No choices available to select from.");
|
|
768
|
+
let n = de({
|
|
769
|
+
input: process.stdin,
|
|
770
|
+
output: process.stderr
|
|
771
|
+
});
|
|
772
|
+
process.stderr.write(`${e}\n`), t.forEach((e, t) => {
|
|
773
|
+
process.stderr.write(` ${(t + 1).toString()}. ${e.label}\n`);
|
|
774
|
+
});
|
|
775
|
+
try {
|
|
776
|
+
for (;;) {
|
|
777
|
+
let e = await St(n, `Enter a number (1-${t.length.toString()}): `), r = Number.parseInt(e, 10), i = Number.isInteger(r) ? t[r - 1] : void 0;
|
|
778
|
+
if (i) return i.value;
|
|
779
|
+
process.stderr.write("Invalid choice, try again.\n");
|
|
780
|
+
}
|
|
781
|
+
} finally {
|
|
782
|
+
n.close();
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
//#endregion
|
|
786
|
+
//#region src/commands/workspace-use.ts
|
|
787
|
+
function $(e, t, n) {
|
|
788
|
+
return {
|
|
789
|
+
projectId: e,
|
|
790
|
+
workspace: {
|
|
791
|
+
id: t,
|
|
792
|
+
name: n.name,
|
|
793
|
+
status: n.status,
|
|
794
|
+
source: "preview",
|
|
795
|
+
previewToken: n.previewToken
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
async function Ct(e, t, n) {
|
|
800
|
+
return n ? $(t, n, await Z(e, t, n)) : { projectId: t };
|
|
801
|
+
}
|
|
802
|
+
async function wt(e) {
|
|
803
|
+
let t = await Q("Select a project", (await X(e)).flatMap((e) => e.projects.map((t) => ({
|
|
804
|
+
label: `${e.name} / ${t.name}`,
|
|
805
|
+
value: t
|
|
806
|
+
})))), n = t.workspaces.map((e) => ({
|
|
807
|
+
label: `${e.name} [${e.status}]`,
|
|
808
|
+
value: e
|
|
809
|
+
}));
|
|
810
|
+
t.liveVersionId && n.unshift({
|
|
811
|
+
label: "Published (live version)",
|
|
812
|
+
value: null
|
|
813
|
+
});
|
|
814
|
+
let r = await Q("Select a workspace", n);
|
|
815
|
+
if (!r) return { projectId: t.id };
|
|
816
|
+
r.status === "ARCHIVED" && console.error("Warning: archived workspaces may fail to load via the delivery API.");
|
|
817
|
+
let i = await Z(e, t.id, r.id);
|
|
818
|
+
return $(t.id, r.id, i);
|
|
819
|
+
}
|
|
820
|
+
function Tt(e) {
|
|
821
|
+
if (!e.workspace) {
|
|
822
|
+
console.log(`Active workspace: live (published) in project ${e.projectId}`);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
let { name: t, status: n, source: r } = e.workspace;
|
|
826
|
+
console.log(`Active workspace: ${t} [${n}] in project ${e.projectId} (source: ${r})`);
|
|
827
|
+
}
|
|
828
|
+
async function Et(e) {
|
|
829
|
+
let t = e?.cwd ?? process.cwd();
|
|
830
|
+
try {
|
|
831
|
+
let n = await R(t), r = await L(n), i = e?.project ? await Ct(r, e.project, e.workspace) : await wt(r);
|
|
832
|
+
return await a(t, n, i), Tt(i), e?.generate !== !1 && await T({ cwd: t }), 0;
|
|
833
|
+
} catch (e) {
|
|
834
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
835
|
+
return console.error(t), 1;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
//#endregion
|
|
839
|
+
export { Ue as a, Be as c, lt as i, T as l, xt as n, He as o, _t as r, Ve as s, Et as t };
|