@bedrockio/yada 1.0.0 → 1.0.2
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/dist/cjs/Schema.js +265 -0
- package/dist/cjs/TypeSchema.js +30 -0
- package/dist/cjs/array.js +128 -0
- package/dist/cjs/boolean.js +29 -0
- package/dist/cjs/date.js +130 -0
- package/dist/cjs/errors.js +87 -0
- package/dist/cjs/index.js +51 -0
- package/dist/cjs/localization.js +39 -0
- package/dist/cjs/messages.js +75 -0
- package/dist/cjs/number.js +91 -0
- package/dist/cjs/object.js +104 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/password.js +52 -0
- package/dist/cjs/string.js +280 -0
- package/dist/cjs/utils.js +28 -0
- package/package.json +3 -1
- package/.eslintrc +0 -13
- package/babel.config.json +0 -17
- package/jest.config.json +0 -5
- package/scripts/build +0 -4
- package/src/__tests__/index.js +0 -1855
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
exports.isSchema = isSchema;
|
|
6
|
+
var _errors = require("./errors");
|
|
7
|
+
const INITIAL_TYPES = ['default', 'required', 'type', 'transform'];
|
|
8
|
+
const REQUIRED_TYPES = ['default', 'required'];
|
|
9
|
+
class Schema {
|
|
10
|
+
constructor(meta = {}) {
|
|
11
|
+
this.assertions = [];
|
|
12
|
+
this.meta = meta;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Public
|
|
16
|
+
|
|
17
|
+
required() {
|
|
18
|
+
return this.clone({
|
|
19
|
+
required: true
|
|
20
|
+
}).assert('required', val => {
|
|
21
|
+
if (val === undefined) {
|
|
22
|
+
throw new _errors.LocalizedError('Value is required.');
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
default(value) {
|
|
27
|
+
return this.clone({
|
|
28
|
+
default: value
|
|
29
|
+
}).assert('default', val => {
|
|
30
|
+
if (val === undefined) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
custom(...args) {
|
|
36
|
+
const type = args.length > 1 ? args[0] : 'custom';
|
|
37
|
+
const fn = args.length > 1 ? args[1] : args[0];
|
|
38
|
+
if (!type) {
|
|
39
|
+
throw new Error('Assertion type required.');
|
|
40
|
+
} else if (!fn) {
|
|
41
|
+
throw new Error('Assertion function required.');
|
|
42
|
+
}
|
|
43
|
+
return this.clone().assert(type, async (val, options) => {
|
|
44
|
+
return await fn(val, options);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
allow(...set) {
|
|
48
|
+
return this.assertEnum(set, true);
|
|
49
|
+
}
|
|
50
|
+
reject(...set) {
|
|
51
|
+
return this.assertEnum(set, false);
|
|
52
|
+
}
|
|
53
|
+
message(message) {
|
|
54
|
+
return this.clone({
|
|
55
|
+
message
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
tag(tags) {
|
|
59
|
+
return this.clone({
|
|
60
|
+
tags: {
|
|
61
|
+
...this.meta.tags,
|
|
62
|
+
...tags
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
description(description) {
|
|
67
|
+
return this.tag({
|
|
68
|
+
description
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
options(options) {
|
|
72
|
+
return this.clone({
|
|
73
|
+
...options
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async validate(value, options = {}) {
|
|
77
|
+
let details = [];
|
|
78
|
+
options = {
|
|
79
|
+
root: value,
|
|
80
|
+
...options,
|
|
81
|
+
...this.meta,
|
|
82
|
+
original: value
|
|
83
|
+
};
|
|
84
|
+
for (let assertion of this.assertions) {
|
|
85
|
+
if (!assertion.required && value === undefined) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const result = await this.runAssertion(assertion, value, options);
|
|
90
|
+
if (result !== undefined) {
|
|
91
|
+
value = result;
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error instanceof _errors.ArrayError) {
|
|
95
|
+
details = [...details, ...error.details];
|
|
96
|
+
} else {
|
|
97
|
+
details.push(error);
|
|
98
|
+
}
|
|
99
|
+
if (assertion.halt) {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (details.length) {
|
|
105
|
+
const {
|
|
106
|
+
message = 'Input failed validation.'
|
|
107
|
+
} = this.meta;
|
|
108
|
+
throw new _errors.ValidationError(message, details);
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
clone(meta) {
|
|
113
|
+
const clone = Object.create(this.constructor.prototype);
|
|
114
|
+
clone.assertions = [...this.assertions];
|
|
115
|
+
clone.meta = {
|
|
116
|
+
...this.meta,
|
|
117
|
+
...meta
|
|
118
|
+
};
|
|
119
|
+
return clone;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Private
|
|
123
|
+
|
|
124
|
+
assertEnum(set, allow) {
|
|
125
|
+
if (set.length === 1 && Array.isArray(set[0])) {
|
|
126
|
+
set = set[0];
|
|
127
|
+
}
|
|
128
|
+
const types = set.map(el => {
|
|
129
|
+
if (!isSchema(el)) {
|
|
130
|
+
el = JSON.stringify(el);
|
|
131
|
+
}
|
|
132
|
+
return el;
|
|
133
|
+
});
|
|
134
|
+
const msg = `${allow ? 'Must' : 'Must not'} be one of [{types}].`;
|
|
135
|
+
return this.clone({
|
|
136
|
+
enum: set
|
|
137
|
+
}).assert('enum', async (val, options) => {
|
|
138
|
+
if (val !== undefined) {
|
|
139
|
+
for (let el of set) {
|
|
140
|
+
if (isSchema(el)) {
|
|
141
|
+
try {
|
|
142
|
+
await el.validate(val, options);
|
|
143
|
+
return;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
} else if (el === val === allow) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
throw new _errors.LocalizedError(msg, {
|
|
152
|
+
types: types.join(', ')
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
assert(type, fn) {
|
|
158
|
+
this.pushAssertion({
|
|
159
|
+
halt: INITIAL_TYPES.includes(type),
|
|
160
|
+
required: REQUIRED_TYPES.includes(type),
|
|
161
|
+
type,
|
|
162
|
+
fn
|
|
163
|
+
});
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
pushAssertion(assertion) {
|
|
167
|
+
this.assertions.push(assertion);
|
|
168
|
+
this.assertions.sort((a, b) => {
|
|
169
|
+
return this.getSortIndex(a.type) - this.getSortIndex(b.type);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
transform(fn) {
|
|
173
|
+
this.assert('transform', (val, options) => {
|
|
174
|
+
if (val !== undefined) {
|
|
175
|
+
return fn(val, options);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
getSortIndex(type) {
|
|
181
|
+
const index = INITIAL_TYPES.indexOf(type);
|
|
182
|
+
return index === -1 ? INITIAL_TYPES.length : index;
|
|
183
|
+
}
|
|
184
|
+
async runAssertion(assertion, value, options = {}) {
|
|
185
|
+
const {
|
|
186
|
+
type,
|
|
187
|
+
fn
|
|
188
|
+
} = assertion;
|
|
189
|
+
try {
|
|
190
|
+
return await fn(value, options);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if ((0, _errors.isSchemaError)(error)) {
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
throw new _errors.AssertionError(error.message, type, error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
toOpenApi(extra) {
|
|
199
|
+
const {
|
|
200
|
+
required,
|
|
201
|
+
format,
|
|
202
|
+
tags,
|
|
203
|
+
default: defaultValue
|
|
204
|
+
} = this.meta;
|
|
205
|
+
return {
|
|
206
|
+
...(required && {
|
|
207
|
+
required: true
|
|
208
|
+
}),
|
|
209
|
+
...(defaultValue && {
|
|
210
|
+
default: defaultValue
|
|
211
|
+
}),
|
|
212
|
+
...(format && {
|
|
213
|
+
format
|
|
214
|
+
}),
|
|
215
|
+
...this.enumToOpenApi(),
|
|
216
|
+
...tags,
|
|
217
|
+
...extra
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
enumToOpenApi() {
|
|
221
|
+
const {
|
|
222
|
+
enum: allowed
|
|
223
|
+
} = this.meta;
|
|
224
|
+
if (allowed?.length) {
|
|
225
|
+
const type = typeof allowed[0];
|
|
226
|
+
const allowEnum = allowed.every(entry => {
|
|
227
|
+
const entryType = typeof entry;
|
|
228
|
+
return entryType !== 'object' && entryType === type;
|
|
229
|
+
});
|
|
230
|
+
if (allowEnum) {
|
|
231
|
+
return {
|
|
232
|
+
type,
|
|
233
|
+
enum: allowed
|
|
234
|
+
};
|
|
235
|
+
} else {
|
|
236
|
+
const oneOf = [];
|
|
237
|
+
for (let entry of allowed) {
|
|
238
|
+
if (isSchema(entry)) {
|
|
239
|
+
oneOf.push(entry.toOpenApi());
|
|
240
|
+
} else {
|
|
241
|
+
const type = typeof entry;
|
|
242
|
+
let forType = oneOf.find(el => {
|
|
243
|
+
return el.type === type;
|
|
244
|
+
});
|
|
245
|
+
if (!forType) {
|
|
246
|
+
forType = {
|
|
247
|
+
type,
|
|
248
|
+
enum: []
|
|
249
|
+
};
|
|
250
|
+
oneOf.push(forType);
|
|
251
|
+
}
|
|
252
|
+
forType.enum.push(entry);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
oneOf
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
exports.default = Schema;
|
|
263
|
+
function isSchema(arg) {
|
|
264
|
+
return arg instanceof Schema;
|
|
265
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _Schema = _interopRequireDefault(require("./Schema"));
|
|
6
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
7
|
+
class TypeSchema extends _Schema.default {
|
|
8
|
+
constructor(Class, meta) {
|
|
9
|
+
const type = Class.name.toLowerCase();
|
|
10
|
+
super({
|
|
11
|
+
type,
|
|
12
|
+
...meta
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
format(name, fn) {
|
|
16
|
+
return this.clone({
|
|
17
|
+
format: name
|
|
18
|
+
}).assert('format', fn);
|
|
19
|
+
}
|
|
20
|
+
toString() {
|
|
21
|
+
return this.meta.type;
|
|
22
|
+
}
|
|
23
|
+
toOpenApi(extra) {
|
|
24
|
+
return {
|
|
25
|
+
type: this.meta.type,
|
|
26
|
+
...super.toOpenApi(extra)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.default = TypeSchema;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _Schema = _interopRequireDefault(require("./Schema"));
|
|
6
|
+
var _errors = require("./errors");
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
+
class ArraySchema extends _Schema.default {
|
|
10
|
+
constructor(...args) {
|
|
11
|
+
let schemas, meta;
|
|
12
|
+
if (Array.isArray(args[0])) {
|
|
13
|
+
schemas = args[0];
|
|
14
|
+
meta = args[1];
|
|
15
|
+
} else {
|
|
16
|
+
schemas = args;
|
|
17
|
+
}
|
|
18
|
+
super({
|
|
19
|
+
message: 'Array failed validation.',
|
|
20
|
+
...meta,
|
|
21
|
+
schemas
|
|
22
|
+
});
|
|
23
|
+
this.setup();
|
|
24
|
+
}
|
|
25
|
+
setup() {
|
|
26
|
+
const {
|
|
27
|
+
schemas
|
|
28
|
+
} = this.meta;
|
|
29
|
+
const schema = schemas.length > 1 ? new _Schema.default().allow(schemas) : schemas[0];
|
|
30
|
+
this.assert('type', (val, options) => {
|
|
31
|
+
if (typeof val === 'string' && options.cast) {
|
|
32
|
+
val = val.split(',');
|
|
33
|
+
}
|
|
34
|
+
if (!Array.isArray(val)) {
|
|
35
|
+
throw new _errors.LocalizedError('Must be an array.');
|
|
36
|
+
}
|
|
37
|
+
return val;
|
|
38
|
+
});
|
|
39
|
+
if (schema) {
|
|
40
|
+
this.assert('elements', async (arr, options) => {
|
|
41
|
+
const errors = [];
|
|
42
|
+
const result = [];
|
|
43
|
+
for (let i = 0; i < arr.length; i++) {
|
|
44
|
+
const el = arr[i];
|
|
45
|
+
try {
|
|
46
|
+
result.push(await schema.validate(el, options));
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error.details?.length === 1) {
|
|
49
|
+
errors.push(new _errors.ElementError(error.details[0].message, i));
|
|
50
|
+
} else {
|
|
51
|
+
errors.push(new _errors.ElementError('Element failed validation.', i, error.details));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (errors.length) {
|
|
56
|
+
throw new _errors.ArrayError(this.meta.message, errors);
|
|
57
|
+
} else {
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
min(length) {
|
|
64
|
+
return this.clone().assert('length', arr => {
|
|
65
|
+
if (arr.length < length) {
|
|
66
|
+
const s = length === 1 ? '' : 's';
|
|
67
|
+
throw new _errors.LocalizedError('Must contain at least {length} element{s}.', {
|
|
68
|
+
length,
|
|
69
|
+
s
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
max(length) {
|
|
75
|
+
return this.clone().assert('length', arr => {
|
|
76
|
+
if (arr.length > length) {
|
|
77
|
+
const s = length === 1 ? '' : 's';
|
|
78
|
+
throw new _errors.LocalizedError('Cannot contain more than {length} element{s}.', {
|
|
79
|
+
length,
|
|
80
|
+
s
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
latlng() {
|
|
86
|
+
return this.clone({
|
|
87
|
+
format: 'latlng'
|
|
88
|
+
}).assert('format', arr => {
|
|
89
|
+
if (arr.length !== 2) {
|
|
90
|
+
throw new _errors.LocalizedError('Must be an array of length 2.');
|
|
91
|
+
} else {
|
|
92
|
+
const [lat, lng] = arr;
|
|
93
|
+
if (typeof lat !== 'number' || lat < -90 || lat > 90) {
|
|
94
|
+
throw new _errors.LocalizedError('Invalid latitude.');
|
|
95
|
+
} else if (typeof lng !== 'number' || lng < -180 || lng > 180) {
|
|
96
|
+
throw new _errors.LocalizedError('Invalid longitude.');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
toString() {
|
|
102
|
+
return 'array';
|
|
103
|
+
}
|
|
104
|
+
toOpenApi(extra) {
|
|
105
|
+
let other;
|
|
106
|
+
const {
|
|
107
|
+
schemas
|
|
108
|
+
} = this.meta;
|
|
109
|
+
if (schemas.length > 1) {
|
|
110
|
+
other = {
|
|
111
|
+
oneOf: schemas.map(schema => {
|
|
112
|
+
return schema.toOpenApi();
|
|
113
|
+
})
|
|
114
|
+
};
|
|
115
|
+
} else if (schemas.length === 1) {
|
|
116
|
+
other = {
|
|
117
|
+
items: schemas[0].toOpenApi()
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
type: 'array',
|
|
122
|
+
...super.toOpenApi(extra),
|
|
123
|
+
...other
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
var _default = (0, _utils.wrapSchema)(ArraySchema);
|
|
128
|
+
exports.default = _default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _TypeSchema = _interopRequireDefault(require("./TypeSchema"));
|
|
6
|
+
var _errors = require("./errors");
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
+
class BooleanSchema extends _TypeSchema.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(Boolean);
|
|
12
|
+
this.assert('type', (val, options) => {
|
|
13
|
+
if (typeof val === 'string' && options.cast) {
|
|
14
|
+
const str = val.toLowerCase();
|
|
15
|
+
if (str === 'true' || str === '1') {
|
|
16
|
+
val = true;
|
|
17
|
+
} else if (str === 'false' || str === '0') {
|
|
18
|
+
val = false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (typeof val !== 'boolean') {
|
|
22
|
+
throw new _errors.LocalizedError('Must be a boolean.');
|
|
23
|
+
}
|
|
24
|
+
return val;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
var _default = (0, _utils.wrapSchema)(BooleanSchema);
|
|
29
|
+
exports.default = _default;
|
package/dist/cjs/date.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _validator = _interopRequireDefault(require("validator"));
|
|
6
|
+
var _utils = require("./utils");
|
|
7
|
+
var _errors = require("./errors");
|
|
8
|
+
var _Schema = _interopRequireDefault(require("./Schema"));
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
class DateSchema extends _Schema.default {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.assert('type', val => {
|
|
14
|
+
const date = new Date(val);
|
|
15
|
+
if (!val && val !== 0 || isNaN(date.getTime())) {
|
|
16
|
+
throw new _errors.LocalizedError('Must be a valid date input.');
|
|
17
|
+
} else {
|
|
18
|
+
return date;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
min(min) {
|
|
23
|
+
min = new Date(min);
|
|
24
|
+
return this.clone().assert('min', date => {
|
|
25
|
+
if (date < min) {
|
|
26
|
+
throw new _errors.LocalizedError('Must be after {date}.', {
|
|
27
|
+
date: min.toISOString()
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
max(max) {
|
|
33
|
+
max = new Date(max);
|
|
34
|
+
return this.clone().assert('max', date => {
|
|
35
|
+
if (date > max) {
|
|
36
|
+
throw new _errors.LocalizedError('Must be before {date}.', {
|
|
37
|
+
date: max.toISOString()
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
before(max) {
|
|
43
|
+
max = new Date(max);
|
|
44
|
+
return this.clone().assert('before', date => {
|
|
45
|
+
if (date >= max) {
|
|
46
|
+
throw new _errors.LocalizedError('Must be before {date}.', {
|
|
47
|
+
date: max.toISOString()
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
after(min) {
|
|
53
|
+
min = new Date(min);
|
|
54
|
+
return this.clone().assert('after', date => {
|
|
55
|
+
if (date <= min) {
|
|
56
|
+
throw new _errors.LocalizedError('Must be after {date}.', {
|
|
57
|
+
date: min.toISOString()
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
past() {
|
|
63
|
+
return this.clone().assert('past', date => {
|
|
64
|
+
const now = new Date();
|
|
65
|
+
if (date > now) {
|
|
66
|
+
throw new _errors.LocalizedError('Must be in the past.');
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
future() {
|
|
71
|
+
return this.clone().assert('future', date => {
|
|
72
|
+
const now = new Date();
|
|
73
|
+
if (date < now) {
|
|
74
|
+
throw new _errors.LocalizedError('Must be in the future.');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
iso(format = 'date-time') {
|
|
79
|
+
return this.clone({
|
|
80
|
+
format
|
|
81
|
+
}).assert('format', (val, options) => {
|
|
82
|
+
const {
|
|
83
|
+
original
|
|
84
|
+
} = options;
|
|
85
|
+
if (typeof original !== 'string') {
|
|
86
|
+
throw new _errors.LocalizedError('Must be a string.');
|
|
87
|
+
} else if (!_validator.default.isISO8601(original)) {
|
|
88
|
+
throw new _errors.LocalizedError('Must be in ISO 8601 format.');
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
timestamp() {
|
|
93
|
+
return this.clone({
|
|
94
|
+
format: 'timestamp'
|
|
95
|
+
}).assert('format', (date, {
|
|
96
|
+
original
|
|
97
|
+
}) => {
|
|
98
|
+
if (typeof original !== 'number') {
|
|
99
|
+
throw new _errors.LocalizedError('Must be a timestamp in milliseconds.');
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
unix() {
|
|
104
|
+
return this.clone({
|
|
105
|
+
format: 'unix timestamp'
|
|
106
|
+
}).assert('format', (date, {
|
|
107
|
+
original
|
|
108
|
+
}) => {
|
|
109
|
+
if (typeof original !== 'number') {
|
|
110
|
+
throw new _errors.LocalizedError('Must be a timestamp in seconds.');
|
|
111
|
+
} else {
|
|
112
|
+
return new Date(original * 1000);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
toString() {
|
|
117
|
+
return 'date';
|
|
118
|
+
}
|
|
119
|
+
toOpenApi(extra) {
|
|
120
|
+
const {
|
|
121
|
+
format
|
|
122
|
+
} = this.meta;
|
|
123
|
+
return {
|
|
124
|
+
type: format.includes('timestamp') ? 'number' : 'string',
|
|
125
|
+
...super.toOpenApi(extra)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
var _default = (0, _utils.wrapSchema)(DateSchema);
|
|
130
|
+
exports.default = _default;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.ValidationError = exports.LocalizedError = exports.FieldError = exports.ElementError = exports.AssertionError = exports.ArrayError = void 0;
|
|
5
|
+
exports.isSchemaError = isSchemaError;
|
|
6
|
+
var _messages = require("./messages");
|
|
7
|
+
var _localization = require("./localization");
|
|
8
|
+
class LocalizedError extends Error {
|
|
9
|
+
constructor(message, values) {
|
|
10
|
+
super((0, _localization.localize)(message, values));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.LocalizedError = LocalizedError;
|
|
14
|
+
class ValidationError extends Error {
|
|
15
|
+
constructor(message, details = [], type = 'validation') {
|
|
16
|
+
super((0, _localization.localize)(message));
|
|
17
|
+
this.details = details;
|
|
18
|
+
this.type = type;
|
|
19
|
+
}
|
|
20
|
+
toJSON() {
|
|
21
|
+
return {
|
|
22
|
+
type: this.type,
|
|
23
|
+
message: this.message,
|
|
24
|
+
details: this.details
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
getFullMessage(options) {
|
|
28
|
+
return (0, _messages.getFullMessage)(this, {
|
|
29
|
+
delimiter: ' ',
|
|
30
|
+
...options
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.ValidationError = ValidationError;
|
|
35
|
+
class FieldError extends ValidationError {
|
|
36
|
+
constructor(message, field, original, details) {
|
|
37
|
+
super(message, details, 'field');
|
|
38
|
+
this.field = field;
|
|
39
|
+
this.original = original;
|
|
40
|
+
this.details = details;
|
|
41
|
+
}
|
|
42
|
+
toJSON() {
|
|
43
|
+
return {
|
|
44
|
+
field: this.field,
|
|
45
|
+
...super.toJSON()
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.FieldError = FieldError;
|
|
50
|
+
class ElementError extends ValidationError {
|
|
51
|
+
constructor(message, index, details) {
|
|
52
|
+
super(message, details, 'element');
|
|
53
|
+
this.index = index;
|
|
54
|
+
this.details = details;
|
|
55
|
+
}
|
|
56
|
+
toJSON() {
|
|
57
|
+
return {
|
|
58
|
+
index: this.index,
|
|
59
|
+
...super.toJSON()
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.ElementError = ElementError;
|
|
64
|
+
class AssertionError extends Error {
|
|
65
|
+
constructor(message, type, original) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.type = type;
|
|
68
|
+
this.original = original;
|
|
69
|
+
}
|
|
70
|
+
toJSON() {
|
|
71
|
+
return {
|
|
72
|
+
type: this.type,
|
|
73
|
+
message: this.message
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.AssertionError = AssertionError;
|
|
78
|
+
class ArrayError extends Error {
|
|
79
|
+
constructor(message, details) {
|
|
80
|
+
super(message);
|
|
81
|
+
this.details = details;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.ArrayError = ArrayError;
|
|
85
|
+
function isSchemaError(arg) {
|
|
86
|
+
return arg instanceof ValidationError || arg instanceof AssertionError || arg instanceof ArrayError;
|
|
87
|
+
}
|