@aeriajs/validation 0.0.178 → 0.0.180

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.js CHANGED
@@ -1,17 +1 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./validate.js"), exports);
1
+ export * from './validate.js';
package/dist/validate.js CHANGED
@@ -1,9 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validator = exports.validatePropertyWithRefs = exports.validateWithRefs = exports.validate = exports.validateWholeness = exports.validateRefs = exports.validateProperty = exports.makeValidationError = void 0;
4
- const common_1 = require("@aeriajs/common");
5
- const types_1 = require("@aeriajs/types");
6
- const entrypoint_1 = require("@aeriajs/entrypoint");
1
+ import { convertConditionToQuery, getMissingProperties } from '@aeriajs/common';
2
+ import { Result, ValidationErrorCode, PropertyValidationErrorCode } from '@aeriajs/types';
3
+ import { getCollection } from '@aeriajs/entrypoint';
7
4
  const isValidObjectId = (what) => {
8
5
  return /^[0-9a-f]{24}$/.test(what);
9
6
  };
@@ -38,28 +35,27 @@ const makePropertyError = (type, details) => {
38
35
  details,
39
36
  };
40
37
  };
41
- const makeValidationError = (error) => {
38
+ export const makeValidationError = (error) => {
42
39
  return error;
43
40
  };
44
- exports.makeValidationError = makeValidationError;
45
- const validateProperty = (what, property, options = {}) => {
41
+ export const validateProperty = (what, property, options = {}) => {
46
42
  if (!property) {
47
43
  if (options.parentProperty && 'additionalProperties' in options.parentProperty) {
48
44
  if (options.parentProperty.additionalProperties === true) {
49
- return types_1.Result.result(what);
45
+ return Result.result(what);
50
46
  }
51
- return (0, exports.validateProperty)(what, options.parentProperty.additionalProperties);
47
+ return validateProperty(what, options.parentProperty.additionalProperties);
52
48
  }
53
49
  if (options.tolerateExtraneous) {
54
- return types_1.Result.result(undefined);
50
+ return Result.result(undefined);
55
51
  }
56
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Extraneous));
52
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Extraneous));
57
53
  }
58
54
  if (what === null || what === undefined) {
59
- return types_1.Result.result(what);
55
+ return Result.result(what);
60
56
  }
61
57
  if ('getter' in property) {
62
- return types_1.Result.result(undefined);
58
+ return Result.result(undefined);
63
59
  }
64
60
  const expectedType = getPropertyType(property);
65
61
  const actualType = Array.isArray(what)
@@ -68,15 +64,15 @@ const validateProperty = (what, property, options = {}) => {
68
64
  if (actualType !== expectedType
69
65
  && !(actualType === 'number' && expectedType === 'integer')) {
70
66
  if (expectedType === 'datetime' && what instanceof Date) {
71
- return types_1.Result.result(what);
67
+ return Result.result(what);
72
68
  }
73
69
  if ('$ref' in property) {
74
70
  switch (typeof what) {
75
71
  case 'string': {
76
72
  if (isValidObjectId(what)) {
77
- return types_1.Result.result(what);
73
+ return Result.result(what);
78
74
  }
79
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
75
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
80
76
  expected: expectedType,
81
77
  got: actualType,
82
78
  }));
@@ -87,28 +83,28 @@ const validateProperty = (what, property, options = {}) => {
87
83
  if (expectedType === 'number' && typeof what === 'string') {
88
84
  const coerced = parseFloat(what);
89
85
  if (!isNaN(coerced)) {
90
- return types_1.Result.result(coerced);
86
+ return Result.result(coerced);
91
87
  }
92
88
  }
93
89
  if (expectedType === 'integer' && typeof what === 'string') {
94
90
  const coerced = parseInt(what);
95
91
  if (!isNaN(coerced)) {
96
- return types_1.Result.result(coerced);
92
+ return Result.result(coerced);
97
93
  }
98
94
  }
99
95
  if (expectedType === 'string' && typeof what === 'number') {
100
- return types_1.Result.result(String(what));
96
+ return Result.result(String(what));
101
97
  }
102
98
  if (expectedType === 'datetime' && typeof what === 'string') {
103
- return types_1.Result.result(new Date(what));
99
+ return Result.result(new Date(what));
104
100
  }
105
101
  }
106
102
  if ((options.coerce || options.coerceObjectIds) && options.objectIdConstructor) {
107
103
  if (('$ref' in property || 'format' in property && property.format === 'objectid') && typeof what === 'string') {
108
- return types_1.Result.result(new options.objectIdConstructor(what));
104
+ return Result.result(new options.objectIdConstructor(what));
109
105
  }
110
106
  }
111
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
107
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
112
108
  expected: expectedType,
113
109
  got: actualType,
114
110
  }));
