Skip to content

feat(typed-config): new package combining cosmiconfig+toml+xdg+standard-schema#297

Open
stephansama wants to merge 1 commit into
mainfrom
stephansama/ste-40-create-typed-config-package
Open

feat(typed-config): new package combining cosmiconfig+toml+xdg+standard-schema#297
stephansama wants to merge 1 commit into
mainfrom
stephansama/ste-40-create-typed-config-package

Conversation

@stephansama

Copy link
Copy Markdown
Owner

Closes STE-40

New @stephansama/typed-config package. One createConfig({ name, schema, xdg?, defaults? }) call wraps cosmiconfig + smol-toml + xdg-app-paths and validates the result through any Standard-Schema-V1 validator (zod / valibot / arktype).

Search order

  1. Standard cosmiconfig discovery (.<name>rc{,.json,.yaml,.yml,.toml}, package.json#<name>).
  2. .config/.<name>rc.{json,yaml,yml,toml} under the project root.
  3. (When xdg: true) $XDG_CONFIG_HOME/<name>/config.{json,yaml,yml,toml} (fallback ~/.config/<name>/).

Explicit defaults merge underneath the loaded file before validation. TOML loader registered automatically via smol-toml.

Tests

5 cases in src/index.test.ts cover defaults, JSON loading, TOML loading, defaults+file merge, and validation-error throw path.

Acceptance criteria

  • createConfig(schema, { name }) loads + validates via cosmiconfig
  • TOML configs supported end-to-end (smol-toml loader)
  • XDG path checked when xdg: true
  • Returns fully-typed validated config
  • Exported types: CreateConfigOptions<T>, ConfigResult<T>

@vercel

vercel Bot commented May 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
packages Error Error May 18, 2026 3:36am

@changeset-bot

changeset-bot Bot commented May 18, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 298bf3f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@stephansama has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 53 minutes and 42 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9bbd38e4-a58a-44e4-a922-741635fc7244

📥 Commits

Reviewing files that changed from the base of the PR and between 9a84b42 and 298bf3f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • README.md
  • core/typed-config/README.md
  • core/typed-config/package.json
  • core/typed-config/src/index.test.ts
  • core/typed-config/src/index.ts
  • core/typed-config/tsconfig.json
  • core/typed-config/tsdown.config.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stephansama/ste-40-create-typed-config-package

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.

@codecov

codecov Bot commented May 18, 2026

Copy link
Copy Markdown

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces @stephansama/typed-config, a new configuration loader that integrates cosmiconfig, smol-toml, and xdg-app-paths with validation via Standard Schema V1. The feedback highlights a missing root-level TOML search path, potential issues with shallow merging of default values for nested schemas, and performance concerns regarding the inclusion of absolute XDG paths in the cosmiconfig search sequence.

Comment on lines +55 to +62
const base = [
...getDefaultSearchPlaces(name),
`.config/.${name}rc.json`,
`.config/.${name}rc.yaml`,
`.config/.${name}rc.yml`,
`.config/.${name}rc.toml`,
`.config/.${name}rc`,
];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The buildSearchPlaces function is missing .${name}rc.toml in the root search places. While it is included for the .config/ subdirectory, the PR description and README state that standard discovery should include .<name>rc.toml at the project root. Since cosmiconfig's getDefaultSearchPlaces does not include TOML by default, it should be explicitly added here to ensure consistency with the documentation.

Suggested change
const base = [
...getDefaultSearchPlaces(name),
`.config/.${name}rc.json`,
`.config/.${name}rc.yaml`,
`.config/.${name}rc.yml`,
`.config/.${name}rc.toml`,
`.config/.${name}rc`,
];
const base = [
...getDefaultSearchPlaces(name),
`.${name}rc.toml`,
`.config/.${name}rc.json`,
`.config/.${name}rc.yaml`,
`.config/.${name}rc.yml`,
`.config/.${name}rc.toml`,
`.config/.${name}rc`,
];

const found = await explorer.search();
const raw = found?.config as Partial<T> | undefined;

const merged: unknown = { ...defaults, ...raw };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The merge between defaults and the loaded config (raw) is a shallow merge. If the configuration schema contains nested objects, any values provided in the config file for a nested key will completely overwrite the corresponding nested object in defaults, rather than merging them. This might be unexpected for users providing complex default configurations. Consider using a deep merge approach if nested support is intended.

Comment on lines +64 to +71
const xdgDirectory = path.join(xdgAppPaths(name).config(), "config");
return [
...base,
`${xdgDirectory}.json`,
`${xdgDirectory}.yaml`,
`${xdgDirectory}.yml`,
`${xdgDirectory}.toml`,
];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Including absolute XDG paths in searchPlaces causes cosmiconfig to check these same absolute paths repeatedly at every level of the directory tree as it climbs upwards from the current working directory. This results in redundant disk I/O. A more efficient approach would be to handle XDG paths as a separate fallback step after the project-local search is completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant