@zitadel/cli 0.1.0-alpha.4 → 0.1.0-alpha.8
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 +70 -63
- package/SKILLS.md +60 -18
- package/dist/commands/apply.mjs +3 -3
- package/dist/commands/doctor.mjs +75 -20
- package/dist/commands/doctor.mjs.map +1 -1
- package/dist/commands/eject.mjs +13 -6
- package/dist/commands/eject.mjs.map +1 -1
- package/dist/commands/logs.mjs +13 -5
- package/dist/commands/logs.mjs.map +1 -1
- package/dist/commands/plan.mjs +3 -3
- package/dist/commands/reset.mjs +16 -7
- package/dist/commands/reset.mjs.map +1 -1
- package/dist/commands/setup.mjs +56 -17
- package/dist/commands/setup.mjs.map +1 -1
- package/dist/commands/start.mjs +104 -11
- package/dist/commands/start.mjs.map +1 -1
- package/dist/commands/status.mjs +26 -7
- package/dist/commands/status.mjs.map +1 -1
- package/dist/commands/stop.mjs +15 -6
- package/dist/commands/stop.mjs.map +1 -1
- package/dist/docker-BA78SdC2.mjs +383 -0
- package/dist/docker-BA78SdC2.mjs.map +1 -0
- package/dist/docker-guidance-BvfpmsDj.mjs +21 -0
- package/dist/docker-guidance-BvfpmsDj.mjs.map +1 -0
- package/dist/{oclif-B3Qhw0cj.mjs → oclif-VkCTGIEk.mjs} +50 -15
- package/dist/oclif-VkCTGIEk.mjs.map +1 -0
- package/dist/orca-CfKDQRop.mjs +2556 -0
- package/dist/orca-CfKDQRop.mjs.map +1 -0
- package/dist/{project-kWWyS7fS.mjs → project-CKAHtHML.mjs} +2 -2
- package/dist/{project-kWWyS7fS.mjs.map → project-CKAHtHML.mjs.map} +1 -1
- package/dist/{sync-CHXZqYR7.mjs → sync-B5lqgQO3.mjs} +2 -2
- package/dist/{sync-CHXZqYR7.mjs.map → sync-B5lqgQO3.mjs.map} +1 -1
- package/oclif.manifest.json +37 -3
- package/package.json +8 -41
- package/dist/docker-B4zvLujy.mjs +0 -210
- package/dist/docker-B4zvLujy.mjs.map +0 -1
- package/dist/oclif-B3Qhw0cj.mjs.map +0 -1
- package/dist/orca-BGM8VCgQ.mjs +0 -1141
- package/dist/orca-BGM8VCgQ.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.mjs","names":[],"sources":["../../src/commands/status.ts"],"sourcesContent":["import { inspectContainer } from \"../lib/local-server/docker\";\nimport {\n DEFAULT_LOCAL_SERVER_URL,\n checkLocalServerHealth,\n
|
|
1
|
+
{"version":3,"file":"status.mjs","names":[],"sources":["../../src/commands/status.ts"],"sourcesContent":["import { isProcessRunning } from \"../lib/local-server/binary\";\nimport { inspectContainer } from \"../lib/local-server/docker\";\nimport {\n DEFAULT_LOCAL_SERVER_URL,\n checkLocalServerHealth,\n readRuntimeMetadata,\n runtimeSummary,\n} from \"../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { resolveCwd } from \"../lib/paths\";\nimport {\n hasZitadelConfig,\n hasZitadelSecret,\n readDevelopmentIssuer,\n readZitadelConfig,\n readZitadelSecret,\n} from \"../lib/project\";\nimport { publicCliCommand } from \"../lib/public-cli\";\n\n/**\n * `zitadel status` — summarize the local server and project state.\n *\n * This is intentionally informational: a missing `zitadel.json`, stopped\n * local server, or orphaned config should be visible without making `status`\n * itself fail.\n */\nexport default class Status extends BaseCommand {\n static override description = \"Summarize the local Zitadel server and project state.\";\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Status);\n const cwd = resolveCwd(typeof flags.cwd === \"string\" ? flags.cwd : undefined);\n const runtime = await readRuntimeMetadata(cwd);\n if (flags.server === \"local\") {\n await this.toMeta(flags, {\n resolveServer: false,\n source: runtime?.server_url ?? DEFAULT_LOCAL_SERVER_URL,\n });\n } else {\n await this.toMeta(flags);\n }\n let docker: Awaited<ReturnType<typeof inspectContainer>> | undefined;\n let dockerError: string | undefined;\n if (runtime?.backend === \"docker\") {\n try {\n docker = await inspectContainer(runtime.container_name);\n } catch (error) {\n dockerError = error instanceof Error ? error.message : String(error);\n }\n }\n const healthy = runtime ? await checkLocalServerHealth(runtime.server_url) : false;\n const processRunning = runtime?.backend === \"binary\" ? isProcessRunning(runtime.pid) : false;\n const serverLifecycle = lifecycleForRuntime({ docker, healthy, processRunning, runtime });\n\n const project = await projectStatus(this.meta.cwd);\n const nextCommands = nextCommandsFor(serverLifecycle, project.lifecycle, this.meta.cliVersion);\n const nextActions = nextActionsFor(project.lifecycle);\n\n return this.emit({\n status: \"ok\",\n data: {\n title: \"Zitadel status.\",\n server: {\n lifecycle: serverLifecycle,\n runtime: runtimeSummary(runtime),\n docker: {\n available: dockerError === undefined,\n error: dockerError,\n container_exists: docker?.exists ?? false,\n container_running: docker?.running ?? false,\n },\n process:\n runtime?.backend === \"binary\"\n ? {\n pid: runtime.pid,\n running: processRunning,\n }\n : undefined,\n health: {\n healthy,\n url: runtime?.server_url,\n },\n },\n project,\n next_actions: nextActions,\n next_commands: nextCommands,\n },\n });\n }\n}\n\nfunction lifecycleForRuntime(input: {\n docker: Awaited<ReturnType<typeof inspectContainer>> | undefined;\n healthy: boolean;\n processRunning: boolean;\n runtime: Awaited<ReturnType<typeof readRuntimeMetadata>>;\n}): string {\n if (!input.runtime) {\n return \"missing\";\n }\n if (input.runtime.backend === \"binary\") {\n if (input.processRunning && input.healthy) {\n return \"running\";\n }\n return input.processRunning ? \"unhealthy\" : \"stopped\";\n }\n if (input.docker?.running && input.healthy) {\n return \"running\";\n }\n if (input.docker?.exists) {\n return \"unhealthy\";\n }\n return \"stopped\";\n}\n\ntype ProjectStatus =\n | {\n lifecycle: \"not-configured\";\n message: string;\n }\n | {\n lifecycle: \"orphaned-config\";\n project_id?: string;\n message: string;\n }\n | {\n lifecycle: \"configured\";\n project_id: string;\n issuer?: string;\n };\n\nasync function projectStatus(cwd: string): Promise<ProjectStatus> {\n if (!(await hasZitadelConfig(cwd))) {\n return {\n lifecycle: \"not-configured\",\n message: \"zitadel.json has not been created yet.\",\n };\n }\n\n const config = await readZitadelConfig(cwd);\n if (!(await hasZitadelSecret(cwd))) {\n return {\n lifecycle: \"orphaned-config\",\n project_id: typeof config.project === \"string\" ? config.project : undefined,\n message: \"zitadel.json exists but .zitadel/secret is missing.\",\n };\n }\n\n const secret = await readZitadelSecret(cwd);\n return {\n lifecycle: \"configured\",\n project_id: String(config.project ?? secret.project_id ?? \"\"),\n issuer: readDevelopmentIssuer(config),\n };\n}\n\nfunction nextActionsFor(projectLifecycle: ProjectStatus[\"lifecycle\"]): string[] {\n if (projectLifecycle === \"not-configured\") {\n return [\n \"From your app directory, run setup; the CLI will detect the framework or ask in an empty directory.\",\n ];\n }\n return [];\n}\n\nfunction nextCommandsFor(\n serverLifecycle: string,\n projectLifecycle: ProjectStatus[\"lifecycle\"],\n cliVersion: string,\n): string[] {\n const commands: string[] = [];\n if (serverLifecycle !== \"running\") {\n commands.push(publicCliCommand(\"start\", cliVersion));\n }\n if (projectLifecycle === \"not-configured\") {\n commands.push(publicCliCommand(\"setup --server local\", cliVersion));\n } else if (projectLifecycle === \"orphaned-config\") {\n commands.push(\n publicCliCommand(\"setup --force\", cliVersion),\n publicCliCommand(\"doctor --fix\", cliVersion),\n );\n } else {\n commands.push(publicCliCommand(\"doctor\", cliVersion), publicCliCommand(\"apply\", cliVersion));\n }\n return commands;\n}\n"],"mappings":"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"}
|
package/dist/commands/stop.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { u as stopAndRemoveContainer } from "../docker-
|
|
1
|
+
import { C as resolveCwd, h as readRuntimeMetadata, p as localContainerName, t as BaseCommand, x as publicCliCommand } from "../oclif-VkCTGIEk.mjs";
|
|
2
|
+
import { g as stopBinaryRuntime, u as stopAndRemoveContainer } from "../docker-BA78SdC2.mjs";
|
|
3
3
|
//#region src/commands/stop.ts
|
|
4
4
|
var Stop = class Stop extends BaseCommand {
|
|
5
5
|
static description = "Stop the local Zitadel server.";
|
|
@@ -10,26 +10,35 @@ var Stop = class Stop extends BaseCommand {
|
|
|
10
10
|
resolveServer: false,
|
|
11
11
|
source: runtime?.server_url ?? "http://localhost:8080"
|
|
12
12
|
});
|
|
13
|
-
const containerName = runtime?.container_name
|
|
13
|
+
const containerName = runtime?.backend === "docker" ? runtime.container_name : localContainerName(this.meta.cwd);
|
|
14
14
|
if (this.meta.dryRun) return this.emit({
|
|
15
15
|
status: "ok",
|
|
16
16
|
data: {
|
|
17
17
|
title: "Local Zitadel server stop plan.",
|
|
18
18
|
runtime: {
|
|
19
|
-
|
|
19
|
+
backend: runtime?.backend ?? "missing",
|
|
20
|
+
...runtime?.backend === "binary" ? {
|
|
21
|
+
pid: runtime.pid,
|
|
22
|
+
log_path: runtime.log_path
|
|
23
|
+
} : { container_name: containerName },
|
|
20
24
|
data_preserved: true,
|
|
21
25
|
data_dir: runtime?.data_dir
|
|
22
26
|
},
|
|
23
27
|
next_commands: [publicCliCommand("stop", this.meta.cliVersion)]
|
|
24
28
|
}
|
|
25
29
|
});
|
|
26
|
-
await
|
|
30
|
+
if (runtime?.backend === "binary") await stopBinaryRuntime(runtime.pid);
|
|
31
|
+
else await stopAndRemoveContainer(containerName);
|
|
27
32
|
return this.emit({
|
|
28
33
|
status: "ok",
|
|
29
34
|
data: {
|
|
30
35
|
title: "Local Zitadel server stopped.",
|
|
31
36
|
runtime: {
|
|
32
|
-
|
|
37
|
+
backend: runtime?.backend ?? "missing",
|
|
38
|
+
...runtime?.backend === "binary" ? {
|
|
39
|
+
pid: runtime.pid,
|
|
40
|
+
log_path: runtime.log_path
|
|
41
|
+
} : { container_name: containerName },
|
|
33
42
|
data_preserved: true,
|
|
34
43
|
data_dir: runtime?.data_dir
|
|
35
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop.mjs","names":[],"sources":["../../src/commands/stop.ts"],"sourcesContent":["import { stopAndRemoveContainer } from \"../lib/local-server/docker\";\nimport {\n DEFAULT_LOCAL_SERVER_URL,\n localContainerName,\n readRuntimeMetadata,\n} from \"../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { resolveCwd } from \"../lib/paths\";\nimport { publicCliCommand } from \"../lib/public-cli\";\n\nexport default class Stop extends BaseCommand {\n static override description = \"Stop the local Zitadel server.\";\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Stop);\n const cwd = resolveCwd(typeof flags.cwd === \"string\" ? flags.cwd : undefined);\n const runtime = await readRuntimeMetadata(cwd);\n await this.toMeta(flags, {\n resolveServer: false,\n source: runtime?.server_url ?? DEFAULT_LOCAL_SERVER_URL,\n });\n\n const containerName
|
|
1
|
+
{"version":3,"file":"stop.mjs","names":[],"sources":["../../src/commands/stop.ts"],"sourcesContent":["import { stopBinaryRuntime } from \"../lib/local-server/binary\";\nimport { stopAndRemoveContainer } from \"../lib/local-server/docker\";\nimport {\n DEFAULT_LOCAL_SERVER_URL,\n localContainerName,\n readRuntimeMetadata,\n} from \"../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { resolveCwd } from \"../lib/paths\";\nimport { publicCliCommand } from \"../lib/public-cli\";\n\nexport default class Stop extends BaseCommand {\n static override description = \"Stop the local Zitadel server.\";\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Stop);\n const cwd = resolveCwd(typeof flags.cwd === \"string\" ? flags.cwd : undefined);\n const runtime = await readRuntimeMetadata(cwd);\n await this.toMeta(flags, {\n resolveServer: false,\n source: runtime?.server_url ?? DEFAULT_LOCAL_SERVER_URL,\n });\n\n const containerName =\n runtime?.backend === \"docker\" ? runtime.container_name : localContainerName(this.meta.cwd);\n if (this.meta.dryRun) {\n return this.emit({\n status: \"ok\",\n data: {\n title: \"Local Zitadel server stop plan.\",\n runtime: {\n backend: runtime?.backend ?? \"missing\",\n ...(runtime?.backend === \"binary\"\n ? { pid: runtime.pid, log_path: runtime.log_path }\n : { container_name: containerName }),\n data_preserved: true,\n data_dir: runtime?.data_dir,\n },\n next_commands: [publicCliCommand(\"stop\", this.meta.cliVersion)],\n },\n });\n }\n\n if (runtime?.backend === \"binary\") {\n await stopBinaryRuntime(runtime.pid);\n } else {\n await stopAndRemoveContainer(containerName);\n }\n\n return this.emit({\n status: \"ok\",\n data: {\n title: \"Local Zitadel server stopped.\",\n runtime: {\n backend: runtime?.backend ?? \"missing\",\n ...(runtime?.backend === \"binary\"\n ? { pid: runtime.pid, log_path: runtime.log_path }\n : { container_name: containerName }),\n data_preserved: true,\n data_dir: runtime?.data_dir,\n },\n },\n });\n }\n}\n"],"mappings":";;;AAWA,IAAqB,OAArB,MAAqB,aAAa,YAAY;CAC5C,OAAgB,cAAc;CAE9B,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,KAAK;EAExC,MAAM,UAAU,MAAM,oBADV,WAAW,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM,KAAA,EACtB,CAAC;AAC9C,QAAM,KAAK,OAAO,OAAO;GACvB,eAAe;GACf,QAAQ,SAAS,cAAA;GAClB,CAAC;EAEF,MAAM,gBACJ,SAAS,YAAY,WAAW,QAAQ,iBAAiB,mBAAmB,KAAK,KAAK,IAAI;AAC5F,MAAI,KAAK,KAAK,OACZ,QAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;IACJ,OAAO;IACP,SAAS;KACP,SAAS,SAAS,WAAW;KAC7B,GAAI,SAAS,YAAY,WACrB;MAAE,KAAK,QAAQ;MAAK,UAAU,QAAQ;MAAU,GAChD,EAAE,gBAAgB,eAAe;KACrC,gBAAgB;KAChB,UAAU,SAAS;KACpB;IACD,eAAe,CAAC,iBAAiB,QAAQ,KAAK,KAAK,WAAW,CAAC;IAChE;GACF,CAAC;AAGJ,MAAI,SAAS,YAAY,SACvB,OAAM,kBAAkB,QAAQ,IAAI;MAEpC,OAAM,uBAAuB,cAAc;AAG7C,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;IACJ,OAAO;IACP,SAAS;KACP,SAAS,SAAS,WAAW;KAC7B,GAAI,SAAS,YAAY,WACrB;MAAE,KAAK,QAAQ;MAAK,UAAU,QAAQ;MAAU,GAChD,EAAE,gBAAgB,eAAe;KACrC,gBAAgB;KAChB,UAAU,SAAS;KACpB;IACF;GACF,CAAC"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { D as ZitadelError, i as CONTAINER_HTTP_PORT, r as CONTAINER_DATA_DIR } from "./oclif-VkCTGIEk.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { mkdir, open, readFile, stat } from "node:fs/promises";
|
|
5
|
+
import { createReadStream } from "node:fs";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
//#region src/lib/local-server/binary.ts
|
|
8
|
+
const SERVER_NPM_PACKAGE = "@zitadel/server";
|
|
9
|
+
const START_COMMAND_ENV = "ZITADEL_SERVER_BINARY";
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
function resolveServerCommand(env = process.env) {
|
|
12
|
+
if (env[START_COMMAND_ENV]) return {
|
|
13
|
+
command: env[START_COMMAND_ENV],
|
|
14
|
+
args: [],
|
|
15
|
+
serverPackage: SERVER_NPM_PACKAGE,
|
|
16
|
+
serverVersion: "override"
|
|
17
|
+
};
|
|
18
|
+
const manifestPath = resolveServerPackageManifest();
|
|
19
|
+
const manifest = require(manifestPath);
|
|
20
|
+
return {
|
|
21
|
+
command: process.execPath,
|
|
22
|
+
args: [join(dirname(manifestPath), "bin", "zitadel-server.js")],
|
|
23
|
+
serverPackage: SERVER_NPM_PACKAGE,
|
|
24
|
+
serverVersion: typeof manifest.version === "string" ? manifest.version : "unknown"
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function startBinaryRuntime(spec) {
|
|
28
|
+
const command = resolveServerCommand();
|
|
29
|
+
await mkdir(dirname(spec.logPath), {
|
|
30
|
+
recursive: true,
|
|
31
|
+
mode: 448
|
|
32
|
+
});
|
|
33
|
+
const log = await open(spec.logPath, "a", 384);
|
|
34
|
+
try {
|
|
35
|
+
const child = spawn(command.command, command.args, {
|
|
36
|
+
detached: true,
|
|
37
|
+
env: {
|
|
38
|
+
...process.env,
|
|
39
|
+
NEXTGEN_SERVER_ADDRESS: `:${String(spec.port)}`,
|
|
40
|
+
NEXTGEN_SERVER_DATA_DIR: spec.dataDir
|
|
41
|
+
},
|
|
42
|
+
stdio: [
|
|
43
|
+
"ignore",
|
|
44
|
+
log.fd,
|
|
45
|
+
log.fd
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
child.unref();
|
|
49
|
+
if (!child.pid) throw new Error("server process did not expose a pid");
|
|
50
|
+
return {
|
|
51
|
+
schema_version: 1,
|
|
52
|
+
backend: "binary",
|
|
53
|
+
pid: child.pid,
|
|
54
|
+
command: [command.command, ...command.args].join(" "),
|
|
55
|
+
log_path: spec.logPath,
|
|
56
|
+
server_package: command.serverPackage,
|
|
57
|
+
server_version: command.serverVersion,
|
|
58
|
+
port: spec.port,
|
|
59
|
+
server_url: spec.serverUrl,
|
|
60
|
+
data_dir: spec.dataDir,
|
|
61
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62
|
+
cli_version: spec.cliVersion
|
|
63
|
+
};
|
|
64
|
+
} finally {
|
|
65
|
+
await log.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function stopBinaryRuntime(pid) {
|
|
69
|
+
if (!isProcessRunning(pid)) return;
|
|
70
|
+
if (!signalProcess(pid, "SIGTERM")) return;
|
|
71
|
+
const deadline = Date.now() + 1e4;
|
|
72
|
+
while (Date.now() < deadline) {
|
|
73
|
+
if (!isProcessRunning(pid)) return;
|
|
74
|
+
await delay(200);
|
|
75
|
+
}
|
|
76
|
+
if (isProcessRunning(pid)) signalProcess(pid, "SIGKILL");
|
|
77
|
+
}
|
|
78
|
+
function isProcessRunning(pid) {
|
|
79
|
+
try {
|
|
80
|
+
process.kill(pid, 0);
|
|
81
|
+
return true;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return isErrno(error, "EPERM");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function binaryLogs(logPath, tail) {
|
|
87
|
+
let content = "";
|
|
88
|
+
try {
|
|
89
|
+
content = await readFile(logPath, "utf8");
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (isErrno(error, "ENOENT")) return "";
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
const lines = content.split(/\r?\n/);
|
|
95
|
+
const hasTrailingNewline = lines.at(-1) === "";
|
|
96
|
+
const selected = (hasTrailingNewline ? lines.slice(0, -1) : lines).slice(-tail).join("\n");
|
|
97
|
+
return selected.length === 0 ? "" : `${selected}${hasTrailingNewline ? "\n" : ""}`;
|
|
98
|
+
}
|
|
99
|
+
async function followBinaryLogs(logPath, tail) {
|
|
100
|
+
process.stdout.write(await binaryLogs(logPath, tail));
|
|
101
|
+
let offset = await fileSize(logPath);
|
|
102
|
+
await new Promise((resolveFollow, reject) => {
|
|
103
|
+
const interval = setInterval(() => {
|
|
104
|
+
(async () => {
|
|
105
|
+
try {
|
|
106
|
+
const size = await fileSize(logPath);
|
|
107
|
+
if (size > offset) {
|
|
108
|
+
createReadStream(logPath, {
|
|
109
|
+
start: offset,
|
|
110
|
+
end: size - 1
|
|
111
|
+
}).pipe(process.stdout, { end: false });
|
|
112
|
+
offset = size;
|
|
113
|
+
}
|
|
114
|
+
} catch (error) {
|
|
115
|
+
reject(error);
|
|
116
|
+
}
|
|
117
|
+
})();
|
|
118
|
+
}, 1e3);
|
|
119
|
+
const stop = () => {
|
|
120
|
+
clearInterval(interval);
|
|
121
|
+
resolveFollow();
|
|
122
|
+
};
|
|
123
|
+
process.once("SIGINT", stop);
|
|
124
|
+
process.once("SIGTERM", stop);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async function assertServerPackageAvailable() {
|
|
128
|
+
try {
|
|
129
|
+
return resolveServerCommand().serverVersion;
|
|
130
|
+
} catch (error) {
|
|
131
|
+
throw new ZitadelError("E_VALIDATION", "Zitadel server npm package is not available", {
|
|
132
|
+
hint: "Reinstall @zitadel/cli so npm can install @zitadel/server and its platform package.",
|
|
133
|
+
nextCommands: ["npm install @zitadel/cli@alpha"],
|
|
134
|
+
details: {
|
|
135
|
+
package: SERVER_NPM_PACKAGE,
|
|
136
|
+
message: errorMessage(error)
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function resolveServerPackageManifest() {
|
|
142
|
+
try {
|
|
143
|
+
return require.resolve(`${SERVER_NPM_PACKAGE}/package.json`);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
throw new Error(`Missing ${SERVER_NPM_PACKAGE}. Reinstall @zitadel/cli.`, { cause: error });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function fileSize(path) {
|
|
149
|
+
try {
|
|
150
|
+
return (await stat(path)).size;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
if (isErrno(error, "ENOENT")) return 0;
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function isErrno(error, code) {
|
|
157
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
158
|
+
}
|
|
159
|
+
function signalProcess(pid, signal) {
|
|
160
|
+
try {
|
|
161
|
+
process.kill(pid, signal);
|
|
162
|
+
return true;
|
|
163
|
+
} catch (error) {
|
|
164
|
+
if (isErrno(error, "ESRCH")) return false;
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function errorMessage(error) {
|
|
169
|
+
return error instanceof Error ? error.message : String(error);
|
|
170
|
+
}
|
|
171
|
+
function delay(ms) {
|
|
172
|
+
return new Promise((resolveDelay) => setTimeout(resolveDelay, ms));
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/lib/local-server/docker.ts
|
|
176
|
+
function dockerRunArgs(spec) {
|
|
177
|
+
const args = [
|
|
178
|
+
"run",
|
|
179
|
+
"--detach",
|
|
180
|
+
"--name",
|
|
181
|
+
spec.containerName,
|
|
182
|
+
"--publish",
|
|
183
|
+
`127.0.0.1:${spec.port}:${CONTAINER_HTTP_PORT}`,
|
|
184
|
+
"--volume",
|
|
185
|
+
`${spec.dataDir}:${CONTAINER_DATA_DIR}`,
|
|
186
|
+
"--env",
|
|
187
|
+
`NEXTGEN_SERVER_ADDRESS=:${CONTAINER_HTTP_PORT}`,
|
|
188
|
+
"--env",
|
|
189
|
+
`NEXTGEN_SERVER_DATA_DIR=${CONTAINER_DATA_DIR}`
|
|
190
|
+
];
|
|
191
|
+
if (spec.identity) args.push("--volume", `${spec.identity.passwdFile}:/etc/passwd:ro`, "--volume", `${spec.identity.groupFile}:/etc/group:ro`, "--user", `${spec.identity.uid}:${spec.identity.gid}`);
|
|
192
|
+
args.push(spec.image);
|
|
193
|
+
return args;
|
|
194
|
+
}
|
|
195
|
+
async function runDocker(args) {
|
|
196
|
+
return new Promise((resolve, reject) => {
|
|
197
|
+
const child = spawn("docker", args, {
|
|
198
|
+
stdio: [
|
|
199
|
+
"ignore",
|
|
200
|
+
"pipe",
|
|
201
|
+
"pipe"
|
|
202
|
+
],
|
|
203
|
+
env: process.env
|
|
204
|
+
});
|
|
205
|
+
let stdout = "";
|
|
206
|
+
let stderr = "";
|
|
207
|
+
child.stdout?.setEncoding("utf8");
|
|
208
|
+
child.stderr?.setEncoding("utf8");
|
|
209
|
+
child.stdout?.on("data", (chunk) => {
|
|
210
|
+
stdout += chunk;
|
|
211
|
+
});
|
|
212
|
+
child.stderr?.on("data", (chunk) => {
|
|
213
|
+
stderr += chunk;
|
|
214
|
+
});
|
|
215
|
+
child.on("error", reject);
|
|
216
|
+
child.on("close", (code) => {
|
|
217
|
+
resolve({
|
|
218
|
+
status: code ?? 1,
|
|
219
|
+
stdout,
|
|
220
|
+
stderr
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
async function streamDocker(args) {
|
|
226
|
+
await new Promise((resolve, reject) => {
|
|
227
|
+
const child = spawn("docker", args, {
|
|
228
|
+
stdio: "inherit",
|
|
229
|
+
env: process.env
|
|
230
|
+
});
|
|
231
|
+
child.on("error", reject);
|
|
232
|
+
child.on("close", (code) => {
|
|
233
|
+
if (code === 0) resolve();
|
|
234
|
+
else reject(/* @__PURE__ */ new Error(`docker ${args.join(" ")} exited with status ${code ?? 1}`));
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async function dockerAvailable() {
|
|
239
|
+
return runDocker([
|
|
240
|
+
"version",
|
|
241
|
+
"--format",
|
|
242
|
+
"{{.Server.Version}}"
|
|
243
|
+
]);
|
|
244
|
+
}
|
|
245
|
+
async function pullImage(image) {
|
|
246
|
+
await requireDocker([
|
|
247
|
+
"pull",
|
|
248
|
+
"--quiet",
|
|
249
|
+
image
|
|
250
|
+
], `Pull Docker image ${image}`);
|
|
251
|
+
}
|
|
252
|
+
async function imageExists(image) {
|
|
253
|
+
let result;
|
|
254
|
+
const args = [
|
|
255
|
+
"image",
|
|
256
|
+
"inspect",
|
|
257
|
+
image
|
|
258
|
+
];
|
|
259
|
+
try {
|
|
260
|
+
result = await runDocker(args);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
throw dockerError(`Inspect Docker image ${image}`, args, error);
|
|
263
|
+
}
|
|
264
|
+
return result.status === 0;
|
|
265
|
+
}
|
|
266
|
+
async function imageAvailable(image) {
|
|
267
|
+
if (await imageExists(image)) return "local";
|
|
268
|
+
const args = [
|
|
269
|
+
"manifest",
|
|
270
|
+
"inspect",
|
|
271
|
+
image
|
|
272
|
+
];
|
|
273
|
+
let result;
|
|
274
|
+
try {
|
|
275
|
+
result = await runDocker(args);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
throw dockerError(`Inspect Docker image ${image}`, args, error);
|
|
278
|
+
}
|
|
279
|
+
if (result.status === 0) return "remote";
|
|
280
|
+
throw dockerError(`Inspect Docker image ${image}`, args, result);
|
|
281
|
+
}
|
|
282
|
+
async function ensureImage(image) {
|
|
283
|
+
if (await imageExists(image)) return "local";
|
|
284
|
+
await pullImage(image);
|
|
285
|
+
return "pulled";
|
|
286
|
+
}
|
|
287
|
+
async function inspectContainer(containerName) {
|
|
288
|
+
const result = await runDocker([
|
|
289
|
+
"inspect",
|
|
290
|
+
"--format",
|
|
291
|
+
"{{.Id}} {{.State.Running}} {{.Config.Image}}",
|
|
292
|
+
containerName
|
|
293
|
+
]);
|
|
294
|
+
if (result.status !== 0) return {
|
|
295
|
+
exists: false,
|
|
296
|
+
running: false
|
|
297
|
+
};
|
|
298
|
+
const [id, running, ...imageParts] = result.stdout.trim().split(/\s+/);
|
|
299
|
+
return {
|
|
300
|
+
exists: true,
|
|
301
|
+
running: running === "true",
|
|
302
|
+
id,
|
|
303
|
+
image: imageParts.join(" ")
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
async function startContainer(spec) {
|
|
307
|
+
return (await requireDocker(dockerRunArgs(spec), "Start local Zitadel container")).stdout.trim();
|
|
308
|
+
}
|
|
309
|
+
async function stopAndRemoveContainer(containerName) {
|
|
310
|
+
const inspect = await inspectContainer(containerName);
|
|
311
|
+
if (!inspect.exists) return;
|
|
312
|
+
if (inspect.running) await requireDocker(["stop", containerName], `Stop ${containerName}`);
|
|
313
|
+
await requireDocker(["rm", containerName], `Remove ${containerName}`);
|
|
314
|
+
}
|
|
315
|
+
async function containerLogs(containerName, tail) {
|
|
316
|
+
return (await requireDocker([
|
|
317
|
+
"logs",
|
|
318
|
+
"--tail",
|
|
319
|
+
String(tail),
|
|
320
|
+
containerName
|
|
321
|
+
], "Read logs")).stdout;
|
|
322
|
+
}
|
|
323
|
+
async function followContainerLogs(containerName, tail) {
|
|
324
|
+
await streamDocker([
|
|
325
|
+
"logs",
|
|
326
|
+
"--tail",
|
|
327
|
+
String(tail),
|
|
328
|
+
"--follow",
|
|
329
|
+
containerName
|
|
330
|
+
]);
|
|
331
|
+
}
|
|
332
|
+
function currentUser() {
|
|
333
|
+
const getuid = process.getuid;
|
|
334
|
+
const getgid = process.getgid;
|
|
335
|
+
if (typeof getuid !== "function") return {};
|
|
336
|
+
const uid = getuid();
|
|
337
|
+
return {
|
|
338
|
+
uid,
|
|
339
|
+
gid: typeof getgid === "function" ? getgid() : uid
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function metadataFromStart(input) {
|
|
343
|
+
return {
|
|
344
|
+
schema_version: 1,
|
|
345
|
+
backend: "docker",
|
|
346
|
+
container_name: input.containerName,
|
|
347
|
+
container_id: input.containerId,
|
|
348
|
+
image: input.image,
|
|
349
|
+
port: input.port,
|
|
350
|
+
server_url: input.serverUrl,
|
|
351
|
+
data_dir: input.cwdDataDir,
|
|
352
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
353
|
+
cli_version: input.cliVersion
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
async function requireDocker(args, action) {
|
|
357
|
+
let result;
|
|
358
|
+
try {
|
|
359
|
+
result = await runDocker(args);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
throw dockerError(action, args, error);
|
|
362
|
+
}
|
|
363
|
+
if (result.status !== 0) throw dockerError(action, args, result);
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
function dockerError(action, args, cause) {
|
|
367
|
+
const details = cause && typeof cause === "object" && "stderr" in cause ? {
|
|
368
|
+
command: ["docker", ...args],
|
|
369
|
+
stderr: String(cause.stderr)
|
|
370
|
+
} : {
|
|
371
|
+
command: ["docker", ...args],
|
|
372
|
+
cause
|
|
373
|
+
};
|
|
374
|
+
return new ZitadelError("E_VALIDATION", `${action} failed`, {
|
|
375
|
+
hint: "Check that Docker is installed, running, and reachable from this shell.",
|
|
376
|
+
nextCommands: ["zitadel doctor"],
|
|
377
|
+
details
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
//#endregion
|
|
381
|
+
export { followContainerLogs as a, metadataFromStart as c, assertServerPackageAvailable as d, binaryLogs as f, stopBinaryRuntime as g, startBinaryRuntime as h, ensureImage as i, startContainer as l, isProcessRunning as m, currentUser as n, imageAvailable as o, followBinaryLogs as p, dockerAvailable as r, inspectContainer as s, containerLogs as t, stopAndRemoveContainer as u };
|
|
382
|
+
|
|
383
|
+
//# sourceMappingURL=docker-BA78SdC2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-BA78SdC2.mjs","names":[],"sources":["../src/lib/local-server/binary.ts","../src/lib/local-server/docker.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { createReadStream } from \"node:fs\";\nimport { mkdir, open, readFile, stat } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\nimport { ZitadelError } from \"../errors\";\nimport {\n type BinaryRuntimeMetadata,\n type RuntimeMetadata,\n checkLocalServerHealth,\n} from \"./runtime\";\n\nexport const SERVER_NPM_PACKAGE = \"@zitadel/server\";\nconst START_COMMAND_ENV = \"ZITADEL_SERVER_BINARY\";\n\nconst require = createRequire(import.meta.url);\n\nexport type BinaryRunSpec = {\n cliVersion: string;\n dataDir: string;\n logPath: string;\n port: number;\n serverUrl: string;\n};\n\nexport function resolveServerCommand(env: NodeJS.ProcessEnv = process.env): {\n command: string;\n args: string[];\n serverPackage: string;\n serverVersion: string;\n} {\n if (env[START_COMMAND_ENV]) {\n return {\n command: env[START_COMMAND_ENV],\n args: [],\n serverPackage: SERVER_NPM_PACKAGE,\n serverVersion: \"override\",\n };\n }\n\n const manifestPath = resolveServerPackageManifest();\n const manifest = require(manifestPath) as { version?: unknown };\n return {\n command: process.execPath,\n args: [join(dirname(manifestPath), \"bin\", \"zitadel-server.js\")],\n serverPackage: SERVER_NPM_PACKAGE,\n serverVersion: typeof manifest.version === \"string\" ? manifest.version : \"unknown\",\n };\n}\n\nexport async function startBinaryRuntime(spec: BinaryRunSpec): Promise<BinaryRuntimeMetadata> {\n const command = resolveServerCommand();\n await mkdir(dirname(spec.logPath), { recursive: true, mode: 0o700 });\n const log = await open(spec.logPath, \"a\", 0o600);\n try {\n const child = spawn(command.command, command.args, {\n detached: true,\n env: {\n ...process.env,\n NEXTGEN_SERVER_ADDRESS: `:${String(spec.port)}`,\n NEXTGEN_SERVER_DATA_DIR: spec.dataDir,\n },\n stdio: [\"ignore\", log.fd, log.fd],\n });\n child.unref();\n if (!child.pid) {\n throw new Error(\"server process did not expose a pid\");\n }\n return {\n schema_version: 1,\n backend: \"binary\",\n pid: child.pid,\n command: [command.command, ...command.args].join(\" \"),\n log_path: spec.logPath,\n server_package: command.serverPackage,\n server_version: command.serverVersion,\n port: spec.port,\n server_url: spec.serverUrl,\n data_dir: spec.dataDir,\n created_at: new Date().toISOString(),\n cli_version: spec.cliVersion,\n };\n } finally {\n await log.close();\n }\n}\n\nexport async function stopBinaryRuntime(pid: number): Promise<void> {\n if (!isProcessRunning(pid)) {\n return;\n }\n if (!signalProcess(pid, \"SIGTERM\")) {\n return;\n }\n const deadline = Date.now() + 10_000;\n while (Date.now() < deadline) {\n if (!isProcessRunning(pid)) {\n return;\n }\n await delay(200);\n }\n if (isProcessRunning(pid)) {\n signalProcess(pid, \"SIGKILL\");\n }\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return isErrno(error, \"EPERM\");\n }\n}\n\nexport async function binaryLogs(logPath: string, tail: number): Promise<string> {\n let content = \"\";\n try {\n content = await readFile(logPath, \"utf8\");\n } catch (error) {\n if (isErrno(error, \"ENOENT\")) {\n return \"\";\n }\n throw error;\n }\n const lines = content.split(/\\r?\\n/);\n const hasTrailingNewline = lines.at(-1) === \"\";\n const body = hasTrailingNewline ? lines.slice(0, -1) : lines;\n const selected = body.slice(-tail).join(\"\\n\");\n return selected.length === 0 ? \"\" : `${selected}${hasTrailingNewline ? \"\\n\" : \"\"}`;\n}\n\nexport async function followBinaryLogs(logPath: string, tail: number): Promise<void> {\n process.stdout.write(await binaryLogs(logPath, tail));\n let offset = await fileSize(logPath);\n await new Promise<void>((resolveFollow, reject) => {\n const interval = setInterval(() => {\n void (async () => {\n try {\n const size = await fileSize(logPath);\n if (size > offset) {\n const stream = createReadStream(logPath, { start: offset, end: size - 1 });\n stream.pipe(process.stdout, { end: false });\n offset = size;\n }\n } catch (error) {\n reject(error);\n }\n })();\n }, 1000);\n const stop = () => {\n clearInterval(interval);\n resolveFollow();\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n });\n}\n\nexport async function assertServerPackageAvailable(): Promise<string> {\n try {\n const command = resolveServerCommand();\n return command.serverVersion;\n } catch (error) {\n throw new ZitadelError(\"E_VALIDATION\", \"Zitadel server npm package is not available\", {\n hint: \"Reinstall @zitadel/cli so npm can install @zitadel/server and its platform package.\",\n nextCommands: [\"npm install @zitadel/cli@alpha\"],\n details: { package: SERVER_NPM_PACKAGE, message: errorMessage(error) },\n });\n }\n}\n\nexport async function binaryRuntimeHealthy(runtime: RuntimeMetadata): Promise<boolean> {\n return (\n runtime.backend === \"binary\" &&\n isProcessRunning(runtime.pid) &&\n (await checkLocalServerHealth(runtime.server_url))\n );\n}\n\nfunction resolveServerPackageManifest(): string {\n try {\n return require.resolve(`${SERVER_NPM_PACKAGE}/package.json`);\n } catch (error) {\n throw new Error(`Missing ${SERVER_NPM_PACKAGE}. Reinstall @zitadel/cli.`, { cause: error });\n }\n}\n\nasync function fileSize(path: string): Promise<number> {\n try {\n return (await stat(path)).size;\n } catch (error) {\n if (isErrno(error, \"ENOENT\")) {\n return 0;\n }\n throw error;\n }\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === code\n );\n}\n\nfunction signalProcess(pid: number, signal: NodeJS.Signals): boolean {\n try {\n process.kill(pid, signal);\n return true;\n } catch (error) {\n if (isErrno(error, \"ESRCH\")) {\n return false;\n }\n throw error;\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n","import { spawn } from \"node:child_process\";\n\nimport { ZitadelError } from \"../errors\";\nimport {\n CONTAINER_DATA_DIR,\n CONTAINER_HTTP_PORT,\n type ContainerIdentity,\n type RuntimeMetadata,\n} from \"./runtime\";\n\nexport type DockerResult = {\n status: number;\n stdout: string;\n stderr: string;\n};\n\nexport type DockerRunSpec = {\n containerName: string;\n image: string;\n port: number;\n dataDir: string;\n identity?: ContainerIdentity;\n};\n\nexport function dockerRunArgs(spec: DockerRunSpec): string[] {\n const args = [\n \"run\",\n \"--detach\",\n \"--name\",\n spec.containerName,\n \"--publish\",\n `127.0.0.1:${spec.port}:${CONTAINER_HTTP_PORT}`,\n \"--volume\",\n `${spec.dataDir}:${CONTAINER_DATA_DIR}`,\n \"--env\",\n `NEXTGEN_SERVER_ADDRESS=:${CONTAINER_HTTP_PORT}`,\n \"--env\",\n `NEXTGEN_SERVER_DATA_DIR=${CONTAINER_DATA_DIR}`,\n ];\n\n if (spec.identity) {\n args.push(\n \"--volume\",\n `${spec.identity.passwdFile}:/etc/passwd:ro`,\n \"--volume\",\n `${spec.identity.groupFile}:/etc/group:ro`,\n \"--user\",\n `${spec.identity.uid}:${spec.identity.gid}`,\n );\n }\n\n args.push(spec.image);\n return args;\n}\n\nexport async function runDocker(args: string[]): Promise<DockerResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"docker\", args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.setEncoding(\"utf8\");\n child.stderr?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (chunk: string) => {\n stdout += chunk;\n });\n child.stderr?.on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n resolve({ status: code ?? 1, stdout, stderr });\n });\n });\n}\n\nexport async function streamDocker(args: string[]): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(\"docker\", args, {\n stdio: \"inherit\",\n env: process.env,\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`docker ${args.join(\" \")} exited with status ${code ?? 1}`));\n }\n });\n });\n}\n\nexport async function dockerAvailable(): Promise<DockerResult> {\n return runDocker([\"version\", \"--format\", \"{{.Server.Version}}\"]);\n}\n\nexport async function pullImage(image: string): Promise<void> {\n await requireDocker([\"pull\", \"--quiet\", image], `Pull Docker image ${image}`);\n}\n\nexport async function imageExists(image: string): Promise<boolean> {\n let result: DockerResult;\n const args = [\"image\", \"inspect\", image];\n try {\n result = await runDocker(args);\n } catch (error) {\n throw dockerError(`Inspect Docker image ${image}`, args, error);\n }\n return result.status === 0;\n}\n\nexport async function imageAvailable(image: string): Promise<\"local\" | \"remote\"> {\n if (await imageExists(image)) {\n return \"local\";\n }\n\n const args = [\"manifest\", \"inspect\", image];\n let result: DockerResult;\n try {\n result = await runDocker(args);\n } catch (error) {\n throw dockerError(`Inspect Docker image ${image}`, args, error);\n }\n if (result.status === 0) {\n return \"remote\";\n }\n throw dockerError(`Inspect Docker image ${image}`, args, result);\n}\n\nexport async function ensureImage(image: string): Promise<\"local\" | \"pulled\"> {\n if (await imageExists(image)) {\n return \"local\";\n }\n await pullImage(image);\n return \"pulled\";\n}\n\nexport async function inspectContainer(containerName: string): Promise<{\n exists: boolean;\n running: boolean;\n id?: string;\n image?: string;\n}> {\n const result = await runDocker([\n \"inspect\",\n \"--format\",\n \"{{.Id}} {{.State.Running}} {{.Config.Image}}\",\n containerName,\n ]);\n if (result.status !== 0) {\n return { exists: false, running: false };\n }\n const [id, running, ...imageParts] = result.stdout.trim().split(/\\s+/);\n return { exists: true, running: running === \"true\", id, image: imageParts.join(\" \") };\n}\n\nexport async function startContainer(spec: DockerRunSpec): Promise<string> {\n const args = dockerRunArgs(spec);\n const result = await requireDocker(args, \"Start local Zitadel container\");\n return result.stdout.trim();\n}\n\nexport async function stopAndRemoveContainer(containerName: string): Promise<void> {\n const inspect = await inspectContainer(containerName);\n if (!inspect.exists) {\n return;\n }\n if (inspect.running) {\n await requireDocker([\"stop\", containerName], `Stop ${containerName}`);\n }\n await requireDocker([\"rm\", containerName], `Remove ${containerName}`);\n}\n\nexport async function containerLogs(containerName: string, tail: number): Promise<string> {\n const result = await requireDocker([\"logs\", \"--tail\", String(tail), containerName], \"Read logs\");\n return result.stdout;\n}\n\nexport async function followContainerLogs(containerName: string, tail: number): Promise<void> {\n await streamDocker([\"logs\", \"--tail\", String(tail), \"--follow\", containerName]);\n}\n\nexport function currentUser(): { uid?: number; gid?: number } {\n const getuid = process.getuid;\n const getgid = process.getgid;\n if (typeof getuid !== \"function\") {\n return {};\n }\n const uid = getuid();\n const gid = typeof getgid === \"function\" ? getgid() : uid;\n return { uid, gid };\n}\n\nexport function metadataFromStart(input: {\n cwdDataDir: string;\n cliVersion: string;\n containerName: string;\n containerId: string;\n image: string;\n port: number;\n serverUrl: string;\n}): RuntimeMetadata {\n return {\n schema_version: 1,\n backend: \"docker\",\n container_name: input.containerName,\n container_id: input.containerId,\n image: input.image,\n port: input.port,\n server_url: input.serverUrl,\n data_dir: input.cwdDataDir,\n created_at: new Date().toISOString(),\n cli_version: input.cliVersion,\n };\n}\n\nexport async function requireDocker(args: string[], action: string): Promise<DockerResult> {\n let result: DockerResult;\n try {\n result = await runDocker(args);\n } catch (error) {\n throw dockerError(action, args, error);\n }\n if (result.status !== 0) {\n throw dockerError(action, args, result);\n }\n return result;\n}\n\nfunction dockerError(action: string, args: string[], cause: unknown): ZitadelError {\n const details =\n cause && typeof cause === \"object\" && \"stderr\" in cause\n ? { command: [\"docker\", ...args], stderr: String((cause as { stderr?: unknown }).stderr) }\n : { command: [\"docker\", ...args], cause };\n return new ZitadelError(\"E_VALIDATION\", `${action} failed`, {\n hint: \"Check that Docker is installed, running, and reachable from this shell.\",\n nextCommands: [\"zitadel doctor\"],\n details,\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { x as publicCliCommand } from "./oclif-VkCTGIEk.mjs";
|
|
2
|
+
//#region src/lib/local-server/docker-guidance.ts
|
|
3
|
+
function dockerUnavailableMessage(error) {
|
|
4
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
5
|
+
return `Docker is not reachable${detail.trim() ? ` (${detail.trim()})` : ""}; managed local runtime commands need Docker, but remote or cloud setup can continue with --server <url>.`;
|
|
6
|
+
}
|
|
7
|
+
function dockerRuntimeGuidance(retryCommand, cliVersion) {
|
|
8
|
+
return {
|
|
9
|
+
hint: "Docker is required only for the managed local runtime (`zitadel start` and `--server local`). Start Docker, then retry; or target a remote server with `--server <url>`.",
|
|
10
|
+
nextActions: [
|
|
11
|
+
"Start Docker Desktop, Docker Engine, or a Docker-compatible runtime such as Colima.",
|
|
12
|
+
`Run \`docker version\`, then rerun \`${publicCliCommand(retryCommand, cliVersion)}\`.`,
|
|
13
|
+
"If you are not using the managed local runtime, run setup with `--server <url>` instead."
|
|
14
|
+
],
|
|
15
|
+
nextCommands: ["docker version", publicCliCommand(retryCommand, cliVersion)]
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { dockerUnavailableMessage as n, dockerRuntimeGuidance as t };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=docker-guidance-BvfpmsDj.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-guidance-BvfpmsDj.mjs","names":[],"sources":["../src/lib/local-server/docker-guidance.ts"],"sourcesContent":["import { publicCliCommand } from \"../public-cli\";\n\nexport type DockerRuntimeGuidance = {\n hint: string;\n nextActions: string[];\n nextCommands: string[];\n};\n\nexport function dockerUnavailableMessage(error: unknown): string {\n const detail = error instanceof Error ? error.message : String(error);\n const suffix = detail.trim() ? ` (${detail.trim()})` : \"\";\n return `Docker is not reachable${suffix}; managed local runtime commands need Docker, but remote or cloud setup can continue with --server <url>.`;\n}\n\nexport function dockerRuntimeGuidance(\n retryCommand: \"doctor\" | \"start\",\n cliVersion: string,\n): DockerRuntimeGuidance {\n return {\n hint:\n \"Docker is required only for the managed local runtime (`zitadel start` and `--server local`). Start Docker, then retry; or target a remote server with `--server <url>`.\",\n nextActions: [\n \"Start Docker Desktop, Docker Engine, or a Docker-compatible runtime such as Colima.\",\n `Run \\`docker version\\`, then rerun \\`${publicCliCommand(retryCommand, cliVersion)}\\`.`,\n \"If you are not using the managed local runtime, run setup with `--server <url>` instead.\",\n ],\n nextCommands: [\"docker version\", publicCliCommand(retryCommand, cliVersion)],\n };\n}\n"],"mappings":";;AAQA,SAAgB,yBAAyB,OAAwB;CAC/D,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAErE,QAAO,0BADQ,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,CAAC,KAAK,GACf;;AAG1C,SAAgB,sBACd,cACA,YACuB;AACvB,QAAO;EACL,MACE;EACF,aAAa;GACX;GACA,wCAAwC,iBAAiB,cAAc,WAAW,CAAC;GACnF;GACD;EACD,cAAc,CAAC,kBAAkB,iBAAiB,cAAc,WAAW,CAAC;EAC7E"}
|