@@ -122,7 +118,7 @@ const validateProperty = (what, property, options = {}) => {
122
118
  throw new Error;
123
119
  }
124
120
  if (!(what instanceof options.objectIdConstructor)) {
125
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.StringConstraint, {
121
+ return Result.error(makePropertyError(PropertyValidationErrorCode.StringConstraint, {
126
122
  expected: 'objectid',
127
123
  got: 'invalid_objectid',
128
124
  }));
@@ -131,14 +127,14 @@ const validateProperty = (what, property, options = {}) => {
131
127
  }
132
128
  default: {
133
129
  if (typeof what !== 'string') {
134
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
130
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
135
131
  expected: expectedType,
136
132
  got: actualType,
137
133
  }));
138
134
  }
139
135
  if ((typeof property.minLength === 'number' && property.minLength > what.length)
140
136
  || (typeof property.maxLength === 'number' && property.maxLength < what.length)) {
141
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.StringConstraint, {
137
+ return Result.error(makePropertyError(PropertyValidationErrorCode.StringConstraint, {
142
138
  expected: 'string',
143
139
  got: 'invalid_string',
144
140
  }));
@@ -149,7 +145,7 @@ const validateProperty = (what, property, options = {}) => {
149
145
  }
150
146
  case 'integer': {
151
147
  if (!Number.isInteger(what)) {
152
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.NumericConstraint, {
148
+ return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
153
149
  expected: 'integer',
154
150
  got: 'invalid_number',
155
151
  }));
@@ -157,7 +153,7 @@ const validateProperty = (what, property, options = {}) => {
157
153
  }
158
154
  case 'number': {
159
155
  if (typeof what !== 'number') {
160
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
156
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
161
157
  expected: expectedType,
162
158
  got: actualType,
163
159
  }));
@@ -166,7 +162,7 @@ const validateProperty = (what, property, options = {}) => {
166
162
  || (typeof property.minimum === 'number' && property.minimum > what)
167
163
  || (typeof property.exclusiveMaximum === 'number' && property.exclusiveMaximum <= what)
168
164
  || (typeof property.exclusiveMinimum === 'number' && property.exclusiveMinimum >= what)) {
169
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.NumericConstraint, {
165
+ return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
170
166
  expected: 'number',
171
167
  got: 'invalid_number',
172
168
  }));
@@ -175,39 +171,39 @@ const validateProperty = (what, property, options = {}) => {
175
171
  }
176
172
  case 'object': {
177
173
  if ('properties' in property) {
178
- return (0, exports.validate)(what, property, options);
174
+ return validate(what, property, options);
179
175
  }
180
176
  switch (typeof property.additionalProperties) {
181
- case 'object': return (0, exports.validate)(what, property.additionalProperties, options);
182
- case 'boolean': return types_1.Result.result(what);
177
+ case 'object': return validate(what, property.additionalProperties, options);
178
+ case 'boolean': return Result.result(what);
183
179
  }
184
180
  }
185
181
  case 'array': {
186
182
  if (!Array.isArray(what)) {
187
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
183
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
188
184
  expected: expectedType,
189
185
  got: actualType,
190
186
  }));
191
187
  }
192
188
  if (property.minItems) {
193
189
  if (what.length < property.minItems) {
194
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.MoreItemsExpected));
190
+ return Result.error(makePropertyError(PropertyValidationErrorCode.MoreItemsExpected));
195
191
  }
196
192
  }
