turbo-schema 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +218 -0
- package/package.json +31 -0
- package/readme.md +452 -0
package/index.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// index.js:
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const UUID =
|
|
6
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
7
|
+
class ValidationError extends Error {
|
|
8
|
+
constructor(errors) {
|
|
9
|
+
const message = errors.length
|
|
10
|
+
? `Schema validation failed: ${errors.join(", ")}`
|
|
11
|
+
: "Schema validation failed";
|
|
12
|
+
|
|
13
|
+
super(message);
|
|
14
|
+
|
|
15
|
+
this.name = "ValidationError";
|
|
16
|
+
|
|
17
|
+
// backward compatibility
|
|
18
|
+
this.errors = errors;
|
|
19
|
+
|
|
20
|
+
// structured version
|
|
21
|
+
this.details = errors.map((msg) => {
|
|
22
|
+
const [field, ...rest] = msg.split(" ");
|
|
23
|
+
return {
|
|
24
|
+
field,
|
|
25
|
+
message: rest.join(" "),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class Schema {
|
|
32
|
+
constructor(def = {}) {
|
|
33
|
+
if (!def || typeof def !== "object" || Array.isArray(def)) {
|
|
34
|
+
throw new TypeError("Schema must be an object");
|
|
35
|
+
}
|
|
36
|
+
this.def = def;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
validate(
|
|
40
|
+
data = {},
|
|
41
|
+
{ partial = false, coerce = true, stripUnknown = true } = {},
|
|
42
|
+
) {
|
|
43
|
+
const out = {};
|
|
44
|
+
const errors = [];
|
|
45
|
+
|
|
46
|
+
for (const [k, c] of Object.entries(this.def)) {
|
|
47
|
+
let v = data[k];
|
|
48
|
+
const exists = Object.hasOwn(data, k);
|
|
49
|
+
|
|
50
|
+
if (partial && !exists) continue;
|
|
51
|
+
|
|
52
|
+
// default values
|
|
53
|
+
if (v == null && c.default !== undefined) {
|
|
54
|
+
v = typeof c.default === "function" ? c.default() : c.default;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// required check
|
|
58
|
+
if (c.required && v == null) {
|
|
59
|
+
errors.push(`${k} required`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (v == null) continue;
|
|
64
|
+
|
|
65
|
+
// envvar special case (ignore input value)
|
|
66
|
+
if (c.type === "envvar") {
|
|
67
|
+
const envName = c.varname;
|
|
68
|
+
|
|
69
|
+
if (!envName) {
|
|
70
|
+
errors.push(`${k} missing varname`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
v = process.env[envName];
|
|
75
|
+
|
|
76
|
+
if (v == null) {
|
|
77
|
+
errors.push(`${k} missing env var ${envName}`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// coercion
|
|
83
|
+
if (coerce) v = this._coerce(v, c.type, c);
|
|
84
|
+
|
|
85
|
+
// type check
|
|
86
|
+
const typeErr = this._type(k, v, c.type);
|
|
87
|
+
if (typeErr) {
|
|
88
|
+
errors.push(typeErr);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// enum check
|
|
93
|
+
if (c.enum && !c.enum.includes(v)) {
|
|
94
|
+
errors.push(`${k} invalid enum`);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// pattern check
|
|
99
|
+
if (c.pattern) {
|
|
100
|
+
const ok =
|
|
101
|
+
c.pattern instanceof RegExp
|
|
102
|
+
? c.pattern.test(v)
|
|
103
|
+
: typeof c.pattern.test === "function" && c.pattern.test(v);
|
|
104
|
+
|
|
105
|
+
if (!ok) {
|
|
106
|
+
errors.push(`${k} pattern mismatch`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// min / max
|
|
112
|
+
if (c.min != null && v < c.min) {
|
|
113
|
+
errors.push(`${k} too small`);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (c.max != null && v > c.max) {
|
|
118
|
+
errors.push(`${k} too large`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
out[k] = v;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// unknown fields
|
|
126
|
+
if (!stripUnknown) {
|
|
127
|
+
for (const k in data) {
|
|
128
|
+
if (!Object.hasOwn(this.def, k)) {
|
|
129
|
+
out[k] = data[k];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (errors.length) {
|
|
135
|
+
throw new ValidationError(errors);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
isValid(d, o) {
|
|
142
|
+
try {
|
|
143
|
+
this.validate(d, o);
|
|
144
|
+
return true;
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fields() {
|
|
151
|
+
return Object.keys(this.def);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ---------------- internal ----------------
|
|
155
|
+
|
|
156
|
+
_coerce(v, t, c) {
|
|
157
|
+
switch (t) {
|
|
158
|
+
case "string":
|
|
159
|
+
return String(v);
|
|
160
|
+
|
|
161
|
+
case "integer":
|
|
162
|
+
return Number.isInteger(+v) ? +v : v;
|
|
163
|
+
|
|
164
|
+
case "number":
|
|
165
|
+
return Number.isFinite(+v) ? +v : v;
|
|
166
|
+
|
|
167
|
+
case "boolean":
|
|
168
|
+
return v === "true" ? true : v === "false" ? false : v;
|
|
169
|
+
|
|
170
|
+
case "date":
|
|
171
|
+
return v instanceof Date ? v.toISOString().slice(0, 10) : String(v);
|
|
172
|
+
|
|
173
|
+
case "datetime":
|
|
174
|
+
return v instanceof Date ? v : new Date(v);
|
|
175
|
+
|
|
176
|
+
case "envvar":
|
|
177
|
+
return v;
|
|
178
|
+
|
|
179
|
+
default:
|
|
180
|
+
return v;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
_type(k, v, t) {
|
|
185
|
+
switch (t) {
|
|
186
|
+
case "string":
|
|
187
|
+
return typeof v === "string" ? null : `${k} must be string`;
|
|
188
|
+
|
|
189
|
+
case "integer":
|
|
190
|
+
return Number.isInteger(v) ? null : `${k} must be integer`;
|
|
191
|
+
|
|
192
|
+
case "number":
|
|
193
|
+
return typeof v === "number" ? null : `${k} must be number`;
|
|
194
|
+
|
|
195
|
+
case "boolean":
|
|
196
|
+
return typeof v === "boolean" ? null : `${k} must be boolean`;
|
|
197
|
+
|
|
198
|
+
case "uuid":
|
|
199
|
+
return UUID.test(v) ? null : `${k} invalid uuid`;
|
|
200
|
+
|
|
201
|
+
case "array":
|
|
202
|
+
return Array.isArray(v) ? null : `${k} must be array`;
|
|
203
|
+
|
|
204
|
+
case "object":
|
|
205
|
+
return v && typeof v === "object" && !Array.isArray(v)
|
|
206
|
+
? null
|
|
207
|
+
: `${k} must be object`;
|
|
208
|
+
|
|
209
|
+
case "envvar":
|
|
210
|
+
return v != null ? null : `${k} missing env value`;
|
|
211
|
+
|
|
212
|
+
default:
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
module.exports = { Schema, ValidationError };
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "commonjs",
|
|
3
|
+
"name": "turbo-schema",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Light weight object validation schema",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"light",
|
|
9
|
+
"weight",
|
|
10
|
+
"object",
|
|
11
|
+
"schema",
|
|
12
|
+
"validate",
|
|
13
|
+
"validation"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/miketerry-org/turbo-schema#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/miketerry-org/turbo-schema/issues"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/miketerry-org/turbo-schema.git"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "Mike Terry",
|
|
25
|
+
"scripts": {
|
|
26
|
+
"test": "node --test",
|
|
27
|
+
"test:watch": "node --test --watch",
|
|
28
|
+
"test:coverage": "node --test --experimental-test-coverage",
|
|
29
|
+
"test:only": "node --test --test-only"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
# Turbo Schema
|
|
2
|
+
|
|
3
|
+
A lightweight, dependency-free schema validation library for Node.js.
|
|
4
|
+
|
|
5
|
+
Turbo Schema validates JavaScript objects against a declarative schema definition. It supports type coercion, default values, required fields, enumerations, regular expression validation, numeric ranges, UUID validation, and configurable handling of unknown properties.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Zero dependencies
|
|
10
|
+
- Declarative object schemas
|
|
11
|
+
- Type validation
|
|
12
|
+
- Optional type coercion
|
|
13
|
+
- Default values
|
|
14
|
+
- Required fields
|
|
15
|
+
- Enum validation
|
|
16
|
+
- Pattern (RegExp) validation
|
|
17
|
+
- Minimum and maximum value validation
|
|
18
|
+
- UUID validation
|
|
19
|
+
- Partial validation for updates
|
|
20
|
+
- Optional removal of unknown properties
|
|
21
|
+
- Structured validation errors
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install turbo-schema
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Basic Usage
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
const { Schema } = require("turbo-schema");
|
|
37
|
+
|
|
38
|
+
const userSchema = new Schema({
|
|
39
|
+
id: {
|
|
40
|
+
type: "uuid",
|
|
41
|
+
required: true,
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
name: {
|
|
45
|
+
type: "string",
|
|
46
|
+
required: true,
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
age: {
|
|
50
|
+
type: "integer",
|
|
51
|
+
min: 18,
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
active: {
|
|
55
|
+
type: "boolean",
|
|
56
|
+
default: true,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const user = userSchema.validate({
|
|
61
|
+
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
62
|
+
name: "Alice",
|
|
63
|
+
age: "25",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log(user);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Output:
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
{
|
|
73
|
+
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
74
|
+
name: "Alice",
|
|
75
|
+
age: 25,
|
|
76
|
+
active: true
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
# Schema Definition
|
|
83
|
+
|
|
84
|
+
A schema consists of an object whose keys represent field names and whose values define validation rules.
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
const schema = new Schema({
|
|
90
|
+
username: {
|
|
91
|
+
type: "string",
|
|
92
|
+
required: true,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Field Properties
|
|
100
|
+
|
|
101
|
+
| Property | Type | Description |
|
|
102
|
+
| ---------- | -------------- | ------------------------------------------------------ |
|
|
103
|
+
| `type` | String | Expected data type |
|
|
104
|
+
| `required` | Boolean | Field must be present |
|
|
105
|
+
| `default` | Any / Function | Default value if missing or `null` |
|
|
106
|
+
| `enum` | Array | List of allowed values |
|
|
107
|
+
| `pattern` | RegExp | Regular expression or any object implementing `test()` |
|
|
108
|
+
| `min` | Number | Minimum numeric value |
|
|
109
|
+
| `max` | Number | Maximum numeric value |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Supported Types
|
|
114
|
+
|
|
115
|
+
| Type | Description |
|
|
116
|
+
| ---------- | -------------------------- |
|
|
117
|
+
| `string` | String value |
|
|
118
|
+
| `integer` | Integer number |
|
|
119
|
+
| `number` | Floating point or integer |
|
|
120
|
+
| `boolean` | Boolean value |
|
|
121
|
+
| `uuid` | UUID string |
|
|
122
|
+
| `array` | JavaScript array |
|
|
123
|
+
| `object` | Plain JavaScript object |
|
|
124
|
+
| `date` | Date string (`YYYY-MM-DD`) |
|
|
125
|
+
| `datetime` | JavaScript `Date` object |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
# Validation
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
const validated = schema.validate(data);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Returns a new validated object.
|
|
136
|
+
|
|
137
|
+
If validation fails, a `ValidationError` is thrown.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
# Validation Options
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
schema.validate(data, {
|
|
145
|
+
partial: false,
|
|
146
|
+
coerce: true,
|
|
147
|
+
stripUnknown: true,
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## partial
|
|
152
|
+
|
|
153
|
+
Default: `false`
|
|
154
|
+
|
|
155
|
+
When `true`, fields that are missing from the input object are ignored instead of being validated.
|
|
156
|
+
|
|
157
|
+
Useful for PATCH requests or partial updates.
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
schema.validate(update, {
|
|
161
|
+
partial: true,
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## coerce
|
|
168
|
+
|
|
169
|
+
Default: `true`
|
|
170
|
+
|
|
171
|
+
Automatically converts values into the expected type when possible.
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
|
|
175
|
+
Input:
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
{
|
|
179
|
+
age: "42";
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Output:
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
{
|
|
187
|
+
age: 42;
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Disable coercion:
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
schema.validate(data, {
|
|
195
|
+
coerce: false,
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## stripUnknown
|
|
202
|
+
|
|
203
|
+
Default: `true`
|
|
204
|
+
|
|
205
|
+
Controls how properties not defined in the schema are handled.
|
|
206
|
+
|
|
207
|
+
Input:
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
{
|
|
211
|
+
name: "Alice",
|
|
212
|
+
admin: true
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Schema:
|
|
217
|
+
|
|
218
|
+
```javascript
|
|
219
|
+
const schema = new Schema({
|
|
220
|
+
name: {
|
|
221
|
+
type: "string",
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
With the default setting:
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
{
|
|
230
|
+
name: "Alice";
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
To preserve unknown properties:
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
schema.validate(data, {
|
|
238
|
+
stripUnknown: false,
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Result:
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
{
|
|
246
|
+
name: "Alice",
|
|
247
|
+
admin: true
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
# Default Values
|
|
254
|
+
|
|
255
|
+
Defaults are applied when a property is `null` or `undefined`.
|
|
256
|
+
|
|
257
|
+
Static default:
|
|
258
|
+
|
|
259
|
+
```javascript
|
|
260
|
+
count: {
|
|
261
|
+
type: "integer",
|
|
262
|
+
default: 0
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Function default:
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
created: {
|
|
270
|
+
type: "datetime",
|
|
271
|
+
default: () => new Date()
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
# Required Fields
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
email: {
|
|
281
|
+
type: "string",
|
|
282
|
+
required: true
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Missing required fields generate validation errors.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
# Enumerations
|
|
291
|
+
|
|
292
|
+
```javascript
|
|
293
|
+
status: {
|
|
294
|
+
enum: ["active", "inactive", "pending"];
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Only values contained in the array are accepted.
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
# Pattern Validation
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
zip: {
|
|
306
|
+
type: "string",
|
|
307
|
+
pattern: /^\d{5}$/
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Any object implementing a `test()` method may also be supplied.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
# Numeric Ranges
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
age: {
|
|
319
|
+
type: "integer",
|
|
320
|
+
min: 18,
|
|
321
|
+
max: 120
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
# UUID Validation
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
id: {
|
|
331
|
+
type: "uuid";
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
UUID values are validated using a built-in regular expression.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
# Validation Errors
|
|
340
|
+
|
|
341
|
+
Validation failures throw a `ValidationError`.
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
try {
|
|
345
|
+
schema.validate(data);
|
|
346
|
+
} catch (err) {
|
|
347
|
+
console.error(err.message);
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Example:
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
Schema validation failed: age too small, email required
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## ValidationError Properties
|
|
360
|
+
|
|
361
|
+
### message
|
|
362
|
+
|
|
363
|
+
A human-readable summary of the validation failures.
|
|
364
|
+
|
|
365
|
+
Example:
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
Schema validation failed: age too small, email required
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
### errors
|
|
374
|
+
|
|
375
|
+
An array of validation messages.
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
["age too small", "email required"];
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### details
|
|
384
|
+
|
|
385
|
+
A structured version of each validation error.
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
[
|
|
389
|
+
{
|
|
390
|
+
field: "age",
|
|
391
|
+
message: "too small",
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
field: "email",
|
|
395
|
+
message: "required",
|
|
396
|
+
},
|
|
397
|
+
];
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
# isValid()
|
|
403
|
+
|
|
404
|
+
Returns `true` if validation succeeds, otherwise `false`.
|
|
405
|
+
|
|
406
|
+
```javascript
|
|
407
|
+
if (schema.isValid(data)) {
|
|
408
|
+
console.log("Valid");
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Equivalent to calling `validate()` and catching any `ValidationError`.
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
# fields()
|
|
417
|
+
|
|
418
|
+
Returns an array of field names defined by the schema.
|
|
419
|
+
|
|
420
|
+
```javascript
|
|
421
|
+
schema.fields();
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Example:
|
|
425
|
+
|
|
426
|
+
```javascript
|
|
427
|
+
["id", "name", "email"];
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
# Type Coercion
|
|
433
|
+
|
|
434
|
+
When coercion is enabled (the default), Turbo Schema performs the following conversions where possible.
|
|
435
|
+
|
|
436
|
+
| Type | Example |
|
|
437
|
+
| ---------- | --------------------- |
|
|
438
|
+
| `string` | `123 → "123"` |
|
|
439
|
+
| `integer` | `"42" → 42` |
|
|
440
|
+
| `number` | `"3.14" → 3.14` |
|
|
441
|
+
| `boolean` | `"true" → true` |
|
|
442
|
+
| `boolean` | `"false" → false` |
|
|
443
|
+
| `date` | `Date → "YYYY-MM-DD"` |
|
|
444
|
+
| `datetime` | ISO string → `Date` |
|
|
445
|
+
|
|
446
|
+
If a value cannot be coerced, the original value is retained and normal validation determines whether it is valid.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
# License
|
|
451
|
+
|
|
452
|
+
MIT
|