@syedar/seedar-cli 1.2.0 → 1.3.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 +24 -3
- package/dist/cli.d.ts +21 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +110 -587
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +18 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +35 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/lifecycle.d.ts +4 -0
- package/dist/commands/lifecycle.d.ts.map +1 -0
- package/dist/commands/lifecycle.js +65 -0
- package/dist/commands/lifecycle.js.map +1 -0
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +24 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +243 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +5 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +166 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/docker/compose.d.ts +6 -0
- package/dist/docker/compose.d.ts.map +1 -0
- package/dist/docker/compose.js +55 -0
- package/dist/docker/compose.js.map +1 -0
- package/dist/docker/health.d.ts +3 -0
- package/dist/docker/health.d.ts.map +1 -0
- package/dist/docker/health.js +38 -0
- package/dist/docker/health.js.map +1 -0
- package/dist/docker/ports.d.ts.map +1 -0
- package/dist/docker/ports.js.map +1 -0
- package/dist/docker/prerequisites.d.ts +2 -0
- package/dist/docker/prerequisites.d.ts.map +1 -0
- package/dist/docker/prerequisites.js +12 -0
- package/dist/docker/prerequisites.js.map +1 -0
- package/dist/{process.d.ts → docker/process.d.ts} +2 -1
- package/dist/docker/process.d.ts.map +1 -0
- package/dist/{process.js → docker/process.js} +11 -0
- package/dist/docker/process.js.map +1 -0
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/install/config.d.ts +7 -0
- package/dist/install/config.d.ts.map +1 -0
- package/dist/install/config.js +82 -0
- package/dist/install/config.js.map +1 -0
- package/dist/install/flow.d.ts +11 -0
- package/dist/install/flow.d.ts.map +1 -0
- package/dist/install/flow.js +115 -0
- package/dist/install/flow.js.map +1 -0
- package/dist/install/output.d.ts +8 -0
- package/dist/install/output.d.ts.map +1 -0
- package/dist/install/output.js +39 -0
- package/dist/install/output.js.map +1 -0
- package/dist/install/ports.d.ts +8 -0
- package/dist/install/ports.d.ts.map +1 -0
- package/dist/install/ports.js +38 -0
- package/dist/install/ports.js.map +1 -0
- package/dist/install/prompts.d.ts +4 -0
- package/dist/install/prompts.d.ts.map +1 -0
- package/dist/install/prompts.js +204 -0
- package/dist/install/prompts.js.map +1 -0
- package/dist/runtime/guards.d.ts +3 -0
- package/dist/runtime/guards.d.ts.map +1 -0
- package/dist/runtime/guards.js +7 -0
- package/dist/runtime/guards.js.map +1 -0
- package/dist/{runtime.d.ts → runtime/index.d.ts} +3 -3
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/{runtime.js → runtime/index.js} +68 -11
- package/dist/runtime/index.js.map +1 -0
- package/dist/shared/constants.d.ts +23 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/{constants.js → shared/constants.js} +44 -4
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/logging.d.ts +3 -0
- package/dist/shared/logging.d.ts.map +1 -0
- package/dist/shared/logging.js +8 -0
- package/dist/shared/logging.js.map +1 -0
- package/dist/shared/package.d.ts +2 -0
- package/dist/shared/package.d.ts.map +1 -0
- package/dist/shared/package.js +2 -0
- package/dist/shared/package.js.map +1 -0
- package/dist/shared/time.d.ts +2 -0
- package/dist/shared/time.d.ts.map +1 -0
- package/dist/shared/time.js +4 -0
- package/dist/shared/time.js.map +1 -0
- package/dist/{types.d.ts → shared/types.d.ts} +9 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/ui.d.ts +7 -0
- package/dist/shared/ui.d.ts.map +1 -0
- package/dist/shared/ui.js +25 -0
- package/dist/shared/ui.js.map +1 -0
- package/package.json +12 -8
- package/dist/constants.d.ts +0 -17
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/ports.d.ts.map +0 -1
- package/dist/ports.js.map +0 -1
- package/dist/process.d.ts.map +0 -1
- package/dist/process.js.map +0 -1
- package/dist/prompts.d.ts +0 -4
- package/dist/prompts.d.ts.map +0 -1
- package/dist/prompts.js +0 -175
- package/dist/prompts.js.map +0 -1
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{ports.d.ts → docker/ports.d.ts} +0 -0
- /package/dist/{ports.js → docker/ports.js} +0 -0
- /package/dist/{types.js → shared/types.js} +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { writeCliLog } from "../shared/logging.js";
|
|
2
|
+
import { waitForServiceHealthy } from "../docker/health.js";
|
|
3
|
+
import { cleanupComposeServices, runComposeCommandWithCapturedOutput } from "../docker/compose.js";
|
|
4
|
+
import { runDockerCompose, runDockerComposeOrThrow } from "../docker/process.js";
|
|
5
|
+
import { writeRuntimeFiles } from "../runtime/index.js";
|
|
6
|
+
import { autoShiftConflictPort, findPortKeyByPort, getPortLabel, parseComposePortConflict } from "./ports.js";
|
|
7
|
+
import { printInstallDetail, printInstallStage, printInstallSuccess } from "./output.js";
|
|
8
|
+
export async function runMigrations(layout) {
|
|
9
|
+
const result = await runDockerCompose(layout, ["run", "--rm", "migrate"]);
|
|
10
|
+
if (result.code !== 0) {
|
|
11
|
+
const detail = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join("\n");
|
|
12
|
+
throw new Error(detail || "docker compose run --rm migrate 执行失败");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function runInstallFlow(layout, env) {
|
|
16
|
+
await startMysqlWithRetry(layout, env);
|
|
17
|
+
await startPostgres(layout);
|
|
18
|
+
printInstallStage("执行数据库迁移");
|
|
19
|
+
await runMigrations(layout);
|
|
20
|
+
await startServerAndWebWithRetry(layout, env);
|
|
21
|
+
}
|
|
22
|
+
export async function pullInstallImages(layout) {
|
|
23
|
+
await runDockerComposeOrThrow(layout, ["pull", "mysql", "postgres", "server", "web"], {
|
|
24
|
+
stdio: "inherit",
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export async function startMysqlWithRetry(layout, env) {
|
|
28
|
+
while (true) {
|
|
29
|
+
printInstallStage("启动 MySQL");
|
|
30
|
+
try {
|
|
31
|
+
await runComposeCommandWithCapturedOutput(layout, ["up", "-d", "mysql"], "docker compose up -d mysql 执行失败");
|
|
32
|
+
printInstallSuccess(`MySQL 容器已启动,等待健康检查,端口 ${env.MYSQL_PORT}`);
|
|
33
|
+
await waitForServiceHealthy(layout, "mysql");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const composeConflictPort = parseComposePortConflict(error);
|
|
38
|
+
if (!composeConflictPort) {
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
const conflictKey = findPortKeyByPort(env, composeConflictPort, ["MYSQL_PORT"]);
|
|
42
|
+
if (!conflictKey) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
await cleanupComposeServices(layout, ["mysql"]);
|
|
46
|
+
const shiftedTo = await autoShiftConflictPort(env, conflictKey, composeConflictPort);
|
|
47
|
+
await writeRuntimeFiles(layout, env);
|
|
48
|
+
printInstallDetail(`${getPortLabel(conflictKey)} ${composeConflictPort} 已冲突,自动避让到 ${shiftedTo},继续重试`);
|
|
49
|
+
await writeCliLog(layout, `mysql startup port shifted ${conflictKey}: ${composeConflictPort} -> ${shiftedTo}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export async function startPostgres(layout) {
|
|
54
|
+
printInstallStage("启动 PostgreSQL");
|
|
55
|
+
await runComposeCommandWithCapturedOutput(layout, ["up", "-d", "postgres"], "docker compose up -d postgres 执行失败");
|
|
56
|
+
await waitForServiceHealthy(layout, "postgres");
|
|
57
|
+
printInstallSuccess("PostgreSQL 容器已启动");
|
|
58
|
+
}
|
|
59
|
+
export async function startServerAndWebWithRetry(layout, env) {
|
|
60
|
+
while (true) {
|
|
61
|
+
printInstallStage("启动 Server 和 Web");
|
|
62
|
+
try {
|
|
63
|
+
await runComposeCommandWithCapturedOutput(layout, ["up", "-d", "server", "web"], "docker compose up -d server web 执行失败");
|
|
64
|
+
printInstallSuccess(`Server 端口 ${env.SERVER_PORT},Web 端口 ${env.WEB_PORT}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const composeConflictPort = parseComposePortConflict(error);
|
|
69
|
+
if (!composeConflictPort) {
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
const conflictKey = findPortKeyByPort(env, composeConflictPort, ["SERVER_PORT", "WEB_PORT"]) ??
|
|
73
|
+
findPortKeyByPort(env, composeConflictPort);
|
|
74
|
+
if (!conflictKey) {
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
await cleanupComposeServices(layout, ["server", "web"]);
|
|
78
|
+
const shiftedTo = await autoShiftConflictPort(env, conflictKey, composeConflictPort);
|
|
79
|
+
await writeRuntimeFiles(layout, env);
|
|
80
|
+
printInstallDetail(`${getPortLabel(conflictKey)} ${composeConflictPort} 已冲突,自动避让到 ${shiftedTo},继续重试`);
|
|
81
|
+
await writeCliLog(layout, `server/web startup port shifted ${conflictKey}: ${composeConflictPort} -> ${shiftedTo}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function runInstallFlowWithValidatedConfig(layout, env) {
|
|
86
|
+
await writeCliLog(layout, `start install target=${env.SEEDAR_VERSION}`);
|
|
87
|
+
printInstallStage("拉取镜像前确认");
|
|
88
|
+
printInstallDetail(`目标版本:${env.SEEDAR_VERSION}`);
|
|
89
|
+
printInstallDetail(`安装目录:${layout.installRoot}`);
|
|
90
|
+
printInstallStage("拉取镜像");
|
|
91
|
+
printInstallDetail("开始拉取 mysql、postgres、server、web 镜像");
|
|
92
|
+
await pullInstallImages(layout);
|
|
93
|
+
printInstallSuccess("镜像拉取完成");
|
|
94
|
+
await runInstallFlow(layout, env);
|
|
95
|
+
await writeCliLog(layout, `install completed version=${env.SEEDAR_VERSION}`);
|
|
96
|
+
}
|
|
97
|
+
export async function startRuntimeServices(layout, env) {
|
|
98
|
+
printInstallStage("启动服务");
|
|
99
|
+
printInstallDetail(`目标版本:${env.SEEDAR_VERSION}`);
|
|
100
|
+
await runInstallFlow(layout, env);
|
|
101
|
+
printInstallSuccess("服务已启动");
|
|
102
|
+
}
|
|
103
|
+
export async function stopRuntimeServices(layout) {
|
|
104
|
+
printInstallStage("停止服务");
|
|
105
|
+
const result = await runDockerCompose(layout, ["stop", "mysql", "postgres", "server", "web"]);
|
|
106
|
+
const detail = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join("\n");
|
|
107
|
+
if (detail) {
|
|
108
|
+
console.log(detail);
|
|
109
|
+
}
|
|
110
|
+
if (result.code !== 0) {
|
|
111
|
+
throw new Error(detail || "停止服务失败");
|
|
112
|
+
}
|
|
113
|
+
printInstallSuccess("mysql、postgres、server、web 已停止");
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/install/flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EnvConfig, RuntimeLayout } from "../shared/types.js";
|
|
2
|
+
export declare function printServiceEndpoints(env: EnvConfig): void;
|
|
3
|
+
export declare function printInstallSummary(layout: RuntimeLayout, env: EnvConfig): void;
|
|
4
|
+
export declare function printInstallStage(title: string): void;
|
|
5
|
+
export declare function printInstallDetail(message: string): void;
|
|
6
|
+
export declare function printInstallSuccess(message: string): void;
|
|
7
|
+
export declare function printInstallWarn(message: string): void;
|
|
8
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/install/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAenE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAM1D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAK/E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAExD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEtD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { renderInfo, renderStage, renderSuccess, renderWarn } from "../shared/ui.js";
|
|
2
|
+
function formatCheckpointTarget(connectionString) {
|
|
3
|
+
try {
|
|
4
|
+
const url = new URL(connectionString);
|
|
5
|
+
const host = url.hostname || "postgres";
|
|
6
|
+
const port = url.port || "5432";
|
|
7
|
+
const database = url.pathname.replace(/^\/+/, "") || "postgres";
|
|
8
|
+
return `${host}:${port}/${database}`;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return "unknown";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function printServiceEndpoints(env) {
|
|
15
|
+
console.log("服务端口:");
|
|
16
|
+
console.log(`- Web: http://localhost:${env.WEB_PORT}`);
|
|
17
|
+
console.log(`- Server: http://localhost:${env.SERVER_PORT}`);
|
|
18
|
+
console.log(`- MySQL: localhost:${env.MYSQL_PORT}`);
|
|
19
|
+
console.log(`- Checkpoint PG: ${formatCheckpointTarget(env.AI_CHECKPOINT_PG_URL)}`);
|
|
20
|
+
}
|
|
21
|
+
export function printInstallSummary(layout, env) {
|
|
22
|
+
console.log("Seedar 安装完成。");
|
|
23
|
+
console.log(`安装目录: ${layout.installRoot}`);
|
|
24
|
+
printServiceEndpoints(env);
|
|
25
|
+
console.log(`版本: ${env.SEEDAR_VERSION}`);
|
|
26
|
+
}
|
|
27
|
+
export function printInstallStage(title) {
|
|
28
|
+
console.log(renderStage(title));
|
|
29
|
+
}
|
|
30
|
+
export function printInstallDetail(message) {
|
|
31
|
+
console.log(renderInfo(message));
|
|
32
|
+
}
|
|
33
|
+
export function printInstallSuccess(message) {
|
|
34
|
+
console.log(renderSuccess(message));
|
|
35
|
+
}
|
|
36
|
+
export function printInstallWarn(message) {
|
|
37
|
+
console.log(renderWarn(message));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/install/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAErF,SAAS,sBAAsB,CAAC,gBAAwB;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,IAAI,UAAU,CAAC;QACxC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC;QAChE,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAc;IAClD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,2BAA2B,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,8BAA8B,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,oBAAoB,sBAAsB,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAqB,EAAE,GAAc;IACvE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3C,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EnvConfig } from "../shared/types.js";
|
|
2
|
+
export type PortEnvKey = "MYSQL_PORT" | "SERVER_PORT" | "WEB_PORT";
|
|
3
|
+
export declare const PORT_ENV_KEYS: PortEnvKey[];
|
|
4
|
+
export declare function parseComposePortConflict(error: unknown): number | null;
|
|
5
|
+
export declare function findPortKeyByPort(env: EnvConfig, port: number, candidateKeys?: readonly PortEnvKey[]): PortEnvKey | null;
|
|
6
|
+
export declare function autoShiftConflictPort(env: EnvConfig, key: PortEnvKey, fromPort: number): Promise<number>;
|
|
7
|
+
export declare function getPortLabel(key: PortEnvKey): string;
|
|
8
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/install/ports.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,aAAa,GAAG,UAAU,CAAC;AAEnE,eAAO,MAAM,aAAa,EAAE,UAAU,EAA8C,CAAC;AAIrF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAStE;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,SAAS,UAAU,EAAkB,GACnD,UAAU,GAAG,IAAI,CAQnB;AAED,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,SAAS,EACd,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CASpD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getAvailablePort } from "../docker/ports.js";
|
|
2
|
+
export const PORT_ENV_KEYS = ["MYSQL_PORT", "SERVER_PORT", "WEB_PORT"];
|
|
3
|
+
const COMPOSE_PORT_CONFLICT_REGEX = /Bind for (?:\[[^\]]+\]|[0-9.]+):(\d+) failed: port is already allocated/i;
|
|
4
|
+
export function parseComposePortConflict(error) {
|
|
5
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6
|
+
const matched = COMPOSE_PORT_CONFLICT_REGEX.exec(message);
|
|
7
|
+
if (!matched) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const port = Number(matched[1]);
|
|
11
|
+
return Number.isInteger(port) ? port : null;
|
|
12
|
+
}
|
|
13
|
+
export function findPortKeyByPort(env, port, candidateKeys = PORT_ENV_KEYS) {
|
|
14
|
+
const targetPort = String(port);
|
|
15
|
+
for (const key of candidateKeys) {
|
|
16
|
+
if (env[key] === targetPort) {
|
|
17
|
+
return key;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export async function autoShiftConflictPort(env, key, fromPort) {
|
|
23
|
+
const occupiedByConfig = new Set(PORT_ENV_KEYS.filter((candidateKey) => candidateKey !== key).map((candidateKey) => Number(env[candidateKey])));
|
|
24
|
+
const nextPort = await getAvailablePort(fromPort + 1, occupiedByConfig);
|
|
25
|
+
env[key] = String(nextPort);
|
|
26
|
+
return nextPort;
|
|
27
|
+
}
|
|
28
|
+
export function getPortLabel(key) {
|
|
29
|
+
switch (key) {
|
|
30
|
+
case "MYSQL_PORT":
|
|
31
|
+
return "MySQL 端口";
|
|
32
|
+
case "SERVER_PORT":
|
|
33
|
+
return "Server 端口";
|
|
34
|
+
case "WEB_PORT":
|
|
35
|
+
return "Web 端口";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/install/ports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKtD,MAAM,CAAC,MAAM,aAAa,GAAiB,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;AAErF,MAAM,2BAA2B,GAAG,0EAA0E,CAAC;AAE/G,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACrD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,GAAc,EACd,IAAY,EACZ,gBAAuC,aAAa;IAEpD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,UAAU,EAAE,CAAC;YAC5B,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAc,EACd,GAAe,EACf,QAAgB;IAEhB,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC9B,aAAa,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAChF,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAC1B,CACF,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,QAAQ,GAAG,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACxE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAe;IAC1C,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,YAAY;YACf,OAAO,UAAU,CAAC;QACpB,KAAK,aAAa;YAChB,OAAO,WAAW,CAAC;QACrB,KAAK,UAAU;YACb,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CliFlags, EnvConfig, InstallConfigField, RuntimeLayout } from "../shared/types.js";
|
|
2
|
+
export declare function collectInstallConfig(layout: RuntimeLayout, versionArg: string | undefined, flags: CliFlags): Promise<EnvConfig>;
|
|
3
|
+
export declare function collectProblemInstallConfig(env: EnvConfig, fields: InstallConfigField[], flags: CliFlags): Promise<EnvConfig>;
|
|
4
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/install/prompts.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAkKjG,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,SAAS,CAAC,CAgEpB;AAED,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,kBAAkB,EAAE,EAC5B,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,SAAS,CAAC,CAYpB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { DEFAULT_DB_NAME, DEFAULT_DB_USER, DEFAULT_PORTS, DEFAULT_VERSION, buildCheckpointPgUrl, REQUIRED_ENV_KEYS, } from "../shared/constants.js";
|
|
5
|
+
import { getAvailablePort } from "../docker/ports.js";
|
|
6
|
+
import { buildDefaultEnv, extractCheckpointPgPassword, parseEnvFile, pathExists, } from "../runtime/index.js";
|
|
7
|
+
const PROMPTABLE_INSTALL_FIELDS = [
|
|
8
|
+
"MYSQL_PORT",
|
|
9
|
+
"SERVER_PORT",
|
|
10
|
+
"WEB_PORT",
|
|
11
|
+
"DB_DATABASE",
|
|
12
|
+
"DB_USERNAME",
|
|
13
|
+
"DB_PASSWORD",
|
|
14
|
+
"MYSQL_ROOT_PASSWORD",
|
|
15
|
+
"AI_CHECKPOINT_PG_PASSWORD",
|
|
16
|
+
"AES_SECRET",
|
|
17
|
+
];
|
|
18
|
+
function createSecret(bytes = 24) {
|
|
19
|
+
return randomBytes(bytes).toString("hex");
|
|
20
|
+
}
|
|
21
|
+
function normalizeCheckpointRuntimeConfig(env) {
|
|
22
|
+
const checkpointPassword = env.AI_CHECKPOINT_PG_PASSWORD.trim();
|
|
23
|
+
const checkpointUrl = env.AI_CHECKPOINT_PG_URL.trim();
|
|
24
|
+
if (checkpointPassword) {
|
|
25
|
+
return {
|
|
26
|
+
...env,
|
|
27
|
+
AI_CHECKPOINT_PG_PASSWORD: checkpointPassword,
|
|
28
|
+
AI_CHECKPOINT_PG_URL: buildCheckpointPgUrl(checkpointPassword),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (checkpointUrl) {
|
|
32
|
+
const derivedPassword = extractCheckpointPgPassword(checkpointUrl);
|
|
33
|
+
if (!derivedPassword) {
|
|
34
|
+
throw new Error("AI_CHECKPOINT_PG_URL 无法解析密码");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
...env,
|
|
38
|
+
AI_CHECKPOINT_PG_PASSWORD: derivedPassword,
|
|
39
|
+
AI_CHECKPOINT_PG_URL: buildCheckpointPgUrl(derivedPassword),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const generatedPassword = createSecret(16);
|
|
43
|
+
return {
|
|
44
|
+
...env,
|
|
45
|
+
AI_CHECKPOINT_PG_PASSWORD: generatedPassword,
|
|
46
|
+
AI_CHECKPOINT_PG_URL: buildCheckpointPgUrl(generatedPassword),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async function askInput(label, defaultValue) {
|
|
50
|
+
const answer = (await input({
|
|
51
|
+
message: label,
|
|
52
|
+
default: defaultValue,
|
|
53
|
+
})).trim();
|
|
54
|
+
return answer || defaultValue;
|
|
55
|
+
}
|
|
56
|
+
function assertPort(value, label) {
|
|
57
|
+
const numericPort = Number(value);
|
|
58
|
+
if (!Number.isInteger(numericPort) || numericPort < 1 || numericPort > 65535) {
|
|
59
|
+
throw new Error(`${label} 必须是 1-65535 之间的端口`);
|
|
60
|
+
}
|
|
61
|
+
return String(numericPort);
|
|
62
|
+
}
|
|
63
|
+
function assertAesSecret(value) {
|
|
64
|
+
const normalized = value.trim();
|
|
65
|
+
if (!normalized) {
|
|
66
|
+
throw new Error("AES_SECRET 不能为空");
|
|
67
|
+
}
|
|
68
|
+
return normalized;
|
|
69
|
+
}
|
|
70
|
+
function toPromptableInstallFields(fields) {
|
|
71
|
+
const requested = new Set(fields);
|
|
72
|
+
return PROMPTABLE_INSTALL_FIELDS.filter((field) => requested.has(field));
|
|
73
|
+
}
|
|
74
|
+
async function loadExistingEnvOverrides(layout) {
|
|
75
|
+
if (!(await pathExists(layout.envPath))) {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const content = await readFile(layout.envPath, "utf8");
|
|
80
|
+
const parsed = parseEnvFile(content);
|
|
81
|
+
const overrides = {};
|
|
82
|
+
for (const key of REQUIRED_ENV_KEYS) {
|
|
83
|
+
const value = parsed[key];
|
|
84
|
+
if (value) {
|
|
85
|
+
overrides[key] = value;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return overrides;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function promptInstallFields(env, fields) {
|
|
95
|
+
const nextEnv = { ...env };
|
|
96
|
+
for (const field of fields) {
|
|
97
|
+
switch (field) {
|
|
98
|
+
case "MYSQL_PORT":
|
|
99
|
+
nextEnv.MYSQL_PORT = assertPort(await askInput("MySQL 端口", nextEnv.MYSQL_PORT), "MySQL 端口");
|
|
100
|
+
break;
|
|
101
|
+
case "SERVER_PORT":
|
|
102
|
+
nextEnv.SERVER_PORT = assertPort(await askInput("Server 端口", nextEnv.SERVER_PORT), "Server 端口");
|
|
103
|
+
break;
|
|
104
|
+
case "WEB_PORT":
|
|
105
|
+
nextEnv.WEB_PORT = assertPort(await askInput("Web 端口", nextEnv.WEB_PORT), "Web 端口");
|
|
106
|
+
break;
|
|
107
|
+
case "DB_DATABASE":
|
|
108
|
+
nextEnv.DB_DATABASE = await askInput("数据库名称", nextEnv.DB_DATABASE);
|
|
109
|
+
nextEnv.MYSQL_DATABASE = nextEnv.DB_DATABASE;
|
|
110
|
+
break;
|
|
111
|
+
case "DB_USERNAME":
|
|
112
|
+
nextEnv.DB_USERNAME = await askInput("数据库用户名", nextEnv.DB_USERNAME);
|
|
113
|
+
nextEnv.MYSQL_USER = nextEnv.DB_USERNAME;
|
|
114
|
+
break;
|
|
115
|
+
case "DB_PASSWORD":
|
|
116
|
+
nextEnv.DB_PASSWORD = await askInput("数据库密码", nextEnv.DB_PASSWORD);
|
|
117
|
+
nextEnv.MYSQL_PASSWORD = nextEnv.DB_PASSWORD;
|
|
118
|
+
break;
|
|
119
|
+
case "MYSQL_ROOT_PASSWORD":
|
|
120
|
+
nextEnv.MYSQL_ROOT_PASSWORD = await askInput("MySQL Root 密码", nextEnv.MYSQL_ROOT_PASSWORD);
|
|
121
|
+
break;
|
|
122
|
+
case "AI_CHECKPOINT_PG_PASSWORD": {
|
|
123
|
+
const checkpointPassword = await askInput("Checkpoint PG 密码", nextEnv.AI_CHECKPOINT_PG_PASSWORD);
|
|
124
|
+
nextEnv.AI_CHECKPOINT_PG_PASSWORD = checkpointPassword;
|
|
125
|
+
nextEnv.AI_CHECKPOINT_PG_URL = buildCheckpointPgUrl(checkpointPassword);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case "AES_SECRET":
|
|
129
|
+
nextEnv.AES_SECRET = assertAesSecret(await askInput("AES_SECRET", nextEnv.AES_SECRET));
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return nextEnv;
|
|
134
|
+
}
|
|
135
|
+
export async function collectInstallConfig(layout, versionArg, flags) {
|
|
136
|
+
const version = versionArg ?? DEFAULT_VERSION;
|
|
137
|
+
const defaultDbPassword = createSecret(16);
|
|
138
|
+
const defaultRootPassword = createSecret(16);
|
|
139
|
+
const defaultCheckpointPassword = createSecret(16);
|
|
140
|
+
const defaultAesSecret = createSecret(24);
|
|
141
|
+
const [mysqlPort, serverPort, webPort] = await Promise.all([
|
|
142
|
+
getAvailablePort(DEFAULT_PORTS.mysql),
|
|
143
|
+
getAvailablePort(DEFAULT_PORTS.server),
|
|
144
|
+
getAvailablePort(DEFAULT_PORTS.web),
|
|
145
|
+
]);
|
|
146
|
+
const generatedDefaults = buildDefaultEnv(layout, {
|
|
147
|
+
SEEDAR_VERSION: version,
|
|
148
|
+
MYSQL_PORT: String(mysqlPort),
|
|
149
|
+
SERVER_PORT: String(serverPort),
|
|
150
|
+
WEB_PORT: String(webPort),
|
|
151
|
+
DB_HOST: "mysql",
|
|
152
|
+
DB_PORT: "3306",
|
|
153
|
+
DB_USERNAME: DEFAULT_DB_USER,
|
|
154
|
+
DB_PASSWORD: defaultDbPassword,
|
|
155
|
+
DB_DATABASE: DEFAULT_DB_NAME,
|
|
156
|
+
MYSQL_ROOT_PASSWORD: defaultRootPassword,
|
|
157
|
+
MYSQL_DATABASE: DEFAULT_DB_NAME,
|
|
158
|
+
MYSQL_USER: DEFAULT_DB_USER,
|
|
159
|
+
MYSQL_PASSWORD: defaultDbPassword,
|
|
160
|
+
AI_CHECKPOINT_PG_PASSWORD: defaultCheckpointPassword,
|
|
161
|
+
AI_CHECKPOINT_PG_URL: buildCheckpointPgUrl(defaultCheckpointPassword),
|
|
162
|
+
AES_SECRET: defaultAesSecret,
|
|
163
|
+
});
|
|
164
|
+
const existingOverrides = await loadExistingEnvOverrides(layout);
|
|
165
|
+
const existingCheckpointPassword = existingOverrides.AI_CHECKPOINT_PG_PASSWORD?.trim();
|
|
166
|
+
const existingCheckpointUrl = existingOverrides.AI_CHECKPOINT_PG_URL?.trim();
|
|
167
|
+
const derivedCheckpointPassword = existingCheckpointUrl
|
|
168
|
+
? extractCheckpointPgPassword(existingCheckpointUrl)
|
|
169
|
+
: null;
|
|
170
|
+
if (existingCheckpointUrl && !existingCheckpointPassword && !derivedCheckpointPassword) {
|
|
171
|
+
throw new Error("AI_CHECKPOINT_PG_URL 无法解析密码");
|
|
172
|
+
}
|
|
173
|
+
const checkpointPassword = existingCheckpointPassword ?? derivedCheckpointPassword ?? defaultCheckpointPassword;
|
|
174
|
+
const defaults = normalizeCheckpointRuntimeConfig({
|
|
175
|
+
...generatedDefaults,
|
|
176
|
+
...existingOverrides,
|
|
177
|
+
AI_CHECKPOINT_PG_PASSWORD: checkpointPassword,
|
|
178
|
+
AI_CHECKPOINT_PG_URL: buildCheckpointPgUrl(checkpointPassword),
|
|
179
|
+
SEEDAR_VERSION: versionArg ?? existingOverrides.SEEDAR_VERSION ?? generatedDefaults.SEEDAR_VERSION,
|
|
180
|
+
SEEDAR_INSTALL_ROOT: generatedDefaults.SEEDAR_INSTALL_ROOT,
|
|
181
|
+
SEEDAR_INSTANCE_ID: generatedDefaults.SEEDAR_INSTANCE_ID,
|
|
182
|
+
SEEDAR_PROJECT_NAME: generatedDefaults.SEEDAR_PROJECT_NAME,
|
|
183
|
+
});
|
|
184
|
+
if (!process.stdin.isTTY || flags.yes) {
|
|
185
|
+
console.log("使用默认安装参数初始化 Seedar。");
|
|
186
|
+
return defaults;
|
|
187
|
+
}
|
|
188
|
+
if (Object.keys(existingOverrides).length > 0) {
|
|
189
|
+
console.log("检测到已有配置,直接回车即可保留当前值。");
|
|
190
|
+
}
|
|
191
|
+
return promptInstallFields(defaults, PROMPTABLE_INSTALL_FIELDS);
|
|
192
|
+
}
|
|
193
|
+
export async function collectProblemInstallConfig(env, fields, flags) {
|
|
194
|
+
if (!process.stdin.isTTY || flags.yes) {
|
|
195
|
+
return env;
|
|
196
|
+
}
|
|
197
|
+
const promptFields = toPromptableInstallFields(fields);
|
|
198
|
+
if (promptFields.length === 0) {
|
|
199
|
+
return env;
|
|
200
|
+
}
|
|
201
|
+
console.log("配置检查未通过,请仅修改有问题的配置项。");
|
|
202
|
+
return promptInstallFields(env, promptFields);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/install/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/runtime/guards.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/E"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { hasRuntimeConfig } from "./index.js";
|
|
2
|
+
export async function requireRuntimeConfig(layout) {
|
|
3
|
+
if (!(await hasRuntimeConfig(layout))) {
|
|
4
|
+
throw new Error(`未检测到运行时配置,请先执行 seedar install。安装目录: ${layout.installRoot}`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/runtime/guards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAqB;IAC9D,IAAI,CAAC,CAAC,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,uCAAuC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { EnvConfig, InstallState, RuntimeLayout } from "
|
|
1
|
+
import type { EnvConfig, InstallState, RuntimeLayout } from "../shared/types.js";
|
|
2
2
|
export declare function resolveInstallRoot(): string;
|
|
3
3
|
export declare function toDockerPath(targetPath: string): string;
|
|
4
|
+
export declare function extractCheckpointPgPassword(connectionString: string): string | null;
|
|
4
5
|
export declare function getRuntimeLayout(): RuntimeLayout;
|
|
5
6
|
export declare function pathExists(targetPath: string): Promise<boolean>;
|
|
6
7
|
export declare function ensureRuntimeDirectories(layout: RuntimeLayout): Promise<void>;
|
|
7
8
|
export declare function renderEnvFile(env: EnvConfig): string;
|
|
8
9
|
export declare function parseEnvFile(content: string): Record<string, string>;
|
|
9
|
-
export declare function assertEnvShape(env: Record<string, string>): EnvConfig;
|
|
10
10
|
export declare function readEnvConfig(layout: RuntimeLayout): Promise<EnvConfig>;
|
|
11
11
|
export declare function writeRuntimeFiles(layout: RuntimeLayout, env: EnvConfig): Promise<void>;
|
|
12
12
|
export declare function writeInstalledVersion(layout: RuntimeLayout, version: string): Promise<void>;
|
|
@@ -17,4 +17,4 @@ export declare function hasRuntimeConfig(layout: RuntimeLayout): Promise<boolean
|
|
|
17
17
|
export declare function backupRuntime(layout: RuntimeLayout): Promise<string>;
|
|
18
18
|
export declare function buildDefaultEnv(layout: RuntimeLayout, values: Omit<EnvConfig, "SEEDAR_INSTALL_ROOT" | "SEEDAR_INSTANCE_ID" | "SEEDAR_PROJECT_NAME">): EnvConfig;
|
|
19
19
|
export declare function restoreRuntimeFromBackup(layout: RuntimeLayout, backupDir: string): Promise<void>;
|
|
20
|
-
//# sourceMappingURL=
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEjF,wBAAgB,kBAAkB,IAAI,MAAM,CAO3C;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,2BAA2B,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQnF;AAyDD,wBAAgB,gBAAgB,IAAI,aAAa,CAsBhD;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrE;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAOnF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAcpD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoBpE;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAS7E;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,YAAY,CAAC,CAcvB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAE9E;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB1E;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,qBAAqB,GAAG,oBAAoB,GAAG,qBAAqB,CAAC,GAC5F,SAAS,CAOX;AAED,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAaf"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
2
|
import { access, copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { COMPOSE_TEMPLATE, ENV_RENDER_ORDER, REQUIRED_ENV_KEYS, } from "
|
|
5
|
+
import { buildCheckpointPgUrl, COMPOSE_TEMPLATE, ENV_RENDER_ORDER, REQUIRED_ENV_KEYS, } from "../shared/constants.js";
|
|
6
6
|
export function resolveInstallRoot() {
|
|
7
7
|
const override = process.env.SEEDAR_INSTALL_DIR?.trim();
|
|
8
8
|
if (override) {
|
|
@@ -13,6 +13,63 @@ export function resolveInstallRoot() {
|
|
|
13
13
|
export function toDockerPath(targetPath) {
|
|
14
14
|
return path.resolve(targetPath).replace(/\\/g, "/");
|
|
15
15
|
}
|
|
16
|
+
export function extractCheckpointPgPassword(connectionString) {
|
|
17
|
+
try {
|
|
18
|
+
const url = new URL(connectionString);
|
|
19
|
+
const password = url.password.trim();
|
|
20
|
+
return password ? decodeURIComponent(password) : null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function normalizeEnvConfig(env) {
|
|
27
|
+
const normalized = { ...env };
|
|
28
|
+
const missing = REQUIRED_ENV_KEYS.filter((key) => !normalized[key]);
|
|
29
|
+
const checkpointPassword = normalized.AI_CHECKPOINT_PG_PASSWORD?.trim() || "";
|
|
30
|
+
const checkpointUrl = normalized.AI_CHECKPOINT_PG_URL?.trim() || "";
|
|
31
|
+
let changed = false;
|
|
32
|
+
if (checkpointPassword) {
|
|
33
|
+
const nextUrl = buildCheckpointPgUrl(checkpointPassword);
|
|
34
|
+
if (normalized.AI_CHECKPOINT_PG_PASSWORD !== checkpointPassword) {
|
|
35
|
+
normalized.AI_CHECKPOINT_PG_PASSWORD = checkpointPassword;
|
|
36
|
+
changed = true;
|
|
37
|
+
}
|
|
38
|
+
if (normalized.AI_CHECKPOINT_PG_URL !== nextUrl) {
|
|
39
|
+
normalized.AI_CHECKPOINT_PG_URL = nextUrl;
|
|
40
|
+
changed = true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else if (checkpointUrl) {
|
|
44
|
+
const derivedPassword = extractCheckpointPgPassword(checkpointUrl);
|
|
45
|
+
if (!derivedPassword) {
|
|
46
|
+
throw new Error("运行时配置中的 AI_CHECKPOINT_PG_URL 无法解析密码");
|
|
47
|
+
}
|
|
48
|
+
const nextUrl = buildCheckpointPgUrl(derivedPassword);
|
|
49
|
+
if (normalized.AI_CHECKPOINT_PG_PASSWORD !== derivedPassword) {
|
|
50
|
+
normalized.AI_CHECKPOINT_PG_PASSWORD = derivedPassword;
|
|
51
|
+
changed = true;
|
|
52
|
+
}
|
|
53
|
+
if (normalized.AI_CHECKPOINT_PG_URL !== nextUrl) {
|
|
54
|
+
normalized.AI_CHECKPOINT_PG_URL = nextUrl;
|
|
55
|
+
changed = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const generatedPassword = randomBytes(16).toString("hex");
|
|
60
|
+
normalized.AI_CHECKPOINT_PG_PASSWORD = generatedPassword;
|
|
61
|
+
normalized.AI_CHECKPOINT_PG_URL = buildCheckpointPgUrl(generatedPassword);
|
|
62
|
+
changed = true;
|
|
63
|
+
}
|
|
64
|
+
const remainingMissing = missing.filter((key) => key !== "AI_CHECKPOINT_PG_PASSWORD" && key !== "AI_CHECKPOINT_PG_URL");
|
|
65
|
+
if (remainingMissing.length > 0) {
|
|
66
|
+
throw new Error(`运行时配置缺少字段: ${remainingMissing.join(", ")}`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
env: normalized,
|
|
70
|
+
changed,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
16
73
|
export function getRuntimeLayout() {
|
|
17
74
|
const installRoot = resolveInstallRoot();
|
|
18
75
|
const instanceId = createHash("sha256")
|
|
@@ -24,6 +81,7 @@ export function getRuntimeLayout() {
|
|
|
24
81
|
runtimeDir: path.join(installRoot, "runtime"),
|
|
25
82
|
dataDir: path.join(installRoot, "data"),
|
|
26
83
|
mysqlDataDir: path.join(installRoot, "data", "mysql"),
|
|
84
|
+
postgresDataDir: path.join(installRoot, "data", "postgres"),
|
|
27
85
|
logsDir: path.join(installRoot, "logs"),
|
|
28
86
|
backupsDir: path.join(installRoot, "backups"),
|
|
29
87
|
composePath: path.join(installRoot, "runtime", "docker-compose.yml"),
|
|
@@ -47,6 +105,7 @@ export async function ensureRuntimeDirectories(layout) {
|
|
|
47
105
|
await mkdir(layout.runtimeDir, { recursive: true });
|
|
48
106
|
await mkdir(layout.dataDir, { recursive: true });
|
|
49
107
|
await mkdir(layout.mysqlDataDir, { recursive: true });
|
|
108
|
+
await mkdir(layout.postgresDataDir, { recursive: true });
|
|
50
109
|
await mkdir(layout.logsDir, { recursive: true });
|
|
51
110
|
await mkdir(layout.backupsDir, { recursive: true });
|
|
52
111
|
}
|
|
@@ -80,16 +139,14 @@ export function parseEnvFile(content) {
|
|
|
80
139
|
}
|
|
81
140
|
return result;
|
|
82
141
|
}
|
|
83
|
-
export function assertEnvShape(env) {
|
|
84
|
-
const missing = REQUIRED_ENV_KEYS.filter((key) => !env[key]);
|
|
85
|
-
if (missing.length > 0) {
|
|
86
|
-
throw new Error(`运行时配置缺少字段: ${missing.join(", ")}`);
|
|
87
|
-
}
|
|
88
|
-
return env;
|
|
89
|
-
}
|
|
90
142
|
export async function readEnvConfig(layout) {
|
|
91
143
|
const content = await readFile(layout.envPath, "utf8");
|
|
92
|
-
|
|
144
|
+
const { env, changed } = normalizeEnvConfig(parseEnvFile(content));
|
|
145
|
+
if (changed) {
|
|
146
|
+
await ensureRuntimeDirectories(layout);
|
|
147
|
+
await writeFile(layout.envPath, renderEnvFile(env), "utf8");
|
|
148
|
+
}
|
|
149
|
+
return env;
|
|
93
150
|
}
|
|
94
151
|
export async function writeRuntimeFiles(layout, env) {
|
|
95
152
|
await ensureRuntimeDirectories(layout);
|
|
@@ -163,4 +220,4 @@ export async function restoreRuntimeFromBackup(layout, backupDir) {
|
|
|
163
220
|
}
|
|
164
221
|
}
|
|
165
222
|
}
|
|
166
|
-
//# sourceMappingURL=
|
|
223
|
+
//# sourceMappingURL=index.js.map
|