From 15a350a5c48400ab45eb8221f2cac1891f57a62e Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:27:25 +0200 Subject: [PATCH 01/12] Add CLI directory entrypoint --- src/cli/index.ts | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/cli/index.ts diff --git a/src/cli/index.ts b/src/cli/index.ts new file mode 100644 index 0000000..f652958 --- /dev/null +++ b/src/cli/index.ts @@ -0,0 +1,108 @@ +#!/usr/bin/env bun + +import packageJson from "../../package.json"; +import { resolveBoardCommand, runBoardCommand } from "../commands.js"; +import { + type BoardCommandServices, + createDefaultBoardCommandServices, +} from "../commandServices.js"; + +export interface BoardCliContext { + readonly cwd: string; + readonly env: Readonly>; + readonly services?: BoardCommandServices; + readonly version: string; + writeStdout(text: string): void; + writeStderr(text: string): void; +} + +export interface BoardCliRunResult { + readonly exitCode: number; +} + +export function createDefaultBoardCliContext(): BoardCliContext { + const { env } = process; + + return { + cwd: process.cwd(), + env, + services: createDefaultBoardCommandServices(env), + version: packageJson.version, + writeStdout(text: string) { + process.stdout.write(text); + }, + writeStderr(text: string) { + process.stderr.write(text); + }, + }; +} + +export async function runCli( + argv: readonly string[], + context: BoardCliContext = createDefaultBoardCliContext(), +): Promise { + const [firstToken] = argv; + + if ( + firstToken === undefined || + firstToken === "--help" || + firstToken === "-h" || + firstToken === "help" + ) { + context.writeStdout(renderHelp()); + return { exitCode: 0 }; + } + + if (firstToken === "--version" || firstToken === "-v") { + context.writeStdout(`${context.version}\n`); + return { exitCode: 0 }; + } + + const resolvedCommand = resolveBoardCommand(argv); + if (resolvedCommand === null) { + context.writeStderr(renderUnknownCommand(argv)); + return { exitCode: 1 }; + } + + return await runBoardCommand( + resolvedCommand.command, + resolvedCommand.argv, + context, + ); +} + +export function renderHelp(): string { + return [ + "@ankhorage/board", + "", + "Ankh provider and standalone CLI for boarding external website sources.", + "", + "Usage:", + " ankhorage-board web ", + " ankhorage-board web --plan", + " ankhorage-board web --create ", + " ankhorage-board openapi ", + " ankhorage-board manifest generate ", + " ankhorage-board --help", + " ankhorage-board --version", + "", + "The website-source pipeline is currently implemented only for `web`.", + "OpenAPI import, standalone manifest generation, project creation, and bare URL shortcuts are deferred.", + "", + ].join("\n"); +} + +function renderUnknownCommand(argv: readonly string[]): string { + const input = argv.join(" ").trim(); + return [ + `Unknown board command: ${input.length > 0 ? input : "(none)"}`, + "Try:", + " ankhorage-board --help", + "", + ].join("\n"); +} + +if (import.meta.main) { + const result = await runCli(process.argv.slice(2)); + process.exit(result.exitCode); +} From 4844bd1355eec54b4204542d817d12dd578df87d Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:27:40 +0200 Subject: [PATCH 02/12] Point package binary at CLI directory --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b3af94..e971a81 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "paradox" ], "bin": { - "ankhorage-board": "./dist/cli.js" + "ankhorage-board": "./dist/cli/index.js" }, "ankh": { "category": "board", From 3f06acb3876e51c2b935790bff34f17aa21ea50a Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:28:04 +0200 Subject: [PATCH 03/12] Update CLI type imports --- src/commands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands.ts b/src/commands.ts index c7f60fe..349f537 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -3,7 +3,7 @@ import type { AnkhCommandDescriptor, } from "@ankhorage/contracts/cli"; -import type { BoardCliContext, BoardCliRunResult } from "./cli.js"; +import type { BoardCliContext, BoardCliRunResult } from "./cli/index.js"; import { createDefaultBoardCommandServices } from "./commandServices.js"; import { renderWebBoardingPlan } from "./webInspection.js"; From ae0df3f69d45d48c064ee6741933134b6d8cde87 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:28:13 +0200 Subject: [PATCH 04/12] Update README usage CLI import --- src/readme-usage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/readme-usage.ts b/src/readme-usage.ts index b0679fe..3d7bdd7 100644 --- a/src/readme-usage.ts +++ b/src/readme-usage.ts @@ -1,4 +1,4 @@ -import { runCli } from "./cli.js"; +import { runCli } from "./cli/index.js"; /*** * Website-source boarding From 56a615d9724d1d15bd7892ea3c5b99a161d32153 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:28:21 +0200 Subject: [PATCH 05/12] Update CLI test support import --- test/testSupport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testSupport.ts b/test/testSupport.ts index 5dd186a..e0618f2 100644 --- a/test/testSupport.ts +++ b/test/testSupport.ts @@ -1,4 +1,4 @@ -import type { BoardCliContext } from "../src/cli.js"; +import type { BoardCliContext } from "../src/cli/index.js"; import type { BoardCommandServices } from "../src/commandServices.js"; export interface BufferedContext extends BoardCliContext { From f01d5e29f399c27ff1037761e87efaabb7474cf2 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:28:31 +0200 Subject: [PATCH 06/12] Update package binary expectation --- test/package.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/package.test.ts b/test/package.test.ts index 29d28ea..901297d 100644 --- a/test/package.test.ts +++ b/test/package.test.ts @@ -8,7 +8,7 @@ describe("package metadata", () => { expect(packageJson.name).toBe("@ankhorage/board"); expect(packageJson.type).toBe("module"); expect(packageJson.bin).toEqual({ - "ankhorage-board": "./dist/cli.js", + "ankhorage-board": "./dist/cli/index.js", }); expect(packageJson.exports).toEqual({ ".": { From b5fd5c449675fe09c1efe25ff6499405d6b00c85 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:28:59 +0200 Subject: [PATCH 07/12] Update CLI tests for directory entrypoint --- test/cli.test.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/cli.test.ts b/test/cli.test.ts index 89d6a66..c4d280b 100644 --- a/test/cli.test.ts +++ b/test/cli.test.ts @@ -3,7 +3,7 @@ import { join } from "node:path"; import { describe, expect, it } from "bun:test"; import packageJson from "../package.json"; -import { runCli } from "../src/cli.js"; +import { runCli } from "../src/cli/index.js"; import { createBufferedContext, createStubBoardCommandServices, @@ -192,9 +192,9 @@ describe("package-scoped CLI commands", () => { const fixturePath = join(import.meta.dir, "fixtures", "example-com.html"); const cwd = import.meta.dir.replace(/\/test$/, ""); - it("covers `bun src/cli.ts web https://example.com`", () => { + it("covers `bun src/cli/index.ts web https://example.com`", () => { const result = Bun.spawnSync( - [process.execPath, "src/cli.ts", "web", "https://example.com"], + [process.execPath, "src/cli/index.ts", "web", "https://example.com"], { cwd, env: { @@ -213,7 +213,7 @@ describe("package-scoped CLI commands", () => { expect(stdout).toContain('"url": "https://example.com/"'); }); - it("covers `bun src/cli.ts web https://example.com --plan` and keeps output identical", () => { + it("covers `bun src/cli/index.ts web https://example.com --plan` and keeps output identical", () => { const env = { ...process.env, ANKHORAGE_BOARD_TEST_WEB_FIXTURE_PATH: fixturePath, @@ -221,7 +221,7 @@ describe("package-scoped CLI commands", () => { }; const withoutPlan = Bun.spawnSync( - [process.execPath, "src/cli.ts", "web", "https://example.com"], + [process.execPath, "src/cli/index.ts", "web", "https://example.com"], { cwd, env, @@ -230,7 +230,13 @@ describe("package-scoped CLI commands", () => { }, ); const withPlan = Bun.spawnSync( - [process.execPath, "src/cli.ts", "web", "https://example.com", "--plan"], + [ + process.execPath, + "src/cli/index.ts", + "web", + "https://example.com", + "--plan", + ], { cwd, env, From d8281c3fe5e1a8393ec5a7230ade3d37f9db2500 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:29:13 +0200 Subject: [PATCH 08/12] Refresh README CLI example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a2e1d0..248c766 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ deferred. Source: `src/readme-usage.ts` ```ts -import { runCli } from "./cli.js"; +import { runCli } from "./cli/index.js"; await runCli(["--help"]); ``` From fcc5358ed034eb592c3b7323d09dc0012c4b3e1c Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:29:19 +0200 Subject: [PATCH 09/12] Add CLI migration changeset --- .changeset/migrate-board-cli-directory.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/migrate-board-cli-directory.md diff --git a/.changeset/migrate-board-cli-directory.md b/.changeset/migrate-board-cli-directory.md new file mode 100644 index 0000000..9219302 --- /dev/null +++ b/.changeset/migrate-board-cli-directory.md @@ -0,0 +1,5 @@ +--- +"@ankhorage/board": patch +--- + +Move the standalone CLI entrypoint into `src/cli/` and update the published binary path. From 5c7e479b08773f1d8f9b99aa734dc27751d105b1 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:29:26 +0200 Subject: [PATCH 10/12] Remove legacy CLI entrypoint --- src/cli.ts | 108 ----------------------------------------------------- 1 file changed, 108 deletions(-) delete mode 100644 src/cli.ts diff --git a/src/cli.ts b/src/cli.ts deleted file mode 100644 index 3961510..0000000 --- a/src/cli.ts +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env bun - -import packageJson from "../package.json"; -import { resolveBoardCommand, runBoardCommand } from "./commands.js"; -import { - type BoardCommandServices, - createDefaultBoardCommandServices, -} from "./commandServices.js"; - -export interface BoardCliContext { - readonly cwd: string; - readonly env: Readonly>; - readonly services?: BoardCommandServices; - readonly version: string; - writeStdout(text: string): void; - writeStderr(text: string): void; -} - -export interface BoardCliRunResult { - readonly exitCode: number; -} - -export function createDefaultBoardCliContext(): BoardCliContext { - const { env } = process; - - return { - cwd: process.cwd(), - env, - services: createDefaultBoardCommandServices(env), - version: packageJson.version, - writeStdout(text: string) { - process.stdout.write(text); - }, - writeStderr(text: string) { - process.stderr.write(text); - }, - }; -} - -export async function runCli( - argv: readonly string[], - context: BoardCliContext = createDefaultBoardCliContext(), -): Promise { - const [firstToken] = argv; - - if ( - firstToken === undefined || - firstToken === "--help" || - firstToken === "-h" || - firstToken === "help" - ) { - context.writeStdout(renderHelp()); - return { exitCode: 0 }; - } - - if (firstToken === "--version" || firstToken === "-v") { - context.writeStdout(`${context.version}\n`); - return { exitCode: 0 }; - } - - const resolvedCommand = resolveBoardCommand(argv); - if (resolvedCommand === null) { - context.writeStderr(renderUnknownCommand(argv)); - return { exitCode: 1 }; - } - - return await runBoardCommand( - resolvedCommand.command, - resolvedCommand.argv, - context, - ); -} - -export function renderHelp(): string { - return [ - "@ankhorage/board", - "", - "Ankh provider and standalone CLI for boarding external website sources.", - "", - "Usage:", - " ankhorage-board web ", - " ankhorage-board web --plan", - " ankhorage-board web --create ", - " ankhorage-board openapi ", - " ankhorage-board manifest generate ", - " ankhorage-board --help", - " ankhorage-board --version", - "", - "The website-source pipeline is currently implemented only for `web`.", - "OpenAPI import, standalone manifest generation, project creation, and bare URL shortcuts are deferred.", - "", - ].join("\n"); -} - -function renderUnknownCommand(argv: readonly string[]): string { - const input = argv.join(" ").trim(); - return [ - `Unknown board command: ${input.length > 0 ? input : "(none)"}`, - "Try:", - " ankhorage-board --help", - "", - ].join("\n"); -} - -if (import.meta.main) { - const result = await runCli(process.argv.slice(2)); - process.exit(result.exitCode); -} From c58282d7877f4b3ca67a95657404d2d7e8886fbd Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:33:02 +0200 Subject: [PATCH 11/12] Declare CLI as Knip entrypoint --- knip.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/knip.config.ts b/knip.config.ts index fe2b27b..45601b1 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -1,6 +1,7 @@ import { createKnipConfig } from "@ankhorage/devtools/knip"; export default createKnipConfig({ + entry: ["src/cli/index.ts"], ignoreFiles: [ "eslint.config.mjs", "paradox.config.ts", From e86c3ec138525f271a044a461061a79bc43bbcd4 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:34:52 +0200 Subject: [PATCH 12/12] Declare all package entrypoints for Knip --- knip.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knip.config.ts b/knip.config.ts index 45601b1..0f466cb 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -1,7 +1,7 @@ import { createKnipConfig } from "@ankhorage/devtools/knip"; export default createKnipConfig({ - entry: ["src/cli/index.ts"], + entry: ["src/index.ts", "src/ankh.provider.ts", "src/cli/index.ts"], ignoreFiles: [ "eslint.config.mjs", "paradox.config.ts",