blobatar-cli — the terminal surface (CLI-only subset of #4) - #5
blobatar-cli — the terminal surface (CLI-only subset of #4)#5guillermolg00 wants to merge 5 commits into
Conversation
One private workspace package turns the six-param string vocabulary (size, background, hue, tone, expression, normalize) into BlobatarOptions with a single set of validation rules and error messages, so the URL service and the CLI cannot drift apart. Glossary gains the one-line exception: render-core is a private support package, never published.
A command-line tool publishing as blobatar-cli with the bin blobatar: SVG to stdout, PNG to files or pipes (never a TTY), and batch generation from stdin with deterministic filenames that abort on collision before anything is written. Flags mirror the /v1 params through render-core, so validation and error messages are identical across both surfaces. The source is plain-Node portable (npx is the audience; a documented exception to the repo's Bun-first rule) and the build inlines the private render-core, leaving exactly two runtime deps: blobatar and @resvg/resvg-js. The whole flag/output/batch matrix runs in-process through an injected process seam under bun test; a smoke script spawns the built bin under node, mirroring the library package's own.
A plain-object lookup answers truthily to __proto__ and constructor, letting a crafted URL bypass the roster and crash downstream — a 400 turned into a 500. Own-property check plus regression tests. Also swaps the CLI batch dedupe from O(n²) includes to a Set.
|
@guillermolg00 is attempting to deploy a commit to the alain00's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
Adds a new terminal-only surface for blobatar by introducing a CLI package plus a small private “render-core” package to keep parameter parsing/validation consistent across string-based surfaces.
Changes:
- Introduces
packages/render-core(private) withparseParams()+ a shared param allowlist and canonicalization behavior. - Adds
packages/cli(blobatar-cli, binblobatar) with in-process unit tests, a Bun build step that inlinesrender-core, and a Node-spawned smoke test. - Updates repo context docs and lockfile to include the new workspace members and
@resvg/resvg-js.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/render-core/tsconfig.json | Adds member TS config (Bun types) for render-core. |
| packages/render-core/package.json | Declares private support package exported from TS source for bundler consumers. |
| packages/render-core/src/index.ts | Implements shared param parsing + canonicalization (parseParams). |
| packages/render-core/test/params.test.ts | Verifies the param table behavior and error messages. |
| packages/cli/tsconfig.json | Adds member TS config (Bun types + JSON module support). |
| packages/cli/package.json | Defines blobatar-cli packaging, build, smoke, and check scripts. |
| packages/cli/README.md | Documents CLI usage, flags, batch behavior, and determinism guarantees. |
| packages/cli/src/cli.ts | Implements pure CLI logic behind injected IO/deps seam (unit-testable). |
| packages/cli/src/main.ts | Wires real Node process + resvg + blobatar into the pure CLI runner. |
| packages/cli/scripts/build.ts | Bun build script producing dist/blobatar.mjs with Node shebang. |
| packages/cli/scripts/smoke.mjs | Node-spawned smoke test validating real SVG/PNG outputs and exit behavior. |
| packages/cli/test/cli.test.ts | In-process test matrix for flags/output/batch behavior. |
| CONTEXT.md | Documents render-core as the deliberate exception to “packages are publishable”. |
| bun.lock | Adds workspace entries and locks @resvg/resvg-js + its optional prebuilds. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3fbff517ad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… packability
tone=100 mapped to exactly 1, which the library's half-open bucketing
wraps to the FIRST swatch — verified: same bytes as tone=0. Now clamps
to the library's own 0.999999. Batch -d keeps the dir verbatim (trimming
made "/" into mkdir("") and a drive root relative) and the collision
preflight groups filenames case-insensitively, since default macOS and
Windows volumes merge casings — exactly when --no-normalize preserves
them. "--" ends option parsing so hyphen-led names render. render-core
gets a version: packing the CLI resolves every workspace range and an
unversioned member failed bun pm pack.
blobatar as a real semver range instead of workspace:* — bun still links the workspace member, while a tarball built by npm pack (which does not rewrite the workspace protocol) stays installable. stdout EPIPE exits 0: piping into head is the reader being done, not an error.
What this is
The CLI slice of #4, standing on its own:
packages/cli(publishes asblobatar-cli, binblobatar) plus the privatepackages/render-coreparam table. No service, nothing touchingapps/— zero overlap withapps/site/worker.Opened separately so the two contributions can be judged independently: if you take #4, close this one; if you'd rather keep your worker as the only URL surface, this PR has the piece that doesn't compete with it.
The CLI
--size,--background,--hue,--tone,--expression,--no-normalize) through render-core — one validation table, one set of error messages.-o, or pipe +--format png); with-othe extension decides the format and a contradicting--formaterrors.[^A-Za-z0-9._-]→_, capped at 200 chars); every filename is precomputed and a collision aborts the whole batch listing the conflicting names — nothing partially written. Exact duplicate lines are deduped.#!/usr/bin/env node, Node ≥ 18) — a deliberate, documented exception to the repo's Bun-first rule, because npx is where the non-JS-project audience lives.bunxworks too.blobatar+@resvg/resvg-js(napi prebuilds, no postinstall).render-core
Private (
private: true, never published), bundled into the CLI's dist at build time. Contains onlyparseParams(strings →BlobatarOptions) and the expression string→value map — no raster, no I/O.CONTEXT.mdgains the one-line glossary exception for it. The param table currently mirrors the roster this branch was written against (happy|sad|mad|idle); extending to the 9 new expressions is a two-line change if this lands. The expression lookup is guarded withObject.hasOwn— a plain-object roster answers truthily to__proto__/constructor(details in the #4 thread; your worker'soneOfhas the same exposure viain).Testing
smoke.mjs.checkscripts, sobun --filter '*' checkcovers both like every other member. Full workspace on this branch: 222 pass, 0 fail.Open questions
blobatar-clithe name you want? The npm name is free, and the@blobatarscope is unclaimed if you'd rather have an org.release.ymlvalidates tags against the library only. Happy to extend it for the CLI once the name is confirmed — your tag convention, your call.