@okfit/cli 0.2.0 → 0.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/bin/okfit.js +2 -51
- package/commands/context.js +3 -6
- package/commands/init.js +3 -9
- package/commands/sync.js +3 -6
- package/commands/validate.js +3 -8
- package/commands/verify.js +3 -7
- package/errors.js +2 -105
- package/index.d.ts +25 -769
- package/index.js +4 -13
- package/main.d.ts +15 -0
- package/main.js +44 -0
- package/package.json +7 -4
- package/render/context.js +1 -80
- package/render/human.js +1 -1
- package/render/sync.js +1 -61
- package/render/verify.js +1 -44
- package/version.js +6 -6
- package/config/anchor.js +0 -57
- package/config/layer.js +0 -129
- package/config/resolve.js +0 -67
- package/context/run.js +0 -35
- package/init/scaffold.js +0 -174
- package/package.js +0 -5
- package/render/exit.js +0 -53
- package/render/json.js +0 -126
- package/render/sort.js +0 -46
- package/sync/generated.js +0 -111
- package/sync/index.js +0 -73
- package/sync/log.js +0 -127
- package/sync/run.js +0 -65
- package/sync/write.js +0 -48
- package/validate/run.js +0 -63
- package/verify/locate.js +0 -249
- package/verify/run.js +0 -106
- package/verify/splice.js +0 -75
package/bin/okfit.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { CLI_VERSION } from "../version.js";
|
|
4
|
-
import { Now } from "../validate/run.js";
|
|
5
|
-
import { rootCommand } from "../commands/root.js";
|
|
6
|
-
import { Command } from "effect/unstable/cli";
|
|
7
|
-
import { DateTime, Effect, Layer, Option } from "effect";
|
|
8
|
-
import { CliLogger, CliRuntime } from "@effected/cli";
|
|
9
|
-
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
|
|
10
|
-
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
11
|
-
import { AppDirs, Xdg } from "@effected/xdg";
|
|
2
|
+
import { main } from "../main.js";
|
|
12
3
|
|
|
13
4
|
//#region src/bin.ts
|
|
14
5
|
/**
|
|
@@ -16,47 +7,7 @@ import { AppDirs, Xdg } from "@effected/xdg";
|
|
|
16
7
|
*
|
|
17
8
|
* @packageDocumentation
|
|
18
9
|
*/
|
|
19
|
-
|
|
20
|
-
* K-9: `AppConfig.layer` only, built by Group B's `config/layer.ts` —
|
|
21
|
-
* `Xdg` and `AppDirs` are provided once, here, for both commands; no
|
|
22
|
-
* `Store`, no `Cache`, so no `store.db`/`cache.db` is ever created.
|
|
23
|
-
*
|
|
24
|
-
* `AppDirs.layer(options)` requires `Xdg | FileSystem | Path`
|
|
25
|
-
* (`XDG/index.d.ts:320`), so `Layer.provide(Xdg.layer)` alone does not close
|
|
26
|
-
* it: `Layer.provideMerge(NodeServices.layer)` supplies `FileSystem`/`Path`
|
|
27
|
-
* to both members and keeps every service in the output. `NodeServices.layer`
|
|
28
|
-
* provides `ChildProcessSpawner | Crypto | FileSystem | Path | Stdio |
|
|
29
|
-
* Terminal`, a superset of `Command.Environment`.
|
|
30
|
-
*
|
|
31
|
-
* `Xdg.layer` fails with `XdgEnvError` when `HOME` is unset (K-13). That
|
|
32
|
-
* error reaches `reportFailures` and takes its `exitCode: 3` fallback, with
|
|
33
|
-
* no special case anywhere — but only because `Effect.provide(PlatformLayer)`
|
|
34
|
-
* is applied INSIDE the region `CliRuntime.reportFailures` wraps, below.
|
|
35
|
-
* `@effected/cli`'s own doc example provides its layer after
|
|
36
|
-
* `reportFailures`; doing that here would let a failure while building this
|
|
37
|
-
* layer (an unset `HOME`, say) escape reportFailures entirely and fall to
|
|
38
|
-
* `NodeRuntime.runMain`'s own fatal-error path — a stack trace on stdout and
|
|
39
|
-
* exit `1`, not the rendered `exitCode: 3` this module promises.
|
|
40
|
-
*/
|
|
41
|
-
const PlatformLayer = Layer.mergeAll(Xdg.layer, AppDirs.layer({ namespace: "okfit" }).pipe(Layer.provide(Xdg.layer))).pipe(Layer.provideMerge(NodeServices.layer));
|
|
42
|
-
/**
|
|
43
|
-
* K-47: an ISO-8601 `OKFIT_NOW` when set, else the wall clock. A documented
|
|
44
|
-
* test hook, not user-facing. Resolved exactly once, here, and provided to
|
|
45
|
-
* the whole command tree through the `Now` tag so no command handler ever
|
|
46
|
-
* reads `process.env["OKFIT_NOW"]` itself.
|
|
47
|
-
*/
|
|
48
|
-
const nowEffect = Option.fromNullishOr(process.env.OKFIT_NOW).pipe(Option.flatMap((iso) => DateTime.make(iso)), Option.match({
|
|
49
|
-
onNone: () => DateTime.now,
|
|
50
|
-
onSome: Effect.succeed
|
|
51
|
-
}));
|
|
52
|
-
const program = Effect.gen(function* () {
|
|
53
|
-
const now = yield* nowEffect;
|
|
54
|
-
return yield* Command.run(rootCommand, { version: CLI_VERSION }).pipe(Effect.provideService(Now, now), Effect.catchTag("ShowHelp", (help) => Effect.fail(CliRuntime.reported(help, help.errors.length > 0 ? 64 : 0))));
|
|
55
|
-
}).pipe(Effect.provide(PlatformLayer), CliRuntime.reportFailures({
|
|
56
|
-
exitCode: 3,
|
|
57
|
-
render: renderFailure
|
|
58
|
-
}));
|
|
59
|
-
NodeRuntime.runMain(program.pipe(Effect.provide(CliLogger.layer())));
|
|
10
|
+
main();
|
|
60
11
|
|
|
61
12
|
//#endregion
|
|
62
13
|
export { };
|
package/commands/context.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { provideConfig } from "../config/layer.js";
|
|
2
|
-
import { resolveProjectConfig } from "../config/resolve.js";
|
|
3
|
-
import { runContext } from "../context/run.js";
|
|
4
1
|
import { setExitCode } from "../internal/exit.js";
|
|
5
|
-
import {
|
|
6
|
-
import { jsonError } from "../render/json.js";
|
|
2
|
+
import { humanContext } from "../render/context.js";
|
|
7
3
|
import { CLI_VERSION } from "../version.js";
|
|
8
4
|
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
5
|
+
import { ContextEnvelope, contextEnvelope, jsonError, provideConfig, resolveProjectConfig, runContext } from "@okfit/engine";
|
|
9
6
|
import { Console, Effect, Option, Schema } from "effect";
|
|
10
7
|
|
|
11
8
|
//#region src/commands/context.ts
|
|
@@ -20,7 +17,7 @@ const formatFlag = Flag.choice("format", ["human", "json"]).pipe(Flag.withDefaul
|
|
|
20
17
|
*
|
|
21
18
|
* Handler order fixed by the contract (§8.3): steps 1–7 are
|
|
22
19
|
* `validateCommand`'s handler in substance (both now share
|
|
23
|
-
* `
|
|
20
|
+
* `@okfit/engine`'s `resolveProjectConfig` — A4) — stat `--config` (K-1) via
|
|
24
21
|
* `provideConfig`, discover (`OkfitConfigFile.discover`), resolve the
|
|
25
22
|
* profile with the K-4 warning, merge `DEFAULTS < profile < file` (D-28),
|
|
26
23
|
* warn on an `okf_version` mismatch (K-15), resolve the project and bundle
|
package/commands/init.js
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
import { InitOverwriteError } from "../errors.js";
|
|
2
|
-
import { provideConfig } from "../config/layer.js";
|
|
3
|
-
import { resolveBundleRoot, resolveProjectRoot } from "../config/anchor.js";
|
|
4
1
|
import { setExitCode } from "../internal/exit.js";
|
|
5
|
-
import { forDiagnostics } from "../render/exit.js";
|
|
6
|
-
import { collect } from "../render/sort.js";
|
|
7
|
-
import { CONFIG_RELATIVE_PATH, SCHEMA_DIRECTIVE, configValue, files, targetPaths } from "../init/scaffold.js";
|
|
8
2
|
import { useColor } from "../internal/tty.js";
|
|
9
3
|
import { displayRoot, human, summary } from "../render/human.js";
|
|
10
|
-
import { Now, run } from "../validate/run.js";
|
|
11
4
|
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
5
|
+
import { CONFIG_RELATIVE_PATH, InitOverwriteError, Now, SCHEMA_DIRECTIVE, collect, configValue, files, forDiagnostics, provideConfig, resolveBundleRoot, resolveProjectRoot, run, targetPaths } from "@okfit/engine";
|
|
12
6
|
import { Console, DateTime, Effect, FileSystem, Layer, Option, Path, Schema } from "effect";
|
|
13
7
|
import { TomlCodec } from "@effected/config-file";
|
|
8
|
+
import { Git } from "@effected/git";
|
|
14
9
|
import { OKF_SPEC_VERSION, OkfitConfig, OkfitConfigFile } from "@okfit/core";
|
|
15
10
|
import { GitHistory, Profiles } from "@okfit/profiles";
|
|
16
|
-
import { Git } from "@effected/git";
|
|
17
11
|
|
|
18
12
|
//#region src/commands/init.ts
|
|
19
13
|
/**
|
|
@@ -74,7 +68,7 @@ const countsOf = (diagnostics, concepts) => ({
|
|
|
74
68
|
* fileConfig)`, `profileConfig` falling back to `NO_PROFILE_CONFIG` when
|
|
75
69
|
* no profile resolved.
|
|
76
70
|
* 6. `merged.okf_version !== OKF_SPEC_VERSION` warns (K-15).
|
|
77
|
-
* 7. `projectRoot`/`bundleRoot` via `config/anchor.ts`; `now = yield* Now`;
|
|
71
|
+
* 7. `projectRoot`/`bundleRoot` via `@okfit/engine`'s `config/anchor.ts`; `now = yield* Now`;
|
|
78
72
|
* `layout` falls back to `Profiles.softwareProject.layout` when no
|
|
79
73
|
* profile resolved (this file's own decision 2 above — `Layout` has no
|
|
80
74
|
* `DEFAULTS` equivalent).
|
package/commands/sync.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { provideConfig } from "../config/layer.js";
|
|
2
|
-
import { resolveProjectConfig } from "../config/resolve.js";
|
|
3
1
|
import { setExitCode } from "../internal/exit.js";
|
|
4
|
-
import { jsonError } from "../render/json.js";
|
|
5
2
|
import { CLI_VERSION } from "../version.js";
|
|
6
3
|
import { displayRoot } from "../render/human.js";
|
|
7
|
-
import {
|
|
8
|
-
import { SyncEnvelope, humanSync, syncEnvelope } from "../render/sync.js";
|
|
4
|
+
import { humanSync } from "../render/sync.js";
|
|
9
5
|
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
6
|
+
import { SyncEnvelope, jsonError, provideConfig, resolveProjectConfig, runSync, syncEnvelope } from "@okfit/engine";
|
|
10
7
|
import { Console, Effect, Layer, Option, Path, Schema } from "effect";
|
|
11
|
-
import { GitHistory } from "@okfit/profiles";
|
|
12
8
|
import { Git } from "@effected/git";
|
|
9
|
+
import { GitHistory } from "@okfit/profiles";
|
|
13
10
|
|
|
14
11
|
//#region src/commands/sync.ts
|
|
15
12
|
/** K-2: `[path]` is the PROJECT root, byte-identical to validate/init/context/verify's. */
|
package/commands/validate.js
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { provideConfig } from "../config/layer.js";
|
|
2
|
-
import { resolveProjectConfig } from "../config/resolve.js";
|
|
3
1
|
import { setExitCode } from "../internal/exit.js";
|
|
4
|
-
import { forDiagnostics } from "../render/exit.js";
|
|
5
|
-
import { collect } from "../render/sort.js";
|
|
6
|
-
import { JsonEnvelope, json, jsonError } from "../render/json.js";
|
|
7
2
|
import { CLI_VERSION } from "../version.js";
|
|
8
3
|
import { useColor } from "../internal/tty.js";
|
|
9
4
|
import { displayRoot, human, summary } from "../render/human.js";
|
|
10
|
-
import { Now, run } from "../validate/run.js";
|
|
11
5
|
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
6
|
+
import { JsonEnvelope, Now, collect, forDiagnostics, json, jsonError, provideConfig, resolveProjectConfig, run } from "@okfit/engine";
|
|
12
7
|
import { Console, Effect, Layer, Option, Path, Schema } from "effect";
|
|
8
|
+
import { Git } from "@effected/git";
|
|
13
9
|
import { OKF_SPEC_VERSION } from "@okfit/core";
|
|
14
10
|
import { GitHistory } from "@okfit/profiles";
|
|
15
|
-
import { Git } from "@effected/git";
|
|
16
11
|
|
|
17
12
|
//#region src/commands/validate.ts
|
|
18
13
|
/** `[path]` is the PROJECT root (K-2), never the bundle root. Absolute at parse time (K-50). */
|
|
@@ -30,7 +25,7 @@ const skipProvenanceFlag = Flag.boolean("skip-provenance").pipe(Flag.withDefault
|
|
|
30
25
|
* stat `--config` (K-1) via `provideConfig`, discover (`OkfitConfigFile.discover`),
|
|
31
26
|
* resolve the profile with the K-4 warning, merge `DEFAULTS < profile < file`
|
|
32
27
|
* (D-28), warn on an `okf_version` mismatch (K-15), resolve the project and
|
|
33
|
-
* bundle roots (K-12), run (`validate/run.ts#run`), collect and sort the
|
|
28
|
+
* bundle roots (K-12), run (`@okfit/engine`'s `validate/run.ts#run`), collect and sort the
|
|
34
29
|
* diagnostics, render per `--format` (K-18, K-20 to K-22), and set the exit
|
|
35
30
|
* code without failing the Effect (K-7, K-8).
|
|
36
31
|
*
|
package/commands/verify.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { provideConfig } from "../config/layer.js";
|
|
2
|
-
import { resolveProjectConfig } from "../config/resolve.js";
|
|
3
1
|
import { setExitCode } from "../internal/exit.js";
|
|
4
|
-
import { jsonError } from "../render/json.js";
|
|
5
2
|
import { CLI_VERSION } from "../version.js";
|
|
6
3
|
import { displayRoot } from "../render/human.js";
|
|
7
|
-
import {
|
|
8
|
-
import { VerifyEnvelope, humanVerify, verifyEnvelope } from "../render/verify.js";
|
|
9
|
-
import { runVerify } from "../verify/run.js";
|
|
4
|
+
import { humanVerify } from "../render/verify.js";
|
|
10
5
|
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
6
|
+
import { Now, VerifyEnvelope, jsonError, provideConfig, resolveProjectConfig, runVerify, verifyEnvelope } from "@okfit/engine";
|
|
11
7
|
import { Console, DateTime, Effect, Option, Path, Schema } from "effect";
|
|
12
|
-
import { Timestamp } from "@okfit/core";
|
|
13
8
|
import { Git } from "@effected/git";
|
|
9
|
+
import { Timestamp } from "@okfit/core";
|
|
14
10
|
|
|
15
11
|
//#region src/commands/verify.ts
|
|
16
12
|
/** V-6: tolerant id, normalised through `ConceptId.normalize`; never `Argument.path`. */
|
package/errors.js
CHANGED
|
@@ -1,111 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigMalformedError, ConfigPathNotFoundError, InitOverwriteError, VerifyConceptNotFoundError, VerifyUnsupportedFrontmatterError } from "@okfit/engine";
|
|
2
2
|
import { ConfigIssueRenderer } from "@effected/cli";
|
|
3
3
|
|
|
4
4
|
//#region src/errors.ts
|
|
5
|
-
/**
|
|
6
|
-
* `--config <path>` named a path that does not exist. Every `ConfigResolver`
|
|
7
|
-
* has a `never` error channel and `explicitPath` absorbs a missing target
|
|
8
|
-
* into `Option.none()`, so a bad `--config` would otherwise fall through to
|
|
9
|
-
* the XDG file silently. The CLI checks it itself before building any layer
|
|
10
|
-
* (K-1, spec 4.1).
|
|
11
|
-
*
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
var ConfigPathNotFoundError = class extends Schema.TaggedError()("ConfigPathNotFoundError", { path: Schema.String }) {
|
|
15
|
-
[Runtime.errorExitCode] = 3;
|
|
16
|
-
get message() {
|
|
17
|
-
return `config path not found: ${this.path}`;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* `okfit init` found one or more of its target paths already present (K-28).
|
|
22
|
-
* Carries the whole conflicting-path list so the renderer prints every one.
|
|
23
|
-
* `paths` are absolute; `renderFailure` relativises them to `cwd` (K-51).
|
|
24
|
-
*
|
|
25
|
-
* @public
|
|
26
|
-
*/
|
|
27
|
-
var InitOverwriteError = class extends Schema.TaggedError()("InitOverwriteError", {
|
|
28
|
-
paths: Schema.Array(Schema.String),
|
|
29
|
-
cwd: Schema.String
|
|
30
|
-
}) {
|
|
31
|
-
[Runtime.errorExitCode] = 3;
|
|
32
|
-
get message() {
|
|
33
|
-
return "refusing to overwrite existing files";
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* V-9: `<id>` did not resolve to a verifiable concept. `reason` is
|
|
38
|
-
* `"not-a-concept"` (no such file, or an id that normalises to nothing),
|
|
39
|
-
* `"reserved"` (the id names `index.md` or `log.md`), or `"undecodable"`
|
|
40
|
-
* (a file exists but `bundle.diagnostics` names it — `diagnosticCode`
|
|
41
|
-
* carries which). `root` is the absolute bundle root, kept OFF `message`
|
|
42
|
-
* so K-51's relativisation rule has nothing to apply to and the human
|
|
43
|
-
* line and the JSON envelope's `message` are identical.
|
|
44
|
-
*
|
|
45
|
-
* @public
|
|
46
|
-
*/
|
|
47
|
-
var VerifyConceptNotFoundError = class extends Schema.TaggedError()("VerifyConceptNotFoundError", {
|
|
48
|
-
id: Schema.String,
|
|
49
|
-
root: Schema.String,
|
|
50
|
-
reason: Schema.Literals([
|
|
51
|
-
"not-a-concept",
|
|
52
|
-
"reserved",
|
|
53
|
-
"undecodable"
|
|
54
|
-
]),
|
|
55
|
-
diagnosticCode: Schema.optionalKey(Schema.String)
|
|
56
|
-
}) {
|
|
57
|
-
[Runtime.errorExitCode] = 3;
|
|
58
|
-
get message() {
|
|
59
|
-
const detail = this.diagnosticCode === void 0 ? this.reason : `${this.reason}: ${this.diagnosticCode}`;
|
|
60
|
-
return `no concept "${this.id}" in this bundle (${detail})`;
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* V-14: fail closed on a `verified` shape the classifier does not name.
|
|
65
|
-
* `shape` is one of `"alias"`, `"merge-key"`, `"scalar"`, `"empty"` (and,
|
|
66
|
-
* defensively, `"no-frontmatter"` or `"not-a-mapping"`, neither reachable
|
|
67
|
-
* for a concept that reached `bundle.concepts`). The file is never opened
|
|
68
|
-
* for writing when this is raised.
|
|
69
|
-
*
|
|
70
|
-
* @public
|
|
71
|
-
*/
|
|
72
|
-
var VerifyUnsupportedFrontmatterError = class extends Schema.TaggedError()("VerifyUnsupportedFrontmatterError", {
|
|
73
|
-
id: Schema.String,
|
|
74
|
-
shape: Schema.String
|
|
75
|
-
}) {
|
|
76
|
-
[Runtime.errorExitCode] = 3;
|
|
77
|
-
get message() {
|
|
78
|
-
return `"${this.id}"'s verified value is a shape okfit verify cannot edit (${this.shape}); edit it by hand`;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
5
|
const hasTag = (error, tag) => typeof error === "object" && error !== null && "_tag" in error && error._tag === tag;
|
|
82
|
-
/** The error's `message` when it has one as a string, else `String(error)`. */
|
|
83
|
-
const messageOf = (error) => {
|
|
84
|
-
if (typeof error === "object" && error !== null && "message" in error) {
|
|
85
|
-
const message = error.message;
|
|
86
|
-
if (typeof message === "string") return message;
|
|
87
|
-
}
|
|
88
|
-
return String(error);
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* A config file at a KNOWN path failed to parse or validate (K-46's own
|
|
92
|
-
* intent — "each class' message already names the offending path" does not
|
|
93
|
-
* hold for `@effected/config-file`'s `ConfigCodecError`, which carries no
|
|
94
|
-
* `path` field at all; this wraps it, and `ConfigValidationError`, with the
|
|
95
|
-
* path the caller already knows). `cause` is the original config-file error,
|
|
96
|
-
* preserved structurally, never stringified early.
|
|
97
|
-
*
|
|
98
|
-
* @public
|
|
99
|
-
*/
|
|
100
|
-
var ConfigMalformedError = class extends Schema.TaggedError()("ConfigMalformedError", {
|
|
101
|
-
path: Schema.String,
|
|
102
|
-
cause: Schema.Defect()
|
|
103
|
-
}) {
|
|
104
|
-
[Runtime.errorExitCode] = 3;
|
|
105
|
-
get message() {
|
|
106
|
-
return `malformed config ${this.path}: ${messageOf(this.cause)}`;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
6
|
/** `path` relative to `cwd` when it is under it, else the absolute path unchanged (K-51). */
|
|
110
7
|
const relativeToCwd = (path, cwd) => {
|
|
111
8
|
if (path === cwd) return ".";
|
|
@@ -170,4 +67,4 @@ const renderFailure = (error) => {
|
|
|
170
67
|
};
|
|
171
68
|
|
|
172
69
|
//#endregion
|
|
173
|
-
export {
|
|
70
|
+
export { renderFailure };
|