@aeriajs/validation 0.0.27 → 0.0.28
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/index.mjs +1 -0
- package/dist/validate.mjs +209 -238
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
package/dist/validate.mjs
CHANGED
|
@@ -1,258 +1,229 @@
|
|
|
1
|
-
|
|
2
|
-
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
3
|
-
return !!right[Symbol.hasInstance](left);
|
|
4
|
-
} else {
|
|
5
|
-
return left instanceof right;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
function _type_of(obj) {
|
|
9
|
-
"@swc/helpers - typeof";
|
|
10
|
-
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
11
|
-
}
|
|
1
|
+
"use strict";
|
|
12
2
|
import { isLeft, left, right, unwrapEither, getMissingProperties } from "@aeriajs/common";
|
|
13
3
|
import { ValidationErrorCodes } from "@aeriajs/types";
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
const getValueType = (value) => {
|
|
5
|
+
return Array.isArray(value) ? "array" : typeof value;
|
|
16
6
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
7
|
+
const getPropertyType = (property) => {
|
|
8
|
+
if ("$ref" in property || "properties" in property || "additionalProperties" in property) {
|
|
9
|
+
return "object";
|
|
10
|
+
}
|
|
11
|
+
if ("enum" in property) {
|
|
12
|
+
return typeof property.enum[0];
|
|
13
|
+
}
|
|
14
|
+
if ("format" in property && property.format) {
|
|
15
|
+
if ([
|
|
16
|
+
"date",
|
|
17
|
+
"date-time"
|
|
18
|
+
].includes(property.format)) {
|
|
19
|
+
return "datetime";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if ("type" in property) {
|
|
23
|
+
return property.type;
|
|
24
|
+
}
|
|
35
25
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
const makePropertyError = (type, details) => {
|
|
27
|
+
return {
|
|
28
|
+
type,
|
|
29
|
+
details
|
|
30
|
+
};
|
|
41
31
|
};
|
|
42
|
-
export
|
|
43
|
-
|
|
32
|
+
export const makeValidationError = (error) => {
|
|
33
|
+
return error;
|
|
44
34
|
};
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
35
|
+
export const validateProperty = (propName, what, property, options = {}) => {
|
|
36
|
+
const { extraneous, filterOutExtraneous, coerce } = options;
|
|
37
|
+
if (what === void 0) {
|
|
38
|
+
return right(what);
|
|
39
|
+
}
|
|
40
|
+
if (!property) {
|
|
41
|
+
if (extraneous || Array.isArray(extraneous) && extraneous.includes(propName)) {
|
|
42
|
+
if (filterOutExtraneous) {
|
|
43
|
+
return right(void 0);
|
|
44
|
+
}
|
|
45
|
+
return right(what);
|
|
46
|
+
}
|
|
47
|
+
return left(makePropertyError("extraneous", {
|
|
48
|
+
expected: "undefined",
|
|
49
|
+
got: getValueType(what)
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
if ("getter" in property) {
|
|
53
|
+
return right(void 0);
|
|
54
|
+
}
|
|
55
|
+
if ("properties" in property) {
|
|
56
|
+
return validate(what, property, options);
|
|
57
|
+
}
|
|
58
|
+
if ("const" in property) {
|
|
59
|
+
if (what !== property.const) {
|
|
60
|
+
return left(makePropertyError("unmatching", {
|
|
61
|
+
expected: property.const,
|
|
62
|
+
got: what
|
|
63
|
+
}));
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
return right(what);
|
|
66
|
+
}
|
|
67
|
+
const expectedType = getPropertyType(property);
|
|
68
|
+
const actualType = getValueType(what);
|
|
69
|
+
if ("enum" in property && property.enum.length === 0) {
|
|
70
|
+
return right(what);
|
|
71
|
+
}
|
|
72
|
+
if (actualType !== expectedType && !("items" in property && actualType === "array") && !(actualType === "number" && expectedType === "integer")) {
|
|
73
|
+
if (expectedType === "datetime" && what instanceof Date) {
|
|
74
|
+
return right(what);
|
|
68
75
|
}
|
|
69
|
-
if ("
|
|
70
|
-
|
|
71
|
-
return left(makePropertyError("unmatching", {
|
|
72
|
-
expected: property.const,
|
|
73
|
-
got: what
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
return right(what);
|
|
76
|
+
if (expectedType === "boolean" && !what) {
|
|
77
|
+
return right(what);
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if ("enum" in property && property.enum.length === 0) {
|
|
79
|
+
if ("$ref" in property && actualType === "string") {
|
|
80
|
+
if (/^[0-9a-fA-F]{24}$/.test(what)) {
|
|
81
81
|
return right(what);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (coerce) {
|
|
85
|
+
if (expectedType === "number" && actualType === "string") {
|
|
86
|
+
const coerced = parseFloat(what);
|
|
87
|
+
if (!isNaN(coerced)) {
|
|
88
|
+
return right(coerced);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (expectedType === "integer" && actualType === "string") {
|
|
92
|
+
const coerced = parseInt(what);
|
|
93
|
+
if (!isNaN(coerced)) {
|
|
94
|
+
return right(coerced);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (expectedType === "string" && actualType === "number") {
|
|
98
|
+
return right(String(what));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return left(makePropertyError("unmatching", {
|
|
102
|
+
expected: expectedType,
|
|
103
|
+
got: actualType
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
if ("items" in property) {
|
|
107
|
+
let i = 0;
|
|
108
|
+
for (const elem of what) {
|
|
109
|
+
const resultEither = validateProperty(propName, elem, property.items, options);
|
|
110
|
+
if (isLeft(resultEither)) {
|
|
111
|
+
const result = unwrapEither(resultEither);
|
|
112
|
+
if ("errors" in result) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
result.index = i;
|
|
116
|
+
return left(result);
|
|
117
|
+
}
|
|
118
|
+
i++;
|
|
119
|
+
}
|
|
120
|
+
} else if ("type" in property) {
|
|
121
|
+
if (property.type === "integer") {
|
|
122
|
+
if (!Number.isInteger(what)) {
|
|
123
|
+
return left(makePropertyError("numeric_constraint", {
|
|
124
|
+
expected: "integer",
|
|
125
|
+
got: "invalid_number"
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
82
128
|
}
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return right(what);
|
|
89
|
-
}
|
|
90
|
-
if ("$ref" in property && actualType === "string") {
|
|
91
|
-
if (/^[0-9a-fA-F]{24}$/.test(what)) {
|
|
92
|
-
return right(what);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (coerce) {
|
|
96
|
-
if (expectedType === "number" && actualType === "string") {
|
|
97
|
-
var coerced = parseFloat(what);
|
|
98
|
-
if (!isNaN(coerced)) {
|
|
99
|
-
return right(coerced);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (expectedType === "integer" && actualType === "string") {
|
|
103
|
-
var coerced1 = parseInt(what);
|
|
104
|
-
if (!isNaN(coerced1)) {
|
|
105
|
-
return right(coerced1);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (expectedType === "string" && actualType === "number") {
|
|
109
|
-
return right(String(what));
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return left(makePropertyError("unmatching", {
|
|
113
|
-
expected: expectedType,
|
|
114
|
-
got: actualType
|
|
129
|
+
if (property.type === "integer" || property.type === "number") {
|
|
130
|
+
if (property.maximum && property.maximum < what || property.minimum && property.minimum > what || property.exclusiveMaximum && property.exclusiveMaximum <= what || property.exclusiveMinimum && property.exclusiveMinimum >= what) {
|
|
131
|
+
return left(makePropertyError("numeric_constraint", {
|
|
132
|
+
expected: "number",
|
|
133
|
+
got: "invalid_number"
|
|
115
134
|
}));
|
|
135
|
+
}
|
|
116
136
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
var resultEither = validateProperty(propName, elem, property.items, options);
|
|
124
|
-
if (isLeft(resultEither)) {
|
|
125
|
-
var result = unwrapEither(resultEither);
|
|
126
|
-
if ("errors" in result) {
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
result.index = i;
|
|
130
|
-
return left(result);
|
|
131
|
-
}
|
|
132
|
-
i++;
|
|
133
|
-
}
|
|
134
|
-
} catch (err) {
|
|
135
|
-
_didIteratorError = true;
|
|
136
|
-
_iteratorError = err;
|
|
137
|
-
} finally{
|
|
138
|
-
try {
|
|
139
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
140
|
-
_iterator.return();
|
|
141
|
-
}
|
|
142
|
-
} finally{
|
|
143
|
-
if (_didIteratorError) {
|
|
144
|
-
throw _iteratorError;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
} else if ("type" in property) {
|
|
149
|
-
if (property.type === "integer") {
|
|
150
|
-
if (!Number.isInteger(what)) {
|
|
151
|
-
return left(makePropertyError("numeric_constraint", {
|
|
152
|
-
expected: "integer",
|
|
153
|
-
got: "invalid_number"
|
|
154
|
-
}));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if (property.type === "integer" || property.type === "number") {
|
|
158
|
-
if (property.maximum && property.maximum < what || property.minimum && property.minimum > what || property.exclusiveMaximum && property.exclusiveMaximum <= what || property.exclusiveMinimum && property.exclusiveMinimum >= what) {
|
|
159
|
-
return left(makePropertyError("numeric_constraint", {
|
|
160
|
-
expected: "number",
|
|
161
|
-
got: "invalid_number"
|
|
162
|
-
}));
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
} else if ("enum" in property) {
|
|
166
|
-
if (!property.enum.includes(what)) {
|
|
167
|
-
return left(makePropertyError("extraneous_element", {
|
|
168
|
-
expected: property.enum,
|
|
169
|
-
got: what
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
137
|
+
} else if ("enum" in property) {
|
|
138
|
+
if (!property.enum.includes(what)) {
|
|
139
|
+
return left(makePropertyError("extraneous_element", {
|
|
140
|
+
expected: property.enum,
|
|
141
|
+
got: what
|
|
142
|
+
}));
|
|
172
143
|
}
|
|
173
|
-
|
|
144
|
+
}
|
|
145
|
+
return right(what);
|
|
174
146
|
};
|
|
175
|
-
export
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
});
|
|
190
|
-
}
|
|
147
|
+
export const validateWholeness = (what, schema) => {
|
|
148
|
+
const required = schema.required ? schema.required : Object.keys(schema.properties);
|
|
149
|
+
const missingProps = getMissingProperties(what, schema, required);
|
|
150
|
+
if (missingProps.length > 0) {
|
|
151
|
+
return makeValidationError({
|
|
152
|
+
code: ValidationErrorCodes.MissingProperties,
|
|
153
|
+
errors: Object.fromEntries(missingProps.map((error) => [
|
|
154
|
+
error,
|
|
155
|
+
{
|
|
156
|
+
type: "missing"
|
|
157
|
+
}
|
|
158
|
+
]))
|
|
159
|
+
});
|
|
160
|
+
}
|
|
191
161
|
};
|
|
192
|
-
export
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
162
|
+
export const validate = (what, schema, options = {}) => {
|
|
163
|
+
if (!what) {
|
|
164
|
+
return left(makeValidationError({
|
|
165
|
+
code: ValidationErrorCodes.EmptyTarget,
|
|
166
|
+
errors: {}
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
if (!("properties" in schema)) {
|
|
170
|
+
const resultEither = validateProperty("", what, schema);
|
|
171
|
+
return isLeft(resultEither) ? resultEither : right(what);
|
|
172
|
+
}
|
|
173
|
+
const wholenessError = validateWholeness(what, schema);
|
|
174
|
+
if (wholenessError) {
|
|
175
|
+
return left(wholenessError);
|
|
176
|
+
}
|
|
177
|
+
const errors = {};
|
|
178
|
+
const resultCopy = {};
|
|
179
|
+
for (const propName in what) {
|
|
180
|
+
const resultEither = validateProperty(
|
|
181
|
+
propName,
|
|
182
|
+
what[propName],
|
|
183
|
+
schema.properties[propName],
|
|
184
|
+
options
|
|
185
|
+
);
|
|
186
|
+
if (isLeft(resultEither)) {
|
|
187
|
+
const result = unwrapEither(resultEither);
|
|
188
|
+
errors[propName] = result;
|
|
189
|
+
}
|
|
190
|
+
const parsed = unwrapEither(resultEither);
|
|
191
|
+
if (parsed !== void 0) {
|
|
192
|
+
resultCopy[propName] = parsed;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (Object.keys(errors).length > 0) {
|
|
196
|
+
if (options.throwOnError) {
|
|
197
|
+
const error = new TypeError(ValidationErrorCodes.InvalidProperties);
|
|
198
|
+
Object.assign(error, {
|
|
199
|
+
errors
|
|
200
|
+
});
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
return left(makeValidationError({
|
|
204
|
+
code: ValidationErrorCodes.InvalidProperties,
|
|
205
|
+
errors
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
return right(resultCopy);
|
|
235
209
|
};
|
|
236
|
-
export
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return isLeft(resultEither) ? null : unwrapEither(resultEither);
|
|
210
|
+
export const validateSilently = (what, schema, options = {}) => {
|
|
211
|
+
const resultEither = validate(what, schema, options);
|
|
212
|
+
return isLeft(resultEither) ? null : unwrapEither(resultEither);
|
|
240
213
|
};
|
|
241
|
-
export
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
];
|
|
214
|
+
export const validator = (schema, options = {}) => {
|
|
215
|
+
return [
|
|
216
|
+
{},
|
|
217
|
+
(what) => {
|
|
218
|
+
return validate(what, schema, options);
|
|
219
|
+
}
|
|
220
|
+
];
|
|
249
221
|
};
|
|
250
|
-
export
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
];
|
|
222
|
+
export const silentValidator = (schema, options = {}) => {
|
|
223
|
+
return [
|
|
224
|
+
{},
|
|
225
|
+
(what) => {
|
|
226
|
+
return validateSilently(what, schema, options);
|
|
227
|
+
}
|
|
228
|
+
];
|
|
258
229
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aeriajs/validation",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"description": "## Installation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@aeriajs/common": "^0.0.
|
|
26
|
-
"@aeriajs/types": "^0.0.
|
|
25
|
+
"@aeriajs/common": "^0.0.25",
|
|
26
|
+
"@aeriajs/types": "^0.0.22"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"test": "env TS_NODE_COMPILER_OPTIONS=\"$(cat ../compilerOptions.json)\" mocha -r ts-node/register tests/*.spec.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"lint:fix": "eslint src --fix",
|
|
32
32
|
"build": "pnpm build:cjs && pnpm build:esm",
|
|
33
33
|
"build:cjs": "tsc",
|
|
34
|
-
"build:esm": "
|
|
34
|
+
"build:esm": "esbuild './src/**/*.ts' --outdir=dist --out-extension:.js=.mjs && pnpm build:esm-transform",
|
|
35
35
|
"build:esm-transform": "pnpm -w esm-transform $PWD/dist"
|
|
36
36
|
}
|
|
37
37
|
}
|