@travetto/schema 6.0.1 → 7.0.0-rc.1
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/README.md +30 -26
- package/__index__.ts +4 -2
- package/package.json +3 -3
- package/src/bind-util.ts +47 -44
- package/src/decorator/common.ts +32 -16
- package/src/decorator/field.ts +21 -184
- package/src/decorator/input.ts +207 -0
- package/src/decorator/method.ts +28 -0
- package/src/decorator/schema.ts +36 -29
- package/src/name.ts +2 -2
- package/src/service/changes.ts +27 -30
- package/src/service/registry-adapter.ts +340 -0
- package/src/service/registry-index.ts +230 -0
- package/src/service/types.ts +113 -63
- package/src/validate/types.ts +4 -0
- package/src/validate/validator.ts +70 -64
- package/support/transformer/util.ts +147 -61
- package/support/transformer.schema.ts +137 -49
- package/src/service/registry.ts +0 -501
package/src/service/types.ts
CHANGED
|
@@ -2,19 +2,40 @@ import { Any, Class, Primitive } from '@travetto/runtime';
|
|
|
2
2
|
|
|
3
3
|
import { MethodValidatorFn, ValidatorFn } from '../validate/types.ts';
|
|
4
4
|
|
|
5
|
-
export type ClassList = Class | [Class];
|
|
6
|
-
|
|
7
5
|
type TemplateLiteralPart = string | NumberConstructor | StringConstructor | BooleanConstructor;
|
|
8
6
|
export type TemplateLiteral = { op: 'and' | 'or', values: (TemplateLiteralPart | TemplateLiteral)[] };
|
|
9
7
|
|
|
8
|
+
export const CONSTRUCTOR_PROPERTY = 'CONSTRUCTOR';
|
|
9
|
+
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Represents a typed item in the schema
|
|
12
12
|
*/
|
|
13
|
-
export
|
|
13
|
+
export type SchemaBasicType = {
|
|
14
|
+
/**
|
|
15
|
+
* Description of the type
|
|
16
|
+
*/
|
|
17
|
+
description?: string;
|
|
14
18
|
/**
|
|
15
|
-
*
|
|
19
|
+
* Is the type an array
|
|
16
20
|
*/
|
|
17
|
-
|
|
21
|
+
array?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The class tied to the type
|
|
24
|
+
*/
|
|
25
|
+
type: Class & {
|
|
26
|
+
bindSchema?(input: unknown): undefined | unknown;
|
|
27
|
+
validateSchema?(input: unknown): string | undefined;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Is the field a foreign type
|
|
31
|
+
*/
|
|
32
|
+
isForeign?: boolean;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Basic schema configuration
|
|
37
|
+
*/
|
|
38
|
+
export interface SchemaCoreConfig {
|
|
18
39
|
/**
|
|
19
40
|
* Description
|
|
20
41
|
*/
|
|
@@ -23,44 +44,52 @@ export interface DescribableConfig {
|
|
|
23
44
|
* List of examples
|
|
24
45
|
*/
|
|
25
46
|
examples?: string[];
|
|
47
|
+
/**
|
|
48
|
+
* Is the field/method/private
|
|
49
|
+
*/
|
|
50
|
+
private?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Metadata that is related to the schema structure
|
|
53
|
+
*/
|
|
54
|
+
metadata?: Record<symbol, unknown>;
|
|
26
55
|
}
|
|
27
56
|
|
|
28
57
|
/**
|
|
29
58
|
* Basic structure for a method configuration
|
|
30
59
|
*/
|
|
31
|
-
export interface SchemaMethodConfig {
|
|
32
|
-
|
|
60
|
+
export interface SchemaMethodConfig extends SchemaCoreConfig {
|
|
61
|
+
/**
|
|
62
|
+
* Is the method static
|
|
63
|
+
*/
|
|
64
|
+
isStatic?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* The parameters of the method
|
|
67
|
+
*/
|
|
68
|
+
parameters: SchemaParameterConfig[];
|
|
69
|
+
/**
|
|
70
|
+
* Validators to run for th method
|
|
71
|
+
*/
|
|
33
72
|
validators: MethodValidatorFn<unknown[]>[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Schema configuration
|
|
38
|
-
*/
|
|
39
|
-
export interface SchemaConfig {
|
|
40
73
|
/**
|
|
41
|
-
*
|
|
74
|
+
* The return type configuration
|
|
42
75
|
*/
|
|
43
|
-
|
|
76
|
+
returnType?: SchemaBasicType;
|
|
44
77
|
}
|
|
45
78
|
|
|
46
79
|
/**
|
|
47
|
-
*
|
|
80
|
+
* Schema configuration
|
|
48
81
|
*/
|
|
49
|
-
export interface
|
|
50
|
-
/**
|
|
51
|
-
* The schema config
|
|
52
|
-
*/
|
|
53
|
-
schema: SchemaConfig;
|
|
82
|
+
export interface SchemaFieldMap {
|
|
54
83
|
/**
|
|
55
|
-
*
|
|
84
|
+
* List of all fields
|
|
56
85
|
*/
|
|
57
|
-
|
|
86
|
+
[key: string | symbol]: SchemaFieldConfig;
|
|
58
87
|
}
|
|
59
88
|
|
|
60
89
|
/**
|
|
61
90
|
* Class configuration
|
|
62
91
|
*/
|
|
63
|
-
export interface
|
|
92
|
+
export interface SchemaClassConfig extends SchemaCoreConfig {
|
|
64
93
|
/**
|
|
65
94
|
* Target class
|
|
66
95
|
*/
|
|
@@ -68,72 +97,61 @@ export interface ClassConfig extends DescribableConfig {
|
|
|
68
97
|
/**
|
|
69
98
|
* List of all views
|
|
70
99
|
*/
|
|
71
|
-
views: Record<string,
|
|
100
|
+
views: Record<string, ViewFieldsConfig<Any>>;
|
|
72
101
|
/**
|
|
73
|
-
*
|
|
102
|
+
* Field configurations
|
|
74
103
|
*/
|
|
75
|
-
|
|
104
|
+
fields: SchemaFieldMap;
|
|
76
105
|
/**
|
|
77
106
|
* Global validators
|
|
78
107
|
*/
|
|
79
108
|
validators: ValidatorFn<Any, unknown>[];
|
|
80
109
|
/**
|
|
81
|
-
* Is
|
|
110
|
+
* Is this a base class for discrimination
|
|
82
111
|
*/
|
|
83
|
-
|
|
112
|
+
discriminatedBase?: boolean;
|
|
84
113
|
/**
|
|
85
|
-
*
|
|
114
|
+
* Do we have a discriminator field
|
|
86
115
|
*/
|
|
87
|
-
|
|
116
|
+
discriminatedField?: string;
|
|
88
117
|
/**
|
|
89
|
-
*
|
|
118
|
+
* Discriminated type name
|
|
90
119
|
*/
|
|
91
|
-
|
|
120
|
+
discriminatedType?: string;
|
|
92
121
|
/**
|
|
93
|
-
*
|
|
122
|
+
* Method configs
|
|
94
123
|
*/
|
|
95
|
-
|
|
124
|
+
methods: Record<string | symbol, SchemaMethodConfig>;
|
|
125
|
+
/**
|
|
126
|
+
* Interfaces that the class implements
|
|
127
|
+
*/
|
|
128
|
+
interfaces: Class[];
|
|
96
129
|
/**
|
|
97
|
-
*
|
|
130
|
+
* Is this class derived from another via a mapped type
|
|
98
131
|
*/
|
|
99
|
-
|
|
132
|
+
mappedOperation?: 'Omit' | 'Pick' | 'Partial' | 'Required';
|
|
133
|
+
/**
|
|
134
|
+
* Are there any restrictions in the mapped type
|
|
135
|
+
*/
|
|
136
|
+
mappedFields?: string[];
|
|
100
137
|
}
|
|
101
138
|
|
|
102
139
|
/**
|
|
103
|
-
*
|
|
140
|
+
* Shared base type for all input-related fields
|
|
104
141
|
*/
|
|
105
|
-
export interface
|
|
142
|
+
export interface SchemaInputConfig extends SchemaCoreConfig, SchemaBasicType {
|
|
106
143
|
/**
|
|
107
|
-
*
|
|
144
|
+
* Key name for validation when dealing with complex types
|
|
108
145
|
*/
|
|
109
|
-
|
|
146
|
+
view?: string;
|
|
110
147
|
/**
|
|
111
|
-
*
|
|
148
|
+
* Owner class
|
|
112
149
|
*/
|
|
113
|
-
|
|
150
|
+
owner: Class;
|
|
114
151
|
/**
|
|
115
152
|
* List of aliases
|
|
116
153
|
*/
|
|
117
154
|
aliases?: string[];
|
|
118
|
-
/**
|
|
119
|
-
* Specific type for the field, with optional binding/validation support
|
|
120
|
-
*/
|
|
121
|
-
type: Class & {
|
|
122
|
-
bindSchema?(input: unknown): undefined | unknown;
|
|
123
|
-
validateSchema?(input: unknown): string | undefined;
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* View name for validation when dealing with complex types
|
|
127
|
-
*/
|
|
128
|
-
view?: string;
|
|
129
|
-
/**
|
|
130
|
-
* The position of the field if ordered
|
|
131
|
-
*/
|
|
132
|
-
index?: number;
|
|
133
|
-
/**
|
|
134
|
-
* Is the field an array
|
|
135
|
-
*/
|
|
136
|
-
array: boolean;
|
|
137
155
|
/**
|
|
138
156
|
* Does the field have a specialization
|
|
139
157
|
*/
|
|
@@ -174,6 +192,38 @@ export interface FieldConfig extends DescribableConfig {
|
|
|
174
192
|
* Default value
|
|
175
193
|
*/
|
|
176
194
|
default?: Primitive | [];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Parameter configuration for methods
|
|
199
|
+
*/
|
|
200
|
+
export interface SchemaParameterConfig extends SchemaInputConfig {
|
|
201
|
+
/**
|
|
202
|
+
* Parameter name
|
|
203
|
+
*/
|
|
204
|
+
name?: string;
|
|
205
|
+
/**
|
|
206
|
+
* The position of the field if ordered
|
|
207
|
+
*/
|
|
208
|
+
index: number;
|
|
209
|
+
/**
|
|
210
|
+
* Method the parameter belongs to
|
|
211
|
+
*/
|
|
212
|
+
method: string | symbol;
|
|
213
|
+
/**
|
|
214
|
+
* Source text for the parameter
|
|
215
|
+
*/
|
|
216
|
+
sourceText?: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Field configuration
|
|
221
|
+
*/
|
|
222
|
+
export interface SchemaFieldConfig extends SchemaInputConfig {
|
|
223
|
+
/**
|
|
224
|
+
* Field name
|
|
225
|
+
*/
|
|
226
|
+
name: string | symbol;
|
|
177
227
|
/**
|
|
178
228
|
* Is the field readonly, or write only?, defaults to no restrictions
|
|
179
229
|
*/
|
package/src/validate/types.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { castKey, castTo, Class, ClassInstance, TypedObject } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { SchemaRegistry } from '../service/registry.ts';
|
|
3
|
+
import { SchemaInputConfig, SchemaFieldMap } from '../service/types.ts';
|
|
5
4
|
import { ValidationError, ValidationKindCore, ValidationResult } from './types.ts';
|
|
6
5
|
import { Messages } from './messages.ts';
|
|
7
6
|
import { isValidationError, TypeMismatchError, ValidationResultError } from './error.ts';
|
|
8
7
|
import { DataUtil } from '../data.ts';
|
|
9
8
|
import { CommonRegExpToName } from './regexp.ts';
|
|
9
|
+
import { SchemaRegistryIndex } from '../service/registry-index.ts';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Get the schema config for Class/Schema config, including support for polymorphism
|
|
13
13
|
* @param base The starting type or config
|
|
14
14
|
* @param o The value to use for the polymorphic check
|
|
15
15
|
*/
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
).schema;
|
|
16
|
+
function resolveFieldMap<T>(base: Class<T>, o: T): SchemaFieldMap {
|
|
17
|
+
const target = SchemaRegistryIndex.resolveInstanceType(base, o);
|
|
18
|
+
return SchemaRegistryIndex.get(target).getFields();
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
function isClassInstance<T>(o: unknown): o is ClassInstance<T> {
|
|
@@ -35,17 +34,16 @@ export class SchemaValidator {
|
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
36
|
* Validate the schema for a given object
|
|
38
|
-
* @param
|
|
37
|
+
* @param fields The config to validate against
|
|
39
38
|
* @param o The object to validate
|
|
40
39
|
* @param relative The relative path as the validation recurses
|
|
41
40
|
*/
|
|
42
|
-
static #
|
|
41
|
+
static #validateFields<T>(fields: SchemaFieldMap, o: T, relative: string): ValidationError[] {
|
|
43
42
|
let errors: ValidationError[] = [];
|
|
44
43
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
errors = errors.concat(this.#validateFieldSchema(schema[field], o[castKey<T>(field)], relative));
|
|
44
|
+
for (const [field, fieldConfig] of TypedObject.entries(fields)) {
|
|
45
|
+
if (fieldConfig.access !== 'readonly') { // Do not validate readonly fields
|
|
46
|
+
errors = errors.concat(this.#validateInputSchema(fieldConfig, o[castKey<T>(field)], relative));
|
|
49
47
|
}
|
|
50
48
|
}
|
|
51
49
|
|
|
@@ -53,25 +51,26 @@ export class SchemaValidator {
|
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
/**
|
|
56
|
-
* Validate a single
|
|
57
|
-
* @param
|
|
54
|
+
* Validate a single input config against a passed in value
|
|
55
|
+
* @param input The input schema configuration
|
|
58
56
|
* @param val The raw value, could be an array or not
|
|
59
57
|
* @param relative The relative path of object traversal
|
|
60
58
|
*/
|
|
61
|
-
static #
|
|
62
|
-
const
|
|
59
|
+
static #validateInputSchema(input: SchemaInputConfig, val: unknown, relative: string = ''): ValidationError[] {
|
|
60
|
+
const key = 'name' in input ? input.name : ('index' in input ? input.index : 'unknown');
|
|
61
|
+
const path = `${relative}${relative ? '.' : ''}${key}`;
|
|
63
62
|
const hasValue = !(val === undefined || val === null || (typeof val === 'string' && val === '') || (Array.isArray(val) && val.length === 0));
|
|
64
63
|
|
|
65
64
|
if (!hasValue) {
|
|
66
|
-
if (
|
|
67
|
-
return this.#prepareErrors(path, [{ kind: 'required', ...
|
|
65
|
+
if (input.required?.active !== false) {
|
|
66
|
+
return this.#prepareErrors(path, [{ kind: 'required', active: true, ...input.required }]);
|
|
68
67
|
} else {
|
|
69
68
|
return [];
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
const { type, array
|
|
74
|
-
const complex =
|
|
72
|
+
const { type, array } = input;
|
|
73
|
+
const complex = SchemaRegistryIndex.has(type);
|
|
75
74
|
|
|
76
75
|
if (type === Object) {
|
|
77
76
|
return [];
|
|
@@ -82,34 +81,34 @@ export class SchemaValidator {
|
|
|
82
81
|
let errors: ValidationError[] = [];
|
|
83
82
|
if (complex) {
|
|
84
83
|
for (let i = 0; i < val.length; i++) {
|
|
85
|
-
const subErrors = this.#
|
|
84
|
+
const subErrors = this.#validateFields(resolveFieldMap(type, val[i]), val[i], `${path}[${i}]`);
|
|
86
85
|
errors = errors.concat(subErrors);
|
|
87
86
|
}
|
|
88
87
|
} else {
|
|
89
88
|
for (let i = 0; i < val.length; i++) {
|
|
90
|
-
const subErrors = this.#
|
|
89
|
+
const subErrors = this.#validateInput(input, val[i]);
|
|
91
90
|
errors.push(...this.#prepareErrors(`${path}[${i}]`, subErrors));
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
93
|
return errors;
|
|
95
94
|
} else if (complex) {
|
|
96
|
-
return this.#
|
|
95
|
+
return this.#validateFields(resolveFieldMap(type, val), val, path);
|
|
97
96
|
} else {
|
|
98
|
-
const fieldErrors = this.#
|
|
97
|
+
const fieldErrors = this.#validateInput(input, val);
|
|
99
98
|
return this.#prepareErrors(path, fieldErrors);
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
/**
|
|
104
103
|
* Validate the range for a number, date
|
|
105
|
-
* @param
|
|
104
|
+
* @param input The config to validate against
|
|
106
105
|
* @param key The bounds to check
|
|
107
106
|
* @param value The value to validate
|
|
108
107
|
*/
|
|
109
|
-
static #validateRange(
|
|
110
|
-
const f =
|
|
108
|
+
static #validateRange(input: SchemaInputConfig, key: 'min' | 'max', value: string | number | Date): boolean {
|
|
109
|
+
const f = input[key]!;
|
|
111
110
|
const valueNum = (typeof value === 'string') ?
|
|
112
|
-
(
|
|
111
|
+
(input.type === Date ? Date.parse(value) : parseInt(value, 10)) :
|
|
113
112
|
(value instanceof Date ? value.getTime() : value);
|
|
114
113
|
|
|
115
114
|
const boundary = (typeof f.n === 'number' ? f.n : f.n.getTime());
|
|
@@ -119,54 +118,54 @@ export class SchemaValidator {
|
|
|
119
118
|
/**
|
|
120
119
|
* Validate a given field by checking all the appropriate constraints
|
|
121
120
|
*
|
|
122
|
-
* @param
|
|
121
|
+
* @param input The config of the field to validate
|
|
123
122
|
* @param value The actual value
|
|
124
123
|
*/
|
|
125
|
-
static #
|
|
126
|
-
const criteria: ([string,
|
|
124
|
+
static #validateInput(input: SchemaInputConfig, value: unknown): ValidationResult[] {
|
|
125
|
+
const criteria: ([string, SchemaInputConfig[ValidationKindCore]] | [string])[] = [];
|
|
127
126
|
|
|
128
127
|
if (
|
|
129
|
-
(
|
|
130
|
-
(
|
|
131
|
-
(
|
|
132
|
-
(
|
|
128
|
+
(input.type === String && (typeof value !== 'string')) ||
|
|
129
|
+
(input.type === Number && ((typeof value !== 'number') || Number.isNaN(value))) ||
|
|
130
|
+
(input.type === Date && (!(value instanceof Date) || Number.isNaN(value.getTime()))) ||
|
|
131
|
+
(input.type === Boolean && typeof value !== 'boolean')
|
|
133
132
|
) {
|
|
134
133
|
criteria.push(['type']);
|
|
135
|
-
return [{ kind: 'type', type:
|
|
134
|
+
return [{ kind: 'type', type: input.type.name.toLowerCase() }];
|
|
136
135
|
}
|
|
137
136
|
|
|
138
|
-
if (
|
|
139
|
-
const kind =
|
|
137
|
+
if (input.type?.validateSchema) {
|
|
138
|
+
const kind = input.type.validateSchema(value);
|
|
140
139
|
switch (kind) {
|
|
141
140
|
case undefined: break;
|
|
142
|
-
case 'type': return [{ kind, type:
|
|
141
|
+
case 'type': return [{ kind, type: input.type.name }];
|
|
143
142
|
default:
|
|
144
143
|
criteria.push([kind]);
|
|
145
144
|
}
|
|
146
145
|
}
|
|
147
146
|
|
|
148
|
-
if (
|
|
149
|
-
criteria.push(['match',
|
|
147
|
+
if (input.match && !input.match.re.test(`${value}`)) {
|
|
148
|
+
criteria.push(['match', input.match]);
|
|
150
149
|
}
|
|
151
150
|
|
|
152
|
-
if (
|
|
153
|
-
criteria.push(['minlength',
|
|
151
|
+
if (input.minlength && `${value}`.length < input.minlength.n) {
|
|
152
|
+
criteria.push(['minlength', input.minlength]);
|
|
154
153
|
}
|
|
155
154
|
|
|
156
|
-
if (
|
|
157
|
-
criteria.push(['maxlength',
|
|
155
|
+
if (input.maxlength && `${value}`.length > input.maxlength.n) {
|
|
156
|
+
criteria.push(['maxlength', input.maxlength]);
|
|
158
157
|
}
|
|
159
158
|
|
|
160
|
-
if (
|
|
161
|
-
criteria.push(['enum',
|
|
159
|
+
if (input.enum && !input.enum.values.includes(castTo(value))) {
|
|
160
|
+
criteria.push(['enum', input.enum]);
|
|
162
161
|
}
|
|
163
162
|
|
|
164
|
-
if (
|
|
165
|
-
criteria.push(['min',
|
|
163
|
+
if (input.min && (!isRangeValue(value) || this.#validateRange(input, 'min', value))) {
|
|
164
|
+
criteria.push(['min', input.min]);
|
|
166
165
|
}
|
|
167
166
|
|
|
168
|
-
if (
|
|
169
|
-
criteria.push(['max',
|
|
167
|
+
if (input.max && (!isRangeValue(value) || this.#validateRange(input, 'max', value))) {
|
|
168
|
+
criteria.push(['max', input.max]);
|
|
170
169
|
}
|
|
171
170
|
|
|
172
171
|
const errors: ValidationResult[] = [];
|
|
@@ -217,14 +216,15 @@ export class SchemaValidator {
|
|
|
217
216
|
* Validate the class level validations
|
|
218
217
|
*/
|
|
219
218
|
static async #validateClassLevel<T>(cls: Class<T>, o: T, view?: string): Promise<ValidationError[]> {
|
|
220
|
-
|
|
221
|
-
if (!schema) {
|
|
219
|
+
if (!SchemaRegistryIndex.has(cls)) {
|
|
222
220
|
return [];
|
|
223
221
|
}
|
|
224
222
|
|
|
223
|
+
const classConfig = SchemaRegistryIndex.getConfig(cls);
|
|
225
224
|
const errors: ValidationError[] = [];
|
|
225
|
+
|
|
226
226
|
// Handle class level validators
|
|
227
|
-
for (const fn of
|
|
227
|
+
for (const fn of classConfig.validators) {
|
|
228
228
|
try {
|
|
229
229
|
const res = await fn(o, view);
|
|
230
230
|
if (res) {
|
|
@@ -255,13 +255,13 @@ export class SchemaValidator {
|
|
|
255
255
|
if (isClassInstance(o) && !(o instanceof cls || cls.Ⲑid === o.constructor.Ⲑid)) {
|
|
256
256
|
throw new TypeMismatchError(cls.name, o.constructor.name);
|
|
257
257
|
}
|
|
258
|
-
cls =
|
|
258
|
+
cls = SchemaRegistryIndex.resolveInstanceType(cls, o);
|
|
259
259
|
|
|
260
|
-
const
|
|
260
|
+
const fields = SchemaRegistryIndex.get(cls).getFields(view);
|
|
261
261
|
|
|
262
262
|
// Validate using standard behaviors
|
|
263
263
|
const errors = [
|
|
264
|
-
...this.#
|
|
264
|
+
...this.#validateFields(fields, o, ''),
|
|
265
265
|
... await this.#validateClassLevel(cls, o, view)
|
|
266
266
|
];
|
|
267
267
|
if (errors.length) {
|
|
@@ -311,19 +311,25 @@ export class SchemaValidator {
|
|
|
311
311
|
* @param method The method being invoked
|
|
312
312
|
* @param params The params to validate
|
|
313
313
|
*/
|
|
314
|
-
static async validateMethod<T>(cls: Class<T>, method: string, params: unknown[], prefixes: (string | undefined)[] = []): Promise<void> {
|
|
314
|
+
static async validateMethod<T>(cls: Class<T>, method: string | symbol, params: unknown[], prefixes: (string | symbol | undefined)[] = []): Promise<void> {
|
|
315
315
|
const errors: ValidationError[] = [];
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
const config = SchemaRegistryIndex.get(cls).getMethod(method);
|
|
317
|
+
|
|
318
|
+
for (const param of config.parameters) {
|
|
319
|
+
const i = param.index;
|
|
318
320
|
errors.push(...[
|
|
319
|
-
... this.#
|
|
320
|
-
... await this.#validateClassLevel(
|
|
321
|
+
... this.#validateInputSchema(param, params[i]),
|
|
322
|
+
... await this.#validateClassLevel(param.type, params[i])
|
|
321
323
|
].map(x => {
|
|
322
|
-
|
|
324
|
+
if (param.name && typeof param.name === 'string') {
|
|
325
|
+
x.path = !prefixes[i] ?
|
|
326
|
+
x.path.replace(`${param.name}.`, '') :
|
|
327
|
+
x.path.replace(param.name, prefixes[i]!.toString());
|
|
328
|
+
}
|
|
323
329
|
return x;
|
|
324
330
|
}));
|
|
325
331
|
}
|
|
326
|
-
for (const validator of
|
|
332
|
+
for (const validator of config.validators) {
|
|
327
333
|
const res = await validator(...params);
|
|
328
334
|
if (res) {
|
|
329
335
|
if (Array.isArray(res)) {
|