Skip to content

Proposal: new package 'valibot-pnpm' for package.json and pnpm-workspace.yaml schemas #54

Description

@gtbuchanan

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions