Skip to content

Commit 45a1f98

Browse files
committed
docs: update v5 docs
1 parent 513c682 commit 45a1f98

File tree

1 file changed

+66
-105
lines changed

1 file changed

+66
-105
lines changed

README.md

Lines changed: 66 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Tiny Schema Validator
22

3-
JSON schema validator with great type inference.
3+
JSON schema validator with excellent type inference for JavaScript and TypeScript.
44

55
[![GitHub license](https://img.shields.io/github/license/5alidz/tiny-schema-validator)](https://github.com/5alidz/tiny-schema-validator/blob/master/LICENSE) ![Minzipped size](https://img.shields.io/bundlephobia/minzip/tiny-schema-validator.svg)
66

@@ -19,47 +19,72 @@ yarn add tiny-schema-validator
1919
```js
2020
import { createSchema, _ } from 'tiny-schema-validator';
2121

22-
export const Person = createSchema({
23-
name: _.string({
24-
maxLength: [100, 'too-long'],
25-
minLength: [2, 'too-short'],
22+
export const User = createSchema({
23+
metadata: _.record({
24+
date_created: _.number(),
25+
id: _.string(),
2626
}),
27-
age: _.number({
28-
max: [150, 'too-old'],
29-
min: [13, 'too-young'],
27+
profile: _.record({
28+
name: _.string({
29+
maxLength: [100, 'too-long'],
30+
minLength: [2, 'too-short'],
31+
}),
32+
age: _.number({
33+
max: [150, 'too-old'],
34+
min: [13, 'too-young'],
35+
}),
36+
email: _.string({
37+
pattern: [/^[^@]+@[^@]+\.[^@]+$/, 'invalid-email'],
38+
}),
3039
}),
31-
email: _.string({
32-
pattern: [/^[^@]+@[^@]+\.[^@]+$/, 'invalid-email'],
33-
});
40+
payment_status: _.union(
41+
_.constant('pending'),
42+
_.constant('failed'),
43+
_.constant('success'),
44+
_.constant('canceled')
45+
),
3446
});
3547
```
3648

3749
and in TypeScript, everything is the same, but to get the data type inferred from the schema, you can do this:
3850

3951
```ts
4052
/*
41-
PersonType {
42-
name: string;
43-
age: number;
44-
email: string;
53+
UserType {
54+
metadata: {
55+
date_created: number;
56+
id: string;
57+
};
58+
profile: {
59+
name: string;
60+
age: number;
61+
email: string;
62+
};
63+
payment_status: 'pending' | 'failed' | 'success' | 'canceled';
4564
}
4665
*/
47-
export type PersonType = ReturnType<typeof Person.produce>;
66+
export type UserType = ReturnType<typeof User.produce>;
4867
```
4968

50-
## Schema
69+
### Using the schema
5170

5271
When you create a schema, you will get a nice API to handle multiple use-cases in the client and the server.
5372

5473
- `is(data: any): boolean` check if the data is valid (eager evaluation)
5574
- `validate(data: any): Errors` errors returned has the same shape as the schema you defined (does not throw)
5675
- `produce(data: any): data` throws an error when the data is invalid. otherwise, it returns data
5776
- `embed(config?: { optional: boolean })` embeds the schema in other schemas
58-
- `traverse(visitor, data?, eager?)` (advanced) see usage below.
77+
- `source` the schema itself in a parsable format
5978

60-
Continuing from the previous example:
79+
example usage:
6180

6281
```js
82+
const Person = createSchema({
83+
name: _.string(),
84+
age: _.number(),
85+
email: _.string(),
86+
});
87+
6388
const john = { name: 'john', age: 42, email: 'john@gmail.com' };
6489
Person.is({}); // false
6590
Person.is(john); // true
@@ -84,18 +109,37 @@ const GroupOfPeople = createSchema({
84109

85110
## Validators
86111

112+
All validators are required by default.
87113
All validators are accessible with the `_` (underscore) namespace; The reason for using `_` instead of a good name like `validators` is developer experience, and you can alias it to whatever you want.
88114

89115
```js
90116
import { _ as validators } from 'tiny-schema-validator';
91117

92-
validators.string(); // creates a string validator
118+
// NOTE: when you call a validator you just create an object with { type: '<type of validator>', ...options }
119+
// this is just a shorthand for that.
120+
121+
// example of all validators and corresponding Typescript types
122+
validators.string(); // string
123+
validators.number(); // number
124+
validators.boolean(); // boolean
125+
validators.constant(42); // 42
126+
validators.union(validators.constant(1), validators.constant(2), validators.constant(3)); // 1 | 2 | 3
127+
validators.list([validators.number(), validators.number()]); // [number, number]
128+
validators.listof(validators.string()); // string[]
129+
validators.recordof(validators.string()); // Record<string, string>
130+
validators.record({
131+
timestamp: validators.number(),
132+
id: validators.string(),
133+
}); // { timestamp: number; id: string; }
93134
```
94135

95136
Check out the full validators API below:
96137

97138
| validator | signature | props |
98139
| :-------- | ------------------------------- | :------------------------------------------------------------- |
140+
| | | |
141+
| constant | `constant(value)` | value: `string \| number \| boolean` |
142+
| | | |
99143
| string | `string(options?)` | options (optional): Object |
100144
| | | - `optional : boolean` defaults to false |
101145
| | | - `maxLength: [length: number, error: string]` |
@@ -111,6 +155,8 @@ Check out the full validators API below:
111155
| boolean | `boolean(options?)` | options(optional): Object |
112156
| | | - `optional: boolean` default to false |
113157
| | | |
158+
| union | `union(...validators)` | validators: Array of validators as paramaters |
159+
| | | |
114160
| list | `list(validators[], options?)` | validators: Array of validators |
115161
| | | options(optional): Object |
116162
| | | - `optional: boolean` default to false |
@@ -154,91 +200,6 @@ const Person = createSchema({
154200
});
155201
```
156202

157-
## Advanced usage
158-
159-
In addition to validating data, you can also reuse your schema in other areas, like creating forms UI.
160-
`traverse` function come-in handy to help you achieve that.
161-
162-
### Example
163-
164-
In this example, we will transform a schema to create meta-data to create form UI elements.
165-
166-
```js
167-
const User = createSchema({
168-
id: _.string(),
169-
created: _.number(),
170-
updated: _.number(),
171-
profile: _.record({ username: _.string(), email: _.string(), age: _.number() }),
172-
});
173-
174-
const form_ui = User.traverse({
175-
number({ path, key }) {
176-
if (path.includes('profile')) return { type: 'number', label: key };
177-
return null; // otherwise ignore
178-
},
179-
string({ path, key }) {
180-
if (path.includes('profile')) return { type: 'text', label: key };
181-
return null; // otherwise ignore
182-
},
183-
// this is required to get the type of "profile" correct
184-
record: () => null,
185-
});
186-
187-
console.log(form_ui); /*
188-
{
189-
profile: {
190-
username: { type: 'text', label: 'username' },
191-
email: { type: 'text', label: 'email' },
192-
age: { type: 'number', label: 'age' }
193-
}
194-
}
195-
*/
196-
```
197-
198-
### How to traverse
199-
200-
there are a few considerations when defining `visitor` object:
201-
202-
- In `string | number | boolean` visitors, returning `null` signals to ignore this node.
203-
- In `record | recordof | list | listof` visitors, returning `null` signals to visit its children.
204-
- To skip over `record | recordof | list | listof` nodes, return `{}` (empty object).
205-
206-
Continuing from the previous `User` Example
207-
208-
```js
209-
/*
210-
Say We need this structure:
211-
{
212-
profile: {
213-
type: 'container',
214-
children: [
215-
{ type: 'text', label: 'username' },
216-
{ type: 'text', label: 'email' },
217-
{ type: 'number', label: 'age' }
218-
]
219-
}
220-
}
221-
*/
222-
const customTraverse = (key, validator) => {
223-
const type = validator.type;
224-
225-
if (type == 'string') return { type: key == 'email' ? key : 'text', label: key };
226-
if (type == 'number') return { type: 'number', label: key };
227-
if (type == 'record')
228-
return {
229-
type: 'container',
230-
children: Object.entries(validator.shape).map(entry => customTraverse(...entry)),
231-
};
232-
return null;
233-
};
234-
235-
const form_ui = User.traverse({
236-
record({ path, key, validator }) {
237-
return customTraverse(key, validator);
238-
},
239-
});
240-
```
241-
242203
## Caveats
243204

244205
- When using the `recordof | listof | list` validators, the optional property of the validator is ignored, example:

0 commit comments

Comments
 (0)