@tablation/crew 0.72.3 → 0.73.0
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 +1 -1
- package/dist/cli.js +42 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -263,7 +263,7 @@ crew inbox [--member NAME] your tickets across every workspace
|
|
|
263
263
|
crew connect WS[/PROJECT] resolve a workspace/project's ids into the state tree
|
|
264
264
|
crew repos add [ROUTE] [NAME] [PATH] attach a local checkout to a route in crew.yaml, creating its Repos row if missing (--dry-run previews)
|
|
265
265
|
crew repos list ROUTE the checkouts a route has, and the tracker Repos row each matches
|
|
266
|
-
crew repos hooks [ROUTE] NAME suggest test/build hooks for a checkout (--write route|repo writes them, --recipes, --hook KEY=CMD, --agent, --json)
|
|
266
|
+
crew repos hooks [ROUTE] NAME suggest test/build hooks for a checkout (--write route|repo [--replace] writes them, --clear route removes them, --recipes, --hook KEY=CMD, --agent, --json)
|
|
267
267
|
crew install [--replace] write and load this platform's scheduler unit (macOS: clears a crew installed from another path)
|
|
268
268
|
crew uninstall [--all] unload and remove it (--all: every crew launchd unit, whichever path it came from)
|
|
269
269
|
```
|
package/dist/cli.js
CHANGED
|
@@ -8692,6 +8692,7 @@ var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
8692
8692
|
"area",
|
|
8693
8693
|
"base-url",
|
|
8694
8694
|
"choose",
|
|
8695
|
+
"clear",
|
|
8695
8696
|
"dir",
|
|
8696
8697
|
"extra-path",
|
|
8697
8698
|
"harness",
|
|
@@ -14363,7 +14364,7 @@ function repoDirOf(text, base, route, name) {
|
|
|
14363
14364
|
}
|
|
14364
14365
|
return hit.dir;
|
|
14365
14366
|
}
|
|
14366
|
-
function planRouteHooks(text, route, name, hooks) {
|
|
14367
|
+
function planRouteHooks(text, route, name, hooks, opts = {}) {
|
|
14367
14368
|
const doc = parseDocument3(text);
|
|
14368
14369
|
if (doc.errors.length > 0) throw new ReposError(`config is not valid YAML \u2014 ${doc.errors[0].message}`);
|
|
14369
14370
|
const m = routeMapOf(doc, route);
|
|
@@ -14388,15 +14389,34 @@ function planRouteHooks(text, route, name, hooks) {
|
|
|
14388
14389
|
}
|
|
14389
14390
|
const written = [];
|
|
14390
14391
|
const kept = [];
|
|
14392
|
+
const replaced = [];
|
|
14391
14393
|
for (const [k, v] of Object.entries(hooks)) {
|
|
14392
14394
|
if (v === void 0) continue;
|
|
14393
|
-
if (hooksMap.has(k)) kept.push(k);
|
|
14395
|
+
if (hooksMap.has(k) && !opts.replace) kept.push(k);
|
|
14394
14396
|
else {
|
|
14397
|
+
if (hooksMap.has(k)) replaced.push(k);
|
|
14395
14398
|
hooksMap.set(k, v);
|
|
14396
14399
|
written.push(k);
|
|
14397
14400
|
}
|
|
14398
14401
|
}
|
|
14399
|
-
return { text: String(doc), written, kept };
|
|
14402
|
+
return { text: String(doc), written, kept, replaced };
|
|
14403
|
+
}
|
|
14404
|
+
function clearRouteHooks(text, route, name) {
|
|
14405
|
+
const doc = parseDocument3(text);
|
|
14406
|
+
if (doc.errors.length > 0) throw new ReposError(`config is not valid YAML \u2014 ${doc.errors[0].message}`);
|
|
14407
|
+
const m = routeMapOf(doc, route);
|
|
14408
|
+
const repos = m.get("repos", true);
|
|
14409
|
+
let target = m;
|
|
14410
|
+
if (isMap2(repos)) {
|
|
14411
|
+
const entry = repos.get(name, true);
|
|
14412
|
+
if (!isMap2(entry)) return { text, removed: [] };
|
|
14413
|
+
target = entry;
|
|
14414
|
+
}
|
|
14415
|
+
const current = target.get("hooks", true);
|
|
14416
|
+
if (!isMap2(current)) return { text, removed: [] };
|
|
14417
|
+
const removed = current.items.map((i) => String(i.key.value ?? i.key));
|
|
14418
|
+
target.delete("hooks");
|
|
14419
|
+
return { text: String(doc), removed };
|
|
14400
14420
|
}
|
|
14401
14421
|
function starterRepoConfig(hooks, release) {
|
|
14402
14422
|
const lines = [
|
|
@@ -18358,7 +18378,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
18358
18378
|
case "repos": {
|
|
18359
18379
|
const sub = positional[1];
|
|
18360
18380
|
const usage2 = () => {
|
|
18361
|
-
process.stderr.write("crew repos add [workspace/project] [name] [path] [--name N] [--project P] [--dry-run] [--no-create]\ncrew repos clone [workspace/project] <name> [--dir PATH] [--dry-run] [--json]\ncrew repos list <workspace/project> [--json]\ncrew repos hooks [workspace/project] <name> [--suggest] [--agent] [--write route|repo] [--recipes ID,ID] [--hook KEY=CMD ...] [--json]\n");
|
|
18381
|
+
process.stderr.write("crew repos add [workspace/project] [name] [path] [--name N] [--project P] [--dry-run] [--no-create]\ncrew repos clone [workspace/project] <name> [--dir PATH] [--dry-run] [--json]\ncrew repos list <workspace/project> [--json]\ncrew repos hooks [workspace/project] <name> [--suggest] [--agent] [--write route|repo [--replace]] [--clear route] [--recipes ID,ID] [--hook KEY=CMD ...] [--json]\n");
|
|
18362
18382
|
process.exit(2);
|
|
18363
18383
|
};
|
|
18364
18384
|
if (sub !== "add" && sub !== "list" && sub !== "clone" && sub !== "hooks") usage2();
|
|
@@ -18384,6 +18404,10 @@ ${changed2.map((c) => ` - ${c}
|
|
|
18384
18404
|
const suggestion = suggestHooks(files);
|
|
18385
18405
|
const write = value("write");
|
|
18386
18406
|
if (write !== void 0 && write !== "route" && write !== "repo") throw new ReposError(`--write takes "route" or "repo" (got "${write}")`);
|
|
18407
|
+
const clear2 = value("clear");
|
|
18408
|
+
if (clear2 !== void 0 && clear2 !== "route") throw new ReposError(`--clear takes "route" (got "${clear2}")`);
|
|
18409
|
+
if (clear2 && (write || flag("suggest") || flag("agent"))) throw new ReposError("--clear cannot be combined with --write, --suggest or --agent");
|
|
18410
|
+
if (flag("replace") && write !== "route") throw new ReposError("--replace only applies with --write route");
|
|
18387
18411
|
const recipeIds = (value("recipes") ?? "").split(",").map((x) => x.trim()).filter((x) => x && x !== "none");
|
|
18388
18412
|
if (recipeIds.length > 0 && !write) throw new ReposError("--recipes only applies with --write route|repo");
|
|
18389
18413
|
if (flag("agent") && write) throw new ReposError("--agent is read-only; drop --write (write the sniffed hooks, then re-run --agent to compare)");
|
|
@@ -18411,20 +18435,26 @@ ${changed2.map((c) => ` - ${c}
|
|
|
18411
18435
|
const base2 = selectRecipes(suggestion, recipeIds);
|
|
18412
18436
|
const picked = { ...base2, hooks: { ...base2.hooks, ...overrides } };
|
|
18413
18437
|
let written;
|
|
18438
|
+
let cleared;
|
|
18439
|
+
if (clear2) {
|
|
18440
|
+
const plan = clearRouteHooks(configText, a.route, a.name);
|
|
18441
|
+
if (plan.removed.length > 0) writeFileSync23(cfg.configFile, plan.text);
|
|
18442
|
+
cleared = { file: cfg.configFile, removed: plan.removed };
|
|
18443
|
+
}
|
|
18414
18444
|
if (write && suggestion.source === null && recipeIds.length === 0 && hookSpecs.length === 0) throw new ReposError(`nothing to write: ${suggestion.notes[0]}`);
|
|
18415
18445
|
if (write === "route") {
|
|
18416
|
-
const plan = planRouteHooks(configText, a.route, a.name, picked.hooks);
|
|
18446
|
+
const plan = planRouteHooks(configText, a.route, a.name, picked.hooks, { replace: flag("replace") });
|
|
18417
18447
|
writeFileSync23(cfg.configFile, plan.text);
|
|
18418
|
-
written = { target: "route", file: cfg.configFile, hooks: plan.written, kept: plan.kept };
|
|
18448
|
+
written = { target: "route", file: cfg.configFile, hooks: plan.written, kept: plan.kept, replaced: plan.replaced };
|
|
18419
18449
|
} else if (write === "repo") {
|
|
18420
18450
|
const have = existingRepoConfig(files);
|
|
18421
18451
|
if (have) throw new ReposError(`${resolvePath(dir, have)} already exists; not overwriting it`);
|
|
18422
18452
|
const file = resolvePath(dir, ".crew.yaml");
|
|
18423
18453
|
writeFileSync23(file, starterRepoConfig(picked.hooks, picked.release), { flag: "wx" });
|
|
18424
|
-
written = { target: "repo", file, hooks: Object.keys(picked.hooks), kept: [] };
|
|
18454
|
+
written = { target: "repo", file, hooks: Object.keys(picked.hooks), kept: [], replaced: [] };
|
|
18425
18455
|
}
|
|
18426
18456
|
if (flag("json")) {
|
|
18427
|
-
process.stdout.write(`${JSON.stringify({ route: a.route, repo: a.name, dir, ...suggestion, agent, agentError, written: written ?? null })}
|
|
18457
|
+
process.stdout.write(`${JSON.stringify({ route: a.route, repo: a.name, dir, ...suggestion, agent, agentError, written: written ?? null, cleared: cleared ?? null })}
|
|
18428
18458
|
`);
|
|
18429
18459
|
} else {
|
|
18430
18460
|
if (suggestion.source) process.stdout.write(`${a.name}: proposed from ${suggestion.source}
|
|
@@ -18445,8 +18475,12 @@ ${changed2.map((c) => ` - ${c}
|
|
|
18445
18475
|
}
|
|
18446
18476
|
if (agentError) process.stderr.write(`crew repos: --agent failed (${agentError.reason}): ${agentError.message}
|
|
18447
18477
|
`);
|
|
18478
|
+
if (cleared) process.stdout.write(cleared.removed.length ? `removed route hooks ${cleared.removed.join(", ")} from ${cleared.file}
|
|
18479
|
+
` : "no route hooks to remove\n");
|
|
18448
18480
|
if (written) {
|
|
18449
18481
|
process.stdout.write(`wrote ${written.hooks.join(", ") || "nothing new"} to ${written.file}
|
|
18482
|
+
`);
|
|
18483
|
+
if (written.replaced.length) process.stdout.write(`replaced route hooks: ${written.replaced.join(", ")}
|
|
18450
18484
|
`);
|
|
18451
18485
|
if (written.kept.length) process.stdout.write(`kept existing route hooks: ${written.kept.join(", ")}
|
|
18452
18486
|
`);
|
package/package.json
CHANGED