@okfit/cli 0.8.1 → 0.9.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/commands/sync.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { CLI_VERSION } from "../version.js";
2
2
  import { displayRoot } from "../render/human.js";
3
- import { humanSync } from "../render/sync.js";
3
+ import { humanPublication, humanSync } from "../render/sync.js";
4
4
  import { Argument, Command, Flag } from "effect/cli";
5
5
  import { CurrentDistribution } from "@effected/engine";
6
- import { Now, SyncEnvelope, jsonError, provideConfig, resolveProjectConfig, runSync, syncEnvelope } from "@okfit/engine";
6
+ import { Now, SyncEnvelope, SyncPublicationConflictError, jsonError, provideConfig, resolveProjectConfig, runSync, stampPublication, syncEnvelope } from "@okfit/engine";
7
7
  import { Console, DateTime, Effect, Layer, Option, Path, Schema } from "effect";
8
8
  import { Git } from "@effected/git";
9
9
  import { GitHistory } from "@okfit/profiles";
@@ -42,9 +42,12 @@ const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefa
42
42
  const ISO_DATE = Schema.String.pipe(Schema.check(Schema.isPattern(/^\d{4}-\d{2}-\d{2}$/u, { message: "Expected a YYYY-MM-DD date" })));
43
43
  const sinceFlag = Flag.String("since").pipe(Flag.withSchema(ISO_DATE), Flag.optional, Flag.withDescription("log mode's inclusive floor (YYYY-MM-DD): consider every committed concept dated on or after it; default: the newest date already in log.md"));
44
44
  const stagedFlag = Flag.Boolean("staged").pipe(Flag.withDefault(false), Flag.withDescription("pre-commit mode: stamp only the concepts in the git index, with now as generated.at, and re-add what was written; log mode is excluded (default modes: generated, index)"));
