withvibe 0.1.4

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 (62) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +67 -0
  3. package/dist/api.js +29 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/assets/docker-compose.yml +130 -0
  6. package/dist/config.js +48 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/env-command.js +331 -0
  9. package/dist/env-command.js.map +1 -0
  10. package/dist/exec.js +35 -0
  11. package/dist/exec.js.map +1 -0
  12. package/dist/git-auth.js +64 -0
  13. package/dist/git-auth.js.map +1 -0
  14. package/dist/index.js +42 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/install/anthropic-validate.js +73 -0
  17. package/dist/install/anthropic-validate.js.map +1 -0
  18. package/dist/install/build-images.js +99 -0
  19. package/dist/install/build-images.js.map +1 -0
  20. package/dist/install/commands/build-images-cmd.js +68 -0
  21. package/dist/install/commands/build-images-cmd.js.map +1 -0
  22. package/dist/install/commands/configure.js +276 -0
  23. package/dist/install/commands/configure.js.map +1 -0
  24. package/dist/install/commands/lifecycle.js +129 -0
  25. package/dist/install/commands/lifecycle.js.map +1 -0
  26. package/dist/install/commands/uninstall.js +88 -0
  27. package/dist/install/commands/uninstall.js.map +1 -0
  28. package/dist/install/commands/upgrade.js +164 -0
  29. package/dist/install/commands/upgrade.js.map +1 -0
  30. package/dist/install/compose-rewriter.js +298 -0
  31. package/dist/install/compose-rewriter.js.map +1 -0
  32. package/dist/install/compose.js +118 -0
  33. package/dist/install/compose.js.map +1 -0
  34. package/dist/install/doctor.js +176 -0
  35. package/dist/install/doctor.js.map +1 -0
  36. package/dist/install/env-file.js +63 -0
  37. package/dist/install/env-file.js.map +1 -0
  38. package/dist/install/exec.js +32 -0
  39. package/dist/install/exec.js.map +1 -0
  40. package/dist/install/images.js +78 -0
  41. package/dist/install/images.js.map +1 -0
  42. package/dist/install/init.js +584 -0
  43. package/dist/install/init.js.map +1 -0
  44. package/dist/install/log.js +15 -0
  45. package/dist/install/log.js.map +1 -0
  46. package/dist/install/paths.js +26 -0
  47. package/dist/install/paths.js.map +1 -0
  48. package/dist/install/ports.js +23 -0
  49. package/dist/install/ports.js.map +1 -0
  50. package/dist/install/register.js +155 -0
  51. package/dist/install/register.js.map +1 -0
  52. package/dist/install/secrets.js +9 -0
  53. package/dist/install/secrets.js.map +1 -0
  54. package/dist/install/state.js +29 -0
  55. package/dist/install/state.js.map +1 -0
  56. package/dist/login.js +56 -0
  57. package/dist/login.js.map +1 -0
  58. package/dist/ports.js +33 -0
  59. package/dist/ports.js.map +1 -0
  60. package/dist/preflight.js +150 -0
  61. package/dist/preflight.js.map +1 -0
  62. package/package.json +38 -0