197
193
  if (property.maxItems) {
198
194
  if (what.length > property.maxItems) {
199
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.LessItemsExpected));
195
+ return Result.error(makePropertyError(PropertyValidationErrorCode.LessItemsExpected));
200
196
  }
201
197
  }
202
198
  let i = 0;
203
199
  for (const elem of what) {
204
- const { error } = (0, exports.validateProperty)(elem, property.items, options);
200
+ const { error } = validateProperty(elem, property.items, options);
205
201
  if (error) {
206
202
  if ('code' in error) {
207
203
  continue;
208
204
  }
209
205
  error.index = i;
210
- return types_1.Result.error(error);
206
+ return Result.error(error);
211
207
  }
212
208
  i++;
213
209
  }
@@ -216,7 +212,7 @@ const validateProperty = (what, property, options = {}) => {
216
212
  }
217
213
  else if ('enum' in property) {
218
214
  if (!property.enum.includes(what)) {
219
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.ExtraneousElement, {
215
+ return Result.error(makePropertyError(PropertyValidationErrorCode.ExtraneousElement, {
220
216
  expected: property.enum,
221
217
  got: what,
222
218
  }));
@@ -224,26 +220,25 @@ const validateProperty = (what, property, options = {}) => {
224
220
  }
225
221
  else if ('const' in property) {
226
222
  if (what !== property.const) {
227
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
223
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
228
224
  expected: property.const,
229
225
  got: what,
230
226
  }));
231
227
  }
232
228
  }
233
- return types_1.Result.result(what);
229
+ return Result.result(what);
234
230
  };
235
- exports.validateProperty = validateProperty;
236
- const validateRefs = async (what, property, options = {}) => {
231
+ export const validateRefs = async (what, property, options = {}) => {
237
232
  if ('$ref' in property) {
238
233
  if (options.checkObjectIds) {
239
234
  if (!options.context || !options.objectIdConstructor) {
240
235
  throw new Error;
241
236
  }
242
237
  if (what === null) {
243
- return types_1.Result.result({});
238
+ return Result.result({});
244
239
  }
245
240
  if (!isValidObjectId(String(what))) {
246
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
241
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
247
242
  expected: 'objectid',
248
243
  got: typeof what,
249
244
  }));
@@ -255,7 +250,7 @@ const validateRefs = async (what, property, options = {}) => {
255
250
  {
256
251
  _id: new options.objectIdConstructor(what),
257
252
  },
258
- (0, common_1.convertConditionToQuery)(property.constraints),
253
+ convertConditionToQuery(property.constraints),
259
254
  ],
260
255
  };
261
256
  }
@@ -270,69 +265,71 @@ const validateRefs = async (what, property, options = {}) => {
270
265
  },
271
266
  });
272
267
  if (!exists) {
273
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.ReferenceConstraint, {
268
+ return Result.error(makePropertyError(PropertyValidationErrorCode.ReferenceConstraint, {
274
269
  expected: 'objectid',
275
270
  got: 'invalid_objectid',
276
271
  }));
277
272
  }
278
- return types_1.Result.result({});
273
+ return Result.result({});
279
274
  }
280
275
  let description;
281
276
  if (options.descriptions) {
282
277
  description = options.descriptions[property.$ref];
283
278
  }
284
279
  else {
285
- const collection = await (0, entrypoint_1.getCollection)(property.$ref);
280
+ const collection = await getCollection(property.$ref);
286
281
  if (!collection) {
287
282
  throw new Error;
288
283
  }
289
284
  description = collection.description;
290
285
  }
291
286
  if (typeof what !== 'object') {
292
- return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
287
+ return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
293
288
  expected: 'object',
294
289
  got: typeof what,
295
290
  }));
296
291
  }
297
- return (0, exports.validate)(what, description, options);
292
+ return validate(what, description, options);
298
293
  }
299
294
  else if ('items' in property) {
300
295
  if (!Array.isArray(what)) {
301
296
  throw new Error;
302
297
  }
303
298
  for (const elem of what) {
304
- const { error } = await (0, exports.validateRefs)(elem, property.items, options);
299
+ const { error } = await validateRefs(elem, property.items, options);
305
300
  if (error) {
306
- return types_1.Result.error(error);
301
+ return Result.error(error);
307
302
  }
308
303
  }
309
304
  }
