@tsed/ajv 6.87.2 → 6.90.0

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.
Files changed (72) hide show
  1. package/lib/{decorators → cjs/decorators}/formats.d.ts +0 -0
  2. package/lib/cjs/decorators/formats.js +22 -0
  3. package/lib/cjs/decorators/formats.js.map +1 -0
  4. package/lib/{decorators → cjs/decorators}/keyword.d.ts +0 -0
  5. package/lib/cjs/decorators/keyword.js +21 -0
  6. package/lib/cjs/decorators/keyword.js.map +1 -0
  7. package/lib/{errors → cjs/errors}/AjvValidationError.d.ts +0 -0
  8. package/lib/cjs/errors/AjvValidationError.js +13 -0
  9. package/lib/cjs/errors/AjvValidationError.js.map +1 -0
  10. package/lib/{index.d.ts → cjs/index.d.ts} +0 -0
  11. package/lib/cjs/index.js +11 -0
  12. package/lib/cjs/index.js.map +1 -0
  13. package/lib/{interfaces → cjs/interfaces}/FormatsMethods.d.ts +0 -0
  14. package/lib/cjs/interfaces/FormatsMethods.js +3 -0
  15. package/lib/cjs/interfaces/FormatsMethods.js.map +1 -0
  16. package/lib/{interfaces → cjs/interfaces}/IAjvSettings.d.ts +0 -0
  17. package/lib/cjs/interfaces/IAjvSettings.js +3 -0
  18. package/lib/cjs/interfaces/IAjvSettings.js.map +1 -0
  19. package/lib/{interfaces → cjs/interfaces}/KeywordMethods.d.ts +0 -0
  20. package/lib/cjs/interfaces/KeywordMethods.js +3 -0
  21. package/lib/cjs/interfaces/KeywordMethods.js.map +1 -0
  22. package/lib/{services → cjs/services}/Ajv.d.ts +0 -0
  23. package/lib/cjs/services/Ajv.js +68 -0
  24. package/lib/cjs/services/Ajv.js.map +1 -0
  25. package/lib/{services → cjs/services}/AjvService.d.ts +0 -0
  26. package/lib/cjs/services/AjvService.js +91 -0
  27. package/lib/cjs/services/AjvService.js.map +1 -0
  28. package/lib/{utils → cjs/utils}/defaultErrorFormatter.d.ts +0 -0
  29. package/lib/cjs/utils/defaultErrorFormatter.js +24 -0
  30. package/lib/cjs/utils/defaultErrorFormatter.js.map +1 -0
  31. package/lib/{utils → cjs/utils}/getPath.d.ts +0 -0
  32. package/lib/cjs/utils/getPath.js +9 -0
  33. package/lib/cjs/utils/getPath.js.map +1 -0
  34. package/lib/esm/decorators/formats.js +18 -0
  35. package/lib/esm/decorators/formats.js.map +1 -0
  36. package/lib/esm/decorators/keyword.js +17 -0
  37. package/lib/esm/decorators/keyword.js.map +1 -0
  38. package/lib/esm/errors/AjvValidationError.js +9 -0
  39. package/lib/esm/errors/AjvValidationError.js.map +1 -0
  40. package/lib/esm/index.js +8 -0
  41. package/lib/esm/index.js.map +1 -0
  42. package/lib/esm/interfaces/FormatsMethods.js +2 -0
  43. package/lib/esm/interfaces/FormatsMethods.js.map +1 -0
  44. package/lib/esm/interfaces/IAjvSettings.js +2 -0
  45. package/lib/esm/interfaces/IAjvSettings.js.map +1 -0
  46. package/lib/esm/interfaces/KeywordMethods.js +2 -0
  47. package/lib/esm/interfaces/KeywordMethods.js.map +1 -0
  48. package/lib/esm/services/Ajv.js +65 -0
  49. package/lib/esm/services/Ajv.js.map +1 -0
  50. package/lib/esm/services/AjvService.js +88 -0
  51. package/lib/esm/services/AjvService.js.map +1 -0
  52. package/lib/esm/utils/defaultErrorFormatter.js +20 -0
  53. package/lib/esm/utils/defaultErrorFormatter.js.map +1 -0
  54. package/lib/esm/utils/getPath.js +5 -0
  55. package/lib/esm/utils/getPath.js.map +1 -0
  56. package/lib/types/decorators/formats.d.ts +10 -0
  57. package/lib/types/decorators/keyword.d.ts +12 -0
  58. package/lib/types/errors/AjvValidationError.d.ts +6 -0
  59. package/lib/types/index.d.ts +15 -0
  60. package/lib/types/interfaces/FormatsMethods.d.ts +4 -0
  61. package/lib/types/interfaces/IAjvSettings.d.ts +19 -0
  62. package/lib/types/interfaces/KeywordMethods.d.ts +23 -0
  63. package/lib/types/services/Ajv.d.ts +1 -0
  64. package/lib/types/services/AjvService.d.ts +19 -0
  65. package/lib/types/utils/defaultErrorFormatter.d.ts +4 -0
  66. package/lib/types/utils/getPath.d.ts +1 -0
  67. package/package.json +18 -15
  68. package/tsconfig.compile.esm.json +23 -0
  69. package/lib/index.js +0 -302
  70. package/lib/index.js.map +0 -1
  71. package/lib/index.modern.js +0 -295
  72. package/lib/index.modern.js.map +0 -1
