npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ppwcode/api-contracts

v1.1.0

Published

Collection of common reusable schemas for OpenAPI specs and TypeScript types

Readme

@ppwcode/api-contracts

Reusable Zod 4 schemas and inferred TypeScript types for canonical API values.

npm install @ppwcode/api-contracts

Zod 4 is a peer dependency. Install zod@^4 explicitly if your package manager does not install peers. Import contracts from their category; the package has no root entrypoint. Output supports browser-safe ES2022, ESM and CommonJS.

import { z } from "zod";
import { TrimmedStringSchema } from "@ppwcode/api-contracts/value/string";
import { DateOnlySchema } from "@ppwcode/api-contracts/value/time";
import {
  BelgianEnterpriseNumberSchema,
  type BelgianEnterpriseNumber,
} from "@ppwcode/api-contracts/identity/be";

const CompanySchema = z.object({
  name: TrimmedStringSchema,
  foundedOn: DateOnlySchema.optional(),
  enterpriseNumber: BelgianEnterpriseNumberSchema,
});
const company = CompanySchema.parse({
  name: "Example company",
  enterpriseNumber: "0123456749",
});
const number: BelgianEnterpriseNumber = company.enterpriseNumber;
const result = BelgianEnterpriseNumberSchema.safeParse("0123.456.749");
// result.success === false: formatting is never silently removed.

Contracts

| Category | Types | Scope | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | /value/string | CanonicalURI; CanonicalURIWithKnowledgeTime; CleanedString; EmailAddress; Language; RelativeURI; TelephoneNumber; TrimmedString | Canonical strings, URIs, email addresses, language codes, and telephone numbers | | /value/time | DateOnly; DateOnlyPeriod; DateTime; ISODateToSecond; Month; Quarter; Year | Calendar values and ISO timestamps | | /value/number | Decimal | Exact integer-based decimal representation | | /value/money | CurrencyCode; MonetaryValue; MonetaryValue2; MonetaryValueEUR2; ZeroMonetaryValueEUR2; NonNegativeMonetaryValue; NonNegativeMonetaryValueEUR2; NonPositiveMonetaryValue; NegativeMonetaryValue; NegativeMonetaryValueEUR2; PositiveMonetaryValue; PositiveMonetaryValueEUR2; PositiveMonetaryValueEUR4 | Currency codes and signed monetary values | | /value/location | Address; Country | Postal addresses and country codes | | /identity/generic | AccountId; Mode; UUID | Generic identifiers and execution modes | | /identity/person | Gender | Person attributes | | /identity/banking | Iban | Uppercase IBAN with country structure and MOD 97-10 checksum | | /identity/be | BelgianEnterpriseNumber; KboNumber; CbeNumber; CrnNumber; BelgianIban; BelgianSocialSecurityNumber; Niss; Insz; Inss; BelgianVatNumber; SigedisId; SigedisRegistrantId; SigedisRegistrantRegulationIdentification | Belgian identity and organization identifiers | | /resource/health | Health; Status | Service health and status | | /resource/lifecycle | Auditable; AuditablePersistent; Audited; CreatedInError; InsertAuditable; InsertAuditablePersistent; Persistent; Timestamped | Resource lifecycle, persistence, and audit metadata | | /resource/versioning | StructureVersion; StructureVersioned; HistoryVersion; History; HREFHistory; HREFHistorySearchable | Resource structure versions and history | | /resource/search | SearchTerm; SearchDocument; SearchDocument2; SearchDocumentBase; SearchDocumentContentBase2; SearchResultBase; SearchResultBase2; SearchResults; HREF; MixedSearchResults; Results | Search documents, results, and links | | /resource/relations | ToOneFromChi | Relative links to associated resources | | /http/parameters | Accept; ForceError; Page; PerPage; PersistenceId | HTTP request parameter values | | /http/headers | CommonResponseHeaders; Location | HTTP response headers | | /http/caching | CacheControlNoCache; CacheControlPrivateImmutable | HTTP cache directives | | /protocol/oauth2 | BearerAccessToken; WWWAuthenticate | OAuth2 resource-server values |