310
305
  else if ('properties' in property) {
311
306
  const details = {};
312
307
  for (const propName in what) {
313
- const { error } = await (0, exports.validateRefs)(what[propName], property.properties[propName], options);
308
+ if (!(propName in property.properties)) {
309
+ continue;
310
+ }
311
+ const { error } = await validateRefs(what[propName], property.properties[propName], options);
314
312
  if (error) {
315
313
  details[propName] = error;
316
314
  }
317
315
  }
318
316
  if (Object.keys(details).length > 0) {
319
- return types_1.Result.error((0, exports.makeValidationError)({
320
- code: types_1.ValidationErrorCode.InvalidProperties,
317
+ return Result.error(makeValidationError({
318
+ code: ValidationErrorCode.InvalidProperties,
321
319
  details,
322
320
  }));
323
321
  }
324
322
  }
325
- return types_1.Result.result({});
323
+ return Result.result({});
326
324
  };
327
- exports.validateRefs = validateRefs;
328
- const validateWholeness = (what, schema) => {
325
+ export const validateWholeness = (what, schema) => {
329
326
  const required = schema.required
330
327
  ? schema.required
331
328
  : Object.keys(schema.properties);
332
- const missingProps = (0, common_1.getMissingProperties)(what, schema, required);
329
+ const missingProps = getMissingProperties(what, schema, required);
333
330
  if (missingProps.length > 0) {
334
- return (0, exports.makeValidationError)({
335
- code: types_1.ValidationErrorCode.MissingProperties,
331
+ return makeValidationError({
332
+ code: ValidationErrorCode.MissingProperties,
336
333
  details: Object.fromEntries(missingProps.map((error) => [
337
334
  error,
338
335
  {
@@ -342,38 +339,37 @@ const validateWholeness = (what, schema) => {
342
339
  });
343
340
  }
344
341
  };
345
- exports.validateWholeness = validateWholeness;
346
- const validate = (what, schema, options = {}) => {
342
+ export const validate = (what, schema, options = {}) => {
347
343
  if (what === undefined) {
348
- return types_1.Result.error((0, exports.makeValidationError)({
349
- code: types_1.ValidationErrorCode.EmptyTarget,
344
+ return Result.error(makeValidationError({
345
+ code: ValidationErrorCode.EmptyTarget,
350
346
  details: {},
351
347
  }));
352
348
  }
353
349
  if (!('properties' in schema)) {
354
- const { error } = (0, exports.validateProperty)(what, schema);
350
+ const { error } = validateProperty(what, schema);
355
351
  if (error) {
356
- return types_1.Result.error(error);
352
+ return Result.error(error);
357
353
  }
358
- return types_1.Result.result(what);
354
+ return Result.result(what);
359
355
  }
360
- const wholenessError = (0, exports.validateWholeness)(what, schema);
356
+ const wholenessError = validateWholeness(what, schema);
361
357
  if (wholenessError) {
362
358
  if (options.throwOnError) {
363
- throw new TypeError(types_1.ValidationErrorCode.MissingProperties);
359
+ throw new TypeError(ValidationErrorCode.MissingProperties);
364
360
  }
365
- return types_1.Result.error(wholenessError);
361
+ return Result.error(wholenessError);
366
362
  }
367
363
  const details = {};
368
364
  const resultCopy = {};
369
365
  for (const propName in what) {
370
- const { error, result: parsed } = (0, exports.validateProperty)(what[propName], schema.properties[propName], {
366
+ const { error, result: parsed } = validateProperty(what[propName], schema.properties[propName], {
371
367
  ...options,
372
368
  parentProperty: schema,
373
369
  });
374
370
  if (error) {
375
371
  if (options.throwOnError) {
376
- throw new TypeError(types_1.ValidationErrorCode.InvalidProperties);
372
+ throw new TypeError(ValidationErrorCode.InvalidProperties);
377
373
  }
378
374
  details[propName] = error;
379
375
  continue;
@@ -383,36 +379,32 @@ const validate = (what, schema, options = {}) => {
383
379
  }
384
380
  }
385
381
  if (Object.keys(details).length > 0) {
386
- return types_1.Result.error((0, exports.makeValidationError)({
387
- code: types_1.ValidationErrorCode.InvalidProperties,
382
+ return Result.error(makeValidationError({
383
+ code: ValidationErrorCode.InvalidProperties,
388
384
  details,
389
385
  }));
390
386
  }
391
- return types_1.Result.result(resultCopy);
387
+ return Result.result(resultCopy);
392
388
  };
393
- exports.validate = validate;
394
- const validateWithRefs = async (what, schema, options = {}) => {
395
- const { error: refsError } = await (0, exports.validateRefs)(what, schema, options);
389
+ export const validateWithRefs = async (what, schema, options = {}) => {
390
+ const { error: refsError } = await validateRefs(what, schema, options);
396
391
  if (refsError) {
397
- return types_1.Result.error(refsError);
392
+ return Result.error(refsError);
398
393
  }
399
- return (0, exports.validate)(what, schema, options);
394
+ return validate(what, schema, options);
400
395
  };
401
- exports.validateWithRefs = validateWithRefs;
402
- const validatePropertyWithRefs = async (what, property, options = {}) => {
403
- const { error: refsError } = await (0, exports.validateRefs)(what, property, options);
396
+ export const validatePropertyWithRefs = async (what, property, options = {}) => {
397
+ const { error: refsError } = await validateRefs(what, property, options);
404
398
  if (refsError) {
405
- return types_1.Result.error(refsError);
399
+ return Result.error(refsError);
406
400
  }
407
- return (0, exports.validateProperty)(what, property, options);
401
+ return validateProperty(what, property, options);
408
402
  };
409
- exports.validatePropertyWithRefs = validatePropertyWithRefs;
410
- const validator = (schema, options = {}) => {
403
+ export const validator = (schema, options = {}) => {
411
404
  return [
412
405
  {},
413
406
  (what) => {
414
- return (0, exports.validate)(what, schema, options);
407
+ return validate(what, schema, options);
415
408
  },
416
409
  ];
417
410
  };
418
- exports.validator = validator;
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@aeriajs/validation",
3
- "version": "0.0.178",
3
+ "type": "module",
4
+ "version": "0.0.180",
4
5
  "description": "## Installation",
5
6
  "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "publishConfig": {
9
9
  "access": "public"
@@ -17,8 +17,7 @@
17
17
  "exports": {
18
18
  ".": {
19
19
  "types": "./dist/index.d.ts",
20
- "import": "./dist/index.mjs",
21
- "require": "./dist/index.js"
20
+ "default": "./dist/index.js"
22
21
  }
23
22
  },
24
23
  "devDependencies": {
@@ -28,9 +27,9 @@
28
27
  "mongodb": "^6.17.0"
29
28
  },
30
29
  "peerDependencies": {
31
- "@aeriajs/common": "^0.0.157",
32
- "@aeriajs/entrypoint": "^0.0.163",
33
- "@aeriajs/types": "^0.0.135",
30
+ "@aeriajs/common": "^0.0.158",
31
+ "@aeriajs/entrypoint": "^0.0.165",
32
+ "@aeriajs/types": "^0.0.136",
34
33
  "mongodb": "^6.17.0"
35
34
  },
36
35
  "scripts": {
@@ -38,9 +37,6 @@
38
37
  "test:typecheck": "tsc -p tsconfig.test.json",
39
38
  "lint": "eslint .",
40
39
  "lint:fix": "eslint . --fix",
41
- "build": "pnpm build:cjs && pnpm build:esm",
42
- "build:cjs": "tsc",
43
- "build:esm": "esbuild './src/**/*.ts' --outdir=dist --out-extension:.js=.mjs && pnpm build:esm-transform",
44
- "build:esm-transform": "pnpm -w esm-transform $PWD/dist"
40
+ "build": "tsc"
45
41
  }
46
42
  }
package/dist/index.mjs DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- export * from "./validate.mjs";
package/dist/validate.mjs DELETED
@@ -1,393 +0,0 @@
1
- "use strict";
2
- import { convertConditionToQuery, getMissingProperties } from "@aeriajs/common";
3
- import { Result, ValidationErrorCode, PropertyValidationErrorCode } from "@aeriajs/types";
4
- import { getCollection } from "@aeriajs/entrypoint";
5
- const isValidObjectId = (what) => {
6
- return /^[0-9a-f]{24}$/.test(what);
7
- };
8
- const getPropertyType = (property) => {
9
- if ("type" in property) {
10
- if ("format" in property && property.format) {
11
- switch (property.format) {
12
- case "date":
13
- case "date-time":
14
- return "datetime";
15
- case "objectid":
16
- return "object";
17
- }
18
- }
19
- return property.type;
20
- }
21
- if ("enum" in property) {
22
- return typeof property.enum[0];
23
- }
24
- if ("const" in property) {
25
- return typeof property.const;
26
- }
27
- if ("properties" in property || "additionalProperties" in property || "$ref" in property) {
28
- return "object";
29
- }
30
- };
31
- const makePropertyError = (type, details) => {
32
- return {
33
- type,
34
- details
35
- };
36
- };
37
- export const makeValidationError = (error) => {
38
- return error;
39
- };
40
- export const validateProperty = (what, property, options = {}) => {
41
- if (!property) {
42
- if (options.parentProperty && "additionalProperties" in options.parentProperty) {
43
- if (options.parentProperty.additionalProperties === true) {
44
- return Result.result(what);
45
- }
46
- return validateProperty(what, options.parentProperty.additionalProperties);
47
- }
48
- if (options.tolerateExtraneous) {
49
- return Result.result(void 0);
50
- }
51
- return Result.error(makePropertyError(PropertyValidationErrorCode.Extraneous));
52
- }
53
- if (what === null || what === void 0) {
54
- return Result.result(what);
55
- }
56
- if ("getter" in property) {
57
- return Result.result(void 0);
58
- }
59
- const expectedType = getPropertyType(property);
60
- const actualType = Array.isArray(what) ? "array" : typeof what;
61
- if (actualType !== expectedType && !(actualType === "number" && expectedType === "integer")) {
62
- if (expectedType === "datetime" && what instanceof Date) {
63
- return Result.result(what);
64
- }
65
- if ("$ref" in property) {
66
- switch (typeof what) {
67
- case "string": {
68
- if (isValidObjectId(what)) {
69
- return Result.result(what);
70
- }
71
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
72
- expected: expectedType,
73
- got: actualType
74
- }));
75
- }
76
- }
77
- }
78
- if (options.coerce) {
79
- if (expectedType === "number" && typeof what === "string") {
80
- const coerced = parseFloat(what);
81
- if (!isNaN(coerced)) {
82
- return Result.result(coerced);
83
- }
84
- }
85
- if (expectedType === "integer" && typeof what === "string") {
86
- const coerced = parseInt(what);
87
- if (!isNaN(coerced)) {
88
- return Result.result(coerced);
89
- }
90
- }
91
- if (expectedType === "string" && typeof what === "number") {
92
- return Result.result(String(what));
93
- }
94
- if (expectedType === "datetime" && typeof what === "string") {
95
- return Result.result(new Date(what));
96
- }
97
- }
98
- if ((options.coerce || options.coerceObjectIds) && options.objectIdConstructor) {
99
- if (("$ref" in property || "format" in property && property.format === "objectid") && typeof what === "string") {
100
- return Result.result(new options.objectIdConstructor(what));
101
- }
102
- }
103
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
104
- expected: expectedType,
105
- got: actualType
106
- }));
107
- }
108
- if ("type" in property) {
109
- switch (property.type) {
110
- case "string": {
111
- switch (property.format) {
112
- case "objectid": {
113
- if (!options.objectIdConstructor) {
114
- throw new Error();
115
- }
116
- if (!(what instanceof options.objectIdConstructor)) {
117
- return Result.error(makePropertyError(PropertyValidationErrorCode.StringConstraint, {
118
- expected: "objectid",
119
- got: "invalid_objectid"
120
- }));
121
- }
122
- break;
123
- }
124
- default: {
125
- if (typeof what !== "string") {
126
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
127
- expected: expectedType,
128
- got: actualType
129
- }));
130
- }
131
- if (typeof property.minLength === "number" && property.minLength > what.length || typeof property.maxLength === "number" && property.maxLength < what.length) {
132
- return Result.error(makePropertyError(PropertyValidationErrorCode.StringConstraint, {
133
- expected: "string",
134
- got: "invalid_string"
135
- }));
136
- }
137
- }
138
- }
139
- break;
140
- }
141
- case "integer": {
142
- if (!Number.isInteger(what)) {
143
- return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
144
- expected: "integer",
145
- got: "invalid_number"
146
- }));
147
- }
148
- }
149
- case "number": {
150
- if (typeof what !== "number") {
151
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
152
- expected: expectedType,
153
- got: actualType
154
- }));
155
- }
156
- if (typeof property.maximum === "number" && property.maximum < what || typeof property.minimum === "number" && property.minimum > what || typeof property.exclusiveMaximum === "number" && property.exclusiveMaximum <= what || typeof property.exclusiveMinimum === "number" && property.exclusiveMinimum >= what) {
157
- return Result.error(makePropertyError(PropertyValidationErrorCode.NumericConstraint, {
158
- expected: "number",
159
- got: "invalid_number"
160
- }));
161
- }
162
- break;
163
- }
164
- case "object": {
165
- if ("properties" in property) {
166
- return validate(what, property, options);
167
- }
168
- switch (typeof property.additionalProperties) {
169
- case "object":
170
- return validate(what, property.additionalProperties, options);
171
- case "boolean":
172
- return Result.result(what);
173
- }
174
- }
175
- case "array": {
176
- if (!Array.isArray(what)) {
177
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
178
- expected: expectedType,
179
- got: actualType
180
- }));
181
- }
182
- if (property.minItems) {
183
- if (what.length < property.minItems) {
184
- return Result.error(makePropertyError(PropertyValidationErrorCode.MoreItemsExpected));
185
- }
186
- }
187
- if (property.maxItems) {
188
- if (what.length > property.maxItems) {
189
- return Result.error(makePropertyError(PropertyValidationErrorCode.LessItemsExpected));
190
- }
191
- }
192
- let i = 0;
193
- for (const elem of what) {
194
- const { error } = validateProperty(elem, property.items, options);
195
- if (error) {
196
- if ("code" in error) {
197
- continue;
198
- }
199
- error.index = i;
200
- return Result.error(error);
201
- }
202
- i++;
203
- }
204
- }
205
- }
206
- } else if ("enum" in property) {
207
- if (!property.enum.includes(what)) {
208
- return Result.error(makePropertyError(PropertyValidationErrorCode.ExtraneousElement, {
209
- expected: property.enum,
210
- got: what
211
- }));
212
- }
213
- } else if ("const" in property) {
214
- if (what !== property.const) {
215
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
216
- expected: property.const,
217
- got: what
218
- }));
219
- }
220
- }
221
- return Result.result(what);
222
- };
223
- export const validateRefs = async (what, property, options = {}) => {
224
- if ("$ref" in property) {
225
- if (options.checkObjectIds) {
226
- if (!options.context || !options.objectIdConstructor) {
227
- throw new Error();
228
- }
229
- if (what === null) {
230
- return Result.result({});
231
- }
232
- if (!isValidObjectId(String(what))) {
233
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
234
- expected: "objectid",
235
- got: typeof what
236
- }));
237
- }
238
- let query;
239
- if (property.constraints) {
240
- query = {
241
- $and: [
242
- {
243
- _id: new options.objectIdConstructor(what)
244
- },
245
- convertConditionToQuery(property.constraints)
246
- ]
247
- };
248
- } else {
249
- query = {
250
- _id: new options.objectIdConstructor(what)
251
- };
252
- }
253
- const exists = await options.context.collections[property.$ref].model.findOne(query, {
254
- projection: {
255
- _id: 1
256
- }
257
- });
258
- if (!exists) {
259
- return Result.error(makePropertyError(PropertyValidationErrorCode.ReferenceConstraint, {
260
- expected: "objectid",
261
- got: "invalid_objectid"
262
- }));
263
- }
264
- return Result.result({});
265
- }
266
- let description;
267
- if (options.descriptions) {
268
- description = options.descriptions[property.$ref];
269
- } else {
270
- const collection = await getCollection(property.$ref);
271
- if (!collection) {
272
- throw new Error();
273
- }
274
- description = collection.description;
275
- }
276
- if (typeof what !== "object") {
277
- return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
278
- expected: "object",
279
- got: typeof what
280
- }));
281
- }
282
- return validate(what, description, options);
283
- } else if ("items" in property) {
284
- if (!Array.isArray(what)) {
285
- throw new Error();
286
- }
287
- for (const elem of what) {
288
- const { error } = await validateRefs(elem, property.items, options);
289
- if (error) {
290
- return Result.error(error);
291
- }
292
- }
293
- } else if ("properties" in property) {
294
- const details = {};
295
- for (const propName in what) {
296
- const { error } = await validateRefs(what[propName], property.properties[propName], options);
297
- if (error) {
298
- details[propName] = error;
299
- }
300
- }
301
- if (Object.keys(details).length > 0) {
302
- return Result.error(makeValidationError({
303
- code: ValidationErrorCode.InvalidProperties,
304
- details
305
- }));
306
- }
307
- }
308
- return Result.result({});
309
- };
310
- export const validateWholeness = (what, schema) => {
311
- const required = schema.required ? schema.required : Object.keys(schema.properties);
312
- const missingProps = getMissingProperties(what, schema, required);
313
- if (missingProps.length > 0) {
314
- return makeValidationError({
315
- code: ValidationErrorCode.MissingProperties,
316
- details: Object.fromEntries(missingProps.map((error) => [
317
- error,
318
- {
319
- type: "missing"
320
- }
321
- ]))
322
- });
323
- }
324
- };
325
- export const validate = (what, schema, options = {}) => {
326
- if (what === void 0) {
327
- return Result.error(makeValidationError({
328
- code: ValidationErrorCode.EmptyTarget,
329
- details: {}
330
- }));
331
- }
332
- if (!("properties" in schema)) {
333
- const { error } = validateProperty(what, schema);
334
- if (error) {
335
- return Result.error(error);
336
- }
337
- return Result.result(what);
338
- }
339
- const wholenessError = validateWholeness(what, schema);
340
- if (wholenessError) {
341
- if (options.throwOnError) {
342
- throw new TypeError(ValidationErrorCode.MissingProperties);
343
- }
344
- return Result.error(wholenessError);
345
- }
346
- const details = {};
347
- const resultCopy = {};
348
- for (const propName in what) {
349
- const { error, result: parsed } = validateProperty(what[propName], schema.properties[propName], {
350
- ...options,
351
- parentProperty: schema
352
- });
353
- if (error) {
354
- if (options.throwOnError) {
355
- throw new TypeError(ValidationErrorCode.InvalidProperties);
356
- }
357
- details[propName] = error;
358
- continue;
359
- }
360
- if (parsed !== void 0) {
361
- resultCopy[propName] = parsed;
362
- }
363
- }
364
- if (Object.keys(details).length > 0) {
365
- return Result.error(makeValidationError({
366
- code: ValidationErrorCode.InvalidProperties,
367
- details
368
- }));
369
- }
370
- return Result.result(resultCopy);
371
- };
372
- export const validateWithRefs = async (what, schema, options = {}) => {
373
- const { error: refsError } = await validateRefs(what, schema, options);
374
- if (refsError) {
375
- return Result.error(refsError);
376
- }
377
- return validate(what, schema, options);
378
- };
379
- export const validatePropertyWithRefs = async (what, property, options = {}) => {
380
- const { error: refsError } = await validateRefs(what, property, options);
381
- if (refsError) {
382
- return Result.error(refsError);
383
- }
384
- return validateProperty(what, property, options);
385
- };
386
- export const validator = (schema, options = {}) => {
387
- return [
388
- {},
389
- (what) => {
390
- return validate(what, schema, options);
391
- }
392
- ];
393
- };