openpalm 0.3.2 → 0.3.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 (2) hide show
  1. package/dist/openpalm.js +99 -39
  2. package/package.json +1 -1
package/dist/openpalm.js CHANGED
@@ -7232,46 +7232,106 @@ function generateToken(length = 64) {
7232
7232
  return urlSafeBase64.slice(0, length);
7233
7233
  }
7234
7234
 
7235
- // packages/lib/src/compose.ts
7236
- function buildComposeArgs(config) {
7237
- return [
7238
- config.subcommand,
7239
- "--env-file",
7240
- config.envFile,
7241
- "-f",
7242
- config.composeFile
7243
- ];
7235
+ // packages/lib/src/compose-runner.ts
7236
+ var transientErrorMatchers = [
7237
+ { pattern: /Cannot connect to the Docker daemon|error during connect|dial unix/i, code: "daemon_unreachable", retryable: true },
7238
+ { pattern: /pull access denied|manifest unknown|failed to fetch/i, code: "image_pull_failed", retryable: true },
7239
+ { pattern: /permission denied|access denied/i, code: "permission_denied", retryable: false },
7240
+ { pattern: /yaml:|invalid compose|unsupported config/i, code: "invalid_compose", retryable: false }
7241
+ ];
7242
+ function classifyError(stderr) {
7243
+ for (const matcher of transientErrorMatchers) {
7244
+ if (matcher.pattern.test(stderr))
7245
+ return { code: matcher.code, retryable: matcher.retryable };
7246
+ }
7247
+ return { code: "unknown", retryable: false };
7244
7248
  }
7245
- async function composeExec(config, args, options) {
7246
- const fullArgs = [...buildComposeArgs(config), ...args];
7247
- const proc = Bun.spawn([config.bin, ...fullArgs], {
7248
- stdout: options?.stream ? "inherit" : "pipe",
7249
- stderr: options?.stream ? "inherit" : "pipe",
7250
- stdin: "inherit"
7251
- });
7252
- const timeoutMs = options?.timeout ?? (options?.stream ? 0 : 30000);
7253
- if (timeoutMs > 0) {
7254
- const result = await Promise.race([
7255
- proc.exited.then(() => "done"),
7256
- new Promise((r) => setTimeout(() => r("timeout"), timeoutMs))
7257
- ]);
7258
- if (result === "timeout") {
7259
- proc.kill();
7260
- return { exitCode: 1, stdout: "", stderr: `compose command timed out after ${timeoutMs}ms` };
7261
- }
7262
- } else {
7263
- await proc.exited;
7249
+ function buildComposeArgs(options, args) {
7250
+ const base = [];
7251
+ if (options.subcommand)
7252
+ base.push(options.subcommand);
7253
+ if (options.envFile)
7254
+ base.push("--env-file", options.envFile);
7255
+ base.push("-f", options.composeFile);
7256
+ return [...base, ...args];
7257
+ }
7258
+ async function runComposeOnce(args, options) {
7259
+ const composeArgs = buildComposeArgs(options, args);
7260
+ const stream = options.stream ?? false;
7261
+ const timeoutMs = options.timeoutMs ?? (stream ? 0 : 30000);
7262
+ const controller = timeoutMs > 0 ? new AbortController : undefined;
7263
+ const spawnOptions = {
7264
+ stdout: stream ? "inherit" : "pipe",
7265
+ stderr: stream ? "inherit" : "pipe",
7266
+ stdin: "inherit",
7267
+ cwd: options.cwd,
7268
+ env: options.env ? { ...process.env, ...options.env } : process.env,
7269
+ signal: controller?.signal
7270
+ };
7271
+ let timeoutId;
7272
+ if (controller && timeoutMs > 0) {
7273
+ timeoutId = setTimeout(() => controller.abort("timeout"), timeoutMs);
7264
7274
  }
7275
+ let proc;
7276
+ try {
7277
+ proc = Bun.spawn([options.bin, ...composeArgs], spawnOptions);
7278
+ await proc.exited;
7279
+ } catch (error) {
7280
+ if (timeoutId)
7281
+ clearTimeout(timeoutId);
7282
+ const message = error instanceof Error ? error.message : String(error);
7283
+ const isTimeout = controller?.signal.aborted === true || message.includes("timeout");
7284
+ const classified2 = classifyError(message);
7285
+ const code = isTimeout ? "timeout" : classified2.code;
7286
+ return { ok: false, exitCode: 1, stdout: "", stderr: message, code };
7287
+ }
7288
+ if (timeoutId)
7289
+ clearTimeout(timeoutId);
7265
7290
  const exitCode = proc.exitCode ?? 1;
7266
- const stdout = options?.stream ? "" : await new Response(proc.stdout).text();
7267
- const stderr = options?.stream ? "" : await new Response(proc.stderr).text();
7268
- return { exitCode, stdout, stderr };
7291
+ const stdoutStream = proc.stdout;
7292
+ const stderrStream = proc.stderr;
7293
+ const stdout = stream || typeof stdoutStream === "number" || !stdoutStream ? "" : await new Response(stdoutStream).text();
7294
+ const stderr = stream || typeof stderrStream === "number" || !stderrStream ? "" : await new Response(stderrStream).text();
7295
+ if (exitCode === 0)
7296
+ return { ok: true, exitCode, stdout, stderr, code: "unknown" };
7297
+ const classified = classifyError(stderr);
7298
+ return { ok: false, exitCode, stdout, stderr, code: classified.code };
7299
+ }
7300
+ async function runCompose(args, options) {
7301
+ const retries = options.retries ?? 2;
7302
+ let attempt = 0;
7303
+ while (true) {
7304
+ const result = await runComposeOnce(args, options);
7305
+ if (result.ok)
7306
+ return result;
7307
+ if (result.code === "timeout")
7308
+ return result;
7309
+ const classified = classifyError(result.stderr);
7310
+ if (classified.code !== "unknown")
7311
+ result.code = classified.code;
7312
+ if (!classified.retryable || attempt >= retries)
7313
+ return result;
7314
+ attempt += 1;
7315
+ }
7316
+ }
7317
+
7318
+ // packages/lib/src/compose.ts
7319
+ async function composeExec(config, args, options) {
7320
+ const result = await runCompose(args, {
7321
+ bin: config.bin,
7322
+ subcommand: config.subcommand,
7323
+ envFile: config.envFile,
7324
+ composeFile: config.composeFile,
7325
+ stream: options?.stream,
7326
+ timeoutMs: options?.timeout
7327
+ });
7328
+ return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr, code: result.code };
7269
7329
  }
7270
7330
  async function composePull(config, services) {
7271
7331
  const args = ["pull", ...services ?? []];
7272
7332
  const result = await composeExec(config, args, { stream: true });
7273
7333
  if (result.exitCode !== 0) {
7274
- throw new Error(`compose pull failed with exit code ${result.exitCode}`);
7334
+ throw new Error(`compose pull failed:${result.code}`);
7275
7335
  }
7276
7336
  }
7277
7337
  async function composeUp(config, services, options) {
@@ -7294,7 +7354,7 @@ async function composeUp(config, services, options) {
7294
7354
  }
7295
7355
  const result = await composeExec(config, args, { stream: true });
7296
7356
  if (result.exitCode !== 0) {
7297
- throw new Error(`compose up failed with exit code ${result.exitCode}`);
7357
+ throw new Error(`compose up failed:${result.code}`);
7298
7358
  }
7299
7359
  }
7300
7360
  async function composeDown(config, options) {
@@ -7308,21 +7368,21 @@ async function composeDown(config, options) {
7308
7368
  }
7309
7369
  const result = await composeExec(config, args, { stream: true });
7310
7370
  if (result.exitCode !== 0) {
7311
- throw new Error(`compose down failed with exit code ${result.exitCode}`);
7371
+ throw new Error(`compose down failed:${result.code}`);
7312
7372
  }
7313
7373
  }
7314
7374
  async function composeRestart(config, services) {
7315
7375
  const args = ["restart", ...services ?? []];
7316
7376
  const result = await composeExec(config, args, { stream: true });
7317
7377
  if (result.exitCode !== 0) {
7318
- throw new Error(`compose restart failed with exit code ${result.exitCode}`);
7378
+ throw new Error(`compose restart failed:${result.code}`);
7319
7379
  }
7320
7380
  }
7321
7381
  async function composeStop(config, services) {
7322
7382
  const args = ["stop", ...services ?? []];
7323
7383
  const result = await composeExec(config, args, { stream: true });
7324
7384
  if (result.exitCode !== 0) {
7325
- throw new Error(`compose stop failed with exit code ${result.exitCode}`);
7385
+ throw new Error(`compose stop failed:${result.code}`);
7326
7386
  }
7327
7387
  }
7328
7388
  async function composeLogs(config, services, options) {
@@ -7338,13 +7398,13 @@ async function composeLogs(config, services, options) {
7338
7398
  }
7339
7399
  const result = await composeExec(config, args, { stream: true });
7340
7400
  if (result.exitCode !== 0) {
7341
- throw new Error(`compose logs failed with exit code ${result.exitCode}`);
7401
+ throw new Error(`compose logs failed:${result.code}`);
7342
7402
  }
7343
7403
  }
7344
7404
  async function composePs(config) {
7345
7405
  const result = await composeExec(config, ["ps", "-a"]);
7346
7406
  if (result.exitCode !== 0) {
7347
- throw new Error(`compose ps failed with exit code ${result.exitCode}`);
7407
+ throw new Error(`compose ps failed:${result.code}`);
7348
7408
  }
7349
7409
  return result.stdout;
7350
7410
  }
@@ -9071,7 +9131,7 @@ async function automation(subcommand, args) {
9071
9131
  // packages/cli/package.json
9072
9132
  var package_default = {
9073
9133
  name: "openpalm",
9074
- version: "0.3.2",
9134
+ version: "0.3.4",
9075
9135
  description: "CLI tool for installing and managing an OpenPalm stack",
9076
9136
  type: "module",
9077
9137
  license: "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openpalm",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "CLI tool for installing and managing an OpenPalm stack",
5
5
  "type": "module",
6
6
  "license": "MIT",