IbanSchema is available from @ppwcode/api-contracts/identity/banking. Its country lengths and BBAN patterns follow the supplied PPWCode.Util.Validation.IV.IBAN class (69 countries); this is a fixed compatibility table, not a live IBAN registry. The PPWCode.vNext documentation describes its country and MOD 97-10 checks. Unlike the C# identification class, this contract accepts only the canonical electronic form and does not normalize paper formatting. Country structures are included in generated JSON Schema; the checksum requires runtime validation. Iban and BelgianIban are distinct brands; parse a value with the desired schema to obtain that type.

import { IbanSchema } from "@ppwcode/api-contracts/identity/banking";

IbanSchema.parse("GB82WEST12345698765432");

No schema trims, changes case, removes separators, or otherwise transforms input. Canonical primitive domain values are branded. Parse untrusted values with the corresponding schema to obtain the branded type; this prevents accidental interchange of values such as dates, currencies, URLs, modes, and identifiers. Structural object schemas are intentionally not branded, so they remain easy to compose and extend. Branding is a TypeScript-only distinction and has no effect on the wire representation, JSON Schema, or OpenAPI output.

NissSchema/Niss and InszSchema/Insz alias the social security number. NISS means numéro d’identification de la sécurité sociale; INSZ means identificatienummer van de sociale zekerheid. BIS numbers are included, so neither birth date nor gender is inferred or validated. The non-standard spelling INSS is not exported. KboNumberSchema/KboNumber and CbeNumberSchema/CbeNumber alias the enterprise number: KBO is Kruispuntbank van Ondernemingen and CBE is Crossroads Bank for Enterprises. All aliases reference their canonical schema instance.

A valid checksum does not prove registry membership, VAT registration, identity, or bank-account existence. Treat NISS/INSZ as sensitive personal data: avoid raw values in logs, telemetry, URLs and validation-error reports; use synthetic test fixtures and restrict storage and access to what your application requires.

JSON Schema and OpenAPI

npm run build also generates a complete OpenAPI 3.1 example at dist/openapi-example.yaml. Open it in an OpenAPI viewer to explore a GET /example response composed from the canonical contracts, with reusable component schemas and their metadata. The spec is self-contained and included in the published package at @ppwcode/api-contracts/openapi-example.yaml; resolve it with import.meta.resolve() or require.resolve() to read the YAML file. Its generator is scripts/generate-openapi-example.mjs.

npm run build generates standalone YAML files in dist/schemas/, included in the published package. Each file contains JSON Schema Draft 2020-12 and is named after its canonical component ID: TrimmedString, TelephoneNumber, DateOnly, BelgianSocialSecurityNumber, BelgianEnterpriseNumber, BelgianVatNumber, BelgianIban, and Iban. Aliases share their canonical file.

Consumers can resolve a file with import.meta.resolve("@ppwcode/api-contracts/schemas/DateOnly.yaml") or require.resolve("@ppwcode/api-contracts/schemas/DateOnly.yaml") and read it with a YAML parser. OpenAPI 3.1/3.2 documents can reference the installed files directly (adjust the relative path to the location of your API document):

components:
  schemas:
    DateOnly:
      $ref: ./node_modules/@ppwcode/api-contracts/dist/schemas/DateOnly.yaml

