@savvy-web/cli 3.2.8 → 3.3.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 +8 -5
- package/commands/changeset/commands/check.js +11 -7
- package/commands/changeset/commands/config-validate.js +6 -4
- package/commands/changeset/commands/deps-detect.js +4 -4
- package/commands/changeset/commands/deps-regen.js +11 -10
- package/commands/changeset/commands/init.js +13 -11
- package/commands/changeset/commands/lint.js +4 -3
- package/commands/changeset/commands/transform.js +7 -5
- package/commands/changeset/commands/validate-file.js +8 -6
- package/commands/changeset/commands/version.js +5 -4
- package/commands/changeset/utils/config-gate.js +3 -3
- package/commands/check.js +3 -2
- package/commands/clean.js +7 -8
- package/commands/commit/check.js +33 -35
- package/commands/commit/constants.js +5 -0
- package/commands/commit/init.js +8 -6
- package/commands/commit/lint.js +2 -1
- package/commands/lint/check.js +43 -47
- package/commands/lint/init.js +20 -22
- package/commands/repos/commands/add.js +8 -9
- package/commands/repos/commands/deregister.js +7 -7
- package/commands/repos/commands/note.js +7 -8
- package/commands/repos/commands/pin.js +11 -13
- package/commands/repos/commands/remove.js +13 -15
- package/commands/repos/commands/rename.js +10 -12
- package/commands/repos/commands/restore.js +12 -14
- package/commands/repos/commands/status.js +16 -8
- package/commands/repos/commands/sync.js +12 -13
- package/index.d.ts +16 -15
- package/internal/failure-line.js +39 -0
- package/internal/output.js +52 -0
- package/internal/version-line.js +19 -0
- package/main.d.ts +18 -2
- package/main.js +26 -16
- package/package.json +3 -1
- package/version.js +13 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { Output } from "../../../internal/output.js";
|
|
1
2
|
import { Command, Flag } from "effect/unstable/cli";
|
|
3
|
+
import { CliExit } from "@effected/cli";
|
|
2
4
|
import { Repos } from "@savvy-web/silk-effects";
|
|
3
5
|
import { Console, Effect } from "effect";
|
|
4
6
|
|
|
@@ -46,11 +48,11 @@ const cwdOption = Flag.Directory("cwd").pipe(Flag.withDescription("Repo root to
|
|
|
46
48
|
*/
|
|
47
49
|
const runReposStatus = (cwd, json, drift = false) => Effect.gen(function* () {
|
|
48
50
|
const report = yield* (yield* Repos.ReposManager).status(cwd);
|
|
49
|
-
if (!report.clean)
|
|
51
|
+
if (!report.clean) yield* CliExit.set(1);
|
|
50
52
|
let driftReport;
|
|
51
53
|
if (drift) {
|
|
52
54
|
driftReport = yield* (yield* Repos.ReposDrift).check(cwd);
|
|
53
|
-
if (!driftReport.clean)
|
|
55
|
+
if (!driftReport.clean) yield* CliExit.set(1);
|
|
54
56
|
}
|
|
55
57
|
if (json) {
|
|
56
58
|
const payload = driftReport === void 0 ? report : {
|
|
@@ -66,20 +68,26 @@ const runReposStatus = (cwd, json, drift = false) => Effect.gen(function* () {
|
|
|
66
68
|
repo.dirty ? "dirty" : void 0,
|
|
67
69
|
repo.staleNoteIds.length > 0 ? `${repo.staleNoteIds.length} stale notes` : void 0
|
|
68
70
|
].filter((f) => f !== void 0);
|
|
69
|
-
yield*
|
|
71
|
+
yield* flags.length > 0 ? Output.warn(`${repo.name} @ ${repo.ref} [${flags.join(", ")}]`) : Output.ok(`${repo.name} @ ${repo.ref}`);
|
|
70
72
|
}
|
|
71
|
-
if (driftReport !== void 0) for (const item of driftReport.drifts) yield*
|
|
73
|
+
if (driftReport !== void 0) for (const item of driftReport.drifts) yield* Output.fail(`${item.name}: ${item.kind} — ${item.detail}`);
|
|
72
74
|
}).pipe(Effect.catchTag("ReposConfigError", (error) => {
|
|
73
75
|
if (error.kind === "missing") {
|
|
74
76
|
if (json) return Console.log(JSON.stringify({
|
|
75
77
|
repos: [],
|
|
76
78
|
clean: true
|
|
77
79
|
}, null, 2));
|
|
78
|
-
return
|
|
80
|
+
return Output.skip("no .repos/config.json — nothing vendored");
|
|
79
81
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
const report = json ? Console.log(JSON.stringify({
|
|
83
|
+
error: error.message,
|
|
84
|
+
clean: false
|
|
85
|
+
}, null, 2)) : Effect.void;
|
|
86
|
+
return CliExit.set(1).pipe(Effect.andThen(report), Effect.andThen(Effect.logError(error.message)));
|
|
87
|
+
}), Effect.catchTag("GitSubmoduleError", (error) => json ? CliExit.set(1).pipe(Effect.andThen(Console.log(JSON.stringify({
|
|
88
|
+
error: error.message,
|
|
89
|
+
clean: false
|
|
90
|
+
}, null, 2))), Effect.andThen(Effect.logError(error.message))) : Effect.fail(error)));
|
|
83
91
|
/* v8 ignore start -- CLI registration; handler tested via runReposStatus */
|
|
84
92
|
const statusCommand = Command.make("status", {
|
|
85
93
|
json: jsonOption,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { Output } from "../../../internal/output.js";
|
|
1
2
|
import { Command, Flag } from "effect/unstable/cli";
|
|
3
|
+
import { CliExit } from "@effected/cli";
|
|
2
4
|
import { Repos } from "@savvy-web/silk-effects";
|
|
3
5
|
import { Effect } from "effect";
|
|
4
6
|
|
|
@@ -37,22 +39,19 @@ const cwdOption = Flag.Directory("cwd").pipe(Flag.withDescription("Repo root to
|
|
|
37
39
|
*/
|
|
38
40
|
const runReposSync = (cwd) => Effect.gen(function* () {
|
|
39
41
|
const report = yield* (yield* Repos.ReposManager).sync(cwd);
|
|
40
|
-
for (const name of report.clearedLocks) yield*
|
|
41
|
-
for (const name of report.initialized) yield*
|
|
42
|
-
for (const name of report.sparseApplied) yield*
|
|
43
|
-
for (const name of report.urlSynced) yield*
|
|
44
|
-
for (const name of report.registered) yield*
|
|
45
|
-
if (report.initialized.length === 0 && report.sparseApplied.length === 0 && report.clearedLocks.length === 0 && report.urlSynced.length === 0 && report.registered.length === 0) yield*
|
|
42
|
+
for (const name of report.clearedLocks) yield* Output.ok(`${name}: cleared stale lock`);
|
|
43
|
+
for (const name of report.initialized) yield* Output.ok(`${name}: initialized`);
|
|
44
|
+
for (const name of report.sparseApplied) yield* Output.ok(`${name}: sparse-checkout applied`);
|
|
45
|
+
for (const name of report.urlSynced) yield* Output.ok(`${name}: url reconciled`);
|
|
46
|
+
for (const name of report.registered) yield* Output.ok(`${name}: registered`);
|
|
47
|
+
if (report.initialized.length === 0 && report.sparseApplied.length === 0 && report.clearedLocks.length === 0 && report.urlSynced.length === 0 && report.registered.length === 0) yield* Output.ok("all vendored repos up to date");
|
|
46
48
|
}).pipe(Effect.catchTag("ReposConfigError", (error) => {
|
|
47
|
-
if (error.kind === "missing") return
|
|
48
|
-
|
|
49
|
-
return Effect.log(error.message);
|
|
49
|
+
if (error.kind === "missing") return Output.skip("no .repos/config.json — nothing vendored");
|
|
50
|
+
return CliExit.set(1).pipe(Effect.andThen(Effect.logError(error.message)));
|
|
50
51
|
}), Effect.catchTag("GitSubmoduleError", (error) => {
|
|
51
|
-
|
|
52
|
-
return Effect.log(error.message);
|
|
52
|
+
return CliExit.set(1).pipe(Effect.andThen(Effect.logError(error.message)));
|
|
53
53
|
}), Effect.catchTag("ReposLockdownError", (error) => {
|
|
54
|
-
|
|
55
|
-
return Effect.log(error.message);
|
|
54
|
+
return CliExit.set(1).pipe(Effect.andThen(Effect.logError(error.message)));
|
|
56
55
|
}));
|
|
57
56
|
/* v8 ignore start -- CLI registration; handler tested via runReposSync */
|
|
58
57
|
const syncCommand = Command.make("sync", { cwd: cwdOption }, ({ cwd }) => runReposSync(cwd)).pipe(Command.withDescription("Reconcile vendored submodules with the manifest: init missing, apply sparse, clear locks"));
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { CliExit } from "@effected/cli";
|
|
1
2
|
import { BiomeSchemaSync, ChangesetConfigReader, Changesets, ConfigDiscovery, Repos } from "@savvy-web/silk-effects";
|
|
2
|
-
import { Cause, Effect, FileSystem, Path } from "effect";
|
|
3
|
+
import { Cause, Effect, FileSystem, Path, Stdio } from "effect";
|
|
3
4
|
import { Command } from "effect/unstable/cli";
|
|
4
5
|
import { ChildProcessSpawner } from "effect/unstable/process";
|
|
5
6
|
import { Git } from "@effected/git";
|
|
@@ -13,14 +14,14 @@ import { JsoncParseError } from "@effected/jsonc";
|
|
|
13
14
|
* Run the check validation pipeline on all changeset files in `dir`.
|
|
14
15
|
*
|
|
15
16
|
* Groups lint messages by file and logs a human-readable summary. Sets
|
|
16
|
-
*
|
|
17
|
+
* exit code 1 through `CliExit.set` when one or more errors are found.
|
|
17
18
|
*
|
|
18
19
|
* @param dir - Path to the changeset directory (resolved relative to cwd)
|
|
19
20
|
* @returns An Effect that performs validation and logs results
|
|
20
21
|
*
|
|
21
22
|
* @internal
|
|
22
23
|
*/
|
|
23
|
-
export declare function runChangesetCheck(dir: string): Effect.Effect<void, Error>;
|
|
24
|
+
export declare function runChangesetCheck(dir: string): Effect.Effect<void, Error, CliExit | Stdio.Stdio>;
|
|
24
25
|
//#endregion
|
|
25
26
|
//#region src/commands/changeset/commands/init.d.ts
|
|
26
27
|
/**
|
|
@@ -39,7 +40,7 @@ export declare function runChangesetInit(opts: {
|
|
|
39
40
|
quiet: boolean;
|
|
40
41
|
skipMarkdownlint: boolean;
|
|
41
42
|
check: boolean;
|
|
42
|
-
}): Effect.Effect<void, never, WorkspaceRoot | Git>;
|
|
43
|
+
}): Effect.Effect<void, never, WorkspaceRoot | Git | CliExit | Stdio.Stdio>;
|
|
43
44
|
//#endregion
|
|
44
45
|
//#region src/commands/changeset/index.d.ts
|
|
45
46
|
/**
|
|
@@ -57,7 +58,7 @@ export declare function runChangesetInit(opts: {
|
|
|
57
58
|
* `Command.withSubcommands` propagates each subcommand's requirements up into
|
|
58
59
|
* the group's `R`, which the root assembly discharges via `AppLive`.
|
|
59
60
|
*/
|
|
60
|
-
export declare const changesetCommand: Command.Command<"changeset", Record<string, never>, Record<string, never>, Changesets.ConfigurationError | Error | Changesets.ReleasePlanError | Cause.UnknownError | Changesets.DepsRegenPlanError, ChildProcessSpawner.ChildProcessSpawner | Changesets.ConfigInspector | FileSystem.FileSystem | Path.Path | Changesets.ReleasePlanner>;
|
|
61
|
+
export declare const changesetCommand: Command.Command<"changeset", Record<string, never>, Record<string, never>, Changesets.ConfigurationError | Error | Changesets.ReleasePlanError | Cause.UnknownError | Changesets.DepsRegenPlanError, ChildProcessSpawner.ChildProcessSpawner | Changesets.ConfigInspector | FileSystem.FileSystem | Path.Path | Changesets.ReleasePlanner | CliExit | Stdio.Stdio>;
|
|
61
62
|
//#endregion
|
|
62
63
|
//#region src/commands/check.d.ts
|
|
63
64
|
/**
|
|
@@ -88,7 +89,7 @@ export declare function runCheck<EChangeset, RChangeset, ECommit, RCommit, ELint
|
|
|
88
89
|
export declare const checkCommand: Command.Command<"check", {
|
|
89
90
|
readonly changesetDir: string;
|
|
90
91
|
readonly quiet: boolean;
|
|
91
|
-
}, {}, Error | import("@effected/jsonc").JsoncParseError | import("effect/PlatformError").PlatformError | import("@effected/templates").SectionFileError | import("@effected/templates").SectionParseError, import("@savvy-web/silk-effects").ChangesetConfigReader | import("@savvy-web/silk-effects").ConfigDiscovery | import("effect/FileSystem").FileSystem | import("@effected/templates").ManagedSection | import("@effected/workspaces").PublishabilityDetector | import("@effected/commands").ToolDiscovery | import("@effected/workspaces").WorkspaceDiscovery>;
|
|
92
|
+
}, {}, Error | import("@effected/jsonc").JsoncParseError | import("effect/PlatformError").PlatformError | import("@effected/templates").SectionFileError | import("@effected/templates").SectionParseError, import("@savvy-web/silk-effects").ChangesetConfigReader | import("@effected/cli").CliExit | import("@savvy-web/silk-effects").ConfigDiscovery | import("effect/FileSystem").FileSystem | import("@effected/templates").ManagedSection | import("@effected/workspaces").PublishabilityDetector | import("effect/Stdio").Stdio | import("@effected/commands").ToolDiscovery | import("@effected/workspaces").WorkspaceDiscovery>;
|
|
92
93
|
//#endregion
|
|
93
94
|
//#region src/commands/commit/check.d.ts
|
|
94
95
|
/**
|
|
@@ -101,7 +102,7 @@ export declare const checkCommand: Command.Command<"check", {
|
|
|
101
102
|
*
|
|
102
103
|
* @internal
|
|
103
104
|
*/
|
|
104
|
-
export declare function runCommitCheck(): Effect.Effect<void, SectionParseError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | ChangesetConfigReader | PublishabilityDetector | WorkspaceDiscovery>;
|
|
105
|
+
export declare function runCommitCheck(): Effect.Effect<void, SectionParseError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | ChangesetConfigReader | PublishabilityDetector | WorkspaceDiscovery | Stdio.Stdio>;
|
|
105
106
|
//#endregion
|
|
106
107
|
//#region src/commands/commit/init.d.ts
|
|
107
108
|
/**
|
|
@@ -118,7 +119,7 @@ export declare function runCommitCheck(): Effect.Effect<void, SectionParseError
|
|
|
118
119
|
export declare function runCommitInit(opts: {
|
|
119
120
|
force: boolean;
|
|
120
121
|
config: string;
|
|
121
|
-
}): Effect.Effect<void, Error | SectionParseError | SectionRenderError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem>;
|
|
122
|
+
}): Effect.Effect<void, Error | SectionParseError | SectionRenderError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | Stdio.Stdio>;
|
|
122
123
|
//#endregion
|
|
123
124
|
//#region src/commands/commit/index.d.ts
|
|
124
125
|
/**
|
|
@@ -129,7 +130,7 @@ export declare function runCommitInit(opts: {
|
|
|
129
130
|
* errors from Effect's internal types. Task B7 should import and use this directly
|
|
130
131
|
* as `Command.withSubcommands([commitCommand])` — the cast is for declaration emit only.
|
|
131
132
|
*/
|
|
132
|
-
export declare const commitCommand: Command.Command<"commit", {}, {}, import("effect/unstable/cli/CliError").UserError, import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | import("@effected/git").Git>;
|
|
133
|
+
export declare const commitCommand: Command.Command<"commit", {}, {}, import("effect/unstable/cli/CliError").UserError, import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | import("@effected/git").Git | import("effect/Stdio").Stdio>;
|
|
133
134
|
//#endregion
|
|
134
135
|
//#region src/commands/init.d.ts
|
|
135
136
|
/**
|
|
@@ -160,7 +161,7 @@ export declare const initCommand: Command.Command<"init", {
|
|
|
160
161
|
readonly commitConfig: string;
|
|
161
162
|
readonly lintConfig: string;
|
|
162
163
|
readonly lintPreset: "minimal" | "silk" | "standard";
|
|
163
|
-
}, {}, Error | import("effect/PlatformError").PlatformError | import("@effected/templates").SectionFileError | import("@effected/templates").SectionParseError | import("@effected/templates").SectionRenderError, import("@savvy-web/silk-effects").BiomeSchemaSync | import("effect/FileSystem").FileSystem | import("@effected/git").Git | import("@effected/templates").ManagedSection | import("@effected/workspaces").WorkspaceDiscovery | import("@effected/workspaces").WorkspaceRoot>;
|
|
164
|
+
}, {}, Error | import("effect/PlatformError").PlatformError | import("@effected/templates").SectionFileError | import("@effected/templates").SectionParseError | import("@effected/templates").SectionRenderError, import("@savvy-web/silk-effects").BiomeSchemaSync | import("@effected/cli").CliExit | import("effect/FileSystem").FileSystem | import("@effected/git").Git | import("@effected/templates").ManagedSection | import("effect/Stdio").Stdio | import("@effected/workspaces").WorkspaceDiscovery | import("@effected/workspaces").WorkspaceRoot>;
|
|
164
165
|
//#endregion
|
|
165
166
|
//#region src/commands/lint/check.d.ts
|
|
166
167
|
/**
|
|
@@ -176,7 +177,7 @@ export declare const initCommand: Command.Command<"init", {
|
|
|
176
177
|
*/
|
|
177
178
|
export declare function runLintCheck(opts: {
|
|
178
179
|
quiet: boolean;
|
|
179
|
-
}): Effect.Effect<void, JsoncParseError | SectionParseError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | ToolDiscovery | ConfigDiscovery>;
|
|
180
|
+
}): Effect.Effect<void, JsoncParseError | SectionParseError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | ToolDiscovery | ConfigDiscovery | Stdio.Stdio>;
|
|
180
181
|
//#endregion
|
|
181
182
|
//#region src/commands/lint/init.d.ts
|
|
182
183
|
/**
|
|
@@ -194,7 +195,7 @@ export declare function runLintInit(opts: {
|
|
|
194
195
|
force: boolean;
|
|
195
196
|
config: string;
|
|
196
197
|
preset: "minimal" | "standard" | "silk";
|
|
197
|
-
}): Effect.Effect<void, Error | SectionParseError | SectionRenderError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | BiomeSchemaSync | WorkspaceDiscovery>;
|
|
198
|
+
}): Effect.Effect<void, Error | SectionParseError | SectionRenderError | SectionFileError | PlatformError, ManagedSection | FileSystem.FileSystem | BiomeSchemaSync | WorkspaceDiscovery | Stdio.Stdio>;
|
|
198
199
|
//#endregion
|
|
199
200
|
//#region src/commands/lint/index.d.ts
|
|
200
201
|
/**
|
|
@@ -213,7 +214,7 @@ export declare const lintCommand: Command.Command<"lint", {}, {}, import("@effec
|
|
|
213
214
|
*
|
|
214
215
|
* @internal
|
|
215
216
|
*/
|
|
216
|
-
export declare const runReposStatus: (cwd: string, json: boolean, drift?: boolean) => Effect.Effect<void, Repos.GitSubmoduleError, Repos.ReposDrift | Repos.ReposManager>;
|
|
217
|
+
export declare const runReposStatus: (cwd: string, json: boolean, drift?: boolean) => Effect.Effect<void, Repos.GitSubmoduleError, CliExit | Repos.ReposDrift | Repos.ReposManager | Stdio.Stdio>;
|
|
217
218
|
//#endregion
|
|
218
219
|
//#region src/commands/repos/commands/sync.d.ts
|
|
219
220
|
/**
|
|
@@ -221,7 +222,7 @@ export declare const runReposStatus: (cwd: string, json: boolean, drift?: boolea
|
|
|
221
222
|
*
|
|
222
223
|
* @internal
|
|
223
224
|
*/
|
|
224
|
-
export declare const runReposSync: (cwd: string) => Effect.Effect<void, never, Repos.ReposManager>;
|
|
225
|
+
export declare const runReposSync: (cwd: string) => Effect.Effect<void, never, CliExit | Repos.ReposManager | Stdio.Stdio>;
|
|
225
226
|
//#endregion
|
|
226
227
|
//#region src/commands/repos/index.d.ts
|
|
227
228
|
/**
|
|
@@ -252,6 +253,6 @@ export declare const runReposSync: (cwd: string) => Effect.Effect<void, never, R
|
|
|
252
253
|
* or (under `--drift`) `Repos.ReposDrift.check` is the sole channel that
|
|
253
254
|
* escapes uncaught, so it is the only member left in this union.
|
|
254
255
|
*/
|
|
255
|
-
export declare const reposCommand: Command.Command<"repos", Record<string, never>, Record<string, never>, Repos.GitSubmoduleError, Repos.ReposManager | Repos.ReposDrift>;
|
|
256
|
+
export declare const reposCommand: Command.Command<"repos", Record<string, never>, Record<string, never>, Repos.GitSubmoduleError, Repos.ReposManager | Repos.ReposDrift | CliExit | Stdio.Stdio>;
|
|
256
257
|
//#endregion
|
|
257
258
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/internal/failure-line.ts
|
|
2
|
+
/**
|
|
3
|
+
* How a failure that reaches `CliRuntime.main` reads on stderr.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
const HIDDEN = /* @__PURE__ */ new Set([
|
|
8
|
+
"_tag",
|
|
9
|
+
"message",
|
|
10
|
+
"name",
|
|
11
|
+
"stack",
|
|
12
|
+
"cause"
|
|
13
|
+
]);
|
|
14
|
+
/**
|
|
15
|
+
* Renders a failure for `CliRuntime.main`'s `render` option.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* The kit's default is `String(error)`, which prints a `Data.TaggedError`
|
|
19
|
+
* with no `message` as its bare tag and drops the fields that say what went
|
|
20
|
+
* wrong (`CleanError`, with the `reason` lost). This prefers the error's own
|
|
21
|
+
* message, then its tag with its fields, then `String`.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
var FailureLine = class {
|
|
26
|
+
constructor() {}
|
|
27
|
+
static render = (error) => {
|
|
28
|
+
if (error instanceof Error && error.message !== "") return error.message;
|
|
29
|
+
if (typeof error === "object" && error !== null && "_tag" in error) {
|
|
30
|
+
const fields = Object.entries(error).filter(([key]) => !HIDDEN.has(key)).map(([key, value]) => `${key}: ${typeof value === "string" ? value : JSON.stringify(value)}`);
|
|
31
|
+
const tag = String(error._tag);
|
|
32
|
+
return fields.length > 0 ? `${tag}: ${fields.join(", ")}` : tag;
|
|
33
|
+
}
|
|
34
|
+
return String(error);
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { FailureLine };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CliColor } from "@effected/cli";
|
|
2
|
+
import { Console, Effect } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/output.ts
|
|
5
|
+
/**
|
|
6
|
+
* Human-readable command output.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
const paint = (on, code, text) => on ? `\u001b[${code}m${text}\u001b[0m` : text;
|
|
11
|
+
const glyphLine = (code, glyph, text) => Effect.flatMap(CliColor.enabled, (on) => Console.log(`${paint(on, code, glyph)} ${text}`));
|
|
12
|
+
/**
|
|
13
|
+
* The result a person ran a command to see, written to stdout.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* Every line goes through `Console.log`, so stdout carries a command's product
|
|
17
|
+
* and nothing else; progress and diagnostics stay on `Effect.log*`, which the
|
|
18
|
+
* CLI logger sends to stderr. Colour follows `CliColor.enabled` — off when
|
|
19
|
+
* stdout is not a terminal or `NO_COLOR` is set — and only ever tints the
|
|
20
|
+
* glyph or heading, so the text reads the same piped.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
var Output = class {
|
|
25
|
+
constructor() {}
|
|
26
|
+
/** A passing item: `✓ text`. */
|
|
27
|
+
static ok = (text) => glyphLine("32", "✓", text);
|
|
28
|
+
/** An item that passed with a caveat: `⚠ text`. */
|
|
29
|
+
static warn = (text) => glyphLine("33", "⚠", text);
|
|
30
|
+
/** A finding — still output, not a crash: `✗ text`. */
|
|
31
|
+
static fail = (text) => glyphLine("31", "✗", text);
|
|
32
|
+
/** An item that is absent or not applicable — neither a pass nor a finding: `• text`, dimmed. */
|
|
33
|
+
static skip = (text) => glyphLine("2", "•", text);
|
|
34
|
+
/** A section title, bold on a terminal. */
|
|
35
|
+
static heading = (text) => Effect.flatMap(CliColor.enabled, (on) => Console.log(paint(on, "1", text)));
|
|
36
|
+
/** Supporting detail under the line before it, indented and dimmed on a terminal. */
|
|
37
|
+
static detail = (text) => Effect.flatMap(CliColor.enabled, (on) => Console.log(` ${paint(on, "2", text)}`));
|
|
38
|
+
/** A line printed as given — a blank separator, or a block already formatted. */
|
|
39
|
+
static line = (text) => Console.log(text);
|
|
40
|
+
/** `3 ok · 1 warning · 2 failed`, zero parts left out; `nothing to do` when every count is zero. */
|
|
41
|
+
static summary = (counts) => {
|
|
42
|
+
const parts = [
|
|
43
|
+
counts.ok ? `${counts.ok} ok` : void 0,
|
|
44
|
+
counts.warn ? `${counts.warn} ${counts.warn === 1 ? "warning" : "warnings"}` : void 0,
|
|
45
|
+
counts.fail ? `${counts.fail} failed` : void 0
|
|
46
|
+
].filter((part) => part !== void 0);
|
|
47
|
+
return Console.log(parts.length === 0 ? "nothing to do" : parts.join(" · "));
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { Output };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { distributionSuffix } from "@effected/engine";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/version-line.ts
|
|
4
|
+
/**
|
|
5
|
+
* Renders the `savvy --version` line: the same `<name> v<version>` shape
|
|
6
|
+
* `effect/unstable/cli`'s default formatter prints, plus the
|
|
7
|
+
* `" via <carrier> <version>"` suffix when the bin was installed through a
|
|
8
|
+
* carrier such as `@savvy-web/silk`.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
var VersionLine = class {
|
|
13
|
+
constructor() {}
|
|
14
|
+
/** `savvy v1.2.3`, or `savvy v1.2.3 via @savvy-web/silk 4.5.6`. */
|
|
15
|
+
static format = (name, version, distribution) => `${name} v${version}${distributionSuffix(distribution)}`;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { VersionLine };
|
package/main.d.ts
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
import { Distribution } from "@effected/engine";
|
|
1
2
|
//#region src/main.d.ts
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* Options for {@link main}.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
4
7
|
*/
|
|
5
|
-
export
|
|
8
|
+
export interface MainOptions {
|
|
9
|
+
/**
|
|
10
|
+
* The carrier this bin was installed through, for example
|
|
11
|
+
* `{ name: "@savvy-web/silk", version }`; `--version` names it. Absent for
|
|
12
|
+
* a direct install.
|
|
13
|
+
*/
|
|
14
|
+
readonly distribution?: Distribution | undefined;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Bootstrap and run the `savvy` CLI application. Owns the process.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export declare const main: (options?: MainOptions) => void;
|
|
6
22
|
//#endregion
|
|
7
23
|
//# sourceMappingURL=main.d.ts.map
|
package/main.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { AppLive, rootCommand } from "./cli/index.js";
|
|
1
|
+
import { AppLive, CliPlatform, rootCommand } from "./cli/index.js";
|
|
2
|
+
import { FailureLine } from "./internal/failure-line.js";
|
|
3
|
+
import { VersionLine } from "./internal/version-line.js";
|
|
4
|
+
import { CLI_VERSION } from "./version.js";
|
|
2
5
|
import { Command } from "effect/unstable/cli";
|
|
3
|
-
import {
|
|
6
|
+
import { CliColor, CliRuntime } from "@effected/cli";
|
|
7
|
+
import { Effect, Layer, Option } from "effect";
|
|
4
8
|
import { NodeRuntime } from "@effect/platform-node";
|
|
9
|
+
import { CurrentDistribution } from "@effected/engine";
|
|
5
10
|
|
|
6
11
|
//#region src/main.ts
|
|
7
12
|
/**
|
|
@@ -10,24 +15,29 @@ import { NodeRuntime } from "@effect/platform-node";
|
|
|
10
15
|
*
|
|
11
16
|
* @remarks
|
|
12
17
|
* Assembles the `Command.run` Effect over `rootCommand`, provides the merged
|
|
13
|
-
* `AppLive`
|
|
14
|
-
* `
|
|
15
|
-
*
|
|
16
|
-
*
|
|
18
|
+
* `AppLive` stack and the carrier-aware version formatter, and hands the
|
|
19
|
+
* program to `@effected/cli`'s `CliRuntime.main`, which provides the platform
|
|
20
|
+
* and the kit-default CLI logger (every log line on stderr), reports failures
|
|
21
|
+
* through that logger, applies the `CliExit` code a command set, and exits
|
|
22
|
+
* `64` on a usage error.
|
|
23
|
+
* No type casts: the layer graph is validated by the compiler.
|
|
17
24
|
*
|
|
18
|
-
* @
|
|
25
|
+
* @packageDocumentation
|
|
19
26
|
*/
|
|
20
|
-
/* v8 ignore start -- bootstrap; commands tested individually */
|
|
27
|
+
/* v8 ignore start -- bootstrap; commands tested individually, the bin by __test__/e2e/bin.e2e.test.ts */
|
|
21
28
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
const cli = Command.run(rootCommand, { version: "3.2.8" });
|
|
26
|
-
/**
|
|
27
|
-
* Bootstrap and run the `savvy` CLI application.
|
|
29
|
+
* Bootstrap and run the `savvy` CLI application. Owns the process.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
28
32
|
*/
|
|
29
|
-
const main = () => {
|
|
30
|
-
|
|
33
|
+
const main = (options = {}) => {
|
|
34
|
+
const distribution = Option.fromNullishOr(options.distribution);
|
|
35
|
+
const VersionFormatterLive = CliColor.formatterLayer({ formatVersion: (name, version) => VersionLine.format(name, version, distribution) });
|
|
36
|
+
const program = Command.run(rootCommand, { version: CLI_VERSION }).pipe(Effect.provide(Layer.merge(AppLive, VersionFormatterLive)), Effect.provideService(CurrentDistribution, distribution));
|
|
37
|
+
NodeRuntime.runMain(CliRuntime.main(program, {
|
|
38
|
+
platform: CliPlatform,
|
|
39
|
+
render: FailureLine.render
|
|
40
|
+
}));
|
|
31
41
|
};
|
|
32
42
|
/* v8 ignore stop */
|
|
33
43
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.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",
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@effect/platform-node": "4.0.0-rc.117",
|
|
40
|
+
"@effected/cli": "^0.8.0",
|
|
40
41
|
"@effected/commands": "^0.9.0",
|
|
42
|
+
"@effected/engine": "^0.1.0",
|
|
41
43
|
"@effected/git": "^0.17.0",
|
|
42
44
|
"@effected/jsonc": "^0.13.0",
|
|
43
45
|
"@effected/templates": "^0.8.0",
|
package/version.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/version.ts
|
|
2
|
+
/**
|
|
3
|
+
* The package version, replaced at build time by the bundler's
|
|
4
|
+
* `process.env.__PACKAGE_VERSION__` define; `0.0.0` in an unbuilt source run.
|
|
5
|
+
* Kept in its own module so the process read stays at the front end's edge.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/** @internal */
|
|
10
|
+
const CLI_VERSION = "3.3.0";
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { CLI_VERSION };
|