@travetto/schema 3.1.0-rc.0 → 3.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/schema",
3
- "version": "3.1.0-rc.0",
3
+ "version": "3.1.0-rc.1",
4
4
  "description": "Data type registry for runtime validation, reflection and binding.",
5
5
  "keywords": [
6
6
  "schema",
@@ -16,9 +16,10 @@ export function Describe(config: Partial<DescribableConfig>) {
16
16
  return (target: Class | ClassInstance, property?: string, descOrIdx?: PropertyDescriptor | number): void => {
17
17
  if (isClassInstance(target, property)) {
18
18
  if (descOrIdx !== undefined && typeof descOrIdx === 'number') {
19
- property = `${property}.${descOrIdx}`;
19
+ SchemaRegistry.registerPendingParamFacet(target.constructor, property!, descOrIdx, config);
20
+ } else {
21
+ SchemaRegistry.registerPendingFieldFacet(target.constructor, property!, config);
20
22
  }
21
- SchemaRegistry.registerPendingFieldFacet(target.constructor, property!, config);
22
23
  } else {
23
24
  SchemaRegistry.register(target, config);
24
25
  }
@@ -28,7 +28,6 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
28
28
  #subTypes = new Map<Class, Map<string, Class>>();
29
29
  #typeKeys = new Map<Class, string>();
30
30
  #pendingViews = new Map<Class, Map<string, ViewFieldsConfig<unknown>>>();
31
- #methodSchemas = new Map<Class, Map<string, FieldConfig[]>>();
32
31
 
33
32
  constructor() {
34
33
  super(RootRegistry);
@@ -191,6 +190,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
191
190
  validators: [],
192
191
  subType: false,
193
192
  metadata: {},
193
+ methods: {},
194
194
  views: {
195
195
  [AllViewⲐ]: {
196
196
  schema: {},
@@ -225,22 +225,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
225
225
  * @param method
226
226
  */
227
227
  getMethodSchema<T>(cls: Class<T>, method: string): FieldConfig[] {
228
- if (!this.#methodSchemas.has(cls)) {
229
- this.#methodSchemas.set(cls, new Map());
230
- }
231
- const cache = this.#methodSchemas.get(cls)!;
232
- if (!cache.has(method) && this.has(cls)) {
233
- const { fields, schema } = this.getViewSchema(cls);
234
- const out = [];
235
- for (const el of fields) {
236
- if (el.startsWith(`${method}.`) && schema[el].forMethod) {
237
- out.push(schema[el]);
238
- }
239
- }
240
- out.sort((a, b) => a.index! - b.index!);
241
- cache.set(method, out);
242
- }
243
- return cache.get(method)! ?? [];
228
+ return (this.get(cls)?.methods?.[method] ?? []).filter(x => !!x).sort((a, b) => a.index! - b.index!);
244
229
  }
245
230
 
246
231
  /**
@@ -265,9 +250,18 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
265
250
  * @param idx The param index
266
251
  * @param config The config to register
267
252
  */
268
- registerPendingParamFacet(target: Class, prop: string, idx: number, config: Partial<FieldConfig>): Class {
269
- config.index = idx;
270
- return this.registerPendingFieldFacet(target, `${prop}.${idx}`, config);
253
+ registerPendingParamFacet(target: Class, method: string, idx: number, config: Partial<FieldConfig>): Class {
254
+ const methods = this.getOrCreatePending(target)!.methods!;
255
+ const params = (methods[method] ??= []);
256
+ params[idx] = {
257
+ // @ts-expect-error
258
+ name: `${method}.${idx}`,
259
+ ...params[idx] ?? {},
260
+ owner: target,
261
+ index: idx,
262
+ ...config,
263
+ };
264
+ return target;
271
265
  }
272
266
 
273
267
  /**
@@ -300,10 +294,11 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
300
294
  * @param conf Extra config
301
295
  */
302
296
  registerPendingParamConfig(target: Class, method: string, idx: number, type: ClassList, conf?: Partial<FieldConfig>): Class {
303
- conf ??= {};
304
- conf.index = idx;
305
- conf.forMethod = true;
306
- return this.registerPendingFieldConfig(target, `${method}.${idx}`, type, conf);
297
+ return this.registerPendingParamFacet(target, method, idx, {
298
+ ...conf,
299
+ array: Array.isArray(type),
300
+ type: Array.isArray(type) ? type[0] : type,
301
+ });
307
302
  }
308
303
 
309
304
  /**
@@ -335,6 +330,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
335
330
  schema: { ...dest.views[AllViewⲐ].schema, ...src.views?.[AllViewⲐ].schema },
336
331
  fields: [...dest.views[AllViewⲐ].fields, ...src.views?.[AllViewⲐ].fields ?? []]
337
332
  };
333
+ dest.methods = { ...src.methods ?? {}, ...dest.methods ?? {} };
338
334
  dest.metadata = { ...src.metadata ?? {}, ...dest.metadata ?? {} };
339
335
  dest.subType = src.subType || dest.subType;
340
336
  dest.title = src.title || dest.title;
@@ -411,7 +407,6 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
411
407
  // Recompute subtypes
412
408
  this.#subTypes.clear();
413
409
  this.#typeKeys.delete(cls);
414
- this.#methodSchemas.delete(cls);
415
410
  this.#accessorDescriptors.delete(cls);
416
411
 
417
412
  // Recompute subtype mappings
@@ -71,6 +71,10 @@ export interface ClassConfig extends DescribableConfig {
71
71
  * Metadata that is related to the schema structure
72
72
  */
73
73
  metadata?: Record<symbol, unknown>;
74
+ /**
75
+ * Method parameter configs
76
+ */
77
+ methods: Record<string, FieldConfig[]>;
74
78
  }
75
79
 
76
80
  /**
@@ -160,10 +164,6 @@ export interface FieldConfig extends DescribableConfig {
160
164
  * Is this field a getter or setter
161
165
  */
162
166
  accessor?: string;
163
- /**
164
- * Is the field for a method
165
- */
166
- forMethod?: boolean;
167
167
  }
168
168
 
169
169
  export type ViewFieldsConfig<T> = { with: Extract<(keyof T), string>[] } | { without: Extract<(keyof T), string>[] };
@@ -40,7 +40,7 @@ export class SchemaValidator {
40
40
 
41
41
  const fields = TypedObject.keys<SchemaConfig>(schema);
42
42
  for (const field of fields) {
43
- if (schema[field].access !== 'readonly' && !schema[field].forMethod) { // Do not validate readonly fields
43
+ if (schema[field].access !== 'readonly') { // Do not validate readonly fields
44
44
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
45
45
  errors = errors.concat(this.#validateFieldSchema(schema[field], o[field as keyof T], relative));
46
46
  }
@@ -107,20 +107,24 @@ export class SchemaValidator {
107
107
  static #validateRange(field: FieldConfig, key: 'min' | 'max', value: string | number | Date): boolean {
108
108
 
109
109
  const f = field[key]!;
110
- if (typeof f.n === 'number') {
110
+ const fn = f.n;
111
+ if (typeof fn === 'number') {
111
112
  if (typeof value === 'string') {
112
113
  value = parseInt(value, 10);
113
114
  }
114
115
  if (field.type === Date) {
115
116
  value = new Date(value);
116
117
  }
117
- if (key === 'min' && value < f.n || key === 'max' && value > f.n) {
118
+ const valN = typeof value === 'number' ? value : value.getTime();
119
+ if (key === 'min' && valN < fn || key === 'max' && valN > fn) {
118
120
  return true;
119
121
  }
120
122
  } else {
121
- const date = f.n.getTime();
123
+ const date = fn.getTime();
122
124
  if (typeof value === 'string') {
123
125
  value = Date.parse(value);
126
+ } else if (value instanceof Date) {
127
+ value = value.getTime();
124
128
  }
125
129
  if (key === 'min' && value < date || key === 'max' && value > date) {
126
130
  return true;