The package also publishes the reusable OpenAPI component fragments migrated from the deprecated @ppwcode/openapi package under @ppwcode/api-contracts/components/.... These include shared parameters, headers, responses, request bodies, and OAuth2/JWT/JWK fragments. Root API documents and endpoint/path compositions are intentionally not part of this library. Component fragments are package artifacts; the Zod schemas and their generated /schemas/*.yaml files remain the canonical data contracts.

No consumer-side schema generation is needed. You can also generate JSON Schema programmatically:

import { z } from "zod";
import { BelgianEnterpriseNumberSchema } from "@ppwcode/api-contracts/identity/be";

const jsonSchema = z.toJSONSchema(BelgianEnterpriseNumberSchema, {
  target: "draft-2020-12",
});

Metadata includes stable component IDs, English titles, descriptions, examples, patterns and lengths, plus the standard date format where applicable. Checksum refinements require runtime Zod validation: JSON Schema and OpenAPI cannot express these calculations. Metadata is attached last; attach your own metadata last too when deriving a schema. Avoid assigning an existing component ID to a new schema.

Choose your own generator. For example, with zod-openapi installed separately:

import { createDocument } from "zod-openapi";
import { BelgianEnterpriseNumberSchema } from "@ppwcode/api-contracts/identity/be";

const document = createDocument({
  openapi: "3.2.0", // '3.1.0' is also tested.
  info: { title: "Company API", version: "1.0.0" },
  paths: {
    "/enterprise-number": {
      get: {
        responses: {
          "200": {
            description: "Enterprise number",
            content: {
              "application/json": { schema: BelgianEnterpriseNumberSchema },
            },
          },
        },
      },
    },
  },
});

There is no runtime dependency on an OpenAPI generator. Native JSON Schema and representative OpenAPI 3.1/3.2 documents are snapshot tested.

Development

Use Node 24 LTS and npm. npm ci installs the locked toolchain. The GitHub workflows read .nvmrc and select the latest available Node 24 release.

| Command | Purpose | | -------------------------- | ---------------------------------------------------------------- | | npm test | Watch unit and metadata tests | | npm run test:unit | Unit, property and metadata tests | | npm run test:types | Identifier and alias type assertions | | npm run test:coverage | Unit tests, coverage and JUnit report | | npm run build | ESM/CommonJS, declarations and standalone schema YAML files | | npm run test:integration | OpenAPI tests against dist (build first) | | npm run test:ci | All tests (build first) | | npm run verify:quality | Lint, strict types, unit coverage and type tests | | npm run verify:package | Build, integration, publint, Are the Types Wrong, dry-run pack | | npm run license:check | REUSE lint (install REUSE 6.2.0 first) | | npm run license:docker | License check using fsfe/reuse:6.2.0 | | npm run verify | All quality, package and license gates | | npm run release:pack | Verify matching RELEASE_TAG, all gates, then create an archive |

npm run ci:check-production-vulnerabilities audits production dependencies using the locked better-npm-audit tool. It also runs as part of npm run verify.

GitHub Actions runs independent quality, package, license and Dependency Audit jobs for PRs, main, releases and manual CI workflow runs. The Release workflow handles new v* tags and creates GitHub releases with the built-in workflow token, using the matching changelog entry as the description. It then calls the reusable Publish workflow, which validates the release tag, calls the reusable CI workflow, and hands the verified package build directly to the production deployment. Publication requires environment approval and uses npm trusted publishing. No repository release token or npm token is stored. A failed publication can be retried by running the Publish workflow manually and selecting the published release tag under Use workflow from. No branch build or manual CI verification run publishes.

Category paths, exported names, component IDs, brands and accepted wire values are public API. The package is organized beneath five top-level namespaces: value/*, identity/*, resource/*, http/*, and protocol/*.

Contributing

Follow the implementation workflow when adding or changing contracts, entrypoints, or package infrastructure.

Keep unreleased changes under ## Unreleased in CHANGELOG.md, then use npm version [major|minor|patch] to bump the version when preparing a release, choosing one of major, minor, or patch (for example, npm version patch). The version lifecycle hook automatically promotes ## Unreleased to the new ## X.Y.Z heading and validates that it contains a change description.

The command runs verify:quality before the bump, updates package.json and package-lock.json, updates and checks the changelog for the new version, and creates the version commit and tag. When preparing the version update for a PR, use npm version [major|minor|patch] --no-git-tag-version and include the updated version files in the PR.

After the version update and changelog are reviewed and merged, push the matching vX.Y.Z tag on the merged commit to trigger the release workflow. Publishing requires successful checks and production approval. Follow release setup for the complete release procedure.

Licensed under Apache License 2.0; see NOTICE.