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

@scalar/validation

v0.3.0

Published

A lightweight, schema-first validation library for Scalar

Readme

@scalar/validation

Small, schema-first helpers to check unknown data and coerce it into predictable shapes. Schemas are plain JavaScript objects (easy to serialize or log), and TypeScript can infer output types with Static.

Install

This package lives in the Scalar monorepo. In workspace consumers:

pnpm add @scalar/validation

Quick start

import { coerce, number, object, string, validate, type Static } from '@scalar/validation'

const userSchema = object({
  id: number(),
  name: string(),
})

type User = Static<typeof userSchema>

validate(userSchema, { id: 1, name: 'Ada' }) // true
validate(userSchema, { id: 1, name: 2 }) // false

// Best-effort shaping: invalid primitives fall back to defaults
coerce(userSchema, { id: 'x', name: 'Ada' }) // { id: 0, name: 'Ada' }

Concepts

validate(schema, value)

Returns true if value satisfies schema, otherwise false.

  • undefined schema — always fails.
  • number() — finite numbers only (NaN and Infinity fail).
  • object({ ... }) — value must be a plain object (see Objects and records). Each declared property is validated; extra properties are not rejected.
  • union([...]) — matches if any branch matches.

coerce(schema, value)

Returns a value typed as Static<typeof schema>. It is not strict validation: it normalizes toward the schema.

  • Valid primitives are returned as-is.
  • Invalid number0, invalid string'', invalid booleanfalse.
  • nullable() — result is always null.
  • notDefined() — result is always undefined.
  • literal(x) — result is always the schema’s literal x (the declared constant).
  • array / object / record — built recursively; wrong shapes become empty containers or defaulted fields.
  • union — picks a branch using a scoring heuristic (object shape and literal tags weigh more than “property exists”).
  • Optional third argument: internal WeakMap cache for cyclic graphs; you normally omit it.

Use validate when you need a yes/no. Use coerce when you want a stable default-filled structure (for example normalizing config or parsed JSON).

Schema builders

| Builder | Validates | Static type (idea) | |--------|-----------|----------------------| | number() | Finite number | number | | string() | string | string | | boolean() | boolean | boolean | | nullable() | null only | null | | notDefined() | undefined only | undefined | | any() | Anything | any | | literal(v) | Strict equality to v | typeof v | | array(item) | Array; every item matches item | Static<item>[] | | record(key, value) | Plain object; keys and values match | Record<…, …> | | object(props) | Plain object; each key in props | Object of static fields | | union([a, b, …]) | Matches any member | Union of branches | | optional(s) | undefined or matches s | Static<s> \| undefined; in object({ … }), property becomes key?: Static<s> | | lazy(() => schema) | Defers schema (recursion) | Inferred from inner schema | | evaluate(fn, schema) | Runs fn(value) then validates schema | Static<schema> |

import { lazy, object, string, union, literal } from '@scalar/validation'

// Discriminated-style union
const message = union([
  object({ type: literal('text'), body: string() }),
  object({ type: literal('ping') }),
])

evaluate — parse then validate

import { evaluate, number, string } from '@scalar/validation'

const trimmed = evaluate((v) => (typeof v === 'string' ? v.trim() : v), string())

validate(trimmed, '  hi  ') // true (after trim)

Objects and records

Plain object means: not null, and prototype is Object.prototype or null. Arrays, Date, and most class instances do not count as objects for object() / record() validation.

object checks only the keys you list. Missing keys are read as undefined, so pair them with optional(...) when a field may be absent.

record during validation checks every key against the key schema and every value against the value schema. During coercion, entries keep their string keys as-is and only values are coerced.

TypeScript: Static and Schema

  • Static<S> — inferred TypeScript type for data that matches schema S (depth-limited to avoid infinite recursion on very deep types).
  • Schema — union of all schema shapes; use when you store or pass schemas around.

Development

pnpm --filter @scalar/validation test
pnpm --filter @scalar/validation types:check
pnpm --filter @scalar/validation build

License

MIT