@aeriajs/validation 0.0.123 → 0.0.125

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.
@@ -2,6 +2,7 @@ import type { JsonSchema, Property, InferSchema, Description, PropertyValidation
2
2
  import { Result } from '@aeriajs/types';
3
3
  import { ValidationErrorCode } from '@aeriajs/types';
4
4
  export type ValidateOptions = {
5
+ tolerateExtraneous?: boolean;
5
6
  filterOutExtraneous?: boolean;
6
7
  throwOnError?: boolean;
7
8
  coerce?: boolean;
package/dist/validate.js CHANGED
@@ -12,11 +12,10 @@ const getValueType = (value) => {
12
12
  const getPropertyType = (property) => {
13
13
  if ('type' in property) {
14
14
  if ('format' in property && property.format) {
15
- if ([
16
- 'date',
17
- 'date-time',
18
- ].includes(property.format)) {
19
- return 'datetime';
15
+ switch (property.format) {
16
+ case 'date':
17
+ case 'date-time':
18
+ return 'datetime';
20
19
  }
21
20
  }
22
21
  return property.type;
@@ -24,6 +23,9 @@ const getPropertyType = (property) => {
24
23
  if ('enum' in property) {
25
24
  return typeof property.enum[0];
26
25
  }
26
+ if ('const' in property) {
27
+ return typeof property.const;
28
+ }
27
29
  if ('$ref' in property
28
30
  || 'properties' in property
29
31
  || 'additionalProperties' in property) {
@@ -41,54 +43,38 @@ const makeValidationError = (error) => {
41
43
  };
42
44
  exports.makeValidationError = makeValidationError;
43
45
  const validateProperty = (propName, what, property, options = {}) => {
44
- const { filterOutExtraneous, coerce } = options;
45
46
  if (!property) {
46
47
  if (options.parentProperty && 'additionalProperties' in options.parentProperty && options.parentProperty.additionalProperties) {
47
- const extraneous = options.parentProperty.additionalProperties;
48
- if (typeof extraneous === 'boolean' || Object.keys(extraneous).includes(propName)) {
49
- if (filterOutExtraneous) {
50
- return types_1.Result.result(undefined);
51
- }
48
+ if (options.filterOutExtraneous) {
49
+ return types_1.Result.result(undefined);
52
50
  }
53
51
  return types_1.Result.result(what);
54
52
  }
53
+ if (options.tolerateExtraneous) {
54
+ return types_1.Result.result(undefined);
55
+ }
55
56
  return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.Extraneous));
56
57
  }
57
58
  if (what === null || what === undefined) {
58
59
  return types_1.Result.result(what);
59
60
  }
60
- if ('properties' in property) {
61
- return (0, exports.validate)(what, property, options);
62
- }
63
- if ('const' in property) {
64
- if (what !== property.const) {
65
- return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.Unmatching, {
66
- expected: property.const,
67
- got: what,
68
- }));
69
- }
70
- return types_1.Result.result(what);
71
- }
72
- if ('enum' in property && property.enum.length === 0) {
73
- return types_1.Result.result(what);
74
- }
75
61
  if ('getter' in property) {
76
62
  return types_1.Result.result(undefined);
77
63
  }
78
64
  const expectedType = getPropertyType(property);
79
65
  const actualType = getValueType(what);
80
66
  if (actualType !== expectedType
81
- && !('items' in property && actualType === 'array')
67
+ && !(('items' in property || 'enum' in property) && actualType === 'array')
82
68
  && !(actualType === 'number' && expectedType === 'integer')) {
83
69
  if (expectedType === 'datetime' && what instanceof Date) {
84
70
  return types_1.Result.result(what);
85
71
  }
86
72
  if ('$ref' in property && typeof what === 'string') {
87
- if (/^[0-9a-fA-F]{24}$/.test(what)) {
73
+ if (/^[0-9a-f]{24}$/.test(what)) {
88
74
  return types_1.Result.result(what);
89
75
  }
90
76
  }
91
- if (coerce) {
77
+ if (options.coerce) {
92
78
  if (expectedType === 'number' && typeof what === 'string') {
93
79
  const coerced = parseFloat(what);
94
80
  if (!isNaN(coerced)) {
@@ -110,6 +96,21 @@ const validateProperty = (propName, what, property, options = {}) => {
110
96
  got: actualType,
111
97
  }));
112
98
  }
99
+ if ('properties' in property) {
100
+ return (0, exports.validate)(what, property, options);
101
+ }
102
+ if ('enum' in property && property.enum.length === 0) {
103
+ return types_1.Result.result(what);
104
+ }
105
+ if ('const' in property) {
106
+ if (what !== property.const) {
107
+ return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.Unmatching, {
108
+ expected: property.const,
109
+ got: what,
110
+ }));
111
+ }
112
+ return types_1.Result.result(what);
113
+ }
113
114
  if ('items' in property) {
114
115
  if (!Array.isArray(what)) {
115
116
  return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.Unmatching, {
@@ -141,29 +142,32 @@ const validateProperty = (propName, what, property, options = {}) => {
141
142
  }
142
143
  }
143
144
  else if ('type' in property) {
144
- if (property.type === 'integer') {
145
- if (!Number.isInteger(what)) {
146
- return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.NumericConstraint, {
147
- expected: 'integer',
148
- got: 'invalid_number',
149
- }));
150
- }
151
- }
152
- if (property.type === 'integer' || property.type === 'number') {
153
- if (typeof what !== 'number') {
154
- return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.Unmatching, {
155
- expected: expectedType,
156
- got: actualType,
157
- }));
158
- }
159
- if ((property.maximum && property.maximum < what)
160
- || (property.minimum && property.minimum > what)
161
- || (property.exclusiveMaximum && property.exclusiveMaximum <= what)
162
- || (property.exclusiveMinimum && property.exclusiveMinimum >= what)) {
163
- return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.NumericConstraint, {
164
- expected: 'number',
165
- got: 'invalid_number',
166
- }));
145
+ switch (property.type) {
146
+ case 'number':
147
+ case 'integer': {
148
+ if (typeof what !== 'number') {
149
+ return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.Unmatching, {
150
+ expected: expectedType,
151
+ got: actualType,
152
+ }));
153
+ }
154
+ if (property.type === 'integer') {
155
+ if (!Number.isInteger(what)) {
156
+ return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.NumericConstraint, {
157
+ expected: 'integer',
158
+ got: 'invalid_number',
159
+ }));
160
+ }
161
+ }
162
+ if ((property.maximum && property.maximum < what)
163
+ || (property.minimum && property.minimum > what)
164
+ || (property.exclusiveMaximum && property.exclusiveMaximum <= what)
165
+ || (property.exclusiveMinimum && property.exclusiveMinimum >= what)) {
166
+ return types_1.Result.error(makePropertyError(types_2.PropertyValidationErrorCode.NumericConstraint, {
167
+ expected: 'number',
168
+ got: 'invalid_number',
169
+ }));
170
+ }
167
171
  }
168
172
  }
169
173
  }
@@ -212,6 +216,9 @@ const validate = (what, schema, options = {}) => {
212
216
  }
213
217
  const wholenessError = (0, exports.validateWholeness)(what, schema);
214
218
  if (wholenessError) {
219
+ if (options.throwOnError) {
220
+ throw new Error(types_2.ValidationErrorCode.MissingProperties);
221
+ }
215
222
  return types_1.Result.error(wholenessError);
216
223
  }
217
224
  const errors = {};
package/dist/validate.mjs CHANGED
@@ -8,11 +8,10 @@ const getValueType = (value) => {
8
8
  const getPropertyType = (property) => {
9
9
  if ("type" in property) {
10
10
  if ("format" in property && property.format) {
11
- if ([
12
- "date",
13
- "date-time"
14
- ].includes(property.format)) {
15
- return "datetime";
11
+ switch (property.format) {
12
+ case "date":
13
+ case "date-time":
14
+ return "datetime";
16
15
  }
17
16
  }
18
17
  return property.type;
@@ -20,6 +19,9 @@ const getPropertyType = (property) => {
20
19
  if ("enum" in property) {
21
20
  return typeof property.enum[0];
22
21
  }
22
+ if ("const" in property) {
23
+ return typeof property.const;
24
+ }
23
25
  if ("$ref" in property || "properties" in property || "additionalProperties" in property) {
24
26
  return "object";
25
27
  }
@@ -34,52 +36,36 @@ export const makeValidationError = (error) => {
34
36
  return error;
35
37
  };
36
38
  export const validateProperty = (propName, what, property, options = {}) => {
37
- const { filterOutExtraneous, coerce } = options;
38
39
  if (!property) {
39
40
  if (options.parentProperty && "additionalProperties" in options.parentProperty && options.parentProperty.additionalProperties) {
40
- const extraneous = options.parentProperty.additionalProperties;
41
- if (typeof extraneous === "boolean" || Object.keys(extraneous).includes(propName)) {
42
- if (filterOutExtraneous) {
43
- return Result.result(void 0);
44
- }
41
+ if (options.filterOutExtraneous) {
42
+ return Result.result(void 0);
45
43
  }
46
44
  return Result.result(what);
47
45
  }
46
+ if (options.tolerateExtraneous) {
47
+ return Result.result(void 0);
48
+ }
48
49
  return Result.error(makePropertyError(PropertyValidationErrorCode.Extraneous));
49
50
  }
50
51
  if (what === null || what === void 0) {
51
52
  return Result.result(what);
52
53
  }
53
- if ("properties" in property) {
54
- return validate(what, property, options);
55
- }
56
- if ("const" in property) {
57
- if (what !== property.const) {
58
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
59
- expected: property.const,
60
- got: what
61
- }));
62
- }
63
- return Result.result(what);
64
- }
65
- if ("enum" in property && property.enum.length === 0) {
66
- return Result.result(what);
67
- }
68
54
  if ("getter" in property) {
69
55
  return Result.result(void 0);
70
56
  }
71
57
  const expectedType = getPropertyType(property);
72
58
  const actualType = getValueType(what);
73
- if (actualType !== expectedType && !("items" in property && actualType === "array") && !(actualType === "number" && expectedType === "integer")) {
59
+ if (actualType !== expectedType && !(("items" in property || "enum" in property) && actualType === "array") && !(actualType === "number" && expectedType === "integer")) {
74
60
  if (expectedType === "datetime" && what instanceof Date) {
75
61
  return Result.result(what);
76
62
  }
77
63
  if ("$ref" in property && typeof what === "string") {
78
- if (/^[0-9a-fA-F]{24}$/.test(what)) {
64
+ if (/^[0-9a-f]{24}$/.test(what)) {
79
65
  return Result.result(what);
80
66
  }
81
67
  }
82
- if (coerce) {
68
+ if (options.coerce) {
83
69
  if (expectedType === "number" && typeof what === "string") {
84
70
  const coerced = parseFloat(what);
85
71
  if (!isNaN(coerced)) {
@@ -101,6 +87,21 @@ export const validateProperty = (propName, what, property, options = {}) => {
101
87
  got: actualType
102
88
  }));
103
89
  }
90
+ if ("properties" in property) {
91
+ return validate(what, property, options);
92
+ }
93
+ if ("enum" in property && property.enum.length === 0) {
94
+ return Result.result(what);
95
+ }
96
+ if ("const" in property) {
97
+ if (what !== property.const) {
98
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
99
+ expected: property.const,
100
+ got: what
101
+ }));
102
+ }
103
+ return Result.result(what);
104
+ }
104
105
  if ("items" in property) {
105
106
  if (!Array.isArray(what)) {
106
107
  return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
@@ -131,26 +132,29 @@ export const validateProperty = (propName, what, property, options = {}) => {
131
132
  i++;
132
133
  }
133
134
  } else if ("type" in property) {
134
- if (property.type === "integer") {
135
- if (!Number.isInteger(what)) {
136
- return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
137
- expected: "integer",
138
- got: "invalid_number"
139
- }));
140
- }
141
- }
142
- if (property.type === "integer" || property.type === "number") {
143
- if (typeof what !== "number") {
144
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
145
- expected: expectedType,
146
- got: actualType
147
- }));
148
- }
149
- if (property.maximum && property.maximum < what || property.minimum && property.minimum > what || property.exclusiveMaximum && property.exclusiveMaximum <= what || property.exclusiveMinimum && property.exclusiveMinimum >= what) {
150
- return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
151
- expected: "number",
152
- got: "invalid_number"
153
- }));
135
+ switch (property.type) {
136
+ case "number":
137
+ case "integer": {
138
+ if (typeof what !== "number") {
139
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
140
+ expected: expectedType,
141
+ got: actualType
142
+ }));
143
+ }
144
+ if (property.type === "integer") {
145
+ if (!Number.isInteger(what)) {
146
+ return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
147
+ expected: "integer",
148
+ got: "invalid_number"
149
+ }));
150
+ }
151
+ }
152
+ if (property.maximum && property.maximum < what || property.minimum && property.minimum > what || property.exclusiveMaximum && property.exclusiveMaximum <= what || property.exclusiveMinimum && property.exclusiveMinimum >= what) {
153
+ return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
154
+ expected: "number",
155
+ got: "invalid_number"
156
+ }));
157
+ }
154
158
  }
155
159
  }
156
160
  } else if ("enum" in property) {
@@ -191,6 +195,9 @@ export const validate = (what, schema, options = {}) => {
191
195
  }
192
196
  const wholenessError = validateWholeness(what, schema);
193
197
  if (wholenessError) {
198
+ if (options.throwOnError) {
199
+ throw new Error(ValidationErrorCode.MissingProperties);
200
+ }
194
201
  return Result.error(wholenessError);
195
202
  }
196
203
  const errors = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/validation",
3
- "version": "0.0.123",
3
+ "version": "0.0.125",
4
4
  "description": "## Installation",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -26,7 +26,7 @@
26
26
  "@aeriajs/types": "link:../types"
27
27
  },
28
28
  "peerDependencies": {
29
- "@aeriajs/common": "^0.0.119",
29
+ "@aeriajs/common": "^0.0.120",
30
30
  "@aeriajs/types": "^0.0.102",
31
31
  "mongodb": "^6.5.0"
32
32
  },