@okfit/cli 0.4.0 → 0.5.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 +28 -0
- package/commands/context.js +3 -3
- package/commands/init.js +10 -12
- package/commands/sync.js +9 -9
- package/commands/validate.js +4 -4
- package/commands/verify.js +8 -8
- package/index.d.ts +4 -3
- package/package.json +15 -15
- package/render/context.js +16 -3
- package/tsdoc-metadata.json +1 -1
- package/version.js +1 -1
package/README.md
CHANGED
|
@@ -113,6 +113,34 @@ $ echo $?
|
|
|
113
113
|
and names every colliding file in one error. An ancestor directory's config
|
|
114
114
|
is a legitimate discovery hit, not a collision, and is never probed.
|
|
115
115
|
|
|
116
|
+
If the repository lints markdown, the bundle needs two exemptions from
|
|
117
|
+
markdownlint's defaults, and neither can be satisfied at the source: MD025
|
|
118
|
+
(one top-level heading) counts a concept's frontmatter `title:` as its H1,
|
|
119
|
+
so the body H1 the spec requires reads as a second one, and the spec shapes
|
|
120
|
+
every `index.md` as `# Section` groups, one H1 per concept type. `log.md`
|
|
121
|
+
is fine: `init` and `sync` both start it with `# Log`. Add this to a
|
|
122
|
+
`.markdownlint-cli2.jsonc` at the repository root, adjusting the bundle
|
|
123
|
+
path if `bundle.path` is not `okf`:
|
|
124
|
+
|
|
125
|
+
```jsonc
|
|
126
|
+
"overrides": [
|
|
127
|
+
{
|
|
128
|
+
"combine": "merge",
|
|
129
|
+
"config": { "MD025": { "front_matter_title": "" } },
|
|
130
|
+
"filter": ["okf/**/*.md", "!okf/**/index.md"]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"combine": "merge",
|
|
134
|
+
"config": { "MD025": false },
|
|
135
|
+
"filter": ["okf/**/index.md"]
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
A repository whose lint config cannot express overrides can drop a nested
|
|
141
|
+
`okf/.markdownlint-cli2.jsonc` carrying `{ "config": { "MD025": false } }`
|
|
142
|
+
instead; the bundle loader ignores non-markdown files.
|
|
143
|
+
|
|
116
144
|
`--profile <name>` picks the profile `init` scaffolds for (default: the
|
|
117
145
|
config's `bundle.profile`, itself defaulting to `software-project`); an
|
|
118
146
|
unrecognised name is a warning, not a failure — `init` continues with the
|
package/commands/context.js
CHANGED
|
@@ -7,11 +7,11 @@ import { Console, Effect, Option, Schema } from "effect";
|
|
|
7
7
|
|
|
8
8
|
//#region src/commands/context.ts
|
|
9
9
|
/** `[path]` is the PROJECT root (K-2), never the bundle root. Absolute at parse time (K-50). */
|
|
10
|
-
const pathArg = Argument.
|
|
10
|
+
const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
|
|
11
11
|
/** K-1: no `mustExist` — the handler stats the path itself, before building any layer. */
|
|
12
|
-
const configFlag = Flag.
|
|
12
|
+
const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
|
|
13
13
|
/** No `--profile` flag: M-15's exact ruling; that flag belongs to `init` alone. */
|
|
14
|
-
const formatFlag = Flag.
|
|
14
|
+
const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
|
|
15
15
|
/**
|
|
16
16
|
* `okfit context [path] [--config <file>] [--format human|json]`.
|
|
17
17
|
*
|
package/commands/init.js
CHANGED
|
@@ -3,8 +3,7 @@ import { useColor } from "../internal/tty.js";
|
|
|
3
3
|
import { displayRoot, human, summary } from "../render/human.js";
|
|
4
4
|
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
5
5
|
import { CONFIG_RELATIVE_PATH, InitOverwriteError, Now, SCHEMA_DIRECTIVE, collect, configValue, files, forDiagnostics, provideConfig, resolveBundleRoot, resolveProjectRoot, run, targetPaths } from "@okfit/engine";
|
|
6
|
-
import { Console, DateTime, Effect, FileSystem, Layer, Option, Path
|
|
7
|
-
import { TomlCodec } from "@effected/config-file";
|
|
6
|
+
import { Console, DateTime, Effect, FileSystem, Layer, Option, Path } from "effect";
|
|
8
7
|
import { Git } from "@effected/git";
|
|
9
8
|
import { OKF_SPEC_VERSION, OkfitConfig, OkfitConfigFile } from "@okfit/core";
|
|
10
9
|
import { GitHistory, Profiles } from "@okfit/profiles";
|
|
@@ -12,19 +11,19 @@ import { GitHistory, Profiles } from "@okfit/profiles";
|
|
|
12
11
|
//#region src/commands/init.ts
|
|
13
12
|
/**
|
|
14
13
|
* `[path]` is the PROJECT root (K-2), never the bundle root — identical to
|
|
15
|
-
* `validate`'s own argument (`Argument.
|
|
14
|
+
* `validate`'s own argument (`Argument.Path` resolves it absolute at the
|
|
16
15
|
* parse boundary, satisfying K-50).
|
|
17
16
|
*/
|
|
18
|
-
const pathArg = Argument.
|
|
17
|
+
const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
|
|
19
18
|
/** K-1: no `mustExist` — existence is checked by `provideConfig`, identical to `validate`'s flag. */
|
|
20
|
-
const configFlag = Flag.
|
|
19
|
+
const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
|
|
21
20
|
/**
|
|
22
|
-
* K-3: `Flag.
|
|
21
|
+
* K-3: `Flag.String`, deliberately not `Flag.Literals` against
|
|
23
22
|
* `PROFILE_NAMES` (`PROFILES/Profile.ts:10`) — an unrecognised name is a
|
|
24
23
|
* CLI-rendered warning (K-4), matching `Profiles.get`'s own `Option.none`
|
|
25
24
|
* contract (P-38), not a parser-level `CliError.InvalidValue`.
|
|
26
25
|
*/
|
|
27
|
-
const profileFlag = Flag.
|
|
26
|
+
const profileFlag = Flag.String("profile").pipe(Flag.optional, Flag.withDescription("profile to scaffold with (default: the config's bundle.profile or software-project)"));
|
|
28
27
|
/**
|
|
29
28
|
* Stands in for `profile.config` when `Profiles.get` returns `None`.
|
|
30
29
|
* `OkfitConfig.merge` only visits `Object.keys(override)`
|
|
@@ -100,7 +99,8 @@ const initCommand = Command.make("init", {
|
|
|
100
99
|
explicitConfigPath: input.config,
|
|
101
100
|
discoveryCwd
|
|
102
101
|
})(Effect.gen(function* () {
|
|
103
|
-
const
|
|
102
|
+
const configFile = yield* OkfitConfigFile;
|
|
103
|
+
const winner = (yield* configFile.discover)[0];
|
|
104
104
|
const fileConfig = winner === void 0 ? { extensions: {} } : winner.value;
|
|
105
105
|
const profileName = Option.getOrElse(input.profile, () => fileConfig.bundle?.profile ?? DEFAULT_PROFILE_NAME);
|
|
106
106
|
const profile = Profiles.get(profileName);
|
|
@@ -145,12 +145,10 @@ const initCommand = Command.make("init", {
|
|
|
145
145
|
});
|
|
146
146
|
for (const target of paths) yield* fs.makeDirectory(path.dirname(target), { recursive: true });
|
|
147
147
|
const bundlePath = merged.bundle?.path ?? DEFAULT_BUNDLE_PATH;
|
|
148
|
-
|
|
148
|
+
yield* configFile.write(configValue({
|
|
149
149
|
...scaffoldOptions,
|
|
150
150
|
bundlePath
|
|
151
|
-
}));
|
|
152
|
-
const toml = yield* TomlCodec.stringify(encoded);
|
|
153
|
-
yield* fs.writeFileString(`${projectRoot}/${CONFIG_RELATIVE_PATH}`, `${SCHEMA_DIRECTIVE}${toml}`);
|
|
151
|
+
}), `${projectRoot}/${CONFIG_RELATIVE_PATH}`, { header: SCHEMA_DIRECTIVE });
|
|
154
152
|
const scaffoldFiles = yield* files(scaffoldOptions);
|
|
155
153
|
for (const file of scaffoldFiles) yield* fs.writeFileString(file.path, file.contents);
|
|
156
154
|
yield* Console.log(`Initialized ${displayRoot(cwd, bundleRoot, path)} with the ${profileName} profile`);
|
package/commands/sync.js
CHANGED
|
@@ -10,11 +10,11 @@ import { GitHistory } from "@okfit/profiles";
|
|
|
10
10
|
|
|
11
11
|
//#region src/commands/sync.ts
|
|
12
12
|
/** K-2: `[path]` is the PROJECT root, byte-identical to validate/init/context/verify's. */
|
|
13
|
-
const pathArg = Argument.
|
|
13
|
+
const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory)"));
|
|
14
14
|
/** K-1: no `mustExist` — the handler stats it via `provideConfig`. */
|
|
15
|
-
const configFlag = Flag.
|
|
15
|
+
const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
|
|
16
16
|
/**
|
|
17
|
-
* S-13: a REPEATED `Flag.
|
|
17
|
+
* S-13: a REPEATED `Flag.Literals`, not a comma-separated `Flag.String`.
|
|
18
18
|
* `Flag.atLeast(0)` allows zero occurrences (all three modes run) up
|
|
19
19
|
* through any number. Each occurrence is independently validated by the
|
|
20
20
|
* underlying `Choice` primitive, so a bad token (`--only badmode`) is a
|
|
@@ -22,22 +22,22 @@ const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription(
|
|
|
22
22
|
* existing 64 remap — no new error class, no hand-built `ShowHelp`
|
|
23
23
|
* (contract §11, S-13, judge note 9).
|
|
24
24
|
*
|
|
25
|
-
* Note: `Flag.
|
|
26
|
-
* takes `(name: string,
|
|
25
|
+
* Note: `Flag.Literals`'s installed signature (`effect/unstable/cli/Flag.ts:169-172`)
|
|
26
|
+
* takes `(name: string, literals: ReadonlyArray<string>)`, matching
|
|
27
27
|
* `formatFlag` below — not the `[value, label]` tuple-pair form
|
|
28
|
-
* `Flag.
|
|
28
|
+
* `Flag.ChoiceWithValue` takes. The contract's own `onlyFlag` sketch
|
|
29
29
|
* writes tuple pairs; since every pair's two elements are identical
|
|
30
30
|
* (`["generated", "generated"]`, etc.), the plain string-array form
|
|
31
31
|
* below is the same flag, verified against the installed primitive
|
|
32
32
|
* rather than copied byte-for-byte from the contract's prose.
|
|
33
33
|
*/
|
|
34
|
-
const onlyFlag = Flag.
|
|
34
|
+
const onlyFlag = Flag.Literals("only", [
|
|
35
35
|
"generated",
|
|
36
36
|
"index",
|
|
37
37
|
"log"
|
|
38
38
|
]).pipe(Flag.atLeast(0), Flag.withDescription("restrict the run to these modes (repeatable: --only generated --only index); default: all three"));
|
|
39
|
-
const dryRunFlag = Flag.
|
|
40
|
-
const formatFlag = Flag.
|
|
39
|
+
const dryRunFlag = Flag.Boolean("dry-run").pipe(Flag.withDefault(false), Flag.withDescription("compute every result and write nothing"));
|
|
40
|
+
const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
|
|
41
41
|
/**
|
|
42
42
|
* `okfit sync [path] [--config <file>] [--only <mode>]... [--dry-run]
|
|
43
43
|
* [--format human|json]`.
|
package/commands/validate.js
CHANGED
|
@@ -11,13 +11,13 @@ import { GitHistory } from "@okfit/profiles";
|
|
|
11
11
|
|
|
12
12
|
//#region src/commands/validate.ts
|
|
13
13
|
/** `[path]` is the PROJECT root (K-2), never the bundle root. Absolute at parse time (K-50). */
|
|
14
|
-
const pathArg = Argument.
|
|
14
|
+
const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
|
|
15
15
|
/** K-1: no `mustExist` — the handler stats the path itself, before building any layer. */
|
|
16
|
-
const configFlag = Flag.
|
|
16
|
+
const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
|
|
17
17
|
/** K-6: `--format` is on `validate` only. */
|
|
18
|
-
const formatFlag = Flag.
|
|
18
|
+
const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
|
|
19
19
|
/** S-31: skips `Provenance.lint`'s git tier for this invocation, without touching `[lint]`. */
|
|
20
|
-
const skipProvenanceFlag = Flag.
|
|
20
|
+
const skipProvenanceFlag = Flag.Boolean("skip-provenance").pipe(Flag.withDefault(false), Flag.withDescription("skip the generated-at-drift lint's git tier for this run"));
|
|
21
21
|
/**
|
|
22
22
|
* `okfit validate [path] [--config <file>] [--format human|json] [--skip-provenance]`.
|
|
23
23
|
*
|
package/commands/verify.js
CHANGED
|
@@ -9,17 +9,17 @@ import { Git } from "@effected/git";
|
|
|
9
9
|
import { Timestamp } from "@okfit/core";
|
|
10
10
|
|
|
11
11
|
//#region src/commands/verify.ts
|
|
12
|
-
/** V-6: tolerant id, normalised through `ConceptId.normalize`; never `Argument.
|
|
13
|
-
const idArg = Argument.
|
|
12
|
+
/** V-6: tolerant id, normalised through `ConceptId.normalize`; never `Argument.Path`. */
|
|
13
|
+
const idArg = Argument.String("id").pipe(Argument.withDescription("concept id to verify, with or without a leading slash or trailing .md"));
|
|
14
14
|
/** K-2: `[path]` is the PROJECT root, byte-identical to validate/init/context's. */
|
|
15
|
-
const pathArg = Argument.
|
|
15
|
+
const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
|
|
16
16
|
/** K-1: no `mustExist`; the handler stats it via `provideConfig`. */
|
|
17
|
-
const configFlag = Flag.
|
|
18
|
-
/** V-6: `Flag.
|
|
19
|
-
const atFlag = Flag.
|
|
17
|
+
const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
|
|
18
|
+
/** V-6: `Flag.String`, decoded through core's `Timestamp` — never `Flag.Date`, which yields a bare Date. */
|
|
19
|
+
const atFlag = Flag.String("at").pipe(Flag.optional, Flag.withDescription("ISO 8601 timestamp with an explicit offset to record instead of now"));
|
|
20
20
|
/** V-6/V-8: the preview is a flag, never a prompt. */
|
|
21
|
-
const dryRunFlag = Flag.
|
|
22
|
-
const formatFlag = Flag.
|
|
21
|
+
const dryRunFlag = Flag.Boolean("dry-run").pipe(Flag.withDefault(false), Flag.withDescription("print the exact fragment a real run would splice in; write nothing"));
|
|
22
|
+
const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
|
|
23
23
|
/**
|
|
24
24
|
* `okfit verify <id> [path] [--config <file>] [--at <iso>] [--dry-run]
|
|
25
25
|
* [--format human|json]`.
|
package/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ import "effect";
|
|
|
20
20
|
*
|
|
21
21
|
* @public
|
|
22
22
|
*/
|
|
23
|
-
export declare const rootCommand: Command.Command<"okfit", {} | {}, {}, import("@okfit/profiles").AgentActorUnconfiguredError | import("@okfit/core").BundleDepthExceededError | import("@okfit/core").BundleReadError | import("@okfit/core").BundleRootNotFoundError | import("@effected/config-file").ConfigCodecError | import("@effected/config-file").ConfigFileReadError | import("@okfit/engine").ConfigMalformedError | import("@okfit/engine").ConfigPathNotFoundError | import("@effected/config-file").ConfigValidationError | import("@effected/markdown").FrontmatterEncodeError | import("@effected/markdown").FrontmatterFormatMismatchError | import("@effected/markdown").FrontmatterValidationError | import("@effected/git").GitCommandError | import("@okfit/profiles").GitHistoryError | import("@okfit/profiles").HumanActorUnresolvedError | import("@okfit/engine").InitOverwriteError | import("@effected/markdown").MarkdownParseError | import("@effected/git").NotARepositoryError | import("effect/PlatformError").PlatformError | import("effect/Schema").SchemaError | import("@effected/git").UnknownRefError | import("@okfit/engine").VerifyConceptNotFoundError | import("@okfit/engine").VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError, import("@effected/xdg").AppDirs | import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/Crypto").Crypto | import("effect/FileSystem").FileSystem | import("@okfit/engine").Now | import("effect/Path").Path | import("@effected/xdg").Xdg>;
|
|
23
|
+
export declare const rootCommand: Command.Command<"okfit", {} | {}, {}, import("@okfit/profiles").AgentActorUnconfiguredError | import("@okfit/core").BundleDepthExceededError | import("@okfit/core").BundleReadError | import("@okfit/core").BundleRootNotFoundError | import("@effected/config-file").ConfigCodecError | import("@effected/config-file").ConfigFileReadError | import("@effected/config-file").ConfigFileWriteError | import("@okfit/engine").ConfigMalformedError | import("@okfit/engine").ConfigPathNotFoundError | import("@effected/config-file").ConfigValidationError | import("@effected/markdown").FrontmatterEncodeError | import("@effected/markdown").FrontmatterFormatMismatchError | import("@effected/markdown").FrontmatterValidationError | import("@effected/git").GitCommandError | import("@okfit/profiles").GitHistoryError | import("@okfit/profiles").HumanActorUnresolvedError | import("@okfit/engine").InitOverwriteError | import("@effected/markdown").MarkdownParseError | import("@effected/git").NotARepositoryError | import("effect/PlatformError").PlatformError | import("effect/Schema").SchemaError | import("@effected/git").UnknownRefError | import("@okfit/engine").VerifyConceptNotFoundError | import("@okfit/engine").VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError, import("@effected/xdg").AppDirs | import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/Crypto").Crypto | import("effect/FileSystem").FileSystem | import("@okfit/engine").Now | import("effect/Path").Path | import("@effected/xdg").Xdg>;
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region src/errors.d.ts
|
|
26
26
|
/**
|
|
@@ -66,8 +66,9 @@ export declare const renderFailure: (error: unknown) => ReadonlyArray<string>;
|
|
|
66
66
|
//#endregion
|
|
67
67
|
//#region src/render/context.d.ts
|
|
68
68
|
/**
|
|
69
|
-
* The `human` format: a short header block, then one line per type
|
|
70
|
-
* per tag. Pure; the caller
|
|
69
|
+
* The `human` format: a short header block, then one line per type (plus
|
|
70
|
+
* its constraint lines, when it has any) and one per tag. Pure; the caller
|
|
71
|
+
* pipes each line through `Console.log`.
|
|
71
72
|
*
|
|
72
73
|
* The `profile:` line reads `profile: (none) (requested NAME, unknown)`
|
|
73
74
|
* when `profile` and `profile_requested` disagree over an actually-unknown
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okfit/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The okfit command line: validate, lint, index, and inspect Open Knowledge Format (OKF) bundles.",
|
|
6
6
|
"keywords": [
|
|
@@ -42,20 +42,20 @@
|
|
|
42
42
|
"okfit": "bin/okfit.js"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@effect/platform-node": "4.0.0-rc.
|
|
46
|
-
"@effected/cli": "^0.
|
|
47
|
-
"@effected/config-file": "^0.
|
|
48
|
-
"@effected/git": "^0.
|
|
49
|
-
"@effected/glob": "^0.
|
|
50
|
-
"@effected/jsonc": "^0.
|
|
51
|
-
"@effected/markdown": "^0.
|
|
52
|
-
"@effected/toml": "^0.
|
|
53
|
-
"@effected/walker": "^0.
|
|
54
|
-
"@effected/yaml": "^0.
|
|
55
|
-
"@okfit/core": "0.
|
|
56
|
-
"@okfit/engine": "0.
|
|
57
|
-
"@okfit/profiles": "0.
|
|
58
|
-
"effect": "4.0.0-rc.
|
|
45
|
+
"@effect/platform-node": "4.0.0-rc.115",
|
|
46
|
+
"@effected/cli": "^0.4.1",
|
|
47
|
+
"@effected/config-file": "^0.9.0",
|
|
48
|
+
"@effected/git": "^0.15.1",
|
|
49
|
+
"@effected/glob": "^0.6.0",
|
|
50
|
+
"@effected/jsonc": "^0.11.0",
|
|
51
|
+
"@effected/markdown": "^0.10.0",
|
|
52
|
+
"@effected/toml": "^0.7.0",
|
|
53
|
+
"@effected/walker": "^0.9.0",
|
|
54
|
+
"@effected/yaml": "^0.15.1",
|
|
55
|
+
"@okfit/core": "0.4.0",
|
|
56
|
+
"@okfit/engine": "0.3.0",
|
|
57
|
+
"@okfit/profiles": "0.4.0",
|
|
58
|
+
"effect": "4.0.0-rc.115"
|
|
59
59
|
},
|
|
60
60
|
"engines": {
|
|
61
61
|
"node": ">=24.11.0"
|
package/render/context.js
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
//#region src/render/context.ts
|
|
2
|
+
/** `kind (a | b)` for an enum field, `resource (path)` for a path field, bare `layer` for free text. */
|
|
3
|
+
const renderField = (field) => field.values !== null ? `${field.name} (${field.values.map((v) => v.name).join(" | ")})` : field.kind !== null ? `${field.name} (${field.kind})` : field.name;
|
|
2
4
|
/**
|
|
3
|
-
* The
|
|
4
|
-
*
|
|
5
|
+
* The constraint lines under one type bullet (issue #33): what `validate`
|
|
6
|
+
* will require of a concept of this type, so an agent learns it here and
|
|
7
|
+
* not from a lint error. Empty for a type that declares none.
|
|
8
|
+
*/
|
|
9
|
+
const constraintLines = (type) => [
|
|
10
|
+
...type.required !== null && type.required.length > 0 ? [` required: ${type.required.join(", ")}`] : [],
|
|
11
|
+
...type.require_verified === true ? [" verified: required"] : [],
|
|
12
|
+
...type.fields.length > 0 ? [` fields: ${type.fields.map(renderField).join(", ")}`] : []
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* The `human` format: a short header block, then one line per type (plus
|
|
16
|
+
* its constraint lines, when it has any) and one per tag. Pure; the caller
|
|
17
|
+
* pipes each line through `Console.log`.
|
|
5
18
|
*
|
|
6
19
|
* The `profile:` line reads `profile: (none) (requested NAME, unknown)`
|
|
7
20
|
* when `profile` and `profile_requested` disagree over an actually-unknown
|
|
@@ -19,7 +32,7 @@ const humanContext = (envelope) => [
|
|
|
19
32
|
`agent: ${envelope.actors.agent ?? "(unset)"}`,
|
|
20
33
|
"",
|
|
21
34
|
"types:",
|
|
22
|
-
...envelope.types.
|
|
35
|
+
...envelope.types.flatMap((t) => [` ${t.name} ${t.description ?? ""}`, ...constraintLines(t)]),
|
|
23
36
|
"",
|
|
24
37
|
"tags:",
|
|
25
38
|
...envelope.tags.map((t) => ` ${t.name} ${t.description ?? ""}`)
|
package/tsdoc-metadata.json
CHANGED