deepspace 0.22.0 → 0.23.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 +20 -0
- package/dist/build.d.ts +115 -0
- package/dist/build.js +66 -0
- package/dist/build.js.map +1 -0
- package/dist/{chunk-7TDBFEB7.js → chunk-A7VKZRCB.js} +2 -2
- package/dist/{chunk-7TDBFEB7.js.map → chunk-A7VKZRCB.js.map} +1 -1
- package/dist/cli.js +272 -52
- package/dist/cli.js.map +1 -1
- package/dist/documentation-client-core.js +1 -1
- package/dist/documentation-default-renderer.cjs +1 -1
- package/dist/documentation-react.js +1 -1
- package/dist/documentation-runtime.js +1 -1
- package/dist/documentation-server-core.js +1 -1
- package/dist/documentation.js +1 -1
- package/dist/documentation.js.map +1 -1
- package/dist/index.d.ts +22 -6
- package/dist/index.js +23 -29
- package/dist/index.js.map +1 -1
- package/dist/schema.js +6 -0
- package/dist/schema.js.map +1 -1
- package/dist/server.d.ts +51 -12
- package/dist/server.js +193 -150
- package/dist/server.js.map +1 -1
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +21 -9
- package/dist/testing.js.map +1 -1
- package/dist/worker.d.ts +54 -12
- package/dist/worker.js +119 -75
- package/dist/worker.js.map +1 -1
- package/package.json +5 -1
package/dist/cli.js
CHANGED
|
@@ -993,18 +993,6 @@ ${line}
|
|
|
993
993
|
}
|
|
994
994
|
writeFileSync2(wranglerPath, src);
|
|
995
995
|
}
|
|
996
|
-
var APP_ID_PLACEHOLDER = "__APP_ID__";
|
|
997
|
-
function stampAppIdInSources(cwd, appId, previousAppId) {
|
|
998
|
-
const constantsPath = join2(resolve2(cwd), "src", "constants.ts");
|
|
999
|
-
if (!existsSync3(constantsPath)) return false;
|
|
1000
|
-
const needles = [APP_ID_PLACEHOLDER, ...previousAppId ? [previousAppId] : []];
|
|
1001
|
-
const content = readFileSync5(constantsPath, "utf-8");
|
|
1002
|
-
let next = content;
|
|
1003
|
-
for (const needle of needles) next = next.replaceAll(needle, appId);
|
|
1004
|
-
if (next === content) return false;
|
|
1005
|
-
writeFileSync2(constantsPath, next);
|
|
1006
|
-
return true;
|
|
1007
|
-
}
|
|
1008
996
|
|
|
1009
997
|
// src/cli/commands/dev.ts
|
|
1010
998
|
import { resolve as resolve8, basename as basename2, join as join11 } from "path";
|
|
@@ -1589,6 +1577,7 @@ function resolveAppNameForEnv(config, envName) {
|
|
|
1589
1577
|
if (!envBlock) {
|
|
1590
1578
|
return {
|
|
1591
1579
|
ok: false,
|
|
1580
|
+
code: "missing_env_block",
|
|
1592
1581
|
reason: `wrangler.toml: no [env.${envName}] block found. Add one with a distinct \`name\` to deploy this environment.`
|
|
1593
1582
|
};
|
|
1594
1583
|
}
|
|
@@ -2193,6 +2182,7 @@ async function secretsApi(deployUrl, token, path, init = {}) {
|
|
|
2193
2182
|
if (!res.ok) {
|
|
2194
2183
|
const err = new Error(body.error ?? `Secrets request failed (${res.status})`);
|
|
2195
2184
|
err.status = res.status;
|
|
2185
|
+
err.code = body.code;
|
|
2196
2186
|
err.apiPath = path;
|
|
2197
2187
|
throw err;
|
|
2198
2188
|
}
|
|
@@ -2399,6 +2389,12 @@ import { join as join10 } from "path";
|
|
|
2399
2389
|
import { pathToFileURL } from "url";
|
|
2400
2390
|
|
|
2401
2391
|
// src/server/schemas/registry.ts
|
|
2392
|
+
var SYSTEM_ASSIGNED_COLUMNS = /* @__PURE__ */ new Set(["email", "name", "imageUrl", "role"]);
|
|
2393
|
+
var SYSTEM_MAINTAINED_COLUMNS = /* @__PURE__ */ new Set(["createdAt", "lastSeenAt"]);
|
|
2394
|
+
var SYSTEM_MANAGED_COLUMNS = /* @__PURE__ */ new Set([
|
|
2395
|
+
...SYSTEM_ASSIGNED_COLUMNS,
|
|
2396
|
+
...SYSTEM_MAINTAINED_COLUMNS
|
|
2397
|
+
]);
|
|
2402
2398
|
var USERS_COLUMNS = [
|
|
2403
2399
|
{ name: "email", storage: "text", interpretation: "plain" },
|
|
2404
2400
|
{ name: "name", storage: "text", interpretation: "plain" },
|
|
@@ -3063,7 +3059,7 @@ function ensurePlaywright(appDir) {
|
|
|
3063
3059
|
import { readFileSync as readFileSync14 } from "fs";
|
|
3064
3060
|
|
|
3065
3061
|
// src/testing/accounts.ts
|
|
3066
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync13
|
|
3062
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync13 } from "fs";
|
|
3067
3063
|
import { homedir as homedir2 } from "os";
|
|
3068
3064
|
import { join as join12 } from "path";
|
|
3069
3065
|
var TEST_ACCOUNTS_PATH = join12(homedir2(), ".deepspace", "test-accounts.json");
|
|
@@ -3102,7 +3098,9 @@ function reconcileTestAccountScopes(store, remote, scope) {
|
|
|
3102
3098
|
};
|
|
3103
3099
|
}
|
|
3104
3100
|
function reconcileTestAccounts(local, remote) {
|
|
3105
|
-
const localById = new Map(
|
|
3101
|
+
const localById = new Map(
|
|
3102
|
+
local.filter((account) => account.id).map((account) => [account.id, account])
|
|
3103
|
+
);
|
|
3106
3104
|
return remote.flatMap((account) => {
|
|
3107
3105
|
const stored = localById.get(account.id);
|
|
3108
3106
|
return stored ? [{ ...stored, ...account }] : [];
|
|
@@ -3137,7 +3135,9 @@ function readTestAccountStore() {
|
|
|
3137
3135
|
return { version: 2, scopes: {} };
|
|
3138
3136
|
}
|
|
3139
3137
|
const candidate = raw;
|
|
3140
|
-
const scopes = candidate.scopes && typeof candidate.scopes === "object" && !Array.isArray(candidate.scopes) ? Object.fromEntries(
|
|
3138
|
+
const scopes = candidate.scopes && typeof candidate.scopes === "object" && !Array.isArray(candidate.scopes) ? Object.fromEntries(
|
|
3139
|
+
Object.entries(candidate.scopes).map(([key, value]) => [key, validTestAccounts(value)])
|
|
3140
|
+
) : {};
|
|
3141
3141
|
return { version: 2, scopes };
|
|
3142
3142
|
} catch {
|
|
3143
3143
|
return { version: 2, scopes: {} };
|
|
@@ -3153,7 +3153,7 @@ function validTestAccounts(value) {
|
|
|
3153
3153
|
}
|
|
3154
3154
|
function saveTestAccountStore(store) {
|
|
3155
3155
|
mkdirSync5(join12(homedir2(), ".deepspace"), { recursive: true });
|
|
3156
|
-
|
|
3156
|
+
writeSecretFileSync(TEST_ACCOUNTS_PATH, JSON.stringify(store, null, 2));
|
|
3157
3157
|
}
|
|
3158
3158
|
|
|
3159
3159
|
// src/cli/lib/test-account-service.ts
|
|
@@ -3189,6 +3189,29 @@ async function createRemoteTestAccount(input) {
|
|
|
3189
3189
|
}
|
|
3190
3190
|
return { ...data, label: data.label ?? null };
|
|
3191
3191
|
}
|
|
3192
|
+
async function recoverRemoteTestAccount(id) {
|
|
3193
|
+
const response = await fetch(`${AUTH_URL4}/api/auth/test-accounts/${id}/credential`, {
|
|
3194
|
+
method: "POST",
|
|
3195
|
+
headers: { Cookie: sessionCookie(), Origin: AUTH_URL4 }
|
|
3196
|
+
});
|
|
3197
|
+
const data = await response.json().catch(() => ({}));
|
|
3198
|
+
if (response.status === 404) {
|
|
3199
|
+
throw new Error(
|
|
3200
|
+
`No test account ${id} on this account. Run \`deepspace test accounts list\` for the current pool.`
|
|
3201
|
+
);
|
|
3202
|
+
}
|
|
3203
|
+
if (!response.ok || typeof data.password !== "string" || typeof data.email !== "string" || typeof data.userId !== "string") {
|
|
3204
|
+
throw new Error(data.error ?? "Failed to re-issue the test account credential");
|
|
3205
|
+
}
|
|
3206
|
+
return {
|
|
3207
|
+
id,
|
|
3208
|
+
email: data.email,
|
|
3209
|
+
userId: data.userId,
|
|
3210
|
+
label: data.label ?? null,
|
|
3211
|
+
createdAt: data.createdAt ?? Date.now(),
|
|
3212
|
+
password: data.password
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3192
3215
|
async function deleteRemoteTestAccount(id) {
|
|
3193
3216
|
const response = await fetch(`${AUTH_URL4}/api/auth/test-accounts/${id}`, {
|
|
3194
3217
|
method: "DELETE",
|
|
@@ -3341,10 +3364,10 @@ var test_default = defineDeepspaceCommand({
|
|
|
3341
3364
|
if (forwarded.grep || forwarded.project || forwarded.headed) {
|
|
3342
3365
|
console.error("note: --grep/--project/--headed apply to Playwright suites and are ignored by `unit`");
|
|
3343
3366
|
}
|
|
3344
|
-
exitCode = runVitest(appDir);
|
|
3367
|
+
exitCode = runVitest(appDir, wranglerEnv);
|
|
3345
3368
|
break;
|
|
3346
3369
|
case "all":
|
|
3347
|
-
exitCode = runVitest(appDir);
|
|
3370
|
+
exitCode = runVitest(appDir, wranglerEnv);
|
|
3348
3371
|
if (exitCode === 0) exitCode = runPlaywright(appDir, [], port, wranglerEnv, forwarded);
|
|
3349
3372
|
break;
|
|
3350
3373
|
case "default":
|
|
@@ -3375,7 +3398,7 @@ Available: smoke, api, e2e, unit, all`,
|
|
|
3375
3398
|
return { data: { suite, port, appDir, wranglerEnv: wranglerEnv ?? null } };
|
|
3376
3399
|
}
|
|
3377
3400
|
});
|
|
3378
|
-
function
|
|
3401
|
+
function runSuite(appDir, argv, wranglerEnv, extraEnv = {}) {
|
|
3379
3402
|
let wranglerConfig;
|
|
3380
3403
|
try {
|
|
3381
3404
|
wranglerConfig = prepareWranglerEnvConfig(appDir, wranglerEnv);
|
|
@@ -3384,25 +3407,24 @@ function runPlaywright(appDir, testFiles, port, wranglerEnv, flags) {
|
|
|
3384
3407
|
return 1;
|
|
3385
3408
|
}
|
|
3386
3409
|
try {
|
|
3387
|
-
const result = spawnSync4("npx",
|
|
3410
|
+
const result = spawnSync4("npx", argv, {
|
|
3388
3411
|
cwd: appDir,
|
|
3389
3412
|
stdio: "inherit",
|
|
3390
|
-
env: wranglerViteEnv(process.env, wranglerConfig,
|
|
3391
|
-
DEEPSPACE_PORT: String(port),
|
|
3392
|
-
PLAYWRIGHT_HTML_OUTPUT_DIR: ".deepspace/playwright-report"
|
|
3393
|
-
})
|
|
3413
|
+
env: wranglerViteEnv(process.env, wranglerConfig, extraEnv)
|
|
3394
3414
|
});
|
|
3395
3415
|
return result.status ?? 1;
|
|
3396
3416
|
} finally {
|
|
3397
3417
|
wranglerConfig.cleanup();
|
|
3398
3418
|
}
|
|
3399
3419
|
}
|
|
3400
|
-
function
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3420
|
+
function runPlaywright(appDir, testFiles, port, wranglerEnv, flags = {}) {
|
|
3421
|
+
return runSuite(appDir, playwrightTestArgs(testFiles, flags), wranglerEnv, {
|
|
3422
|
+
DEEPSPACE_PORT: String(port),
|
|
3423
|
+
PLAYWRIGHT_HTML_OUTPUT_DIR: ".deepspace/playwright-report"
|
|
3404
3424
|
});
|
|
3405
|
-
|
|
3425
|
+
}
|
|
3426
|
+
function runVitest(appDir, wranglerEnv) {
|
|
3427
|
+
return runSuite(appDir, ["vitest", "run", "--passWithNoTests"], wranglerEnv);
|
|
3406
3428
|
}
|
|
3407
3429
|
|
|
3408
3430
|
// src/cli/commands/screenshot.ts
|
|
@@ -3740,6 +3762,107 @@ Failed:
|
|
|
3740
3762
|
return { data: { deleted: ok2, requested: targets.length, failures: [] } };
|
|
3741
3763
|
}
|
|
3742
3764
|
});
|
|
3765
|
+
var recover = defineDeepspaceCommand({
|
|
3766
|
+
meta: {
|
|
3767
|
+
name: "recover",
|
|
3768
|
+
description: "Re-issue the local credential for a test account you own"
|
|
3769
|
+
},
|
|
3770
|
+
args: {
|
|
3771
|
+
email: {
|
|
3772
|
+
type: "string",
|
|
3773
|
+
description: "Email of the test account to recover",
|
|
3774
|
+
required: false
|
|
3775
|
+
},
|
|
3776
|
+
id: {
|
|
3777
|
+
type: "string",
|
|
3778
|
+
description: "ID of the test account to recover",
|
|
3779
|
+
required: false
|
|
3780
|
+
},
|
|
3781
|
+
all: {
|
|
3782
|
+
type: "boolean",
|
|
3783
|
+
description: "Recover every pool account missing a local credential",
|
|
3784
|
+
required: false
|
|
3785
|
+
}
|
|
3786
|
+
},
|
|
3787
|
+
async run({ args }) {
|
|
3788
|
+
const selectors = [args.email, args.id, args.all].filter(Boolean).length;
|
|
3789
|
+
if (selectors === 0) {
|
|
3790
|
+
throw new Refusal("Provide --email <email>, --id <id>, or --all.", "missing_argument");
|
|
3791
|
+
}
|
|
3792
|
+
if (selectors > 1) {
|
|
3793
|
+
throw new Refusal("Provide exactly one of --email, --id, or --all.", "conflicting_arguments");
|
|
3794
|
+
}
|
|
3795
|
+
await ensureToken();
|
|
3796
|
+
let remote;
|
|
3797
|
+
try {
|
|
3798
|
+
remote = await fetchRemoteTestAccounts();
|
|
3799
|
+
} catch (err) {
|
|
3800
|
+
throw new Refusal(`Failed: ${err.message}`, "test_accounts_list_failed");
|
|
3801
|
+
}
|
|
3802
|
+
const localAccounts = loadAllTestAccounts();
|
|
3803
|
+
const known = new Set(localAccounts.map((account) => account.id));
|
|
3804
|
+
const localNames = new Map(
|
|
3805
|
+
localAccounts.flatMap(
|
|
3806
|
+
(account) => account.name ? [[account.email, account.name]] : []
|
|
3807
|
+
)
|
|
3808
|
+
);
|
|
3809
|
+
let targets;
|
|
3810
|
+
if (args.all) {
|
|
3811
|
+
targets = remote.filter((account) => !known.has(account.id));
|
|
3812
|
+
if (targets.length === 0) {
|
|
3813
|
+
if (!args.json) console.log("Every pool account already has a local credential.");
|
|
3814
|
+
return { data: { recovered: [], alreadyLocal: remote.length } };
|
|
3815
|
+
}
|
|
3816
|
+
} else {
|
|
3817
|
+
const match = args.id ? remote.find((account) => account.id === args.id) : remote.find((account) => account.email === args.email);
|
|
3818
|
+
if (!match) {
|
|
3819
|
+
throw new Refusal(
|
|
3820
|
+
`No test account ${args.id ? `with id ${args.id}` : `with email ${args.email}`} on this account.`,
|
|
3821
|
+
"test_account_not_found",
|
|
3822
|
+
{ action: cliAction("deepspace", "test", "accounts", "list") }
|
|
3823
|
+
);
|
|
3824
|
+
}
|
|
3825
|
+
targets = [match];
|
|
3826
|
+
}
|
|
3827
|
+
const recovered = [];
|
|
3828
|
+
const failures = [];
|
|
3829
|
+
for (const target2 of targets) {
|
|
3830
|
+
try {
|
|
3831
|
+
const account = await recoverRemoteTestAccount(target2.id);
|
|
3832
|
+
const name = localNames.get(account.email);
|
|
3833
|
+
upsertTestAccount({
|
|
3834
|
+
id: account.id,
|
|
3835
|
+
email: account.email,
|
|
3836
|
+
password: account.password,
|
|
3837
|
+
userId: account.userId,
|
|
3838
|
+
label: account.label,
|
|
3839
|
+
...name ? { name } : {},
|
|
3840
|
+
createdAt: account.createdAt
|
|
3841
|
+
});
|
|
3842
|
+
recovered.push({ id: account.id, email: account.email });
|
|
3843
|
+
} catch (err) {
|
|
3844
|
+
failures.push({ email: target2.email, error: err.message });
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
if (failures.length > 0) {
|
|
3848
|
+
throw new Refusal(
|
|
3849
|
+
`Recovered ${recovered.length}/${targets.length} test account(s).
|
|
3850
|
+
Failed:
|
|
3851
|
+
` + failures.map((failure) => ` ${failure.email}: ${failure.error}`).join("\n"),
|
|
3852
|
+
"test_account_recover_failed",
|
|
3853
|
+
{ extra: { recovered, requested: targets.length, failures } }
|
|
3854
|
+
);
|
|
3855
|
+
}
|
|
3856
|
+
if (!args.json) {
|
|
3857
|
+
for (const account of recovered) console.log(`Recovered ${account.email}`);
|
|
3858
|
+
console.log(
|
|
3859
|
+
`
|
|
3860
|
+
Stored in ${TEST_ACCOUNTS_PATH}. The previous password (if any machine still holds one) no longer works \u2014 recover there too.`
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3863
|
+
return { data: { recovered, requested: targets.length, failures: [] } };
|
|
3864
|
+
}
|
|
3865
|
+
});
|
|
3743
3866
|
var test_accounts_default = defineCommand2({
|
|
3744
3867
|
meta: {
|
|
3745
3868
|
name: "test-accounts",
|
|
@@ -3749,7 +3872,8 @@ var test_accounts_default = defineCommand2({
|
|
|
3749
3872
|
create,
|
|
3750
3873
|
list,
|
|
3751
3874
|
delete: del,
|
|
3752
|
-
clear
|
|
3875
|
+
clear,
|
|
3876
|
+
recover
|
|
3753
3877
|
}
|
|
3754
3878
|
});
|
|
3755
3879
|
|
|
@@ -4469,7 +4593,7 @@ function declaredCompatibilityDate(config) {
|
|
|
4469
4593
|
return typeof declared === "string" && /^\d{4}-\d{2}-\d{2}$/.test(declared) ? declared : null;
|
|
4470
4594
|
}
|
|
4471
4595
|
async function buildDeployBundle(options) {
|
|
4472
|
-
const { appDir, appName, envName, output, spinner: spinner2 } = options;
|
|
4596
|
+
const { appDir, appName, appId, envName, output, spinner: spinner2 } = options;
|
|
4473
4597
|
const junk = removeMacosJunk(appDir);
|
|
4474
4598
|
if (junk > 0) p6.log.info(`Removed ${junk} macOS metadata file(s) (._*, .DS_Store)`);
|
|
4475
4599
|
const lintFindings = await lintProjectSchemas(appDir);
|
|
@@ -4544,6 +4668,8 @@ async function buildDeployBundle(options) {
|
|
|
4544
4668
|
const assets = collectAssets(clientDir);
|
|
4545
4669
|
const assetConfig = readDeployAssetConfig(clientDir);
|
|
4546
4670
|
spinner2.stop(`Collected ${assets.length} assets`);
|
|
4671
|
+
const appIdRefusal = clientAppIdRefusal(assets, appId, envName);
|
|
4672
|
+
if (appIdRefusal) output.die(appIdRefusal.message, appIdRefusal.code);
|
|
4547
4673
|
const workerJs = readFileSync17(workerBundlePath, "utf-8");
|
|
4548
4674
|
const doBindings = outputConfig.durable_objects?.bindings;
|
|
4549
4675
|
const sqliteClasses = new Set(
|
|
@@ -4612,6 +4738,44 @@ function oversizedAssetRefusal(assets) {
|
|
|
4612
4738
|
if (!tooBig) return null;
|
|
4613
4739
|
return `${tooBig.path} is ${formatBytes(tooBig.size)}; the per-file limit for deploy assets is ${formatBytes(MAX_DEPLOY_ASSET_FILE_BYTES)}. ${LARGE_MEDIA_HOME}`;
|
|
4614
4740
|
}
|
|
4741
|
+
var CLIENT_CODE_ASSET = /\.(?:js|mjs|html)$/i;
|
|
4742
|
+
var APP_ID_LITERAL = /app_[0-9A-HJKMNP-TV-Z]{26}/g;
|
|
4743
|
+
var APP_ID_DEFINE = "__DEEPSPACE_APP_ID__";
|
|
4744
|
+
var APP_ID_ADOPTION_STEPS = `Point the client at the build-injected id \u2014 the SDK's \`deepspace/build\` supplies it:
|
|
4745
|
+
\u2022 vite.config.ts: import { deepspaceBuild } from 'deepspace/build' and add
|
|
4746
|
+
deepspaceBuild({ appDir: fileURLToPath(new URL('.', import.meta.url)) }) to plugins
|
|
4747
|
+
\u2022 vitest.config.ts: import { appIdDefine } and set define: appIdDefine({ appDir })
|
|
4748
|
+
\u2022 src/constants.ts: declare const __DEEPSPACE_APP_ID__: string; export it as APP_ID
|
|
4749
|
+
(drop the frozen literal)
|
|
4750
|
+
Apply all three together: src/constants.ts on its own builds clean and then throws in the browser. A newly scaffolded app already has this.`;
|
|
4751
|
+
function clientAppIdRefusal(assets, appId, envName) {
|
|
4752
|
+
const foreign = /* @__PURE__ */ new Map();
|
|
4753
|
+
let unsubstituted;
|
|
4754
|
+
for (const asset of assets) {
|
|
4755
|
+
if (!CLIENT_CODE_ASSET.test(asset.path)) continue;
|
|
4756
|
+
const source = readFileSync17(asset.sourcePath, "utf-8");
|
|
4757
|
+
if (unsubstituted === void 0 && source.includes(APP_ID_DEFINE)) unsubstituted = asset.path;
|
|
4758
|
+
for (const found of source.matchAll(APP_ID_LITERAL)) {
|
|
4759
|
+
if (found[0] !== appId && !foreign.has(found[0])) foreign.set(found[0], asset.path);
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
if (unsubstituted !== void 0) {
|
|
4763
|
+
return {
|
|
4764
|
+
code: "app_id_define_unsubstituted",
|
|
4765
|
+
message: `Built client assets still contain \`${APP_ID_DEFINE}\` (first in ${unsubstituted}) \u2014 nothing replaced it at build time. The browser evaluates that identifier and throws ReferenceError before the app renders, so this bundle is a blank page for every visitor. src/constants.ts was moved onto the build-time app id without the build config that supplies it.
|
|
4766
|
+
${APP_ID_ADOPTION_STEPS}`
|
|
4767
|
+
};
|
|
4768
|
+
}
|
|
4769
|
+
if (foreign.size === 0) return null;
|
|
4770
|
+
const target2 = envName ? `--env ${envName} (${appId})` : appId;
|
|
4771
|
+
return {
|
|
4772
|
+
code: "app_id_env_mismatch",
|
|
4773
|
+
message: `Built client assets carry a different app id than the one being deployed. Deploying ${target2}, but the bundle contains:
|
|
4774
|
+
` + [...foreign].map(([id, path]) => ` \u2022 ${id} in ${path}`).join("\n") + `
|
|
4775
|
+
The browser keys its RecordRooms to the id in the bundle, so this would serve ${envName ? `${envName}'s` : "this app's"} worker against another app's data. The usual cause is an app scaffolded before the id was build-injected: src/constants.ts still holds \`export const APP_ID = 'app_\u2026'\` frozen at scaffold time.
|
|
4776
|
+
${APP_ID_ADOPTION_STEPS}`
|
|
4777
|
+
};
|
|
4778
|
+
}
|
|
4615
4779
|
var LARGE_MEDIA_HOME = "Large media belongs in your app files (`deepspace app files put`), not in the deploy bundle \u2014 move it out of `public/` and reference it at runtime.";
|
|
4616
4780
|
function collectAssets(dir) {
|
|
4617
4781
|
const assets = [];
|
|
@@ -6251,7 +6415,7 @@ var deploy_default = defineCommand3({
|
|
|
6251
6415
|
output.showIntro();
|
|
6252
6416
|
const wranglerConfig = readWranglerConfig(appDir);
|
|
6253
6417
|
const nameResult = resolveAppNameForEnv(wranglerConfig, envName);
|
|
6254
|
-
if (!nameResult.ok) return output.die(nameResult.reason, "invalid_app_name");
|
|
6418
|
+
if (!nameResult.ok) return output.die(nameResult.reason, nameResult.code ?? "invalid_app_name");
|
|
6255
6419
|
const declaredName = envName ? wranglerConfig.env?.[envName]?.name : wranglerConfig.name;
|
|
6256
6420
|
if (declaredName !== nameResult.name) {
|
|
6257
6421
|
const location = envName ? `[env.${envName}].name` : "`name`";
|
|
@@ -6267,7 +6431,14 @@ var deploy_default = defineCommand3({
|
|
|
6267
6431
|
if (!appId) {
|
|
6268
6432
|
return output.die(
|
|
6269
6433
|
`No app id in wrangler.toml${envName ? ` for [env.${envName}]` : ""}. Run \`deepspace app init${envName ? ` --env ${envName}` : ""}\` to register this app, then re-deploy.`,
|
|
6270
|
-
"app_not_initialized"
|
|
6434
|
+
"app_not_initialized",
|
|
6435
|
+
{
|
|
6436
|
+
action: {
|
|
6437
|
+
cwd: appDir,
|
|
6438
|
+
argv: ["deepspace", "app", "init", ...envName ? ["--env", envName] : []]
|
|
6439
|
+
},
|
|
6440
|
+
actionRequired: true
|
|
6441
|
+
}
|
|
6271
6442
|
);
|
|
6272
6443
|
}
|
|
6273
6444
|
p12.log.info(`Id: ${appId}`);
|
|
@@ -6281,6 +6452,12 @@ var deploy_default = defineCommand3({
|
|
|
6281
6452
|
output
|
|
6282
6453
|
});
|
|
6283
6454
|
const sourceState = await getAppSource(DEPLOY_URL3, token, appId);
|
|
6455
|
+
if (!sourceState.registered) {
|
|
6456
|
+
output.die(
|
|
6457
|
+
`${appId} is not registered. If this repo's id came from an older SDK's scaffold, run \`deepspace app init --new-id\` to register it as a fresh app; a brand-new app dir registers with \`deepspace app init\`.`,
|
|
6458
|
+
"app_not_registered"
|
|
6459
|
+
);
|
|
6460
|
+
}
|
|
6284
6461
|
const repositoryPreflight = preflightDeployRepository({
|
|
6285
6462
|
appDir,
|
|
6286
6463
|
push: args.push !== false,
|
|
@@ -6293,6 +6470,7 @@ var deploy_default = defineCommand3({
|
|
|
6293
6470
|
const bundle = await buildDeployBundle({
|
|
6294
6471
|
appDir,
|
|
6295
6472
|
appName,
|
|
6473
|
+
appId,
|
|
6296
6474
|
envName,
|
|
6297
6475
|
output,
|
|
6298
6476
|
spinner: spinner2
|
|
@@ -6556,7 +6734,7 @@ async function warnIfPhantomApp(deployUrl, token, appId, explicit) {
|
|
|
6556
6734
|
const apps = await listApps(deployUrl, token);
|
|
6557
6735
|
if (!apps.some((app2) => app2.appId === appId)) {
|
|
6558
6736
|
process.stderr.write(
|
|
6559
|
-
`warning: ${appId} is not among your apps. If it exists and you have access (collaborator/admin), the server will use it; if it doesn't exist,
|
|
6737
|
+
`warning: ${appId} is not among your apps. If it exists and you have access (collaborator/admin), the server will use it; if it doesn't exist, the command will be refused (app_not_registered \u2014 ids are registered at \`deepspace app init\`). Check the id (a subdomain name also works with -a).
|
|
6560
6738
|
`
|
|
6561
6739
|
);
|
|
6562
6740
|
}
|
|
@@ -7128,7 +7306,7 @@ import {
|
|
|
7128
7306
|
readSync,
|
|
7129
7307
|
readdirSync as readdirSync5,
|
|
7130
7308
|
rmSync as rmSync4,
|
|
7131
|
-
writeFileSync as
|
|
7309
|
+
writeFileSync as writeFileSync5
|
|
7132
7310
|
} from "fs";
|
|
7133
7311
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
7134
7312
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -7227,7 +7405,7 @@ function copyFileWithImportShift(src, dest, levels) {
|
|
|
7227
7405
|
/(from\s+|import\s+|import\()(['"])(\.\.\/)/g,
|
|
7228
7406
|
`$1$2${prefix}$3`
|
|
7229
7407
|
);
|
|
7230
|
-
|
|
7408
|
+
writeFileSync5(dest, shifted);
|
|
7231
7409
|
}
|
|
7232
7410
|
function installFiles(packageRoot, config, targetDir, emit) {
|
|
7233
7411
|
let copied = 0;
|
|
@@ -7313,7 +7491,7 @@ export const schemas`
|
|
|
7313
7491
|
return [unresolvedSchema(config.schema, reason, emit)];
|
|
7314
7492
|
}
|
|
7315
7493
|
content = withEntry;
|
|
7316
|
-
|
|
7494
|
+
writeFileSync5(schemasPath, content);
|
|
7317
7495
|
emit(` Schema integrated: ${exportName} -> schemas.ts`);
|
|
7318
7496
|
return [];
|
|
7319
7497
|
}
|
|
@@ -7379,7 +7557,7 @@ ${registryEntry}`);
|
|
|
7379
7557
|
integrated++;
|
|
7380
7558
|
emit(` Action integrated: ${action.registerAs} (${action.exportName})`);
|
|
7381
7559
|
}
|
|
7382
|
-
if (integrated > 0)
|
|
7560
|
+
if (integrated > 0) writeFileSync5(actionsPath, content);
|
|
7383
7561
|
return unresolved;
|
|
7384
7562
|
}
|
|
7385
7563
|
function integrateCode(config, targetDir, emit) {
|
|
@@ -7424,7 +7602,7 @@ ${content.slice(
|
|
|
7424
7602
|
const prefix = insertion.placement === "before" ? "" : "\n";
|
|
7425
7603
|
const suffix = insertion.placement === "before" ? "\n" : "";
|
|
7426
7604
|
content = `${content.slice(0, insertAt)}${prefix}${insertion.insert}${suffix}${content.slice(insertAt)}`;
|
|
7427
|
-
|
|
7605
|
+
writeFileSync5(targetPath, content);
|
|
7428
7606
|
emit(` Integrated: ${insertion.file}`);
|
|
7429
7607
|
}
|
|
7430
7608
|
return unresolved;
|
|
@@ -7437,7 +7615,7 @@ function integrateIgnore(config, targetDir) {
|
|
|
7437
7615
|
const missing = config.ignore.filter((pattern) => !present.has(pattern));
|
|
7438
7616
|
if (missing.length === 0) return;
|
|
7439
7617
|
const separator = current === "" || current.endsWith("\n") ? "" : "\n";
|
|
7440
|
-
|
|
7618
|
+
writeFileSync5(targetPath, `${current}${separator}${missing.join("\n")}
|
|
7441
7619
|
`);
|
|
7442
7620
|
}
|
|
7443
7621
|
function integrateWrangler(config, targetDir, emit) {
|
|
@@ -7474,7 +7652,7 @@ ${rateLimitBindingBlock(scope, binding)}
|
|
|
7474
7652
|
}
|
|
7475
7653
|
}
|
|
7476
7654
|
if (changed) {
|
|
7477
|
-
|
|
7655
|
+
writeFileSync5(targetPath, source);
|
|
7478
7656
|
emit(" Integrated: wrangler.toml");
|
|
7479
7657
|
} else emit(" Integration already present: wrangler.toml");
|
|
7480
7658
|
return [];
|
|
@@ -7567,7 +7745,7 @@ ${css}`;
|
|
|
7567
7745
|
integrated++;
|
|
7568
7746
|
emit(` CSS integrated: ${cssFile} -> styles.css`);
|
|
7569
7747
|
}
|
|
7570
|
-
if (integrated > 0)
|
|
7748
|
+
if (integrated > 0) writeFileSync5(stylesPath, styles);
|
|
7571
7749
|
return unresolved;
|
|
7572
7750
|
}
|
|
7573
7751
|
function unresolvedRoute(route, config, reason, emit) {
|
|
@@ -7614,7 +7792,7 @@ function integrateRoute(config, targetDir, emit) {
|
|
|
7614
7792
|
const entry = ` { path: '${routePath}', label: '${config.name}'${roles} },`;
|
|
7615
7793
|
content = content.replace(NAV_MARKER, `${NAV_MARKER}
|
|
7616
7794
|
${entry}`);
|
|
7617
|
-
|
|
7795
|
+
writeFileSync5(navPath, content);
|
|
7618
7796
|
emit(` Nav wired: ${routePath} (${config.name})`);
|
|
7619
7797
|
emit(" Route: automatic (file-based routing via src/pages/)");
|
|
7620
7798
|
return [];
|
|
@@ -7698,7 +7876,7 @@ function integrateDependencies(config, targetDir, runInstall, outputVisible, emi
|
|
|
7698
7876
|
if (added.length === 0) {
|
|
7699
7877
|
emit(" Dependencies already present");
|
|
7700
7878
|
} else {
|
|
7701
|
-
|
|
7879
|
+
writeFileSync5(packagePath, `${JSON.stringify(pkg2, null, 2)}
|
|
7702
7880
|
`, "utf-8");
|
|
7703
7881
|
emit(` Added to package.json: ${added.map(({ name }) => name).join(", ")}`);
|
|
7704
7882
|
if (skipped.length) emit(` Already present (kept your version): ${skipped.join(", ")}`);
|
|
@@ -10291,6 +10469,25 @@ var init_default = defineDeepspaceCommand({
|
|
|
10291
10469
|
const envName = args.env || void 0;
|
|
10292
10470
|
const existing = readAppId(appDir, envName);
|
|
10293
10471
|
if (existing && !args["new-id"]) {
|
|
10472
|
+
const token2 = await ensureToken();
|
|
10473
|
+
let state;
|
|
10474
|
+
try {
|
|
10475
|
+
state = await getAppSource(DEPLOY_URL12, token2, existing);
|
|
10476
|
+
} catch (error) {
|
|
10477
|
+
if (error instanceof ApiError && error.code === "forbidden") {
|
|
10478
|
+
throw new Refusal(
|
|
10479
|
+
`wrangler.toml carries ${existing}, which is registered to another user. Run \`deepspace app init --new-id\` to fork this repo as your own app (new data and secrets; the original is untouched).`,
|
|
10480
|
+
"not_app_owner"
|
|
10481
|
+
);
|
|
10482
|
+
}
|
|
10483
|
+
throw error;
|
|
10484
|
+
}
|
|
10485
|
+
if (!state.registered) {
|
|
10486
|
+
throw new Refusal(
|
|
10487
|
+
`wrangler.toml carries ${existing}, but that id was never registered \u2014 it was minted locally by an older SDK. Ids are server-minted at registration now, and an existing unregistered id cannot be claimed. Run \`deepspace app init --new-id\` to register this repo as a fresh app (new data and secrets; nothing to migrate \u2014 the old id never had server-side state).`,
|
|
10488
|
+
"app_not_registered"
|
|
10489
|
+
);
|
|
10490
|
+
}
|
|
10294
10491
|
if (!args.json) {
|
|
10295
10492
|
console.log(`Already initialized: ${existing}${envName ? ` (env: ${envName})` : ""}`);
|
|
10296
10493
|
console.log(`App dir: ${appDir}`);
|
|
@@ -10304,7 +10501,6 @@ var init_default = defineDeepspaceCommand({
|
|
|
10304
10501
|
method: "POST"
|
|
10305
10502
|
});
|
|
10306
10503
|
writeAppId(appDir, appId, { wranglerEnv: envName, force: Boolean(args["new-id"]) });
|
|
10307
|
-
if (!envName) stampAppIdInSources(appDir, appId, existing);
|
|
10308
10504
|
const committedScaffold = commitScaffoldIfUnborn(appDir, token);
|
|
10309
10505
|
if (!args.json) {
|
|
10310
10506
|
if (existing) {
|
|
@@ -10747,6 +10943,24 @@ var push_default = defineDeepspaceCommand({
|
|
|
10747
10943
|
);
|
|
10748
10944
|
}
|
|
10749
10945
|
const { token, appId } = await resolveTarget3();
|
|
10946
|
+
let sourceState;
|
|
10947
|
+
try {
|
|
10948
|
+
sourceState = await getAppSource(deployBaseUrl(), token, appId);
|
|
10949
|
+
} catch (error) {
|
|
10950
|
+
if (error instanceof ApiError && error.code === "forbidden") {
|
|
10951
|
+
throw new Refusal(
|
|
10952
|
+
`${appId} is registered to another user. Run \`deepspace app init --new-id\` to fork this repo as your own app (new data and secrets; the original is untouched).`,
|
|
10953
|
+
"not_app_owner"
|
|
10954
|
+
);
|
|
10955
|
+
}
|
|
10956
|
+
throw error;
|
|
10957
|
+
}
|
|
10958
|
+
if (!sourceState.registered) {
|
|
10959
|
+
throw new Refusal(
|
|
10960
|
+
`${appId} is not registered. If this repo's id came from an older SDK's scaffold, run \`deepspace app init --new-id\` to register it as a fresh app; a brand-new app dir registers with \`deepspace app init\`.`,
|
|
10961
|
+
"app_not_registered"
|
|
10962
|
+
);
|
|
10963
|
+
}
|
|
10750
10964
|
const pullRecoveryCwd = selectedBranchCheckout(appDir, branch) ?? appDir;
|
|
10751
10965
|
ensureSpaceRemote(appDir, appId);
|
|
10752
10966
|
if (force) {
|
|
@@ -11611,7 +11825,7 @@ import {
|
|
|
11611
11825
|
realpathSync as realpathSync6,
|
|
11612
11826
|
renameSync as renameSync2,
|
|
11613
11827
|
statSync as statSync3,
|
|
11614
|
-
writeFileSync as
|
|
11828
|
+
writeFileSync as writeFileSync6
|
|
11615
11829
|
} from "fs";
|
|
11616
11830
|
import { dirname as dirname11, isAbsolute as isAbsolute5, join as join22, relative as relative2, sep as sep2 } from "path";
|
|
11617
11831
|
var WORKSPACE_MARKER = "deepspace-workspace.json";
|
|
@@ -11646,7 +11860,7 @@ function markManagedWorkspace(worktreeRoot, workspaceId) {
|
|
|
11646
11860
|
const tempPath = `${markerPath}.${process.pid}.tmp`;
|
|
11647
11861
|
try {
|
|
11648
11862
|
mkdirSync7(dirname11(markerPath), { recursive: true });
|
|
11649
|
-
|
|
11863
|
+
writeFileSync6(tempPath, JSON.stringify(marker) + "\n");
|
|
11650
11864
|
renameSync2(tempPath, markerPath);
|
|
11651
11865
|
return true;
|
|
11652
11866
|
} catch {
|
|
@@ -13780,13 +13994,13 @@ function sameRefs(left, right) {
|
|
|
13780
13994
|
|
|
13781
13995
|
// src/cli/commands/update.ts
|
|
13782
13996
|
import * as p34 from "@clack/prompts";
|
|
13783
|
-
import { existsSync as existsSync26, readFileSync as readFileSync27, writeFileSync as
|
|
13997
|
+
import { existsSync as existsSync26, readFileSync as readFileSync27, writeFileSync as writeFileSync7 } from "fs";
|
|
13784
13998
|
import { join as join24, resolve as resolve20 } from "path";
|
|
13785
13999
|
|
|
13786
14000
|
// package.json
|
|
13787
14001
|
var package_default = {
|
|
13788
14002
|
name: "deepspace",
|
|
13789
|
-
version: "0.
|
|
14003
|
+
version: "0.23.0",
|
|
13790
14004
|
engines: {
|
|
13791
14005
|
node: ">=22.15.0 <23 || >=24 <25 || >=26 <27"
|
|
13792
14006
|
},
|
|
@@ -13823,6 +14037,10 @@ var package_default = {
|
|
|
13823
14037
|
types: "./dist/testing-mcp.d.ts",
|
|
13824
14038
|
import: "./dist/testing-mcp.js"
|
|
13825
14039
|
},
|
|
14040
|
+
"./build": {
|
|
14041
|
+
types: "./dist/build.d.ts",
|
|
14042
|
+
import: "./dist/build.js"
|
|
14043
|
+
},
|
|
13826
14044
|
"./documentation": {
|
|
13827
14045
|
types: "./dist/documentation.d.ts",
|
|
13828
14046
|
import: "./dist/documentation.js"
|
|
@@ -13986,7 +14204,7 @@ function pinSdkVersion(appDir, version) {
|
|
|
13986
14204
|
const eol = source.includes("\r\n") ? "\r\n" : "\n";
|
|
13987
14205
|
const indent = source.match(/\r?\n([\t ]+)"/)?.[1] ?? " ";
|
|
13988
14206
|
const finalEol = source.endsWith("\n") ? eol : "";
|
|
13989
|
-
|
|
14207
|
+
writeFileSync7(path, JSON.stringify(manifest, null, indent).replaceAll("\n", eol) + finalEol);
|
|
13990
14208
|
return true;
|
|
13991
14209
|
}
|
|
13992
14210
|
function buildPreviewSecretsUpgradeInstruction(appDir) {
|
|
@@ -13998,8 +14216,10 @@ function buildPreviewSecretsUpgradeInstruction(appDir) {
|
|
|
13998
14216
|
].find((candidate) => existsSync26(join24(appDir, candidate)));
|
|
13999
14217
|
if (!configName) return null;
|
|
14000
14218
|
const source = readFileSync27(join24(appDir, configName), "utf8");
|
|
14001
|
-
if (source.includes("deepspace-remove-build-preview-secrets"))
|
|
14002
|
-
|
|
14219
|
+
if (source.includes("deepspace-remove-build-preview-secrets") || source.includes("deepspaceBuild(") || source.includes("'deepspace/build'") || source.includes('"deepspace/build"')) {
|
|
14220
|
+
return null;
|
|
14221
|
+
}
|
|
14222
|
+
return `${configName}: adopt the deepspaceBuild() plugin from deepspace/build (which owns this cleanup), or add the inline cleanup from ${BUILD_PREVIEW_SECRETS_GUIDE}; app update left this app-owned file unchanged.`;
|
|
14003
14223
|
}
|
|
14004
14224
|
function usersSchemaVisibilityUpgradeInstruction(appDir) {
|
|
14005
14225
|
const schemaName = "src/schemas/users-schema.ts";
|