45
+ const publicationFlag = Flag.String("publication").pipe(Flag.optional, Flag.withDescription("restamp one Publication's renders digests after re-rendering its page; runs nothing else"));
45
46
  /**
46
47
  * `okfit sync [path] [--config <file>] [--only <mode>]... [--dry-run]
47
- * [--format human|json] [--since <YYYY-MM-DD>] [--staged]`.
48
+ * [--format human|json] [--since <YYYY-MM-DD>] [--staged]
49
+ * [--publication <id>]`. `--publication` runs only `stampPublication` and
50
+ * rejects `--only`, `--staged` and `--since`.
48
51
  *
49
52
  * Handler order fixed by contract §4.3. Steps 1–3 are `context`'s/
50
53
  * `validate`'s handler in substance — stat `--config` (K-1) via
@@ -72,7 +75,8 @@ const syncCommand = Command.make("sync", {
72
75
  dryRun: dryRunFlag,
73
76
  format: formatFlag,
74
77
  since: sinceFlag,
75
- staged: stagedFlag
78
+ staged: stagedFlag,
79
+ publication: publicationFlag
76
80
  }, (input) => Effect.gen(function* () {
77
81
  const cwd = process.cwd();
78
82
  const discoveryCwd = Option.getOrElse(input.path, () => cwd);
@@ -84,6 +88,30 @@ const syncCommand = Command.make("sync", {
84
88
  explicitConfigPath: input.config,
85
89
  cwd
86
90
  });
91
+ if (Option.isSome(input.publication)) {
92
+ const conflicts = [
93
+ ...input.only.length > 0 ? ["--only"] : [],
94
+ ...input.staged ? ["--staged"] : [],
95
+ ...Option.isSome(input.since) ? ["--since"] : []
96
+ ];
97
+ if (conflicts.length > 0) return yield* new SyncPublicationConflictError({ flags: conflicts });
98
+ const stamped = yield* stampPublication({
99
+ bundleRoot: resolved.bundleRoot,
100
+ id: input.publication.value,
101
+ dryRun: input.dryRun
102
+ });
103
+ if (input.format === "json") {
104
+ const envelope = syncEnvelope({
105
+ okfitVersion: CLI_VERSION,
106
+ root: displayRoot(cwd, resolved.bundleRoot, path),
107
+ dryRun: input.dryRun,
108
+ publication: stamped,
109
+ ...Option.isSome(distribution) ? { distribution: distribution.value } : {}
110
+ });
111
+ yield* Console.log(JSON.stringify(Schema.encodeSync(SyncEnvelope)(envelope)));
112
+ } else for (const line of humanPublication(stamped, input.dryRun)) yield* Console.log(line);
113
+ return;
114
+ }
87
115
  const modes = input.only.length > 0 ? new Set(input.only) : input.staged ? /* @__PURE__ */ new Set(["generated", "index"]) : /* @__PURE__ */ new Set([
88
116
  "generated",
89
117
  "index",
package/errors.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { InitBundleDirError } from "./internal/initWizard.js";
2
2
  import { DocumentStdinIsTerminalError } from "./internal/stdin.js";
3
3
  import { Cancelled, ConfigIssueRenderer, NotInteractive } from "@effected/cli";
4
- import { ConfigMalformedError, ConfigPathNotFoundError, DocumentPathError, InitOverwriteError, QueryConceptNotFoundError, QuerySelectionError, QueryUnknownVocabularyError, SyncStagedLogError, VerifyConceptNotFoundError, VerifySelectionError, VerifyUnsupportedFrontmatterError } from "@okfit/engine";
4
+ import { ConfigMalformedError, ConfigPathNotFoundError, DocumentPathError, InitOverwriteError, NotAPublicationError, PublicationNotFoundError, QueryConceptNotFoundError, QuerySelectionError, QueryUnknownVocabularyError, SyncPublicationConflictError, SyncStagedLogError, VerifyConceptNotFoundError, VerifySelectionError, VerifyUnsupportedFrontmatterError } from "@okfit/engine";
5
5
 
6
6
  //#region src/errors.ts
7
7
  const hasTag = (error, tag) => typeof error === "object" && error !== null && "_tag" in error && error._tag === tag;
@@ -79,6 +79,9 @@ const renderFailure = (error) => {
79
79
  if (error instanceof VerifyConceptNotFoundError) return [`error: ${error.message}`];
80
80
  if (error instanceof VerifyUnsupportedFrontmatterError) return [`error: ${error.message}`];
81
81
  if (error instanceof SyncStagedLogError) return [`error: ${error.message}`];
82
+ if (error instanceof SyncPublicationConflictError) return [`error: ${error.message}`];
83
+ if (error instanceof PublicationNotFoundError) return error.publication === void 0 ? [`error: ${error.message}`, "hint: run okfit query --type Publication to list publication ids"] : [`error: ${error.message}`];
84
+ if (error instanceof NotAPublicationError) return [`error: ${error.message}`, "hint: run okfit query --type Publication to list publication ids"];
82
85
  if (error instanceof VerifySelectionError) return [`error: ${error.message}`];
83
86
  if (error instanceof QueryUnknownVocabularyError) return [`error: ${error.message}`];
84
87
  if (error instanceof QueryConceptNotFoundError) return [`error: ${error.message}`];
package/index.d.ts CHANGED
@@ -37,7 +37,7 @@ export declare const rootCommand: Command.Command<"okfit", {
37
37
  readonly human: readonly boolean[];
38
38
  readonly agent: readonly boolean[];
39
39
  readonly ci: readonly boolean[];
40
- }, import("@okfit/profiles").AgentActorUnconfiguredError | import("@okfit/core").BundleDepthExceededError | import("@okfit/core").BundleReadError | import("@okfit/core").BundleRootNotFoundError | import("@effected/cli").Cancelled | 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("@okfit/engine").DocumentPathError | DocumentStdinIsTerminalError | import("@effected/markdown").FrontmatterEncodeError | import("@effected/markdown").FrontmatterFormatMismatchError | import("@effected/markdown").FrontmatterValidationError | import("@effected/git").GitCommandError | import("@okfit/profiles").GitHistoryError | import("@okfit/profiles").HumanActorUnresolvedError | InitBundleDirError | import("@okfit/engine").InitOverwriteError | import("@effected/markdown").MarkdownParseError | import("@effected/git").NotARepositoryError | import("@effected/cli").NotInteractive | import("effect/PlatformError").PlatformError | import("@okfit/engine").QueryConceptNotFoundError | import("@okfit/engine").QuerySelectionError | import("@okfit/engine").QueryUnknownVocabularyError | import("effect/Schema").SchemaError | import("@okfit/engine").SyncStagedLogError | import("@effected/git").UnknownRefError | import("@okfit/engine").VerifyConceptNotFoundError | import("@okfit/engine").VerifySelectionError | import("@okfit/engine").VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError, import("@effected/xdg").AppDirs | import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("@effected/cli").CliExit | import("@effected/cli").CliTheme | import("effect/Crypto").Crypto | import("effect/FileSystem").FileSystem | import("@okfit/engine").Now | import("effect/Path").Path | import("effect/Stdio").Stdio | import("@effected/xdg").Xdg>;
40
+ }, import("@okfit/profiles").AgentActorUnconfiguredError | import("@okfit/core").BundleDepthExceededError | import("@okfit/core").BundleReadError | import("@okfit/core").BundleRootNotFoundError | import("@effected/cli").Cancelled | 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("@okfit/engine").DocumentPathError | DocumentStdinIsTerminalError | import("@effected/markdown").FrontmatterEncodeError | import("@effected/markdown").FrontmatterFormatMismatchError | import("@effected/markdown").FrontmatterValidationError | import("@effected/git").GitCommandError | import("@okfit/profiles").GitHistoryError | import("@okfit/profiles").HumanActorUnresolvedError | InitBundleDirError | import("@okfit/engine").InitOverwriteError | import("@effected/markdown").MarkdownParseError | import("@okfit/engine").NotAPublicationError | import("@effected/git").NotARepositoryError | import("@effected/cli").NotInteractive | import("effect/PlatformError").PlatformError | import("@okfit/engine").PublicationNotFoundError | import("@okfit/engine").QueryConceptNotFoundError | import("@okfit/engine").QuerySelectionError | import("@okfit/engine").QueryUnknownVocabularyError | import("effect/Schema").SchemaError | import("@okfit/engine").SyncPublicationConflictError | import("@okfit/engine").SyncStagedLogError | import("@effected/git").UnknownRefError | import("@okfit/engine").UnsupportedFrontmatterError | import("@okfit/engine").VerifyConceptNotFoundError | import("@okfit/engine").VerifySelectionError | import("@okfit/engine").VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError, import("@effected/xdg").AppDirs | import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("@effected/cli").CliExit | import("@effected/cli").CliTheme | import("effect/Crypto").Crypto | import("effect/FileSystem").FileSystem | import("@okfit/engine").Now | import("effect/Path").Path | import("effect/Stdio").Stdio | import("@effected/xdg").Xdg>;
41
41
  //#endregion
42
42
  //#region src/errors.d.ts
43
43
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okfit/cli",
3
- "version": "0.8.1",
3
+ "version": "0.9.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": [
@@ -55,9 +55,9 @@
55
55
  "@effected/toml": "^0.11.0",
56
56
  "@effected/walker": "^0.15.0",
57
57
  "@effected/yaml": "^0.19.0",
58
- "@okfit/core": "0.8.5",
59
- "@okfit/engine": "0.11.1",
60
- "@okfit/profiles": "0.8.3",
58
+ "@okfit/core": "0.9.0",
59
+ "@okfit/engine": "0.12.0",
60
+ "@okfit/profiles": "0.9.0",
61
61
  "effect": "^4.0.0",
62
62
  "ink": "^7.1.1",
63
63
  "react": "^19.2.0"
package/render/sync.js CHANGED
@@ -36,6 +36,17 @@ const humanSync = (result) => {
36
36
  lines.push(result.dryRun ? `would write ${totalWritten}, unchanged ${totalUnchanged}, skipped ${totalSkipped} (dry run, nothing written)` : `wrote ${totalWritten}, unchanged ${totalUnchanged}, skipped ${totalSkipped}`);
37
37
  return lines;
38
38
  };
39
+ /**
40
+ * Human output for `okfit sync --publication`: one line per rendered source's
41
+ * digest, then whether the Publication file changed.
42
+ *
43
+ * @public
44
+ */
45
+ const humanPublication = (result, dryRun) => [
46
+ `publication ${result.id}:`,
47
+ ...result.digests.map((d) => ` ${d.path} ${d.body_sha256}`),
48
+ result.written ? dryRun ? `would restamp ${result.id} (dry run, nothing written)` : `restamped ${result.id}` : `unchanged ${result.id}`
49
+ ];
39
50
 
40
51
  //#endregion
41
- export { humanSync };
52
+ export { humanPublication, humanSync };
package/version.js CHANGED
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @public
13
13
  */
14
- const CLI_VERSION = "0.8.1";
14
+ const CLI_VERSION = "0.9.0";
15
15
 
16
16
  //#endregion
17
17
  export { CLI_VERSION };