@@ -0,0 +1,88 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { deepClone, getValue, nameOf, prototypeOf, setValue } from "@tsed/core";
3
+ import { Constant, Inject, Injectable } from "@tsed/di";
4
+ import { getJsonSchema, JsonEntityStore, JsonSchema } from "@tsed/schema";
5
+ import Ajv from "ajv";
6
+ import { AjvValidationError } from "../errors/AjvValidationError";
7
+ import { defaultErrorFormatter } from "../utils/defaultErrorFormatter";
8
+ import "./Ajv";
9
+ import { getPath } from "../utils/getPath";
10
+ let AjvService = class AjvService {
11
+ async validate(value, options) {
12
+ let { schema, type, collectionType, ...additionalOptions } = this.mapOptions(options);
13
+ schema = schema || getJsonSchema(type, { ...additionalOptions, customKeys: true });
14
+ if (schema) {
15
+ const localValue = deepClone(value);
16
+ const valid = await this.ajv.validate(schema, localValue);
17
+ if (!valid) {
18
+ throw this.mapErrors(this.ajv.errors || [], {
19
+ type,
20
+ collectionType,
21
+ async: true,
22
+ value: localValue
23
+ });
24
+ }
25
+ }
26
+ return value;
27
+ }
28
+ mapOptions(options) {
29
+ if (options instanceof JsonSchema) {
30
+ return {
31
+ schema: options.toJSON({ customKeys: true })
32
+ };
33
+ }
34
+ return options;
35
+ }
36
+ mapErrors(errors, options) {
37
+ const { type, collectionType, value } = options;
38
+ const message = errors
39
+ .map((error) => {
40
+ if (collectionType) {
41
+ error.collectionName = nameOf(collectionType);
42
+ }
43
+ const dataPath = getPath(error);
44
+ if (!error.data) {
45
+ if (dataPath) {
46
+ error.data = getValue(value, dataPath.replace(/^\./, ""));
47
+ }
48
+ else if (error.schemaPath !== "#/required") {
49
+ error.data = value;
50
+ }
51
+ }
52
+ if (dataPath && dataPath.match(/pwd|password|mdp|secret/)) {
53
+ error.data = "[REDACTED]";
54
+ }
55
+ if (type) {
56
+ error.modelName = nameOf(type);
57
+ error.message = this.mapClassError(error, type);
58
+ }
59
+ return this.errorFormatter.call(this, error, {});
60
+ })
61
+ .join("\n");
62
+ return new AjvValidationError(message, errors);
63
+ }
64
+ mapClassError(error, targetType) {
65
+ const propertyKey = getValue(error, "params.missingProperty");
66
+ if (propertyKey) {
67
+ const store = JsonEntityStore.from(prototypeOf(targetType), propertyKey);
68
+ if (store) {
69
+ setValue(error, "params.missingProperty", store.name || propertyKey);
70
+ return error.message.replace(`'${propertyKey}'`, `'${store.name || propertyKey}'`);
71
+ }
72
+ }
73
+ return error.message;
74
+ }
75
+ };
76
+ __decorate([
77
+ Constant("ajv.errorFormatter", defaultErrorFormatter),
78
+ __metadata("design:type", Function)
79
+ ], AjvService.prototype, "errorFormatter", void 0);
80
+ __decorate([
81
+ Inject(),
82
+ __metadata("design:type", Ajv)
83
+ ], AjvService.prototype, "ajv", void 0);
84
+ AjvService = __decorate([
85
+ Injectable()
86
+ ], AjvService);
87
+ export { AjvService };
88
+ //# sourceMappingURL=AjvService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AjvService.js","sourceRoot":"","sources":["../../../src/services/AjvService.ts"],"names":[],"mappings":"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","sourcesContent":["import {deepClone, getValue, nameOf, prototypeOf, setValue, Type} from \"@tsed/core\";\nimport {Constant, Inject, Injectable} from \"@tsed/di\";\nimport {getJsonSchema, JsonEntityStore, JsonSchema, JsonSchemaObject} from \"@tsed/schema\";\nimport Ajv, {ErrorObject} from \"ajv\";\nimport {AjvValidationError} from \"../errors/AjvValidationError\";\nimport {AjvErrorObject, ErrorFormatter} from \"../interfaces/IAjvSettings\";\nimport {defaultErrorFormatter} from \"../utils/defaultErrorFormatter\";\nimport \"./Ajv\";\nimport {getPath} from \"../utils/getPath\";\n\nexport interface AjvValidateOptions extends Record<string, any> {\n schema?: JsonSchema | Partial<JsonSchemaObject>;\n type?: Type<any> | any;\n collectionType?: Type<any> | any;\n}\n\n@Injectable()\nexport class AjvService {\n @Constant(\"ajv.errorFormatter\", defaultErrorFormatter)\n protected errorFormatter: ErrorFormatter;\n\n @Inject()\n protected ajv: Ajv;\n\n async validate(value: any, options: AjvValidateOptions | JsonSchema): Promise<any> {\n let {schema, type, collectionType, ...additionalOptions} = this.mapOptions(options);\n\n schema = schema || getJsonSchema(type, {...additionalOptions, customKeys: true});\n\n if (schema) {\n const localValue = deepClone(value);\n const valid = await this.ajv.validate(schema as any, localValue);\n if (!valid) {\n throw this.mapErrors(this.ajv.errors || [], {\n type,\n collectionType,\n async: true,\n value: localValue\n });\n }\n }\n\n return value;\n }\n\n protected mapOptions(options: AjvValidateOptions | JsonSchema): AjvValidateOptions {\n if (options instanceof JsonSchema) {\n return {\n schema: options.toJSON({customKeys: true})\n };\n }\n\n return options;\n }\n\n protected mapErrors(errors: ErrorObject[], options: any) {\n const {type, collectionType, value} = options;\n\n const message = errors\n .map((error: AjvErrorObject) => {\n if (collectionType) {\n error.collectionName = nameOf(collectionType);\n }\n\n const dataPath = getPath(error);\n\n if (!error.data) {\n if (dataPath) {\n error.data = getValue(value, dataPath.replace(/^\\./, \"\"));\n } else if (error.schemaPath !== \"#/required\") {\n error.data = value;\n }\n }\n\n if (dataPath && dataPath.match(/pwd|password|mdp|secret/)) {\n error.data = \"[REDACTED]\";\n }\n\n if (type) {\n error.modelName = nameOf(type);\n error.message = this.mapClassError(error, type);\n }\n\n return this.errorFormatter.call(this, error, {});\n })\n .join(\"\\n\");\n\n return new AjvValidationError(message, errors);\n }\n\n protected mapClassError(error: AjvErrorObject, targetType: Type<any>) {\n const propertyKey = getValue(error, \"params.missingProperty\");\n\n if (propertyKey) {\n const store = JsonEntityStore.from<JsonEntityStore>(prototypeOf(targetType), propertyKey);\n\n if (store) {\n setValue(error, \"params.missingProperty\", store.name || propertyKey);\n\n return error.message!.replace(`'${propertyKey}'`, `'${store.name || propertyKey}'`);\n }\n }\n\n return error.message;\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { getPath } from "./getPath";
2
+ export function defaultErrorFormatter(error) {
3
+ const value = JSON.stringify(error.data === undefined ? "undefined" : error.data);
4
+ const join = (list) => list.filter(Boolean).join("").trim();
5
+ error.dataPath = getPath(error);
6
+ const [, indexPath, ...paths] = error.dataPath.split(".");
7
+ const deepPaths = paths.length ? "." + paths.join(".") : "";
8
+ if (error.collectionName) {
9
+ switch (error.collectionName) {
10
+ case "Array":
11
+ return join([`${error.modelName || ""}[${indexPath}]${deepPaths}`, ` ${error.message}. Given value: ${value}`]);
12
+ case "Map":
13
+ return join([`Map<${indexPath}, ${error.modelName || ""}>${deepPaths}`, ` ${error.message}. Given value: ${value}`]);
14
+ case "Set":
15
+ return join([`Set<${indexPath}, ${error.modelName || ""}>${deepPaths}`, ` ${error.message}. Given value: ${value}`]);
16
+ }
17
+ }
18
+ return join([!error.modelName && "Value", `${error.modelName || ""}`, error.dataPath, ` ${error.message}. Given value: ${value}`]);
19
+ }
20
+ //# sourceMappingURL=defaultErrorFormatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultErrorFormatter.js","sourceRoot":"","sources":["../../../src/utils/defaultErrorFormatter.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,MAAM,UAAU,qBAAqB,CAAC,KAA0C;IAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClF,MAAM,IAAI,GAAG,CAAC,IAAW,EAAU,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAE3E,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAEhC,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5D,IAAI,KAAK,CAAC,cAAc,EAAE;QACxB,QAAQ,KAAK,CAAC,cAAc,EAAE;YAC5B,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,IAAI,SAAS,IAAI,SAAS,EAAE,EAAE,IAAI,KAAK,CAAC,OAAO,kBAAkB,KAAK,EAAE,CAAC,CAAC,CAAC;YAClH,KAAK,KAAK;gBACR,OAAO,IAAI,CAAC,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,SAAS,IAAI,EAAE,IAAI,SAAS,EAAE,EAAE,IAAI,KAAK,CAAC,OAAO,kBAAkB,KAAK,EAAE,CAAC,CAAC,CAAC;YACvH,KAAK,KAAK;gBACR,OAAO,IAAI,CAAC,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,SAAS,IAAI,EAAE,IAAI,SAAS,EAAE,EAAE,IAAI,KAAK,CAAC,OAAO,kBAAkB,KAAK,EAAE,CAAC,CAAC,CAAC;SACxH;KACF;IAED,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,KAAK,CAAC,OAAO,kBAAkB,KAAK,EAAE,CAAC,CAAC,CAAC;AACrI,CAAC","sourcesContent":["import {AjvErrorObject} from \"../interfaces/IAjvSettings\";\nimport {getPath} from \"./getPath\";\n\nexport function defaultErrorFormatter(error: AjvErrorObject & {dataPath: string}) {\n const value = JSON.stringify(error.data === undefined ? \"undefined\" : error.data);\n const join = (list: any[]): string => list.filter(Boolean).join(\"\").trim();\n\n error.dataPath = getPath(error);\n\n const [, indexPath, ...paths] = error.dataPath.split(\".\");\n const deepPaths = paths.length ? \".\" + paths.join(\".\") : \"\";\n\n if (error.collectionName) {\n switch (error.collectionName) {\n case \"Array\":\n return join([`${error.modelName || \"\"}[${indexPath}]${deepPaths}`, ` ${error.message}. Given value: ${value}`]);\n case \"Map\":\n return join([`Map<${indexPath}, ${error.modelName || \"\"}>${deepPaths}`, ` ${error.message}. Given value: ${value}`]);\n case \"Set\":\n return join([`Set<${indexPath}, ${error.modelName || \"\"}>${deepPaths}`, ` ${error.message}. Given value: ${value}`]);\n }\n }\n\n return join([!error.modelName && \"Value\", `${error.modelName || \"\"}`, error.dataPath, ` ${error.message}. Given value: ${value}`]);\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import { getValue } from "@tsed/core";
2
+ export function getPath(error) {
3
+ return getValue(error, "dataPath", getValue(error, "instancePath", "")).replace(/\//gi, ".");
4
+ }
5
+ //# sourceMappingURL=getPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPath.js","sourceRoot":"","sources":["../../../src/utils/getPath.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,UAAU,OAAO,CAAC,KAAU;IAChC,OAAO,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC/F,CAAC","sourcesContent":["import {getValue} from \"@tsed/core\";\n\nexport function getPath(error: any) {\n return getValue(error, \"dataPath\", getValue(error, \"instancePath\", \"\")).replace(/\\//gi, \".\");\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import { AsyncFormatDefinition, FormatDefinition } from "ajv";
2
+ export declare type FormatsOptions = Omit<FormatDefinition<any>, "validate" | "compare"> | Omit<AsyncFormatDefinition<any>, "validate" | "compare">;
3
+ /**
4
+ * Create a new custom formats validator
5
+ * @param name
6
+ * @param options
7
+ * @decorator
8
+ * @ajv
9
+ */
10
+ export declare function Formats(name: string, options?: FormatsOptions): ClassDecorator;
@@ -0,0 +1,12 @@
1
+ import { JsonSchema } from "@tsed/schema";
2
+ import { AnySchemaObject, KeywordDefinition } from "ajv";
3
+ export declare type KeywordOptions = Partial<Omit<KeywordDefinition, "metaSchema">> & {
4
+ metaSchema?: AnySchemaObject | JsonSchema;
5
+ };
6
+ /**
7
+ * Create new keyword custom validator
8
+ * @param options
9
+ * @decorator
10
+ * @ajv
11
+ */
12
+ export declare function Keyword(options: KeywordOptions): ClassDecorator;
@@ -0,0 +1,6 @@
1
+ import { BadRequest } from "@tsed/exceptions";
2
+ export declare class AjvValidationError extends BadRequest {
3
+ name: string;
4
+ errors: any[];
5
+ constructor(message: string, errors?: any[]);
6
+ }
@@ -0,0 +1,15 @@
1
+ export * from "./errors/AjvValidationError";
2
+ export * from "./services/AjvService";
3
+ export * from "./services/Ajv";
4
+ export * from "./decorators/keyword";
5
+ export * from "./interfaces/KeywordMethods";
6
+ export * from "./decorators/formats";
7
+ export * from "./interfaces/FormatsMethods";
8
+ import { IAjvSettings } from "./interfaces/IAjvSettings";
9
+ declare global {
10
+ namespace TsED {
11
+ interface Configuration {
12
+ ajv?: IAjvSettings;
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,4 @@
1
+ export interface FormatsMethods<T extends string | number> {
2
+ compare?: (data1: T, data2: T) => number | undefined;
3
+ validate(data: T): boolean;
4
+ }
@@ -0,0 +1,19 @@
1
+ import { ErrorObject, Options } from "ajv";
2
+ /**
3
+ *
4
+ */
5
+ export interface AjvErrorObject extends ErrorObject {
6
+ modelName: string;
7
+ collectionName?: string;
8
+ }
9
+ /**
10
+ *
11
+ */
12
+ export declare type ErrorFormatter = (error: AjvErrorObject) => string;
13
+ /**
14
+ *
15
+ */
16
+ export interface IAjvSettings extends Options {
17
+ Ajv?: any;
18
+ errorFormatter?: ErrorFormatter;
19
+ }
@@ -0,0 +1,23 @@
1
+ import { AnySchemaObject, KeywordCxt, SchemaObjCxt, ValidateFunction } from "ajv";
2
+ export interface AjvDataValidationCtx<T extends string | number = string | number> {
3
+ dataPath: string;
4
+ parentData: {
5
+ [K in T]: any;
6
+ };
7
+ parentDataProperty: T;
8
+ rootData: Record<string, any> | any[];
9
+ dynamicAnchors: {
10
+ [Ref in string]?: ValidateFunction;
11
+ };
12
+ }
13
+ export interface AjvDataValidateFunction {
14
+ (...args: Parameters<ValidateFunction>): boolean | Promise<any>;
15
+ }
16
+ export interface AjvSchemaValidateFunction {
17
+ (schema: any, data: any, parentSchema?: AnySchemaObject, dataCxt?: AjvDataValidationCtx): boolean | Promise<any>;
18
+ }
19
+ export interface KeywordMethods {
20
+ code?: (cxt: KeywordCxt, ruleType?: string) => void;
21
+ compile?: (schema: any, parentSchema: AnySchemaObject, it: SchemaObjCxt) => AjvDataValidateFunction;
22
+ validate?: AjvSchemaValidateFunction | AjvDataValidateFunction;
23
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import { Type } from "@tsed/core";
2
+ import { JsonSchema, JsonSchemaObject } from "@tsed/schema";
3
+ import Ajv, { ErrorObject } from "ajv";
4
+ import { AjvValidationError } from "../errors/AjvValidationError";
5
+ import { AjvErrorObject, ErrorFormatter } from "../interfaces/IAjvSettings";
6
+ import "./Ajv";
7
+ export interface AjvValidateOptions extends Record<string, any> {
8
+ schema?: JsonSchema | Partial<JsonSchemaObject>;
9
+ type?: Type<any> | any;
10
+ collectionType?: Type<any> | any;
11
+ }
12
+ export declare class AjvService {
13
+ protected errorFormatter: ErrorFormatter;
14
+ protected ajv: Ajv;
15
+ validate(value: any, options: AjvValidateOptions | JsonSchema): Promise<any>;
16
+ protected mapOptions(options: AjvValidateOptions | JsonSchema): AjvValidateOptions;
17
+ protected mapErrors(errors: ErrorObject[], options: any): AjvValidationError;
18
+ protected mapClassError(error: AjvErrorObject, targetType: Type<any>): string | undefined;
19
+ }
@@ -0,0 +1,4 @@
1
+ import { AjvErrorObject } from "../interfaces/IAjvSettings";
2
+ export declare function defaultErrorFormatter(error: AjvErrorObject & {
3
+ dataPath: string;
4
+ }): string;
@@ -0,0 +1 @@
1
+ export declare function getPath(error: any): string;
package/package.json CHANGED
@@ -1,34 +1,37 @@
1
1
  {
2
2
  "name": "@tsed/ajv",
3
- "version": "6.87.2",
3
+ "version": "6.90.0",
4
4
  "description": "AJV package for Ts.ED framework",
5
5
  "source": "./src/index.ts",
6
- "main": "./lib/index.js",
7
- "typings": "./lib/index.d.ts",
8
- "private": false,
6
+ "main": "./lib/cjs/index.js",
7
+ "typings": "./lib/types/index.d.ts",
9
8
  "exports": {
10
- "require": "./lib/index.js",
11
- "default": "./lib/index.modern.js"
9
+ "types": "./lib/types/index.d.ts",
10
+ "import": "./lib/esm/index.js",
11
+ "require": "./lib/cjs/index.js",
12
+ "default": "./lib/esm/index.js"
12
13
  },
13
14
  "scripts": {
14
- "build": "microbundle --target node --no-compress --format modern,cjs --tsconfig ./tsconfig.compile.json"
15
+ "build": "yarn run build:esm && yarn run build:cjs",
16
+ "build:cjs": "tsc --build tsconfig.compile.json",
17
+ "build:esm": "tsc --build tsconfig.compile.esm.json"
15
18
  },
16
19
  "dependencies": {
17
20
  "ajv-formats": "1.5.1",
18
21
  "tslib": "2.2.0"
19
22
  },
20
23
  "devDependencies": {
21
- "@tsed/core": "6.87.2",
22
- "@tsed/di": "6.87.2",
23
- "@tsed/exceptions": "6.87.2",
24
- "@tsed/schema": "6.87.2",
24
+ "@tsed/core": "6.90.0",
25
+ "@tsed/di": "6.90.0",
26
+ "@tsed/exceptions": "6.90.0",
27
+ "@tsed/schema": "6.90.0",
25
28
  "ajv": "8.6.0"
26
29
  },
27
30
  "peerDependencies": {
28
- "@tsed/core": "^6.87.2",
29
- "@tsed/di": "^6.87.2",
30
- "@tsed/exceptions": "^6.87.2",
31
- "@tsed/schema": "^6.87.2",
31
+ "@tsed/core": "^6.90.0",
32
+ "@tsed/di": "^6.90.0",
33
+ "@tsed/exceptions": "^6.90.0",
34
+ "@tsed/schema": "^6.90.0",
32
35
  "ajv": "7||8"
33
36
  },
34
37
  "repository": "https://github.com/tsedio/tsed",
@@ -0,0 +1,23 @@
1
+ {
2
+ "extends": "./tsconfig.compile.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "module": "ES2020",
6
+ "rootDir": "src",
7
+ "outDir": "./lib/esm",
8
+ "declaration": true,
9
+ "declarationDir": "./lib/types"
10
+ },
11
+ "exclude": [
12
+ "node_modules",
13
+ "test",
14
+ "lib",
15
+ "benchmark",
16
+ "coverage",
17
+ "spec",
18
+ "**/*.benchmark.ts",
19
+ "**/*.spec.ts",
20
+ "keys",
21
+ "jest.config.js"
22
+ ]
23
+ }
package/lib/index.js DELETED
@@ -1,302 +0,0 @@
1
- var exceptions = require('@tsed/exceptions');
2
- var tslib = require('tslib');
3
- var core = require('@tsed/core');
4
- var di = require('@tsed/di');
5
- var schema = require('@tsed/schema');
6
- var Ajv = require('ajv');
7
- var AjvFormats = require('ajv-formats');
8
-
9
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
-
11
- var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
12
- var AjvFormats__default = /*#__PURE__*/_interopDefaultLegacy(AjvFormats);
13
-
14
- class AjvValidationError extends exceptions.BadRequest {
15
- constructor(message, errors = []) {
16
- super(message);
17
- this.name = "AJV_VALIDATION_ERROR";
18
- this.errors = errors;
19
- }
20
-
21
- }
22
-
23
- function _extends() {
24
- _extends = Object.assign || function (target) {
25
- for (var i = 1; i < arguments.length; i++) {
26
- var source = arguments[i];
27
-
28
- for (var key in source) {
29
- if (Object.prototype.hasOwnProperty.call(source, key)) {
30
- target[key] = source[key];
31
- }
32
- }
33
- }
34
-
35
- return target;
36
- };
37
-
38
- return _extends.apply(this, arguments);
39
- }
40
-
41
- function _objectWithoutPropertiesLoose(source, excluded) {
42
- if (source == null) return {};
43
- var target = {};
44
- var sourceKeys = Object.keys(source);
45
- var key, i;
46
-
47
- for (i = 0; i < sourceKeys.length; i++) {
48
- key = sourceKeys[i];
49
- if (excluded.indexOf(key) >= 0) continue;
50
- target[key] = source[key];
51
- }
52
-
53
- return target;
54
- }
55
-
56
- function getPath(error) {
57
- return core.getValue(error, "dataPath", core.getValue(error, "instancePath", "")).replace(/\//gi, ".");
58
- }
59
-
60
- function defaultErrorFormatter(error) {
61
- const value = JSON.stringify(error.data === undefined ? "undefined" : error.data);
62
-
63
- const join = list => list.filter(Boolean).join("").trim();
64
-
65
- error.dataPath = getPath(error);
66
- const [, indexPath, ...paths] = error.dataPath.split(".");
67
- const deepPaths = paths.length ? "." + paths.join(".") : "";
68
-
69
- if (error.collectionName) {
70
- switch (error.collectionName) {
71
- case "Array":
72
- return join([`${error.modelName || ""}[${indexPath}]${deepPaths}`, ` ${error.message}. Given value: ${value}`]);
73
-
74
- case "Map":
75
- return join([`Map<${indexPath}, ${error.modelName || ""}>${deepPaths}`, ` ${error.message}. Given value: ${value}`]);
76
-
77
- case "Set":
78
- return join([`Set<${indexPath}, ${error.modelName || ""}>${deepPaths}`, ` ${error.message}. Given value: ${value}`]);
79
- }
80
- }
81
-
82
- return join([!error.modelName && "Value", `${error.modelName || ""}`, error.dataPath, ` ${error.message}. Given value: ${value}`]);
83
- }
84
-
85
- const _excluded$1 = ["errorFormatter", "keywords"];
86
-
87
- function getHandler(key, service) {
88
- if (service[key]) {
89
- return service[key].bind(service);
90
- }
91
- }
92
-
93
- function getKeywordProviders(injector) {
94
- return injector.getProviders("ajv:keyword");
95
- }
96
-
97
- function bindKeywords(injector) {
98
- return getKeywordProviders(injector).map(provider => {
99
- const options = provider.store.get("ajv:keyword", {});
100
- const service = injector.invoke(provider.token);
101
- return core.cleanObject(_extends({}, options, {
102
- validate: getHandler("validate", service),
103
- compile: getHandler("compile", service),
104
- code: getHandler("code", service),
105
- macro: getHandler("macro", service)
106
- }));
107
- });
108
- }
109
-
110
- function getFormatsProviders(injector) {
111
- return injector.getProviders("ajv:formats");
112
- }
113
-
114
- function getFormats(injector) {
115
- return getFormatsProviders(injector).map(provider => {
116
- var _service$compare;
117
-
118
- const {
119
- name,
120
- options
121
- } = provider.store.get("ajv:formats", {});
122
- const service = injector.invoke(provider.token);
123
- return {
124
- name,
125
- options: _extends({}, options, {
126
- validate: service.validate.bind(service),
127
- compare: (_service$compare = service.compare) == null ? void 0 : _service$compare.bind(service)
128
- })
129
- };
130
- });
131
- }
132
-
133
- di.registerProvider({
134
- provide: Ajv__default['default'],
135
- deps: [di.Configuration, di.InjectorService],
136
- scope: di.ProviderScope.SINGLETON,
137
-
138
- useFactory(configuration, injector) {
139
- const _ref = configuration.get("ajv") || {},
140
- {
141
- keywords = []
142
- } = _ref,
143
- props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
144
-
145
- const options = _extends({
146
- verbose: false,
147
- coerceTypes: true,
148
- strict: false,
149
- keywords: [...keywords, ...bindKeywords(injector)]
150
- }, props);
151
-
152
- const ajv = new Ajv__default['default'](options);
153
- AjvFormats__default['default'](ajv);
154
- getFormats(injector).forEach(({
155
- name,
156
- options
157
- }) => {
158
- ajv.addFormat(name, options);
159
- });
160
- return ajv;
161
- }
162
-
163
- });
164
-
165
- const _excluded = ["schema", "type", "collectionType"];
166
- exports.AjvService = class AjvService {
167
- async validate(value, options) {
168
- let _this$mapOptions = this.mapOptions(options),
169
- {
170
- schema: schema$1,
171
- type,
172
- collectionType
173
- } = _this$mapOptions,
174
- additionalOptions = _objectWithoutPropertiesLoose(_this$mapOptions, _excluded);
175
-
176
- schema$1 = schema$1 || schema.getJsonSchema(type, _extends({}, additionalOptions, {
177
- customKeys: true
178
- }));
179
-
180
- if (schema$1) {
181
- const localValue = core.deepClone(value);
182
- const valid = await this.ajv.validate(schema$1, localValue);
183
-
184
- if (!valid) {
185
- throw this.mapErrors(this.ajv.errors || [], {
186
- type,
187
- collectionType,
188
- async: true,
189
- value: localValue
190
- });
191
- }
192
- }
193
-
194
- return value;
195
- }
196
-
197
- mapOptions(options) {
198
- if (options instanceof schema.JsonSchema) {
199
- return {
200
- schema: options.toJSON({
201
- customKeys: true
202
- })
203
- };
204
- }
205
-
206
- return options;
207
- }
208
-
209
- mapErrors(errors, options) {
210
- const {
211
- type,
212
- collectionType,
213
- value
214
- } = options;
215
- const message = errors.map(error => {
216
- if (collectionType) {
217
- error.collectionName = core.nameOf(collectionType);
218
- }
219
-
220
- const dataPath = getPath(error);
221
-
222
- if (!error.data) {
223
- if (dataPath) {
224
- error.data = core.getValue(value, dataPath.replace(/^\./, ""));
225
- } else if (error.schemaPath !== "#/required") {
226
- error.data = value;
227
- }
228
- }
229
-
230
- if (dataPath && dataPath.match(/pwd|password|mdp|secret/)) {
231
- error.data = "[REDACTED]";
232
- }
233
-
234
- if (type) {
235
- error.modelName = core.nameOf(type);
236
- error.message = this.mapClassError(error, type);
237
- }
238
-
239
- return this.errorFormatter.call(this, error, {});
240
- }).join("\n");
241
- return new AjvValidationError(message, errors);
242
- }
243
-
244
- mapClassError(error, targetType) {
245
- const propertyKey = core.getValue(error, "params.missingProperty");
246
-
247
- if (propertyKey) {
248
- const store = schema.JsonEntityStore.from(core.prototypeOf(targetType), propertyKey);
249
-
250
- if (store) {
251
- core.setValue(error, "params.missingProperty", store.name || propertyKey);
252
- return error.message.replace(`'${propertyKey}'`, `'${store.name || propertyKey}'`);
253
- }
254
- }
255
-
256
- return error.message;
257
- }
258
-
259
- };
260
-
261
- tslib.__decorate([di.Constant("ajv.errorFormatter", defaultErrorFormatter), tslib.__metadata("design:type", Function)], exports.AjvService.prototype, "errorFormatter", void 0);
262
-
263
- tslib.__decorate([di.Inject(), tslib.__metadata("design:type", Ajv__default['default'])], exports.AjvService.prototype, "ajv", void 0);
264
-
265
- exports.AjvService = tslib.__decorate([di.Injectable()], exports.AjvService);
266
-
267
- /**
268
- * Create new keyword custom validator
269
- * @param options
270
- * @decorator
271
- * @ajv
272
- */
273
-
274
- function Keyword(options) {
275
- return core.useDecorators(di.Injectable({
276
- type: "ajv:keyword"
277
- }), core.StoreSet("ajv:keyword", _extends({}, options, {
278
- metaSchema: options.metaSchema && options.metaSchema.toJSON ? options.metaSchema.toJSON() : options.metaSchema
279
- })));
280
- }
281
-
282
- /**
283
- * Create a new custom formats validator
284
- * @param name
285
- * @param options
286
- * @decorator
287
- * @ajv
288
- */
289
-
290
- function Formats(name, options = {}) {
291
- return core.useDecorators(di.Injectable({
292
- type: "ajv:formats"
293
- }), core.StoreSet("ajv:formats", {
294
- name,
295
- options
296
- }));
297
- }
298
-
299
- exports.AjvValidationError = AjvValidationError;
300
- exports.Formats = Formats;
301
- exports.Keyword = Keyword;
302
- //# sourceMappingURL=index.js.map