Use Match for CLI MIME detection

This commit is contained in:
elpresidank 2026-06-04 05:56:53 -05:00
parent 89f9d63b88
commit a0d98a573b
4 changed files with 51 additions and 22 deletions

View file

@ -499,6 +499,21 @@ Notes:
- `bun run --cwd ts/packages/flow test -- src/__tests__/agent-service.test.ts` - `bun run --cwd ts/packages/flow test -- src/__tests__/agent-service.test.ts`
- `cd ts && bun run check:tsgo` - `cd ts && bun run check:tsgo`
### 2026-06-04: CLI Library MIME Match Slice
- Status: migrated and package-verified.
- Completed:
- `ts/packages/cli/src/commands/library.ts` now uses `effect/Match` for
extension-to-MIME mapping instead of a native `switch`.
- `guessMimeType` is exported for focused CLI helper coverage.
- CLI tests now cover known extensions, case normalization, `html`/`htm`
aliases, and fallback behavior for unknown or extensionless paths.
- `ts/packages/cli/package.json` excludes `dist/**` from Vitest so built
test output is not executed a second time after root build lanes.
- Verification:
- `bun run --cwd ts/packages/cli test -- src/__tests__/library.test.ts`
- `cd ts && bun run check:tsgo`
### 2026-06-02: RAG And Agent Requestor Bridge Slice ### 2026-06-02: RAG And Agent Requestor Bridge Slice
- Status: migrated, root-verified, committed, and pushed. - Status: migrated, root-verified, committed, and pushed.

View file

@ -9,7 +9,7 @@
"build": "bunx --bun tsc", "build": "bunx --bun tsc",
"dev": "tsc --watch", "dev": "tsc --watch",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"test": "bunx --bun vitest run --passWithNoTests" "test": "bunx --bun vitest run --passWithNoTests --exclude=dist/**"
}, },
"dependencies": { "dependencies": {
"@trustgraph/base": "workspace:*", "@trustgraph/base": "workspace:*",

View file

@ -0,0 +1,22 @@
import { describe, expect, it } from "vitest";
import { guessMimeType } from "../commands/library.js";
describe("library CLI helpers", () => {
it("detects known MIME types through the Match-backed extension mapper", () => {
expect(guessMimeType("paper.pdf")).toBe("application/pdf");
expect(guessMimeType("notes.TXT")).toBe("text/plain");
expect(guessMimeType("readme.md")).toBe("text/markdown");
expect(guessMimeType("index.html")).toBe("text/html");
expect(guessMimeType("partial.htm")).toBe("text/html");
expect(guessMimeType("data.json")).toBe("application/json");
expect(guessMimeType("table.csv")).toBe("text/csv");
expect(guessMimeType("brief.docx")).toBe(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
);
});
it("falls back for unknown or extensionless paths", () => {
expect(guessMimeType("archive.bin")).toBe("application/octet-stream");
expect(guessMimeType("README")).toBe("application/octet-stream");
});
});

View file

@ -5,7 +5,7 @@
*/ */
import type { Command } from "commander"; import type { Command } from "commander";
import { Effect } from "effect"; import { Effect, Match } from "effect";
import { cliCommandError, withSocket, writeJson } from "./util.js"; import { cliCommandError, withSocket, writeJson } from "./util.js";
function basenamePath(filepath: string): string { function basenamePath(filepath: string): string {
@ -15,27 +15,19 @@ function basenamePath(filepath: string): string {
} }
/** Simple MIME-type lookup by file extension. */ /** Simple MIME-type lookup by file extension. */
function guessMimeType(filepath: string): string { export function guessMimeType(filepath: string): string {
const ext = filepath.split(".").pop()?.toLowerCase(); const ext = filepath.split(".").pop()?.toLowerCase();
switch (ext) { return Match.value(ext).pipe(
case "pdf": Match.when("pdf", () => "application/pdf"),
return "application/pdf"; Match.when("txt", () => "text/plain"),
case "txt": Match.when("md", () => "text/markdown"),
return "text/plain"; Match.when("html", () => "text/html"),
case "md": Match.when("htm", () => "text/html"),
return "text/markdown"; Match.when("json", () => "application/json"),
case "html": Match.when("csv", () => "text/csv"),
case "htm": Match.when("docx", () => "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
return "text/html"; Match.orElse(() => "application/octet-stream"),
case "json": );
return "application/json";
case "csv":
return "text/csv";
case "docx":
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
default:
return "application/octet-stream";
}
} }
export function registerLibraryCommands(program: Command): void { export function registerLibraryCommands(program: Command): void {