lakebed 0.0.21 → 0.0.23-staging.26699880384
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/package.json +7 -6
- package/src/anonymous-server.js +68 -1
- package/src/cli.js +71 -47
- package/src/release.js +3 -0
- package/src/version.js +1 -1
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lakebed",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23-staging.26699880384",
|
|
4
4
|
"description": "Agent-native CLI and runtime for building and deploying Lakebed capsules.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://lakebed.dev",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/pingdotgg/
|
|
10
|
+
"url": "git+https://github.com/pingdotgg/lakebed.git",
|
|
11
11
|
"directory": "packages/lakebed"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"src/cli.js",
|
|
27
27
|
"src/client.d.ts",
|
|
28
28
|
"src/client.js",
|
|
29
|
+
"src/release.js",
|
|
29
30
|
"src/runtime.js",
|
|
30
31
|
"src/server.d.ts",
|
|
31
32
|
"src/server.js",
|
|
@@ -55,6 +56,9 @@
|
|
|
55
56
|
"publishConfig": {
|
|
56
57
|
"access": "public"
|
|
57
58
|
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"check": "node --check src/cli.js && node --check src/runtime.js && node --check src/server.js && node --check src/client.js && node --check src/release.js && node --check src/source-store.js && node --check src/source-runtime.js && node --check src/source-runtime-worker.js && node --check src/source-runtime-loader.mjs && node --check src/anonymous.js && node --check src/anonymous-server.js && node --check src/auth.js && node --check src/version.js && node --check src/services/all-in-one.js && node --check src/services/api-dashboard.js && node --check src/services/capsule-runner.js"
|
|
61
|
+
},
|
|
58
62
|
"dependencies": {
|
|
59
63
|
"esbuild": "^0.27.1",
|
|
60
64
|
"pg": "^8.16.3",
|
|
@@ -63,8 +67,5 @@
|
|
|
63
67
|
},
|
|
64
68
|
"devDependencies": {
|
|
65
69
|
"@types/ws": "^8.18.1"
|
|
66
|
-
},
|
|
67
|
-
"scripts": {
|
|
68
|
-
"check": "node --check src/cli.js && node --check src/runtime.js && node --check src/server.js && node --check src/client.js && node --check src/source-store.js && node --check src/source-runtime.js && node --check src/source-runtime-worker.js && node --check src/source-runtime-loader.mjs && node --check src/anonymous.js && node --check src/anonymous-server.js && node --check src/auth.js && node --check src/version.js && node --check src/services/all-in-one.js && node --check src/services/api-dashboard.js && node --check src/services/capsule-runner.js"
|
|
69
70
|
}
|
|
70
|
-
}
|
|
71
|
+
}
|
package/src/anonymous-server.js
CHANGED
|
@@ -111,6 +111,15 @@ function sendText(res, status, value, headers = {}) {
|
|
|
111
111
|
res.end(value);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
function healthReleaseMetadata(env = process.env) {
|
|
115
|
+
return {
|
|
116
|
+
environment: env.RAILWAY_ENVIRONMENT_NAME ?? null,
|
|
117
|
+
gitSha: env.RAILWAY_GIT_COMMIT_SHA ?? null,
|
|
118
|
+
service: env.RAILWAY_SERVICE_NAME ?? null,
|
|
119
|
+
version: LAKEBED_VERSION
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
114
123
|
function redirect(res, location, headers = {}) {
|
|
115
124
|
res.writeHead(302, {
|
|
116
125
|
Location: location,
|
|
@@ -436,6 +445,48 @@ function isApiDashboardRoute(pathname) {
|
|
|
436
445
|
);
|
|
437
446
|
}
|
|
438
447
|
|
|
448
|
+
function isDashboardBrowserRoute(pathname) {
|
|
449
|
+
return (
|
|
450
|
+
pathname === "/" ||
|
|
451
|
+
pathname === "/deploys" ||
|
|
452
|
+
pathname === "/dashboard" ||
|
|
453
|
+
pathname === "/auth" ||
|
|
454
|
+
pathname.startsWith("/auth/") ||
|
|
455
|
+
pathname === "/admin" ||
|
|
456
|
+
pathname.startsWith("/admin/") ||
|
|
457
|
+
pathname.startsWith("/claim/")
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function normalizedUrlHost(value) {
|
|
462
|
+
try {
|
|
463
|
+
return new URL(value).host.toLowerCase();
|
|
464
|
+
} catch {
|
|
465
|
+
return "";
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function dashboardRedirectLocation({ dashboardRootUrl, requestUrl }) {
|
|
470
|
+
const pathname = requestUrl.pathname === "/" ? "/deploys" : requestUrl.pathname;
|
|
471
|
+
const target = new URL(pathname, dashboardRootUrl);
|
|
472
|
+
target.search = requestUrl.search;
|
|
473
|
+
return target.href;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function shouldRedirectToDashboardHost({ dashboardRootUrl, host, publicRootUrl, requestUrl }) {
|
|
477
|
+
if (!isDashboardBrowserRoute(requestUrl.pathname)) {
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const publicHost = normalizedUrlHost(publicRootUrl);
|
|
482
|
+
const dashboardHost = normalizedUrlHost(dashboardRootUrl);
|
|
483
|
+
if (!publicHost || !dashboardHost || publicHost === dashboardHost) {
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return String(host).toLowerCase() === publicHost;
|
|
488
|
+
}
|
|
489
|
+
|
|
439
490
|
function appUrlForSlug({ appBaseDomain, slug }) {
|
|
440
491
|
if (!appBaseDomain) {
|
|
441
492
|
throw new Error("LAKEBED_APP_BASE_DOMAIN is required to create hosted deploy URLs.");
|
|
@@ -6213,7 +6264,23 @@ export async function startAnonymousServer({
|
|
|
6213
6264
|
|
|
6214
6265
|
try {
|
|
6215
6266
|
if (req.method === "GET" && requestUrl.pathname === "/healthz") {
|
|
6216
|
-
sendJson(res, 200, {
|
|
6267
|
+
sendJson(res, 200, {
|
|
6268
|
+
ok: true,
|
|
6269
|
+
release: healthReleaseMetadata()
|
|
6270
|
+
});
|
|
6271
|
+
return;
|
|
6272
|
+
}
|
|
6273
|
+
|
|
6274
|
+
if (
|
|
6275
|
+
servesApiDashboard &&
|
|
6276
|
+
shouldRedirectToDashboardHost({
|
|
6277
|
+
dashboardRootUrl: resolvedDashboardRootUrl,
|
|
6278
|
+
host,
|
|
6279
|
+
publicRootUrl: resolvedPublicRootUrl,
|
|
6280
|
+
requestUrl
|
|
6281
|
+
})
|
|
6282
|
+
) {
|
|
6283
|
+
redirect(res, dashboardRedirectLocation({ dashboardRootUrl: resolvedDashboardRootUrl, requestUrl }));
|
|
6217
6284
|
return;
|
|
6218
6285
|
}
|
|
6219
6286
|
|
package/src/cli.js
CHANGED
|
@@ -23,6 +23,11 @@ import {
|
|
|
23
23
|
} from "./anonymous.js";
|
|
24
24
|
import { startAnonymousServer } from "./anonymous-server.js";
|
|
25
25
|
import { authFromUrl as resolveAuthFromUrl, createGuestAuth, requestOrigin, shooBaseUrlFromEnv } from "./auth.js";
|
|
26
|
+
import {
|
|
27
|
+
LAKEBED_APP_BASE_DOMAIN as defaultHostedAppBaseDomain,
|
|
28
|
+
LAKEBED_DEPLOY_API_URL as defaultDeployApiUrl,
|
|
29
|
+
LAKEBED_RELEASE_CHANNEL
|
|
30
|
+
} from "./release.js";
|
|
26
31
|
import { LogBuffer, StateCell } from "./runtime.js";
|
|
27
32
|
import { MemorySourceStore, createMemorySourceStoreFromDirectory, sourcePathDirname, sourcePathJoin } from "./source-store.js";
|
|
28
33
|
|
|
@@ -30,7 +35,10 @@ const root = process.cwd();
|
|
|
30
35
|
const packageDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
31
36
|
const packageNodeModules = resolve(packageDir, "node_modules");
|
|
32
37
|
const sourceNamespace = "lakebed-source";
|
|
33
|
-
const
|
|
38
|
+
const cliPackageSpec = LAKEBED_RELEASE_CHANNEL === "staging" ? "lakebed@staging" : "lakebed";
|
|
39
|
+
const cliCommand = `npx ${cliPackageSpec}`;
|
|
40
|
+
const productionDeployApiUrl = "https://api.lakebed.dev";
|
|
41
|
+
const legacyDeployApiUrl = "https://api.lakebed.app";
|
|
34
42
|
const execFileAsync = promisify(execFile);
|
|
35
43
|
const endpointBodyMaxBytes = 2 * 1024 * 1024;
|
|
36
44
|
|
|
@@ -38,21 +46,21 @@ function usage() {
|
|
|
38
46
|
console.log(`lakebed
|
|
39
47
|
|
|
40
48
|
Usage:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
${cliCommand} new [name] [--template todo] [--no-git]
|
|
50
|
+
${cliCommand} create [name] [--template todo] [--no-git]
|
|
51
|
+
${cliCommand} dev [capsule-dir] [--port 3000]
|
|
52
|
+
${cliCommand} build [capsule-dir] --target anonymous [--out .lakebed/artifacts/app.json] [--json]
|
|
53
|
+
${cliCommand} deploy [capsule-dir] [--api <url>] [--public-inspect] [--json]
|
|
54
|
+
${cliCommand} claim [capsule-dir] [--api <url>] [--json]
|
|
55
|
+
${cliCommand} domains add <subdomain.${defaultHostedAppBaseDomain}> [--api <url>] [--json]
|
|
56
|
+
${cliCommand} anonymous-server [--port 8787] [--public-root-url <url>] [--dashboard-root-url <url>] [--app-base-domain <domain>] [--role all|api-dashboard|runner]
|
|
57
|
+
${cliCommand} inspect <deploy-id-or-url> [--api <url>] [--inspect-token <token>] [--json]
|
|
58
|
+
${cliCommand} run-many [capsule-dir] [--count 20] [--base-port 4000]
|
|
59
|
+
${cliCommand} auth as <name>
|
|
60
|
+
${cliCommand} auth reset
|
|
61
|
+
${cliCommand} db list [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
|
|
62
|
+
${cliCommand} db dump [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
|
|
63
|
+
${cliCommand} logs [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
|
|
56
64
|
`);
|
|
57
65
|
}
|
|
58
66
|
|
|
@@ -1096,7 +1104,7 @@ export default capsule({
|
|
|
1096
1104
|
<p className="text-sm font-semibold uppercase tracking-wide text-cyan-300">Lakebed deploy</p>
|
|
1097
1105
|
<h1 className="mt-3 text-3xl font-semibold">Claim required</h1>
|
|
1098
1106
|
<p className="mt-4 text-neutral-300">
|
|
1099
|
-
This capsule uses ${feature}. Claim this deploy, then run
|
|
1107
|
+
This capsule uses ${feature}. Claim this deploy, then run ${cliCommand} deploy again to publish the app.
|
|
1100
1108
|
</p>
|
|
1101
1109
|
</section>
|
|
1102
1110
|
</main>
|
|
@@ -1193,16 +1201,16 @@ function claimTokenFromDeployResponse(deployed) {
|
|
|
1193
1201
|
return null;
|
|
1194
1202
|
}
|
|
1195
1203
|
|
|
1196
|
-
function claimUrlFromDeployMetadata(metadata) {
|
|
1204
|
+
function claimUrlFromDeployMetadata(metadata, api = metadata?.api) {
|
|
1197
1205
|
if (!metadata?.api || !metadata?.deployId || !metadata?.claimToken) {
|
|
1198
1206
|
return null;
|
|
1199
1207
|
}
|
|
1200
1208
|
|
|
1201
|
-
return `${
|
|
1209
|
+
return `${normalizeHostedUrl(api)}/claim/${encodeURIComponent(metadata.deployId)}/${encodeURIComponent(metadata.claimToken)}`;
|
|
1202
1210
|
}
|
|
1203
1211
|
|
|
1204
1212
|
function claimCommandText({ api, capsuleArg }) {
|
|
1205
|
-
const parts = ["npx",
|
|
1213
|
+
const parts = ["npx", cliPackageSpec, "claim"];
|
|
1206
1214
|
if (capsuleArg) {
|
|
1207
1215
|
parts.push(capsuleArg);
|
|
1208
1216
|
}
|
|
@@ -1219,7 +1227,7 @@ function normalizeDomainCommandHostname(value) {
|
|
|
1219
1227
|
}
|
|
1220
1228
|
|
|
1221
1229
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw) || raw.includes("/") || raw.includes("\\") || raw.includes(":")) {
|
|
1222
|
-
throw new Error(
|
|
1230
|
+
throw new Error(`Enter a domain like my-app.${defaultHostedAppBaseDomain}, without a scheme, port, or path.`);
|
|
1223
1231
|
}
|
|
1224
1232
|
|
|
1225
1233
|
const hostname = domainToASCII(raw.replace(/\.$/, "").toLowerCase());
|
|
@@ -1330,6 +1338,15 @@ function normalizeHostedUrl(value) {
|
|
|
1330
1338
|
}
|
|
1331
1339
|
}
|
|
1332
1340
|
|
|
1341
|
+
function canonicalDeployApiUrl(value) {
|
|
1342
|
+
const normalized = normalizeHostedUrl(value);
|
|
1343
|
+
return normalized === legacyDeployApiUrl ? productionDeployApiUrl : normalized;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
function deployApiUrlsMatch(left, right) {
|
|
1347
|
+
return canonicalDeployApiUrl(left) === canonicalDeployApiUrl(right);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1333
1350
|
async function readResponseJson(response) {
|
|
1334
1351
|
const body = await response.text();
|
|
1335
1352
|
if (!response.ok) {
|
|
@@ -1340,7 +1357,7 @@ async function readResponseJson(response) {
|
|
|
1340
1357
|
|
|
1341
1358
|
async function deployCommand(args) {
|
|
1342
1359
|
if (args.some((arg) => arg === "--ttl" || arg.startsWith("--ttl="))) {
|
|
1343
|
-
throw new Error(
|
|
1360
|
+
throw new Error(`${cliCommand} deploy no longer accepts --ttl. Deploy expiry is set by the server.`);
|
|
1344
1361
|
}
|
|
1345
1362
|
|
|
1346
1363
|
const [capsuleArg] = positionals(args);
|
|
@@ -1354,7 +1371,7 @@ async function deployCommand(args) {
|
|
|
1354
1371
|
const inspectPolicy = hasFlag(args, "--public-inspect") ? "public" : undefined;
|
|
1355
1372
|
const metadata = await readDeployMetadata(capsuleDir);
|
|
1356
1373
|
const canUpdate =
|
|
1357
|
-
metadata?.api
|
|
1374
|
+
deployApiUrlsMatch(metadata?.api, api) && typeof metadata?.deployId === "string" && typeof metadata?.claimToken === "string";
|
|
1358
1375
|
let currentDeploy = null;
|
|
1359
1376
|
if (canUpdate) {
|
|
1360
1377
|
const currentResponse = await fetch(`${api}/v1/deploys/${encodeURIComponent(metadata.deployId)}`);
|
|
@@ -1367,7 +1384,7 @@ async function deployCommand(args) {
|
|
|
1367
1384
|
if (!currentDeploy?.claimed && hasServerEnvValues) {
|
|
1368
1385
|
if (canUpdate && currentDeploy) {
|
|
1369
1386
|
throw new Error(
|
|
1370
|
-
`This capsule defines server env in ${SERVER_ENV_FILE}.\n\nThis deploy is still anonymous. Claim it first, then run
|
|
1387
|
+
`This capsule defines server env in ${SERVER_ENV_FILE}.\n\nThis deploy is still anonymous. Claim it first, then run ${cliCommand} deploy again to sync server env.`
|
|
1371
1388
|
);
|
|
1372
1389
|
}
|
|
1373
1390
|
try {
|
|
@@ -1384,7 +1401,7 @@ async function deployCommand(args) {
|
|
|
1384
1401
|
} catch (error) {
|
|
1385
1402
|
if (error instanceof AnonymousCompilerError && canUpdate && currentDeploy && !currentDeploy.claimed) {
|
|
1386
1403
|
throw new Error(
|
|
1387
|
-
`${error.message}\n\nThis deploy is still anonymous. Claim it first, then run
|
|
1404
|
+
`${error.message}\n\nThis deploy is still anonymous. Claim it first, then run ${cliCommand} deploy again to use server-side fetch.`
|
|
1388
1405
|
);
|
|
1389
1406
|
}
|
|
1390
1407
|
if ((!canUpdate || !currentDeploy) && canDeployAfterClaim(error)) {
|
|
@@ -1466,7 +1483,7 @@ async function deployCommand(args) {
|
|
|
1466
1483
|
if (deployed.claimUrl) {
|
|
1467
1484
|
console.log(`Claim: ${claimCommandText({ api, capsuleArg })}`);
|
|
1468
1485
|
}
|
|
1469
|
-
console.log(`Inspect:
|
|
1486
|
+
console.log(`Inspect: ${cliCommand} inspect ${deployed.deployId}`);
|
|
1470
1487
|
if (deployed.inspectPolicy === "public") {
|
|
1471
1488
|
console.log("Inspect policy: public - data and logs are readable by anyone with the app URL.");
|
|
1472
1489
|
}
|
|
@@ -1484,7 +1501,7 @@ async function deployCommand(args) {
|
|
|
1484
1501
|
}
|
|
1485
1502
|
if (envelope.claimRequired) {
|
|
1486
1503
|
console.log("\nThis app needs a claimed deploy before server-side fetch or server env can run.");
|
|
1487
|
-
console.log(`Run ${claimCommandText({ api, capsuleArg })}, then run
|
|
1504
|
+
console.log(`Run ${claimCommandText({ api, capsuleArg })}, then run ${cliCommand} deploy again.`);
|
|
1488
1505
|
}
|
|
1489
1506
|
}
|
|
1490
1507
|
|
|
@@ -1495,14 +1512,14 @@ async function claimCommand(args) {
|
|
|
1495
1512
|
const metadata = await readDeployMetadata(capsuleDir);
|
|
1496
1513
|
|
|
1497
1514
|
if (!metadata) {
|
|
1498
|
-
throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run
|
|
1515
|
+
throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run ${cliCommand} deploy from this project first.`);
|
|
1499
1516
|
}
|
|
1500
1517
|
|
|
1501
|
-
if (metadata.api
|
|
1518
|
+
if (!deployApiUrlsMatch(metadata.api, api)) {
|
|
1502
1519
|
throw new Error(`Saved deploy metadata is for ${metadata.api}, but this command is using ${api}. Pass --api ${metadata.api} to claim it.`);
|
|
1503
1520
|
}
|
|
1504
1521
|
|
|
1505
|
-
const claimUrl = claimUrlFromDeployMetadata(metadata);
|
|
1522
|
+
const claimUrl = claimUrlFromDeployMetadata(metadata, api);
|
|
1506
1523
|
if (!claimUrl) {
|
|
1507
1524
|
throw new Error("This project does not have a saved claim token. Redeploy to create a new claim URL.");
|
|
1508
1525
|
}
|
|
@@ -1559,9 +1576,9 @@ async function domainsCommand(args) {
|
|
|
1559
1576
|
const api = deployApiUrl(args);
|
|
1560
1577
|
const metadata = await readDeployMetadata(capsuleDir);
|
|
1561
1578
|
if (!metadata) {
|
|
1562
|
-
throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run
|
|
1579
|
+
throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run ${cliCommand} deploy from this project first.`);
|
|
1563
1580
|
}
|
|
1564
|
-
if (metadata.api
|
|
1581
|
+
if (!deployApiUrlsMatch(metadata.api, api)) {
|
|
1565
1582
|
throw new Error(`Saved deploy metadata is for ${metadata.api}, but this command is using ${api}. Pass --api ${metadata.api} to use it.`);
|
|
1566
1583
|
}
|
|
1567
1584
|
if (!metadata.deployId || !metadata.claimToken) {
|
|
@@ -1603,7 +1620,7 @@ async function anonymousServerCommand(args) {
|
|
|
1603
1620
|
|
|
1604
1621
|
function deployLookupApiUrl(target, args, metadata) {
|
|
1605
1622
|
if (!hasExplicitOption(args, "--api") && metadata?.api && metadata.deployId === target) {
|
|
1606
|
-
return
|
|
1623
|
+
return canonicalDeployApiUrl(metadata.api);
|
|
1607
1624
|
}
|
|
1608
1625
|
|
|
1609
1626
|
return deployApiUrl(args);
|
|
@@ -1841,7 +1858,7 @@ Your role is to build software within this capsule. Lakebed is the runtime, the
|
|
|
1841
1858
|
## Hard rules
|
|
1842
1859
|
|
|
1843
1860
|
- No installing node modules. You can use the built-in APIs. Write TypeScript for anything that is not included.
|
|
1844
|
-
- Lakebed CLI should always be run with
|
|
1861
|
+
- Lakebed CLI should always be run with \`${cliCommand} [command]\`. It is not a global. Launch with \`npx\` always.
|
|
1845
1862
|
- All client code goes in the \`client\` directory, and all server code goes in the \`server\` directory. Shared code can go in \`shared\`.
|
|
1846
1863
|
- Use \`lakebed/server\` only from \`server/*.ts\`.
|
|
1847
1864
|
- Use \`lakebed/client\` only from \`client/*.tsx\`.
|
|
@@ -1855,7 +1872,7 @@ Your role is to build software within this capsule. Lakebed is the runtime, the
|
|
|
1855
1872
|
- Read server-only environment variables through \`ctx.env\`; define them in \`.env.lakebed.server\`.
|
|
1856
1873
|
- Auth can be added with a Google sign-in using \`<SignInWithGoogle />\` or \`signInWithGoogle()\` from \`lakebed/client\`.
|
|
1857
1874
|
- Keep \`shared/\` free of DOM, Node, env, and Lakebed runtime imports.
|
|
1858
|
-
- Environment variables are only available on the server, and must be defined in \`.env.lakebed.server\`. They are not available during build time. If you need build-time environment variables, define them in code and do conditional logic based on them. They will be synced with
|
|
1875
|
+
- Environment variables are only available on the server, and must be defined in \`.env.lakebed.server\`. They are not available during build time. If you need build-time environment variables, define them in code and do conditional logic based on them. They will be synced with ${LAKEBED_RELEASE_CHANNEL} on \`${cliCommand} deploy\`.
|
|
1859
1876
|
|
|
1860
1877
|
## Default project structure
|
|
1861
1878
|
|
|
@@ -1868,21 +1885,21 @@ Your role is to build software within this capsule. Lakebed is the runtime, the
|
|
|
1868
1885
|
Run locally:
|
|
1869
1886
|
|
|
1870
1887
|
\`\`\`sh
|
|
1871
|
-
|
|
1888
|
+
${cliCommand} dev
|
|
1872
1889
|
\`\`\`
|
|
1873
1890
|
|
|
1874
1891
|
Deploy:
|
|
1875
1892
|
|
|
1876
1893
|
\`\`\`sh
|
|
1877
|
-
|
|
1894
|
+
${cliCommand} deploy
|
|
1878
1895
|
\`\`\`
|
|
1879
1896
|
|
|
1880
|
-
Inspect local state while
|
|
1897
|
+
Inspect local state while \`${cliCommand} dev\` is running:
|
|
1881
1898
|
|
|
1882
1899
|
\`\`\`sh
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1900
|
+
${cliCommand} db list --port 3000
|
|
1901
|
+
${cliCommand} db dump --port 3000
|
|
1902
|
+
${cliCommand} logs --port 3000
|
|
1886
1903
|
\`\`\`
|
|
1887
1904
|
|
|
1888
1905
|
## External endpoints
|
|
@@ -1902,8 +1919,8 @@ Use \`endpoint({ method, path }, handler)\` from \`lakebed/server\` when the app
|
|
|
1902
1919
|
- No file storage.
|
|
1903
1920
|
- No outbound fetch in anonymous deploys. Claim the deploy before using server-side fetch.
|
|
1904
1921
|
- Non-empty \`.env.lakebed.server\` files sync only after a deploy is claimed.
|
|
1905
|
-
- Local state resets when
|
|
1906
|
-
- All
|
|
1922
|
+
- Local state resets when \`${cliCommand} dev\` restarts.
|
|
1923
|
+
- All ${LAKEBED_RELEASE_CHANNEL} deploys are on '${defaultHostedAppBaseDomain}'
|
|
1907
1924
|
`;
|
|
1908
1925
|
}
|
|
1909
1926
|
|
|
@@ -2091,7 +2108,7 @@ export function cleanTodoText(value: string): string {
|
|
|
2091
2108
|
Run this Lakebed capsule:
|
|
2092
2109
|
|
|
2093
2110
|
\`\`\`sh
|
|
2094
|
-
|
|
2111
|
+
${cliCommand} dev
|
|
2095
2112
|
\`\`\`
|
|
2096
2113
|
|
|
2097
2114
|
The starter app includes two client routes:
|
|
@@ -2138,12 +2155,19 @@ async function newCommand(args) {
|
|
|
2138
2155
|
const gitStatus = shouldInitGit ? await initializeGitRepository(targetDir) : "Skipped git setup (--no-git).";
|
|
2139
2156
|
console.log(gitStatus);
|
|
2140
2157
|
console.log(`
|
|
2158
|
+
Project files:
|
|
2159
|
+
AGENTS.md contains the Lakebed-specific instructions for agents working in this capsule.
|
|
2160
|
+
CLAUDE.md mirrors AGENTS.md for Claude-based workflows.
|
|
2161
|
+
|
|
2141
2162
|
Next:
|
|
2142
2163
|
cd ${shellQuote(name)}
|
|
2143
|
-
|
|
2164
|
+
${cliCommand} dev
|
|
2165
|
+
|
|
2166
|
+
Deploy:
|
|
2167
|
+
${cliCommand} deploy
|
|
2144
2168
|
|
|
2145
|
-
|
|
2146
|
-
|
|
2169
|
+
Notice to agents who run this command:
|
|
2170
|
+
make sure to read AGENTS.md before changing files in this capsule.`);
|
|
2147
2171
|
}
|
|
2148
2172
|
|
|
2149
2173
|
async function initializeGitRepository(targetDir) {
|
package/src/release.js
ADDED
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LAKEBED_VERSION = "0.0.
|
|
1
|
+
export const LAKEBED_VERSION = "0.0.23-staging.26699880384";
|