@okfit/cli 0.1.0 → 0.2.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 +332 -3
- package/bin/okfit.js +47 -4
- package/commands/context.js +78 -0
- package/commands/init.js +177 -0
- package/commands/root.js +26 -3
- package/commands/sync.js +111 -0
- package/commands/validate.js +98 -0
- package/commands/verify.js +98 -0
- package/config/anchor.js +57 -0
- package/config/layer.js +129 -0
- package/config/resolve.js +67 -0
- package/context/run.js +35 -0
- package/errors.js +173 -0
- package/index.d.ts +891 -6
- package/index.js +15 -10
- package/init/scaffold.js +174 -0
- package/internal/exit.js +14 -0
- package/internal/tty.js +13 -0
- package/package.js +5 -0
- package/package.json +17 -5
- package/render/context.js +108 -0
- package/render/exit.js +53 -0
- package/render/human.js +68 -0
- package/render/json.js +126 -0
- package/render/sort.js +46 -0
- package/render/sync.js +101 -0
- package/render/verify.js +72 -0
- package/sync/generated.js +111 -0
- package/sync/index.js +73 -0
- package/sync/log.js +127 -0
- package/sync/run.js +65 -0
- package/sync/write.js +48 -0
- package/validate/run.js +63 -0
- package/verify/locate.js +249 -0
- package/verify/run.js +106 -0
- package/verify/splice.js +75 -0
- package/version.js +14 -0
package/errors.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { Runtime, Schema } from "effect";
|
|
2
|
+
import { ConfigIssueRenderer } from "@effected/cli";
|
|
3
|
+
|
|
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
|
+
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
|
+
/** `path` relative to `cwd` when it is under it, else the absolute path unchanged (K-51). */
|
|
110
|
+
const relativeToCwd = (path, cwd) => {
|
|
111
|
+
if (path === cwd) return ".";
|
|
112
|
+
const prefix = cwd.endsWith("/") ? cwd : `${cwd}/`;
|
|
113
|
+
return path.startsWith(prefix) ? path.slice(prefix.length) : path;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* The `render` option for `CliRuntime.reportFailures` (K-30, K-46, K-51). One
|
|
117
|
+
* string per stderr line; `reportFailures` emits each through its own
|
|
118
|
+
* `Effect.logError`, which `CliLogger` routes to stderr.
|
|
119
|
+
*
|
|
120
|
+
* Rules, in order:
|
|
121
|
+
*
|
|
122
|
+
* 1. A `ShowHelp` (any `_tag === "ShowHelp"`) renders as `[]` — the empty
|
|
123
|
+
* array. `Command.runWith` has already rendered the help document and any
|
|
124
|
+
* parse errors before re-failing, so a second rendering here would print
|
|
125
|
+
* "Help requested" after the help text. This is why the K-30 remap in
|
|
126
|
+
* `bin.ts` can run ahead of `reportFailures` without corrupting `--help`
|
|
127
|
+
* output.
|
|
128
|
+
* 2. `ConfigPathNotFoundError` renders as its own `error: <message>` line;
|
|
129
|
+
* `InitOverwriteError` renders as the K-51 header, one two-space-indented
|
|
130
|
+
* relativised path per conflict, and the literal `Nothing was written.`.
|
|
131
|
+
* 3. `ConfigMalformedError` renders as its own `error: <message>` line —
|
|
132
|
+
* `error: malformed config <path>: <cause message>` — since it already
|
|
133
|
+
* carries the offending path (`config/layer.ts#provideConfig` wraps a
|
|
134
|
+
* `ConfigCodecError`/`ConfigValidationError` into this the moment the
|
|
135
|
+
* path is known).
|
|
136
|
+
* 4. A `ConfigValidationError` NOT already wrapped above (detected by
|
|
137
|
+
* `_tag`, since the peer is optional and this module keeps it a
|
|
138
|
+
* type-only import — this is the "path unknown" case, K-46) renders as
|
|
139
|
+
* `error: ${String(error)}` followed by one two-space-indented
|
|
140
|
+
* `ConfigIssueRenderer.render(error)` line per entry.
|
|
141
|
+
* 5. `VerifyConceptNotFoundError` and `VerifyUnsupportedFrontmatterError`
|
|
142
|
+
* each render as their own `error: <message>` line; both messages
|
|
143
|
+
* already name the concept id and what to do about it, and neither
|
|
144
|
+
* carries a filesystem path needing K-51 relativisation.
|
|
145
|
+
* 6. Everything else — core's `BundleRootNotFoundError`/`BundleReadError`/
|
|
146
|
+
* `BundleDepthExceededError`, config-file's other errors, `XdgEnvError`
|
|
147
|
+
* (the K-13 `HOME`-unset case) — renders as the single line
|
|
148
|
+
* `error: ${String(error)}`. Each of those
|
|
149
|
+
* classes' own `message` already names the offending path, which is all
|
|
150
|
+
* K-46 asserts.
|
|
151
|
+
*
|
|
152
|
+
* @public
|
|
153
|
+
*/
|
|
154
|
+
const renderFailure = (error) => {
|
|
155
|
+
if (hasTag(error, "ShowHelp")) return [];
|
|
156
|
+
if (error instanceof ConfigPathNotFoundError) return [`error: ${error.message}`];
|
|
157
|
+
if (error instanceof ConfigMalformedError) return [`error: ${error.message}`];
|
|
158
|
+
if (error instanceof InitOverwriteError) return [
|
|
159
|
+
"error: refusing to overwrite existing files:",
|
|
160
|
+
...error.paths.map((path) => ` ${relativeToCwd(path, error.cwd)}`),
|
|
161
|
+
"Nothing was written."
|
|
162
|
+
];
|
|
163
|
+
if (error instanceof VerifyConceptNotFoundError) return [`error: ${error.message}`];
|
|
164
|
+
if (error instanceof VerifyUnsupportedFrontmatterError) return [`error: ${error.message}`];
|
|
165
|
+
if (hasTag(error, "ConfigValidationError")) {
|
|
166
|
+
const validationError = error;
|
|
167
|
+
return [`error: ${String(validationError)}`, ...ConfigIssueRenderer.render(validationError).map((line) => ` ${line}`)];
|
|
168
|
+
}
|
|
169
|
+
return [`error: ${String(error)}`];
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
//#endregion
|
|
173
|
+
export { ConfigMalformedError, ConfigPathNotFoundError, InitOverwriteError, VerifyConceptNotFoundError, VerifyUnsupportedFrontmatterError, renderFailure };
|