dev-cockpit 0.6.0 → 0.6.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"composer-drift.d.ts","sourceRoot":"","sources":["../../../src/health/predicates/composer-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAoBD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,YAAY,CAAC,CA0CvB;AAeD,MAAM,WAAW,+BAAgC,SAAQ,yBAAyB;IAChF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;CAC1C;AAED,wBAAgB,wBAAwB,CACtC,IAAI,GAAE,+BAAoC,GACzC,WAAW,CAiBb"}
1
+ {"version":3,"file":"composer-drift.d.ts","sourceRoot":"","sources":["../../../src/health/predicates/composer-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAyBD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,YAAY,CAAC,CA0CvB;AAeD,MAAM,WAAW,+BAAgC,SAAQ,yBAAyB;IAChF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;CAC1C;AAED,wBAAgB,wBAAwB,CACtC,IAAI,GAAE,+BAAoC,GACzC,WAAW,CA4Bb"}
@@ -24,4 +24,15 @@ export declare function runRemediation(key: RemediationKey, checks: HealthCheck[
24
24
  */
25
25
  export declare function findRemediation(key: RemediationKey, checks: HealthCheck[]): HealthCheck | undefined;
26
26
  export declare function dispatchRemediation(remediation: Remediation, ctx: HealthContext, workspaceRoot: string, sourceId: string): Promise<void>;
27
+ /**
28
+ * Run a single command, streaming its stdout/stderr into the health output log
29
+ * under `health:<sourceId>`. Resolves with the process exit code once it exits.
30
+ *
31
+ * Shared by the `command`-shape dispatcher above and by `run`-shape
32
+ * remediations that need to invoke one or more commands with a proper per-call
33
+ * `cwd` (e.g. `composer install` in several package dirs). Keeping this the one
34
+ * way a remediation reaches a subprocess means commands stay plain argv — no
35
+ * shell string is ever parsed, so `&&` / `(cd …)` can't leak into argv.
36
+ */
37
+ export declare function streamCommand(ctx: HealthContext, sourceId: string, program: string, args: string[], cwd: string): Promise<number>;
27
38
  //# sourceMappingURL=remediations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remediations.d.ts","sourceRoot":"","sources":["../../src/health/remediations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,WAAW,EAAE,CASf;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAevE;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,WAAW,GAAG,SAAS,CAEzB;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiCf"}
1
+ {"version":3,"file":"remediations.d.ts","sourceRoot":"","sources":["../../src/health/remediations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EAEb,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,WAAW,EAAE,CASf;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAevE;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,WAAW,GAAG,SAAS,CAEzB;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
package/dist/index.js CHANGED
@@ -88257,22 +88257,24 @@ async function dispatchRemediation(remediation, ctx, workspaceRoot, sourceId) {
88257
88257
  if (!program2) return;
88258
88258
  const args = parts.slice(1);
88259
88259
  const cwd = remediation.cwd ?? workspaceRoot;
88260
+ await streamCommand(ctx, sourceId, program2, args, cwd);
88261
+ }
88262
+ async function streamCommand(ctx, sourceId, program2, args, cwd) {
88263
+ const emit = (severity, text) => ctx.appendOutput?.({ ts: Date.now(), source: `health:${sourceId}`, severity, text });
88260
88264
  const handle = spawnStream(program2, args, {
88261
88265
  cwd,
88262
- onStdout: (line2) => ctx.appendOutput?.({
88263
- ts: Date.now(),
88264
- source: `health:${sourceId}`,
88265
- severity: "info",
88266
- text: line2
88267
- }),
88268
- onStderr: (line2) => ctx.appendOutput?.({
88269
- ts: Date.now(),
88270
- source: `health:${sourceId}`,
88271
- severity: "warn",
88272
- text: line2
88273
- })
88266
+ // Stream both channels as info. Many CLIs (composer, git, npm) write all of
88267
+ // their normal progress to stderr, so the channel says nothing about
88268
+ // severity — treating stderr as a warning renders ordinary success output
88269
+ // as a wall of ⚠. Success vs failure is decided by the exit code below.
88270
+ onStdout: (line2) => emit("info", line2),
88271
+ onStderr: (line2) => emit("info", line2)
88274
88272
  });
88275
- await handle.exitCode;
88273
+ const code = await handle.exitCode;
88274
+ const label = [program2, ...args].join(" ");
88275
+ if (code === 0) emit("info", `\u2713 ${label}`);
88276
+ else emit("error", `\u2717 ${label} failed (exit ${code})`);
88277
+ return code;
88276
88278
  }
88277
88279
 
88278
88280
  // src/health/notify-resolver.ts
@@ -91134,7 +91136,12 @@ function resolveScopes(workspaceRoot, dirs) {
91134
91136
  const base = rel ? path15.join(workspaceRoot, rel) : workspaceRoot;
91135
91137
  return {
91136
91138
  lock: path15.join(base, "composer.lock"),
91137
- vendor: path15.join(base, "vendor"),
91139
+ // Compare against the autoload dump, which `composer install` regenerates
91140
+ // on EVERY run — even a no-op "Nothing to install". The `vendor/`
91141
+ // directory mtime only moves when entries are added/removed directly in
91142
+ // it, so a clean reinstall would never bump it and a drift flagged
91143
+ // against the dir could never clear.
91144
+ installed: path15.join(base, "vendor", "autoload.php"),
91138
91145
  label: rel || "root"
91139
91146
  };
91140
91147
  });
@@ -91152,18 +91159,18 @@ async function checkComposerDrift(ctx, opts = {}) {
91152
91159
  } catch {
91153
91160
  continue;
91154
91161
  }
91155
- if (!fs19.existsSync(scope.vendor)) {
91162
+ if (!fs19.existsSync(scope.installed)) {
91156
91163
  missing.push(scope.label);
91157
91164
  continue;
91158
91165
  }
91159
- let vendorMtime;
91166
+ let installedMtime;
91160
91167
  try {
91161
- vendorMtime = fs19.statSync(scope.vendor).mtimeMs;
91168
+ installedMtime = fs19.statSync(scope.installed).mtimeMs;
91162
91169
  } catch {
91163
- stale.push(`${scope.label} (vendor unreadable)`);
91170
+ stale.push(`${scope.label} (autoload unreadable)`);
91164
91171
  continue;
91165
91172
  }
91166
- if (lockMtime > vendorMtime) {
91173
+ if (lockMtime > installedMtime) {
91167
91174
  stale.push(scope.label);
91168
91175
  }
91169
91176
  }
@@ -91171,7 +91178,7 @@ async function checkComposerDrift(ctx, opts = {}) {
91171
91178
  return status3("ok", "composer.lock and vendor/ are in sync");
91172
91179
  }
91173
91180
  const parts = [];
91174
- if (missing.length > 0) parts.push(`vendor missing in: ${missing.join(", ")}`);
91181
+ if (missing.length > 0) parts.push(`dependencies not installed in: ${missing.join(", ")}`);
91175
91182
  if (stale.length > 0) parts.push(`composer.lock newer than vendor/ in: ${stale.join(", ")}`);
91176
91183
  return status3("error", `${parts.join("; ")} \u2014 run composer install`);
91177
91184
  }
@@ -91186,17 +91193,29 @@ function status3(severity, detail) {
91186
91193
  }
91187
91194
  function createComposerDriftCheck(opts = {}) {
91188
91195
  const dirs = opts.packageDirs ?? ["."];
91189
- const defaultCommand = dirs.map((d) => d === "" || d === "." ? "composer install" : `(cd ${d} && composer install)`).join(" && ");
91196
+ const id = opts.id ?? "composer-drift";
91190
91197
  return {
91191
- id: opts.id ?? "composer-drift",
91198
+ id,
91192
91199
  label: opts.label ?? "Composer",
91193
91200
  severity: opts.severity ?? "error",
91194
91201
  triggers: opts.triggers ?? ["startup", "lockfile"],
91195
91202
  predicate: (ctx) => checkComposerDrift(ctx, opts),
91203
+ // Run `composer install` once per package dir, each in its own cwd. A
91204
+ // declarative `command` string can't express this without shell syntax
91205
+ // (`&&`, `(cd …)`), and the dispatcher runs commands as plain argv — so
91206
+ // that syntax would reach composer as bogus package arguments. The `run`
91207
+ // shape keeps each invocation a clean argv in the right directory and
91208
+ // short-circuits on the first failure, mirroring `&&`.
91196
91209
  remediation: opts.remediation ?? {
91197
91210
  key: "R",
91198
91211
  label: "Run composer install",
91199
- command: defaultCommand
91212
+ run: async (ctx, workspaceRoot) => {
91213
+ for (const d of dirs) {
91214
+ const cwd = d === "" || d === "." ? workspaceRoot : path15.join(workspaceRoot, d);
91215
+ const code = await streamCommand(ctx, id, "composer", ["install"], cwd);
91216
+ if (code !== 0) break;
91217
+ }
91218
+ }
91200
91219
  }
91201
91220
  };
91202
91221
  }