@@ -0,0 +1,99 @@
1
+ import path from "node:path";
2
+ import { run } from "../exec.js";
3
+ import { log } from "./log.js";
4
+ import { EXTERNAL_IMAGES, imagesForFeatures, registryName, STACK_IMAGES, } from "./images.js";
5
+ // Build every stack image enabled by the install's features, locally, in
6
+ // place. Streams docker output so the operator can see progress.
7
+ export async function buildAllImages(opts) {
8
+ const images = imagesForFeatures(opts.features);
9
+ log.header(`Building ${images.length} image(s) from source`);
10
+ for (const img of images) {
11
+ await buildOne(img, opts.repoPath);
12
+ }
13
+ log.ok("All images built.");
14
+ }
15
+ async function buildOne(img, repoPath) {
16
+ const args = ["build", "-t", img.localName];
17
+ if (img.dockerfile)
18
+ args.push("-f", path.join(repoPath, img.dockerfile));
19
+ args.push(path.join(repoPath, img.contextDir));
20
+ log.step(`docker ${args.join(" ")}`);
21
+ const res = await run("docker", args, { streamTo: "inherit" });
22
+ if (res.code !== 0) {
23
+ throw new Error(`docker build failed for ${img.label} (exit ${res.code})`);
24
+ }
25
+ log.ok(`Built ${img.localName}`);
26
+ }
27
+ // Pull each image from a registry and re-tag it to the local name the api
28
+ // expects. We always tag locally as :latest because the api pins to that.
29
+ export async function pullAllImages(opts) {
30
+ const images = imagesForFeatures(opts.features);
31
+ log.header(`Pulling ${images.length} image(s) from ${opts.namespace}`);
32
+ for (const img of images) {
33
+ const remote = registryName(img.localName, opts.namespace, opts.tag);
34
+ log.step(`docker pull ${remote}`);
35
+ const pull = await run("docker", ["pull", remote], { streamTo: "inherit" });
36
+ if (pull.code !== 0) {
37
+ throw new Error(`docker pull failed for ${remote} (exit ${pull.code})`);
38
+ }
39
+ if (remote !== img.localName) {
40
+ const tag = await run("docker", ["tag", remote, img.localName]);
41
+ if (tag.code !== 0) {
42
+ throw new Error(`docker tag ${remote} ${img.localName} failed`);
43
+ }
44
+ }
45
+ log.ok(`Tagged as ${img.localName}`);
46
+ }
47
+ // Postgres is referenced by tag in compose; ensure it's local too so
48
+ // `compose up` doesn't surprise-pull on first start.
49
+ log.step(`docker pull ${EXTERNAL_IMAGES.postgres}`);
50
+ await run("docker", ["pull", EXTERNAL_IMAGES.postgres], { streamTo: "inherit" });
51
+ }
52
+ // Load images from an offline bundle (created by scripts/build-bundle.sh).
53
+ // Accepts either the .tar directly or the bundle directory.
54
+ export async function loadBundleImages(opts) {
55
+ const tarPath = opts.bundlePath.endsWith(".tar")
56
+ ? opts.bundlePath
57
+ : path.join(opts.bundlePath, "images.tar");
58
+ log.header(`Loading images from ${tarPath}`);
59
+ const res = await run("docker", ["load", "-i", tarPath], { streamTo: "inherit" });
60
+ if (res.code !== 0) {
61
+ throw new Error(`docker load failed (exit ${res.code})`);
62
+ }
63
+ log.ok("Bundle images loaded.");
64
+ }
65
+ // Check which expected images are present locally. Used by `status` and
66
+ // before `compose up` so we can warn before the api crashes on a missing
67
+ // sidecar image.
68
+ //
69
+ // `bundleVersion` (from state.bundle.version) overrides the :latest fallback
70
+ // for every withvibe image — both compose (api/web) and the api's sidecar
71
+ // spawners resolve the same tag from $WITHVIBE_VERSION at runtime.
72
+ export async function imagePresence(features, bundleVersion) {
73
+ const expected = imagesForFeatures(features).map((i) => retagToVersion(i.localName, bundleVersion));
74
+ expected.push(EXTERNAL_IMAGES.postgres);
75
+ const out = [];
76
+ for (const name of expected) {
77
+ const res = await run("docker", ["image", "inspect", name]);
78
+ out.push({ image: name, present: res.code === 0 });
79
+ }
80
+ return out;
81
+ }
82
+ function retagToVersion(local, version) {
83
+ if (!version)
84
+ return local;
85
+ // Replace :latest with the bundle's version tag. All withvibe local names
86
+ // end in :latest (see images.ts).
87
+ if (local.endsWith(":latest")) {
88
+ return `${local.slice(0, -":latest".length)}:${version}`;
89
+ }
90
+ return local;
91
+ }
92
+ // Convenience: which stack image specs the registry namespace would push to.
93
+ // Used by `status` to print the expected remote tags.
94
+ export function expectedRemotes(namespace, tag, features) {
95
+ return imagesForFeatures(features).map((i) => registryName(i.localName, namespace, tag));
96
+ }
97
+ // Re-export the spec list so callers don't need to import from two places.
98
+ export { STACK_IMAGES };
99
+ //# sourceMappingURL=build-images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-images.js","sourceRoot":"","sources":["../../src/install/build-images.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import { buildAllImages, loadBundleImages, pullAllImages, } from "../build-images.js";
4
+ import { log } from "../log.js";
5
+ import { DEFAULT_INSTALL_DIR, expandHome } from "../paths.js";
6
+ import { readState } from "../state.js";
7
+ export async function runBuildImages(args) {
8
+ const installDir = args.installDir
9
+ ? path.resolve(expandHome(args.installDir))
10
+ : DEFAULT_INSTALL_DIR;
11
+ const state = await readState(installDir);
12
+ if (!state) {
13
+ log.fail(`No install state at ${installDir}. Run \`withvibe init\` first, or pass --repo-path / --bundle-path to override.`);
14
+ if (!args.repoPath && !args.bundlePath)
15
+ process.exit(1);
16
+ }
17
+ const repoPath = args.repoPath
18
+ ? path.resolve(expandHome(args.repoPath))
19
+ : state?.source?.repoPath;
20
+ const bundlePath = args.bundlePath
21
+ ? path.resolve(expandHome(args.bundlePath))
22
+ : state?.bundle?.bundlePath;
23
+ const features = state?.features ?? {
24
+ qaBrowser: true,
25
+ codeServer: true,
26
+ traefik: false,
27
+ googleOAuth: false,
28
+ };
29
+ const mode = state?.mode ?? (repoPath ? "from-source" : bundlePath ? "from-bundle" : null);
30
+ if (!mode) {
31
+ log.fail("Cannot determine install mode. Run init or pass --repo-path / --bundle-path.");
32
+ process.exit(1);
33
+ }
34
+ if (mode === "from-source") {
35
+ if (!repoPath) {
36
+ log.fail("from-source requires a source tree. Pass --repo-path.");
37
+ process.exit(1);
38
+ }
39
+ await assertDir(repoPath, "Source tree");
40
+ await buildAllImages({ repoPath, features });
41
+ }
42
+ else if (mode === "from-bundle") {
43
+ if (!bundlePath) {
44
+ log.fail("from-bundle requires the bundle path. Pass --bundle-path.");
45
+ process.exit(1);
46
+ }
47
+ await loadBundleImages({ bundlePath });
48
+ }
49
+ else {
50
+ if (!state?.registry) {
51
+ log.fail("from-registry requires registry config in install state.");
52
+ process.exit(1);
53
+ }
54
+ await pullAllImages({
55
+ namespace: state.registry.namespace,
56
+ tag: state.registry.tag,
57
+ features,
58
+ });
59
+ }
60
+ }
61
+ async function assertDir(p, label) {
62
+ const stat = await fs.stat(p).catch(() => null);
63
+ if (!stat?.isDirectory()) {
64
+ log.fail(`${label} not found: ${p}`);
65
+ process.exit(1);
66
+ }
67
+ }
68
+ //# sourceMappingURL=build-images-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-images-cmd.js","sourceRoot":"","sources":["../../../src/install/commands/build-images-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,276 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import prompts from "prompts";
4
+ import ora from "ora";
5
+ import { log } from "../log.js";
6
+ import { composePath, DEFAULT_INSTALL_DIR, envPath, expandHome, } from "../paths.js";
7
+ import { readEnvFile, serializeEnv, writeEnvFile } from "../env-file.js";
8
+ import { setTraefik } from "../compose-rewriter.js";
9
+ import { readState, writeState } from "../state.js";
10
+ import { validateAnthropicKey } from "../anthropic-validate.js";
11
+ import { randomSecret } from "../secrets.js";
12
+ import { buildAllImages, pullAllImages } from "../build-images.js";
13
+ export async function runConfigure(args) {
14
+ const installDir = args.installDir
15
+ ? path.resolve(expandHome(args.installDir))
16
+ : DEFAULT_INSTALL_DIR;
17
+ const state = await readState(installDir);
18
+ if (!state) {
19
+ log.fail(`No install at ${installDir}. Run \`withvibe init\` first.`);
20
+ process.exit(1);
21
+ }
22
+ log.header("withvibe — configure");
23
+ log.info(`Editing install at ${installDir}`);
24
+ for (;;) {
25
+ const choice = await prompts({
26
+ type: "select",
27
+ name: "v",
28
+ message: "What do you want to change?",
29
+ choices: [
30
+ { title: `Traefik (TLS + subdomain routing): ${onOff(state.features.traefik)}`, value: "traefik" },
31
+ { title: `QA browser sidecar: ${onOff(state.features.qaBrowser)}`, value: "qaBrowser" },
32
+ { title: `code-server sidecar: ${onOff(state.features.codeServer)}`, value: "codeServer" },
33
+ { title: `Google OAuth: ${onOff(state.features.googleOAuth)}`, value: "google" },
34
+ { title: "GitHub token", value: "github" },
35
+ { title: "Public URLs (PUBLIC_HOST / WEB_PUBLIC_URL / API_PUBLIC_URL)", value: "urls" },
36
+ { title: "Rotate secrets (INTERNAL_JWT_SECRET / POSTGRES_PASSWORD)", value: "rotate" },
37
+ { title: "Update Anthropic key", value: "anthropic" },
38
+ { title: "Save & exit", value: "exit" },
39
+ ],
40
+ initial: 0,
41
+ }, { onCancel: () => process.exit(0) });
42
+ if (!choice.v || choice.v === "exit")
43
+ break;
44
+ if (choice.v === "traefik")
45
+ await toggleTraefik(state, installDir);
46
+ else if (choice.v === "qaBrowser")
47
+ await toggleSidecar(state, installDir, "qaBrowser");
48
+ else if (choice.v === "codeServer")
49
+ await toggleSidecar(state, installDir, "codeServer");
50
+ else if (choice.v === "google")
51
+ await toggleGoogle(state, installDir);
52
+ else if (choice.v === "github")
53
+ await editGithubToken(installDir);
54
+ else if (choice.v === "urls")
55
+ await editUrls(installDir);
56
+ else if (choice.v === "rotate")
57
+ await rotateSecrets(installDir);
58
+ else if (choice.v === "anthropic")
59
+ await updateAnthropicKey(installDir);
60
+ await writeState(installDir, state);
61
+ }
62
+ log.ok("Saved.");
63
+ log.dim("Restart affected services with `withvibe restart`.");
64
+ }
65
+ function onOff(b) {
66
+ return b ? "ON" : "off";
67
+ }
68
+ async function toggleTraefik(state, installDir) {
69
+ const enable = !state.features.traefik;
70
+ if (enable) {
71
+ const baseDomain = await ask({
72
+ type: "text",
73
+ name: "v",
74
+ message: "Traefik base domain (e.g. withvibe.example.com):",
75
+ initial: state.traefik?.baseDomain ?? "",
76
+ validate: (v) => /^[a-z0-9.-]+\.[a-z]{2,}$/i.test(v.trim())
77
+ ? true
78
+ : "Enter a valid domain",
79
+ });
80
+ const acmeEmail = await ask({
81
+ type: "text",
82
+ name: "v",
83
+ message: "ACME email (Let's Encrypt):",
84
+ initial: state.traefik?.acmeEmail ?? "",
85
+ validate: (v) => /.+@.+\..+/.test(v.trim()) ? true : "Enter a valid email",
86
+ });
87
+ state.traefik = { baseDomain: baseDomain.trim(), acmeEmail: acmeEmail.trim() };
88
+ state.features.traefik = true;
89
+ await mergeEnv(installDir, {
90
+ TRAEFIK_BASE_DOMAIN: state.traefik.baseDomain,
91
+ TRAEFIK_ACME_EMAIL: state.traefik.acmeEmail,
92
+ });
93
+ }
94
+ else {
95
+ state.features.traefik = false;
96
+ state.traefik = undefined;
97
+ }
98
+ await rewriteCompose(installDir, (yaml) => setTraefik(yaml, enable, state.traefik?.baseDomain));
99
+ log.ok(`Traefik ${enable ? "enabled" : "disabled"}.`);
100
+ }
101
+ async function toggleSidecar(state, installDir, feature) {
102
+ const next = !state.features[feature];
103
+ state.features[feature] = next;
104
+ if (!next) {
105
+ log.ok(`${feature} disabled in state. Existing local image (if any) is left in place; remove with \`docker image rm\` if you want to free space.`);
106
+ return;
107
+ }
108
+ // Re-enabling: make sure the image is present.
109
+ const featureFlags = state.features;
110
+ if (state.mode === "from-source" && state.source) {
111
+ await buildAllImages({ repoPath: state.source.repoPath, features: featureFlags });
112
+ }
113
+ else if (state.mode === "from-registry" && state.registry) {
114
+ await pullAllImages({
115
+ namespace: state.registry.namespace,
116
+ tag: state.registry.tag,
117
+ features: featureFlags,
118
+ });
119
+ }
120
+ else {
121
+ log.warn(`${feature} re-enabled but image must be (re)loaded manually for from-bundle installs.`);
122
+ }
123
+ }
124
+ async function toggleGoogle(state, installDir) {
125
+ const next = !state.features.googleOAuth;
126
+ if (next) {
127
+ const id = await ask({
128
+ type: "text",
129
+ name: "v",
130
+ message: "GOOGLE_CLIENT_ID:",
131
+ validate: (v) => (v.trim() ? true : "Required"),
132
+ });
133
+ const secret = await ask({
134
+ type: "password",
135
+ name: "v",
136
+ message: "GOOGLE_CLIENT_SECRET:",
137
+ validate: (v) => (v.trim() ? true : "Required"),
138
+ });
139
+ await mergeEnv(installDir, {
140
+ GOOGLE_CLIENT_ID: id.trim(),
141
+ GOOGLE_CLIENT_SECRET: secret,
142
+ });
143
+ }
144
+ else {
145
+ await mergeEnv(installDir, {
146
+ GOOGLE_CLIENT_ID: "",
147
+ GOOGLE_CLIENT_SECRET: "",
148
+ });
149
+ }
150
+ state.features.googleOAuth = next;
151
+ log.ok(`Google OAuth ${next ? "enabled" : "disabled"}.`);
152
+ }
153
+ async function editGithubToken(installDir) {
154
+ const token = await ask({
155
+ type: "password",
156
+ name: "v",
157
+ message: "GITHUB_TOKEN (blank to clear):",
158
+ initial: "",
159
+ });
160
+ await mergeEnv(installDir, { GITHUB_TOKEN: token });
161
+ log.ok(`GITHUB_TOKEN ${token ? "updated" : "cleared"}.`);
162
+ }
163
+ async function editUrls(installDir) {
164
+ const env = await readEnvFile(envPath(installDir));
165
+ const publicHost = await ask({
166
+ type: "text",
167
+ name: "v",
168
+ message: "PUBLIC_HOST:",
169
+ initial: env.PUBLIC_HOST ?? "localhost",
170
+ });
171
+ const web = await ask({
172
+ type: "text",
173
+ name: "v",
174
+ message: "WEB_PUBLIC_URL:",
175
+ initial: env.WEB_PUBLIC_URL ?? `http://${publicHost}:3000`,
176
+ });
177
+ const api = await ask({
178
+ type: "text",
179
+ name: "v",
180
+ message: "API_PUBLIC_URL:",
181
+ initial: env.API_PUBLIC_URL ?? `http://${publicHost}:4000`,
182
+ });
183
+ await mergeEnv(installDir, {
184
+ PUBLIC_HOST: publicHost.trim(),
185
+ WEB_PUBLIC_URL: web.trim(),
186
+ API_PUBLIC_URL: api.trim(),
187
+ });
188
+ log.ok("URLs updated.");
189
+ }
190
+ async function rotateSecrets(installDir) {
191
+ const which = await prompts({
192
+ type: "multiselect",
193
+ name: "v",
194
+ message: "Which secrets to rotate?",
195
+ choices: [
196
+ {
197
+ title: "INTERNAL_JWT_SECRET (invalidates every active session)",
198
+ value: "jwt",
199
+ },
200
+ {
201
+ title: "POSTGRES_PASSWORD (requires DB password change inside postgres too)",
202
+ value: "pg",
203
+ },
204
+ ],
205
+ hint: "space to select, enter to confirm",
206
+ }, { onCancel: () => process.exit(0) });
207
+ const picks = (which.v ?? []);
208
+ if (picks.length === 0)
209
+ return;
210
+ const update = {};
211
+ if (picks.includes("jwt"))
212
+ update.INTERNAL_JWT_SECRET = randomSecret(32);
213
+ if (picks.includes("pg")) {
214
+ log.warn("Rotating POSTGRES_PASSWORD only updates .env. You must ALSO ALTER USER inside postgres before restarting.");
215
+ update.POSTGRES_PASSWORD = randomSecret(24);
216
+ }
217
+ await mergeEnv(installDir, update);
218
+ log.ok("Secrets rotated.");
219
+ }
220
+ async function updateAnthropicKey(installDir) {
221
+ const key = await ask({
222
+ type: "password",
223
+ name: "v",
224
+ message: "ANTHROPIC_API_KEY:",
225
+ validate: (v) => {
226
+ const trimmed = v.trim();
227
+ if (!trimmed)
228
+ return "Required";
229
+ if (!/^sk-ant-(api|oat)/.test(trimmed))
230
+ return "Must start with `sk-ant-api` (API key) or `sk-ant-oat` (Claude Max/Pro OAuth token).";
231
+ if (trimmed.length < 40)
232
+ return "Key looks too short to be valid. Re-paste the full key.";
233
+ return true;
234
+ },
235
+ });
236
+ const spinner = ora("Validating key…").start();
237
+ const r = await validateAnthropicKey(key);
238
+ if (r.ok) {
239
+ spinner.succeed(r.kind === "oauth-token"
240
+ ? "Claude Max/Pro OAuth token accepted (live-check skipped — only API keys can be live-validated)"
241
+ : "API key is valid");
242
+ }
243
+ else {
244
+ spinner.fail(r.error);
245
+ const proceed = await prompts({ type: "confirm", name: "v", message: "Save anyway?", initial: false }, { onCancel: () => process.exit(0) });
246
+ if (!proceed.v)
247
+ return;
248
+ }
249
+ // Both API keys and OAuth tokens live in the same .env slot; the api code
250
+ // (chat-stream.service.ts) detects the prefix and routes at spawn time.
251
+ await mergeEnv(installDir, { ANTHROPIC_API_KEY: key });
252
+ log.ok("ANTHROPIC_API_KEY updated.");
253
+ }
254
+ async function mergeEnv(installDir, patch) {
255
+ const existing = await readEnvFile(envPath(installDir));
256
+ const merged = { ...existing, ...patch };
257
+ // Preserve existing key order; new keys are appended.
258
+ const order = Array.from(new Set([...Object.keys(existing), ...Object.keys(patch)]));
259
+ await writeEnvFile(envPath(installDir), serializeEnv(merged, order));
260
+ }
261
+ async function rewriteCompose(installDir, fn) {
262
+ const file = composePath(installDir);
263
+ const original = await fs.readFile(file, "utf8");
264
+ const next = fn(original);
265
+ if (next === original)
266
+ return;
267
+ // Atomic write: never leave compose half-written.
268
+ const tmp = file + ".tmp";
269
+ await fs.writeFile(tmp, next);
270
+ await fs.rename(tmp, file);
271
+ }
272
+ async function ask(q) {
273
+ const r = await prompts(q, { onCancel: () => process.exit(0) });
274
+ return typeof r.v === "string" ? r.v : "";
275
+ }
276
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../../../src/install/commands/configure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ import path from "node:path";
2
+ import ora from "ora";
3
+ import { compose, composePs, readPublicUrls, waitForUrl } from "../compose.js";
4
+ import { imagePresence } from "../build-images.js";
5
+ import { log } from "../log.js";
6
+ import { DEFAULT_INSTALL_DIR, expandHome } from "../paths.js";
7
+ import { readState } from "../state.js";
8
+ function resolveInstallDir(args) {
9
+ return args.installDir
10
+ ? path.resolve(expandHome(args.installDir))
11
+ : DEFAULT_INSTALL_DIR;
12
+ }
13
+ export async function runStart(args) {
14
+ const installDir = resolveInstallDir(args);
15
+ const state = await readState(installDir);
16
+ if (!state) {
17
+ log.fail(`No install state at ${installDir}. Run \`withvibe init\` first.`);
18
+ process.exit(1);
19
+ }
20
+ // Pre-check: warn if any expected images are missing. Don't block — `compose
21
+ // up` will fail with its own error, but the operator should know to run
22
+ // `build-images` first if they skipped that step.
23
+ const presence = await imagePresence(state.features, state.bundle?.version);
24
+ const missing = presence.filter((p) => !p.present);
25
+ if (missing.length > 0) {
26
+ log.warn(`Missing images (compose may fail): ${missing.map((m) => m.image).join(", ")}`);
27
+ log.dim(` Run \`withvibe build-images\` first.`);
28
+ }
29
+ log.header("Starting stack");
30
+ const up = await compose(installDir, ["up", "-d"]);
31
+ if (up.code !== 0) {
32
+ log.fail(`compose up failed (exit ${up.code})`);
33
+ process.exit(up.code);
34
+ }
35
+ // Health gate: poll the web app first (its readiness implies the api is
36
+ // reachable inside the network), then the api directly.
37
+ const urls = await readPublicUrls(installDir);
38
+ if (urls.api) {
39
+ await waitFor("api", `${urls.api.replace(/\/+$/, "")}/api/health`);
40
+ }
41
+ if (urls.web) {
42
+ await waitFor("web", urls.web);
43
+ }
44
+ log.ok("Stack started.");
45
+ if (urls.web)
46
+ log.info(` Web: ${urls.web}`);
47
+ if (urls.api)
48
+ log.info(` API: ${urls.api}`);
49
+ }
50
+ async function waitFor(label, url) {
51
+ const spinner = ora(`Waiting for ${label} (${url})…`).start();
52
+ const r = await waitForUrl(url);
53
+ if (r.ok)
54
+ spinner.succeed(`${label} reachable (HTTP ${r.lastStatus})`);
55
+ else
56
+ spinner.fail(`${label} did not become reachable: ${r.lastError ?? `HTTP ${r.lastStatus}`}`);
57
+ }
58
+ export async function runStop(args) {
59
+ const installDir = resolveInstallDir(args);
60
+ log.header("Stopping stack");
61
+ const res = await compose(installDir, ["down"]);
62
+ if (res.code !== 0) {
63
+ log.fail(`compose down failed (exit ${res.code})`);
64
+ process.exit(res.code);
65
+ }
66
+ log.ok("Stack stopped.");
67
+ }
68
+ export async function runRestart(args) {
69
+ const installDir = resolveInstallDir(args);
70
+ log.header("Restarting stack");
71
+ // Use `up -d` rather than `restart` so containers get recreated when the
72
+ // image they were built from has changed (which is the whole reason a
73
+ // user runs `withvibe restart` after `build-images`). `restart` alone
74
+ // reuses the old container layer and silently keeps stale code running.
75
+ const res = await compose(installDir, ["up", "-d"]);
76
+ if (res.code !== 0) {
77
+ log.fail(`compose up failed (exit ${res.code})`);
78
+ process.exit(res.code);
79
+ }
80
+ log.ok("Stack restarted.");
81
+ }
82
+ export async function runStatus(args) {
83
+ const installDir = resolveInstallDir(args);
84
+ const state = await readState(installDir);
85
+ if (!state) {
86
+ log.fail(`No install state at ${installDir}.`);
87
+ process.exit(1);
88
+ }
89
+ log.header("Install");
90
+ log.info(`Mode: ${state.mode}`);
91
+ log.info(`Install dir: ${installDir}`);
92
+ log.info(`Features: traefik=${state.features.traefik} qaBrowser=${state.features.qaBrowser} codeServer=${state.features.codeServer} googleOAuth=${state.features.googleOAuth}`);
93
+ log.header("Services");
94
+ const services = await composePs(installDir);
95
+ if (services.length === 0) {
96
+ log.warn("No services running (or compose ps failed).");
97
+ }
98
+ else {
99
+ for (const s of services) {
100
+ const health = s.health ? ` (${s.health})` : "";
101
+ const dot = s.state === "running" ? "●" : "○";
102
+ log.info(` ${dot} ${s.name}: ${s.state}${health}`);
103
+ }
104
+ }
105
+ log.header("Images");
106
+ const presence = await imagePresence(state.features, state.bundle?.version);
107
+ for (const p of presence) {
108
+ if (p.present)
109
+ log.ok(` ${p.image}`);
110
+ else
111
+ log.fail(` ${p.image} — not present`);
112
+ }
113
+ const urls = await readPublicUrls(installDir);
114
+ log.header("URLs");
115
+ if (urls.web)
116
+ log.info(` Web: ${urls.web}`);
117
+ if (urls.api)
118
+ log.info(` API: ${urls.api}`);
119
+ }
120
+ export async function runLogs(args) {
121
+ const installDir = resolveInstallDir(args);
122
+ const composeArgs = ["logs"];
123
+ if (args.follow)
124
+ composeArgs.push("-f");
125
+ if (args.service)
126
+ composeArgs.push(args.service);
127
+ await compose(installDir, composeArgs);
128
+ }
129
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../src/install/commands/lifecycle.ts"],"names":[],"mappings":"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"}