@papack/schema
v1.3.1
Published
Simple Schemas are with all-required or all-optional and values never allow null/undefined
Readme
@papack/schema
Opinionated, fully synchronous TypeScript schemas for developers who want strict, minimal, predictable data structures.
No nulls. No undefined. No async. No partial optionality.
Core Rules
- Sync only — no Promises anywhere.
- First error wins —
validate()throws immediately. - Objects are all-required or all-optional — never mixed.
- No null/undefined —
- values:
""or0 - lists:
[]
- values:
- Only
validate()— noparse, nosafeParse. - Strong typing —
Infer<T>extracts exact static types. - Describe — inspect schema for UI forms, etc.
- Checks — curried, functional; includes
char(n),isPassword,isIban, etc. - Union checks — support primitive unions, never object unions.
Installation
npm install @papack/schemaConcept
With the three primitives — object, list, value — you can express any structure.
Strict, lightweight, zero magic.
Examples
Basic schema
import { object, value, isString } from "@papack/schema";
const UserSchema = object({
name: value(isString),
});
UserSchema.validate({ name: "Max" });Complete example
import {
value,
object,
partial,
pick,
omit,
Infer,
isUnionList,
isPassword,
isString,
extend,
isBoolean,
} from "@papack/schema";
const UserSchema = object({
name: value(isString)
pw: value(
isPassword({
minLength: 8,
minNumbers: 1,
minSpecialChars: 1,
})
),
gender: value(isUnionList(["w", "m"], { allowEmpty: true })),
});
// Derived schemas
const a = pick(UserSchema, ["name"]);
const b = omit(UserSchema, ["name"]);
const c = partial(UserSchema);
// Extended schema
const d = extend(UserSchema, {
locked: value(isBoolean),
});
// Final schema
const e = omit(d, ["name"]);
type User = Infer<typeof e>;
const u: User = {
gender: ["m", "m"],
locked: false,
pw: "asdfias2df!sadfed",
};
d.validate(u);Using describe()
const info = UserSchema.describe();
// Structural metadata for:
// - UI form builders
// - tools, automation, codegenErrors
Errors are short, stable, and i18n-ready. Examples:
"TOO_SMALL""NOT_STRING""INVALID_UNION"
validate() throws always on the first error.
Design Intent
- Minimal surface, predictable behavior.
- No hidden transformations.
- No optional-field chaos.
