@zitadel/cli 0.1.0-alpha.5 → 0.1.0-alpha.9

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.
Files changed (41) hide show
  1. package/README.md +15 -12
  2. package/SKILLS.md +54 -20
  3. package/dist/commands/apply.mjs +3 -3
  4. package/dist/commands/doctor.mjs +160 -26
  5. package/dist/commands/doctor.mjs.map +1 -1
  6. package/dist/commands/eject.mjs +3 -3
  7. package/dist/commands/logs.mjs +13 -5
  8. package/dist/commands/logs.mjs.map +1 -1
  9. package/dist/commands/plan.mjs +3 -3
  10. package/dist/commands/reset.mjs +24 -7
  11. package/dist/commands/reset.mjs.map +1 -1
  12. package/dist/commands/setup.mjs +18 -78
  13. package/dist/commands/setup.mjs.map +1 -1
  14. package/dist/commands/start.mjs +171 -11
  15. package/dist/commands/start.mjs.map +1 -1
  16. package/dist/commands/status.mjs +26 -7
  17. package/dist/commands/status.mjs.map +1 -1
  18. package/dist/commands/stop.mjs +69 -7
  19. package/dist/commands/stop.mjs.map +1 -1
  20. package/dist/docker-CnGQK3ZK.mjs +432 -0
  21. package/dist/docker-CnGQK3ZK.mjs.map +1 -0
  22. package/dist/docker-guidance-ypN3IM3o.mjs +21 -0
  23. package/dist/docker-guidance-ypN3IM3o.mjs.map +1 -0
  24. package/dist/{oclif-2t97lHfY.mjs → oclif-B7lBzh3R.mjs} +51 -26
  25. package/dist/oclif-B7lBzh3R.mjs.map +1 -0
  26. package/dist/{orca-CYqJP4ZJ.mjs → orca-U142Wrau.mjs} +155 -114
  27. package/dist/orca-U142Wrau.mjs.map +1 -0
  28. package/dist/ports-B09RjuHx.mjs +111 -0
  29. package/dist/ports-B09RjuHx.mjs.map +1 -0
  30. package/dist/processes-Cw8TO1SY.mjs +120 -0
  31. package/dist/processes-Cw8TO1SY.mjs.map +1 -0
  32. package/dist/{project-IzPVR0Pr.mjs → project-Cd0L3PtM.mjs} +2 -2
  33. package/dist/{project-IzPVR0Pr.mjs.map → project-Cd0L3PtM.mjs.map} +1 -1
  34. package/dist/{sync-Df9S8Pio.mjs → sync-BojoQm2P.mjs} +2 -2
  35. package/dist/{sync-Df9S8Pio.mjs.map → sync-BojoQm2P.mjs.map} +1 -1
  36. package/oclif.manifest.json +29 -1
  37. package/package.json +8 -42
  38. package/dist/docker--EAWr_WY.mjs +0 -210
  39. package/dist/docker--EAWr_WY.mjs.map +0 -1
  40. package/dist/oclif-2t97lHfY.mjs.map +0 -1
  41. package/dist/orca-CYqJP4ZJ.mjs.map +0 -1
