deepspace 0.10.3 → 0.11.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 +8 -0
- package/dist/cli.js +177 -101
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# deepspace
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Replace the base64 deploy asset transport with a content-addressed one. The CLI now hashes the build output locally, asks the platform which files it is missing, and streams only those into the app's release store; unchanged files are never re-uploaded, and no deploy ever serializes its assets into a JSON payload. This removes the "Worker exceeded memory limit" failure that surfaced as a misleading Cloudflare-incident 503 on asset-heavy deploys, and a deploy-service resource limit is now reported distinctly from a genuine Cloudflare API incident.
|
|
8
|
+
|
|
9
|
+
**This release requires an updated deploy service and is required to deploy.** The old grouped-upload endpoints are gone: an older CLI is answered with a clear "update to deploy" instruction, and this CLI refuses to start against a deploy service that does not advertise the new transport. Releases recorded before the cutover can no longer be rolled back to directly — redeploy that commit instead.
|
|
10
|
+
|
|
3
11
|
## 0.10.3
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/cli/cli.ts
|
|
4
4
|
import { defineCommand as defineCommand13, runMain, runCommand } from "citty";
|
|
5
5
|
import { sync as spawnSync8 } from "cross-spawn";
|
|
6
|
-
import { readFileSync as
|
|
6
|
+
import { readFileSync as readFileSync28, existsSync as existsSync25 } from "fs";
|
|
7
7
|
import { dirname as dirname10, join as join24 } from "path";
|
|
8
8
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9
9
|
|
|
@@ -3715,6 +3715,7 @@ import { resolve as resolve12 } from "path";
|
|
|
3715
3715
|
// src/cli/commands/deploy/build.ts
|
|
3716
3716
|
import * as p6 from "@clack/prompts";
|
|
3717
3717
|
import { execSync as execSync2 } from "child_process";
|
|
3718
|
+
import { createHash as createHash2 } from "crypto";
|
|
3718
3719
|
import { existsSync as existsSync15, readFileSync as readFileSync17, readdirSync as readdirSync4 } from "fs";
|
|
3719
3720
|
import { dirname as dirname5, join as join16, resolve as resolve10 } from "path";
|
|
3720
3721
|
|
|
@@ -4174,9 +4175,12 @@ function collectAssets(dir) {
|
|
|
4174
4175
|
if (entry.isDirectory()) {
|
|
4175
4176
|
walk(fullPath, relativePath);
|
|
4176
4177
|
} else {
|
|
4178
|
+
const bytes = readFileSync17(fullPath);
|
|
4177
4179
|
assets.push({
|
|
4178
4180
|
path: `/${relativePath}`,
|
|
4179
|
-
|
|
4181
|
+
hash: createHash2("sha256").update(bytes).digest("hex"),
|
|
4182
|
+
size: bytes.byteLength,
|
|
4183
|
+
sourcePath: fullPath
|
|
4180
4184
|
});
|
|
4181
4185
|
}
|
|
4182
4186
|
}
|
|
@@ -4463,7 +4467,7 @@ function createDeployOutput(json) {
|
|
|
4463
4467
|
|
|
4464
4468
|
// src/cli/commands/deploy/request.ts
|
|
4465
4469
|
import * as p10 from "@clack/prompts";
|
|
4466
|
-
import {
|
|
4470
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
4467
4471
|
|
|
4468
4472
|
// src/cli/commands/deploy/repository.ts
|
|
4469
4473
|
import * as p9 from "@clack/prompts";
|
|
@@ -5203,12 +5207,9 @@ function detachedHeadRefusal() {
|
|
|
5203
5207
|
|
|
5204
5208
|
// src/cli/commands/deploy/request.ts
|
|
5205
5209
|
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
|
-
})();
|
|
5210
|
+
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.";
|
|
5211
|
+
var REQUIRED_ASSET_TRANSPORT = "content-addressed-v1";
|
|
5212
|
+
var UPLOAD_CONCURRENCY = 4;
|
|
5212
5213
|
async function deployBuiltBundle(options) {
|
|
5213
5214
|
const {
|
|
5214
5215
|
deployUrl,
|
|
@@ -5229,44 +5230,11 @@ async function deployBuiltBundle(options) {
|
|
|
5229
5230
|
} else if (bundle.extraRoutes.length) {
|
|
5230
5231
|
p10.log.info(`Custom worker-first routes: ${bundle.extraRoutes.join(", ")}`);
|
|
5231
5232
|
}
|
|
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
|
-
}
|
|
5233
|
+
await requireAssetTransport(deployUrl, spinner2, output);
|
|
5234
|
+
await uploadDeployAssets({ deployUrl, appId, token, assets: bundle.assets, output, spinner: spinner2 });
|
|
5266
5235
|
spinner2.message(`Deploying ${appName}...`);
|
|
5267
5236
|
let confirmRename = options.rename;
|
|
5268
5237
|
const bail = async (message, stopLabel = "Deploy failed", code, actionRequired = false, action) => {
|
|
5269
|
-
await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
|
|
5270
5238
|
if (stopLabel !== null) spinner2.stop(stopLabel);
|
|
5271
5239
|
p10.cancel(code ? withSlug(message, code) : message);
|
|
5272
5240
|
if (action) printAction(action);
|
|
@@ -5288,8 +5256,7 @@ async function deployBuiltBundle(options) {
|
|
|
5288
5256
|
new Blob([bundle.workerJs], { type: "application/javascript" }),
|
|
5289
5257
|
"worker.js"
|
|
5290
5258
|
);
|
|
5291
|
-
form.append("
|
|
5292
|
-
form.append("totalGroups", String(totalGroups));
|
|
5259
|
+
form.append("assetManifest", JSON.stringify(assetManifest(bundle.assets)));
|
|
5293
5260
|
form.append("appMigrations", JSON.stringify(bundle.appMigrations));
|
|
5294
5261
|
if (bundle.doManifest) form.append("doManifest", JSON.stringify(bundle.doManifest));
|
|
5295
5262
|
if (bundle.customBindings.length) {
|
|
@@ -5368,7 +5335,11 @@ async function deployBuiltBundle(options) {
|
|
|
5368
5335
|
);
|
|
5369
5336
|
}
|
|
5370
5337
|
if (!response.ok || !body.success) {
|
|
5371
|
-
await bail(
|
|
5338
|
+
await bail(
|
|
5339
|
+
formatDeployWorkerError(response.status, body.error, body.code),
|
|
5340
|
+
"Deploy failed",
|
|
5341
|
+
body.code
|
|
5342
|
+
);
|
|
5372
5343
|
}
|
|
5373
5344
|
if (body.onBehalfOfOwner) {
|
|
5374
5345
|
p10.log.warn(`Deployed on behalf of owner ${body.onBehalfOfOwner}`);
|
|
@@ -5385,17 +5356,139 @@ async function deployBuiltBundle(options) {
|
|
|
5385
5356
|
}
|
|
5386
5357
|
return body;
|
|
5387
5358
|
}
|
|
5388
|
-
|
|
5359
|
+
function assetManifest(assets) {
|
|
5360
|
+
return assets.map((asset) => ({ path: asset.path, hash: asset.hash, size: asset.size }));
|
|
5361
|
+
}
|
|
5362
|
+
async function requireAssetTransport(deployUrl, spinner2, output) {
|
|
5363
|
+
let advertised;
|
|
5389
5364
|
try {
|
|
5390
|
-
await fetch(
|
|
5391
|
-
|
|
5392
|
-
|
|
5365
|
+
const response = await fetch(`${deployUrl}/api/health`);
|
|
5366
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
5367
|
+
const body = await response.json();
|
|
5368
|
+
advertised = body.capabilities?.assetTransport;
|
|
5369
|
+
} catch (error) {
|
|
5370
|
+
spinner2.stop("Deploy failed");
|
|
5371
|
+
output.die(
|
|
5372
|
+
`Could not reach the DeepSpace deploy service at ${deployUrl} to check its capabilities: ${errorMessage4(error)}`,
|
|
5373
|
+
"deploy_service_unreachable"
|
|
5374
|
+
);
|
|
5375
|
+
}
|
|
5376
|
+
if (advertised !== REQUIRED_ASSET_TRANSPORT) {
|
|
5377
|
+
spinner2.stop("Deploy failed");
|
|
5378
|
+
output.die(
|
|
5379
|
+
`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.`,
|
|
5380
|
+
"asset_transport_unsupported"
|
|
5393
5381
|
);
|
|
5394
|
-
} catch {
|
|
5395
5382
|
}
|
|
5396
5383
|
}
|
|
5397
|
-
function
|
|
5384
|
+
async function uploadDeployAssets(options) {
|
|
5385
|
+
const { deployUrl, appId, token, assets, spinner: spinner2 } = options;
|
|
5386
|
+
const output = options.output;
|
|
5387
|
+
const byHash = new Map(assets.map((asset) => [asset.hash, asset]));
|
|
5388
|
+
spinner2.message("Checking which assets are already uploaded...");
|
|
5389
|
+
let planResponse;
|
|
5390
|
+
try {
|
|
5391
|
+
planResponse = await postWithRetry(`${deployUrl}/api/deploy/${appId}/asset-plan`, () => ({
|
|
5392
|
+
method: "POST",
|
|
5393
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
5394
|
+
body: JSON.stringify({
|
|
5395
|
+
assets: [...byHash.values()].map((asset) => ({ hash: asset.hash, size: asset.size }))
|
|
5396
|
+
})
|
|
5397
|
+
}));
|
|
5398
|
+
} catch (error) {
|
|
5399
|
+
spinner2.stop("Deploy failed");
|
|
5400
|
+
output.die(`Asset plan failed (network): ${errorMessage4(error)}`, "upload_failed");
|
|
5401
|
+
}
|
|
5402
|
+
const planBody = await planResponse.json().catch(() => ({}));
|
|
5403
|
+
if (!planResponse.ok) {
|
|
5404
|
+
spinner2.stop("Deploy failed");
|
|
5405
|
+
output.die(
|
|
5406
|
+
formatDeployWorkerError(planResponse.status, planBody.error, planBody.code),
|
|
5407
|
+
planBody.code ?? "upload_failed"
|
|
5408
|
+
);
|
|
5409
|
+
}
|
|
5410
|
+
const missing = [];
|
|
5411
|
+
for (const hash of planBody.missing ?? []) {
|
|
5412
|
+
const asset = byHash.get(hash);
|
|
5413
|
+
if (!asset) {
|
|
5414
|
+
spinner2.stop("Deploy failed");
|
|
5415
|
+
output.die(
|
|
5416
|
+
`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.`,
|
|
5417
|
+
"upload_failed"
|
|
5418
|
+
);
|
|
5419
|
+
}
|
|
5420
|
+
missing.push(asset);
|
|
5421
|
+
}
|
|
5422
|
+
if (missing.length === 0) {
|
|
5423
|
+
p10.log.info(`Assets: ${byHash.size} file(s), all already uploaded`);
|
|
5424
|
+
return;
|
|
5425
|
+
}
|
|
5426
|
+
const missingBytes = missing.reduce((total, asset) => total + asset.size, 0);
|
|
5427
|
+
p10.log.info(
|
|
5428
|
+
`Assets: ${byHash.size} file(s), uploading ${missing.length} (${Math.ceil(missingBytes / 1024)} KiB); the rest are already stored`
|
|
5429
|
+
);
|
|
5430
|
+
let uploaded = 0;
|
|
5431
|
+
const next = () => missing.pop();
|
|
5432
|
+
const worker = async () => {
|
|
5433
|
+
for (let asset = next(); asset; asset = next()) {
|
|
5434
|
+
const response = await postWithRetry(
|
|
5435
|
+
`${deployUrl}/api/deploy/${appId}/assets/${asset.hash}`,
|
|
5436
|
+
() => ({
|
|
5437
|
+
method: "PUT",
|
|
5438
|
+
headers: {
|
|
5439
|
+
Authorization: `Bearer ${token}`,
|
|
5440
|
+
"Content-Type": "application/octet-stream"
|
|
5441
|
+
},
|
|
5442
|
+
// Read whole, per attempt. The platform matches Content-Length
|
|
5443
|
+
// against the plan before it touches storage, and a stream body
|
|
5444
|
+
// would be sent chunked with no length at all; a retry also needs a
|
|
5445
|
+
// body it can send again.
|
|
5446
|
+
body: readFileSync18(asset.sourcePath)
|
|
5447
|
+
})
|
|
5448
|
+
);
|
|
5449
|
+
if (!response.ok) {
|
|
5450
|
+
const body = await response.json().catch(() => ({}));
|
|
5451
|
+
throw new AssetUploadError(
|
|
5452
|
+
body.error ?? `Upload of ${asset.path} failed: HTTP ${response.status}`,
|
|
5453
|
+
body.code ?? "upload_failed",
|
|
5454
|
+
response.status
|
|
5455
|
+
);
|
|
5456
|
+
}
|
|
5457
|
+
uploaded++;
|
|
5458
|
+
spinner2.message(`Uploading assets \u2014 ${uploaded}/${uploaded + missing.length}...`);
|
|
5459
|
+
}
|
|
5460
|
+
};
|
|
5461
|
+
try {
|
|
5462
|
+
await Promise.all(
|
|
5463
|
+
Array.from({ length: Math.min(UPLOAD_CONCURRENCY, missing.length) }, worker)
|
|
5464
|
+
);
|
|
5465
|
+
} catch (error) {
|
|
5466
|
+
spinner2.stop("Deploy failed");
|
|
5467
|
+
if (error instanceof AssetUploadError) {
|
|
5468
|
+
output.die(formatDeployWorkerError(error.status, error.message, error.code), error.code);
|
|
5469
|
+
}
|
|
5470
|
+
output.die(`Asset upload failed (network): ${errorMessage4(error)}`, "upload_failed");
|
|
5471
|
+
}
|
|
5472
|
+
}
|
|
5473
|
+
var AssetUploadError = class extends Error {
|
|
5474
|
+
constructor(message, code, status3) {
|
|
5475
|
+
super(message);
|
|
5476
|
+
this.code = code;
|
|
5477
|
+
this.status = status3;
|
|
5478
|
+
}
|
|
5479
|
+
};
|
|
5480
|
+
function isDeployServiceResourceLimit(status3, error) {
|
|
5481
|
+
if (!error) return status3 === 500 || status3 === 502;
|
|
5482
|
+
return /\b110[12]\b/.test(error) && /worker|error code/i.test(error);
|
|
5483
|
+
}
|
|
5484
|
+
function formatDeployWorkerError(status3, error, code) {
|
|
5398
5485
|
const detail = error ?? `Deployment error (${status3})`;
|
|
5486
|
+
if (code === "cli_outdated") return detail;
|
|
5487
|
+
if (isDeployServiceResourceLimit(status3, error)) {
|
|
5488
|
+
return `${DEPLOY_SERVICE_LIMIT_HINT}
|
|
5489
|
+
|
|
5490
|
+
Underlying error: ${detail}`;
|
|
5491
|
+
}
|
|
5399
5492
|
if (status3 < 500 && ![
|
|
5400
5493
|
"Upload session failed",
|
|
5401
5494
|
"Asset upload failed",
|
|
@@ -5412,23 +5505,6 @@ Underlying error: ${detail}`;
|
|
|
5412
5505
|
function errorMessage4(error) {
|
|
5413
5506
|
return error instanceof Error ? error.message : String(error);
|
|
5414
5507
|
}
|
|
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
5508
|
async function postWithRetry(url, makeInit, {
|
|
5433
5509
|
attempts = 4,
|
|
5434
5510
|
retryServerErrors = true
|
|
@@ -5454,7 +5530,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5454
5530
|
|
|
5455
5531
|
// src/cli/commands/deploy/secrets.ts
|
|
5456
5532
|
import * as p11 from "@clack/prompts";
|
|
5457
|
-
import { existsSync as existsSync18, readFileSync as
|
|
5533
|
+
import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
|
|
5458
5534
|
function classifyDevVarsSecrets(options) {
|
|
5459
5535
|
const store = new Set(options.storeSecretNames);
|
|
5460
5536
|
const strayKeys = options.handEditedDevVarKeys.filter((key) => !store.has(key));
|
|
@@ -5553,7 +5629,7 @@ function prepareDeploySecrets(options) {
|
|
|
5553
5629
|
}
|
|
5554
5630
|
function readCustomDevVars(path, output) {
|
|
5555
5631
|
if (!existsSync18(path)) return {};
|
|
5556
|
-
const section = extractCustomDevVars(stripGeneratedSecretsCache(
|
|
5632
|
+
const section = extractCustomDevVars(stripGeneratedSecretsCache(readFileSync19(path, "utf-8")));
|
|
5557
5633
|
if (!section) return {};
|
|
5558
5634
|
try {
|
|
5559
5635
|
return parseDevVars(section);
|
|
@@ -6479,7 +6555,7 @@ var usage_default = defineDeepspaceCommand({
|
|
|
6479
6555
|
});
|
|
6480
6556
|
|
|
6481
6557
|
// src/cli/commands/add.ts
|
|
6482
|
-
import { existsSync as existsSync20, readFileSync as
|
|
6558
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21, realpathSync as realpathSync3 } from "fs";
|
|
6483
6559
|
import { dirname as dirname7, join as join19, resolve as resolve14 } from "path";
|
|
6484
6560
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6485
6561
|
|
|
@@ -6492,7 +6568,7 @@ import {
|
|
|
6492
6568
|
mkdirSync as mkdirSync6,
|
|
6493
6569
|
mkdtempSync,
|
|
6494
6570
|
openSync as openSync2,
|
|
6495
|
-
readFileSync as
|
|
6571
|
+
readFileSync as readFileSync20,
|
|
6496
6572
|
readSync,
|
|
6497
6573
|
readdirSync as readdirSync5,
|
|
6498
6574
|
rmSync as rmSync4,
|
|
@@ -6509,7 +6585,7 @@ function featurePackageRoot(moduleUrl = import.meta.url) {
|
|
|
6509
6585
|
const packagePath = join18(dir, "package.json");
|
|
6510
6586
|
if (existsSync19(packagePath)) {
|
|
6511
6587
|
try {
|
|
6512
|
-
const pkg2 = JSON.parse(
|
|
6588
|
+
const pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
|
|
6513
6589
|
if (pkg2.name === "deepspace") return dir;
|
|
6514
6590
|
} catch {
|
|
6515
6591
|
}
|
|
@@ -6526,7 +6602,7 @@ function readFeatureConfig(id, packageRoot = featurePackageRoot()) {
|
|
|
6526
6602
|
const configPath = join18(packageRoot, "features", id, "feature.json");
|
|
6527
6603
|
if (!existsSync19(configPath)) return null;
|
|
6528
6604
|
try {
|
|
6529
|
-
const config = JSON.parse(
|
|
6605
|
+
const config = JSON.parse(readFileSync20(configPath, "utf-8"));
|
|
6530
6606
|
if (typeof config.id !== "string" || typeof config.name !== "string" || !Array.isArray(config.files)) {
|
|
6531
6607
|
return null;
|
|
6532
6608
|
}
|
|
@@ -6591,7 +6667,7 @@ function copyFile(src, dest) {
|
|
|
6591
6667
|
function copyFileWithImportShift(src, dest, levels) {
|
|
6592
6668
|
mkdirSync6(dirname6(dest), { recursive: true });
|
|
6593
6669
|
const prefix = "../".repeat(levels);
|
|
6594
|
-
const shifted =
|
|
6670
|
+
const shifted = readFileSync20(src, "utf-8").replace(
|
|
6595
6671
|
/(from\s+|import\s+|import\()(['"])(\.\.\/)/g,
|
|
6596
6672
|
`$1$2${prefix}$3`
|
|
6597
6673
|
);
|
|
@@ -6650,7 +6726,7 @@ function integrateSchema(config, targetDir, emit) {
|
|
|
6650
6726
|
if (!existsSync19(schemasPath)) {
|
|
6651
6727
|
return [unresolvedSchema(config.schema, "src/schemas.ts was not found.", emit)];
|
|
6652
6728
|
}
|
|
6653
|
-
let content =
|
|
6729
|
+
let content = readFileSync20(schemasPath, "utf-8");
|
|
6654
6730
|
const { exportName, importPath, spreadOperator } = config.schema;
|
|
6655
6731
|
const importPattern = new RegExp(`^import\\s+\\{[^}]*\\b${exportName}\\b`, "m");
|
|
6656
6732
|
if (importPattern.test(content)) {
|
|
@@ -6707,7 +6783,7 @@ function integrateActions(config, targetDir, emit) {
|
|
|
6707
6783
|
if (!existsSync19(actionsPath)) {
|
|
6708
6784
|
return [unresolvedActions(config.actions, "src/actions/index.ts was not found.", emit)];
|
|
6709
6785
|
}
|
|
6710
|
-
let content =
|
|
6786
|
+
let content = readFileSync20(actionsPath, "utf-8");
|
|
6711
6787
|
const registryPattern = /export const actions:\s*Record<string,\s*ActionHandler(?:<[^>]*>)?>\s*=\s*\{/;
|
|
6712
6788
|
if (!registryPattern.test(content)) {
|
|
6713
6789
|
const reason = "src/actions/index.ts has an unexpected structure.";
|
|
@@ -6762,7 +6838,7 @@ function integrateCode(config, targetDir, emit) {
|
|
|
6762
6838
|
});
|
|
6763
6839
|
continue;
|
|
6764
6840
|
}
|
|
6765
|
-
const original =
|
|
6841
|
+
const original = readFileSync20(targetPath, "utf-8");
|
|
6766
6842
|
if (original.includes(insertion.insert.trim())) {
|
|
6767
6843
|
emit(` Integration already present: ${insertion.file}`);
|
|
6768
6844
|
continue;
|
|
@@ -6798,7 +6874,7 @@ ${content.slice(importIndex < 0 ? 0 : importIndex)}`;
|
|
|
6798
6874
|
function integrateIgnore(config, targetDir) {
|
|
6799
6875
|
if (!config.ignore?.length) return;
|
|
6800
6876
|
const targetPath = join18(targetDir, ".gitignore");
|
|
6801
|
-
const current = existsSync19(targetPath) ?
|
|
6877
|
+
const current = existsSync19(targetPath) ? readFileSync20(targetPath, "utf-8") : "";
|
|
6802
6878
|
const present = new Set(current.split(/\r?\n/).map((line) => line.trim()));
|
|
6803
6879
|
const missing = config.ignore.filter((pattern) => !present.has(pattern));
|
|
6804
6880
|
if (missing.length === 0) return;
|
|
@@ -6818,7 +6894,7 @@ function integrateWrangler(config, targetDir, emit) {
|
|
|
6818
6894
|
if (!existsSync19(targetPath)) {
|
|
6819
6895
|
return [{ area: "wrangler", reason: "wrangler.toml was not found.", steps }];
|
|
6820
6896
|
}
|
|
6821
|
-
let source =
|
|
6897
|
+
let source = readFileSync20(targetPath, "utf-8");
|
|
6822
6898
|
if (runWorkerFirst && !/^\[assets\]\s*$/m.test(source)) {
|
|
6823
6899
|
return [{ area: "wrangler", reason: "wrangler.toml has no [assets] section.", steps }];
|
|
6824
6900
|
}
|
|
@@ -6907,7 +6983,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
6907
6983
|
}
|
|
6908
6984
|
];
|
|
6909
6985
|
}
|
|
6910
|
-
let styles =
|
|
6986
|
+
let styles = readFileSync20(stylesPath, "utf-8");
|
|
6911
6987
|
let integrated = 0;
|
|
6912
6988
|
const unresolved = [];
|
|
6913
6989
|
for (const cssFile of config.css) {
|
|
@@ -6921,7 +6997,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
6921
6997
|
});
|
|
6922
6998
|
continue;
|
|
6923
6999
|
}
|
|
6924
|
-
const css =
|
|
7000
|
+
const css = readFileSync20(srcPath, "utf-8");
|
|
6925
7001
|
const fingerprint = css.match(/\.([\w-]+)\s*\{|@keyframes\s+([\w-]+)/);
|
|
6926
7002
|
const marker = fingerprint?.[1] ?? fingerprint?.[2];
|
|
6927
7003
|
if (marker && styles.includes(marker)) {
|
|
@@ -6952,7 +7028,7 @@ function integrateRoute(config, targetDir, emit) {
|
|
|
6952
7028
|
if (!existsSync19(navPath)) {
|
|
6953
7029
|
return [unresolvedRoute(config.route, config, "src/nav.ts was not found.", emit)];
|
|
6954
7030
|
}
|
|
6955
|
-
let content =
|
|
7031
|
+
let content = readFileSync20(navPath, "utf-8");
|
|
6956
7032
|
const routePath = config.route.path;
|
|
6957
7033
|
if (content.includes(`'${routePath}'`)) {
|
|
6958
7034
|
emit(` Nav already present: ${routePath}`);
|
|
@@ -7033,7 +7109,7 @@ function integrateDependencies(config, targetDir, runInstall, outputVisible, emi
|
|
|
7033
7109
|
}
|
|
7034
7110
|
let pkg2;
|
|
7035
7111
|
try {
|
|
7036
|
-
pkg2 = JSON.parse(
|
|
7112
|
+
pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
|
|
7037
7113
|
} catch (error) {
|
|
7038
7114
|
emit(
|
|
7039
7115
|
` Could not patch package.json (parse error: ${error instanceof Error ? error.message : String(error)})`
|
|
@@ -7093,7 +7169,7 @@ ${child.diagnosticTail}` : "";
|
|
|
7093
7169
|
}
|
|
7094
7170
|
function dependencySnapshot(targetDir) {
|
|
7095
7171
|
try {
|
|
7096
|
-
const pkg2 = JSON.parse(
|
|
7172
|
+
const pkg2 = JSON.parse(readFileSync20(join18(targetDir, "package.json"), "utf-8"));
|
|
7097
7173
|
return {
|
|
7098
7174
|
dependencies: pkg2.dependencies ?? {},
|
|
7099
7175
|
devDependencies: pkg2.devDependencies ?? {}
|
|
@@ -7342,7 +7418,7 @@ function isDeepSpaceApp(dir) {
|
|
|
7342
7418
|
const packagePath = join19(dir, "package.json");
|
|
7343
7419
|
if (!existsSync20(packagePath)) return false;
|
|
7344
7420
|
try {
|
|
7345
|
-
const pkg2 = JSON.parse(
|
|
7421
|
+
const pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
|
|
7346
7422
|
return Boolean(pkg2.dependencies?.deepspace || pkg2.devDependencies?.deepspace);
|
|
7347
7423
|
} catch {
|
|
7348
7424
|
return false;
|
|
@@ -8125,7 +8201,7 @@ var transfer_default = defineCommand7({
|
|
|
8125
8201
|
import { defineCommand as defineCommand8 } from "citty";
|
|
8126
8202
|
|
|
8127
8203
|
// src/cli/commands/_invoke-impl.ts
|
|
8128
|
-
import { readFileSync as
|
|
8204
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
8129
8205
|
import * as p15 from "@clack/prompts";
|
|
8130
8206
|
var API_URL7 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
8131
8207
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -8166,7 +8242,7 @@ function resolveBody(opts) {
|
|
|
8166
8242
|
if (opts.body != null) {
|
|
8167
8243
|
raw = opts.body;
|
|
8168
8244
|
} else if (opts.bodyFile != null) {
|
|
8169
|
-
raw = opts.bodyFile === "-" ?
|
|
8245
|
+
raw = opts.bodyFile === "-" ? readFileSync22(0, "utf-8") : readFileSync22(opts.bodyFile, "utf-8");
|
|
8170
8246
|
} else {
|
|
8171
8247
|
return "{}";
|
|
8172
8248
|
}
|
|
@@ -8445,7 +8521,7 @@ var integrations_default = defineCommand8({
|
|
|
8445
8521
|
|
|
8446
8522
|
// src/cli/commands/feedback.ts
|
|
8447
8523
|
import * as p16 from "@clack/prompts";
|
|
8448
|
-
import { existsSync as existsSync21, readFileSync as
|
|
8524
|
+
import { existsSync as existsSync21, readFileSync as readFileSync23 } from "fs";
|
|
8449
8525
|
import { dirname as dirname8, join as join20 } from "path";
|
|
8450
8526
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8451
8527
|
import { release } from "os";
|
|
@@ -8474,7 +8550,7 @@ function readCliVersion() {
|
|
|
8474
8550
|
];
|
|
8475
8551
|
for (const path of candidates) {
|
|
8476
8552
|
if (!existsSync21(path)) continue;
|
|
8477
|
-
const pkg2 = JSON.parse(
|
|
8553
|
+
const pkg2 = JSON.parse(readFileSync23(path, "utf-8"));
|
|
8478
8554
|
if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
|
|
8479
8555
|
}
|
|
8480
8556
|
} catch {
|
|
@@ -8670,7 +8746,7 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
|
|
|
8670
8746
|
|
|
8671
8747
|
// src/cli/commands/secrets.ts
|
|
8672
8748
|
import { defineCommand as defineCommand9 } from "citty";
|
|
8673
|
-
import { readFileSync as
|
|
8749
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
8674
8750
|
|
|
8675
8751
|
// src/cli/lib/citty-args.ts
|
|
8676
8752
|
function dedupePositionals(bound, rest) {
|
|
@@ -8940,7 +9016,7 @@ var upload = defineCommand9({
|
|
|
8940
9016
|
async run({ args }) {
|
|
8941
9017
|
try {
|
|
8942
9018
|
const t = await resolveTarget(args);
|
|
8943
|
-
const content = args.file === "-" ?
|
|
9019
|
+
const content = args.file === "-" ? readFileSync24(0, "utf-8") : readFileSync24(args.file, "utf-8");
|
|
8944
9020
|
const secrets = parseSecretsUpload(content);
|
|
8945
9021
|
if (Object.keys(secrets).length === 0)
|
|
8946
9022
|
fail(new InputError("No secrets found in the input.", "empty_input"));
|
|
@@ -9196,7 +9272,7 @@ var init_default = defineDeepspaceCommand({
|
|
|
9196
9272
|
// src/cli/commands/status.ts
|
|
9197
9273
|
import { defineCommand as defineCommand10 } from "citty";
|
|
9198
9274
|
import * as p17 from "@clack/prompts";
|
|
9199
|
-
import { existsSync as existsSync22, readFileSync as
|
|
9275
|
+
import { existsSync as existsSync22, readFileSync as readFileSync25 } from "fs";
|
|
9200
9276
|
function timeAgo(iso) {
|
|
9201
9277
|
const ms = Date.now() - Date.parse(iso);
|
|
9202
9278
|
if (!Number.isFinite(ms) || ms < 0) return iso;
|
|
@@ -9290,7 +9366,7 @@ var status_default = defineCommand10({
|
|
|
9290
9366
|
let who = "logged in";
|
|
9291
9367
|
try {
|
|
9292
9368
|
const payload = decodeJwtPayload(
|
|
9293
|
-
|
|
9369
|
+
readFileSync25(TOKEN_PATH, "utf-8").trim()
|
|
9294
9370
|
);
|
|
9295
9371
|
if (payload.email) who = payload.email;
|
|
9296
9372
|
userId = payload.sub ?? null;
|
|
@@ -10408,7 +10484,7 @@ function printOverlaps(overlaps, json) {
|
|
|
10408
10484
|
|
|
10409
10485
|
// src/cli/commands/workspace/local.ts
|
|
10410
10486
|
import * as p24 from "@clack/prompts";
|
|
10411
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
10487
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync26, realpathSync as realpathSync5, renameSync as renameSync2, statSync, writeFileSync as writeFileSync9 } from "fs";
|
|
10412
10488
|
import { dirname as dirname9, isAbsolute as isAbsolute5, join as join22, relative as relative2, sep as sep2 } from "path";
|
|
10413
10489
|
var WORKSPACE_MARKER = "deepspace-workspace.json";
|
|
10414
10490
|
function excludeWorktreeDir(appDir, dir) {
|
|
@@ -10466,7 +10542,7 @@ function isManagedWorkspaceWorktree(worktreeRoot, workspaceId) {
|
|
|
10466
10542
|
const markerPath = worktreeMarkerPath(worktreeRoot);
|
|
10467
10543
|
if (!markerPath) return false;
|
|
10468
10544
|
try {
|
|
10469
|
-
const marker = JSON.parse(
|
|
10545
|
+
const marker = JSON.parse(readFileSync26(markerPath, "utf-8"));
|
|
10470
10546
|
return marker.version === 1 && marker.workspaceId === workspaceId && marker.mode === "managed-linked";
|
|
10471
10547
|
} catch {
|
|
10472
10548
|
return false;
|
|
@@ -11328,13 +11404,13 @@ import * as p30 from "@clack/prompts";
|
|
|
11328
11404
|
|
|
11329
11405
|
// src/cli/lib/validation.ts
|
|
11330
11406
|
import { sync as spawnSync7 } from "cross-spawn";
|
|
11331
|
-
import { readFileSync as
|
|
11407
|
+
import { readFileSync as readFileSync27 } from "fs";
|
|
11332
11408
|
import { join as join23 } from "path";
|
|
11333
11409
|
var MAX_SUMMARY_CHARS = 4e3;
|
|
11334
11410
|
var MAX_OUTPUT_BUFFER = 64 * 1024 * 1024;
|
|
11335
11411
|
function configuredCommand(appDir) {
|
|
11336
11412
|
try {
|
|
11337
|
-
const pkg2 = JSON.parse(
|
|
11413
|
+
const pkg2 = JSON.parse(readFileSync27(join23(appDir, "package.json"), "utf-8"));
|
|
11338
11414
|
if (pkg2.scripts?.validate) return `${detectPackageManager(appDir)} run --silent validate`;
|
|
11339
11415
|
} catch {
|
|
11340
11416
|
}
|
|
@@ -12828,7 +12904,7 @@ function reportMigration(migration, json) {
|
|
|
12828
12904
|
|
|
12829
12905
|
// src/cli/cli.ts
|
|
12830
12906
|
var __dirname = dirname10(fileURLToPath3(import.meta.url));
|
|
12831
|
-
var pkg = JSON.parse(
|
|
12907
|
+
var pkg = JSON.parse(readFileSync28(join24(__dirname, "..", "package.json"), "utf-8"));
|
|
12832
12908
|
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync25("/etc/ssl/certs/ca-certificates.crt")) {
|
|
12833
12909
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
12834
12910
|
}
|