Skip to content

Make formatter a required option for config bucket#4

Merged
k0d13 merged 3 commits intomainfrom
kodie/require-explicit-formatter
Mar 30, 2026
Merged

Make formatter a required option for config bucket#4
k0d13 merged 3 commits intomainfrom
kodie/require-explicit-formatter

Conversation

@k0d13
Copy link
Copy Markdown
Owner

@k0d13 k0d13 commented Mar 30, 2026

  • Make formatter field of bucket config required
  • Remove support for non js/ts config files

Summary by CodeRabbit

  • New Features

    • Formatter is now a required configuration option for all translation buckets.
  • Chores

    • Configuration discovery now only accepts JavaScript/TypeScript config formats.
    • Legacy JSON/YAML config support removed.
    • Example projects updated to use the PO message formatter (dev tooling added).

@github-actions github-actions bot added dependencies Updates or changes related to project dependencies examples Updates or additions to example apps package: config Related to @saykit/config and the CLI labels Mar 30, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 30, 2026

🦋 Changeset detected

Latest commit: 615afcf

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@saykit/config Patch
@saykit/format-po Patch
saykit Patch
@saykit/react Patch
@saykit/carbon Patch
@saykit/babel-plugin Patch
unplugin-saykit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c5651000-fa30-4d32-9fde-49cacfa04034

📥 Commits

Reviewing files that changed from the base of the PR and between 9cb028e and 615afcf.

📒 Files selected for processing (1)
  • examples/carbon-tsdown/saykit.config.ts
✅ Files skipped from review due to trivial changes (1)
  • examples/carbon-tsdown/saykit.config.ts

Walkthrough

Formatters are now required in the @saykit/config configuration (no automatic fallback). JSON/YAML config loaders and many filename candidates were removed; config discovery and loader resolution now fail on unsupported extensions. Examples were updated to use an explicit PO formatter and TypeScript configs; minor path/extension handling was adjusted.

Changes

Cohort / File(s) Summary
Changeset
​.changeset/plain-oranges-wonder.md
Adds a patch changeset declaring formatter must be a required option for @saykit/config.
Example Packages
examples/carbon-tsdown/package.json, examples/nextjs-babel/package.json
Added devDependency @saykit/format-po (workspace:^).
Example Configs
examples/carbon-tsdown/saykit.config.json, examples/carbon-tsdown/saykit.config.ts, examples/nextjs-babel/saykit.config.ts
Replaced JSON config with TypeScript for carbon-tsdown; added createFormatter() usage in buckets to explicitly set PO formatter. Removed old JSON config file.
Package manifest
packages/config/package.json
Removed neverthrow dependency.
Output path / extension handling
packages/config/src/features/compile.ts, packages/config/src/features/extract.ts
writeTranslationsToDisk now passes '.json' to expandOutputPath; expandOutputPath now strips the leading dot from the {extension} placeholder before substitution.
Config discovery
packages/config/src/features/loader/explorer.ts
Reduced candidate filenames — removed many dotfile and package.json fallbacks; now targets ${name}.config code-based variants.
Loaders removed
packages/config/src/features/loader/loaders.ts
Removed json, yaml, and detect loaders and their exports; default loader map no longer includes .json, .yaml, .yml, or the '' fallback.
Loader resolution
packages/config/src/features/loader/resolve.ts
When loader for an extension is missing, resolution sets loader to null and now throws Unsupported config file type "${ext}" for "${name}" instead of using a fallback.
Schema & formatter handling
packages/config/src/shapes.ts
Formatter.extension no longer strips the leading dot; Bucket.formatter changed from optional with automatic runtime import/validation to a required Formatter value. Simplified Configuration refine message.
Build config
packages/config/tsdown.config.ts
Removed onSuccess hook that generated and wrote the JSON Schema to disk.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through configs, tidy and neat,

No hidden fallbacks under my feet.
PO flags raised, extensions held tight,
TypeScript leads on a clear, bright night.
Hooray for clarity — a rabbit’s delight! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: making the formatter a required option for config buckets, which is reflected throughout the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch kodie/require-explicit-formatter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/config/src/shapes.ts (1)

25-36: ⚠️ Potential issue | 🟠 Major

Reconsider version bump strategy for this breaking change.