@@ -0,0 +1,432 @@
1
+ import { E as ZitadelError, i as CONTAINER_HTTP_PORT, r as CONTAINER_DATA_DIR } from "./oclif-B7lBzh3R.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 STOP_TIMEOUT_MS = 1e4;
11
+ const STOP_KILL_TIMEOUT_MS = 2e3;
12
+ const require = createRequire(import.meta.url);
13
+ function resolveServerCommand(env = process.env) {
14
+ if (env[START_COMMAND_ENV]) return {
15
+ command: env[START_COMMAND_ENV],
16
+ args: [],
17
+ serverPackage: SERVER_NPM_PACKAGE,
18
+ serverVersion: "override"
19
+ };
20
+ const manifestPath = resolveServerPackageManifest();
21
+ const manifest = require(manifestPath);
22
+ return {
23
+ command: process.execPath,
24
+ args: [join(dirname(manifestPath), "bin", "zitadel-server.js")],
25
+ serverPackage: SERVER_NPM_PACKAGE,
26
+ serverVersion: typeof manifest.version === "string" ? manifest.version : "unknown"
27
+ };
28
+ }
29
+ async function startBinaryRuntime(spec) {
30
+ const command = resolveServerCommand();
31
+ await mkdir(dirname(spec.logPath), {
32
+ recursive: true,
33
+ mode: 448
34
+ });
35
+ const log = await open(spec.logPath, "a", 384);
36
+ try {
37
+ const child = spawn(command.command, command.args, {
38
+ detached: true,
39
+ env: {
40
+ ...process.env,
41
+ NEXTGEN_SERVER_ADDRESS: `:${String(spec.port)}`,
42
+ NEXTGEN_SERVER_DATA_DIR: spec.dataDir
43
+ },
44
+ stdio: [
45
+ "ignore",
46
+ log.fd,
47
+ log.fd
48
+ ]
49
+ });
50
+ child.unref();
51
+ if (!child.pid) throw new Error("server process did not expose a pid");
52
+ return {
53
+ schema_version: 1,
54
+ backend: "binary",
55
+ pid: child.pid,
56
+ command: [command.command, ...command.args].join(" "),
57
+ log_path: spec.logPath,
58
+ server_package: command.serverPackage,
59
+ server_version: command.serverVersion,
60
+ port: spec.port,
61
+ server_url: spec.serverUrl,
62
+ data_dir: spec.dataDir,
63
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
64
+ cli_version: spec.cliVersion
65
+ };
66
+ } finally {
67
+ await log.close();
68
+ }
69
+ }
70
+ async function stopBinaryRuntime(pid) {
71
+ if (!isProcessRunning(pid)) return {
72
+ pid,
73
+ status: "stale",
74
+ target: "process"
75
+ };
76
+ const term = signalRuntime(pid, "SIGTERM");
77
+ if (!term.sent) return {
78
+ pid,
79
+ status: "stale",
80
+ target: term.target
81
+ };
82
+ if (await waitForExit(pid, STOP_TIMEOUT_MS)) return {
83
+ pid,
84
+ status: "stopped",
85
+ target: term.target,
86
+ signal: "SIGTERM"
87
+ };
88
+ if (isProcessRunning(pid)) {
89
+ const kill = signalRuntime(pid, "SIGKILL");
90
+ if (kill.sent && await waitForExit(pid, STOP_KILL_TIMEOUT_MS)) return {
91
+ pid,
92
+ status: "stopped",
93
+ target: kill.target,
94
+ signal: "SIGKILL"
95
+ };
96
+ }
97
+ return {
98
+ pid,
99
+ status: "failed",
100
+ target: term.target,
101
+ signal: "SIGKILL"
102
+ };
103
+ }
104
+ function isProcessRunning(pid) {
105
+ try {
106
+ process.kill(pid, 0);
107
+ return true;
108
+ } catch (error) {
109
+ return isErrno(error, "EPERM");
110
+ }
111
+ }
112
+ async function binaryLogs(logPath, tail) {
113
+ let content = "";
114
+ try {
115
+ content = await readFile(logPath, "utf8");
116
+ } catch (error) {
117
+ if (isErrno(error, "ENOENT")) return "";
118
+ throw error;
119
+ }
120
+ const lines = content.split(/\r?\n/);
121
+ const hasTrailingNewline = lines.at(-1) === "";
122
+ const selected = (hasTrailingNewline ? lines.slice(0, -1) : lines).slice(-tail).join("\n");
123
+ return selected.length === 0 ? "" : `${selected}${hasTrailingNewline ? "\n" : ""}`;
124
+ }
125
+ async function followBinaryLogs(logPath, tail) {
126
+ process.stdout.write(await binaryLogs(logPath, tail));
127
+ let offset = await fileSize(logPath);
128
+ await new Promise((resolveFollow, reject) => {
129
+ const interval = setInterval(() => {
130
+ (async () => {
131
+ try {
132
+ const size = await fileSize(logPath);
133
+ if (size > offset) {
134
+ createReadStream(logPath, {
135
+ start: offset,
136
+ end: size - 1
137
+ }).pipe(process.stdout, { end: false });
138
+ offset = size;
139
+ }
140
+ } catch (error) {
141
+ reject(error);
142
+ }
143
+ })();
144
+ }, 1e3);
145
+ const stop = () => {
146
+ clearInterval(interval);
147
+ resolveFollow();
148
+ };
149
+ process.once("SIGINT", stop);
150
+ process.once("SIGTERM", stop);
151
+ });
152
+ }
153
+ async function assertServerPackageAvailable() {
154
+ try {
155
+ return resolveServerCommand().serverVersion;
156
+ } catch (error) {
157
+ throw new ZitadelError("E_VALIDATION", "Zitadel server npm package is not available", {
158
+ hint: "Reinstall @zitadel/cli so npm can install @zitadel/server and its platform package.",
159
+ nextCommands: ["npm install @zitadel/cli@alpha"],
160
+ details: {
161
+ package: SERVER_NPM_PACKAGE,
162
+ message: errorMessage(error)
163
+ }
164
+ });
165
+ }
166
+ }
167
+ function resolveServerPackageManifest() {
168
+ try {
169
+ return require.resolve(`${SERVER_NPM_PACKAGE}/package.json`);
170
+ } catch (error) {
171
+ throw new Error(`Missing ${SERVER_NPM_PACKAGE}. Reinstall @zitadel/cli.`, { cause: error });
172
+ }
173
+ }
174
+ async function fileSize(path) {
175
+ try {
176
+ return (await stat(path)).size;
177
+ } catch (error) {
178
+ if (isErrno(error, "ENOENT")) return 0;
179
+ throw error;
180
+ }
181
+ }
182
+ function isErrno(error, code) {
183
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
184
+ }
185
+ function signalProcess(pid, signal) {
186
+ try {
187
+ process.kill(pid, signal);
188
+ return true;
189
+ } catch (error) {
190
+ if (isErrno(error, "ESRCH")) return false;
191
+ throw error;
192
+ }
193
+ }
194
+ function signalRuntime(pid, signal) {
195
+ if (process.platform !== "win32") try {
196
+ process.kill(-pid, signal);
197
+ return {
198
+ sent: true,
199
+ target: "process-group"
200
+ };
201
+ } catch (error) {
202
+ if (!isErrno(error, "ESRCH")) throw error;
203
+ }
204
+ return {
205
+ sent: signalProcess(pid, signal),
206
+ target: "process"
207
+ };
208
+ }
209
+ async function waitForExit(pid, timeoutMs) {
210
+ const deadline = Date.now() + timeoutMs;
211
+ while (Date.now() < deadline) {
212
+ if (!isProcessRunning(pid)) return true;
213
+ await delay(200);
214
+ }
215
+ return !isProcessRunning(pid);
216
+ }
217
+ function errorMessage(error) {
218
+ return error instanceof Error ? error.message : String(error);
219
+ }
220
+ function delay(ms) {
221
+ return new Promise((resolveDelay) => setTimeout(resolveDelay, ms));
222
+ }
223
+ //#endregion
224
+ //#region src/lib/local-server/docker.ts
225
+ function dockerRunArgs(spec) {
226
+ const args = [
227
+ "run",
228
+ "--detach",
229
+ "--name",
230
+ spec.containerName,
231
+ "--publish",
232
+ `127.0.0.1:${spec.port}:${CONTAINER_HTTP_PORT}`,
233
+ "--volume",
234
+ `${spec.dataDir}:${CONTAINER_DATA_DIR}`,
235
+ "--env",
236
+ `NEXTGEN_SERVER_ADDRESS=:${CONTAINER_HTTP_PORT}`,
237
+ "--env",
238
+ `NEXTGEN_SERVER_DATA_DIR=${CONTAINER_DATA_DIR}`
239
+ ];
240
+ 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}`);
241
+ args.push(spec.image);
242
+ return args;
243
+ }
244
+ async function runDocker(args) {
245
+ return new Promise((resolve, reject) => {
246
+ const child = spawn("docker", args, {
247
+ stdio: [
248
+ "ignore",
249
+ "pipe",
250
+ "pipe"
251
+ ],
252
+ env: process.env
253
+ });
254
+ let stdout = "";
255
+ let stderr = "";
256
+ child.stdout?.setEncoding("utf8");
257
+ child.stderr?.setEncoding("utf8");
258
+ child.stdout?.on("data", (chunk) => {
259
+ stdout += chunk;
260
+ });
261
+ child.stderr?.on("data", (chunk) => {
262
+ stderr += chunk;
263
+ });
264
+ child.on("error", reject);
265
+ child.on("close", (code) => {
266
+ resolve({
267
+ status: code ?? 1,
268
+ stdout,
269
+ stderr
270
+ });
271
+ });
272
+ });
273
+ }
274
+ async function streamDocker(args) {
275
+ await new Promise((resolve, reject) => {
276
+ const child = spawn("docker", args, {
277
+ stdio: "inherit",
278
+ env: process.env
279
+ });
280
+ child.on("error", reject);
281
+ child.on("close", (code) => {
282
+ if (code === 0) resolve();
283
+ else reject(/* @__PURE__ */ new Error(`docker ${args.join(" ")} exited with status ${code ?? 1}`));
284
+ });
285
+ });
286
+ }
287
+ async function dockerAvailable() {
288
+ return runDocker([
289
+ "version",
290
+ "--format",
291
+ "{{.Server.Version}}"
292
+ ]);
293
+ }
294
+ async function pullImage(image) {
295
+ await requireDocker([
296
+ "pull",
297
+ "--quiet",
298
+ image
299
+ ], `Pull Docker image ${image}`);
300
+ }
301
+ async function imageExists(image) {
302
+ let result;
303
+ const args = [
304
+ "image",
305
+ "inspect",
306
+ image
307
+ ];
308
+ try {
309
+ result = await runDocker(args);
310
+ } catch (error) {
311
+ throw dockerError(`Inspect Docker image ${image}`, args, error);
312
+ }
313
+ return result.status === 0;
314
+ }
315
+ async function imageAvailable(image) {
316
+ if (await imageExists(image)) return "local";
317
+ const args = [
318
+ "manifest",
319
+ "inspect",
320
+ image
321
+ ];
322
+ let result;
323
+ try {
324
+ result = await runDocker(args);
325
+ } catch (error) {
326
+ throw dockerError(`Inspect Docker image ${image}`, args, error);
327
+ }
328
+ if (result.status === 0) return "remote";
329
+ throw dockerError(`Inspect Docker image ${image}`, args, result);
330
+ }
331
+ async function ensureImage(image) {
332
+ if (await imageExists(image)) return "local";
333
+ await pullImage(image);
334
+ return "pulled";
335
+ }
336
+ async function inspectContainer(containerName) {
337
+ const result = await runDocker([
338
+ "inspect",
339
+ "--format",
340
+ "{{.Id}} {{.State.Running}} {{.Config.Image}}",
341
+ containerName
342
+ ]);
343
+ if (result.status !== 0) return {
344
+ exists: false,
345
+ running: false
346
+ };
347
+ const [id, running, ...imageParts] = result.stdout.trim().split(/\s+/);
348
+ return {
349
+ exists: true,
350
+ running: running === "true",
351
+ id,
352
+ image: imageParts.join(" ")
353
+ };
354
+ }
355
+ async function startContainer(spec) {
356
+ return (await requireDocker(dockerRunArgs(spec), "Start local Zitadel container")).stdout.trim();
357
+ }
358
+ async function stopAndRemoveContainer(containerName) {
359
+ const inspect = await inspectContainer(containerName);
360
+ if (!inspect.exists) return;
361
+ if (inspect.running) await requireDocker(["stop", containerName], `Stop ${containerName}`);
362
+ await requireDocker(["rm", containerName], `Remove ${containerName}`);
363
+ }
364
+ async function containerLogs(containerName, tail) {
365
+ return (await requireDocker([
366
+ "logs",
367
+ "--tail",
368
+ String(tail),
369
+ containerName
370
+ ], "Read logs")).stdout;
371
+ }
372
+ async function followContainerLogs(containerName, tail) {
373
+ await streamDocker([
374
+ "logs",
375
+ "--tail",
376
+ String(tail),
377
+ "--follow",
378
+ containerName
379
+ ]);
380
+ }
381
+ function currentUser() {
382
+ const getuid = process.getuid;
383
+ const getgid = process.getgid;
384
+ if (typeof getuid !== "function") return {};
385
+ const uid = getuid();
386
+ return {
387
+ uid,
388
+ gid: typeof getgid === "function" ? getgid() : uid
389
+ };
390
+ }
391
+ function metadataFromStart(input) {
392
+ return {
393
+ schema_version: 1,
394
+ backend: "docker",
395
+ container_name: input.containerName,
396
+ container_id: input.containerId,
397
+ image: input.image,
398
+ port: input.port,
399
+ server_url: input.serverUrl,
400
+ data_dir: input.cwdDataDir,
401
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
402
+ cli_version: input.cliVersion
403
+ };
404
+ }
405
+ async function requireDocker(args, action) {
406
+ let result;
407
+ try {
408
+ result = await runDocker(args);
409
+ } catch (error) {
410
+ throw dockerError(action, args, error);
411
+ }
412
+ if (result.status !== 0) throw dockerError(action, args, result);
413
+ return result;
414
+ }
415
+ function dockerError(action, args, cause) {
416
+ const details = cause && typeof cause === "object" && "stderr" in cause ? {
417
+ command: ["docker", ...args],
418
+ stderr: String(cause.stderr)
419
+ } : {
420
+ command: ["docker", ...args],
421
+ cause
422
+ };
423
+ return new ZitadelError("E_VALIDATION", `${action} failed`, {
424
+ hint: "Check that Docker is installed, running, and reachable from this shell.",
425
+ nextCommands: ["zitadel doctor"],
426
+ details
427
+ });
428
+ }
429
+ //#endregion
430
+ 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 };
431
+
432
+ //# sourceMappingURL=docker-CnGQK3ZK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-CnGQK3ZK.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\";\nconst STOP_TIMEOUT_MS = 10_000;\nconst STOP_KILL_TIMEOUT_MS = 2_000;\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 type StopBinaryRuntimeResult = Readonly<{\n pid: number;\n signal?: NodeJS.Signals;\n status: \"failed\" | \"stale\" | \"stopped\";\n target: \"process\" | \"process-group\";\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<StopBinaryRuntimeResult> {\n if (!isProcessRunning(pid)) {\n return { pid, status: \"stale\", target: \"process\" };\n }\n const term = signalRuntime(pid, \"SIGTERM\");\n if (!term.sent) {\n return { pid, status: \"stale\", target: term.target };\n }\n if (await waitForExit(pid, STOP_TIMEOUT_MS)) {\n return { pid, status: \"stopped\", target: term.target, signal: \"SIGTERM\" };\n }\n\n if (isProcessRunning(pid)) {\n const kill = signalRuntime(pid, \"SIGKILL\");\n if (kill.sent && (await waitForExit(pid, STOP_KILL_TIMEOUT_MS))) {\n return { pid, status: \"stopped\", target: kill.target, signal: \"SIGKILL\" };\n }\n }\n return { pid, status: \"failed\", target: term.target, signal: \"SIGKILL\" };\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 signalRuntime(\n pid: number,\n signal: NodeJS.Signals,\n): { sent: boolean; target: \"process\" | \"process-group\" } {\n if (process.platform !== \"win32\") {\n try {\n process.kill(-pid, signal);\n return { sent: true, target: \"process-group\" };\n } catch (error) {\n if (!isErrno(error, \"ESRCH\")) {\n throw error;\n }\n }\n }\n return { sent: signalProcess(pid, signal), target: \"process\" };\n}\n\nasync function waitForExit(pid: number, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (!isProcessRunning(pid)) {\n return true;\n }\n await delay(200);\n }\n return !isProcessRunning(pid);\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 { b as publicCliCommand } from "./oclif-B7lBzh3R.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-ypN3IM3o.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-guidance-ypN3IM3o.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"}
@@ -6,7 +6,6 @@ import { dirname, join, resolve } from "node:path";
6
6
  import { access, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
7
7
  import { createHash } from "node:crypto";
8
8
  import { constants } from "node:fs";
9
- import { createServer } from "node:net";
10
9
  //#region src/lib/errors.ts
11
10
  /**
12
11
  * Maps each {@link ZitadelErrorCode} to the process exit code the CLI
@@ -21,6 +20,7 @@ const EXIT_CODES = {
21
20
  E_AUTH: 1,
22
21
  E_CONFLICT: 5,
23
22
  E_LOCAL_SERVER_NOT_RUNNING: 4,
23
+ E_PORT_IN_USE: 5,
24
24
  E_VALIDATION: 3,
25
25
  E_NOT_IMPLEMENTED: 2
26
26
  };
@@ -197,6 +197,7 @@ const DEFAULT_LOCAL_SERVER_URL = "http://localhost:8080";
197
197
  const LOCAL_RUNTIME_DIR = ".zitadel/local";
198
198
  const LOCAL_DATA_DIR = ".zitadel/local/nextgen-data";
199
199
  const LOCAL_RUNTIME_FILE = ".zitadel/local/runtime.json";
200
+ const LOCAL_SERVER_LOG_FILE = ".zitadel/local/server.log";
200
201
  const LOCAL_CONTAINER_PASSWD_FILE = ".zitadel/local/container-passwd";
201
202
  const LOCAL_CONTAINER_GROUP_FILE = ".zitadel/local/container-group";
202
203
  const CONTAINER_DATA_DIR = "/var/lib/zitadel/nextgen-data";
@@ -206,6 +207,7 @@ function localRuntimePaths(cwd) {
206
207
  runtimeDir: join(cwd, LOCAL_RUNTIME_DIR),
207
208
  dataDir: join(cwd, LOCAL_DATA_DIR),
208
209
  runtimeFile: join(cwd, LOCAL_RUNTIME_FILE),
210
+ logFile: join(cwd, LOCAL_SERVER_LOG_FILE),
209
211
  containerPasswdFile: join(cwd, LOCAL_CONTAINER_PASSWD_FILE),
210
212
  containerGroupFile: join(cwd, LOCAL_CONTAINER_GROUP_FILE)
211
213
  };
@@ -302,16 +304,6 @@ async function checkLocalServerHealth(serverUrl, timeoutMs = 1500) {
302
304
  return false;
303
305
  }
304
306
  }
305
- async function isPortAvailable(port) {
306
- return new Promise((resolvePort) => {
307
- const server = createServer();
308
- server.once("error", () => resolvePort(false));
309
- server.once("listening", () => {
310
- server.close(() => resolvePort(true));
311
- });
312
- server.listen(port, "127.0.0.1");
313
- });
314
- }
315
307
  async function resolveLocalServer(cwd) {
316
308
  const runtime = await readRuntimeMetadata(cwd);
317
309
  if (runtime) {
@@ -341,22 +333,36 @@ async function appendGitignoreEntry(cwd, entry) {
341
333
  await writeFile(path, `${existing}${prefix}${entry}\n`);
342
334
  }
343
335
  function normalizeRuntimeMetadata(input) {
344
- if (input.schema_version !== 1 || typeof input.container_name !== "string" || typeof input.container_id !== "string" || typeof input.image !== "string" || typeof input.port !== "number" || !isValidPort(input.port) || typeof input.server_url !== "string" || !isValidServerUrl(input.server_url, input.port) || typeof input.data_dir !== "string" || typeof input.created_at !== "string" || typeof input.cli_version !== "string") throw new ZitadelError("E_VALIDATION", `${LOCAL_RUNTIME_FILE} is malformed`, {
345
- hint: "Run `zitadel reset --force`, then `zitadel start`.",
346
- nextCommands: ["zitadel reset --force", "zitadel start"],
347
- details: input
348
- });
349
- return {
336
+ if (input.schema_version !== 1 || typeof input.port !== "number" || !isValidPort(input.port) || typeof input.server_url !== "string" || !isValidServerUrl(input.server_url, input.port) || typeof input.data_dir !== "string" || typeof input.created_at !== "string" || typeof input.cli_version !== "string") throw malformedRuntime(input);
337
+ const backend = input.backend === void 0 ? "docker" : input.backend;
338
+ const base = {
350
339
  schema_version: 1,
351
- container_name: input.container_name,
352
- container_id: input.container_id,
353
- image: input.image,
354
340
  port: input.port,
355
341
  server_url: input.server_url,
356
342
  data_dir: input.data_dir,
357
343
  created_at: input.created_at,
358
344
  cli_version: input.cli_version
359
345
  };
346
+ if (backend === "binary") {
347
+ if (typeof input.pid !== "number" || !Number.isInteger(input.pid) || input.pid <= 0 || typeof input.command !== "string" || typeof input.log_path !== "string" || typeof input.server_package !== "string" || typeof input.server_version !== "string") throw malformedRuntime(input);
348
+ return {
349
+ ...base,
350
+ backend: "binary",
351
+ pid: input.pid,
352
+ command: input.command,
353
+ log_path: input.log_path,
354
+ server_package: input.server_package,
355
+ server_version: input.server_version
356
+ };
357
+ }
358
+ if (backend !== "docker" || typeof input.container_name !== "string" || typeof input.container_id !== "string" || typeof input.image !== "string") throw malformedRuntime(input);
359
+ return {
360
+ ...base,
361
+ backend: "docker",
362
+ container_name: input.container_name,
363
+ container_id: input.container_id,
364
+ image: input.image
365
+ };
360
366
  }
361
367
  async function nearestExistingDirectory(path) {
362
368
  let current = path;
@@ -375,16 +381,28 @@ function isErrno(error, code) {
375
381
  }
376
382
  function runtimeSummary(metadata) {
377
383
  if (!metadata) return { configured: false };
378
- return {
384
+ const base = {
379
385
  configured: true,
380
- container_name: metadata.container_name,
381
- container_id: metadata.container_id,
382
- image: metadata.image,
386
+ backend: metadata.backend,
383
387
  port: metadata.port,
384
388
  server_url: metadata.server_url,
385
389
  data_dir: metadata.data_dir,
386
390
  created_at: metadata.created_at
387
391
  };
392
+ if (metadata.backend === "binary") return {
393
+ ...base,
394
+ pid: metadata.pid,
395
+ command: metadata.command,
396
+ log_path: metadata.log_path,
397
+ server_package: metadata.server_package,
398
+ server_version: metadata.server_version
399
+ };
400
+ return {
401
+ ...base,
402
+ container_name: metadata.container_name,
403
+ container_id: metadata.container_id,
404
+ image: metadata.image
405
+ };
388
406
  }
389
407
  function isValidPort(value) {
390
408
  return Number.isInteger(value) && value >= 1 && value <= 65535;
@@ -403,6 +421,13 @@ function explicitUrlPort(value) {
403
421
  const port = Number(match[1]);
404
422
  return isValidPort(port) ? port : void 0;
405
423
  }
424
+ function malformedRuntime(input) {
425
+ return new ZitadelError("E_VALIDATION", `${LOCAL_RUNTIME_FILE} is malformed`, {
426
+ hint: "Run `zitadel reset --force`, then `zitadel start`.",
427
+ nextCommands: ["zitadel reset --force", "zitadel start"],
428
+ details: input
429
+ });
430
+ }
406
431
  //#endregion
407
432
  //#region src/lib/server.ts
408
433
  /**
@@ -778,6 +803,6 @@ function suffixBlock(opts) {
778
803
  return suffix ? ` ${suffix}` : "";
779
804
  }
780
805
  //#endregion
781
- export { resolveCwd as C, ZitadelError as D, stableStringify as E, toZitadelError as O, MANAGED_MARKER as S, parseJsonObject as T, removeRuntimeMetadata as _, DEFAULT_LOCAL_SERVER_PORT as a, npmDistTagForCliVersion as b, checkLocalServerHealth as c, ensureLocalState as d, isPortAvailable as f, removeLocalData as g, readRuntimeMetadata as h, CONTAINER_HTTP_PORT as i, defaultLocalServerImageForCliVersion as l, localServerUrl as m, DEFAULT_SERVER as n, DEFAULT_LOCAL_SERVER_URL as o, localContainerName as p, CONTAINER_DATA_DIR as r, assertLocalStateWritable as s, BaseCommand as t, ensureContainerIdentity as u, runtimeSummary as v, isObject as w, publicCliCommand as x, writeRuntimeMetadata as y };
806
+ export { isObject as C, toZitadelError as D, ZitadelError as E, resolveCwd as S, stableStringify as T, runtimeSummary as _, DEFAULT_LOCAL_SERVER_PORT as a, publicCliCommand as b, checkLocalServerHealth as c, ensureLocalState as d, localContainerName as f, removeRuntimeMetadata as g, removeLocalData as h, CONTAINER_HTTP_PORT as i, defaultLocalServerImageForCliVersion as l, readRuntimeMetadata as m, DEFAULT_SERVER as n, DEFAULT_LOCAL_SERVER_URL as o, localServerUrl as p, CONTAINER_DATA_DIR as r, assertLocalStateWritable as s, BaseCommand as t, ensureContainerIdentity as u, writeRuntimeMetadata as v, parseJsonObject as w, MANAGED_MARKER as x, npmDistTagForCliVersion as y };
782
807
 
783
- //# sourceMappingURL=oclif-2t97lHfY.mjs.map
808
+ //# sourceMappingURL=oclif-B7lBzh3R.mjs.map