lakebed 0.0.9 → 0.0.11
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/README.md +6 -3
- package/package.json +1 -1
- package/src/anonymous-server.js +1059 -329
- package/src/cli.js +75 -10
- package/src/version.js +1 -1
package/src/cli.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
2
3
|
import { createServer } from "node:http";
|
|
3
4
|
import { existsSync, realpathSync } from "node:fs";
|
|
4
5
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
5
6
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
6
7
|
import { createInterface } from "node:readline/promises";
|
|
8
|
+
import { promisify } from "node:util";
|
|
7
9
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
10
|
import * as esbuild from "esbuild";
|
|
9
11
|
import { WebSocketServer } from "ws";
|
|
@@ -28,19 +30,21 @@ const packageDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
28
30
|
const packageNodeModules = resolve(packageDir, "node_modules");
|
|
29
31
|
const sourceNamespace = "lakebed-source";
|
|
30
32
|
const defaultDeployApiUrl = "https://api.lakebed.app";
|
|
33
|
+
const execFileAsync = promisify(execFile);
|
|
31
34
|
|
|
32
35
|
function usage() {
|
|
33
36
|
console.log(`lakebed
|
|
34
37
|
|
|
35
38
|
Usage:
|
|
36
|
-
lakebed new [name] [--template todo]
|
|
37
|
-
lakebed
|
|
38
|
-
lakebed
|
|
39
|
+
lakebed new [name] [--template todo] [--no-git]
|
|
40
|
+
lakebed create [name] [--template todo] [--no-git]
|
|
41
|
+
lakebed dev [capsule-dir] [--port 3000]
|
|
42
|
+
lakebed build [capsule-dir] --target anonymous [--out .lakebed/artifacts/app.json] [--json]
|
|
39
43
|
lakebed deploy [capsule-dir] [--ttl 7d] [--api <url>] [--json]
|
|
40
44
|
lakebed claim [capsule-dir] [--api <url>] [--json]
|
|
41
45
|
lakebed anonymous-server [--port 8787] [--public-root-url <url>] [--app-base-domain <domain>]
|
|
42
46
|
lakebed inspect <deploy-id-or-url> [--api <url>] [--json]
|
|
43
|
-
lakebed run-many
|
|
47
|
+
lakebed run-many [capsule-dir] [--count 20] [--base-port 4000]
|
|
44
48
|
lakebed auth as <name>
|
|
45
49
|
lakebed auth reset
|
|
46
50
|
lakebed db list [deploy-id-or-url] [--port 3000]
|
|
@@ -58,12 +62,27 @@ function readArg(args, name, fallback) {
|
|
|
58
62
|
return args[index + 1] ?? fallback;
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
const optionsWithValues = new Set([
|
|
66
|
+
"--api",
|
|
67
|
+
"--app-base-domain",
|
|
68
|
+
"--base-port",
|
|
69
|
+
"--count",
|
|
70
|
+
"--out",
|
|
71
|
+
"--port",
|
|
72
|
+
"--public-root-url",
|
|
73
|
+
"--target",
|
|
74
|
+
"--template",
|
|
75
|
+
"--ttl"
|
|
76
|
+
]);
|
|
77
|
+
|
|
61
78
|
function positionals(args) {
|
|
62
79
|
const values = [];
|
|
63
80
|
for (let index = 0; index < args.length; index += 1) {
|
|
64
81
|
const value = args[index];
|
|
65
82
|
if (value.startsWith("--")) {
|
|
66
|
-
|
|
83
|
+
if (optionsWithValues.has(value)) {
|
|
84
|
+
index += 1;
|
|
85
|
+
}
|
|
67
86
|
continue;
|
|
68
87
|
}
|
|
69
88
|
|
|
@@ -88,7 +107,7 @@ function hasFlag(args, name) {
|
|
|
88
107
|
|
|
89
108
|
function resolveCapsuleDir(value) {
|
|
90
109
|
if (!value) {
|
|
91
|
-
return
|
|
110
|
+
return root;
|
|
92
111
|
}
|
|
93
112
|
|
|
94
113
|
return isAbsolute(value) ? value : resolve(root, value);
|
|
@@ -827,7 +846,7 @@ async function readResponseJson(response) {
|
|
|
827
846
|
|
|
828
847
|
async function deployCommand(args) {
|
|
829
848
|
const [capsuleArg] = positionals(args);
|
|
830
|
-
const capsuleDir =
|
|
849
|
+
const capsuleDir = resolveCapsuleDir(capsuleArg);
|
|
831
850
|
const sourceStore = await createMemorySourceStoreFromDirectory(capsuleDir);
|
|
832
851
|
const serverEnvFileExists = sourceStore.hasFile(SERVER_ENV_FILE);
|
|
833
852
|
const serverEnv = await readCapsuleServerEnv(sourceStore);
|
|
@@ -969,7 +988,7 @@ async function deployCommand(args) {
|
|
|
969
988
|
|
|
970
989
|
async function claimCommand(args) {
|
|
971
990
|
const [capsuleArg] = positionals(args);
|
|
972
|
-
const capsuleDir =
|
|
991
|
+
const capsuleDir = resolveCapsuleDir(capsuleArg);
|
|
973
992
|
const api = deployApiUrl(args);
|
|
974
993
|
const metadata = await readDeployMetadata(capsuleDir);
|
|
975
994
|
|
|
@@ -1149,7 +1168,7 @@ This is a Lakebed capsule. Build the app inside this directory using the Lakebed
|
|
|
1149
1168
|
Run locally:
|
|
1150
1169
|
|
|
1151
1170
|
\`\`\`sh
|
|
1152
|
-
lakebed dev
|
|
1171
|
+
lakebed dev
|
|
1153
1172
|
\`\`\`
|
|
1154
1173
|
|
|
1155
1174
|
Deploy:
|
|
@@ -1311,6 +1330,7 @@ pnpm lakebed dev ${name}
|
|
|
1311
1330
|
async function newCommand(args) {
|
|
1312
1331
|
const [nameArg] = positionals(args);
|
|
1313
1332
|
const template = readArg(args, "--template", "todo");
|
|
1333
|
+
const shouldInitGit = !hasFlag(args, "--no-git");
|
|
1314
1334
|
|
|
1315
1335
|
if (template !== "todo") {
|
|
1316
1336
|
throw new Error(`Unknown template: ${template}`);
|
|
@@ -1334,6 +1354,51 @@ async function newCommand(args) {
|
|
|
1334
1354
|
}
|
|
1335
1355
|
|
|
1336
1356
|
console.log(`Created Lakebed capsule at ${targetDir}`);
|
|
1357
|
+
const gitStatus = shouldInitGit ? await initializeGitRepository(targetDir) : "Skipped git setup (--no-git).";
|
|
1358
|
+
console.log(gitStatus);
|
|
1359
|
+
console.log(`
|
|
1360
|
+
Next:
|
|
1361
|
+
cd ${shellQuote(name)}
|
|
1362
|
+
npx lakebed dev
|
|
1363
|
+
|
|
1364
|
+
deploy instantly for free with:
|
|
1365
|
+
npx lakebed deploy`);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
async function initializeGitRepository(targetDir) {
|
|
1369
|
+
if (await isInsideGitWorkTree(dirname(targetDir))) {
|
|
1370
|
+
return "Skipped git setup because the capsule is inside an existing git repository.";
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
try {
|
|
1374
|
+
await execFileAsync("git", ["init"], { cwd: targetDir });
|
|
1375
|
+
await execFileAsync("git", ["add", "."], { cwd: targetDir });
|
|
1376
|
+
await execFileAsync(
|
|
1377
|
+
"git",
|
|
1378
|
+
["-c", "user.name=Lakebed", "-c", "user.email=lakebed@example.invalid", "commit", "-m", "Initial Lakebed capsule"],
|
|
1379
|
+
{ cwd: targetDir }
|
|
1380
|
+
);
|
|
1381
|
+
return "Initialized git repository and created initial commit.";
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
return `Skipped git setup: ${error instanceof Error ? error.message : String(error)}`;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
async function isInsideGitWorkTree(cwd) {
|
|
1388
|
+
try {
|
|
1389
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd });
|
|
1390
|
+
return stdout.trim() === "true";
|
|
1391
|
+
} catch {
|
|
1392
|
+
return false;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
function shellQuote(value) {
|
|
1397
|
+
if (/^[A-Za-z0-9_./:-]+$/.test(value)) {
|
|
1398
|
+
return value;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
1337
1402
|
}
|
|
1338
1403
|
|
|
1339
1404
|
async function promptForCapsuleName() {
|
|
@@ -1396,7 +1461,7 @@ async function runMany(args) {
|
|
|
1396
1461
|
async function main() {
|
|
1397
1462
|
const [command, ...args] = process.argv.slice(2);
|
|
1398
1463
|
|
|
1399
|
-
if (command === "new") {
|
|
1464
|
+
if (command === "new" || command === "create") {
|
|
1400
1465
|
await newCommand(args);
|
|
1401
1466
|
return;
|
|
1402
1467
|
}
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LAKEBED_VERSION = "0.0.
|
|
1
|
+
export const LAKEBED_VERSION = "0.0.11";
|