The changeset specifies patch, but making formatter required is a breaking change. Previously, formatter was optional with automatic fallback to @saykit/format-po; users who didn't explicitly configure a formatter now encounter validation errors. For a 0.0.0 package, this warrants a minor version bump under pre-release semantic versioning conventions (or major for stricter interpretation). Whilst patch versions are technically permitted pre-1.0, they conventionally signal backward compatibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/config/src/shapes.ts` around lines 25 - 36, The schema change to
make formatter required in the Bucket zod schema (symbol: Bucket, field:
formatter, type: Formatter) is a breaking change for consumers who relied on the
previous optional fallback to `@saykit/format-po`; either revert the schema to
keep formatter optional (restore z.optional() or provide a default/fallback in
the transform) or update the release metadata to a non-patch bump (e.g., bump to
minor/major in the changeset) to reflect the breaking change; locate the Bucket
definition and adjust the formatter property or the changeset accordingly.
🧹 Nitpick comments (1)
packages/config/src/features/loader/resolve.ts (1)

11-12: Improve unsupported-type error clarity for extension-less files

Nice fail-fast check. Small tweak: at Line 12, when ext === '', the message renders as "", which is a bit cryptic. Consider mapping that case to "<no extension>" and including supported extensions to make fixes quicker.

💡 Suggested patch
   const ext = extname(file.id).toLowerCase();
   const loader = ext in loaders ? loaders[ext as keyof typeof loaders] : null;
-  if (!loader) throw new Error(`Unsupported config file type "${ext}" for "${name}"`);
+  if (!loader) {
+    const fileType = ext || '<no extension>';
+    const supported = Object.keys(loaders).join(', ');
+    throw new Error(
+      `Unsupported config file type "${fileType}" for "${name}". Supported types: ${supported}`
+    );
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/config/src/features/loader/resolve.ts` around lines 11 - 12, The
error thrown when no loader is found (the block using loaders, loader, ext and
name) should map an empty ext to a friendly "<no extension>" label and append
the list of supported extensions to the message; update the thrown Error in the
check that uses ext in loaders ? loaders[ext as keyof typeof loaders] : null to
build a displayExt variable like ext || "<no extension>" and include
Object.keys(loaders) (or a joined string of supported extensions) in the Error
text so it reads something like Unsupported config file type "<displayExt>" for
"<name>" — supported: [..].
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/config/src/shapes.ts`:
- Around line 25-36: The schema change to make formatter required in the Bucket
zod schema (symbol: Bucket, field: formatter, type: Formatter) is a breaking
change for consumers who relied on the previous optional fallback to
`@saykit/format-po`; either revert the schema to keep formatter optional (restore
z.optional() or provide a default/fallback in the transform) or update the
release metadata to a non-patch bump (e.g., bump to minor/major in the
changeset) to reflect the breaking change; locate the Bucket definition and
adjust the formatter property or the changeset accordingly.

---

Nitpick comments:
In `@packages/config/src/features/loader/resolve.ts`:
- Around line 11-12: The error thrown when no loader is found (the block using
loaders, loader, ext and name) should map an empty ext to a friendly "<no
extension>" label and append the list of supported extensions to the message;
update the thrown Error in the check that uses ext in loaders ? loaders[ext as
keyof typeof loaders] : null to build a displayExt variable like ext || "<no
extension>" and include Object.keys(loaders) (or a joined string of supported
extensions) in the Error text so it reads something like Unsupported config file
type "<displayExt>" for "<name>" — supported: [..].

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d0c87684-3dcb-4c92-95eb-4e2e10d9bf4e

📥 Commits

Reviewing files that changed from the base of the PR and between 0a4b8aa and 9cb028e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .changeset/plain-oranges-wonder.md
  • examples/carbon-tsdown/package.json
  • examples/carbon-tsdown/saykit.config.json
  • examples/carbon-tsdown/saykit.config.ts
  • examples/nextjs-babel/package.json
  • examples/nextjs-babel/saykit.config.ts
  • packages/config/package.json
  • packages/config/src/features/compile.ts
  • packages/config/src/features/extract.ts
  • packages/config/src/features/loader/explorer.ts
  • packages/config/src/features/loader/loaders.ts
  • packages/config/src/features/loader/resolve.ts
  • packages/config/src/shapes.ts
  • packages/config/tsdown.config.ts
💤 Files with no reviewable changes (5)
  • examples/carbon-tsdown/saykit.config.json
  • packages/config/package.json
  • packages/config/src/features/loader/explorer.ts
  • packages/config/tsdown.config.ts
  • packages/config/src/features/loader/loaders.ts

@k0d13 k0d13 merged commit 7b75d7c into main Mar 30, 2026
8 checks passed
@k0d13 k0d13 deleted the kodie/require-explicit-formatter branch March 30, 2026 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Updates or changes related to project dependencies examples Updates or additions to example apps package: config Related to @saykit/config and the CLI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant