deepspace 0.10.3 → 0.12.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/CHANGELOG.md +53 -0
- package/dist/cli.js +656 -238
- package/dist/cli.js.map +1 -1
- package/dist/index.js +53 -5
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +29 -1
- package/dist/server.js +27 -2
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +29 -1
- package/dist/worker.js +27 -2
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/cli.ts
|
|
4
|
-
import { defineCommand as
|
|
4
|
+
import { defineCommand as defineCommand14, runMain, runCommand } from "citty";
|
|
5
5
|
import { sync as spawnSync8 } from "cross-spawn";
|
|
6
|
-
import { readFileSync as
|
|
6
|
+
import { readFileSync as readFileSync28, existsSync as existsSync26 } from "fs";
|
|
7
7
|
import { dirname as dirname10, join as join24 } from "path";
|
|
8
8
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9
9
|
|
|
@@ -709,7 +709,7 @@ async function provisionProfile(jwt) {
|
|
|
709
709
|
}
|
|
710
710
|
}
|
|
711
711
|
function sleep(ms) {
|
|
712
|
-
return new Promise((
|
|
712
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
713
713
|
}
|
|
714
714
|
function base64url(bytes) {
|
|
715
715
|
return bytes.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -929,6 +929,7 @@ import { dirname as dirname2, join as join5, resolve as resolve3 } from "path";
|
|
|
929
929
|
// src/cli/lib/git/process.ts
|
|
930
930
|
import { sync as spawnSync } from "cross-spawn";
|
|
931
931
|
var MAX_GIT_BUFFER = 512 * 1024 * 1024;
|
|
932
|
+
var GIT_TIMEOUT_MS = 3e5;
|
|
932
933
|
var GitError = class extends Error {
|
|
933
934
|
constructor(message, code) {
|
|
934
935
|
super(message);
|
|
@@ -937,10 +938,16 @@ var GitError = class extends Error {
|
|
|
937
938
|
}
|
|
938
939
|
};
|
|
939
940
|
function runGit(cwd, args, opts = {}) {
|
|
941
|
+
const timeout = opts.timeoutMs ?? GIT_TIMEOUT_MS;
|
|
940
942
|
const result = spawnSync("git", args, {
|
|
941
943
|
cwd,
|
|
942
944
|
input: opts.input,
|
|
943
945
|
maxBuffer: MAX_GIT_BUFFER,
|
|
946
|
+
timeout,
|
|
947
|
+
// SIGKILL, not the default SIGTERM: a child that ignores or traps TERM
|
|
948
|
+
// would otherwise keep running for its full duration and the "timeout"
|
|
949
|
+
// would bound nothing.
|
|
950
|
+
killSignal: "SIGKILL",
|
|
944
951
|
stdio: ["pipe", "pipe", "pipe"],
|
|
945
952
|
env: {
|
|
946
953
|
...process.env,
|
|
@@ -949,6 +956,12 @@ function runGit(cwd, args, opts = {}) {
|
|
|
949
956
|
...opts.env ?? {}
|
|
950
957
|
}
|
|
951
958
|
});
|
|
959
|
+
if (result.error?.code === "ETIMEDOUT") {
|
|
960
|
+
throw new GitError(
|
|
961
|
+
`git ${args[0]} did not finish within ${Math.round(timeout / 1e3)}s and was stopped. If this was a push, the history is probably too large to transfer \u2014 see \`deepspace push\` for the size limits; otherwise retry, and report it with \`deepspace feedback\` if it persists.`,
|
|
962
|
+
"git_timeout"
|
|
963
|
+
);
|
|
964
|
+
}
|
|
952
965
|
if (result.error) {
|
|
953
966
|
const code = result.error.code;
|
|
954
967
|
if (code === "ENOENT") {
|
|
@@ -2534,10 +2547,10 @@ function formatSchemaLintFindings(findings) {
|
|
|
2534
2547
|
import { createServer } from "net";
|
|
2535
2548
|
var DEFAULT_PORT = 5173;
|
|
2536
2549
|
function checkPortAvailable(port, host = "0.0.0.0") {
|
|
2537
|
-
return new Promise((
|
|
2550
|
+
return new Promise((resolve19) => {
|
|
2538
2551
|
const srv = createServer();
|
|
2539
|
-
srv.once("error", () =>
|
|
2540
|
-
srv.once("listening", () => srv.close(() =>
|
|
2552
|
+
srv.once("error", () => resolve19(false));
|
|
2553
|
+
srv.once("listening", () => srv.close(() => resolve19(true)));
|
|
2541
2554
|
srv.listen(port, host);
|
|
2542
2555
|
});
|
|
2543
2556
|
}
|
|
@@ -3679,8 +3692,8 @@ var clear = defineDeepspaceCommand({
|
|
|
3679
3692
|
failures.push({ email: a.email, error: err.message });
|
|
3680
3693
|
}
|
|
3681
3694
|
}
|
|
3682
|
-
const deleted = targets.filter((
|
|
3683
|
-
removeTestAccounts(deleted.map((
|
|
3695
|
+
const deleted = targets.filter((target2) => !failures.some((failure) => failure.email === target2.email));
|
|
3696
|
+
removeTestAccounts(deleted.map((target2) => target2.id), deleted.map((target2) => target2.email));
|
|
3684
3697
|
if (failures.length > 0) {
|
|
3685
3698
|
throw new Refusal(
|
|
3686
3699
|
`Deleted ${ok2}/${targets.length} test account(s).
|
|
@@ -3715,6 +3728,7 @@ import { resolve as resolve12 } from "path";
|
|
|
3715
3728
|
// src/cli/commands/deploy/build.ts
|
|
3716
3729
|
import * as p6 from "@clack/prompts";
|
|
3717
3730
|
import { execSync as execSync2 } from "child_process";
|
|
3731
|
+
import { createHash as createHash2 } from "crypto";
|
|
3718
3732
|
import { existsSync as existsSync15, readFileSync as readFileSync17, readdirSync as readdirSync4 } from "fs";
|
|
3719
3733
|
import { dirname as dirname5, join as join16, resolve as resolve10 } from "path";
|
|
3720
3734
|
|
|
@@ -4174,9 +4188,12 @@ function collectAssets(dir) {
|
|
|
4174
4188
|
if (entry.isDirectory()) {
|
|
4175
4189
|
walk(fullPath, relativePath);
|
|
4176
4190
|
} else {
|
|
4191
|
+
const bytes = readFileSync17(fullPath);
|
|
4177
4192
|
assets.push({
|
|
4178
4193
|
path: `/${relativePath}`,
|
|
4179
|
-
|
|
4194
|
+
hash: createHash2("sha256").update(bytes).digest("hex"),
|
|
4195
|
+
size: bytes.byteLength,
|
|
4196
|
+
sourcePath: fullPath
|
|
4180
4197
|
});
|
|
4181
4198
|
}
|
|
4182
4199
|
}
|
|
@@ -4463,7 +4480,7 @@ function createDeployOutput(json) {
|
|
|
4463
4480
|
|
|
4464
4481
|
// src/cli/commands/deploy/request.ts
|
|
4465
4482
|
import * as p10 from "@clack/prompts";
|
|
4466
|
-
import {
|
|
4483
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
4467
4484
|
|
|
4468
4485
|
// src/cli/commands/deploy/repository.ts
|
|
4469
4486
|
import * as p9 from "@clack/prompts";
|
|
@@ -4653,6 +4670,37 @@ function repoApi(deployUrl, token, appId) {
|
|
|
4653
4670
|
};
|
|
4654
4671
|
}
|
|
4655
4672
|
|
|
4673
|
+
// src/shared/app-files.ts
|
|
4674
|
+
var MAX_APP_FILE_BYTES = 25 * 1024 * 1024;
|
|
4675
|
+
function formatBytes(bytes) {
|
|
4676
|
+
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
4677
|
+
if (bytes >= 1024) return `${Math.round(bytes / 1024)} KiB`;
|
|
4678
|
+
return `${bytes} B`;
|
|
4679
|
+
}
|
|
4680
|
+
function encodeKeyPath(key) {
|
|
4681
|
+
return key.split("/").map(encodeURIComponent).join("/");
|
|
4682
|
+
}
|
|
4683
|
+
function oversizeMessage(bytes) {
|
|
4684
|
+
return `That file is ${formatBytes(bytes)}; the limit is ${formatBytes(MAX_APP_FILE_BYTES)} per file.`;
|
|
4685
|
+
}
|
|
4686
|
+
function describeFilesFailure(status3, body) {
|
|
4687
|
+
const trimmed = body.trim();
|
|
4688
|
+
if (trimmed.startsWith("{")) {
|
|
4689
|
+
try {
|
|
4690
|
+
const parsed = JSON.parse(trimmed);
|
|
4691
|
+
if (parsed.error) return parsed.error;
|
|
4692
|
+
} catch {
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
if (status3 === 413) {
|
|
4696
|
+
return `The file is too large to upload. The limit is ${formatBytes(MAX_APP_FILE_BYTES)} per file; larger uploads are rejected by the network before the app receives them.`;
|
|
4697
|
+
}
|
|
4698
|
+
if (status3 === 401 || status3 === 403) return "Not authorized to write these files.";
|
|
4699
|
+
if (status3 === 415) return "That file type is not accepted.";
|
|
4700
|
+
if (status3 >= 500) return `The files service failed (HTTP ${status3}). Retry shortly.`;
|
|
4701
|
+
return `Upload failed (HTTP ${status3}).`;
|
|
4702
|
+
}
|
|
4703
|
+
|
|
4656
4704
|
// src/cli/lib/vc-remote.ts
|
|
4657
4705
|
import { existsSync as existsSync17 } from "fs";
|
|
4658
4706
|
import { tmpdir } from "os";
|
|
@@ -4817,7 +4865,7 @@ function isThinPackRejection(result) {
|
|
|
4817
4865
|
function isRecoverablePushFailure(status3) {
|
|
4818
4866
|
return status3 === "non_fast_forward" || status3 === "ref_conflict";
|
|
4819
4867
|
}
|
|
4820
|
-
function classifyPushTransportFailure(error) {
|
|
4868
|
+
function classifyPushTransportFailure(error, cwd) {
|
|
4821
4869
|
const message = error instanceof Error ? error.message : String(error);
|
|
4822
4870
|
if (/(?:HTTP |error: )409\b/i.test(message)) {
|
|
4823
4871
|
return {
|
|
@@ -4837,6 +4885,9 @@ function classifyPushTransportFailure(error) {
|
|
|
4837
4885
|
error: "The cloud repo rate-limited this push. Wait a few seconds, then retry."
|
|
4838
4886
|
};
|
|
4839
4887
|
}
|
|
4888
|
+
if (/(?:HTTP |error: )413\b/i.test(message)) {
|
|
4889
|
+
return { code: "push_too_large", error: pushTooLargeMessage(cwd) };
|
|
4890
|
+
}
|
|
4840
4891
|
return null;
|
|
4841
4892
|
}
|
|
4842
4893
|
function pushToSpace(cwd, token, refspec, opts = {}) {
|
|
@@ -4861,18 +4912,28 @@ function pushToSpace(cwd, token, refspec, opts = {}) {
|
|
|
4861
4912
|
}
|
|
4862
4913
|
var OVERSIZED_PUSH_RE = /too large|exceeds|\bLFS\b/i;
|
|
4863
4914
|
var SERVER_OBJECT_CAP_BYTES = 20 * 1024 * 1024;
|
|
4864
|
-
var
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
return
|
|
4869
|
-
}
|
|
4870
|
-
function
|
|
4871
|
-
|
|
4872
|
-
if (objects.length === 0) return OVERSIZED_PUSH_FIX;
|
|
4915
|
+
var SERVER_PACK_CAP_BYTES = 32 * 1024 * 1024;
|
|
4916
|
+
var OVERSIZED_PUSH_FIX = `Find the offending object with \`git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectsize) %(rest)' | sort -k2 -n | tail\`.`;
|
|
4917
|
+
function removeFromHistoryAdvice(path) {
|
|
4918
|
+
const file = path ? shQuote(path) : "<file>";
|
|
4919
|
+
return `Media belongs in the app's files rather than Git history \u2014 \`deepspace app files put ${file}\` stores it in the app's own allocation and serves it over HTTP. Then get it out of the push: add it to .gitignore, and drop it from the commits that carry it \u2014 if those commits are still local, \`git reset --soft <last pushed commit>\` and re-commit without the file. \`git rm --cached\` plus a new commit is NOT sufficient on its own: the blob stays reachable from the earlier commit and the push is rejected the same way. If it already reached pushed history, rewrite it out (\`git filter-repo --path ${file} --invert-paths\`).`;
|
|
4920
|
+
}
|
|
4921
|
+
function fixForObjects(objects) {
|
|
4922
|
+
if (objects.length === 0) return `${OVERSIZED_PUSH_FIX} ${removeFromHistoryAdvice(null)}`;
|
|
4873
4923
|
const one = objects.length === 1;
|
|
4874
4924
|
const named = objects.map((object) => `${object.path} (${formatBytes(object.bytes)})`).join(", ");
|
|
4875
|
-
return `The oversized ${one ? "file is" : "files are"} ${named}.
|
|
4925
|
+
return `The oversized ${one ? "file is" : "files are"} ${named}. ${removeFromHistoryAdvice(one ? objects[0].path : null)}`;
|
|
4926
|
+
}
|
|
4927
|
+
function oversizedPushFix(cwd, cap = SERVER_OBJECT_CAP_BYTES) {
|
|
4928
|
+
return fixForObjects(cwd ? findOversizedObjects(cwd, cap) : []);
|
|
4929
|
+
}
|
|
4930
|
+
function pushTooLargeMessage(cwd) {
|
|
4931
|
+
const ceilings = `The cloud repo refused this push as too large (HTTP 413). The ceilings are ${formatBytes(SERVER_OBJECT_CAP_BYTES)} per file and ${formatBytes(SERVER_PACK_CAP_BYTES)} of compressed history per push. Large media never compresses, so every clone would pay for it forever.`;
|
|
4932
|
+
const objects = cwd ? findOversizedObjects(cwd, SERVER_OBJECT_CAP_BYTES) : [];
|
|
4933
|
+
if (objects.length === 0) {
|
|
4934
|
+
return `${ceilings} No single file is over the per-file cap, so this is the volume of history \u2014 push it in smaller batches (\`git push space <earlier-commit>:refs/heads/<branch>\` first, then the rest). ${OVERSIZED_PUSH_FIX}`;
|
|
4935
|
+
}
|
|
4936
|
+
return `${ceilings} ${fixForObjects(objects)}`;
|
|
4876
4937
|
}
|
|
4877
4938
|
function pushFailureMessage(label, push, cwd) {
|
|
4878
4939
|
const reason = push.reason ?? push.summary ?? "";
|
|
@@ -4962,7 +5023,7 @@ function remotePublicRefs(cwd, remote) {
|
|
|
4962
5023
|
function remoteBranchOid(cwd, remote, branch) {
|
|
4963
5024
|
return remotePublicRefs(cwd, remote).find((ref) => ref.name === `refs/heads/${branch}`)?.oid ?? null;
|
|
4964
5025
|
}
|
|
4965
|
-
function localTransferRefs(cwd, prefix,
|
|
5026
|
+
function localTransferRefs(cwd, prefix, target2) {
|
|
4966
5027
|
const output = runGit(cwd, [
|
|
4967
5028
|
"for-each-ref",
|
|
4968
5029
|
"--format=%(refname) %(objectname)",
|
|
@@ -4970,7 +5031,7 @@ function localTransferRefs(cwd, prefix, target) {
|
|
|
4970
5031
|
]).stdout.toString("utf-8");
|
|
4971
5032
|
return output.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
4972
5033
|
const [name, oid] = line.split(/\s+/, 2);
|
|
4973
|
-
return { name: `${
|
|
5034
|
+
return { name: `${target2}/${name.slice(`${prefix}/`.length)}`, oid };
|
|
4974
5035
|
}).filter((ref) => /^[0-9a-f]{40}$/.test(ref.oid));
|
|
4975
5036
|
}
|
|
4976
5037
|
|
|
@@ -5083,7 +5144,7 @@ async function syncDeployRepository(options) {
|
|
|
5083
5144
|
}
|
|
5084
5145
|
} else if (pushResult.status === "rejected") {
|
|
5085
5146
|
output.die(
|
|
5086
|
-
|
|
5147
|
+
`${pushFailureMessage("Cloud repo push", pushResult, appDir)} Publish the commit before deploying.`,
|
|
5087
5148
|
"vc_push_rejected"
|
|
5088
5149
|
);
|
|
5089
5150
|
} else {
|
|
@@ -5127,7 +5188,7 @@ async function syncDeployRepository(options) {
|
|
|
5127
5188
|
sourceRevision = claimed.revision;
|
|
5128
5189
|
}
|
|
5129
5190
|
} catch (error) {
|
|
5130
|
-
const failure = deployRepositoryFailure(error);
|
|
5191
|
+
const failure = deployRepositoryFailure(error, appDir);
|
|
5131
5192
|
output.die(failure.error, failure.code);
|
|
5132
5193
|
}
|
|
5133
5194
|
return { commitOid, recoverable, deployKey, source, sourceRevision, baseReleaseId };
|
|
@@ -5154,8 +5215,8 @@ function classifyRemoteState(appDir, token, branch, localTip, remote) {
|
|
|
5154
5215
|
function errorMessage3(error) {
|
|
5155
5216
|
return error instanceof Error ? error.message : String(error);
|
|
5156
5217
|
}
|
|
5157
|
-
function deployRepositoryFailure(error) {
|
|
5158
|
-
const transportFailure = classifyPushTransportFailure(error);
|
|
5218
|
+
function deployRepositoryFailure(error, cwd) {
|
|
5219
|
+
const transportFailure = classifyPushTransportFailure(error, cwd);
|
|
5159
5220
|
if (transportFailure) return transportFailure;
|
|
5160
5221
|
const code = errorCode(error);
|
|
5161
5222
|
const message = errorMessage3(error);
|
|
@@ -5165,15 +5226,18 @@ function deployRepositoryFailure(error) {
|
|
|
5165
5226
|
error: `Version-control sync failed: ${message}`
|
|
5166
5227
|
};
|
|
5167
5228
|
}
|
|
5229
|
+
var PUSH_RETRY_BUDGET_MS = 12e4;
|
|
5168
5230
|
async function pushWithTransientRetry(push) {
|
|
5169
5231
|
const backoffMs = [500, 1500, 3500];
|
|
5232
|
+
const deadline = Date.now() + PUSH_RETRY_BUDGET_MS;
|
|
5170
5233
|
for (let attempt = 0; ; attempt++) {
|
|
5171
5234
|
try {
|
|
5172
5235
|
return push();
|
|
5173
5236
|
} catch (error) {
|
|
5174
5237
|
const message = errorMessage3(error);
|
|
5175
|
-
|
|
5176
|
-
|
|
5238
|
+
const transient = /(?:HTTP |error: )(?:429|503)\b/i.test(message);
|
|
5239
|
+
if (transient && attempt < backoffMs.length && Date.now() + backoffMs[attempt] < deadline) {
|
|
5240
|
+
await new Promise((resolve19) => setTimeout(resolve19, backoffMs[attempt]));
|
|
5177
5241
|
continue;
|
|
5178
5242
|
}
|
|
5179
5243
|
throw error;
|
|
@@ -5203,12 +5267,9 @@ function detachedHeadRefusal() {
|
|
|
5203
5267
|
|
|
5204
5268
|
// src/cli/commands/deploy/request.ts
|
|
5205
5269
|
var CLOUDFLARE_DEPLOY_ERROR_HINT = "Deployment reached the DeepSpace deploy worker, but Cloudflare's deployment control-plane API failed. This is often caused by a Cloudflare Dashboard/API incident or Workers for Platforms entitlement outage. Already deployed apps should keep serving; wait for Cloudflare to recover and retry.";
|
|
5206
|
-
var
|
|
5207
|
-
var
|
|
5208
|
-
|
|
5209
|
-
const bytes = Number.isInteger(configured) && configured > 0 ? configured : 3 * 1024 * 1024;
|
|
5210
|
-
return Math.min(bytes, MAX_GROUP_BYTES);
|
|
5211
|
-
})();
|
|
5270
|
+
var DEPLOY_SERVICE_LIMIT_HINT = "The DeepSpace deploy service hit a resource limit processing this deploy (the deploy worker was terminated before it could answer). This is a DeepSpace-side failure, not a Cloudflare incident \u2014 your app was not changed. Retry; if it keeps happening, report the app id and asset count.";
|
|
5271
|
+
var REQUIRED_ASSET_TRANSPORT = "content-addressed-v1";
|
|
5272
|
+
var UPLOAD_CONCURRENCY = 4;
|
|
5212
5273
|
async function deployBuiltBundle(options) {
|
|
5213
5274
|
const {
|
|
5214
5275
|
deployUrl,
|
|
@@ -5229,44 +5290,11 @@ async function deployBuiltBundle(options) {
|
|
|
5229
5290
|
} else if (bundle.extraRoutes.length) {
|
|
5230
5291
|
p10.log.info(`Custom worker-first routes: ${bundle.extraRoutes.join(", ")}`);
|
|
5231
5292
|
}
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
const uploadId = randomUUID2();
|
|
5235
|
-
const totalGroups = assetGroups.length;
|
|
5236
|
-
try {
|
|
5237
|
-
for (let index = 0; index < totalGroups; index++) {
|
|
5238
|
-
const groupJson = JSON.stringify(assetGroups[index]);
|
|
5239
|
-
spinner2.message(`Uploading assets \u2014 group ${index + 1}/${totalGroups}...`);
|
|
5240
|
-
const groupResponse = await postWithRetry(
|
|
5241
|
-
`${deployUrl}/api/deploy/${appId}/assets?uploadId=${uploadId}&groupIndex=${index}&totalGroups=${totalGroups}`,
|
|
5242
|
-
() => ({
|
|
5243
|
-
method: "POST",
|
|
5244
|
-
headers: {
|
|
5245
|
-
Authorization: `Bearer ${token}`,
|
|
5246
|
-
"Content-Type": "application/json"
|
|
5247
|
-
},
|
|
5248
|
-
body: groupJson
|
|
5249
|
-
})
|
|
5250
|
-
);
|
|
5251
|
-
if (!groupResponse.ok) {
|
|
5252
|
-
const errorBody = await groupResponse.json().catch(() => ({}));
|
|
5253
|
-
await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
|
|
5254
|
-
spinner2.stop("Deploy failed");
|
|
5255
|
-
output.die(
|
|
5256
|
-
`Asset upload failed on group ${index + 1}/${totalGroups}: ${errorBody.error ?? `HTTP ${groupResponse.status}`}`,
|
|
5257
|
-
"upload_failed"
|
|
5258
|
-
);
|
|
5259
|
-
}
|
|
5260
|
-
}
|
|
5261
|
-
} catch (error) {
|
|
5262
|
-
await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
|
|
5263
|
-
spinner2.stop("Deploy failed");
|
|
5264
|
-
output.die(`Asset upload failed (network): ${errorMessage4(error)}`, "upload_failed");
|
|
5265
|
-
}
|
|
5293
|
+
await requireAssetTransport(deployUrl, spinner2, output);
|
|
5294
|
+
await uploadDeployAssets({ deployUrl, appId, token, assets: bundle.assets, output, spinner: spinner2 });
|
|
5266
5295
|
spinner2.message(`Deploying ${appName}...`);
|
|
5267
5296
|
let confirmRename = options.rename;
|
|
5268
5297
|
const bail = async (message, stopLabel = "Deploy failed", code, actionRequired = false, action) => {
|
|
5269
|
-
await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
|
|
5270
5298
|
if (stopLabel !== null) spinner2.stop(stopLabel);
|
|
5271
5299
|
p10.cancel(code ? withSlug(message, code) : message);
|
|
5272
5300
|
if (action) printAction(action);
|
|
@@ -5288,8 +5316,7 @@ async function deployBuiltBundle(options) {
|
|
|
5288
5316
|
new Blob([bundle.workerJs], { type: "application/javascript" }),
|
|
5289
5317
|
"worker.js"
|
|
5290
5318
|
);
|
|
5291
|
-
form.append("
|
|
5292
|
-
form.append("totalGroups", String(totalGroups));
|
|
5319
|
+
form.append("assetManifest", JSON.stringify(assetManifest(bundle.assets)));
|
|
5293
5320
|
form.append("appMigrations", JSON.stringify(bundle.appMigrations));
|
|
5294
5321
|
if (bundle.doManifest) form.append("doManifest", JSON.stringify(bundle.doManifest));
|
|
5295
5322
|
if (bundle.customBindings.length) {
|
|
@@ -5368,7 +5395,11 @@ async function deployBuiltBundle(options) {
|
|
|
5368
5395
|
);
|
|
5369
5396
|
}
|
|
5370
5397
|
if (!response.ok || !body.success) {
|
|
5371
|
-
await bail(
|
|
5398
|
+
await bail(
|
|
5399
|
+
formatDeployWorkerError(response.status, body.error, body.code),
|
|
5400
|
+
"Deploy failed",
|
|
5401
|
+
body.code
|
|
5402
|
+
);
|
|
5372
5403
|
}
|
|
5373
5404
|
if (body.onBehalfOfOwner) {
|
|
5374
5405
|
p10.log.warn(`Deployed on behalf of owner ${body.onBehalfOfOwner}`);
|
|
@@ -5385,17 +5416,139 @@ async function deployBuiltBundle(options) {
|
|
|
5385
5416
|
}
|
|
5386
5417
|
return body;
|
|
5387
5418
|
}
|
|
5388
|
-
|
|
5419
|
+
function assetManifest(assets) {
|
|
5420
|
+
return assets.map((asset) => ({ path: asset.path, hash: asset.hash, size: asset.size }));
|
|
5421
|
+
}
|
|
5422
|
+
async function requireAssetTransport(deployUrl, spinner2, output) {
|
|
5423
|
+
let advertised;
|
|
5389
5424
|
try {
|
|
5390
|
-
await fetch(
|
|
5391
|
-
|
|
5392
|
-
|
|
5425
|
+
const response = await fetch(`${deployUrl}/api/health`);
|
|
5426
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
5427
|
+
const body = await response.json();
|
|
5428
|
+
advertised = body.capabilities?.assetTransport;
|
|
5429
|
+
} catch (error) {
|
|
5430
|
+
spinner2.stop("Deploy failed");
|
|
5431
|
+
output.die(
|
|
5432
|
+
`Could not reach the DeepSpace deploy service at ${deployUrl} to check its capabilities: ${errorMessage4(error)}`,
|
|
5433
|
+
"deploy_service_unreachable"
|
|
5393
5434
|
);
|
|
5394
|
-
}
|
|
5435
|
+
}
|
|
5436
|
+
if (advertised !== REQUIRED_ASSET_TRANSPORT) {
|
|
5437
|
+
spinner2.stop("Deploy failed");
|
|
5438
|
+
output.die(
|
|
5439
|
+
`The DeepSpace deploy service at ${deployUrl} does not support this CLI's asset transport (needs "${REQUIRED_ASSET_TRANSPORT}", found ${advertised === void 0 ? "none" : `"${String(advertised)}"`}). Wait for the platform to finish updating, or pin an older deepspace CLI.`,
|
|
5440
|
+
"asset_transport_unsupported"
|
|
5441
|
+
);
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5444
|
+
async function uploadDeployAssets(options) {
|
|
5445
|
+
const { deployUrl, appId, token, assets, spinner: spinner2 } = options;
|
|
5446
|
+
const output = options.output;
|
|
5447
|
+
const byHash = new Map(assets.map((asset) => [asset.hash, asset]));
|
|
5448
|
+
spinner2.message("Checking which assets are already uploaded...");
|
|
5449
|
+
let planResponse;
|
|
5450
|
+
try {
|
|
5451
|
+
planResponse = await postWithRetry(`${deployUrl}/api/deploy/${appId}/asset-plan`, () => ({
|
|
5452
|
+
method: "POST",
|
|
5453
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
5454
|
+
body: JSON.stringify({
|
|
5455
|
+
assets: [...byHash.values()].map((asset) => ({ hash: asset.hash, size: asset.size }))
|
|
5456
|
+
})
|
|
5457
|
+
}));
|
|
5458
|
+
} catch (error) {
|
|
5459
|
+
spinner2.stop("Deploy failed");
|
|
5460
|
+
output.die(`Asset plan failed (network): ${errorMessage4(error)}`, "upload_failed");
|
|
5461
|
+
}
|
|
5462
|
+
const planBody = await planResponse.json().catch(() => ({}));
|
|
5463
|
+
if (!planResponse.ok) {
|
|
5464
|
+
spinner2.stop("Deploy failed");
|
|
5465
|
+
output.die(
|
|
5466
|
+
formatDeployWorkerError(planResponse.status, planBody.error, planBody.code),
|
|
5467
|
+
planBody.code ?? "upload_failed"
|
|
5468
|
+
);
|
|
5469
|
+
}
|
|
5470
|
+
const missing = [];
|
|
5471
|
+
for (const hash of planBody.missing ?? []) {
|
|
5472
|
+
const asset = byHash.get(hash);
|
|
5473
|
+
if (!asset) {
|
|
5474
|
+
spinner2.stop("Deploy failed");
|
|
5475
|
+
output.die(
|
|
5476
|
+
`The deploy service asked for asset ${hash}, which is not part of this build. Re-run the deploy; if it persists, report the app id.`,
|
|
5477
|
+
"upload_failed"
|
|
5478
|
+
);
|
|
5479
|
+
}
|
|
5480
|
+
missing.push(asset);
|
|
5481
|
+
}
|
|
5482
|
+
if (missing.length === 0) {
|
|
5483
|
+
p10.log.info(`Assets: ${byHash.size} file(s), all already uploaded`);
|
|
5484
|
+
return;
|
|
5485
|
+
}
|
|
5486
|
+
const missingBytes = missing.reduce((total, asset) => total + asset.size, 0);
|
|
5487
|
+
p10.log.info(
|
|
5488
|
+
`Assets: ${byHash.size} file(s), uploading ${missing.length} (${Math.ceil(missingBytes / 1024)} KiB); the rest are already stored`
|
|
5489
|
+
);
|
|
5490
|
+
let uploaded = 0;
|
|
5491
|
+
const next = () => missing.pop();
|
|
5492
|
+
const worker = async () => {
|
|
5493
|
+
for (let asset = next(); asset; asset = next()) {
|
|
5494
|
+
const response = await postWithRetry(
|
|
5495
|
+
`${deployUrl}/api/deploy/${appId}/assets/${asset.hash}`,
|
|
5496
|
+
() => ({
|
|
5497
|
+
method: "PUT",
|
|
5498
|
+
headers: {
|
|
5499
|
+
Authorization: `Bearer ${token}`,
|
|
5500
|
+
"Content-Type": "application/octet-stream"
|
|
5501
|
+
},
|
|
5502
|
+
// Read whole, per attempt. The platform matches Content-Length
|
|
5503
|
+
// against the plan before it touches storage, and a stream body
|
|
5504
|
+
// would be sent chunked with no length at all; a retry also needs a
|
|
5505
|
+
// body it can send again.
|
|
5506
|
+
body: readFileSync18(asset.sourcePath)
|
|
5507
|
+
})
|
|
5508
|
+
);
|
|
5509
|
+
if (!response.ok) {
|
|
5510
|
+
const body = await response.json().catch(() => ({}));
|
|
5511
|
+
throw new AssetUploadError(
|
|
5512
|
+
body.error ?? `Upload of ${asset.path} failed: HTTP ${response.status}`,
|
|
5513
|
+
body.code ?? "upload_failed",
|
|
5514
|
+
response.status
|
|
5515
|
+
);
|
|
5516
|
+
}
|
|
5517
|
+
uploaded++;
|
|
5518
|
+
spinner2.message(`Uploading assets \u2014 ${uploaded}/${uploaded + missing.length}...`);
|
|
5519
|
+
}
|
|
5520
|
+
};
|
|
5521
|
+
try {
|
|
5522
|
+
await Promise.all(
|
|
5523
|
+
Array.from({ length: Math.min(UPLOAD_CONCURRENCY, missing.length) }, worker)
|
|
5524
|
+
);
|
|
5525
|
+
} catch (error) {
|
|
5526
|
+
spinner2.stop("Deploy failed");
|
|
5527
|
+
if (error instanceof AssetUploadError) {
|
|
5528
|
+
output.die(formatDeployWorkerError(error.status, error.message, error.code), error.code);
|
|
5529
|
+
}
|
|
5530
|
+
output.die(`Asset upload failed (network): ${errorMessage4(error)}`, "upload_failed");
|
|
5395
5531
|
}
|
|
5396
5532
|
}
|
|
5397
|
-
|
|
5533
|
+
var AssetUploadError = class extends Error {
|
|
5534
|
+
constructor(message, code, status3) {
|
|
5535
|
+
super(message);
|
|
5536
|
+
this.code = code;
|
|
5537
|
+
this.status = status3;
|
|
5538
|
+
}
|
|
5539
|
+
};
|
|
5540
|
+
function isDeployServiceResourceLimit(status3, error) {
|
|
5541
|
+
if (!error) return status3 === 500 || status3 === 502;
|
|
5542
|
+
return /\b110[12]\b/.test(error) && /worker|error code/i.test(error);
|
|
5543
|
+
}
|
|
5544
|
+
function formatDeployWorkerError(status3, error, code) {
|
|
5398
5545
|
const detail = error ?? `Deployment error (${status3})`;
|
|
5546
|
+
if (code === "cli_outdated") return detail;
|
|
5547
|
+
if (isDeployServiceResourceLimit(status3, error)) {
|
|
5548
|
+
return `${DEPLOY_SERVICE_LIMIT_HINT}
|
|
5549
|
+
|
|
5550
|
+
Underlying error: ${detail}`;
|
|
5551
|
+
}
|
|
5399
5552
|
if (status3 < 500 && ![
|
|
5400
5553
|
"Upload session failed",
|
|
5401
5554
|
"Asset upload failed",
|
|
@@ -5412,23 +5565,6 @@ Underlying error: ${detail}`;
|
|
|
5412
5565
|
function errorMessage4(error) {
|
|
5413
5566
|
return error instanceof Error ? error.message : String(error);
|
|
5414
5567
|
}
|
|
5415
|
-
function packAssetGroups(assets, maxBytes) {
|
|
5416
|
-
const groups = [];
|
|
5417
|
-
let current = [];
|
|
5418
|
-
let currentBytes = 2;
|
|
5419
|
-
for (const asset of assets) {
|
|
5420
|
-
const entryBytes = Buffer.byteLength(JSON.stringify(asset), "utf-8") + 1;
|
|
5421
|
-
if (current.length > 0 && currentBytes + entryBytes > maxBytes) {
|
|
5422
|
-
groups.push(current);
|
|
5423
|
-
current = [];
|
|
5424
|
-
currentBytes = 2;
|
|
5425
|
-
}
|
|
5426
|
-
current.push(asset);
|
|
5427
|
-
currentBytes += entryBytes;
|
|
5428
|
-
}
|
|
5429
|
-
if (current.length > 0) groups.push(current);
|
|
5430
|
-
return groups;
|
|
5431
|
-
}
|
|
5432
5568
|
async function postWithRetry(url, makeInit, {
|
|
5433
5569
|
attempts = 4,
|
|
5434
5570
|
retryServerErrors = true
|
|
@@ -5445,7 +5581,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5445
5581
|
lastError = error;
|
|
5446
5582
|
}
|
|
5447
5583
|
if (attempt < attempts) {
|
|
5448
|
-
await new Promise((
|
|
5584
|
+
await new Promise((resolve19) => setTimeout(resolve19, Math.min(8e3, 500 * 2 ** (attempt - 1))));
|
|
5449
5585
|
}
|
|
5450
5586
|
}
|
|
5451
5587
|
if (lastResponse) return lastResponse;
|
|
@@ -5454,7 +5590,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5454
5590
|
|
|
5455
5591
|
// src/cli/commands/deploy/secrets.ts
|
|
5456
5592
|
import * as p11 from "@clack/prompts";
|
|
5457
|
-
import { existsSync as existsSync18, readFileSync as
|
|
5593
|
+
import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
|
|
5458
5594
|
function classifyDevVarsSecrets(options) {
|
|
5459
5595
|
const store = new Set(options.storeSecretNames);
|
|
5460
5596
|
const strayKeys = options.handEditedDevVarKeys.filter((key) => !store.has(key));
|
|
@@ -5553,7 +5689,7 @@ function prepareDeploySecrets(options) {
|
|
|
5553
5689
|
}
|
|
5554
5690
|
function readCustomDevVars(path, output) {
|
|
5555
5691
|
if (!existsSync18(path)) return {};
|
|
5556
|
-
const section = extractCustomDevVars(stripGeneratedSecretsCache(
|
|
5692
|
+
const section = extractCustomDevVars(stripGeneratedSecretsCache(readFileSync19(path, "utf-8")));
|
|
5557
5693
|
if (!section) return {};
|
|
5558
5694
|
try {
|
|
5559
5695
|
return parseDevVars(section);
|
|
@@ -5827,7 +5963,7 @@ async function waitForAssetsReady(url, timeoutMs) {
|
|
|
5827
5963
|
if (!body.includes("Assets have not yet deployed") && !body.includes("No app configured")) {
|
|
5828
5964
|
streak++;
|
|
5829
5965
|
if (streak >= 3) return true;
|
|
5830
|
-
await new Promise((
|
|
5966
|
+
await new Promise((resolve19) => setTimeout(resolve19, 1500));
|
|
5831
5967
|
continue;
|
|
5832
5968
|
}
|
|
5833
5969
|
streak = 0;
|
|
@@ -5835,7 +5971,7 @@ async function waitForAssetsReady(url, timeoutMs) {
|
|
|
5835
5971
|
streak = 0;
|
|
5836
5972
|
}
|
|
5837
5973
|
const waitMs = Math.min(8e3, 1e3 * 2 ** (attempt - 1));
|
|
5838
|
-
await new Promise((
|
|
5974
|
+
await new Promise((resolve19) => setTimeout(resolve19, waitMs));
|
|
5839
5975
|
}
|
|
5840
5976
|
return false;
|
|
5841
5977
|
}
|
|
@@ -6479,7 +6615,7 @@ var usage_default = defineDeepspaceCommand({
|
|
|
6479
6615
|
});
|
|
6480
6616
|
|
|
6481
6617
|
// src/cli/commands/add.ts
|
|
6482
|
-
import { existsSync as existsSync20, readFileSync as
|
|
6618
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21, realpathSync as realpathSync3 } from "fs";
|
|
6483
6619
|
import { dirname as dirname7, join as join19, resolve as resolve14 } from "path";
|
|
6484
6620
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6485
6621
|
|
|
@@ -6492,7 +6628,7 @@ import {
|
|
|
6492
6628
|
mkdirSync as mkdirSync6,
|
|
6493
6629
|
mkdtempSync,
|
|
6494
6630
|
openSync as openSync2,
|
|
6495
|
-
readFileSync as
|
|
6631
|
+
readFileSync as readFileSync20,
|
|
6496
6632
|
readSync,
|
|
6497
6633
|
readdirSync as readdirSync5,
|
|
6498
6634
|
rmSync as rmSync4,
|
|
@@ -6509,7 +6645,7 @@ function featurePackageRoot(moduleUrl = import.meta.url) {
|
|
|
6509
6645
|
const packagePath = join18(dir, "package.json");
|
|
6510
6646
|
if (existsSync19(packagePath)) {
|
|
6511
6647
|
try {
|
|
6512
|
-
const pkg2 = JSON.parse(
|
|
6648
|
+
const pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
|
|
6513
6649
|
if (pkg2.name === "deepspace") return dir;
|
|
6514
6650
|
} catch {
|
|
6515
6651
|
}
|
|
@@ -6526,7 +6662,7 @@ function readFeatureConfig(id, packageRoot = featurePackageRoot()) {
|
|
|
6526
6662
|
const configPath = join18(packageRoot, "features", id, "feature.json");
|
|
6527
6663
|
if (!existsSync19(configPath)) return null;
|
|
6528
6664
|
try {
|
|
6529
|
-
const config = JSON.parse(
|
|
6665
|
+
const config = JSON.parse(readFileSync20(configPath, "utf-8"));
|
|
6530
6666
|
if (typeof config.id !== "string" || typeof config.name !== "string" || !Array.isArray(config.files)) {
|
|
6531
6667
|
return null;
|
|
6532
6668
|
}
|
|
@@ -6591,7 +6727,7 @@ function copyFile(src, dest) {
|
|
|
6591
6727
|
function copyFileWithImportShift(src, dest, levels) {
|
|
6592
6728
|
mkdirSync6(dirname6(dest), { recursive: true });
|
|
6593
6729
|
const prefix = "../".repeat(levels);
|
|
6594
|
-
const shifted =
|
|
6730
|
+
const shifted = readFileSync20(src, "utf-8").replace(
|
|
6595
6731
|
/(from\s+|import\s+|import\()(['"])(\.\.\/)/g,
|
|
6596
6732
|
`$1$2${prefix}$3`
|
|
6597
6733
|
);
|
|
@@ -6650,7 +6786,7 @@ function integrateSchema(config, targetDir, emit) {
|
|
|
6650
6786
|
if (!existsSync19(schemasPath)) {
|
|
6651
6787
|
return [unresolvedSchema(config.schema, "src/schemas.ts was not found.", emit)];
|
|
6652
6788
|
}
|
|
6653
|
-
let content =
|
|
6789
|
+
let content = readFileSync20(schemasPath, "utf-8");
|
|
6654
6790
|
const { exportName, importPath, spreadOperator } = config.schema;
|
|
6655
6791
|
const importPattern = new RegExp(`^import\\s+\\{[^}]*\\b${exportName}\\b`, "m");
|
|
6656
6792
|
if (importPattern.test(content)) {
|
|
@@ -6707,7 +6843,7 @@ function integrateActions(config, targetDir, emit) {
|
|
|
6707
6843
|
if (!existsSync19(actionsPath)) {
|
|
6708
6844
|
return [unresolvedActions(config.actions, "src/actions/index.ts was not found.", emit)];
|
|
6709
6845
|
}
|
|
6710
|
-
let content =
|
|
6846
|
+
let content = readFileSync20(actionsPath, "utf-8");
|
|
6711
6847
|
const registryPattern = /export const actions:\s*Record<string,\s*ActionHandler(?:<[^>]*>)?>\s*=\s*\{/;
|
|
6712
6848
|
if (!registryPattern.test(content)) {
|
|
6713
6849
|
const reason = "src/actions/index.ts has an unexpected structure.";
|
|
@@ -6762,7 +6898,7 @@ function integrateCode(config, targetDir, emit) {
|
|
|
6762
6898
|
});
|
|
6763
6899
|
continue;
|
|
6764
6900
|
}
|
|
6765
|
-
const original =
|
|
6901
|
+
const original = readFileSync20(targetPath, "utf-8");
|
|
6766
6902
|
if (original.includes(insertion.insert.trim())) {
|
|
6767
6903
|
emit(` Integration already present: ${insertion.file}`);
|
|
6768
6904
|
continue;
|
|
@@ -6798,7 +6934,7 @@ ${content.slice(importIndex < 0 ? 0 : importIndex)}`;
|
|
|
6798
6934
|
function integrateIgnore(config, targetDir) {
|
|
6799
6935
|
if (!config.ignore?.length) return;
|
|
6800
6936
|
const targetPath = join18(targetDir, ".gitignore");
|
|
6801
|
-
const current = existsSync19(targetPath) ?
|
|
6937
|
+
const current = existsSync19(targetPath) ? readFileSync20(targetPath, "utf-8") : "";
|
|
6802
6938
|
const present = new Set(current.split(/\r?\n/).map((line) => line.trim()));
|
|
6803
6939
|
const missing = config.ignore.filter((pattern) => !present.has(pattern));
|
|
6804
6940
|
if (missing.length === 0) return;
|
|
@@ -6818,7 +6954,7 @@ function integrateWrangler(config, targetDir, emit) {
|
|
|
6818
6954
|
if (!existsSync19(targetPath)) {
|
|
6819
6955
|
return [{ area: "wrangler", reason: "wrangler.toml was not found.", steps }];
|
|
6820
6956
|
}
|
|
6821
|
-
let source =
|
|
6957
|
+
let source = readFileSync20(targetPath, "utf-8");
|
|
6822
6958
|
if (runWorkerFirst && !/^\[assets\]\s*$/m.test(source)) {
|
|
6823
6959
|
return [{ area: "wrangler", reason: "wrangler.toml has no [assets] section.", steps }];
|
|
6824
6960
|
}
|
|
@@ -6907,7 +7043,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
6907
7043
|
}
|
|
6908
7044
|
];
|
|
6909
7045
|
}
|
|
6910
|
-
let styles =
|
|
7046
|
+
let styles = readFileSync20(stylesPath, "utf-8");
|
|
6911
7047
|
let integrated = 0;
|
|
6912
7048
|
const unresolved = [];
|
|
6913
7049
|
for (const cssFile of config.css) {
|
|
@@ -6921,7 +7057,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
6921
7057
|
});
|
|
6922
7058
|
continue;
|
|
6923
7059
|
}
|
|
6924
|
-
const css =
|
|
7060
|
+
const css = readFileSync20(srcPath, "utf-8");
|
|
6925
7061
|
const fingerprint = css.match(/\.([\w-]+)\s*\{|@keyframes\s+([\w-]+)/);
|
|
6926
7062
|
const marker = fingerprint?.[1] ?? fingerprint?.[2];
|
|
6927
7063
|
if (marker && styles.includes(marker)) {
|
|
@@ -6952,7 +7088,7 @@ function integrateRoute(config, targetDir, emit) {
|
|
|
6952
7088
|
if (!existsSync19(navPath)) {
|
|
6953
7089
|
return [unresolvedRoute(config.route, config, "src/nav.ts was not found.", emit)];
|
|
6954
7090
|
}
|
|
6955
|
-
let content =
|
|
7091
|
+
let content = readFileSync20(navPath, "utf-8");
|
|
6956
7092
|
const routePath = config.route.path;
|
|
6957
7093
|
if (content.includes(`'${routePath}'`)) {
|
|
6958
7094
|
emit(` Nav already present: ${routePath}`);
|
|
@@ -7033,7 +7169,7 @@ function integrateDependencies(config, targetDir, runInstall, outputVisible, emi
|
|
|
7033
7169
|
}
|
|
7034
7170
|
let pkg2;
|
|
7035
7171
|
try {
|
|
7036
|
-
pkg2 = JSON.parse(
|
|
7172
|
+
pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
|
|
7037
7173
|
} catch (error) {
|
|
7038
7174
|
emit(
|
|
7039
7175
|
` Could not patch package.json (parse error: ${error instanceof Error ? error.message : String(error)})`
|
|
@@ -7093,7 +7229,7 @@ ${child.diagnosticTail}` : "";
|
|
|
7093
7229
|
}
|
|
7094
7230
|
function dependencySnapshot(targetDir) {
|
|
7095
7231
|
try {
|
|
7096
|
-
const pkg2 = JSON.parse(
|
|
7232
|
+
const pkg2 = JSON.parse(readFileSync20(join18(targetDir, "package.json"), "utf-8"));
|
|
7097
7233
|
return {
|
|
7098
7234
|
dependencies: pkg2.dependencies ?? {},
|
|
7099
7235
|
devDependencies: pkg2.devDependencies ?? {}
|
|
@@ -7342,7 +7478,7 @@ function isDeepSpaceApp(dir) {
|
|
|
7342
7478
|
const packagePath = join19(dir, "package.json");
|
|
7343
7479
|
if (!existsSync20(packagePath)) return false;
|
|
7344
7480
|
try {
|
|
7345
|
-
const pkg2 = JSON.parse(
|
|
7481
|
+
const pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
|
|
7346
7482
|
return Boolean(pkg2.dependencies?.deepspace || pkg2.devDependencies?.deepspace);
|
|
7347
7483
|
} catch {
|
|
7348
7484
|
return false;
|
|
@@ -7545,11 +7681,11 @@ function fmtDate(iso) {
|
|
|
7545
7681
|
}
|
|
7546
7682
|
async function confirm4(message) {
|
|
7547
7683
|
process.stdout.write(`${message} [y/N] `);
|
|
7548
|
-
return new Promise((
|
|
7684
|
+
return new Promise((resolve19) => {
|
|
7549
7685
|
process.stdin.setEncoding("utf-8");
|
|
7550
7686
|
process.stdin.once("data", (data) => {
|
|
7551
7687
|
const answer = data.toString().trim().toLowerCase();
|
|
7552
|
-
|
|
7688
|
+
resolve19(answer === "y" || answer === "yes");
|
|
7553
7689
|
});
|
|
7554
7690
|
});
|
|
7555
7691
|
}
|
|
@@ -7837,8 +7973,289 @@ var domain_default = defineCommand5({
|
|
|
7837
7973
|
subCommands: { search, buy, list: list2, status, attach, detach, renew }
|
|
7838
7974
|
});
|
|
7839
7975
|
|
|
7840
|
-
// src/cli/commands/
|
|
7976
|
+
// src/cli/commands/app-files.ts
|
|
7841
7977
|
import { defineCommand as defineCommand6 } from "citty";
|
|
7978
|
+
import { basename as basename4, resolve as resolve15 } from "path";
|
|
7979
|
+
import { existsSync as existsSync21, statSync as statSync2 } from "fs";
|
|
7980
|
+
|
|
7981
|
+
// src/cli/lib/app-files-api.ts
|
|
7982
|
+
import { createWriteStream, openAsBlob, statSync } from "fs";
|
|
7983
|
+
import { basename as basename3, extname } from "path";
|
|
7984
|
+
import { Readable } from "stream";
|
|
7985
|
+
import { pipeline } from "stream/promises";
|
|
7986
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
7987
|
+
var CONTENT_TYPES = {
|
|
7988
|
+
".avif": "image/avif",
|
|
7989
|
+
".css": "text/css",
|
|
7990
|
+
".csv": "text/csv",
|
|
7991
|
+
".gif": "image/gif",
|
|
7992
|
+
".ico": "image/x-icon",
|
|
7993
|
+
".jpeg": "image/jpeg",
|
|
7994
|
+
".jpg": "image/jpeg",
|
|
7995
|
+
".json": "application/json",
|
|
7996
|
+
".md": "text/markdown",
|
|
7997
|
+
".mp3": "audio/mpeg",
|
|
7998
|
+
".mp4": "video/mp4",
|
|
7999
|
+
".otf": "font/otf",
|
|
8000
|
+
".pdf": "application/pdf",
|
|
8001
|
+
".png": "image/png",
|
|
8002
|
+
".txt": "text/plain",
|
|
8003
|
+
".wasm": "application/wasm",
|
|
8004
|
+
".wav": "audio/wav",
|
|
8005
|
+
".webm": "video/webm",
|
|
8006
|
+
".webp": "image/webp",
|
|
8007
|
+
".woff": "font/woff",
|
|
8008
|
+
".woff2": "font/woff2",
|
|
8009
|
+
".zip": "application/zip"
|
|
8010
|
+
};
|
|
8011
|
+
function contentTypeFor(path) {
|
|
8012
|
+
return CONTENT_TYPES[extname(path).toLowerCase()] ?? "application/octet-stream";
|
|
8013
|
+
}
|
|
8014
|
+
function filesPath(appId, rest = "") {
|
|
8015
|
+
return `/api/app-files/${appId}${rest}`;
|
|
8016
|
+
}
|
|
8017
|
+
async function request(baseUrl, token, path, init = {}) {
|
|
8018
|
+
let res;
|
|
8019
|
+
try {
|
|
8020
|
+
res = await fetch(`${baseUrl}${path}`, {
|
|
8021
|
+
...init,
|
|
8022
|
+
headers: { Authorization: `Bearer ${token}`, ...init.headers ?? {} }
|
|
8023
|
+
});
|
|
8024
|
+
} catch (err) {
|
|
8025
|
+
throw new ApiError(
|
|
8026
|
+
`Could not reach the DeepSpace platform at ${baseUrl}: ${err instanceof Error ? err.message : String(err)}. Check your connection (and DEEPSPACE_PLATFORM_URL), then retry.`,
|
|
8027
|
+
0,
|
|
8028
|
+
"network_error",
|
|
8029
|
+
path
|
|
8030
|
+
);
|
|
8031
|
+
}
|
|
8032
|
+
if (res.ok) return res;
|
|
8033
|
+
const text2 = await res.text();
|
|
8034
|
+
let code;
|
|
8035
|
+
try {
|
|
8036
|
+
code = JSON.parse(text2.trim()).code;
|
|
8037
|
+
} catch {
|
|
8038
|
+
}
|
|
8039
|
+
throw new ApiError(
|
|
8040
|
+
describeFilesFailure(res.status, text2),
|
|
8041
|
+
res.status,
|
|
8042
|
+
code ?? (res.status === 413 ? "file_too_large" : res.status >= 500 ? "server_error" : "http_error"),
|
|
8043
|
+
path
|
|
8044
|
+
);
|
|
8045
|
+
}
|
|
8046
|
+
async function readJson(res, path) {
|
|
8047
|
+
const text2 = await res.text();
|
|
8048
|
+
try {
|
|
8049
|
+
return JSON.parse(text2);
|
|
8050
|
+
} catch {
|
|
8051
|
+
throw new ApiError(
|
|
8052
|
+
`The DeepSpace platform returned a malformed (non-JSON) response.`,
|
|
8053
|
+
res.status,
|
|
8054
|
+
"invalid_response",
|
|
8055
|
+
path
|
|
8056
|
+
);
|
|
8057
|
+
}
|
|
8058
|
+
}
|
|
8059
|
+
async function multipartBody(localPath, fileName, contentType) {
|
|
8060
|
+
const boundary = `----deepspace${randomUUID2().replace(/-/g, "")}`;
|
|
8061
|
+
const safeName = fileName.replace(/["\\\r\n]/g, "_");
|
|
8062
|
+
const head = `--${boundary}\r
|
|
8063
|
+
Content-Disposition: form-data; name="file"; filename="${safeName}"\r
|
|
8064
|
+
Content-Type: ${contentType}\r
|
|
8065
|
+
\r
|
|
8066
|
+
`;
|
|
8067
|
+
const file = await openAsBlob(localPath, { type: contentType });
|
|
8068
|
+
return {
|
|
8069
|
+
blob: new Blob([head, file, `\r
|
|
8070
|
+
--${boundary}--\r
|
|
8071
|
+
`]),
|
|
8072
|
+
contentType: `multipart/form-data; boundary=${boundary}`
|
|
8073
|
+
};
|
|
8074
|
+
}
|
|
8075
|
+
async function uploadAppFile(baseUrl, token, appId, localPath, key) {
|
|
8076
|
+
const path = filesPath(appId, `/upload?key=${encodeKeyPath(key)}`);
|
|
8077
|
+
const size = statSync(localPath).size;
|
|
8078
|
+
if (size > MAX_APP_FILE_BYTES) {
|
|
8079
|
+
throw new ApiError(oversizeMessage(size), 0, "file_too_large", path);
|
|
8080
|
+
}
|
|
8081
|
+
const { blob, contentType } = await multipartBody(
|
|
8082
|
+
localPath,
|
|
8083
|
+
basename3(localPath),
|
|
8084
|
+
contentTypeFor(localPath)
|
|
8085
|
+
);
|
|
8086
|
+
const res = await request(baseUrl, token, path, {
|
|
8087
|
+
method: "POST",
|
|
8088
|
+
headers: { "Content-Type": contentType },
|
|
8089
|
+
body: blob
|
|
8090
|
+
});
|
|
8091
|
+
const body = await readJson(res, path);
|
|
8092
|
+
return { key: body.key, name: body.name, size };
|
|
8093
|
+
}
|
|
8094
|
+
async function listAppFiles(baseUrl, token, appId, query) {
|
|
8095
|
+
const path = filesPath(appId, `?${query}`);
|
|
8096
|
+
return readJson(await request(baseUrl, token, path), path);
|
|
8097
|
+
}
|
|
8098
|
+
async function deleteAppFile(baseUrl, token, appId, key) {
|
|
8099
|
+
await request(baseUrl, token, filesPath(appId, `/${encodeKeyPath(key)}`), { method: "DELETE" });
|
|
8100
|
+
}
|
|
8101
|
+
async function downloadAppFile(baseUrl, token, appId, key, destination) {
|
|
8102
|
+
const path = filesPath(appId, `/${encodeKeyPath(key)}`);
|
|
8103
|
+
const res = await request(baseUrl, token, path);
|
|
8104
|
+
if (!res.body) {
|
|
8105
|
+
throw new ApiError("The server returned an empty response", 502, "invalid_response", path);
|
|
8106
|
+
}
|
|
8107
|
+
let bytes = 0;
|
|
8108
|
+
await pipeline(
|
|
8109
|
+
Readable.fromWeb(res.body),
|
|
8110
|
+
async function* (chunks) {
|
|
8111
|
+
for await (const chunk of chunks) {
|
|
8112
|
+
bytes += chunk.length;
|
|
8113
|
+
yield chunk;
|
|
8114
|
+
}
|
|
8115
|
+
},
|
|
8116
|
+
createWriteStream(destination)
|
|
8117
|
+
);
|
|
8118
|
+
return { bytes, contentType: res.headers.get("content-type") ?? "application/octet-stream" };
|
|
8119
|
+
}
|
|
8120
|
+
|
|
8121
|
+
// src/cli/commands/app-files.ts
|
|
8122
|
+
var DEPLOY_URL8 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
|
|
8123
|
+
var PLATFORM_URL = process.env.DEEPSPACE_PLATFORM_URL ?? PLATFORM_URLS.platform;
|
|
8124
|
+
async function target(app2) {
|
|
8125
|
+
const token = await ensureToken();
|
|
8126
|
+
const appId = await resolveAppTarget(DEPLOY_URL8, token, app2);
|
|
8127
|
+
return { token, appId };
|
|
8128
|
+
}
|
|
8129
|
+
var MAX_LIST_LIMIT = 1e3;
|
|
8130
|
+
function parseLimit(raw) {
|
|
8131
|
+
const limit = Number(raw ?? 100);
|
|
8132
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > MAX_LIST_LIMIT) {
|
|
8133
|
+
throw new Refusal(`--limit must be a whole number from 1 to ${MAX_LIST_LIMIT}.`, "invalid_limit");
|
|
8134
|
+
}
|
|
8135
|
+
return limit;
|
|
8136
|
+
}
|
|
8137
|
+
function requireKey(raw) {
|
|
8138
|
+
const key = raw.trim().replace(/^\/+/, "");
|
|
8139
|
+
if (!key) throw new Refusal("A key is required (for example `logo.png`).", "invalid_key");
|
|
8140
|
+
if (key.split("/").some((segment) => segment === ".." || segment === ".")) {
|
|
8141
|
+
throw new Refusal(
|
|
8142
|
+
`"${raw}" contains a path traversal segment. Keys are relative to the app, e.g. \`img/hero.jpg\`.`,
|
|
8143
|
+
"invalid_key"
|
|
8144
|
+
);
|
|
8145
|
+
}
|
|
8146
|
+
return key;
|
|
8147
|
+
}
|
|
8148
|
+
function appPrefixOf(key) {
|
|
8149
|
+
const segments = key.split("/");
|
|
8150
|
+
return segments.length > 2 ? `${segments[0]}/${segments[1]}/` : "";
|
|
8151
|
+
}
|
|
8152
|
+
function relativeKey(key, prefix) {
|
|
8153
|
+
return prefix && key.startsWith(prefix) ? key.slice(prefix.length) : key;
|
|
8154
|
+
}
|
|
8155
|
+
function servedPath(key) {
|
|
8156
|
+
return `/api/files/${encodeKeyPath(key)}?scope=app`;
|
|
8157
|
+
}
|
|
8158
|
+
var put = defineDeepspaceCommand({
|
|
8159
|
+
meta: { name: "put", description: "Upload a file to the app\u2019s files" },
|
|
8160
|
+
args: {
|
|
8161
|
+
file: { type: "positional", description: "Local file to upload", required: true },
|
|
8162
|
+
key: { type: "string", description: "Key to store it under (default: the file name)" },
|
|
8163
|
+
app: { type: "string", description: "App id or live name (defaults to ./wrangler.toml)" }
|
|
8164
|
+
},
|
|
8165
|
+
async run({ args }) {
|
|
8166
|
+
const localPath = resolve15(String(args.file));
|
|
8167
|
+
if (!existsSync21(localPath) || !statSync2(localPath).isFile()) {
|
|
8168
|
+
throw new Refusal(`No such file: ${args.file}`, "file_not_found");
|
|
8169
|
+
}
|
|
8170
|
+
const key = requireKey(args.key ?? basename4(localPath));
|
|
8171
|
+
const { token, appId } = await target(args.app);
|
|
8172
|
+
const result = await uploadAppFile(PLATFORM_URL, token, appId, localPath, key);
|
|
8173
|
+
if (!args.json) {
|
|
8174
|
+
console.log(`\u2713 ${key} (${formatBytes(result.size)})`);
|
|
8175
|
+
console.log(` Served from your app at ${servedPath(result.key)}`);
|
|
8176
|
+
}
|
|
8177
|
+
return { data: { appId, key, storedKey: result.key, size: result.size, path: servedPath(result.key) } };
|
|
8178
|
+
}
|
|
8179
|
+
});
|
|
8180
|
+
var list3 = defineDeepspaceCommand({
|
|
8181
|
+
meta: { name: "list", description: "List the app\u2019s files" },
|
|
8182
|
+
args: {
|
|
8183
|
+
prefix: { type: "string", description: "Only keys starting with this prefix" },
|
|
8184
|
+
limit: {
|
|
8185
|
+
type: "string",
|
|
8186
|
+
description: `Max entries, 1-${MAX_LIST_LIMIT} (default 100)`,
|
|
8187
|
+
default: "100"
|
|
8188
|
+
},
|
|
8189
|
+
app: { type: "string", description: "App id or live name (defaults to ./wrangler.toml)" }
|
|
8190
|
+
},
|
|
8191
|
+
async run({ args }) {
|
|
8192
|
+
const limit = parseLimit(args.limit);
|
|
8193
|
+
const { token, appId } = await target(args.app);
|
|
8194
|
+
const query = new URLSearchParams({ limit: String(limit) });
|
|
8195
|
+
if (args.prefix) query.set("prefix", String(args.prefix));
|
|
8196
|
+
const result = await listAppFiles(PLATFORM_URL, token, appId, query);
|
|
8197
|
+
const prefix = result.files.length ? appPrefixOf(result.files[0].key) : "";
|
|
8198
|
+
const files = result.files.map((file) => ({
|
|
8199
|
+
key: relativeKey(file.key, prefix),
|
|
8200
|
+
size: file.size,
|
|
8201
|
+
uploaded: file.uploaded,
|
|
8202
|
+
path: servedPath(file.key)
|
|
8203
|
+
}));
|
|
8204
|
+
if (!args.json) {
|
|
8205
|
+
if (files.length === 0) {
|
|
8206
|
+
console.log("No files. Upload one with `deepspace app files put <file>`.");
|
|
8207
|
+
} else {
|
|
8208
|
+
const keyWidth = Math.max(3, ...files.map((file) => file.key.length));
|
|
8209
|
+
console.log(`${"KEY".padEnd(keyWidth)} ${"SIZE".padStart(9)} UPLOADED`);
|
|
8210
|
+
for (const file of files) {
|
|
8211
|
+
console.log(
|
|
8212
|
+
`${file.key.padEnd(keyWidth)} ${formatBytes(file.size).padStart(9)} ${file.uploaded.slice(0, 10)}`
|
|
8213
|
+
);
|
|
8214
|
+
}
|
|
8215
|
+
const more = limit < MAX_LIST_LIMIT ? "raise --limit or narrow with --prefix" : "narrow with --prefix";
|
|
8216
|
+
if (result.truncated) console.log(`(truncated at ${limit} \u2014 ${more})`);
|
|
8217
|
+
}
|
|
8218
|
+
}
|
|
8219
|
+
return { data: { appId, files, truncated: result.truncated } };
|
|
8220
|
+
}
|
|
8221
|
+
});
|
|
8222
|
+
var get = defineDeepspaceCommand({
|
|
8223
|
+
meta: { name: "get", description: "Download one file" },
|
|
8224
|
+
args: {
|
|
8225
|
+
key: { type: "positional", description: "Key to download", required: true },
|
|
8226
|
+
out: { type: "string", description: "Write here (default: the key\u2019s file name)" },
|
|
8227
|
+
app: { type: "string", description: "App id or live name (defaults to ./wrangler.toml)" }
|
|
8228
|
+
},
|
|
8229
|
+
async run({ args }) {
|
|
8230
|
+
const key = requireKey(String(args.key));
|
|
8231
|
+
const destination = resolve15(String(args.out ?? basename4(key)));
|
|
8232
|
+
const { token, appId } = await target(args.app);
|
|
8233
|
+
const result = await downloadAppFile(PLATFORM_URL, token, appId, key, destination);
|
|
8234
|
+
if (!args.json) console.log(`\u2713 ${key} \u2192 ${destination} (${formatBytes(result.bytes)})`);
|
|
8235
|
+
return { data: { appId, key, out: destination, size: result.bytes, contentType: result.contentType } };
|
|
8236
|
+
}
|
|
8237
|
+
});
|
|
8238
|
+
var rm = defineDeepspaceCommand({
|
|
8239
|
+
meta: { name: "rm", description: "Delete one file" },
|
|
8240
|
+
args: {
|
|
8241
|
+
key: { type: "positional", description: "Key to delete", required: true },
|
|
8242
|
+
app: { type: "string", description: "App id or live name (defaults to ./wrangler.toml)" }
|
|
8243
|
+
},
|
|
8244
|
+
async run({ args }) {
|
|
8245
|
+
const key = requireKey(String(args.key));
|
|
8246
|
+
const { token, appId } = await target(args.app);
|
|
8247
|
+
await deleteAppFile(PLATFORM_URL, token, appId, key);
|
|
8248
|
+
if (!args.json) console.log(`\u2713 deleted ${key}`);
|
|
8249
|
+
return { data: { appId, key, deleted: true } };
|
|
8250
|
+
}
|
|
8251
|
+
});
|
|
8252
|
+
var app_files_default = defineCommand6({
|
|
8253
|
+
meta: { name: "files", description: "Upload and manage the app\u2019s files (images, media)" },
|
|
8254
|
+
subCommands: { put, list: list3, get, rm }
|
|
8255
|
+
});
|
|
8256
|
+
|
|
8257
|
+
// src/cli/commands/collaborators.ts
|
|
8258
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
7842
8259
|
|
|
7843
8260
|
// src/server/auth/testAccounts.ts
|
|
7844
8261
|
var TEST_ACCOUNT_EMAIL_SUFFIX = "@deepspace.test";
|
|
@@ -7848,18 +8265,18 @@ function isTestAccountEmail(email) {
|
|
|
7848
8265
|
|
|
7849
8266
|
// src/cli/commands/collaborators.ts
|
|
7850
8267
|
var API_URL5 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
7851
|
-
var
|
|
8268
|
+
var DEPLOY_URL9 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
|
|
7852
8269
|
function api2(token, path, init) {
|
|
7853
8270
|
return apiFetch(API_URL5, token, path, init);
|
|
7854
8271
|
}
|
|
7855
|
-
var
|
|
8272
|
+
var list4 = defineDeepspaceCommand({
|
|
7856
8273
|
meta: { name: "list", description: "List collaborators on your app" },
|
|
7857
8274
|
args: {
|
|
7858
8275
|
app: { type: "string", alias: "a", description: "App id or name (defaults to ./wrangler.toml)" }
|
|
7859
8276
|
},
|
|
7860
8277
|
async run({ args }) {
|
|
7861
8278
|
const token = await ensureToken();
|
|
7862
|
-
const app2 = await resolveAppTarget(
|
|
8279
|
+
const app2 = await resolveAppTarget(DEPLOY_URL9, token, args.app);
|
|
7863
8280
|
const { collaborators, pending = [] } = await api2(token, `/api/app-collaborators/${encodeURIComponent(app2)}`);
|
|
7864
8281
|
if (!collaborators.length && !pending.length) {
|
|
7865
8282
|
if (!args.json) {
|
|
@@ -7897,7 +8314,7 @@ var add = defineDeepspaceCommand({
|
|
|
7897
8314
|
async run({ args }) {
|
|
7898
8315
|
const email = String(args.email);
|
|
7899
8316
|
const token = await ensureToken();
|
|
7900
|
-
const app2 = await resolveAppTarget(
|
|
8317
|
+
const app2 = await resolveAppTarget(DEPLOY_URL9, token, args.app);
|
|
7901
8318
|
if (isTestAccountEmail(email)) {
|
|
7902
8319
|
throw new Refusal(
|
|
7903
8320
|
"Test accounts (@deepspace.test) cannot be added as collaborators. Use a real DeepSpace account.",
|
|
@@ -7939,13 +8356,13 @@ var remove = defineDeepspaceCommand({
|
|
|
7939
8356
|
async run({ args }) {
|
|
7940
8357
|
const email = String(args.email);
|
|
7941
8358
|
const token = await ensureToken();
|
|
7942
|
-
const app2 = await resolveAppTarget(
|
|
8359
|
+
const app2 = await resolveAppTarget(DEPLOY_URL9, token, args.app);
|
|
7943
8360
|
const { collaborators } = await api2(
|
|
7944
8361
|
token,
|
|
7945
8362
|
`/api/app-collaborators/${encodeURIComponent(app2)}`
|
|
7946
8363
|
);
|
|
7947
|
-
const
|
|
7948
|
-
const found = collaborators.find((c) => c.emailDisplay.toLowerCase() ===
|
|
8364
|
+
const target2 = email.trim().toLowerCase();
|
|
8365
|
+
const found = collaborators.find((c) => c.emailDisplay.toLowerCase() === target2);
|
|
7949
8366
|
if (!found) {
|
|
7950
8367
|
throw new Refusal(`${email} is not a collaborator on ${app2}`, "not_a_collaborator", {
|
|
7951
8368
|
action: cliAction("deepspace", "app", "collaborators", "list", "--app", app2)
|
|
@@ -7969,13 +8386,13 @@ var cancel3 = defineDeepspaceCommand({
|
|
|
7969
8386
|
async run({ args }) {
|
|
7970
8387
|
const email = String(args.email);
|
|
7971
8388
|
const token = await ensureToken();
|
|
7972
|
-
const app2 = await resolveAppTarget(
|
|
8389
|
+
const app2 = await resolveAppTarget(DEPLOY_URL9, token, args.app);
|
|
7973
8390
|
const { pending = [] } = await api2(
|
|
7974
8391
|
token,
|
|
7975
8392
|
`/api/app-collaborators/${encodeURIComponent(app2)}`
|
|
7976
8393
|
);
|
|
7977
|
-
const
|
|
7978
|
-
const found = pending.find((p34) => p34.email.toLowerCase() ===
|
|
8394
|
+
const target2 = email.trim().toLowerCase();
|
|
8395
|
+
const found = pending.find((p34) => p34.email.toLowerCase() === target2);
|
|
7979
8396
|
if (!found) {
|
|
7980
8397
|
throw new Refusal(`${email} has no pending invite on ${app2}`, "no_pending_invite", {
|
|
7981
8398
|
action: cliAction("deepspace", "app", "collaborators", "list", "--app", app2)
|
|
@@ -7990,16 +8407,16 @@ var cancel3 = defineDeepspaceCommand({
|
|
|
7990
8407
|
return { data: { cancelled: found } };
|
|
7991
8408
|
}
|
|
7992
8409
|
});
|
|
7993
|
-
var collaborators_default =
|
|
8410
|
+
var collaborators_default = defineCommand7({
|
|
7994
8411
|
meta: { name: "collaborators", description: "Manage who can deploy your app" },
|
|
7995
|
-
subCommands: { list:
|
|
8412
|
+
subCommands: { list: list4, add, remove, cancel: cancel3 }
|
|
7996
8413
|
});
|
|
7997
8414
|
|
|
7998
8415
|
// src/cli/commands/transfer.ts
|
|
7999
|
-
import { defineCommand as
|
|
8416
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
8000
8417
|
import * as p14 from "@clack/prompts";
|
|
8001
8418
|
var API_URL6 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
8002
|
-
var
|
|
8419
|
+
var DEPLOY_URL10 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
|
|
8003
8420
|
var offer = defineDeepspaceCommand({
|
|
8004
8421
|
meta: { name: "offer", description: "Offer this app to another DeepSpace user" },
|
|
8005
8422
|
args: {
|
|
@@ -8013,7 +8430,7 @@ var offer = defineDeepspaceCommand({
|
|
|
8013
8430
|
async run({ args }) {
|
|
8014
8431
|
const email = String(args.email);
|
|
8015
8432
|
const token = await ensureToken();
|
|
8016
|
-
const app2 = await resolveAppTarget(
|
|
8433
|
+
const app2 = await resolveAppTarget(DEPLOY_URL10, token, args.app);
|
|
8017
8434
|
const pending = await apiFetch(
|
|
8018
8435
|
API_URL6,
|
|
8019
8436
|
token,
|
|
@@ -8065,7 +8482,7 @@ var status2 = defineDeepspaceCommand({
|
|
|
8065
8482
|
},
|
|
8066
8483
|
async run({ args }) {
|
|
8067
8484
|
const token = await ensureToken();
|
|
8068
|
-
const app2 = await resolveAppTarget(
|
|
8485
|
+
const app2 = await resolveAppTarget(DEPLOY_URL10, token, args.app);
|
|
8069
8486
|
const { transfer } = await apiFetch(API_URL6, token, `/api/app-transfers/${encodeURIComponent(app2)}`);
|
|
8070
8487
|
if (!transfer) {
|
|
8071
8488
|
if (!args.json) console.log(`No pending transfer for ${app2}.`);
|
|
@@ -8092,7 +8509,7 @@ var accept = defineDeepspaceCommand({
|
|
|
8092
8509
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8093
8510
|
throw new Refusal(msg, msg.startsWith("No app id") ? "not_in_app_repo" : "invalid_app");
|
|
8094
8511
|
}
|
|
8095
|
-
await apiFetch(
|
|
8512
|
+
await apiFetch(DEPLOY_URL10, token, `/api/apps/${encodeURIComponent(app2)}/transfer/accept`, {
|
|
8096
8513
|
method: "POST"
|
|
8097
8514
|
});
|
|
8098
8515
|
if (!args.json) {
|
|
@@ -8110,37 +8527,37 @@ var cancel4 = defineDeepspaceCommand({
|
|
|
8110
8527
|
},
|
|
8111
8528
|
async run({ args }) {
|
|
8112
8529
|
const token = await ensureToken();
|
|
8113
|
-
const app2 = await resolveAppTarget(
|
|
8530
|
+
const app2 = await resolveAppTarget(DEPLOY_URL10, token, args.app);
|
|
8114
8531
|
await apiFetch(API_URL6, token, `/api/app-transfers/${encodeURIComponent(app2)}`, { method: "DELETE" });
|
|
8115
8532
|
if (!args.json) console.log(`\u2713 Transfer offer for ${app2} cancelled.`);
|
|
8116
8533
|
return { data: { app: app2, cancelled: true } };
|
|
8117
8534
|
}
|
|
8118
8535
|
});
|
|
8119
|
-
var transfer_default =
|
|
8536
|
+
var transfer_default = defineCommand8({
|
|
8120
8537
|
meta: { name: "transfer", description: "Transfer app ownership to another user" },
|
|
8121
8538
|
subCommands: { offer, status: status2, accept, cancel: cancel4 }
|
|
8122
8539
|
});
|
|
8123
8540
|
|
|
8124
8541
|
// src/cli/commands/integrations.ts
|
|
8125
|
-
import { defineCommand as
|
|
8542
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
8126
8543
|
|
|
8127
8544
|
// src/cli/commands/_invoke-impl.ts
|
|
8128
|
-
import { readFileSync as
|
|
8545
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
8129
8546
|
import * as p15 from "@clack/prompts";
|
|
8130
8547
|
var API_URL7 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
8131
8548
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
8132
|
-
function parseTarget(
|
|
8133
|
-
if (!
|
|
8549
|
+
function parseTarget(target2) {
|
|
8550
|
+
if (!target2 || typeof target2 !== "string") {
|
|
8134
8551
|
throw new Refusal(
|
|
8135
8552
|
"Missing target. Expected '<integration>/<endpoint>' (e.g. 'openai/chat-completion').",
|
|
8136
8553
|
"missing_target",
|
|
8137
8554
|
{ action: cliAction("deepspace", "integrations", "list") }
|
|
8138
8555
|
);
|
|
8139
8556
|
}
|
|
8140
|
-
const parts =
|
|
8557
|
+
const parts = target2.split("/");
|
|
8141
8558
|
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
8142
8559
|
throw new Refusal(
|
|
8143
|
-
`Bad target '${
|
|
8560
|
+
`Bad target '${target2}'. Expected '<integration>/<endpoint>' (e.g. 'openai/chat-completion').`,
|
|
8144
8561
|
"bad_target",
|
|
8145
8562
|
{ action: cliAction("deepspace", "integrations", "list") }
|
|
8146
8563
|
);
|
|
@@ -8166,7 +8583,7 @@ function resolveBody(opts) {
|
|
|
8166
8583
|
if (opts.body != null) {
|
|
8167
8584
|
raw = opts.body;
|
|
8168
8585
|
} else if (opts.bodyFile != null) {
|
|
8169
|
-
raw = opts.bodyFile === "-" ?
|
|
8586
|
+
raw = opts.bodyFile === "-" ? readFileSync22(0, "utf-8") : readFileSync22(opts.bodyFile, "utf-8");
|
|
8170
8587
|
} else {
|
|
8171
8588
|
return "{}";
|
|
8172
8589
|
}
|
|
@@ -8360,7 +8777,7 @@ async function runInvoke(args) {
|
|
|
8360
8777
|
}
|
|
8361
8778
|
|
|
8362
8779
|
// src/cli/commands/integrations.ts
|
|
8363
|
-
var
|
|
8780
|
+
var list5 = defineDeepspaceCommand({
|
|
8364
8781
|
meta: {
|
|
8365
8782
|
name: "list",
|
|
8366
8783
|
description: "List all available integrations"
|
|
@@ -8431,13 +8848,13 @@ var invoke = defineDeepspaceCommand({
|
|
|
8431
8848
|
});
|
|
8432
8849
|
}
|
|
8433
8850
|
});
|
|
8434
|
-
var integrations_default =
|
|
8851
|
+
var integrations_default = defineCommand9({
|
|
8435
8852
|
meta: {
|
|
8436
8853
|
name: "integrations",
|
|
8437
8854
|
description: "List, inspect, and invoke platform integrations"
|
|
8438
8855
|
},
|
|
8439
8856
|
subCommands: {
|
|
8440
|
-
list:
|
|
8857
|
+
list: list5,
|
|
8441
8858
|
info,
|
|
8442
8859
|
invoke
|
|
8443
8860
|
}
|
|
@@ -8445,7 +8862,7 @@ var integrations_default = defineCommand8({
|
|
|
8445
8862
|
|
|
8446
8863
|
// src/cli/commands/feedback.ts
|
|
8447
8864
|
import * as p16 from "@clack/prompts";
|
|
8448
|
-
import { existsSync as
|
|
8865
|
+
import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
|
|
8449
8866
|
import { dirname as dirname8, join as join20 } from "path";
|
|
8450
8867
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8451
8868
|
import { release } from "os";
|
|
@@ -8473,8 +8890,8 @@ function readCliVersion() {
|
|
|
8473
8890
|
join20(here, "..", "..", "..", "package.json")
|
|
8474
8891
|
];
|
|
8475
8892
|
for (const path of candidates) {
|
|
8476
|
-
if (!
|
|
8477
|
-
const pkg2 = JSON.parse(
|
|
8893
|
+
if (!existsSync22(path)) continue;
|
|
8894
|
+
const pkg2 = JSON.parse(readFileSync23(path, "utf-8"));
|
|
8478
8895
|
if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
|
|
8479
8896
|
}
|
|
8480
8897
|
} catch {
|
|
@@ -8669,8 +9086,8 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
|
|
|
8669
9086
|
});
|
|
8670
9087
|
|
|
8671
9088
|
// src/cli/commands/secrets.ts
|
|
8672
|
-
import { defineCommand as
|
|
8673
|
-
import { readFileSync as
|
|
9089
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
9090
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
8674
9091
|
|
|
8675
9092
|
// src/cli/lib/citty-args.ts
|
|
8676
9093
|
function dedupePositionals(bound, rest) {
|
|
@@ -8703,7 +9120,7 @@ function parseCursorArg(raw) {
|
|
|
8703
9120
|
}
|
|
8704
9121
|
|
|
8705
9122
|
// src/cli/commands/secrets.ts
|
|
8706
|
-
var
|
|
9123
|
+
var DEPLOY_URL11 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
|
|
8707
9124
|
var COMMON_ARGS = {
|
|
8708
9125
|
app: {
|
|
8709
9126
|
type: "string",
|
|
@@ -8773,7 +9190,7 @@ function warnIfDebugRoutesEnabled(secrets) {
|
|
|
8773
9190
|
}
|
|
8774
9191
|
var APPLY_HINT = "Run `deepspace deploy` to apply \u2014 secrets take effect at deploy time.";
|
|
8775
9192
|
var LOCAL_DEV_HINT = "Running `deepspace dev start`? Restart it to load the change locally.";
|
|
8776
|
-
var
|
|
9193
|
+
var list6 = defineCommand10({
|
|
8777
9194
|
meta: { name: "list", description: "List masked secrets in a config" },
|
|
8778
9195
|
args: {
|
|
8779
9196
|
...COMMON_ARGS,
|
|
@@ -8786,7 +9203,7 @@ var list5 = defineCommand9({
|
|
|
8786
9203
|
async run({ args }) {
|
|
8787
9204
|
try {
|
|
8788
9205
|
const t = await resolveTarget(args);
|
|
8789
|
-
const { secrets } = await listSecrets(
|
|
9206
|
+
const { secrets } = await listSecrets(DEPLOY_URL11, t.token, t.appId, t.configName);
|
|
8790
9207
|
if (args.json) {
|
|
8791
9208
|
console.log(JSON.stringify({ ok: true, appId: t.appId, config: t.configName, secrets }));
|
|
8792
9209
|
return;
|
|
@@ -8803,7 +9220,7 @@ var list5 = defineCommand9({
|
|
|
8803
9220
|
}
|
|
8804
9221
|
}
|
|
8805
9222
|
});
|
|
8806
|
-
var set =
|
|
9223
|
+
var set = defineCommand10({
|
|
8807
9224
|
meta: { name: "set", description: "Set secrets from KEY=value pairs" },
|
|
8808
9225
|
args: {
|
|
8809
9226
|
...COMMON_ARGS,
|
|
@@ -8831,9 +9248,9 @@ var set = defineCommand9({
|
|
|
8831
9248
|
}
|
|
8832
9249
|
if (Object.keys(secrets).length === 1) {
|
|
8833
9250
|
const [[k, v]] = Object.entries(secrets);
|
|
8834
|
-
await setSecret(
|
|
9251
|
+
await setSecret(DEPLOY_URL11, t.token, t.appId, t.configName, k, v);
|
|
8835
9252
|
} else {
|
|
8836
|
-
await uploadSecrets(
|
|
9253
|
+
await uploadSecrets(DEPLOY_URL11, t.token, t.appId, t.configName, secrets, false);
|
|
8837
9254
|
}
|
|
8838
9255
|
const n = Object.keys(secrets).length;
|
|
8839
9256
|
ok(
|
|
@@ -8852,7 +9269,7 @@ var set = defineCommand9({
|
|
|
8852
9269
|
}
|
|
8853
9270
|
}
|
|
8854
9271
|
});
|
|
8855
|
-
var
|
|
9272
|
+
var get2 = defineCommand10({
|
|
8856
9273
|
meta: { name: "get", description: "Get a secret; pass --plain to print the value" },
|
|
8857
9274
|
args: {
|
|
8858
9275
|
...COMMON_ARGS,
|
|
@@ -8864,11 +9281,11 @@ var get = defineCommand9({
|
|
|
8864
9281
|
const t = await resolveTarget(args);
|
|
8865
9282
|
const key = validateSecretName(args.key);
|
|
8866
9283
|
if (args.plain) {
|
|
8867
|
-
const { value } = await getSecretPlain(
|
|
9284
|
+
const { value } = await getSecretPlain(DEPLOY_URL11, t.token, t.appId, t.configName, key);
|
|
8868
9285
|
process.stdout.write(process.stdout.isTTY ? value + "\n" : value);
|
|
8869
9286
|
return;
|
|
8870
9287
|
}
|
|
8871
|
-
const { secrets } = await listSecrets(
|
|
9288
|
+
const { secrets } = await listSecrets(DEPLOY_URL11, t.token, t.appId, t.configName);
|
|
8872
9289
|
const item = secrets.find((s) => s.key === key);
|
|
8873
9290
|
if (!item)
|
|
8874
9291
|
fail(new InputError(`Secret "${key}" not found in ${t.configName}`, "secret_not_found"));
|
|
@@ -8888,7 +9305,7 @@ var get = defineCommand9({
|
|
|
8888
9305
|
}
|
|
8889
9306
|
}
|
|
8890
9307
|
});
|
|
8891
|
-
var del2 =
|
|
9308
|
+
var del2 = defineCommand10({
|
|
8892
9309
|
meta: { name: "delete", description: "Delete one or more secrets" },
|
|
8893
9310
|
args: {
|
|
8894
9311
|
...COMMON_ARGS,
|
|
@@ -8903,7 +9320,7 @@ var del2 = defineCommand9({
|
|
|
8903
9320
|
for (const key of keys) {
|
|
8904
9321
|
const name = validateSecretName(key);
|
|
8905
9322
|
try {
|
|
8906
|
-
await deleteSecret(
|
|
9323
|
+
await deleteSecret(DEPLOY_URL11, t.token, t.appId, t.configName, name);
|
|
8907
9324
|
deleted++;
|
|
8908
9325
|
} catch (err) {
|
|
8909
9326
|
if (err?.status === 404) absent++;
|
|
@@ -8922,7 +9339,7 @@ var del2 = defineCommand9({
|
|
|
8922
9339
|
}
|
|
8923
9340
|
}
|
|
8924
9341
|
});
|
|
8925
|
-
var upload =
|
|
9342
|
+
var upload = defineCommand10({
|
|
8926
9343
|
meta: { name: "upload", description: "Upload secrets from a dotenv or JSON file" },
|
|
8927
9344
|
args: {
|
|
8928
9345
|
...COMMON_ARGS,
|
|
@@ -8940,11 +9357,11 @@ var upload = defineCommand9({
|
|
|
8940
9357
|
async run({ args }) {
|
|
8941
9358
|
try {
|
|
8942
9359
|
const t = await resolveTarget(args);
|
|
8943
|
-
const content = args.file === "-" ?
|
|
9360
|
+
const content = args.file === "-" ? readFileSync24(0, "utf-8") : readFileSync24(args.file, "utf-8");
|
|
8944
9361
|
const secrets = parseSecretsUpload(content);
|
|
8945
9362
|
if (Object.keys(secrets).length === 0)
|
|
8946
9363
|
fail(new InputError("No secrets found in the input.", "empty_input"));
|
|
8947
|
-
await uploadSecrets(
|
|
9364
|
+
await uploadSecrets(DEPLOY_URL11, t.token, t.appId, t.configName, secrets, args.replace);
|
|
8948
9365
|
const uploaded = Object.keys(secrets);
|
|
8949
9366
|
ok(
|
|
8950
9367
|
args.json === true,
|
|
@@ -8959,7 +9376,7 @@ var upload = defineCommand9({
|
|
|
8959
9376
|
}
|
|
8960
9377
|
}
|
|
8961
9378
|
});
|
|
8962
|
-
var download =
|
|
9379
|
+
var download = defineCommand10({
|
|
8963
9380
|
meta: { name: "download", description: "Download a config\u2019s secrets (dotenv/json/shell)" },
|
|
8964
9381
|
args: {
|
|
8965
9382
|
...COMMON_ARGS,
|
|
@@ -8981,14 +9398,14 @@ var download = defineCommand9({
|
|
|
8981
9398
|
)
|
|
8982
9399
|
);
|
|
8983
9400
|
}
|
|
8984
|
-
const { secrets } = await fetchSecretsValues(
|
|
9401
|
+
const { secrets } = await fetchSecretsValues(DEPLOY_URL11, t.token, t.appId, t.configName);
|
|
8985
9402
|
process.stdout.write(formatSecretsDownload(secrets, format));
|
|
8986
9403
|
} catch (err) {
|
|
8987
9404
|
fail(err);
|
|
8988
9405
|
}
|
|
8989
9406
|
}
|
|
8990
9407
|
});
|
|
8991
|
-
var pull =
|
|
9408
|
+
var pull = defineCommand10({
|
|
8992
9409
|
meta: { name: "pull", description: "Refresh the .dev.vars cache from the app store" },
|
|
8993
9410
|
args: { ...COMMON_ARGS },
|
|
8994
9411
|
async run({ args }) {
|
|
@@ -9004,7 +9421,7 @@ var pull = defineCommand9({
|
|
|
9004
9421
|
);
|
|
9005
9422
|
const t = await resolveTarget(args);
|
|
9006
9423
|
const ownerId = decodeJwtPayload(t.token).sub;
|
|
9007
|
-
const pulled = await pullAppSecretsCache(
|
|
9424
|
+
const pulled = await pullAppSecretsCache(DEPLOY_URL11, t.token, t.appId, t.configName);
|
|
9008
9425
|
if (!pulled) {
|
|
9009
9426
|
ok(
|
|
9010
9427
|
args.json === true,
|
|
@@ -9031,13 +9448,13 @@ var pull = defineCommand9({
|
|
|
9031
9448
|
}
|
|
9032
9449
|
}
|
|
9033
9450
|
});
|
|
9034
|
-
var configsList =
|
|
9451
|
+
var configsList = defineCommand10({
|
|
9035
9452
|
meta: { name: "list", description: "List the app\u2019s configs" },
|
|
9036
9453
|
args: { ...COMMON_ARGS },
|
|
9037
9454
|
async run({ args }) {
|
|
9038
9455
|
try {
|
|
9039
9456
|
const t = await resolveTarget(args);
|
|
9040
|
-
const { configs: configs2 } = await listConfigs(
|
|
9457
|
+
const { configs: configs2 } = await listConfigs(DEPLOY_URL11, t.token, t.appId);
|
|
9041
9458
|
ok(args.json === true, { appId: t.appId, configs: configs2 }, () => {
|
|
9042
9459
|
if (configs2.length === 0) {
|
|
9043
9460
|
console.log("No configs yet \u2014 the first `secrets set` creates one.");
|
|
@@ -9052,7 +9469,7 @@ var configsList = defineCommand9({
|
|
|
9052
9469
|
}
|
|
9053
9470
|
}
|
|
9054
9471
|
});
|
|
9055
|
-
var configsCreate =
|
|
9472
|
+
var configsCreate = defineCommand10({
|
|
9056
9473
|
meta: { name: "create", description: "Create a config (optionally copying another)" },
|
|
9057
9474
|
args: {
|
|
9058
9475
|
...COMMON_ARGS,
|
|
@@ -9064,7 +9481,7 @@ var configsCreate = defineCommand9({
|
|
|
9064
9481
|
const t = await resolveTarget(args);
|
|
9065
9482
|
const name = validateConfigName(args.name);
|
|
9066
9483
|
const copyFrom = args["copy-from"] || void 0;
|
|
9067
|
-
const { configs: configs2 } = await listConfigs(
|
|
9484
|
+
const { configs: configs2 } = await listConfigs(DEPLOY_URL11, t.token, t.appId);
|
|
9068
9485
|
if (configs2.some((c) => c.name === name)) {
|
|
9069
9486
|
if (copyFrom) {
|
|
9070
9487
|
fail(
|
|
@@ -9081,7 +9498,7 @@ var configsCreate = defineCommand9({
|
|
|
9081
9498
|
);
|
|
9082
9499
|
return;
|
|
9083
9500
|
}
|
|
9084
|
-
await createConfig(
|
|
9501
|
+
await createConfig(DEPLOY_URL11, t.token, t.appId, name, copyFrom);
|
|
9085
9502
|
ok(
|
|
9086
9503
|
args.json === true,
|
|
9087
9504
|
{ appId: t.appId, config: name, created: true, ...copyFrom ? { copyFrom } : {} },
|
|
@@ -9092,7 +9509,7 @@ var configsCreate = defineCommand9({
|
|
|
9092
9509
|
}
|
|
9093
9510
|
}
|
|
9094
9511
|
});
|
|
9095
|
-
var configsDelete =
|
|
9512
|
+
var configsDelete = defineCommand10({
|
|
9096
9513
|
meta: { name: "delete", description: "Delete a config and all of its secrets" },
|
|
9097
9514
|
args: {
|
|
9098
9515
|
...COMMON_ARGS,
|
|
@@ -9102,7 +9519,7 @@ var configsDelete = defineCommand9({
|
|
|
9102
9519
|
try {
|
|
9103
9520
|
const t = await resolveTarget(args);
|
|
9104
9521
|
const name = validateConfigName(args.name);
|
|
9105
|
-
await deleteConfig(
|
|
9522
|
+
await deleteConfig(DEPLOY_URL11, t.token, t.appId, name);
|
|
9106
9523
|
ok(
|
|
9107
9524
|
args.json === true,
|
|
9108
9525
|
{ appId: t.appId, config: name, deleted: true },
|
|
@@ -9113,16 +9530,16 @@ var configsDelete = defineCommand9({
|
|
|
9113
9530
|
}
|
|
9114
9531
|
}
|
|
9115
9532
|
});
|
|
9116
|
-
var configs =
|
|
9533
|
+
var configs = defineCommand10({
|
|
9117
9534
|
meta: { name: "configs", description: "Manage the app\u2019s secrets configs" },
|
|
9118
9535
|
subCommands: { list: configsList, create: configsCreate, delete: configsDelete }
|
|
9119
9536
|
});
|
|
9120
|
-
var secrets_default =
|
|
9537
|
+
var secrets_default = defineCommand10({
|
|
9121
9538
|
meta: { name: "secrets", description: "Manage the app\u2019s secrets store" },
|
|
9122
9539
|
subCommands: {
|
|
9123
|
-
list:
|
|
9540
|
+
list: list6,
|
|
9124
9541
|
set,
|
|
9125
|
-
get,
|
|
9542
|
+
get: get2,
|
|
9126
9543
|
delete: del2,
|
|
9127
9544
|
upload,
|
|
9128
9545
|
download,
|
|
@@ -9194,9 +9611,9 @@ var init_default = defineDeepspaceCommand({
|
|
|
9194
9611
|
});
|
|
9195
9612
|
|
|
9196
9613
|
// src/cli/commands/status.ts
|
|
9197
|
-
import { defineCommand as
|
|
9614
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
9198
9615
|
import * as p17 from "@clack/prompts";
|
|
9199
|
-
import { existsSync as
|
|
9616
|
+
import { existsSync as existsSync23, readFileSync as readFileSync25 } from "fs";
|
|
9200
9617
|
function timeAgo(iso) {
|
|
9201
9618
|
const ms = Date.now() - Date.parse(iso);
|
|
9202
9619
|
if (!Number.isFinite(ms) || ms < 0) return iso;
|
|
@@ -9229,7 +9646,7 @@ function resolveStatusApp(appDir, wranglerEnv) {
|
|
|
9229
9646
|
if (!resolved.ok) throw new InputError(resolved.reason, "invalid_env");
|
|
9230
9647
|
return { appName: resolved.name, appId: readAppId(appDir, wranglerEnv) };
|
|
9231
9648
|
}
|
|
9232
|
-
var status_default =
|
|
9649
|
+
var status_default = defineCommand11({
|
|
9233
9650
|
meta: {
|
|
9234
9651
|
name: "status",
|
|
9235
9652
|
description: "One screenful of current state: session, app, workspace, and live release"
|
|
@@ -9281,7 +9698,7 @@ var status_default = defineCommand10({
|
|
|
9281
9698
|
json.services = urls;
|
|
9282
9699
|
if (urlOverrides.length > 0) json.urlOverrides = urlOverrides;
|
|
9283
9700
|
}
|
|
9284
|
-
facts.loggedIn =
|
|
9701
|
+
facts.loggedIn = existsSync23(SESSION_PATH);
|
|
9285
9702
|
let userId = null;
|
|
9286
9703
|
if (!facts.loggedIn) {
|
|
9287
9704
|
lines.push(["Session", "not logged in"]);
|
|
@@ -9290,7 +9707,7 @@ var status_default = defineCommand10({
|
|
|
9290
9707
|
let who = "logged in";
|
|
9291
9708
|
try {
|
|
9292
9709
|
const payload = decodeJwtPayload(
|
|
9293
|
-
|
|
9710
|
+
readFileSync25(TOKEN_PATH, "utf-8").trim()
|
|
9294
9711
|
);
|
|
9295
9712
|
if (payload.email) who = payload.email;
|
|
9296
9713
|
userId = payload.sub ?? null;
|
|
@@ -9520,8 +9937,8 @@ var push_default = defineDeepspaceCommand({
|
|
|
9520
9937
|
const branchArg = args.branch === void 0 ? void 0 : String(args.branch);
|
|
9521
9938
|
const appArg = typeof args.app === "string" ? args.app : void 0;
|
|
9522
9939
|
const force = args.force === true;
|
|
9940
|
+
const appDir = findAppDir();
|
|
9523
9941
|
try {
|
|
9524
|
-
const appDir = findAppDir();
|
|
9525
9942
|
if (!appDir)
|
|
9526
9943
|
throw new Refusal(
|
|
9527
9944
|
"No wrangler.toml found \u2014 run from inside an app directory.",
|
|
@@ -9650,7 +10067,7 @@ var push_default = defineDeepspaceCommand({
|
|
|
9650
10067
|
}
|
|
9651
10068
|
const recoverable = isRecoverablePushFailure(result.status);
|
|
9652
10069
|
const rejectReason = result.reason ?? result.summary;
|
|
9653
|
-
const errorMsg = ok2 ? null : result.status === "ref_conflict" ? `The cloud repo's ${branch} moved while you worked (${rejectReason}). Run \`deepspace pull --app ${shQuote(appId)} --branch ${shQuote(branch)}\` to integrate, then push again.` : result.status === "rejected" ? `The cloud repo rejected ${branch}
|
|
10070
|
+
const errorMsg = ok2 ? null : result.status === "ref_conflict" ? `The cloud repo's ${branch} moved while you worked (${rejectReason}). Run \`deepspace pull --app ${shQuote(appId)} --branch ${shQuote(branch)}\` to integrate, then push again.` : result.status === "rejected" ? pushFailureMessage(`The cloud repo rejected ${branch}`, result, appDir ?? void 0) : `The cloud repo's ${branch} has commit(s) your local ${branch} doesn't. Run \`deepspace pull --app ${shQuote(appId)} --branch ${shQuote(branch)}\` and merge (or rebase), then push. Avoid --force here \u2014 it's guarded and will refuse rather than silently drop a peer's commits.`;
|
|
9654
10071
|
if (!args.json && ok2) p18.log.info(`App: ${appId}`);
|
|
9655
10072
|
const action = recoverable ? pullRecoveryAction(pullRecoveryCwd, appId, branch) : void 0;
|
|
9656
10073
|
if (!ok2) {
|
|
@@ -9663,7 +10080,7 @@ var push_default = defineDeepspaceCommand({
|
|
|
9663
10080
|
return { data: { status: result.status, appId, branch, oid: tipOid } };
|
|
9664
10081
|
} catch (err) {
|
|
9665
10082
|
if (err instanceof Refusal) throw err;
|
|
9666
|
-
const transportFailure = classifyPushTransportFailure(err);
|
|
10083
|
+
const transportFailure = classifyPushTransportFailure(err, appDir ?? void 0);
|
|
9667
10084
|
if (transportFailure) {
|
|
9668
10085
|
throw new Refusal(transportFailure.error, transportFailure.code);
|
|
9669
10086
|
}
|
|
@@ -9955,14 +10372,14 @@ var pull_default = defineDeepspaceCommand({
|
|
|
9955
10372
|
|
|
9956
10373
|
// src/cli/commands/clone.ts
|
|
9957
10374
|
import * as p20 from "@clack/prompts";
|
|
9958
|
-
import { existsSync as
|
|
9959
|
-
import { resolve as
|
|
10375
|
+
import { existsSync as existsSync24, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
|
|
10376
|
+
import { resolve as resolve16, basename as basename5, join as join21 } from "path";
|
|
9960
10377
|
function cleanFailedCloneDir(dir) {
|
|
9961
10378
|
let entries;
|
|
9962
10379
|
try {
|
|
9963
10380
|
entries = readdirSync6(dir);
|
|
9964
10381
|
} catch {
|
|
9965
|
-
return
|
|
10382
|
+
return existsSync24(dir) ? ["<unreadable>"] : [];
|
|
9966
10383
|
}
|
|
9967
10384
|
if (entries.length === 1 && entries[0] === ".git") {
|
|
9968
10385
|
try {
|
|
@@ -9975,7 +10392,7 @@ function cleanFailedCloneDir(dir) {
|
|
|
9975
10392
|
return entries;
|
|
9976
10393
|
}
|
|
9977
10394
|
function validateCloneTarget(dir) {
|
|
9978
|
-
if (!
|
|
10395
|
+
if (!existsSync24(dir)) return false;
|
|
9979
10396
|
let entries;
|
|
9980
10397
|
try {
|
|
9981
10398
|
entries = readdirSync6(dir);
|
|
@@ -10010,7 +10427,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10010
10427
|
async run({ args }) {
|
|
10011
10428
|
assertAppTargetResolvable(String(args.app));
|
|
10012
10429
|
const selector = String(args.app).trim();
|
|
10013
|
-
const dir =
|
|
10430
|
+
const dir = resolve16(String(args.dir ?? selector));
|
|
10014
10431
|
const dirPreexisted = validateCloneTarget(dir);
|
|
10015
10432
|
const spinner2 = args.json ? null : createSpinner();
|
|
10016
10433
|
spinner2?.start(`Resolving ${selector}\u2026`);
|
|
@@ -10053,7 +10470,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10053
10470
|
const head = resolveCommit(dir, "HEAD");
|
|
10054
10471
|
const branch = currentBranch(dir);
|
|
10055
10472
|
spinner2?.stop(
|
|
10056
|
-
`Cloned ${selector} (${branches.length} ${branches.length === 1 ? "branch" : "branches"}) into ${
|
|
10473
|
+
`Cloned ${selector} (${branches.length} ${branches.length === 1 ? "branch" : "branches"}) into ${basename5(dir)}/ at ${head?.slice(0, 10) ?? "(unborn)"}.`
|
|
10057
10474
|
);
|
|
10058
10475
|
if (!args.json && !branch) {
|
|
10059
10476
|
p20.log.warn("HEAD is detached \u2014 check `git branch -a`.");
|
|
@@ -10076,7 +10493,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10076
10493
|
|
|
10077
10494
|
// src/cli/commands/releases.ts
|
|
10078
10495
|
import * as p21 from "@clack/prompts";
|
|
10079
|
-
var
|
|
10496
|
+
var DEPLOY_URL12 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
|
|
10080
10497
|
var releases_default = defineDeepspaceCommand({
|
|
10081
10498
|
meta: {
|
|
10082
10499
|
name: "releases",
|
|
@@ -10111,8 +10528,8 @@ var releases_default = defineDeepspaceCommand({
|
|
|
10111
10528
|
const spinner2 = args.json ? null : createSpinner();
|
|
10112
10529
|
spinner2?.start("Loading release history\u2026");
|
|
10113
10530
|
const token = await ensureToken();
|
|
10114
|
-
const appId = await resolveAppTarget(
|
|
10115
|
-
const { releases } = await repoApi(
|
|
10531
|
+
const appId = await resolveAppTarget(DEPLOY_URL12, token, appArg, { wranglerEnv: envArg });
|
|
10532
|
+
const { releases } = await repoApi(DEPLOY_URL12, token, appId).listReleases(limit);
|
|
10116
10533
|
spinner2?.stop(`Loaded ${releases.length} ${releases.length === 1 ? "release" : "releases"}.`);
|
|
10117
10534
|
if (!args.json) {
|
|
10118
10535
|
if (releases.length === 0) {
|
|
@@ -10144,7 +10561,7 @@ Retry in a moment, or re-run with --allow-do-deletion to accept the risk.`,
|
|
|
10144
10561
|
"do_guard_unavailable"
|
|
10145
10562
|
);
|
|
10146
10563
|
}
|
|
10147
|
-
var
|
|
10564
|
+
var DEPLOY_URL13 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
|
|
10148
10565
|
function pickPreviousRelease(releases) {
|
|
10149
10566
|
if (releases.length === 0) {
|
|
10150
10567
|
return { error: "No releases recorded yet \u2014 nothing to roll back to.", code: "no_releases" };
|
|
@@ -10206,8 +10623,8 @@ var rollback_default = defineDeepspaceCommand({
|
|
|
10206
10623
|
const spinner2 = args.json ? null : createSpinner();
|
|
10207
10624
|
spinner2?.start("Preparing rollback\u2026");
|
|
10208
10625
|
const token = await ensureToken();
|
|
10209
|
-
const appId = await resolveAppTarget(
|
|
10210
|
-
const api4 = repoApi(
|
|
10626
|
+
const appId = await resolveAppTarget(DEPLOY_URL13, token, appArg, { wranglerEnv: envArg });
|
|
10627
|
+
const api4 = repoApi(DEPLOY_URL13, token, appId);
|
|
10211
10628
|
let releaseId = args.release ? String(args.release).trim() : "";
|
|
10212
10629
|
if (!releaseId) {
|
|
10213
10630
|
const { releases } = await api4.listReleases(2);
|
|
@@ -10218,7 +10635,7 @@ var rollback_default = defineDeepspaceCommand({
|
|
|
10218
10635
|
spinner2?.message(`Rolling back to ${releaseId}\u2026`);
|
|
10219
10636
|
let result;
|
|
10220
10637
|
try {
|
|
10221
|
-
result = await apiFetch(
|
|
10638
|
+
result = await apiFetch(DEPLOY_URL13, token, `/api/deploy/${appId}/rollback`, {
|
|
10222
10639
|
method: "POST",
|
|
10223
10640
|
body: JSON.stringify({
|
|
10224
10641
|
releaseId,
|
|
@@ -10279,11 +10696,11 @@ Re-run with --allow-do-deletion to accept the data loss.`,
|
|
|
10279
10696
|
});
|
|
10280
10697
|
|
|
10281
10698
|
// src/cli/commands/workspace.ts
|
|
10282
|
-
import { defineCommand as
|
|
10699
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
10283
10700
|
|
|
10284
10701
|
// src/cli/commands/workspace/new.ts
|
|
10285
10702
|
import * as p25 from "@clack/prompts";
|
|
10286
|
-
import { isAbsolute as isAbsolute6, resolve as
|
|
10703
|
+
import { isAbsolute as isAbsolute6, resolve as resolve17 } from "path";
|
|
10287
10704
|
|
|
10288
10705
|
// src/cli/commands/workspace/analysis.ts
|
|
10289
10706
|
import * as p23 from "@clack/prompts";
|
|
@@ -10408,7 +10825,7 @@ function printOverlaps(overlaps, json) {
|
|
|
10408
10825
|
|
|
10409
10826
|
// src/cli/commands/workspace/local.ts
|
|
10410
10827
|
import * as p24 from "@clack/prompts";
|
|
10411
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
10828
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync26, realpathSync as realpathSync5, renameSync as renameSync2, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
|
|
10412
10829
|
import { dirname as dirname9, isAbsolute as isAbsolute5, join as join22, relative as relative2, sep as sep2 } from "path";
|
|
10413
10830
|
var WORKSPACE_MARKER = "deepspace-workspace.json";
|
|
10414
10831
|
function excludeWorktreeDir(appDir, dir) {
|
|
@@ -10466,7 +10883,7 @@ function isManagedWorkspaceWorktree(worktreeRoot, workspaceId) {
|
|
|
10466
10883
|
const markerPath = worktreeMarkerPath(worktreeRoot);
|
|
10467
10884
|
if (!markerPath) return false;
|
|
10468
10885
|
try {
|
|
10469
|
-
const marker = JSON.parse(
|
|
10886
|
+
const marker = JSON.parse(readFileSync26(markerPath, "utf-8"));
|
|
10470
10887
|
return marker.version === 1 && marker.workspaceId === workspaceId && marker.mode === "managed-linked";
|
|
10471
10888
|
} catch {
|
|
10472
10889
|
return false;
|
|
@@ -10497,7 +10914,7 @@ function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint,
|
|
|
10497
10914
|
function inOwnLinkedWorktree(appDir, id) {
|
|
10498
10915
|
if (workspaceIdFromBranch(currentBranch(appDir)) !== id) return false;
|
|
10499
10916
|
try {
|
|
10500
|
-
return
|
|
10917
|
+
return statSync3(join22(repoToplevel(appDir), ".git")).isFile();
|
|
10501
10918
|
} catch {
|
|
10502
10919
|
return false;
|
|
10503
10920
|
}
|
|
@@ -10843,7 +11260,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
10843
11260
|
idempotencyKey: mintIdempotencyKey()
|
|
10844
11261
|
});
|
|
10845
11262
|
const dirInput = typeof args.dir === "string" ? args.dir.trim() : "";
|
|
10846
|
-
const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput :
|
|
11263
|
+
const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput : resolve17(appDir, dirInput) : defaultWorkspaceRoot(appDir, id);
|
|
10847
11264
|
const dir = appDirInWorktree(appDir, worktreeRoot);
|
|
10848
11265
|
try {
|
|
10849
11266
|
materializeWorkspaceWorktree(appDir, worktreeRoot, branch, baseOid, id);
|
|
@@ -10881,8 +11298,8 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
10881
11298
|
|
|
10882
11299
|
// src/cli/commands/workspace/attach.ts
|
|
10883
11300
|
import * as p26 from "@clack/prompts";
|
|
10884
|
-
import { existsSync as
|
|
10885
|
-
import { isAbsolute as isAbsolute7, resolve as
|
|
11301
|
+
import { existsSync as existsSync25, readdirSync as readdirSync7, rmSync as rmSync6 } from "fs";
|
|
11302
|
+
import { isAbsolute as isAbsolute7, resolve as resolve18 } from "path";
|
|
10886
11303
|
function finishedWorkspaceMessage(id, view) {
|
|
10887
11304
|
const workspace = view.workspace;
|
|
10888
11305
|
if (workspace.status === "landed") {
|
|
@@ -10891,7 +11308,7 @@ function finishedWorkspaceMessage(id, view) {
|
|
|
10891
11308
|
return `Workspace ${id} is ${workspace.status} \u2014 its ref is retained briefly (fetch ${workspace.ref} to inspect), but attach only works on active workspaces.`;
|
|
10892
11309
|
}
|
|
10893
11310
|
function cleanFailedFreshAttachDir(dir) {
|
|
10894
|
-
if (!
|
|
11311
|
+
if (!existsSync25(dir)) return [];
|
|
10895
11312
|
let entries;
|
|
10896
11313
|
try {
|
|
10897
11314
|
entries = readdirSync7(dir);
|
|
@@ -10967,7 +11384,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
10967
11384
|
);
|
|
10968
11385
|
}
|
|
10969
11386
|
const requestedDir = typeof args.dir === "string" ? args.dir.trim() : "";
|
|
10970
|
-
const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir :
|
|
11387
|
+
const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir : resolve18(appDir, requestedDir) : defaultWorkspaceRoot(appDir, id);
|
|
10971
11388
|
const dir2 = appDirInWorktree(appDir, worktreeRoot);
|
|
10972
11389
|
if (resolveCommit(appDir, `refs/heads/${branch}`)) {
|
|
10973
11390
|
throw new Refusal(
|
|
@@ -11006,11 +11423,11 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11006
11423
|
extra: { status: view.workspace.status }
|
|
11007
11424
|
});
|
|
11008
11425
|
}
|
|
11009
|
-
const dir =
|
|
11426
|
+
const dir = resolve18(
|
|
11010
11427
|
process.cwd(),
|
|
11011
11428
|
(typeof args.dir === "string" ? args.dir.trim() : "") || `ws-${id.slice(3).toLowerCase()}`
|
|
11012
11429
|
);
|
|
11013
|
-
if (
|
|
11430
|
+
if (existsSync25(dir)) {
|
|
11014
11431
|
spinner2?.stop("Target exists.");
|
|
11015
11432
|
throw new Refusal(`${dir} already exists \u2014 pass a different directory.`, "dir_exists");
|
|
11016
11433
|
}
|
|
@@ -11328,13 +11745,13 @@ import * as p30 from "@clack/prompts";
|
|
|
11328
11745
|
|
|
11329
11746
|
// src/cli/lib/validation.ts
|
|
11330
11747
|
import { sync as spawnSync7 } from "cross-spawn";
|
|
11331
|
-
import { readFileSync as
|
|
11748
|
+
import { readFileSync as readFileSync27 } from "fs";
|
|
11332
11749
|
import { join as join23 } from "path";
|
|
11333
11750
|
var MAX_SUMMARY_CHARS = 4e3;
|
|
11334
11751
|
var MAX_OUTPUT_BUFFER = 64 * 1024 * 1024;
|
|
11335
11752
|
function configuredCommand(appDir) {
|
|
11336
11753
|
try {
|
|
11337
|
-
const pkg2 = JSON.parse(
|
|
11754
|
+
const pkg2 = JSON.parse(readFileSync27(join23(appDir, "package.json"), "utf-8"));
|
|
11338
11755
|
if (pkg2.scripts?.validate) return `${detectPackageManager(appDir)} run --silent validate`;
|
|
11339
11756
|
} catch {
|
|
11340
11757
|
}
|
|
@@ -11754,7 +12171,7 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11754
12171
|
});
|
|
11755
12172
|
|
|
11756
12173
|
// src/cli/commands/workspace.ts
|
|
11757
|
-
var workspace_default =
|
|
12174
|
+
var workspace_default = defineCommand12({
|
|
11758
12175
|
meta: {
|
|
11759
12176
|
name: "workspace",
|
|
11760
12177
|
description: "Durable parallel-agent workspaces (new/attach/sync/list/status/land/drop)"
|
|
@@ -11925,7 +12342,7 @@ var activity_default = defineDeepspaceCommand({
|
|
|
11925
12342
|
});
|
|
11926
12343
|
|
|
11927
12344
|
// src/cli/commands/git-credential.ts
|
|
11928
|
-
import { defineCommand as
|
|
12345
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
11929
12346
|
function parseFields(input) {
|
|
11930
12347
|
const fields = /* @__PURE__ */ new Map();
|
|
11931
12348
|
for (const line of input.split("\n")) {
|
|
@@ -11974,7 +12391,7 @@ async function readStdin() {
|
|
|
11974
12391
|
for await (const chunk of process.stdin) data += chunk;
|
|
11975
12392
|
return data;
|
|
11976
12393
|
}
|
|
11977
|
-
var git_credential_default =
|
|
12394
|
+
var git_credential_default = defineCommand13({
|
|
11978
12395
|
meta: {
|
|
11979
12396
|
name: "git-credential",
|
|
11980
12397
|
description: "Git credential helper (installed automatically; not for direct use)"
|
|
@@ -12092,8 +12509,8 @@ function reportSource(appId, state, json) {
|
|
|
12092
12509
|
async function moveToGitHub(input) {
|
|
12093
12510
|
const { appDir, appId, token, deployUrl, state, remoteArg } = input;
|
|
12094
12511
|
const selected = requireGitHubRemote(appDir, remoteArg);
|
|
12095
|
-
const
|
|
12096
|
-
if (sameSource(state.source,
|
|
12512
|
+
const target2 = { provider: "github", repository: selected.repository };
|
|
12513
|
+
if (sameSource(state.source, target2)) return { source: target2, revision: state.revision };
|
|
12097
12514
|
if (state.source?.provider === "deepspace") {
|
|
12098
12515
|
requireLocalHead(appDir);
|
|
12099
12516
|
const api4 = repoApi(deployUrl, token, appId);
|
|
@@ -12149,7 +12566,7 @@ async function moveToGitHub(input) {
|
|
|
12149
12566
|
);
|
|
12150
12567
|
}
|
|
12151
12568
|
return setAppSource(deployUrl, token, appId, {
|
|
12152
|
-
source:
|
|
12569
|
+
source: target2,
|
|
12153
12570
|
expectedRevision: state.revision,
|
|
12154
12571
|
refs: wanted,
|
|
12155
12572
|
...releaseExpectation(latest)
|
|
@@ -12157,17 +12574,17 @@ async function moveToGitHub(input) {
|
|
|
12157
12574
|
}
|
|
12158
12575
|
requirePublishedHead(appDir, selected, appId);
|
|
12159
12576
|
return setAppSource(deployUrl, token, appId, {
|
|
12160
|
-
source:
|
|
12577
|
+
source: target2,
|
|
12161
12578
|
expectedRevision: state.revision
|
|
12162
12579
|
});
|
|
12163
12580
|
}
|
|
12164
12581
|
async function moveToDeepSpace(input) {
|
|
12165
12582
|
const { appDir, appId, token, deployUrl, state, remoteArg } = input;
|
|
12166
|
-
const
|
|
12167
|
-
if (sameSource(state.source,
|
|
12583
|
+
const target2 = { provider: "deepspace" };
|
|
12584
|
+
if (sameSource(state.source, target2)) return { source: target2, revision: state.revision };
|
|
12168
12585
|
if (state.source?.provider !== "github") {
|
|
12169
12586
|
return setAppSource(deployUrl, token, appId, {
|
|
12170
|
-
source:
|
|
12587
|
+
source: target2,
|
|
12171
12588
|
expectedRevision: state.revision
|
|
12172
12589
|
});
|
|
12173
12590
|
}
|
|
@@ -12201,7 +12618,7 @@ async function moveToDeepSpace(input) {
|
|
|
12201
12618
|
);
|
|
12202
12619
|
}
|
|
12203
12620
|
return setAppSource(deployUrl, token, appId, {
|
|
12204
|
-
source:
|
|
12621
|
+
source: target2,
|
|
12205
12622
|
expectedRevision: state.revision,
|
|
12206
12623
|
branch,
|
|
12207
12624
|
commitOid: oid,
|
|
@@ -12828,11 +13245,11 @@ function reportMigration(migration, json) {
|
|
|
12828
13245
|
|
|
12829
13246
|
// src/cli/cli.ts
|
|
12830
13247
|
var __dirname = dirname10(fileURLToPath3(import.meta.url));
|
|
12831
|
-
var pkg = JSON.parse(
|
|
12832
|
-
if (process.platform === "linux" && !process.env.SSL_CERT_FILE &&
|
|
13248
|
+
var pkg = JSON.parse(readFileSync28(join24(__dirname, "..", "package.json"), "utf-8"));
|
|
13249
|
+
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync26("/etc/ssl/certs/ca-certificates.crt")) {
|
|
12833
13250
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
12834
13251
|
}
|
|
12835
|
-
var create2 =
|
|
13252
|
+
var create2 = defineCommand14({
|
|
12836
13253
|
meta: {
|
|
12837
13254
|
name: "create",
|
|
12838
13255
|
description: "Create a new DeepSpace app (runs create-deepspace; all flags are forwarded)"
|
|
@@ -12871,19 +13288,20 @@ var create2 = defineCommand13({
|
|
|
12871
13288
|
}
|
|
12872
13289
|
});
|
|
12873
13290
|
var rename = (cmd, name) => ({ ...cmd, meta: { ...cmd.meta ?? {}, name } });
|
|
12874
|
-
var auth =
|
|
13291
|
+
var auth = defineCommand14({
|
|
12875
13292
|
meta: { name: "auth", description: "Session: login, logout, whoami" },
|
|
12876
13293
|
subCommands: { login: login_default, logout: logout_default, whoami: whoami_default }
|
|
12877
13294
|
});
|
|
12878
|
-
var app =
|
|
13295
|
+
var app = defineCommand14({
|
|
12879
13296
|
meta: {
|
|
12880
13297
|
name: "app",
|
|
12881
|
-
description: "The app itself: create, init, list, source, migrate, undeploy, transfer, collaborators, domain, usage"
|
|
13298
|
+
description: "The app itself: create, init, list, files, source, migrate, undeploy, transfer, collaborators, domain, usage"
|
|
12882
13299
|
},
|
|
12883
13300
|
subCommands: {
|
|
12884
13301
|
create: create2,
|
|
12885
13302
|
init: init_default,
|
|
12886
13303
|
list: rename(apps_default, "list"),
|
|
13304
|
+
files: app_files_default,
|
|
12887
13305
|
undeploy: undeploy_default,
|
|
12888
13306
|
transfer: transfer_default,
|
|
12889
13307
|
collaborators: collaborators_default,
|
|
@@ -12893,11 +13311,11 @@ var app = defineCommand13({
|
|
|
12893
13311
|
migrate: migrate_default
|
|
12894
13312
|
}
|
|
12895
13313
|
});
|
|
12896
|
-
var devGroup =
|
|
13314
|
+
var devGroup = defineCommand14({
|
|
12897
13315
|
meta: { name: "dev", description: "Local development" },
|
|
12898
13316
|
subCommands: { start: rename(dev_default, "start"), kill: kill_default }
|
|
12899
13317
|
});
|
|
12900
|
-
var testGroup =
|
|
13318
|
+
var testGroup = defineCommand14({
|
|
12901
13319
|
meta: { name: "test", description: "App tests and test tooling" },
|
|
12902
13320
|
subCommands: {
|
|
12903
13321
|
run: rename(test_default, "run"),
|
|
@@ -12905,7 +13323,7 @@ var testGroup = defineCommand13({
|
|
|
12905
13323
|
accounts: rename(test_accounts_default, "accounts")
|
|
12906
13324
|
}
|
|
12907
13325
|
});
|
|
12908
|
-
var main =
|
|
13326
|
+
var main = defineCommand14({
|
|
12909
13327
|
meta: {
|
|
12910
13328
|
name: "deepspace",
|
|
12911
13329
|
version: pkg.version,
|