@aeriajs/validation 0.0.162 → 0.0.163
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/validate.d.ts +10 -2
- package/dist/validate.js +83 -35
- package/dist/validate.mjs +80 -34
- package/package.json +7 -6
package/dist/validate.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { JsonSchema, Property, InferSchema, Description, PropertyValidationError, ValidationError } from '@aeriajs/types';
|
|
1
|
+
import type { JsonSchema, Property, InferSchema, Description, PropertyValidationError, ValidationError, CollectionModel } from '@aeriajs/types';
|
|
2
|
+
import type { ObjectId } from 'mongodb';
|
|
2
3
|
import { Result } from '@aeriajs/types';
|
|
3
4
|
export type ValidateOptions = {
|
|
4
5
|
tolerateExtraneous?: boolean;
|
|
@@ -7,10 +8,16 @@ export type ValidateOptions = {
|
|
|
7
8
|
coerce?: boolean;
|
|
8
9
|
parentProperty?: Property | Description;
|
|
9
10
|
descriptions?: Record<string, Description>;
|
|
11
|
+
objectIdConstructor?: new (arg: unknown) => ObjectId;
|
|
12
|
+
context?: {
|
|
13
|
+
collections: Record<string, {
|
|
14
|
+
model: CollectionModel<Description>;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
10
17
|
};
|
|
11
18
|
export declare const makeValidationError: <TValidationError extends ValidationError>(error: TValidationError) => TValidationError;
|
|
12
19
|
export declare const validateProperty: <TWhat>(what: TWhat, property: Property | undefined, options?: ValidateOptions) => Result.Either<PropertyValidationError | ValidationError, unknown>;
|
|
13
|
-
export declare const validateRefs: <TWhat>(what: TWhat, property: Property | Description
|
|
20
|
+
export declare const validateRefs: <TWhat>(what: TWhat, property: Property | Description, options?: ValidateOptions) => Promise<Result.Either<PropertyValidationError | ValidationError, unknown>>;
|
|
14
21
|
export declare const validateWholeness: (what: Record<string, unknown>, schema: Omit<JsonSchema, "$id">) => {
|
|
15
22
|
code: "MISSING_PROPERTIES";
|
|
16
23
|
details: {
|
|
@@ -37,6 +44,7 @@ export declare const validateWithRefs: <TWhat, const TJsonSchema extends Propert
|
|
|
37
44
|
readonly error: undefined;
|
|
38
45
|
readonly result: InferSchema<TJsonSchema, {}>;
|
|
39
46
|
}>;
|
|
47
|
+
export declare const validatePropertyWithRefs: <TWhat>(what: TWhat | undefined, property: Property, options?: ValidateOptions) => Promise<Result.Either<PropertyValidationError | ValidationError, unknown>>;
|
|
40
48
|
export declare const validator: <const TJsonSchema extends Property | Description>(schema: TJsonSchema, options?: ValidateOptions) => readonly [InferSchema<TJsonSchema>, <TWhat>(what: TWhat) => {
|
|
41
49
|
readonly _tag: "Error";
|
|
42
50
|
readonly error: PropertyValidationError | ValidationError;
|
package/dist/validate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validator = exports.validateWithRefs = exports.validate = exports.validateWholeness = exports.validateRefs = exports.validateProperty = exports.makeValidationError = void 0;
|
|
3
|
+
exports.validator = exports.validatePropertyWithRefs = exports.validateWithRefs = exports.validate = exports.validateWholeness = exports.validateRefs = exports.validateProperty = exports.makeValidationError = void 0;
|
|
4
4
|
const common_1 = require("@aeriajs/common");
|
|
5
5
|
const types_1 = require("@aeriajs/types");
|
|
6
6
|
const entrypoint_1 = require("@aeriajs/entrypoint");
|
|
@@ -212,53 +212,93 @@ const validateProperty = (what, property, options = {}) => {
|
|
|
212
212
|
};
|
|
213
213
|
exports.validateProperty = validateProperty;
|
|
214
214
|
const validateRefs = async (what, property, options = {}) => {
|
|
215
|
-
if (property) {
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
description = options.descriptions[property.$ref];
|
|
215
|
+
if ('$ref' in property) {
|
|
216
|
+
if (options.checkObjectIds) {
|
|
217
|
+
if (!options.context || !options.objectIdConstructor) {
|
|
218
|
+
throw new Error;
|
|
220
219
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (!collection) {
|
|
224
|
-
throw new Error;
|
|
225
|
-
}
|
|
226
|
-
description = collection.description;
|
|
220
|
+
if (what === null) {
|
|
221
|
+
return types_1.Result.result({});
|
|
227
222
|
}
|
|
228
|
-
if (
|
|
223
|
+
if (!isValidObjectId(String(what))) {
|
|
229
224
|
return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
|
|
230
|
-
expected: '
|
|
225
|
+
expected: 'objectid',
|
|
231
226
|
got: typeof what,
|
|
232
227
|
}));
|
|
233
228
|
}
|
|
234
|
-
|
|
229
|
+
let query;
|
|
230
|
+
if (property.constraints) {
|
|
231
|
+
query = {
|
|
232
|
+
$and: [
|
|
233
|
+
{
|
|
234
|
+
_id: new options.objectIdConstructor(what),
|
|
235
|
+
},
|
|
236
|
+
(0, common_1.convertConditionToQuery)(property.constraints),
|
|
237
|
+
],
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
query = {
|
|
242
|
+
_id: new options.objectIdConstructor(what),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const exists = await options.context.collections[property.$ref].model.findOne(query, {
|
|
246
|
+
projection: {
|
|
247
|
+
_id: 1,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
if (!exists) {
|
|
251
|
+
return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.ReferenceConstraint, {
|
|
252
|
+
expected: 'objectid',
|
|
253
|
+
got: 'invalid_objectid',
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
return types_1.Result.result({});
|
|
257
|
+
}
|
|
258
|
+
let description;
|
|
259
|
+
if (options.descriptions) {
|
|
260
|
+
description = options.descriptions[property.$ref];
|
|
235
261
|
}
|
|
236
|
-
else
|
|
237
|
-
|
|
262
|
+
else {
|
|
263
|
+
const collection = await (0, entrypoint_1.getCollection)(property.$ref);
|
|
264
|
+
if (!collection) {
|
|
238
265
|
throw new Error;
|
|
239
266
|
}
|
|
240
|
-
|
|
241
|
-
const { error } = await (0, exports.validateRefs)(elem, property.items, options);
|
|
242
|
-
if (error) {
|
|
243
|
-
return types_1.Result.error(error);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
267
|
+
description = collection.description;
|
|
246
268
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
269
|
+
if (typeof what !== 'object') {
|
|
270
|
+
return types_1.Result.error(makePropertyError(types_1.PropertyValidationErrorCode.Unmatching, {
|
|
271
|
+
expected: 'object',
|
|
272
|
+
got: typeof what,
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
return (0, exports.validate)(what, description, options);
|
|
276
|
+
}
|
|
277
|
+
else if ('items' in property) {
|
|
278
|
+
if (!Array.isArray(what)) {
|
|
279
|
+
throw new Error;
|
|
280
|
+
}
|
|
281
|
+
for (const elem of what) {
|
|
282
|
+
const { error } = await (0, exports.validateRefs)(elem, property.items, options);
|
|
283
|
+
if (error) {
|
|
284
|
+
return types_1.Result.error(error);
|
|
254
285
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
else if ('properties' in property) {
|
|
289
|
+
const details = {};
|
|
290
|
+
for (const propName in what) {
|
|
291
|
+
const { error } = await (0, exports.validateRefs)(what[propName], property.properties[propName], options);
|
|
292
|
+
if (error) {
|
|
293
|
+
details[propName] = error;
|
|
260
294
|
}
|
|
261
295
|
}
|
|
296
|
+
if (Object.keys(details).length > 0) {
|
|
297
|
+
return types_1.Result.error((0, exports.makeValidationError)({
|
|
298
|
+
code: types_1.ValidationErrorCode.InvalidProperties,
|
|
299
|
+
details,
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
262
302
|
}
|
|
263
303
|
return types_1.Result.result({});
|
|
264
304
|
};
|
|
@@ -337,6 +377,14 @@ const validateWithRefs = async (what, schema, options = {}) => {
|
|
|
337
377
|
return (0, exports.validate)(what, schema, options);
|
|
338
378
|
};
|
|
339
379
|
exports.validateWithRefs = validateWithRefs;
|
|
380
|
+
const validatePropertyWithRefs = async (what, property, options = {}) => {
|
|
381
|
+
const { error: refsError } = await (0, exports.validateRefs)(what, property, options);
|
|
382
|
+
if (refsError) {
|
|
383
|
+
return types_1.Result.error(refsError);
|
|
384
|
+
}
|
|
385
|
+
return (0, exports.validateProperty)(what, property, options);
|
|
386
|
+
};
|
|
387
|
+
exports.validatePropertyWithRefs = validatePropertyWithRefs;
|
|
340
388
|
const validator = (schema, options = {}) => {
|
|
341
389
|
return [
|
|
342
390
|
{},
|
package/dist/validate.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
import { getMissingProperties } from "@aeriajs/common";
|
|
2
|
+
import { convertConditionToQuery, getMissingProperties } from "@aeriajs/common";
|
|
3
3
|
import { Result, ValidationErrorCode, PropertyValidationErrorCode } from "@aeriajs/types";
|
|
4
4
|
import { getCollection } from "@aeriajs/entrypoint";
|
|
5
5
|
const isValidObjectId = (what) => {
|
|
@@ -198,50 +198,89 @@ export const validateProperty = (what, property, options = {}) => {
|
|
|
198
198
|
return Result.result(what);
|
|
199
199
|
};
|
|
200
200
|
export const validateRefs = async (what, property, options = {}) => {
|
|
201
|
-
if (property) {
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
description = options.descriptions[property.$ref];
|
|
206
|
-
} else {
|
|
207
|
-
const collection = await getCollection(property.$ref);
|
|
208
|
-
if (!collection) {
|
|
209
|
-
throw new Error();
|
|
210
|
-
}
|
|
211
|
-
description = collection.description;
|
|
201
|
+
if ("$ref" in property) {
|
|
202
|
+
if (options.checkObjectIds) {
|
|
203
|
+
if (!options.context || !options.objectIdConstructor) {
|
|
204
|
+
throw new Error();
|
|
212
205
|
}
|
|
213
|
-
if (
|
|
206
|
+
if (what === null) {
|
|
207
|
+
return Result.result({});
|
|
208
|
+
}
|
|
209
|
+
if (!isValidObjectId(String(what))) {
|
|
214
210
|
return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
|
|
215
|
-
expected: "
|
|
211
|
+
expected: "objectid",
|
|
216
212
|
got: typeof what
|
|
217
213
|
}));
|
|
218
214
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
215
|
+
let query;
|
|
216
|
+
if (property.constraints) {
|
|
217
|
+
query = {
|
|
218
|
+
$and: [
|
|
219
|
+
{
|
|
220
|
+
_id: new options.objectIdConstructor(what)
|
|
221
|
+
},
|
|
222
|
+
convertConditionToQuery(property.constraints)
|
|
223
|
+
]
|
|
224
|
+
};
|
|
225
|
+
} else {
|
|
226
|
+
query = {
|
|
227
|
+
_id: new options.objectIdConstructor(what)
|
|
228
|
+
};
|
|
223
229
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
return Result.error(error);
|
|
230
|
+
const exists = await options.context.collections[property.$ref].model.findOne(query, {
|
|
231
|
+
projection: {
|
|
232
|
+
_id: 1
|
|
228
233
|
}
|
|
234
|
+
});
|
|
235
|
+
if (!exists) {
|
|
236
|
+
return Result.error(makePropertyError(PropertyValidationErrorCode.ReferenceConstraint, {
|
|
237
|
+
expected: "objectid",
|
|
238
|
+
got: "invalid_objectid"
|
|
239
|
+
}));
|
|
229
240
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
241
|
+
return Result.result({});
|
|
242
|
+
}
|
|
243
|
+
let description;
|
|
244
|
+
if (options.descriptions) {
|
|
245
|
+
description = options.descriptions[property.$ref];
|
|
246
|
+
} else {
|
|
247
|
+
const collection = await getCollection(property.$ref);
|
|
248
|
+
if (!collection) {
|
|
249
|
+
throw new Error();
|
|
237
250
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
251
|
+
description = collection.description;
|
|
252
|
+
}
|
|
253
|
+
if (typeof what !== "object") {
|
|
254
|
+
return Result.error(makePropertyError(PropertyValidationErrorCode.Unmatching, {
|
|
255
|
+
expected: "object",
|
|
256
|
+
got: typeof what
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
return validate(what, description, options);
|
|
260
|
+
} else if ("items" in property) {
|
|
261
|
+
if (!Array.isArray(what)) {
|
|
262
|
+
throw new Error();
|
|
263
|
+
}
|
|
264
|
+
for (const elem of what) {
|
|
265
|
+
const { error } = await validateRefs(elem, property.items, options);
|
|
266
|
+
if (error) {
|
|
267
|
+
return Result.error(error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} else if ("properties" in property) {
|
|
271
|
+
const details = {};
|
|
272
|
+
for (const propName in what) {
|
|
273
|
+
const { error } = await validateRefs(what[propName], property.properties[propName], options);
|
|
274
|
+
if (error) {
|
|
275
|
+
details[propName] = error;
|
|
243
276
|
}
|
|
244
277
|
}
|
|
278
|
+
if (Object.keys(details).length > 0) {
|
|
279
|
+
return Result.error(makeValidationError({
|
|
280
|
+
code: ValidationErrorCode.InvalidProperties,
|
|
281
|
+
details
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
245
284
|
}
|
|
246
285
|
return Result.result({});
|
|
247
286
|
};
|
|
@@ -314,6 +353,13 @@ export const validateWithRefs = async (what, schema, options = {}) => {
|
|
|
314
353
|
}
|
|
315
354
|
return validate(what, schema, options);
|
|
316
355
|
};
|
|
356
|
+
export const validatePropertyWithRefs = async (what, property, options = {}) => {
|
|
357
|
+
const { error: refsError } = await validateRefs(what, property, options);
|
|
358
|
+
if (refsError) {
|
|
359
|
+
return Result.error(refsError);
|
|
360
|
+
}
|
|
361
|
+
return validateProperty(what, property, options);
|
|
362
|
+
};
|
|
317
363
|
export const validator = (schema, options = {}) => {
|
|
318
364
|
return [
|
|
319
365
|
{},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aeriajs/validation",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.163",
|
|
4
4
|
"description": "## Installation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@aeriajs/common": "link:../common",
|
|
26
26
|
"@aeriajs/entrypoint": "link:../entrypoint",
|
|
27
|
-
"@aeriajs/types": "link:../types"
|
|
27
|
+
"@aeriajs/types": "link:../types",
|
|
28
|
+
"mongodb": "^6.16.0"
|
|
28
29
|
},
|
|
29
30
|
"peerDependencies": {
|
|
30
|
-
"@aeriajs/common": "^0.0.
|
|
31
|
-
"@aeriajs/entrypoint": "^0.0.
|
|
32
|
-
"@aeriajs/types": "^0.0.
|
|
33
|
-
"mongodb": "^6.
|
|
31
|
+
"@aeriajs/common": "^0.0.145",
|
|
32
|
+
"@aeriajs/entrypoint": "^0.0.150",
|
|
33
|
+
"@aeriajs/types": "^0.0.127",
|
|
34
|
+
"mongodb": "^6.16.0"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
37
|
"test": "vitest run",
|