@savvy-web/cli 2.5.4 → 2.6.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/cli/index.js CHANGED
@@ -76,7 +76,7 @@ const rootCommand = Command.make("savvy").pipe(Command.withSubcommands([
76
76
  * CLI application: reads argv from the Stdio service provided by NodeServices.
77
77
  * (v4's `Command.run` takes only `version` — the name comes from the root command.)
78
78
  */
79
- const cli = Command.run(rootCommand, { version: "2.5.4" });
79
+ const cli = Command.run(rootCommand, { version: "2.6.0" });
80
80
  /**
81
81
  * Shared workspace services from `@effected/workspaces`, wired as a
82
82
  * self-contained unit and built ONCE (layers memoize by reference).
@@ -0,0 +1,67 @@
1
+ import { Repos } from "@savvy-web/silk-effects";
2
+ import { Effect } from "effect";
3
+ import { Argument, Command, Flag } from "effect/unstable/cli";
4
+
5
+ //#region src/commands/repos/commands/deregister.ts
6
+ /**
7
+ * `repos deregister` command -- clear a stale submodule registration from the
8
+ * superproject's LOCAL git config.
9
+ *
10
+ * @remarks
11
+ * A thin adapter over {@link Repos.ReposManager.deregister}: removes the
12
+ * `submodule.<section>` section a rename or an unvendoring left behind — the
13
+ * phantom entry `savvy repos status --drift` reports as
14
+ * `localRegistrationDivergence` with no matching manifest entry. The section
15
+ * argument is the registration name exactly as the drift report states it
16
+ * (e.g. `.repos/old-name`); the `submodule.` prefix is implied.
17
+ *
18
+ * Unlike the other mutating repos commands, nothing is staged afterwards:
19
+ * the local git config is unversioned, so there is nothing to commit. It also
20
+ * never touches a vendored worktree, so no lockdown bracket is involved and
21
+ * `ReposLockdownError` is not in its error union.
22
+ *
23
+ * Every failure here is a REAL failure (exit 1): a `ReposConfigError` means
24
+ * the section still backs a live manifest entry (use `remove` to unvendor, or
25
+ * `sync` to reconcile), the section is not registered at all (usually a
26
+ * typo), or the manifest itself is unreadable; a `GitSubmoduleError` means
27
+ * the underlying git command failed. There is no friendly missing-manifest
28
+ * exit-0 case: the manager folds a missing manifest to "no live entries" and
29
+ * proceeds, since a stale registration can outlive the manifest itself.
30
+ *
31
+ * @example
32
+ * ```bash
33
+ * savvy repos deregister .repos/old-name
34
+ * ```
35
+ *
36
+ * @internal
37
+ */
38
+ /* v8 ignore start -- CLI option/arg definitions */
39
+ const sectionArg = Argument.string("section");
40
+ const cwdOption = Flag.directory("cwd").pipe(Flag.withDescription("Repo root to deregister within"), Flag.withDefault("."));
41
+ /* v8 ignore stop */
42
+ /**
43
+ * Deregister handler; exported for tests.
44
+ *
45
+ * @internal
46
+ */
47
+ const runReposDeregister = (cwd, section) => Effect.gen(function* () {
48
+ const result = yield* (yield* Repos.ReposManager).deregister(cwd, section);
49
+ yield* Effect.log(`${result.section}: deregistered (${result.removedKeys.length} config keys removed)`);
50
+ for (const key of result.removedKeys) yield* Effect.log(` removed ${key}`);
51
+ yield* Effect.log("local git config only — nothing to commit");
52
+ }).pipe(Effect.catchTag("ReposConfigError", (error) => {
53
+ process.exitCode = 1;
54
+ return Effect.log(error.message);
55
+ }), Effect.catchTag("GitSubmoduleError", (error) => {
56
+ process.exitCode = 1;
57
+ return Effect.log(error.message);
58
+ }));
59
+ /* v8 ignore start -- CLI registration; handler tested via runReposDeregister */
60
+ const deregisterCommand = Command.make("deregister", {
61
+ section: sectionArg,
62
+ cwd: cwdOption
63
+ }, ({ section, cwd }) => runReposDeregister(cwd, section)).pipe(Command.withDescription("Clear a stale submodule registration (a submodule.<section> section matching no manifest entry) from the local git config"));
64
+ /* v8 ignore stop */
65
+
66
+ //#endregion
67
+ export { deregisterCommand, runReposDeregister };
@@ -1,4 +1,5 @@
1
1
  import { addCommand, runReposAdd } from "./commands/add.js";
2
+ import { deregisterCommand, runReposDeregister } from "./commands/deregister.js";
2
3
  import { noteCommand, runReposNote } from "./commands/note.js";
3
4
  import { pinCommand, runReposPin } from "./commands/pin.js";
4
5
  import { removeCommand, runReposRemove } from "./commands/remove.js";
@@ -18,7 +19,8 @@ const _reposCommand = Command.make("repos").pipe(Command.withSubcommands([
18
19
  noteCommand,
19
20
  removeCommand,
20
21
  renameCommand,
21
- restoreCommand
22
+ restoreCommand,
23
+ deregisterCommand
22
24
  ]), Command.withDescription("Vendored reference repos under .repos/"));
23
25
  /**
24
26
  * The `savvy repos` command group.
@@ -38,8 +40,8 @@ const _reposCommand = Command.make("repos").pipe(Command.withSubcommands([
38
40
  * `status --drift` runs `Repos.ReposDrift.check` after the status check.
39
41
  *
40
42
  * The error channel is `Repos.GitSubmoduleError` alone: `add`/`pin`/`note`/
41
- * `remove`/`rename`/`restore`/`sync` each `catchTag` every error their
42
- * underlying `ReposManager` method can produce — `ReposConfigError`,
43
+ * `remove`/`rename`/`restore`/`sync`/`deregister` each `catchTag` every error
44
+ * their underlying `ReposManager` method can produce — `ReposConfigError`,
43
45
  * `GitSubmoduleError`, `RepoNotFoundError`, `NoteNotFoundError`, and (for the
44
46
  * six ops that unlock/re-lock the vendored tree around a git mutation)
45
47
  * `ReposLockdownError` — down to a logged message and a non-zero exit code,
package/index.d.ts CHANGED
@@ -301,8 +301,8 @@ declare const runReposSync: (cwd: string) => Effect.Effect<void, never, Repos.Re
301
301
  * `status --drift` runs `Repos.ReposDrift.check` after the status check.
302
302
  *
303
303
  * The error channel is `Repos.GitSubmoduleError` alone: `add`/`pin`/`note`/
304
- * `remove`/`rename`/`restore`/`sync` each `catchTag` every error their
305
- * underlying `ReposManager` method can produce — `ReposConfigError`,
304
+ * `remove`/`rename`/`restore`/`sync`/`deregister` each `catchTag` every error
305
+ * their underlying `ReposManager` method can produce — `ReposConfigError`,
306
306
  * `GitSubmoduleError`, `RepoNotFoundError`, `NoteNotFoundError`, and (for the
307
307
  * six ops that unlock/re-lock the vendored tree around a git mutation)
308
308
  * `ReposLockdownError` — down to a logged message and a non-zero exit code,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/cli",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "private": false,
5
5
  "description": "The savvy CLI — unified commit, changeset, and lint commands for the Silk Suite",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/cli",
@@ -33,12 +33,12 @@
33
33
  "dependencies": {
34
34
  "@effect/platform-node": "4.0.0-beta.107",
35
35
  "@effected/commands": "^0.4.0",
36
- "@effected/git": "^0.7.0",
36
+ "@effected/git": "^0.8.0",
37
37
  "@effected/jsonc": "^0.6.0",
38
38
  "@effected/templates": "^0.2.0",
39
- "@effected/workspaces": "^0.12.0",
39
+ "@effected/workspaces": "^0.13.0",
40
40
  "@effected/yaml": "^0.8.0",
41
- "@savvy-web/silk-effects": "5.8.0",
41
+ "@savvy-web/silk-effects": "5.9.0",
42
42
  "effect": "4.0.0-beta.107"
43
43
  }
44
44
  }