dev-prism 0.6.0 → 0.7.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/README.md +143 -286
- package/bin/dev-prism.js +65 -87
- package/dist/{chunk-7YGOMAJG.js → chunk-3CIXBEXK.js} +22 -28
- package/dist/chunk-AHC6CD7F.js +92 -0
- package/dist/chunk-FQTS57VO.js +64 -0
- package/dist/chunk-GWQPK7MZ.js +50 -0
- package/dist/chunk-HDGBJGIH.js +55 -0
- package/dist/chunk-ILICQAU7.js +60 -0
- package/dist/chunk-IWZN6P6M.js +155 -0
- package/dist/chunk-KP56QH72.js +133 -0
- package/dist/{chunk-3Q454U3I.js → chunk-NJAITOCG.js} +0 -10
- package/dist/{chunk-25WQHUYW.js → chunk-TSNFAXVQ.js} +5 -12
- package/dist/chunk-VAPRJUC7.js +67 -0
- package/dist/chunk-VL56YPMK.js +45 -0
- package/dist/commands/claude.js +1 -1
- package/dist/commands/create.d.ts +1 -5
- package/dist/commands/create.js +5 -8
- package/dist/commands/destroy.d.ts +1 -1
- package/dist/commands/destroy.js +4 -6
- package/dist/commands/env.d.ts +7 -0
- package/dist/commands/env.js +9 -0
- package/dist/commands/info.js +4 -3
- package/dist/commands/list.js +2 -3
- package/dist/commands/prune.js +2 -6
- package/dist/commands/with-env.d.ts +3 -0
- package/dist/commands/with-env.js +9 -0
- package/dist/index.d.ts +9 -14
- package/dist/index.js +57 -73
- package/dist/lib/config.d.ts +4 -11
- package/dist/lib/config.js +1 -3
- package/dist/lib/db.d.ts +26 -0
- package/dist/lib/db.js +28 -0
- package/dist/lib/env.d.ts +7 -5
- package/dist/lib/env.js +9 -9
- package/dist/lib/worktree.d.ts +1 -2
- package/dist/lib/worktree.js +1 -3
- package/package.json +9 -6
- package/dist/chunk-24OM3LGM.js +0 -35
- package/dist/chunk-35SHBLIZ.js +0 -69
- package/dist/chunk-3ATDGV4Y.js +0 -22
- package/dist/chunk-3FYEGH2G.js +0 -217
- package/dist/chunk-3MSC3CGG.js +0 -78
- package/dist/chunk-3NW2OWIU.js +0 -78
- package/dist/chunk-3TRRZEFR.js +0 -38
- package/dist/chunk-4UNCSJRM.js +0 -70
- package/dist/chunk-5KDDYO6Y.js +0 -168
- package/dist/chunk-63II3EL4.js +0 -98
- package/dist/chunk-6YMQTISJ.js +0 -84
- package/dist/chunk-76LSQIZI.js +0 -31
- package/dist/chunk-7OSTLJLO.js +0 -219
- package/dist/chunk-7YEZWM6Y.js +0 -97
- package/dist/chunk-AEVARZQ4.js +0 -203
- package/dist/chunk-AIVPJ467.js +0 -70
- package/dist/chunk-AOM6BONB.js +0 -98
- package/dist/chunk-AW2FJGXA.js +0 -38
- package/dist/chunk-BXYXWNGH.js +0 -30
- package/dist/chunk-C4WLIOBR.js +0 -67
- package/dist/chunk-CUQVGZBX.js +0 -44
- package/dist/chunk-D6QWWXZD.js +0 -49
- package/dist/chunk-DQER5GNG.js +0 -72
- package/dist/chunk-DTE5YQMI.js +0 -41
- package/dist/chunk-EXRHG5KQ.js +0 -60
- package/dist/chunk-FKTFCSU7.js +0 -78
- package/dist/chunk-GBN67HYD.js +0 -57
- package/dist/chunk-GKXXK2ZH.js +0 -203
- package/dist/chunk-GWDGC2OE.js +0 -116
- package/dist/chunk-H3L73URT.js +0 -65
- package/dist/chunk-H4HPDIY3.js +0 -95
- package/dist/chunk-HCCZKLC4.js +0 -64
- package/dist/chunk-HZBJF67X.js +0 -60
- package/dist/chunk-HZUN6NRB.js +0 -70
- package/dist/chunk-I3U6JK77.js +0 -66
- package/dist/chunk-J36LRUXM.js +0 -60
- package/dist/chunk-JHR4WADC.js +0 -200
- package/dist/chunk-JIU574KX.js +0 -41
- package/dist/chunk-JMKE3ZKI.js +0 -61
- package/dist/chunk-JZ2VPQXP.js +0 -132
- package/dist/chunk-KDYKLH6P.js +0 -40
- package/dist/chunk-KZJE62TK.js +0 -203
- package/dist/chunk-LAOWFCQL.js +0 -21
- package/dist/chunk-LDK6QMR6.js +0 -67
- package/dist/chunk-LEHA65A7.js +0 -59
- package/dist/chunk-LNIOSGC4.js +0 -78
- package/dist/chunk-LOVO4P3Y.js +0 -41
- package/dist/chunk-MRBTH5PL.js +0 -66
- package/dist/chunk-NNVP5F6I.js +0 -77
- package/dist/chunk-OL25TBYX.js +0 -67
- package/dist/chunk-OOJ6YOGS.js +0 -53
- package/dist/chunk-OPEZFBBI.js +0 -219
- package/dist/chunk-P3ETW2KK.js +0 -166
- package/dist/chunk-PJKUD2N2.js +0 -22
- package/dist/chunk-PKC2ZED2.js +0 -168
- package/dist/chunk-PS76Q3HD.js +0 -168
- package/dist/chunk-Q5DPX4WL.js +0 -219
- package/dist/chunk-QSG5CXPX.js +0 -171
- package/dist/chunk-QUMZI5KK.js +0 -98
- package/dist/chunk-RC2AUYZ7.js +0 -49
- package/dist/chunk-RQ245R7T.js +0 -67
- package/dist/chunk-SD3TON6N.js +0 -32
- package/dist/chunk-SEKH4ZV6.js +0 -60
- package/dist/chunk-SMFAL2VP.js +0 -69
- package/dist/chunk-SSQ7XBY2.js +0 -30
- package/dist/chunk-SUMJLXT7.js +0 -30
- package/dist/chunk-UHI2QJFI.js +0 -200
- package/dist/chunk-UKYQN4A3.js +0 -38
- package/dist/chunk-URGGS3XM.js +0 -95
- package/dist/chunk-VR3QWHHB.js +0 -57
- package/dist/chunk-VUNPVDSO.js +0 -74
- package/dist/chunk-VXP2SPRI.js +0 -51
- package/dist/chunk-W54CPPSK.js +0 -217
- package/dist/chunk-X2PXZRYU.js +0 -41
- package/dist/chunk-X5A6H4Q7.js +0 -70
- package/dist/chunk-X6FHBEAS.js +0 -200
- package/dist/chunk-XUWQUDLT.js +0 -67
- package/dist/chunk-Y3GR6XK7.js +0 -71
- package/dist/chunk-YSO3IDZZ.js +0 -40
- package/dist/chunk-YY5DA35Z.js +0 -40
- package/dist/chunk-Z2ISJMLW.js +0 -92
- package/dist/chunk-ZKHNUDSL.js +0 -119
- package/dist/commands/logs.d.ts +0 -8
- package/dist/commands/logs.js +0 -9
- package/dist/commands/start.d.ts +0 -7
- package/dist/commands/start.js +0 -10
- package/dist/commands/stop-all.d.ts +0 -3
- package/dist/commands/stop-all.js +0 -8
- package/dist/commands/stop.d.ts +0 -3
- package/dist/commands/stop.js +0 -8
- package/dist/lib/compose.d.ts +0 -12
- package/dist/lib/compose.js +0 -12
- package/dist/lib/config.test.d.ts +0 -1
- package/dist/lib/config.test.js +0 -32
- package/dist/lib/docker-inspect.d.ts +0 -24
- package/dist/lib/docker-inspect.js +0 -16
- package/dist/lib/docker.d.ts +0 -12
- package/dist/lib/docker.js +0 -14
- package/dist/lib/env.test.d.ts +0 -1
- package/dist/lib/env.test.js +0 -68
- package/dist/lib/ports.d.ts +0 -6
- package/dist/lib/ports.js +0 -8
- package/dist/lib/ports.test.d.ts +0 -1
- package/dist/lib/ports.test.js +0 -61
- package/dist/lib/session.d.ts +0 -16
- package/dist/lib/session.js +0 -13
- package/dist/lib/store.d.ts +0 -46
- package/dist/lib/store.js +0 -6
- package/dist/lib/store.test.d.ts +0 -1
- package/dist/lib/store.test.js +0 -205
- package/dist/lib/worktree.test.d.ts +0 -1
- package/dist/lib/worktree.test.js +0 -41
package/dist/chunk-DTE5YQMI.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listActiveSessions
|
|
3
|
-
} from "./chunk-DQER5GNG.js";
|
|
4
|
-
|
|
5
|
-
// src/commands/stop-all.ts
|
|
6
|
-
import { existsSync, unlinkSync } from "fs";
|
|
7
|
-
import { resolve } from "path";
|
|
8
|
-
import chalk from "chalk";
|
|
9
|
-
import { execa } from "execa";
|
|
10
|
-
async function stopAllSessions() {
|
|
11
|
-
const sessions = await listActiveSessions();
|
|
12
|
-
if (sessions.length === 0) {
|
|
13
|
-
console.log(chalk.gray("No active sessions found."));
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
console.log(chalk.blue(`Stopping ${sessions.length} session(s)...
|
|
17
|
-
`));
|
|
18
|
-
for (const session of sessions) {
|
|
19
|
-
console.log(chalk.gray(` Stopping session in ${session.workingDir}...`));
|
|
20
|
-
try {
|
|
21
|
-
await execa(
|
|
22
|
-
"docker",
|
|
23
|
-
["compose", "-f", "docker-compose.session.yml", "--env-file", ".env.session", "stop"],
|
|
24
|
-
{ cwd: session.workingDir, stdio: "pipe" }
|
|
25
|
-
);
|
|
26
|
-
const envPath = resolve(session.workingDir, ".env.session");
|
|
27
|
-
if (existsSync(envPath)) {
|
|
28
|
-
unlinkSync(envPath);
|
|
29
|
-
}
|
|
30
|
-
console.log(chalk.green(` Stopped: ${session.workingDir}`));
|
|
31
|
-
} catch {
|
|
32
|
-
console.log(chalk.yellow(` Warning: Could not stop session in ${session.workingDir}`));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
console.log(chalk.green(`
|
|
36
|
-
Stopped ${sessions.length} session(s).`));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export {
|
|
40
|
-
stopAllSessions
|
|
41
|
-
};
|
package/dist/chunk-EXRHG5KQ.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isRunning
|
|
3
|
-
} from "./chunk-GBN67HYD.js";
|
|
4
|
-
import {
|
|
5
|
-
SessionStore
|
|
6
|
-
} from "./chunk-ZKHNUDSL.js";
|
|
7
|
-
|
|
8
|
-
// src/commands/stop-all.ts
|
|
9
|
-
import { existsSync } from "fs";
|
|
10
|
-
import { resolve } from "path";
|
|
11
|
-
import chalk from "chalk";
|
|
12
|
-
import { execa } from "execa";
|
|
13
|
-
async function stopAllSessions() {
|
|
14
|
-
const store = new SessionStore();
|
|
15
|
-
let sessions;
|
|
16
|
-
try {
|
|
17
|
-
sessions = store.listAll();
|
|
18
|
-
} finally {
|
|
19
|
-
store.close();
|
|
20
|
-
}
|
|
21
|
-
if (sessions.length === 0) {
|
|
22
|
-
console.log(chalk.gray("No sessions found."));
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const runningSessions = [];
|
|
26
|
-
for (const session of sessions) {
|
|
27
|
-
const envFile = resolve(session.session_dir, ".env.session");
|
|
28
|
-
if (existsSync(envFile)) {
|
|
29
|
-
const running = await isRunning({ cwd: session.session_dir });
|
|
30
|
-
if (running) {
|
|
31
|
-
runningSessions.push({ sessionId: session.session_id, path: session.session_dir, projectRoot: session.project_root });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (runningSessions.length === 0) {
|
|
36
|
-
console.log(chalk.gray("No running sessions found."));
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
console.log(chalk.blue(`Stopping ${runningSessions.length} running session(s)...
|
|
40
|
-
`));
|
|
41
|
-
for (const session of runningSessions) {
|
|
42
|
-
console.log(chalk.gray(` Stopping session ${session.sessionId}...`));
|
|
43
|
-
try {
|
|
44
|
-
await execa(
|
|
45
|
-
"docker",
|
|
46
|
-
["compose", "-f", "docker-compose.session.yml", "--env-file", ".env.session", "stop"],
|
|
47
|
-
{ cwd: session.path, stdio: "inherit" }
|
|
48
|
-
);
|
|
49
|
-
console.log(chalk.green(` Session ${session.sessionId} stopped.`));
|
|
50
|
-
} catch {
|
|
51
|
-
console.log(chalk.yellow(` Warning: Could not stop session ${session.sessionId}`));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
console.log(chalk.green(`
|
|
55
|
-
Stopped ${runningSessions.length} session(s).`));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export {
|
|
59
|
-
stopAllSessions
|
|
60
|
-
};
|
package/dist/chunk-FKTFCSU7.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// src/lib/worktree.ts
|
|
2
|
-
import { existsSync, rmSync } from "fs";
|
|
3
|
-
import { execa } from "execa";
|
|
4
|
-
async function branchExists(projectRoot, branchName) {
|
|
5
|
-
try {
|
|
6
|
-
await execa("git", ["rev-parse", "--verify", branchName], {
|
|
7
|
-
cwd: projectRoot,
|
|
8
|
-
stdio: "pipe"
|
|
9
|
-
});
|
|
10
|
-
return true;
|
|
11
|
-
} catch {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function findNextSessionId(usedIds) {
|
|
16
|
-
for (let i = 1; i <= 999; i++) {
|
|
17
|
-
const sessionId = String(i).padStart(3, "0");
|
|
18
|
-
if (!usedIds.has(sessionId)) {
|
|
19
|
-
return sessionId;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
throw new Error("No available session IDs (001-999 all in use)");
|
|
23
|
-
}
|
|
24
|
-
function generateDefaultBranchName(sessionId) {
|
|
25
|
-
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
26
|
-
return `session/${today}/${sessionId}`;
|
|
27
|
-
}
|
|
28
|
-
async function createWorktree(projectRoot, sessionDir, branchName) {
|
|
29
|
-
if (existsSync(sessionDir)) {
|
|
30
|
-
try {
|
|
31
|
-
await execa("git", ["worktree", "remove", "--force", sessionDir], {
|
|
32
|
-
cwd: projectRoot,
|
|
33
|
-
stdio: "pipe"
|
|
34
|
-
});
|
|
35
|
-
} catch {
|
|
36
|
-
rmSync(sessionDir, { recursive: true, force: true });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const exists = await branchExists(projectRoot, branchName);
|
|
40
|
-
if (exists) {
|
|
41
|
-
await execa("git", ["worktree", "add", sessionDir, branchName], {
|
|
42
|
-
cwd: projectRoot,
|
|
43
|
-
stdio: "inherit"
|
|
44
|
-
});
|
|
45
|
-
} else {
|
|
46
|
-
await execa("git", ["worktree", "add", sessionDir, "-b", branchName, "HEAD"], {
|
|
47
|
-
cwd: projectRoot,
|
|
48
|
-
stdio: "inherit"
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function removeWorktree(projectRoot, sessionDir, branchName) {
|
|
53
|
-
if (existsSync(sessionDir)) {
|
|
54
|
-
try {
|
|
55
|
-
await execa("git", ["worktree", "remove", "--force", sessionDir], {
|
|
56
|
-
cwd: projectRoot,
|
|
57
|
-
stdio: "inherit"
|
|
58
|
-
});
|
|
59
|
-
} catch {
|
|
60
|
-
rmSync(sessionDir, { recursive: true, force: true });
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
await execa("git", ["branch", "-D", branchName], {
|
|
65
|
-
cwd: projectRoot,
|
|
66
|
-
stdio: "pipe"
|
|
67
|
-
// Don't show output, branch might not exist
|
|
68
|
-
});
|
|
69
|
-
} catch {
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export {
|
|
74
|
-
findNextSessionId,
|
|
75
|
-
generateDefaultBranchName,
|
|
76
|
-
createWorktree,
|
|
77
|
-
removeWorktree
|
|
78
|
-
};
|
package/dist/chunk-GBN67HYD.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// src/lib/docker.ts
|
|
2
|
-
import { execa } from "execa";
|
|
3
|
-
var COMPOSE_FILE = "docker-compose.session.yml";
|
|
4
|
-
var ENV_FILE = ".env.session";
|
|
5
|
-
async function compose(args, options) {
|
|
6
|
-
const profileFlags = options.profiles?.flatMap((p) => ["--profile", p]) ?? [];
|
|
7
|
-
const fullArgs = [
|
|
8
|
-
"compose",
|
|
9
|
-
"-f",
|
|
10
|
-
COMPOSE_FILE,
|
|
11
|
-
"--env-file",
|
|
12
|
-
ENV_FILE,
|
|
13
|
-
...profileFlags,
|
|
14
|
-
...args
|
|
15
|
-
];
|
|
16
|
-
return execa("docker", fullArgs, {
|
|
17
|
-
cwd: options.cwd,
|
|
18
|
-
stdio: "inherit"
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
async function up(options) {
|
|
22
|
-
const detach = options.detach !== false;
|
|
23
|
-
const args = detach ? ["up", "-d", "--build"] : ["up", "--build"];
|
|
24
|
-
await compose(args, options);
|
|
25
|
-
}
|
|
26
|
-
async function logs(options) {
|
|
27
|
-
await compose(["logs", "-f", "--tail=50"], options);
|
|
28
|
-
}
|
|
29
|
-
async function down(options) {
|
|
30
|
-
await compose(["down", "-v"], options);
|
|
31
|
-
}
|
|
32
|
-
async function ps(options) {
|
|
33
|
-
const result = await execa(
|
|
34
|
-
"docker",
|
|
35
|
-
["compose", "-f", COMPOSE_FILE, "--env-file", ENV_FILE, "ps", "--format", "json"],
|
|
36
|
-
{ cwd: options.cwd, reject: false }
|
|
37
|
-
);
|
|
38
|
-
return result.stdout;
|
|
39
|
-
}
|
|
40
|
-
async function isRunning(options) {
|
|
41
|
-
try {
|
|
42
|
-
const output = await ps(options);
|
|
43
|
-
if (!output.trim()) return false;
|
|
44
|
-
const services = output.trim().split("\n").map((line) => JSON.parse(line));
|
|
45
|
-
return services.some((s) => s.State === "running");
|
|
46
|
-
} catch {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export {
|
|
52
|
-
up,
|
|
53
|
-
logs,
|
|
54
|
-
down,
|
|
55
|
-
ps,
|
|
56
|
-
isRunning
|
|
57
|
-
};
|
package/dist/chunk-GKXXK2ZH.js
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
writeAppEnvFiles,
|
|
3
|
-
writeEnvFile
|
|
4
|
-
} from "./chunk-J36LRUXM.js";
|
|
5
|
-
import {
|
|
6
|
-
calculatePorts,
|
|
7
|
-
formatPortsTable
|
|
8
|
-
} from "./chunk-3ATDGV4Y.js";
|
|
9
|
-
import {
|
|
10
|
-
createWorktree,
|
|
11
|
-
findNextSessionId,
|
|
12
|
-
generateDefaultBranchName,
|
|
13
|
-
removeWorktree
|
|
14
|
-
} from "./chunk-Y3GR6XK7.js";
|
|
15
|
-
import {
|
|
16
|
-
down,
|
|
17
|
-
logs,
|
|
18
|
-
up
|
|
19
|
-
} from "./chunk-GBN67HYD.js";
|
|
20
|
-
import {
|
|
21
|
-
getSessionDir,
|
|
22
|
-
getSessionsDir,
|
|
23
|
-
loadConfig
|
|
24
|
-
} from "./chunk-25WQHUYW.js";
|
|
25
|
-
import {
|
|
26
|
-
SessionStore
|
|
27
|
-
} from "./chunk-H4HPDIY3.js";
|
|
28
|
-
|
|
29
|
-
// src/commands/create.ts
|
|
30
|
-
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync } from "fs";
|
|
31
|
-
import { basename, join } from "path";
|
|
32
|
-
import chalk from "chalk";
|
|
33
|
-
import { execa } from "execa";
|
|
34
|
-
function updateEnvDatabaseUrl(envPath, newDbUrl) {
|
|
35
|
-
if (!existsSync(envPath)) return;
|
|
36
|
-
let content = readFileSync(envPath, "utf-8");
|
|
37
|
-
if (content.includes("DATABASE_URL=")) {
|
|
38
|
-
content = content.replace(/^DATABASE_URL=.*/m, `DATABASE_URL=${newDbUrl}`);
|
|
39
|
-
} else {
|
|
40
|
-
content += `
|
|
41
|
-
DATABASE_URL=${newDbUrl}
|
|
42
|
-
`;
|
|
43
|
-
}
|
|
44
|
-
writeFileSync(envPath, content);
|
|
45
|
-
}
|
|
46
|
-
async function createSession(projectRoot, sessionId, options) {
|
|
47
|
-
const config = await loadConfig(projectRoot);
|
|
48
|
-
const sessionsDir = getSessionsDir(config, projectRoot);
|
|
49
|
-
const store = new SessionStore();
|
|
50
|
-
try {
|
|
51
|
-
if (!sessionId) {
|
|
52
|
-
sessionId = findNextSessionId(store.getUsedSessionIds(projectRoot));
|
|
53
|
-
console.log(chalk.gray(`Auto-assigned session ID: ${sessionId}`));
|
|
54
|
-
}
|
|
55
|
-
if (!/^\d{3}$/.test(sessionId)) {
|
|
56
|
-
console.error(chalk.red("Error: Session ID must be exactly 3 digits (001-999)"));
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
const inPlace = options.inPlace ?? false;
|
|
60
|
-
const branchName = options.branch || generateDefaultBranchName(sessionId);
|
|
61
|
-
const mode = options.mode || "docker";
|
|
62
|
-
console.log(chalk.blue(`Creating session ${sessionId} (${mode} mode${inPlace ? ", in-place" : ""})...`));
|
|
63
|
-
if (!inPlace) {
|
|
64
|
-
console.log(chalk.gray(`Branch: ${branchName}`));
|
|
65
|
-
}
|
|
66
|
-
const ports = calculatePorts(config, sessionId);
|
|
67
|
-
console.log(chalk.gray("\nPorts:"));
|
|
68
|
-
console.log(chalk.gray(formatPortsTable(ports)));
|
|
69
|
-
const sessionDir = inPlace ? projectRoot : getSessionDir(config, projectRoot, sessionId);
|
|
70
|
-
try {
|
|
71
|
-
store.reserve({
|
|
72
|
-
sessionId,
|
|
73
|
-
projectRoot,
|
|
74
|
-
sessionDir,
|
|
75
|
-
branch: inPlace ? "" : branchName,
|
|
76
|
-
mode,
|
|
77
|
-
inPlace
|
|
78
|
-
});
|
|
79
|
-
} catch {
|
|
80
|
-
console.error(chalk.red(`Error: Session ${sessionId} is already being created by another process.`));
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
if (inPlace) {
|
|
85
|
-
console.log(chalk.blue("\nUsing current directory (in-place mode)..."));
|
|
86
|
-
console.log(chalk.green(` Directory: ${sessionDir}`));
|
|
87
|
-
} else {
|
|
88
|
-
if (!existsSync(sessionsDir)) {
|
|
89
|
-
mkdirSync(sessionsDir, { recursive: true });
|
|
90
|
-
}
|
|
91
|
-
console.log(chalk.blue("\nCreating git worktree..."));
|
|
92
|
-
await createWorktree(projectRoot, sessionDir, branchName);
|
|
93
|
-
console.log(chalk.green(` Created: ${sessionDir}`));
|
|
94
|
-
const sessionDbUrl = `postgresql://postgres:postgres@localhost:${ports.POSTGRES_PORT}/postgres`;
|
|
95
|
-
const envFilesToCopy = config.envFiles ?? [];
|
|
96
|
-
for (const envFile of envFilesToCopy) {
|
|
97
|
-
const srcPath = join(projectRoot, envFile);
|
|
98
|
-
const destPath = join(sessionDir, envFile);
|
|
99
|
-
if (existsSync(srcPath)) {
|
|
100
|
-
copyFileSync(srcPath, destPath);
|
|
101
|
-
updateEnvDatabaseUrl(destPath, sessionDbUrl);
|
|
102
|
-
console.log(chalk.green(` Copied: ${envFile} (updated DATABASE_URL)`));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
console.log(chalk.blue("\nGenerating .env.session..."));
|
|
107
|
-
const projectName = config.projectName ?? basename(projectRoot);
|
|
108
|
-
const envPath = writeEnvFile(sessionDir, sessionId, ports, projectName);
|
|
109
|
-
console.log(chalk.green(` Written: ${envPath}`));
|
|
110
|
-
const appEnvFiles = writeAppEnvFiles(config, sessionDir, sessionId, ports);
|
|
111
|
-
for (const file of appEnvFiles) {
|
|
112
|
-
console.log(chalk.green(` Written: ${file}`));
|
|
113
|
-
}
|
|
114
|
-
console.log(chalk.blue("\nStarting Docker services..."));
|
|
115
|
-
let profiles2;
|
|
116
|
-
if (mode === "docker") {
|
|
117
|
-
const allApps = config.apps ?? [];
|
|
118
|
-
const excludeApps = options.without ?? [];
|
|
119
|
-
profiles2 = allApps.filter((app) => !excludeApps.includes(app));
|
|
120
|
-
if (excludeApps.length > 0) {
|
|
121
|
-
console.log(chalk.gray(` Excluding apps: ${excludeApps.join(", ")}`));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
await up({ cwd: sessionDir, profiles: profiles2 });
|
|
125
|
-
console.log(chalk.blue("Waiting for services to be ready..."));
|
|
126
|
-
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
127
|
-
if (config.setup.length > 0) {
|
|
128
|
-
console.log(chalk.blue("\nRunning setup commands..."));
|
|
129
|
-
const setupEnv = {
|
|
130
|
-
...process.env,
|
|
131
|
-
SESSION_ID: sessionId,
|
|
132
|
-
// Add DATABASE_URL for db commands
|
|
133
|
-
DATABASE_URL: `postgresql://postgres:postgres@localhost:${ports.POSTGRES_PORT}/postgres`
|
|
134
|
-
};
|
|
135
|
-
for (const [name, port] of Object.entries(ports)) {
|
|
136
|
-
setupEnv[name] = String(port);
|
|
137
|
-
}
|
|
138
|
-
for (const cmd of config.setup) {
|
|
139
|
-
console.log(chalk.gray(` Running: ${cmd}`));
|
|
140
|
-
const [command, ...args] = cmd.split(" ");
|
|
141
|
-
try {
|
|
142
|
-
await execa(command, args, {
|
|
143
|
-
cwd: sessionDir,
|
|
144
|
-
stdio: "inherit",
|
|
145
|
-
env: setupEnv
|
|
146
|
-
});
|
|
147
|
-
} catch {
|
|
148
|
-
console.warn(chalk.yellow(` Warning: Command failed: ${cmd}`));
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.error(chalk.red("Session creation failed. Cleaning up..."));
|
|
154
|
-
store.remove(projectRoot, sessionId);
|
|
155
|
-
try {
|
|
156
|
-
await down({ cwd: sessionDir });
|
|
157
|
-
} catch {
|
|
158
|
-
}
|
|
159
|
-
if (!inPlace) {
|
|
160
|
-
try {
|
|
161
|
-
await removeWorktree(projectRoot, sessionDir, branchName);
|
|
162
|
-
} catch {
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
throw error;
|
|
166
|
-
}
|
|
167
|
-
console.log(chalk.green(`
|
|
168
|
-
Session ${sessionId} ready!`));
|
|
169
|
-
console.log(chalk.gray(`Directory: ${sessionDir}`));
|
|
170
|
-
if (mode === "docker") {
|
|
171
|
-
console.log(chalk.gray("\nDocker mode - all services in containers."));
|
|
172
|
-
console.log(chalk.gray("View logs: docker compose -f docker-compose.session.yml logs -f"));
|
|
173
|
-
} else {
|
|
174
|
-
console.log(chalk.gray("\nNative mode - run apps with: pnpm dev"));
|
|
175
|
-
}
|
|
176
|
-
console.log(chalk.gray("\nPorts:"));
|
|
177
|
-
for (const [name, port] of Object.entries(ports)) {
|
|
178
|
-
console.log(chalk.cyan(` ${name}: http://localhost:${port}`));
|
|
179
|
-
}
|
|
180
|
-
if (options.detach === false) {
|
|
181
|
-
console.log(chalk.blue("\nStreaming logs (Ctrl+C to stop)..."));
|
|
182
|
-
console.log(chalk.gray("\u2500".repeat(60)));
|
|
183
|
-
try {
|
|
184
|
-
await logs({ cwd: sessionDir, profiles });
|
|
185
|
-
} catch (error) {
|
|
186
|
-
const execaError = error;
|
|
187
|
-
if (execaError.signal === "SIGINT") {
|
|
188
|
-
console.log(chalk.gray("\n\u2500".repeat(60)));
|
|
189
|
-
console.log(chalk.yellow("\nLog streaming stopped. Services are still running."));
|
|
190
|
-
console.log(chalk.gray(`Resume logs: cd ${sessionDir} && docker compose -f docker-compose.session.yml --env-file .env.session logs -f`));
|
|
191
|
-
} else {
|
|
192
|
-
throw error;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
} finally {
|
|
197
|
-
store.close();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export {
|
|
202
|
-
createSession
|
|
203
|
-
};
|
package/dist/chunk-GWDGC2OE.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
// src/lib/worktree.ts
|
|
2
|
-
import { existsSync, rmSync } from "fs";
|
|
3
|
-
import { execa } from "execa";
|
|
4
|
-
async function branchExists(projectRoot, branchName) {
|
|
5
|
-
try {
|
|
6
|
-
await execa("git", ["rev-parse", "--verify", branchName], {
|
|
7
|
-
cwd: projectRoot,
|
|
8
|
-
stdio: "pipe"
|
|
9
|
-
});
|
|
10
|
-
return true;
|
|
11
|
-
} catch {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
async function findNextSessionId(projectRoot, sessionsDir) {
|
|
16
|
-
const sessions = await getSessionWorktrees(projectRoot);
|
|
17
|
-
const usedIds = new Set(sessions.map((s) => parseInt(s.sessionId, 10)));
|
|
18
|
-
for (let i = 1; i <= 999; i++) {
|
|
19
|
-
if (!usedIds.has(i)) {
|
|
20
|
-
const sessionId = String(i).padStart(3, "0");
|
|
21
|
-
if (sessionsDir) {
|
|
22
|
-
const sessionDir = `${sessionsDir}/session-${sessionId}`;
|
|
23
|
-
if (existsSync(sessionDir)) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return sessionId;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
throw new Error("No available session IDs (001-999 all in use)");
|
|
31
|
-
}
|
|
32
|
-
function generateDefaultBranchName(sessionId) {
|
|
33
|
-
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
34
|
-
return `session/${today}/${sessionId}`;
|
|
35
|
-
}
|
|
36
|
-
async function createWorktree(projectRoot, sessionDir, branchName) {
|
|
37
|
-
if (existsSync(sessionDir)) {
|
|
38
|
-
throw new Error(`Session directory already exists: ${sessionDir}`);
|
|
39
|
-
}
|
|
40
|
-
const exists = await branchExists(projectRoot, branchName);
|
|
41
|
-
if (exists) {
|
|
42
|
-
await execa("git", ["worktree", "add", sessionDir, branchName], {
|
|
43
|
-
cwd: projectRoot,
|
|
44
|
-
stdio: "inherit"
|
|
45
|
-
});
|
|
46
|
-
} else {
|
|
47
|
-
await execa("git", ["worktree", "add", sessionDir, "-b", branchName, "HEAD"], {
|
|
48
|
-
cwd: projectRoot,
|
|
49
|
-
stdio: "inherit"
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async function removeWorktree(projectRoot, sessionDir, branchName) {
|
|
54
|
-
if (existsSync(sessionDir)) {
|
|
55
|
-
try {
|
|
56
|
-
await execa("git", ["worktree", "remove", "--force", sessionDir], {
|
|
57
|
-
cwd: projectRoot,
|
|
58
|
-
stdio: "inherit"
|
|
59
|
-
});
|
|
60
|
-
} catch {
|
|
61
|
-
rmSync(sessionDir, { recursive: true, force: true });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
await execa("git", ["branch", "-D", branchName], {
|
|
66
|
-
cwd: projectRoot,
|
|
67
|
-
stdio: "pipe"
|
|
68
|
-
// Don't show output, branch might not exist
|
|
69
|
-
});
|
|
70
|
-
} catch {
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
async function listWorktrees(projectRoot) {
|
|
74
|
-
const { stdout } = await execa("git", ["worktree", "list", "--porcelain"], {
|
|
75
|
-
cwd: projectRoot
|
|
76
|
-
});
|
|
77
|
-
const worktrees = [];
|
|
78
|
-
let current = null;
|
|
79
|
-
for (const line of stdout.split("\n")) {
|
|
80
|
-
if (line.startsWith("worktree ")) {
|
|
81
|
-
if (current) {
|
|
82
|
-
worktrees.push(current);
|
|
83
|
-
}
|
|
84
|
-
current = { path: line.replace("worktree ", ""), branch: "", commit: "" };
|
|
85
|
-
} else if (line.startsWith("HEAD ") && current) {
|
|
86
|
-
current.commit = line.replace("HEAD ", "");
|
|
87
|
-
} else if (line.startsWith("branch ") && current) {
|
|
88
|
-
current.branch = line.replace("branch refs/heads/", "");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (current) {
|
|
92
|
-
worktrees.push(current);
|
|
93
|
-
}
|
|
94
|
-
return worktrees;
|
|
95
|
-
}
|
|
96
|
-
async function getSessionWorktrees(projectRoot) {
|
|
97
|
-
const worktrees = await listWorktrees(projectRoot);
|
|
98
|
-
const sessionPattern = /\/session-(\d{3})$/;
|
|
99
|
-
return worktrees.filter((wt) => sessionPattern.test(wt.path)).map((wt) => {
|
|
100
|
-
const match = wt.path.match(sessionPattern);
|
|
101
|
-
return {
|
|
102
|
-
sessionId: match[1],
|
|
103
|
-
path: wt.path,
|
|
104
|
-
branch: wt.branch
|
|
105
|
-
};
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export {
|
|
110
|
-
findNextSessionId,
|
|
111
|
-
generateDefaultBranchName,
|
|
112
|
-
createWorktree,
|
|
113
|
-
removeWorktree,
|
|
114
|
-
listWorktrees,
|
|
115
|
-
getSessionWorktrees
|
|
116
|
-
};
|
package/dist/chunk-H3L73URT.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// src/lib/compose.ts
|
|
2
|
-
import { writeFileSync } from "fs";
|
|
3
|
-
import { resolve } from "path";
|
|
4
|
-
import { createHash } from "crypto";
|
|
5
|
-
function generateComposeFile(workingDir, projectName, services) {
|
|
6
|
-
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7
|
-
const dirHash = createHash("md5").update(workingDir).digest("hex").substring(0, 8);
|
|
8
|
-
const composeProjectName = `${projectName}-${dirHash}`;
|
|
9
|
-
const lines = [
|
|
10
|
-
"# Auto-generated by dev-prism - DO NOT EDIT",
|
|
11
|
-
'version: "3.8"',
|
|
12
|
-
"",
|
|
13
|
-
"x-dev-prism-labels: &dev-prism-labels",
|
|
14
|
-
' dev-prism.managed: "true"',
|
|
15
|
-
` dev-prism.working_dir: "${workingDir}"`,
|
|
16
|
-
` dev-prism.session_id: "${workingDir}"`,
|
|
17
|
-
` dev-prism.created_at: "${createdAt}"`,
|
|
18
|
-
"",
|
|
19
|
-
"services:"
|
|
20
|
-
];
|
|
21
|
-
for (const service of services) {
|
|
22
|
-
lines.push(` ${service.name}:`);
|
|
23
|
-
lines.push(` extends:`);
|
|
24
|
-
lines.push(` file: docker-compose.yml`);
|
|
25
|
-
lines.push(` service: ${service.name}`);
|
|
26
|
-
lines.push(` ports:`);
|
|
27
|
-
lines.push(` - "0:${service.internalPort}" # Random host port`);
|
|
28
|
-
lines.push(` labels:`);
|
|
29
|
-
lines.push(` <<: *dev-prism-labels`);
|
|
30
|
-
lines.push(` dev-prism.service: "${service.name}"`);
|
|
31
|
-
lines.push(` dev-prism.internal_port: "${service.internalPort}"`);
|
|
32
|
-
lines.push(``);
|
|
33
|
-
}
|
|
34
|
-
lines.unshift(`# Compose project name: ${composeProjectName}`);
|
|
35
|
-
lines.unshift("");
|
|
36
|
-
return lines.join("\n");
|
|
37
|
-
}
|
|
38
|
-
function writeComposeFile(workingDir, projectName, services) {
|
|
39
|
-
const content = generateComposeFile(workingDir, projectName, services);
|
|
40
|
-
const filePath = resolve(workingDir, "docker-compose.session.yml");
|
|
41
|
-
writeFileSync(filePath, content, "utf-8");
|
|
42
|
-
return filePath;
|
|
43
|
-
}
|
|
44
|
-
function generateEnvStub(workingDir, projectName) {
|
|
45
|
-
const composeProjectName = getComposeProjectName(workingDir, projectName);
|
|
46
|
-
const lines = [
|
|
47
|
-
"# Auto-generated by dev-prism",
|
|
48
|
-
`COMPOSE_PROJECT_NAME=${composeProjectName}`,
|
|
49
|
-
`SESSION_DIR=${workingDir}`,
|
|
50
|
-
"",
|
|
51
|
-
"# Ports will be added after containers start"
|
|
52
|
-
];
|
|
53
|
-
return lines.join("\n") + "\n";
|
|
54
|
-
}
|
|
55
|
-
function getComposeProjectName(workingDir, projectName) {
|
|
56
|
-
const dirHash = createHash("md5").update(workingDir).digest("hex").substring(0, 8);
|
|
57
|
-
return `${projectName}-${dirHash}`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export {
|
|
61
|
-
generateComposeFile,
|
|
62
|
-
writeComposeFile,
|
|
63
|
-
generateEnvStub,
|
|
64
|
-
getComposeProjectName
|
|
65
|
-
};
|