Comparing version 1.2.0 to 1.3.0
{ | ||
"name": "pukka", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Typescript schema-first zod compatible hyper validation", | ||
@@ -5,0 +5,0 @@ "repository": { |
181
README.md
@@ -16,4 +16,9 @@ [![version(scoped)](https://img.shields.io/npm/v/pukka.svg)](https://www.npmjs.com/package/pukka) | ||
## Declare schema and validations | ||
## Install | ||
``` | ||
npm install pukka | ||
``` | ||
## Usage | ||
Define a schema as usual, and consolidate validations. | ||
@@ -37,2 +42,8 @@ | ||
}); | ||
const data = Register.parse({ password: "secret" }); | ||
const { success, data, issues, input } = Register.safeParse({ | ||
password: "secret", | ||
}); | ||
``` | ||
@@ -44,2 +55,87 @@ | ||
## API | ||
pukka has just a handful of APIs. | ||
Every schema has the following methods. | ||
```ts | ||
schema.optional() | ||
schema.nullable() | ||
schema.refine((ctx, data) => {...}) | ||
schema.refineAsync(async (ctx, data) => {...}) | ||
schema.parse(input, options) | ||
schema.parseAsync(input, options) | ||
schema.safeParse(input, options) | ||
schema.safeParseAsync(input, options) | ||
``` | ||
And the following are available on the context. | ||
```ts | ||
schema.refine((ctx, data) => { | ||
data.foo.bar[0] // access a field | ||
ctx.path // ["foo", "bar", 0] | ||
ctx.issue("major issue") // raise an issue | ||
ctx.pathFor(data.foo) // ["foo"] | ||
ctx.isDefined(data.foo) // data.foo != null | ||
ctx.get<T>("baz") // property from parse options: s.parse(input, { baz: any }) | ||
// and a few overloads for ctx.issue(...) | ||
ctx.issue(() => "major issue") // function (eg ParaglideJS - m.major_issue) | ||
ctx.issue(condition, "major issue") // raise issue only if condition is true | ||
ctx.issue("severe", "major issue") // issue with code & message | ||
ctx.issue("severe", "major issue", ["foo"]) // issue with code, message & path | ||
}) | ||
``` | ||
## Types | ||
Though it's very easy to [add types](./src/types.ts), the list of supported types is intentionally kept simple. | ||
```ts | ||
z.string() | ||
z.string().optional() // string | undefined | ||
z.string().nullable() // string | null | ||
z.number() | ||
z.boolean() | ||
z.enum(["ordered", "shipped"]) | ||
z.enum(["ordered", "shipped"] as const) // as needed | ||
z.file() | ||
z.literal(...) | ||
z.literal(true) | ||
z.literal(1) | ||
z.literal("type") | ||
z.record(z.number()) // { jan: 1, feb: 2 } | ||
z.array(z.string()) | ||
z.array(z.string(), { coerce: true }) // parse("a") => [ "a" ] | ||
z.object({ | ||
name: z.string(), | ||
age: z.number(), | ||
interests: z.array(z.string()) | ||
}) | ||
z.union([ | ||
z.object({ | ||
success: z.literal(true), | ||
data: z.object({ | ||
name: z.string(), | ||
}), | ||
}), | ||
z.object({ | ||
success: z.literal(false), | ||
issues: z.array( | ||
z.object({ | ||
code: z.string(), | ||
message: z.string(), | ||
path: z.array(z.number()), | ||
}), | ||
), | ||
}), | ||
]); | ||
``` | ||
## Parse | ||
@@ -280,51 +376,2 @@ | ||
## Types | ||
Though it's very easy to [add types](./src/types.ts), the list of supported types is intentionally kept simple. | ||
pukka is meant to validate data that is posted from a form or an api. | ||
So no recursive types for now. | ||
```ts | ||
z.string() | ||
z.string().optional() // string | undefined | ||
z.string().nullable() // string | null | ||
z.number() | ||
z.boolean() | ||
z.enum(["ordered", "shipped"]) | ||
z.enum(["ordered", "shipped"] as const) // as needed | ||
z.file() | ||
z.literal(...) | ||
z.literal(true) | ||
z.literal(1) | ||
z.literal("type") | ||
z.record(z.number()) // { jan: 1, feb: 2 } | ||
z.array(z.string()) | ||
z.array(z.string(), { coerce: true }) // parse("a") => [ "a" ] | ||
z.object({ | ||
name: z.string(), | ||
age: z.number(), | ||
interests: z.array(z.string()) | ||
}) | ||
z.union([ | ||
z.object({ | ||
success: z.literal(true), | ||
data: z.object({ | ||
name: z.string(), | ||
}), | ||
}), | ||
z.object({ | ||
success: z.literal(false), | ||
issues: z.array( | ||
z.object({ | ||
code: z.string(), | ||
message: z.string(), | ||
path: z.array(z.number()), | ||
}), | ||
), | ||
}), | ||
]); | ||
``` | ||
## Type coercion and sanitization | ||
@@ -361,34 +408,2 @@ | ||
## API | ||
pukka strives to be minimal and has just a handful of APIs. | ||
Every schema has the following methods. | ||
```ts | ||
schema.optional() | ||
schema.nullable() | ||
schema.parse(input, options) | ||
schema.parseAsync(input, options) | ||
schema.safeParse(input, options) | ||
schema.safeParseAsync(input, options) | ||
schema.refine((ctx, data) => {...}) | ||
schema.refineAsync((ctx, data) => {...}) | ||
``` | ||
And the following are available on the context. | ||
```ts | ||
schema.refine((ctx, data) => { | ||
data.foo.bar // access a prop | ||
ctx.path // ["foo", "bar"] | ||
ctx.isDefined(data.foo) // data.foo != null | ||
ctx.issue("major issue") // raise an issue | ||
ctx.issue("severe", "major issue") // issue with code | ||
ctx.issue("severe", "major issue", ["foo"]) // issue with code & path | ||
ctx.pathFor(data.foo) // ["foo"] | ||
ctx.get<T>("prop") // get a runtime property | ||
}) | ||
``` | ||
## Helpers | ||
@@ -485,3 +500,3 @@ | ||
### Register and use the new type and extension. | ||
### Register and use the new type and extension | ||
@@ -488,0 +503,0 @@ ```ts |
120339
585