@@ -53,12 +53,12 @@ export const Person = createSchema<IPerson>({
5353
5454## Schema
5555
56- When you create a schema you will get a nice API to handle multiple use-cases in the client and the server.
56+ When you create a schema, you will get a nice API to handle multiple use-cases in the client and the server.
5757
58- - ` is(data: any): boolean ` check wether data is valid
58+ - ` is(data: any): boolean ` check if the data is valid
5959- ` validate(data: any): Errors ` errors returned has the same shape as the schema you defined (does not throw)
60- - ` produce(data: any): data ` throws an error when data has errors otherwise returns data
61- - ` embed(config?: { optiona : boolean }) ` embeds the schema in other schemas
60+ - ` produce(data: any): data ` throws an error when the data is invalid. otherwise, it returns data
61+ - ` embed(config?: { optional : boolean }) ` embeds the schema in other schemas
6262- ` traverse(visitor, data?, eager?) ` (advanced) see usage below.
6363
6464Continuing from the previous example:
@@ -70,7 +70,7 @@ Person.is({ name: 'john', age: 42, email: '
[email protected] ' }); // true
7070Person .validate ({}); // { name: 'invalid-type', age: 'invalid-type', email: 'invalid-type' }
7171Person .
validate ({ name
: ' john' , age
: 42 , email
: ' [email protected] ' });
// null7272
73- Person .produce (undefined ); // throws error with the same shape as the schema
73+ Person .produce (undefined ); // throws an error with the same shape as the schema
7474
7575// embedding the person schema
7676const GroupOfPeople = createSchema ({
@@ -125,14 +125,40 @@ Check out the full validators API below:
125125| | | options(optional): Object |
126126| | | - ` optional ` boolean default to false |
127127
128+ ### Custom validators
129+
130+ You can use validators from ` _ ` as building blocks for your custom validator:
131+
132+ ``` js
133+ const alphaNumeric = validatorOpts =>
134+ _ .string ({
135+ pattern: [/ ^ [a-zA-Z0-9 ] * $ / , ' only-letters-and-number' ],
136+ ... validatorOpts,
137+ });
138+
139+ const email = validatorOpts =>
140+ _ .string ({
141+ pattern: [/ ^ [^ @] + @[^ @] + \. [^ @] + $ / , ' invalid-email' ],
142+ ... validatorOpts,
143+ });
144+
145+ const Person = createSchema ({
146+ // ...
147+ username: alphaNumeric ({ maxLength: [20 , ' username-too-long' ] }),
148+ email: email (),
149+ alt_email: email ({ optional: true }),
150+ // ...
151+ });
152+ ```
153+
128154## Advanced usage
129155
130- In addition to validating data, you can also reuse your schema in other areas, like creating forms and TypeScript types.
156+ In addition to validating data, you can also reuse your schema in other areas, like creating forms UI for example,
131157` traverse ` function come-in handy to help you achieve that.
132158
133159### Example
134160
135- In this example we will transform a schema to create meta-data to be used to create form UI elements.
161+ In this example, we will transform a schema to create meta-data to be used to create form UI elements.
136162
137163``` js
138164const User = createSchema ({
@@ -166,14 +192,14 @@ console.log(form_ui); /*
166192
167193### How to traverse
168194
169- The return type of your visitor is important, and there is some few considerations:
195+ The return type of your visitor is important, and there are a few considerations:
170196
171- Returning ` null ` from a visitor signals to ignore this node from the end result, with the exception of :
197+ Returning ` null ` from visitor signals to ignore this node from the result, with the exception:
172198` record | recordof | list | listof ` , returning ` null ` signals to continue down recursively.
173199
174- This means, to return something from ` record ` visitor you will need to visit its children recursively.
200+ So to return something from ` record ` visitor you will need to visit its children recursively.
175201
176- _ Note_ : in most cases defining only the primitive visitors is enough, otherwise look at the next example .
202+ _ Note_ : in most cases defining only the primitive visitors is enough.
177203
178204Continuing from the previous ` User ` Example
179205
@@ -183,30 +209,25 @@ Say We need this structure:
183209{
184210 profile: {
185211 type: 'container',
186- children: {
187- username: { type: 'text', label: 'username' },
188- email: { type: 'text', label: 'email' },
189- age: { type: 'number', label: 'age' }
190- }
212+ children: [
213+ { type: 'text', label: 'username' },
214+ { type: 'text', label: 'email' },
215+ { type: 'number', label: 'age' }
216+ ]
191217 }
192218}
193219*/
194- const customTraverse = (key : string , validator : Validator ) => {
220+ const customTraverse = (key , validator ) => {
195221 const type = validator .type ;
196222
197- if (type == ' string' ) {
198- return { type: key == ' email' ? key : ' text' , label: key };
199- } else if (type == ' number' ) {
200- return { type: ' number' , label: key };
201- } else if (type == ' record' ) {
202- const children = Object .entries (validator .shape ).reduce ((acc , [shapeKey , shapeValidator ]) => {
203- acc[shapeKey] = customTraverse (shapeKey, shapeValidator); // visit children
204- return acc;
205- }, {});
206- return { type: ' container' , children };
207- } else {
208- return null ;
209- }
223+ if (type == ' string' ) return { type: key == ' email' ? key : ' text' , label: key };
224+ if (type == ' number' ) return { type: ' number' , label: key };
225+ if (type == ' record' )
226+ return {
227+ type: ' container' ,
228+ children: Object .entries (validator .shape ).map (entry => customTraverse (... entry)),
229+ };
230+ return null ;
210231};
211232
212233const form_ui = User .traverse ({
0 commit comments