Motivation
Both `@gtbuchanan/cli` and `@gtbuchanan/test-utils` have now reinvented
partial valibot schemas for `package.json` (see #52 for the latest
round). The same pattern surfaces in other repos each time a tool needs
to read a manifest with runtime validation. No existing valibot package
fills this gap — `type-fest`'s `PackageJson` gives types but no
runtime schema, and `@pnpm/types` is TS-only.
A dedicated package removes the temptation to hand-roll a sloppy partial
schema every time.
Scope
Name: `valibot-pnpm`. Explicit about the ecosystem it targets (valibot
- pnpm-flavored package.json + `pnpm-workspace.yaml`), leaving room
for `valibot-npm`, `valibot-yarn` siblings if the design generalizes.
Covers:
- `package.json` — npm spec fields plus pnpm-specific extensions
(`pnpm.overrides`, `pnpm.patchedDependencies`, catalog specs,
`workspace:` protocol, `publishConfig.directory` / `linkDirectory`).
- `pnpm-workspace.yaml` — `packages`, `catalog`, `catalogs`,
`overrides`, `onlyBuiltDependencies`, etc.
Design
- Loose base, tighten at consumer. Root schema is `v.looseObject`
with every field optional. Consumers compose with `v.pick` +
`v.required` to get the narrow view they need. Avoids forcing a
one-size-fits-all strictness.
- Granular sub-schemas exported separately. `PublishConfigSchema`,
`RepositorySchema`, `BinSchema`, `ExportsSchema`, `EnginesSchema`,
`WorkspaceProtocolSchema`, `CatalogSchema`, etc. Matches how
consumers actually use these files — touch one field, not the whole
object.
- Inferred types re-exported. `type Manifest = v.InferOutput`
for each schema, so consumers get both runtime + type coverage from
one import.
- No value helpers in v1. Just schemas. Tooling (merge catalogs,
resolve workspace protocol, etc.) can go in sibling packages if
demand appears.
Open questions
- Combined package vs split (`valibot-pnpm-manifest` + `valibot-pnpm-workspace`)?
Leaning combined — they're small and usually used together.
- Whose fields win when npm and pnpm disagree (`publishConfig.bin`,
`publishConfig.scripts`)? Probably model both, let consumers pick.
Dogfooding path
Start by lifting this repo's two copies (`packages/cli/src/lib/manifest.ts`
and the new `PackageJson` in `packages/test-utils/src/fixture.ts`) into
a shared internal module first. Use that as the v0 spec; publish once
the API feels right across both consumers here.
When to build
Not yet. Revisit when a third project independently needs this — by
then the sub-schema boundaries and strictness model will be clearer.
In the meantime, this issue is the parking lot.
Motivation
Both `@gtbuchanan/cli` and `@gtbuchanan/test-utils` have now reinvented
partial valibot schemas for `package.json` (see #52 for the latest
round). The same pattern surfaces in other repos each time a tool needs
to read a manifest with runtime validation. No existing valibot package
fills this gap — `type-fest`'s `PackageJson` gives types but no
runtime schema, and `@pnpm/types` is TS-only.
A dedicated package removes the temptation to hand-roll a sloppy partial
schema every time.
Scope
Name: `valibot-pnpm`. Explicit about the ecosystem it targets (valibot
for `valibot-npm`, `valibot-yarn` siblings if the design generalizes.
Covers:
(`pnpm.overrides`, `pnpm.patchedDependencies`, catalog specs,
`workspace:` protocol, `publishConfig.directory` / `linkDirectory`).
`overrides`, `onlyBuiltDependencies`, etc.
Design
with every field optional. Consumers compose with `v.pick` +
`v.required` to get the narrow view they need. Avoids forcing a
one-size-fits-all strictness.
`RepositorySchema`, `BinSchema`, `ExportsSchema`, `EnginesSchema`,
`WorkspaceProtocolSchema`, `CatalogSchema`, etc. Matches how
consumers actually use these files — touch one field, not the whole
object.
for each schema, so consumers get both runtime + type coverage from
one import.
resolve workspace protocol, etc.) can go in sibling packages if
demand appears.
Open questions
Leaning combined — they're small and usually used together.
`publishConfig.scripts`)? Probably model both, let consumers pick.
Dogfooding path
Start by lifting this repo's two copies (`packages/cli/src/lib/manifest.ts`
and the new `PackageJson` in `packages/test-utils/src/fixture.ts`) into
a shared internal module first. Use that as the v0 spec; publish once
the API feels right across both consumers here.
When to build
Not yet. Revisit when a third project independently needs this — by
then the sub-schema boundaries and strictness model will be clearer.
In the meantime, this issue is the parking lot.