deepspace 0.4.3 → 0.4.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/cli.js +331 -384
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +47 -425
- package/dist/index.js +272 -1688
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +122 -27
- package/dist/server.js +218 -17
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +122 -27
- package/dist/worker.js +218 -17
- package/dist/worker.js.map +1 -1
- package/features/admin-page/src/AdminPage.tsx +1 -1
- package/features/canvas/src/CanvasListPage.tsx +1 -1
- package/features/canvas/src/components/CanvasView.tsx +1 -1
- package/features/docs/src/DocsEditorPage.tsx +1 -1
- package/features/docs/src/InviteDialog.tsx +130 -139
- package/features/file-attachments/src/AttachmentsPage.tsx +1 -4
- package/features/file-manager/src/FileManagerPage.tsx +2 -1
- package/features/items/src/ItemsPage.tsx +1 -1
- package/features/landing/src/LandingPage.tsx +1 -1
- package/features/landing/src/primitives.tsx +1 -1
- package/features/leaderboard/src/LeaderboardPage.tsx +1 -1
- package/features/leaderboard/src/leaderboard-constants.ts +1 -1
- package/features/search-bar/src/SearchOverlay.tsx +1 -1
- package/features/tasks/src/TasksPage.tsx +1 -1
- package/features/tasks/src/tasks-constants.ts +1 -1
- package/package.json +1 -18
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/cli.ts
|
|
4
|
-
import { defineCommand as
|
|
4
|
+
import { defineCommand as defineCommand18, runMain } from "citty";
|
|
5
5
|
import { execSync as execSync5 } from "child_process";
|
|
6
|
-
import { readFileSync as
|
|
7
|
-
import { dirname as
|
|
8
|
-
import { fileURLToPath } from "url";
|
|
6
|
+
import { readFileSync as readFileSync12, existsSync as existsSync13 } from "fs";
|
|
7
|
+
import { dirname as dirname4, join as join14 } from "path";
|
|
8
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9
9
|
|
|
10
10
|
// src/cli/commands/login.ts
|
|
11
11
|
import { defineCommand } from "citty";
|
|
@@ -581,8 +581,8 @@ import { join as join5 } from "path";
|
|
|
581
581
|
import { homedir as homedir3 } from "os";
|
|
582
582
|
|
|
583
583
|
// src/cli/jwt.ts
|
|
584
|
-
function decodeJwtPayload(
|
|
585
|
-
const payloadSegment =
|
|
584
|
+
function decodeJwtPayload(token) {
|
|
585
|
+
const payloadSegment = token.split(".")[1];
|
|
586
586
|
if (!payloadSegment) {
|
|
587
587
|
throw new Error("JWT payload is missing");
|
|
588
588
|
}
|
|
@@ -605,13 +605,13 @@ async function ensureToken() {
|
|
|
605
605
|
throw new Error("Not logged in. Run `deepspace login` first.");
|
|
606
606
|
}
|
|
607
607
|
const sessionToken = readFileSync4(SESSION_PATH2, "utf-8").trim();
|
|
608
|
-
const
|
|
609
|
-
if (!
|
|
608
|
+
const token = await exchangeSession(AUTH_URL3, sessionToken);
|
|
609
|
+
if (!token) {
|
|
610
610
|
throw new Error("Session expired. Run `deepspace login` to re-authenticate.");
|
|
611
611
|
}
|
|
612
612
|
mkdirSync2(DIR2, { recursive: true, mode: 448 });
|
|
613
|
-
writeFileSync3(TOKEN_PATH2,
|
|
614
|
-
return
|
|
613
|
+
writeFileSync3(TOKEN_PATH2, token, { mode: 384 });
|
|
614
|
+
return token;
|
|
615
615
|
}
|
|
616
616
|
function isTokenValid(jwt) {
|
|
617
617
|
try {
|
|
@@ -794,16 +794,16 @@ var dev_default = defineCommand3({
|
|
|
794
794
|
}
|
|
795
795
|
writeLaunchConfigIfMissing(appDir, detectAppName(appDir) ?? basename(appDir), port);
|
|
796
796
|
ensureInstallReady(appDir);
|
|
797
|
-
let
|
|
797
|
+
let token;
|
|
798
798
|
try {
|
|
799
|
-
|
|
799
|
+
token = await ensureToken();
|
|
800
800
|
} catch (err) {
|
|
801
801
|
console.error(err.message);
|
|
802
802
|
process.exit(1);
|
|
803
803
|
}
|
|
804
804
|
let payload;
|
|
805
805
|
try {
|
|
806
|
-
payload = decodeJwtPayload(
|
|
806
|
+
payload = decodeJwtPayload(token);
|
|
807
807
|
} catch {
|
|
808
808
|
console.error("Malformed session token. Run `npx deepspace login`.");
|
|
809
809
|
process.exit(1);
|
|
@@ -812,7 +812,7 @@ var dev_default = defineCommand3({
|
|
|
812
812
|
console.log(`Platform: ${env}`);
|
|
813
813
|
if (wranglerEnv) console.log(`Wrangler env: ${wranglerEnv}`);
|
|
814
814
|
console.log(`Port: ${port}`);
|
|
815
|
-
await writeDevVars(appDir, env, payload.sub,
|
|
815
|
+
await writeDevVars(appDir, env, payload.sub, token, wranglerEnv);
|
|
816
816
|
preflightWindowsWorkerd(appDir);
|
|
817
817
|
console.log("Starting dev server...\n");
|
|
818
818
|
const vite = spawn(
|
|
@@ -1074,17 +1074,17 @@ var test_default = defineCommand5({
|
|
|
1074
1074
|
process.exit(1);
|
|
1075
1075
|
}
|
|
1076
1076
|
ensureInstallReady(appDir);
|
|
1077
|
-
let
|
|
1077
|
+
let token;
|
|
1078
1078
|
let ownerId;
|
|
1079
1079
|
try {
|
|
1080
|
-
|
|
1081
|
-
const payload = decodeJwtPayload(
|
|
1080
|
+
token = await ensureToken();
|
|
1081
|
+
const payload = decodeJwtPayload(token);
|
|
1082
1082
|
ownerId = payload.sub;
|
|
1083
1083
|
} catch (err) {
|
|
1084
1084
|
console.error("`deepspace test` requires you to be logged in. Run `deepspace login` first.");
|
|
1085
1085
|
process.exit(1);
|
|
1086
1086
|
}
|
|
1087
|
-
await writeDevVars(appDir, "dev", ownerId,
|
|
1087
|
+
await writeDevVars(appDir, "dev", ownerId, token);
|
|
1088
1088
|
if (suite !== "unit") {
|
|
1089
1089
|
preflightWindowsWorkerd(appDir);
|
|
1090
1090
|
ensurePlaywright(appDir);
|
|
@@ -1224,8 +1224,8 @@ function saveAccounts(accounts) {
|
|
|
1224
1224
|
writeFileSync5(ACCOUNTS_PATH, JSON.stringify(accounts, null, 2), { mode: 384 });
|
|
1225
1225
|
}
|
|
1226
1226
|
function sessionCookie() {
|
|
1227
|
-
const
|
|
1228
|
-
return `${SESSION_COOKIE2}=${encodeURIComponent(
|
|
1227
|
+
const token = readFileSync7(SESSION_PATH2, "utf-8").trim();
|
|
1228
|
+
return `${SESSION_COOKIE2}=${encodeURIComponent(token)}`;
|
|
1229
1229
|
}
|
|
1230
1230
|
async function fetchRemoteAccounts() {
|
|
1231
1231
|
const res = await fetch(`${AUTH_URL4}/api/auth/test-accounts`, {
|
|
@@ -1788,11 +1788,11 @@ async function postWithRetry(url, makeInit, { attempts = 4, retryServerErrors =
|
|
|
1788
1788
|
if (lastRes) return lastRes;
|
|
1789
1789
|
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
1790
1790
|
}
|
|
1791
|
-
async function abortStagedUpload(appName, uploadId, totalGroups,
|
|
1791
|
+
async function abortStagedUpload(appName, uploadId, totalGroups, token) {
|
|
1792
1792
|
try {
|
|
1793
1793
|
await fetch(
|
|
1794
1794
|
`${DEPLOY_URL}/api/deploy/${appName}/assets?uploadId=${uploadId}&totalGroups=${totalGroups}`,
|
|
1795
|
-
{ method: "DELETE", headers: { Authorization: `Bearer ${
|
|
1795
|
+
{ method: "DELETE", headers: { Authorization: `Bearer ${token}` } }
|
|
1796
1796
|
);
|
|
1797
1797
|
} catch {
|
|
1798
1798
|
}
|
|
@@ -1839,9 +1839,9 @@ var deploy_default = defineCommand8({
|
|
|
1839
1839
|
}
|
|
1840
1840
|
const appName = nameRes.name;
|
|
1841
1841
|
p4.log.info(envName ? `App: ${appName} (env: ${envName})` : `App: ${appName}`);
|
|
1842
|
-
let
|
|
1842
|
+
let token;
|
|
1843
1843
|
try {
|
|
1844
|
-
|
|
1844
|
+
token = await ensureToken();
|
|
1845
1845
|
} catch (err) {
|
|
1846
1846
|
p4.cancel(err.message);
|
|
1847
1847
|
process.exit(1);
|
|
@@ -1979,7 +1979,7 @@ var deploy_default = defineCommand8({
|
|
|
1979
1979
|
() => ({
|
|
1980
1980
|
method: "POST",
|
|
1981
1981
|
headers: {
|
|
1982
|
-
Authorization: `Bearer ${
|
|
1982
|
+
Authorization: `Bearer ${token}`,
|
|
1983
1983
|
"Content-Type": "application/json"
|
|
1984
1984
|
},
|
|
1985
1985
|
body: groupJson
|
|
@@ -1987,7 +1987,7 @@ var deploy_default = defineCommand8({
|
|
|
1987
1987
|
);
|
|
1988
1988
|
if (!groupRes.ok) {
|
|
1989
1989
|
const errBody = await groupRes.json().catch(() => ({}));
|
|
1990
|
-
await abortStagedUpload(appName, uploadId, totalGroups,
|
|
1990
|
+
await abortStagedUpload(appName, uploadId, totalGroups, token);
|
|
1991
1991
|
s.stop("Deploy failed");
|
|
1992
1992
|
p4.cancel(
|
|
1993
1993
|
`Asset upload failed on group ${i + 1}/${totalGroups}: ${errBody.error ?? `HTTP ${groupRes.status}`}`
|
|
@@ -1996,7 +1996,7 @@ var deploy_default = defineCommand8({
|
|
|
1996
1996
|
}
|
|
1997
1997
|
}
|
|
1998
1998
|
} catch (err) {
|
|
1999
|
-
await abortStagedUpload(appName, uploadId, totalGroups,
|
|
1999
|
+
await abortStagedUpload(appName, uploadId, totalGroups, token);
|
|
2000
2000
|
s.stop("Deploy failed");
|
|
2001
2001
|
p4.cancel(`Asset upload failed (network): ${err?.message ?? err}`);
|
|
2002
2002
|
process.exit(1);
|
|
@@ -2032,7 +2032,7 @@ var deploy_default = defineCommand8({
|
|
|
2032
2032
|
`${DEPLOY_URL}/api/deploy/${appName}`,
|
|
2033
2033
|
() => ({
|
|
2034
2034
|
method: "POST",
|
|
2035
|
-
headers: { Authorization: `Bearer ${
|
|
2035
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
2036
2036
|
body: makeForm()
|
|
2037
2037
|
}),
|
|
2038
2038
|
// Commit runs a real deploy — don't retry its 5xx (could double-deploy);
|
|
@@ -2041,14 +2041,14 @@ var deploy_default = defineCommand8({
|
|
|
2041
2041
|
{ retryServerErrors: false }
|
|
2042
2042
|
);
|
|
2043
2043
|
} catch (err) {
|
|
2044
|
-
if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups,
|
|
2044
|
+
if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token);
|
|
2045
2045
|
s.stop("Deploy failed");
|
|
2046
2046
|
p4.cancel(`Deploy request failed: ${err?.message ?? err}`);
|
|
2047
2047
|
process.exit(1);
|
|
2048
2048
|
}
|
|
2049
2049
|
const body = await res.json().catch(() => ({}));
|
|
2050
2050
|
if (!res.ok || !body.success) {
|
|
2051
|
-
if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups,
|
|
2051
|
+
if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token);
|
|
2052
2052
|
s.stop("Deploy failed");
|
|
2053
2053
|
p4.cancel(formatDeployWorkerError(res.status, body.error));
|
|
2054
2054
|
process.exit(1);
|
|
@@ -2060,20 +2060,20 @@ var deploy_default = defineCommand8({
|
|
|
2060
2060
|
s.stop("Deployed (edge propagation still in progress after 90s)");
|
|
2061
2061
|
p4.log.warn("First requests may briefly hit the assets transitional page; retry in a minute.");
|
|
2062
2062
|
p4.log.success(`Live at: ${body.url}`);
|
|
2063
|
-
await syncSubscriptionPlans(appDir, appName,
|
|
2064
|
-
await syncOneTimeProducts(appDir, appName,
|
|
2063
|
+
await syncSubscriptionPlans(appDir, appName, token);
|
|
2064
|
+
await syncOneTimeProducts(appDir, appName, token);
|
|
2065
2065
|
p4.outro("Done");
|
|
2066
2066
|
return;
|
|
2067
2067
|
}
|
|
2068
2068
|
}
|
|
2069
2069
|
s.stop("Deployed!");
|
|
2070
2070
|
p4.log.success(`Live at: ${body.url}`);
|
|
2071
|
-
await syncSubscriptionPlans(appDir, appName,
|
|
2072
|
-
await syncOneTimeProducts(appDir, appName,
|
|
2071
|
+
await syncSubscriptionPlans(appDir, appName, token);
|
|
2072
|
+
await syncOneTimeProducts(appDir, appName, token);
|
|
2073
2073
|
p4.outro("Done");
|
|
2074
2074
|
}
|
|
2075
2075
|
});
|
|
2076
|
-
async function syncSubscriptionPlans(appDir, appName,
|
|
2076
|
+
async function syncSubscriptionPlans(appDir, appName, token) {
|
|
2077
2077
|
const subsPath = join9(appDir, "src", "subscriptions.ts");
|
|
2078
2078
|
if (!existsSync9(subsPath)) return;
|
|
2079
2079
|
const s = createSpinner();
|
|
@@ -2112,7 +2112,7 @@ async function syncSubscriptionPlans(appDir, appName, token2) {
|
|
|
2112
2112
|
res = await fetch(`${API_URL}/api/subscriptions/sync`, {
|
|
2113
2113
|
method: "POST",
|
|
2114
2114
|
headers: {
|
|
2115
|
-
Authorization: `Bearer ${
|
|
2115
|
+
Authorization: `Bearer ${token}`,
|
|
2116
2116
|
"Content-Type": "application/json"
|
|
2117
2117
|
},
|
|
2118
2118
|
body: JSON.stringify({ appName, plans })
|
|
@@ -2132,7 +2132,7 @@ async function syncSubscriptionPlans(appDir, appName, token2) {
|
|
|
2132
2132
|
}
|
|
2133
2133
|
const changes = (body.planChanges ?? []).filter((c) => c.affectedSubscribers > 0);
|
|
2134
2134
|
if (changes.length > 0) {
|
|
2135
|
-
await promptAndCancelChangedPlans(appName,
|
|
2135
|
+
await promptAndCancelChangedPlans(appName, token, changes);
|
|
2136
2136
|
}
|
|
2137
2137
|
return;
|
|
2138
2138
|
}
|
|
@@ -2153,7 +2153,7 @@ function summaryLine(c) {
|
|
|
2153
2153
|
const diffs = (c.intervals ?? []).map((i) => `${i.interval}: ${formatCents(i.oldCents)} \u2192 ${formatCents(i.newCents)}`).join("; ");
|
|
2154
2154
|
return ` \u2022 ${c.slug} \u2014 repriced (${diffs}; ${suffix} grandfathered on old price)`;
|
|
2155
2155
|
}
|
|
2156
|
-
async function promptAndCancelChangedPlans(appName,
|
|
2156
|
+
async function promptAndCancelChangedPlans(appName, token, changes) {
|
|
2157
2157
|
const summary = changes.map(summaryLine).join("\n");
|
|
2158
2158
|
p4.log.warn(
|
|
2159
2159
|
`Plan change${changes.length === 1 ? "" : "s"} from this deploy left subscribers stranded:
|
|
@@ -2184,7 +2184,7 @@ current billing period? (Skip to leave them grandfathered.)`
|
|
|
2184
2184
|
const res = await fetch(`${API_URL}/api/subscriptions/admin-cancel`, {
|
|
2185
2185
|
method: "POST",
|
|
2186
2186
|
headers: {
|
|
2187
|
-
Authorization: `Bearer ${
|
|
2187
|
+
Authorization: `Bearer ${token}`,
|
|
2188
2188
|
"Content-Type": "application/json"
|
|
2189
2189
|
},
|
|
2190
2190
|
body: JSON.stringify({
|
|
@@ -2222,7 +2222,7 @@ current billing period? (Skip to leave them grandfathered.)`
|
|
|
2222
2222
|
}
|
|
2223
2223
|
}
|
|
2224
2224
|
}
|
|
2225
|
-
async function syncOneTimeProducts(appDir, appName,
|
|
2225
|
+
async function syncOneTimeProducts(appDir, appName, token) {
|
|
2226
2226
|
const productsPath = join9(appDir, "src", "products.ts");
|
|
2227
2227
|
if (!existsSync9(productsPath)) return;
|
|
2228
2228
|
const s = createSpinner();
|
|
@@ -2261,7 +2261,7 @@ async function syncOneTimeProducts(appDir, appName, token2) {
|
|
|
2261
2261
|
res = await fetch(`${API_URL}/api/charges/products/sync`, {
|
|
2262
2262
|
method: "POST",
|
|
2263
2263
|
headers: {
|
|
2264
|
-
Authorization: `Bearer ${
|
|
2264
|
+
Authorization: `Bearer ${token}`,
|
|
2265
2265
|
"Content-Type": "application/json"
|
|
2266
2266
|
},
|
|
2267
2267
|
body: JSON.stringify({ appName, products })
|
|
@@ -2360,9 +2360,9 @@ var undeploy_default = defineCommand9({
|
|
|
2360
2360
|
p5.cancel("Provide an app name or run from a DeepSpace app directory.");
|
|
2361
2361
|
process.exit(1);
|
|
2362
2362
|
}
|
|
2363
|
-
let
|
|
2363
|
+
let token;
|
|
2364
2364
|
try {
|
|
2365
|
-
|
|
2365
|
+
token = await ensureToken();
|
|
2366
2366
|
} catch (err) {
|
|
2367
2367
|
p5.cancel(err.message);
|
|
2368
2368
|
process.exit(1);
|
|
@@ -2372,7 +2372,7 @@ var undeploy_default = defineCommand9({
|
|
|
2372
2372
|
s.start("Removing...");
|
|
2373
2373
|
const res = await fetch(`${DEPLOY_URL2}/api/deploy/${appName}`, {
|
|
2374
2374
|
method: "DELETE",
|
|
2375
|
-
headers: { Authorization: `Bearer ${
|
|
2375
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
2376
2376
|
});
|
|
2377
2377
|
const body = await res.json().catch(() => ({}));
|
|
2378
2378
|
if (!res.ok || !body.success) {
|
|
@@ -2591,25 +2591,25 @@ var skills_default = defineCommand12({
|
|
|
2591
2591
|
import { defineCommand as defineCommand13 } from "citty";
|
|
2592
2592
|
import { execSync as execSync4 } from "child_process";
|
|
2593
2593
|
var API_URL2 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
|
|
2594
|
-
async function api(
|
|
2594
|
+
async function api(token, path, init) {
|
|
2595
2595
|
const res = await fetch(`${API_URL2}${path}`, {
|
|
2596
2596
|
...init,
|
|
2597
2597
|
headers: {
|
|
2598
|
-
Authorization: `Bearer ${
|
|
2598
|
+
Authorization: `Bearer ${token}`,
|
|
2599
2599
|
"Content-Type": "application/json",
|
|
2600
2600
|
...init?.headers ?? {}
|
|
2601
2601
|
}
|
|
2602
2602
|
});
|
|
2603
|
-
const
|
|
2603
|
+
const text2 = await res.text();
|
|
2604
2604
|
if (!res.ok) {
|
|
2605
|
-
let msg =
|
|
2605
|
+
let msg = text2;
|
|
2606
2606
|
try {
|
|
2607
|
-
msg = JSON.parse(
|
|
2607
|
+
msg = JSON.parse(text2).error ?? text2;
|
|
2608
2608
|
} catch {
|
|
2609
2609
|
}
|
|
2610
2610
|
throw new Error(`API ${path} (${res.status}): ${msg}`);
|
|
2611
2611
|
}
|
|
2612
|
-
return JSON.parse(
|
|
2612
|
+
return JSON.parse(text2);
|
|
2613
2613
|
}
|
|
2614
2614
|
function scrubInternal(value) {
|
|
2615
2615
|
if (Array.isArray(value)) return value.map(scrubInternal);
|
|
@@ -2652,10 +2652,10 @@ var search = defineCommand13({
|
|
|
2652
2652
|
json: { type: "boolean", description: "Emit JSON instead of a table" }
|
|
2653
2653
|
},
|
|
2654
2654
|
async run({ args }) {
|
|
2655
|
-
const
|
|
2655
|
+
const token = await ensureToken();
|
|
2656
2656
|
const limit = parseInt(args.limit ?? "10", 10) || 10;
|
|
2657
2657
|
const result = await api(
|
|
2658
|
-
|
|
2658
|
+
token,
|
|
2659
2659
|
`/api/domains/search?q=${encodeURIComponent(args.query)}&limit=${limit}`
|
|
2660
2660
|
);
|
|
2661
2661
|
if (args.json) {
|
|
@@ -2685,9 +2685,9 @@ var buy = defineCommand13({
|
|
|
2685
2685
|
json: { type: "boolean", description: "Emit JSON to stdout", default: false }
|
|
2686
2686
|
},
|
|
2687
2687
|
async run({ args }) {
|
|
2688
|
-
const
|
|
2688
|
+
const token = await ensureToken();
|
|
2689
2689
|
const appName = requireAppName(args.app);
|
|
2690
|
-
const priceCheck = await api(
|
|
2690
|
+
const priceCheck = await api(token, "/api/domains/check", {
|
|
2691
2691
|
method: "POST",
|
|
2692
2692
|
body: JSON.stringify({ domains: [args.domain] })
|
|
2693
2693
|
});
|
|
@@ -2708,7 +2708,7 @@ var buy = defineCommand13({
|
|
|
2708
2708
|
}
|
|
2709
2709
|
}
|
|
2710
2710
|
const checkout = await api(
|
|
2711
|
-
|
|
2711
|
+
token,
|
|
2712
2712
|
"/api/domains/checkout",
|
|
2713
2713
|
{
|
|
2714
2714
|
method: "POST",
|
|
@@ -2735,7 +2735,7 @@ var buy = defineCommand13({
|
|
|
2735
2735
|
await new Promise((r) => setTimeout(r, 5e3));
|
|
2736
2736
|
try {
|
|
2737
2737
|
const detail = await api(
|
|
2738
|
-
|
|
2738
|
+
token,
|
|
2739
2739
|
`/api/domains/${checkout.purchaseId}`
|
|
2740
2740
|
);
|
|
2741
2741
|
if (detail.domain.status !== lastStatus) {
|
|
@@ -2769,8 +2769,8 @@ var list2 = defineCommand13({
|
|
|
2769
2769
|
json: { type: "boolean", description: "Emit JSON" }
|
|
2770
2770
|
},
|
|
2771
2771
|
async run({ args }) {
|
|
2772
|
-
const
|
|
2773
|
-
const result = await api(
|
|
2772
|
+
const token = await ensureToken();
|
|
2773
|
+
const result = await api(token, "/api/domains");
|
|
2774
2774
|
if (args.json) {
|
|
2775
2775
|
process.stdout.write(JSON.stringify(scrubInternal(result), null, 2) + "\n");
|
|
2776
2776
|
return;
|
|
@@ -2794,8 +2794,8 @@ var status = defineCommand13({
|
|
|
2794
2794
|
json: { type: "boolean" }
|
|
2795
2795
|
},
|
|
2796
2796
|
async run({ args }) {
|
|
2797
|
-
const
|
|
2798
|
-
const all = await api(
|
|
2797
|
+
const token = await ensureToken();
|
|
2798
|
+
const all = await api(token, "/api/domains");
|
|
2799
2799
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2800
2800
|
if (!found) {
|
|
2801
2801
|
console.error(`No domain ${args.domain} in your account`);
|
|
@@ -2823,16 +2823,16 @@ var attach = defineCommand13({
|
|
|
2823
2823
|
json: { type: "boolean" }
|
|
2824
2824
|
},
|
|
2825
2825
|
async run({ args }) {
|
|
2826
|
-
const
|
|
2826
|
+
const token = await ensureToken();
|
|
2827
2827
|
const targetApp = requireAppName(args.app);
|
|
2828
|
-
const all = await api(
|
|
2828
|
+
const all = await api(token, "/api/domains");
|
|
2829
2829
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2830
2830
|
if (!found) {
|
|
2831
2831
|
console.error(`No domain ${args.domain} in your account`);
|
|
2832
2832
|
process.exit(1);
|
|
2833
2833
|
}
|
|
2834
2834
|
const result = await api(
|
|
2835
|
-
|
|
2835
|
+
token,
|
|
2836
2836
|
`/api/domains/${found.id}/reattach`,
|
|
2837
2837
|
{
|
|
2838
2838
|
method: "POST",
|
|
@@ -2856,8 +2856,8 @@ var detach = defineCommand13({
|
|
|
2856
2856
|
yes: { type: "boolean", description: "Skip the confirmation prompt" }
|
|
2857
2857
|
},
|
|
2858
2858
|
async run({ args }) {
|
|
2859
|
-
const
|
|
2860
|
-
const all = await api(
|
|
2859
|
+
const token = await ensureToken();
|
|
2860
|
+
const all = await api(token, "/api/domains");
|
|
2861
2861
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2862
2862
|
if (!found) {
|
|
2863
2863
|
console.error(`No domain ${args.domain} in your account`);
|
|
@@ -2872,7 +2872,7 @@ var detach = defineCommand13({
|
|
|
2872
2872
|
return;
|
|
2873
2873
|
}
|
|
2874
2874
|
}
|
|
2875
|
-
await api(
|
|
2875
|
+
await api(token, `/api/domains/${found.id}`, { method: "DELETE" });
|
|
2876
2876
|
console.log(`\u2713 ${args.domain} detached. Use \`deepspace domain attach\` to re-route, or \`renew --auto off\` to stop auto-renewal.`);
|
|
2877
2877
|
}
|
|
2878
2878
|
});
|
|
@@ -2887,15 +2887,15 @@ var renew = defineCommand13({
|
|
|
2887
2887
|
console.error('--auto must be "on" or "off"');
|
|
2888
2888
|
process.exit(1);
|
|
2889
2889
|
}
|
|
2890
|
-
const
|
|
2891
|
-
const all = await api(
|
|
2890
|
+
const token = await ensureToken();
|
|
2891
|
+
const all = await api(token, "/api/domains");
|
|
2892
2892
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2893
2893
|
if (!found) {
|
|
2894
2894
|
console.error(`No domain ${args.domain} in your account`);
|
|
2895
2895
|
process.exit(1);
|
|
2896
2896
|
}
|
|
2897
2897
|
const enabled = args.auto === "on";
|
|
2898
|
-
await api(
|
|
2898
|
+
await api(token, `/api/domains/${found.id}/auto-renew`, {
|
|
2899
2899
|
method: "POST",
|
|
2900
2900
|
body: JSON.stringify({ autoRenew: enabled })
|
|
2901
2901
|
});
|
|
@@ -3277,257 +3277,14 @@ var invoke_default = defineCommand15({
|
|
|
3277
3277
|
}
|
|
3278
3278
|
});
|
|
3279
3279
|
|
|
3280
|
-
// src/cli/commands/managed-repos.ts
|
|
3281
|
-
import { defineCommand as defineCommand16 } from "citty";
|
|
3282
|
-
var API_URL4 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
|
|
3283
|
-
var SIMPLE_APP_ID = /^[a-z0-9][a-z0-9_.:-]{0,119}$/i;
|
|
3284
|
-
var SIMPLE_APP_NAME = /^[a-z0-9][a-z0-9_-]{0,119}$/i;
|
|
3285
|
-
async function api2(token2, path, init) {
|
|
3286
|
-
const res = await fetch(`${API_URL4}${path}`, {
|
|
3287
|
-
...init,
|
|
3288
|
-
headers: {
|
|
3289
|
-
Authorization: `Bearer ${token2}`,
|
|
3290
|
-
"Content-Type": "application/json",
|
|
3291
|
-
...init?.headers ?? {}
|
|
3292
|
-
}
|
|
3293
|
-
});
|
|
3294
|
-
const text = await res.text();
|
|
3295
|
-
if (!res.ok) {
|
|
3296
|
-
let msg = text;
|
|
3297
|
-
try {
|
|
3298
|
-
msg = JSON.parse(text).error ?? text;
|
|
3299
|
-
} catch {
|
|
3300
|
-
}
|
|
3301
|
-
throw new Error(`API ${path} (${res.status}): ${msg}`);
|
|
3302
|
-
}
|
|
3303
|
-
return JSON.parse(text);
|
|
3304
|
-
}
|
|
3305
|
-
function defaultAppId(appName) {
|
|
3306
|
-
return `cli-${slugId(appName)}`;
|
|
3307
|
-
}
|
|
3308
|
-
function slugId(raw) {
|
|
3309
|
-
return raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "app";
|
|
3310
|
-
}
|
|
3311
|
-
function assertSimple(value, pattern, label) {
|
|
3312
|
-
if (!pattern.test(value)) {
|
|
3313
|
-
throw new Error(`${label} must start with a letter or number and contain only simple identifier characters.`);
|
|
3314
|
-
}
|
|
3315
|
-
}
|
|
3316
|
-
function printQuota(quota) {
|
|
3317
|
-
console.log(`Repo quota: ${quota.activeCount} / ${quota.limit} active (${quota.remaining} remaining)`);
|
|
3318
|
-
}
|
|
3319
|
-
function printRepo(repo) {
|
|
3320
|
-
console.log(`${repo.fullName}`);
|
|
3321
|
-
console.log(` ID: ${repo.id}`);
|
|
3322
|
-
console.log(` App: ${repo.appName}`);
|
|
3323
|
-
console.log(` App ID: ${repo.appId}`);
|
|
3324
|
-
console.log(` URL: ${repo.htmlUrl}`);
|
|
3325
|
-
console.log(` Clone: ${repo.cloneUrl}`);
|
|
3326
|
-
}
|
|
3327
|
-
async function confirm4(message) {
|
|
3328
|
-
if (!process.stdin.isTTY) {
|
|
3329
|
-
throw new Error(`${message} \u2014 pass --yes to confirm non-interactively`);
|
|
3330
|
-
}
|
|
3331
|
-
process.stdout.write(`${message} [y/N] `);
|
|
3332
|
-
return new Promise((resolve9) => {
|
|
3333
|
-
process.stdin.setEncoding("utf-8");
|
|
3334
|
-
process.stdin.once("data", (data) => {
|
|
3335
|
-
const answer = data.toString().trim().toLowerCase();
|
|
3336
|
-
resolve9(answer === "y" || answer === "yes");
|
|
3337
|
-
});
|
|
3338
|
-
});
|
|
3339
|
-
}
|
|
3340
|
-
var list4 = defineCommand16({
|
|
3341
|
-
meta: {
|
|
3342
|
-
name: "list",
|
|
3343
|
-
description: "List your DeepSpace-managed repos and quota"
|
|
3344
|
-
},
|
|
3345
|
-
args: {
|
|
3346
|
-
json: {
|
|
3347
|
-
type: "boolean",
|
|
3348
|
-
description: "Emit JSON instead of human output",
|
|
3349
|
-
default: false
|
|
3350
|
-
}
|
|
3351
|
-
},
|
|
3352
|
-
async run({ args }) {
|
|
3353
|
-
const token2 = await ensureToken();
|
|
3354
|
-
const result = await api2(token2, "/api/github/repos");
|
|
3355
|
-
if (args.json) {
|
|
3356
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
3357
|
-
return;
|
|
3358
|
-
}
|
|
3359
|
-
printQuota(result.quota);
|
|
3360
|
-
if (result.repos.length === 0) {
|
|
3361
|
-
console.log("No DeepSpace-managed repos. Create one with `deepspace managed-repos create <app-name>`.");
|
|
3362
|
-
return;
|
|
3363
|
-
}
|
|
3364
|
-
console.log("");
|
|
3365
|
-
for (const repo of result.repos) {
|
|
3366
|
-
printRepo(repo);
|
|
3367
|
-
}
|
|
3368
|
-
}
|
|
3369
|
-
});
|
|
3370
|
-
var create2 = defineCommand16({
|
|
3371
|
-
meta: {
|
|
3372
|
-
name: "create",
|
|
3373
|
-
description: "Create a private DeepSpace-managed GitHub repo"
|
|
3374
|
-
},
|
|
3375
|
-
args: {
|
|
3376
|
-
appName: {
|
|
3377
|
-
type: "positional",
|
|
3378
|
-
description: "Working app name for this repo",
|
|
3379
|
-
required: true
|
|
3380
|
-
},
|
|
3381
|
-
appId: {
|
|
3382
|
-
type: "string",
|
|
3383
|
-
description: "Stable DeepSpace repo app id (defaults to cli-<app-name>)",
|
|
3384
|
-
required: false
|
|
3385
|
-
},
|
|
3386
|
-
nameHint: {
|
|
3387
|
-
type: "string",
|
|
3388
|
-
description: "Repo-name hint (defaults to app name)",
|
|
3389
|
-
required: false
|
|
3390
|
-
},
|
|
3391
|
-
json: {
|
|
3392
|
-
type: "boolean",
|
|
3393
|
-
description: "Emit JSON instead of human output",
|
|
3394
|
-
default: false
|
|
3395
|
-
}
|
|
3396
|
-
},
|
|
3397
|
-
async run({ args }) {
|
|
3398
|
-
const appName = String(args.appName);
|
|
3399
|
-
const appId = args.appId ? String(args.appId) : defaultAppId(appName);
|
|
3400
|
-
const nameHint = args.nameHint ? String(args.nameHint) : void 0;
|
|
3401
|
-
try {
|
|
3402
|
-
assertSimple(appName, SIMPLE_APP_NAME, "appName");
|
|
3403
|
-
assertSimple(appId, SIMPLE_APP_ID, "appId");
|
|
3404
|
-
if (nameHint) assertSimple(nameHint, SIMPLE_APP_NAME, "nameHint");
|
|
3405
|
-
} catch (err) {
|
|
3406
|
-
console.error(err.message);
|
|
3407
|
-
process.exit(1);
|
|
3408
|
-
}
|
|
3409
|
-
const token2 = await ensureToken();
|
|
3410
|
-
const result = await api2(token2, "/api/github/repos", {
|
|
3411
|
-
method: "POST",
|
|
3412
|
-
body: JSON.stringify({ appName, appId, ...nameHint ? { nameHint } : {} })
|
|
3413
|
-
});
|
|
3414
|
-
if (args.json) {
|
|
3415
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
3416
|
-
return;
|
|
3417
|
-
}
|
|
3418
|
-
console.log(result.alreadyExists ? "Existing DeepSpace-managed repo:" : "Created DeepSpace-managed repo:");
|
|
3419
|
-
printRepo(result.repo);
|
|
3420
|
-
}
|
|
3421
|
-
});
|
|
3422
|
-
var token = defineCommand16({
|
|
3423
|
-
meta: {
|
|
3424
|
-
name: "token",
|
|
3425
|
-
description: "Mint a short-lived GitHub token for a DeepSpace-managed repo"
|
|
3426
|
-
},
|
|
3427
|
-
args: {
|
|
3428
|
-
repoId: {
|
|
3429
|
-
type: "positional",
|
|
3430
|
-
description: "Repo id from `deepspace managed-repos list`",
|
|
3431
|
-
required: true
|
|
3432
|
-
},
|
|
3433
|
-
json: {
|
|
3434
|
-
type: "boolean",
|
|
3435
|
-
description: "Emit JSON instead of human output",
|
|
3436
|
-
default: false
|
|
3437
|
-
}
|
|
3438
|
-
},
|
|
3439
|
-
async run({ args }) {
|
|
3440
|
-
const jwt = await ensureToken();
|
|
3441
|
-
const result = await api2(
|
|
3442
|
-
jwt,
|
|
3443
|
-
`/api/github/repos/${encodeURIComponent(String(args.repoId))}/agent-token`,
|
|
3444
|
-
{ method: "POST" }
|
|
3445
|
-
);
|
|
3446
|
-
if (args.json) {
|
|
3447
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
3448
|
-
return;
|
|
3449
|
-
}
|
|
3450
|
-
console.log(`Repo: ${result.repo.fullName}`);
|
|
3451
|
-
console.log(`Expires: ${result.token.expiresAt}`);
|
|
3452
|
-
console.log(`Token: ${result.token.token}`);
|
|
3453
|
-
console.log("");
|
|
3454
|
-
console.log(`Clone: git clone https://x-access-token:${encodeURIComponent(result.token.token)}@github.com/${result.repo.fullName}.git`);
|
|
3455
|
-
}
|
|
3456
|
-
});
|
|
3457
|
-
var remove = defineCommand16({
|
|
3458
|
-
meta: {
|
|
3459
|
-
name: "delete",
|
|
3460
|
-
description: "Delete a DeepSpace-managed GitHub repo"
|
|
3461
|
-
},
|
|
3462
|
-
args: {
|
|
3463
|
-
repoId: {
|
|
3464
|
-
type: "positional",
|
|
3465
|
-
description: "Repo id from `deepspace managed-repos list`",
|
|
3466
|
-
required: true
|
|
3467
|
-
},
|
|
3468
|
-
yes: {
|
|
3469
|
-
type: "boolean",
|
|
3470
|
-
description: "Skip the confirmation prompt",
|
|
3471
|
-
default: false
|
|
3472
|
-
},
|
|
3473
|
-
json: {
|
|
3474
|
-
type: "boolean",
|
|
3475
|
-
description: "Emit JSON instead of human output",
|
|
3476
|
-
default: false
|
|
3477
|
-
}
|
|
3478
|
-
},
|
|
3479
|
-
async run({ args }) {
|
|
3480
|
-
if (!args.yes) {
|
|
3481
|
-
try {
|
|
3482
|
-
const ok = await confirm4(
|
|
3483
|
-
"Delete this DeepSpace-managed GitHub repo? This removes the GitHub repository and counts against your daily delete quota."
|
|
3484
|
-
);
|
|
3485
|
-
if (!ok) {
|
|
3486
|
-
console.log("Cancelled.");
|
|
3487
|
-
return;
|
|
3488
|
-
}
|
|
3489
|
-
} catch (err) {
|
|
3490
|
-
console.error(err.message);
|
|
3491
|
-
process.exit(1);
|
|
3492
|
-
}
|
|
3493
|
-
}
|
|
3494
|
-
const jwt = await ensureToken();
|
|
3495
|
-
const result = await api2(
|
|
3496
|
-
jwt,
|
|
3497
|
-
`/api/github/repos/${encodeURIComponent(String(args.repoId))}`,
|
|
3498
|
-
{ method: "DELETE" }
|
|
3499
|
-
);
|
|
3500
|
-
if (args.json) {
|
|
3501
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
3502
|
-
return;
|
|
3503
|
-
}
|
|
3504
|
-
console.log(`Deleted ${result.repo.fullName}`);
|
|
3505
|
-
console.log(
|
|
3506
|
-
`Delete quota: ${result.deletionQuota.deletedCount} / ${result.deletionQuota.limit} used today (${result.deletionQuota.remaining} remaining)`
|
|
3507
|
-
);
|
|
3508
|
-
}
|
|
3509
|
-
});
|
|
3510
|
-
var managed_repos_default = defineCommand16({
|
|
3511
|
-
meta: {
|
|
3512
|
-
name: "managed-repos",
|
|
3513
|
-
description: "Create and manage DeepSpace-owned GitHub repos"
|
|
3514
|
-
},
|
|
3515
|
-
subCommands: {
|
|
3516
|
-
list: list4,
|
|
3517
|
-
create: create2,
|
|
3518
|
-
token,
|
|
3519
|
-
delete: remove
|
|
3520
|
-
}
|
|
3521
|
-
});
|
|
3522
|
-
|
|
3523
3280
|
// src/cli/commands/library.ts
|
|
3524
|
-
import { defineCommand as
|
|
3281
|
+
import { defineCommand as defineCommand16 } from "citty";
|
|
3525
3282
|
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
3526
3283
|
import { join as join12, resolve as resolve8 } from "path";
|
|
3527
3284
|
import { parse as parseToml3 } from "smol-toml";
|
|
3528
3285
|
import * as p6 from "@clack/prompts";
|
|
3529
3286
|
var DEFAULT_LIBRARY_APP = "deepdotspace-site";
|
|
3530
|
-
var publish =
|
|
3287
|
+
var publish = defineCommand16({
|
|
3531
3288
|
meta: {
|
|
3532
3289
|
name: "publish",
|
|
3533
3290
|
description: "Publish the current app to the DeepSpace library"
|
|
@@ -3586,7 +3343,7 @@ var publish = defineCommand17({
|
|
|
3586
3343
|
},
|
|
3587
3344
|
async run({ args }) {
|
|
3588
3345
|
const json = !!args.json;
|
|
3589
|
-
const
|
|
3346
|
+
const intro6 = (s) => {
|
|
3590
3347
|
if (!json) p6.intro(s);
|
|
3591
3348
|
};
|
|
3592
3349
|
const info2 = (s) => {
|
|
@@ -3597,7 +3354,7 @@ var publish = defineCommand17({
|
|
|
3597
3354
|
else p6.cancel(msg);
|
|
3598
3355
|
process.exit(1);
|
|
3599
3356
|
};
|
|
3600
|
-
|
|
3357
|
+
intro6("Publishing to the DeepSpace library");
|
|
3601
3358
|
let appName = typeof args.app === "string" && args.app.trim() ? args.app.trim() : void 0;
|
|
3602
3359
|
if (!appName) {
|
|
3603
3360
|
const appDir = resolve8(typeof args.dir === "string" && args.dir ? args.dir : ".");
|
|
@@ -3618,9 +3375,9 @@ var publish = defineCommand17({
|
|
|
3618
3375
|
const tags = typeof args.tags === "string" && args.tags ? args.tags.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
3619
3376
|
const libraryApp = typeof args["library-app"] === "string" && args["library-app"] ? args["library-app"] : DEFAULT_LIBRARY_APP;
|
|
3620
3377
|
const libraryHost = process.env.DEEPSPACE_LIBRARY_HOST ?? `https://${libraryApp}.app.space`;
|
|
3621
|
-
let
|
|
3378
|
+
let token;
|
|
3622
3379
|
try {
|
|
3623
|
-
|
|
3380
|
+
token = await ensureToken();
|
|
3624
3381
|
} catch (err) {
|
|
3625
3382
|
return die(err instanceof Error ? err.message : String(err));
|
|
3626
3383
|
}
|
|
@@ -3640,7 +3397,7 @@ var publish = defineCommand17({
|
|
|
3640
3397
|
method: "POST",
|
|
3641
3398
|
headers: {
|
|
3642
3399
|
"Content-Type": "application/json",
|
|
3643
|
-
Authorization: `Bearer ${
|
|
3400
|
+
Authorization: `Bearer ${token}`
|
|
3644
3401
|
},
|
|
3645
3402
|
body: JSON.stringify(payload)
|
|
3646
3403
|
});
|
|
@@ -3666,7 +3423,7 @@ var publish = defineCommand17({
|
|
|
3666
3423
|
p6.outro("Done");
|
|
3667
3424
|
}
|
|
3668
3425
|
});
|
|
3669
|
-
var unpublish =
|
|
3426
|
+
var unpublish = defineCommand16({
|
|
3670
3427
|
meta: {
|
|
3671
3428
|
name: "unpublish",
|
|
3672
3429
|
description: "Remove a library entry (owner or admin only)"
|
|
@@ -3696,9 +3453,9 @@ var unpublish = defineCommand17({
|
|
|
3696
3453
|
process.exit(1);
|
|
3697
3454
|
};
|
|
3698
3455
|
if (!json) p6.intro("Unpublishing library entry");
|
|
3699
|
-
let
|
|
3456
|
+
let token;
|
|
3700
3457
|
try {
|
|
3701
|
-
|
|
3458
|
+
token = await ensureToken();
|
|
3702
3459
|
} catch (err) {
|
|
3703
3460
|
return die(err instanceof Error ? err.message : String(err));
|
|
3704
3461
|
}
|
|
@@ -3706,7 +3463,7 @@ var unpublish = defineCommand17({
|
|
|
3706
3463
|
const libraryHost = process.env.DEEPSPACE_LIBRARY_HOST ?? `https://${libraryApp}.app.space`;
|
|
3707
3464
|
const res = await fetch(`${libraryHost}/api/actions/library.unpublish`, {
|
|
3708
3465
|
method: "POST",
|
|
3709
|
-
headers: { "Content-Type": "application/json", Authorization: `Bearer ${
|
|
3466
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
3710
3467
|
body: JSON.stringify({ templateHandle: String(args.handle) })
|
|
3711
3468
|
});
|
|
3712
3469
|
const body = await res.text();
|
|
@@ -3725,7 +3482,7 @@ var unpublish = defineCommand17({
|
|
|
3725
3482
|
p6.outro("Done");
|
|
3726
3483
|
}
|
|
3727
3484
|
});
|
|
3728
|
-
var library_default =
|
|
3485
|
+
var library_default = defineCommand16({
|
|
3729
3486
|
meta: {
|
|
3730
3487
|
name: "library",
|
|
3731
3488
|
description: "Manage your DeepSpace library entries"
|
|
@@ -3736,85 +3493,276 @@ var library_default = defineCommand17({
|
|
|
3736
3493
|
}
|
|
3737
3494
|
});
|
|
3738
3495
|
|
|
3739
|
-
// src/cli/commands/
|
|
3740
|
-
import { defineCommand as
|
|
3741
|
-
import
|
|
3742
|
-
import {
|
|
3743
|
-
import { join as join13 } from "path";
|
|
3744
|
-
|
|
3745
|
-
|
|
3496
|
+
// src/cli/commands/feedback.ts
|
|
3497
|
+
import { defineCommand as defineCommand17 } from "citty";
|
|
3498
|
+
import * as p7 from "@clack/prompts";
|
|
3499
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
3500
|
+
import { dirname as dirname3, join as join13 } from "path";
|
|
3501
|
+
import { fileURLToPath } from "url";
|
|
3502
|
+
import { release } from "os";
|
|
3503
|
+
var API_URL4 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
|
|
3504
|
+
var TYPES = ["bug", "feature", "other"];
|
|
3505
|
+
var TYPE_LABELS = {
|
|
3506
|
+
bug: "Bug report",
|
|
3507
|
+
feature: "Feature request",
|
|
3508
|
+
other: "Other feedback"
|
|
3509
|
+
};
|
|
3510
|
+
var MAX_TITLE_LEN = 200;
|
|
3511
|
+
var MAX_BODY_LEN = 1e4;
|
|
3512
|
+
var MAX_CONTEXT_LEN = 200;
|
|
3513
|
+
async function api2(token, path, init) {
|
|
3514
|
+
const res = await fetch(`${API_URL4}${path}`, {
|
|
3515
|
+
...init,
|
|
3516
|
+
headers: {
|
|
3517
|
+
Authorization: `Bearer ${token}`,
|
|
3518
|
+
"Content-Type": "application/json",
|
|
3519
|
+
...init?.headers ?? {}
|
|
3520
|
+
}
|
|
3521
|
+
});
|
|
3522
|
+
const text2 = await res.text();
|
|
3523
|
+
if (!res.ok) {
|
|
3524
|
+
let msg = text2;
|
|
3525
|
+
try {
|
|
3526
|
+
msg = JSON.parse(text2).error ?? text2;
|
|
3527
|
+
} catch {
|
|
3528
|
+
}
|
|
3529
|
+
throw new Error(`API ${path} (${res.status}): ${msg}`);
|
|
3530
|
+
}
|
|
3531
|
+
return JSON.parse(text2);
|
|
3532
|
+
}
|
|
3533
|
+
function normalizeType(raw) {
|
|
3534
|
+
const value = (raw ?? "bug").toLowerCase();
|
|
3535
|
+
if (TYPES.includes(value)) return value;
|
|
3536
|
+
throw new Error(`Invalid --type "${raw}". Use one of: ${TYPES.join(", ")}.`);
|
|
3537
|
+
}
|
|
3538
|
+
function readCliVersion() {
|
|
3539
|
+
try {
|
|
3540
|
+
const here = dirname3(fileURLToPath(import.meta.url));
|
|
3541
|
+
const candidates = [
|
|
3542
|
+
join13(here, "..", "package.json"),
|
|
3543
|
+
join13(here, "..", "..", "..", "package.json")
|
|
3544
|
+
];
|
|
3545
|
+
for (const path of candidates) {
|
|
3546
|
+
if (!existsSync12(path)) continue;
|
|
3547
|
+
const pkg2 = JSON.parse(readFileSync11(path, "utf-8"));
|
|
3548
|
+
if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
|
|
3549
|
+
}
|
|
3550
|
+
} catch {
|
|
3551
|
+
}
|
|
3552
|
+
return "unknown";
|
|
3553
|
+
}
|
|
3554
|
+
function detectAppName2() {
|
|
3555
|
+
try {
|
|
3556
|
+
const cwd = process.cwd();
|
|
3557
|
+
if (!hasWranglerConfig(cwd)) return void 0;
|
|
3558
|
+
const config = readWranglerConfig(cwd);
|
|
3559
|
+
return typeof config.name === "string" ? config.name : void 0;
|
|
3560
|
+
} catch {
|
|
3561
|
+
return void 0;
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
function clampContext(value) {
|
|
3565
|
+
return value.length > MAX_CONTEXT_LEN ? value.slice(0, MAX_CONTEXT_LEN) : value;
|
|
3566
|
+
}
|
|
3567
|
+
function collectContext() {
|
|
3568
|
+
const appName = detectAppName2();
|
|
3569
|
+
return {
|
|
3570
|
+
cliVersion: clampContext(readCliVersion()),
|
|
3571
|
+
nodeVersion: clampContext(process.version),
|
|
3572
|
+
platform: clampContext(`${process.platform} ${release()}`),
|
|
3573
|
+
...appName ? { appName: clampContext(appName) } : {}
|
|
3574
|
+
};
|
|
3575
|
+
}
|
|
3576
|
+
function buildFeedbackPayload(input) {
|
|
3577
|
+
const title = input.title.trim();
|
|
3578
|
+
const body = input.body.trim();
|
|
3579
|
+
if (!title) throw new Error("A title is required.");
|
|
3580
|
+
if (!body) throw new Error("A message/description is required.");
|
|
3581
|
+
if (title.length > MAX_TITLE_LEN) {
|
|
3582
|
+
throw new Error(
|
|
3583
|
+
`Title must be ${MAX_TITLE_LEN} characters or fewer (got ${title.length}).`
|
|
3584
|
+
);
|
|
3585
|
+
}
|
|
3586
|
+
if (body.length > MAX_BODY_LEN) {
|
|
3587
|
+
throw new Error(
|
|
3588
|
+
`Description must be ${MAX_BODY_LEN} characters or fewer (got ${body.length}).`
|
|
3589
|
+
);
|
|
3590
|
+
}
|
|
3591
|
+
return {
|
|
3592
|
+
type: normalizeType(input.type),
|
|
3593
|
+
title,
|
|
3594
|
+
body,
|
|
3595
|
+
...input.context
|
|
3596
|
+
};
|
|
3597
|
+
}
|
|
3598
|
+
var feedback_default = defineCommand17({
|
|
3746
3599
|
meta: {
|
|
3747
|
-
name: "
|
|
3748
|
-
description: "
|
|
3600
|
+
name: "feedback",
|
|
3601
|
+
description: "Submit a bug report, feature request, or feedback to DeepSpace"
|
|
3749
3602
|
},
|
|
3750
3603
|
args: {
|
|
3751
|
-
|
|
3752
|
-
type: "
|
|
3753
|
-
description: "
|
|
3604
|
+
title: {
|
|
3605
|
+
type: "positional",
|
|
3606
|
+
description: "Short summary (prompted if omitted in a terminal)",
|
|
3754
3607
|
required: false
|
|
3755
3608
|
},
|
|
3756
|
-
|
|
3609
|
+
type: {
|
|
3757
3610
|
type: "string",
|
|
3758
|
-
|
|
3611
|
+
alias: "t",
|
|
3612
|
+
description: `Report type: ${TYPES.join(" | ")} (default: bug)`,
|
|
3759
3613
|
required: false
|
|
3760
3614
|
},
|
|
3761
|
-
|
|
3615
|
+
message: {
|
|
3762
3616
|
type: "string",
|
|
3763
|
-
|
|
3617
|
+
alias: "m",
|
|
3618
|
+
description: "Details / description (prompted if omitted in a terminal)",
|
|
3764
3619
|
required: false
|
|
3620
|
+
},
|
|
3621
|
+
yes: {
|
|
3622
|
+
type: "boolean",
|
|
3623
|
+
description: "Skip the confirmation prompt",
|
|
3624
|
+
default: false
|
|
3625
|
+
},
|
|
3626
|
+
json: {
|
|
3627
|
+
type: "boolean",
|
|
3628
|
+
description: "Emit JSON instead of human output",
|
|
3629
|
+
default: false
|
|
3765
3630
|
}
|
|
3766
3631
|
},
|
|
3767
3632
|
async run({ args }) {
|
|
3768
|
-
const
|
|
3769
|
-
|
|
3770
|
-
|
|
3633
|
+
const interactive = process.stdin.isTTY && !args.json;
|
|
3634
|
+
const fail = (message) => {
|
|
3635
|
+
if (args.json) {
|
|
3636
|
+
process.stdout.write(JSON.stringify({ ok: false, error: message }) + "\n");
|
|
3637
|
+
} else {
|
|
3638
|
+
console.error(message);
|
|
3639
|
+
}
|
|
3771
3640
|
process.exit(1);
|
|
3641
|
+
};
|
|
3642
|
+
let type;
|
|
3643
|
+
try {
|
|
3644
|
+
type = normalizeType(args.type ? String(args.type) : void 0);
|
|
3645
|
+
} catch (err) {
|
|
3646
|
+
return fail(err.message);
|
|
3772
3647
|
}
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3648
|
+
let title = args.title ? String(args.title) : "";
|
|
3649
|
+
let body = args.message ? String(args.message) : "";
|
|
3650
|
+
if ((!title || !body) && !interactive) {
|
|
3651
|
+
return fail(
|
|
3652
|
+
'Provide a title and --message to submit non-interactively, e.g. `deepspace feedback "Title" --message "Details"`.'
|
|
3653
|
+
);
|
|
3776
3654
|
}
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3655
|
+
if (interactive && (!args.type || !title || !body)) {
|
|
3656
|
+
p7.intro("DeepSpace Feedback");
|
|
3657
|
+
if (!args.type) {
|
|
3658
|
+
const picked = await p7.select({
|
|
3659
|
+
message: "What kind of feedback is this?",
|
|
3660
|
+
options: TYPES.map((t) => ({ value: t, label: TYPE_LABELS[t] })),
|
|
3661
|
+
initialValue: type
|
|
3662
|
+
});
|
|
3663
|
+
if (p7.isCancel(picked)) {
|
|
3664
|
+
p7.cancel("Cancelled.");
|
|
3665
|
+
process.exit(0);
|
|
3666
|
+
}
|
|
3667
|
+
type = picked;
|
|
3668
|
+
}
|
|
3669
|
+
if (!title) {
|
|
3670
|
+
const t = await p7.text({
|
|
3671
|
+
message: "Title",
|
|
3672
|
+
placeholder: "Short summary of the issue",
|
|
3673
|
+
validate: (v) => {
|
|
3674
|
+
if (!v?.trim()) return "Title is required";
|
|
3675
|
+
if (v.length > MAX_TITLE_LEN)
|
|
3676
|
+
return `Title must be ${MAX_TITLE_LEN} characters or fewer`;
|
|
3677
|
+
return void 0;
|
|
3678
|
+
}
|
|
3679
|
+
});
|
|
3680
|
+
if (p7.isCancel(t)) {
|
|
3681
|
+
p7.cancel("Cancelled.");
|
|
3682
|
+
process.exit(0);
|
|
3683
|
+
}
|
|
3684
|
+
title = String(t);
|
|
3685
|
+
}
|
|
3686
|
+
if (!body) {
|
|
3687
|
+
const m = await p7.text({
|
|
3688
|
+
message: "Details",
|
|
3689
|
+
placeholder: "What happened? Steps to reproduce, what you expected\u2026",
|
|
3690
|
+
validate: (v) => {
|
|
3691
|
+
if (!v?.trim()) return "A description is required";
|
|
3692
|
+
if (v.length > MAX_BODY_LEN)
|
|
3693
|
+
return `Description must be ${MAX_BODY_LEN} characters or fewer`;
|
|
3694
|
+
return void 0;
|
|
3695
|
+
}
|
|
3696
|
+
});
|
|
3697
|
+
if (p7.isCancel(m)) {
|
|
3698
|
+
p7.cancel("Cancelled.");
|
|
3699
|
+
process.exit(0);
|
|
3700
|
+
}
|
|
3701
|
+
body = String(m);
|
|
3702
|
+
}
|
|
3792
3703
|
}
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
});
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3704
|
+
let payload;
|
|
3705
|
+
try {
|
|
3706
|
+
payload = buildFeedbackPayload({
|
|
3707
|
+
type,
|
|
3708
|
+
title,
|
|
3709
|
+
body,
|
|
3710
|
+
context: collectContext()
|
|
3711
|
+
});
|
|
3712
|
+
} catch (err) {
|
|
3713
|
+
return fail(err.message);
|
|
3714
|
+
}
|
|
3715
|
+
if (interactive && !args.yes) {
|
|
3716
|
+
p7.note(
|
|
3717
|
+
`${TYPE_LABELS[payload.type]}
|
|
3718
|
+
${payload.title}
|
|
3719
|
+
|
|
3720
|
+
${payload.body}
|
|
3721
|
+
|
|
3722
|
+
Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payload.platform}` + (payload.appName ? ` \xB7 app ${payload.appName}` : ""),
|
|
3723
|
+
"Review"
|
|
3724
|
+
);
|
|
3725
|
+
const ok = await p7.confirm({ message: "Send this to the DeepSpace team?" });
|
|
3726
|
+
if (p7.isCancel(ok) || !ok) {
|
|
3727
|
+
p7.cancel("Not sent.");
|
|
3728
|
+
process.exit(0);
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
let token;
|
|
3732
|
+
try {
|
|
3733
|
+
token = await ensureToken();
|
|
3734
|
+
} catch (err) {
|
|
3735
|
+
return fail(err.message ?? "Not signed in. Run `deepspace login`.");
|
|
3736
|
+
}
|
|
3737
|
+
let result;
|
|
3738
|
+
try {
|
|
3739
|
+
result = await api2(token, "/api/feedback", {
|
|
3740
|
+
method: "POST",
|
|
3741
|
+
body: JSON.stringify(payload)
|
|
3742
|
+
});
|
|
3743
|
+
} catch (err) {
|
|
3744
|
+
return fail(err.message);
|
|
3745
|
+
}
|
|
3746
|
+
if (args.json) {
|
|
3747
|
+
process.stdout.write(JSON.stringify({ ok: true, report: result.report }) + "\n");
|
|
3748
|
+
return;
|
|
3749
|
+
}
|
|
3750
|
+
if (interactive) {
|
|
3751
|
+
p7.outro(`Thanks! Submitted as ${result.report.id}.`);
|
|
3752
|
+
} else {
|
|
3753
|
+
console.log(`Submitted feedback ${result.report.id} (${result.report.type}).`);
|
|
3754
|
+
}
|
|
3755
|
+
console.log(`Track triage status at ${DASHBOARD_URL}.`);
|
|
3808
3756
|
}
|
|
3809
3757
|
});
|
|
3810
3758
|
|
|
3811
3759
|
// src/cli/cli.ts
|
|
3812
|
-
var __dirname =
|
|
3813
|
-
var pkg = JSON.parse(
|
|
3814
|
-
if (process.platform === "linux" && !process.env.SSL_CERT_FILE &&
|
|
3760
|
+
var __dirname = dirname4(fileURLToPath2(import.meta.url));
|
|
3761
|
+
var pkg = JSON.parse(readFileSync12(join14(__dirname, "..", "package.json"), "utf-8"));
|
|
3762
|
+
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync13("/etc/ssl/certs/ca-certificates.crt")) {
|
|
3815
3763
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
3816
3764
|
}
|
|
3817
|
-
var
|
|
3765
|
+
var create2 = defineCommand18({
|
|
3818
3766
|
meta: {
|
|
3819
3767
|
name: "create",
|
|
3820
3768
|
description: "Create a new DeepSpace app"
|
|
@@ -3833,14 +3781,14 @@ var create3 = defineCommand19({
|
|
|
3833
3781
|
execSync5(`npm create deepspace@latest${name}`, { stdio: "inherit" });
|
|
3834
3782
|
}
|
|
3835
3783
|
});
|
|
3836
|
-
var main =
|
|
3784
|
+
var main = defineCommand18({
|
|
3837
3785
|
meta: {
|
|
3838
3786
|
name: "deepspace",
|
|
3839
3787
|
version: pkg.version,
|
|
3840
3788
|
description: "DeepSpace SDK CLI"
|
|
3841
3789
|
},
|
|
3842
3790
|
subCommands: {
|
|
3843
|
-
create:
|
|
3791
|
+
create: create2,
|
|
3844
3792
|
login: login_default,
|
|
3845
3793
|
logout: logout_default,
|
|
3846
3794
|
whoami: whoami_default,
|
|
@@ -3852,13 +3800,12 @@ var main = defineCommand19({
|
|
|
3852
3800
|
add: add_default,
|
|
3853
3801
|
skills: skills_default,
|
|
3854
3802
|
integrations: integrations_default,
|
|
3855
|
-
"managed-repos": managed_repos_default,
|
|
3856
3803
|
invoke: invoke_default,
|
|
3857
3804
|
deploy: deploy_default,
|
|
3858
3805
|
undeploy: undeploy_default,
|
|
3859
3806
|
domain: domain_default,
|
|
3860
3807
|
library: library_default,
|
|
3861
|
-
|
|
3808
|
+
feedback: feedback_default
|
|
3862
3809
|
}
|
|
3863
3810
|
// No `run()` here — citty cascades parent run() AFTER subcommand finishes,
|
|
3864
3811
|
// which corrupts agent-friendly output (`--json`) and prints noise on every
|