@travetto/schema 7.0.0-rc.1 → 7.0.0-rc.3

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.
@@ -7,14 +7,16 @@ import {
7
7
  CONSTRUCTOR_PROPERTY
8
8
  } from './types';
9
9
 
10
+ export type SchemaDiscriminatedInfo = Required<Pick<SchemaClassConfig, 'discriminatedType' | 'discriminatedField' | 'discriminatedBase'>>;
11
+
10
12
  const classToDiscriminatedType = (cls: Class): string => cls.name
11
- .replace(/([A-Z])([A-Z][a-z])/g, (all, l, r) => `${l}_${r.toLowerCase()}`)
12
- .replace(/([a-z]|\b)([A-Z])/g, (all, l, r) => l ? `${l}_${r.toLowerCase()}` : r.toLowerCase())
13
+ .replace(/([A-Z])([A-Z][a-z])/g, (all, left, right) => `${left}_${right.toLowerCase()}`)
14
+ .replace(/([a-z]|\b)([A-Z])/g, (all, left, right) => left ? `${left}_${right.toLowerCase()}` : right.toLowerCase())
13
15
  .toLowerCase();
14
16
 
15
17
  function assignMetadata<T>(key: symbol, base: SchemaCoreConfig, data: Partial<T>[]): T {
16
- const md = base.metadata ??= {};
17
- const out = md[key] ??= {};
18
+ const metadata = base.metadata ??= {};
19
+ const out = metadata[key] ??= {};
18
20
  for (const d of data) {
19
21
  safeAssign(out, d);
20
22
  }
@@ -69,6 +71,7 @@ function getConstructorConfig<T extends SchemaClassConfig>(base: Partial<T>, par
69
71
  const parentCons = parent?.methods?.[CONSTRUCTOR_PROPERTY];
70
72
  const baseCons = base.methods?.[CONSTRUCTOR_PROPERTY];
71
73
  return {
74
+ class: base.class!,
72
75
  parameters: [],
73
76
  validators: [],
74
77
  ...parentCons,
@@ -92,8 +95,8 @@ function combineClassWithParent<T extends SchemaClassConfig>(base: T, parent: T)
92
95
  case 'Required':
93
96
  case 'Partial': {
94
97
  base.fields = Object.fromEntries(
95
- Object.entries(parent.fields).map(([k, v]) => [k, {
96
- ...v,
98
+ Object.entries(parent.fields).map(([key, value]) => [key, {
99
+ ...value,
97
100
  required: {
98
101
  active: base.mappedOperation === 'Required'
99
102
  }
@@ -105,8 +108,8 @@ function combineClassWithParent<T extends SchemaClassConfig>(base: T, parent: T)
105
108
  case 'Omit': {
106
109
  const keys = new Set<string>(base.mappedFields ?? []);
107
110
  base.fields = Object.fromEntries(
108
- Object.entries(parent.fields).filter(([k]) =>
109
- base.mappedOperation === 'Pick' ? keys.has(k) : !keys.has(k)
111
+ Object.entries(parent.fields).filter(([key]) =>
112
+ base.mappedOperation === 'Pick' ? keys.has(key) : !keys.has(key)
110
113
  )
111
114
  );
112
115
  break;
@@ -145,7 +148,7 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
145
148
  }
146
149
 
147
150
  register(...data: Partial<SchemaClassConfig>[]): SchemaClassConfig {
148
- const cfg = this.#config ??= {
151
+ const config = this.#config ??= {
149
152
  methods: {},
150
153
  class: this.#cls,
151
154
  views: {},
@@ -153,38 +156,38 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
153
156
  interfaces: [],
154
157
  fields: {},
155
158
  };
156
- return combineClasses(cfg, data);
159
+ return combineClasses(config, data);
157
160
  }
158
161
 
159
162
  registerMetadata<T>(key: symbol, ...data: Partial<T>[]): T {
160
- const cfg = this.register({});
161
- return assignMetadata(key, cfg, data);
163
+ const config = this.register({});
164
+ return assignMetadata(key, config, data);
162
165
  }
163
166
 
164
167
  getMetadata<T>(key: symbol): T | undefined {
165
- const md = this.#config?.metadata;
166
- return castTo<T>(md?.[key]);
168
+ const metadata = this.#config?.metadata;
169
+ return castTo<T>(metadata?.[key]);
167
170
  }
168
171
 
169
- registerField(field: string | symbol, ...data: Partial<SchemaFieldConfig>[]): SchemaFieldConfig {
170
- const config = this.register({});
171
- const cfg = config.fields[field] ??= { name: field, owner: this.#cls, type: null! };
172
- const combined = combineInputs(cfg, data);
172
+ registerField(field: string, ...data: Partial<SchemaFieldConfig>[]): SchemaFieldConfig {
173
+ const classConfig = this.register({});
174
+ const config = classConfig.fields[field] ??= { name: field, class: this.#cls, type: null! };
175
+ const combined = combineInputs(config, data);
173
176
  return combined;
174
177
  }
175
178
 
176
- registerFieldMetadata<T>(field: string | symbol, key: symbol, ...data: Partial<T>[]): T {
177
- const cfg = this.registerField(field);
178
- return assignMetadata(key, cfg, data);
179
+ registerFieldMetadata<T>(field: string, key: symbol, ...data: Partial<T>[]): T {
180
+ const config = this.registerField(field);
181
+ return assignMetadata(key, config, data);
179
182
  }
180
183
 
181
- getFieldMetadata<T>(field: string | symbol, key: symbol): T | undefined {
182
- const md = this.#config?.fields[field]?.metadata;
183
- return castTo<T>(md?.[key]);
184
+ getFieldMetadata<T>(field: string, key: symbol): T | undefined {
185
+ const metadata = this.#config?.fields[field]?.metadata;
186
+ return castTo<T>(metadata?.[key]);
184
187
  }
185
188
 
186
- registerClass({ methods, ...cfg }: Partial<SchemaClassConfig> = {}): SchemaClassConfig {
187
- this.register({ ...cfg });
189
+ registerClass({ methods, ...config }: Partial<SchemaClassConfig> = {}): SchemaClassConfig {
190
+ this.register({ ...config });
188
191
  if (methods?.[CONSTRUCTOR_PROPERTY]) {
189
192
  const { parameters, ...rest } = methods[CONSTRUCTOR_PROPERTY];
190
193
  this.registerMethod(CONSTRUCTOR_PROPERTY, rest);
@@ -195,36 +198,36 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
195
198
  return this.#config;
196
199
  }
197
200
 
198
- registerMethod(method: string | symbol, ...data: Partial<SchemaMethodConfig>[]): SchemaMethodConfig {
199
- const config = this.register();
200
- const cfg = config.methods[method] ??= { parameters: [], validators: [] };
201
- return combineMethods(cfg, data);
201
+ registerMethod(method: string, ...data: Partial<SchemaMethodConfig>[]): SchemaMethodConfig {
202
+ const classConfig = this.register();
203
+ const config = classConfig.methods[method] ??= { class: this.#cls, parameters: [], validators: [] };
204
+ return combineMethods(config, data);
202
205
  }
203
206
 
204
- registerMethodMetadata<T>(method: string | symbol, key: symbol, ...data: Partial<T>[]): T {
205
- const cfg = this.registerMethod(method);
206
- return assignMetadata(key, cfg, data);
207
+ registerMethodMetadata<T>(method: string, key: symbol, ...data: Partial<T>[]): T {
208
+ const config = this.registerMethod(method);
209
+ return assignMetadata(key, config, data);
207
210
  }
208
211
 
209
- getMethodMetadata<T>(method: string | symbol, key: symbol): T | undefined {
210
- const md = this.#config?.methods[method]?.metadata;
211
- return castTo<T>(md?.[key]);
212
+ getMethodMetadata<T>(method: string, key: symbol): T | undefined {
213
+ const metadata = this.#config?.methods[method]?.metadata;
214
+ return castTo<T>(metadata?.[key]);
212
215
  }
213
216
 
214
- registerParameter(method: string | symbol, idx: number, ...data: Partial<SchemaParameterConfig>[]): SchemaParameterConfig {
217
+ registerParameter(method: string, idx: number, ...data: Partial<SchemaParameterConfig>[]): SchemaParameterConfig {
215
218
  const params = this.registerMethod(method, {}).parameters;
216
- const cfg = params[idx] ??= { method, index: idx, owner: this.#cls, array: false, type: null! };
217
- return combineInputs(cfg, data);
219
+ const config = params[idx] ??= { method, index: idx, class: this.#cls, array: false, type: null! };
220
+ return combineInputs(config, data);
218
221
  }
219
222
 
220
- registerParameterMetadata<T>(method: string | symbol, idx: number, key: symbol, ...data: Partial<T>[]): T {
221
- const cfg = this.registerParameter(method, idx);
222
- return assignMetadata(key, cfg, data);
223
+ registerParameterMetadata<T>(method: string, idx: number, key: symbol, ...data: Partial<T>[]): T {
224
+ const config = this.registerParameter(method, idx);
225
+ return assignMetadata(key, config, data);
223
226
  }
224
227
 
225
- getParameterMetadata<T>(method: string | symbol, idx: number, key: symbol): T | undefined {
226
- const md = this.#config?.methods[method]?.parameters[idx]?.metadata;
227
- return castTo<T>(md?.[key]);
228
+ getParameterMetadata<T>(method: string, idx: number, key: symbol): T | undefined {
229
+ const metadata = this.#config?.methods[method]?.parameters[idx]?.metadata;
230
+ return castTo<T>(metadata?.[key]);
228
231
  }
229
232
 
230
233
  finalize(parent?: SchemaClassConfig): void {
@@ -256,13 +259,13 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
256
259
  const fields = config.views[view];
257
260
  const withoutSet = 'without' in fields ? new Set<string>(fields.without) : undefined;
258
261
  const fieldList = withoutSet ?
259
- Object.keys(config.fields).filter(x => !withoutSet.has(x)) :
262
+ Object.keys(config.fields).filter(field => !withoutSet.has(field)) :
260
263
  ('with' in fields ? fields.with : []);
261
264
 
262
265
  this.#views.set(view,
263
- fieldList.reduce<SchemaFieldMap>((acc, v) => {
264
- acc[v] = config.fields[v];
265
- return acc;
266
+ fieldList.reduce<SchemaFieldMap>((map, value) => {
267
+ map[value] = config.fields[value];
268
+ return map;
266
269
  }, {})
267
270
  );
268
271
  }
@@ -278,19 +281,19 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
278
281
  return this.#config;
279
282
  }
280
283
 
281
- getField(field: string | symbol): SchemaFieldConfig {
284
+ getField(field: string): SchemaFieldConfig {
282
285
  return this.#config.fields[field];
283
286
  }
284
287
 
285
- getMethod(method: string | symbol): SchemaMethodConfig {
286
- const res = this.#config.methods[method];
287
- if (!res) {
288
+ getMethod(method: string): SchemaMethodConfig {
289
+ const methodConfig = this.#config.methods[method];
290
+ if (!methodConfig) {
288
291
  throw new AppError(`Unknown method ${String(method)} on class ${this.#cls.Ⲑid}`);
289
292
  }
290
- return res;
293
+ return methodConfig;
291
294
  }
292
295
 
293
- getMethodReturnType(method: string | symbol): Class {
296
+ getMethodReturnType(method: string): Class {
294
297
  return this.getMethod(method).returnType!.type;
295
298
  }
296
299
 
@@ -305,8 +308,8 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
305
308
  }
306
309
 
307
310
  /**
308
- * Provides the prototype-derived descriptor for a property
309
- */
311
+ * Provides the prototype-derived descriptor for a property
312
+ */
310
313
  getAccessorDescriptor(field: string): PropertyDescriptor {
311
314
  if (!this.#accessorDescriptors.has(field)) {
312
315
  let proto = this.#cls.prototype;
@@ -321,16 +324,16 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
321
324
  /**
322
325
  * Ensure type is set properly
323
326
  */
324
- ensureInstanceTypeField<T>(o: T): T {
327
+ ensureInstanceTypeField<T>(value: T): T {
325
328
  const config = this.getDiscriminatedConfig();
326
329
  if (config) {
327
330
  const typeField = castKey<T>(config.discriminatedField);
328
- o[typeField] ??= castTo(config.discriminatedType); // Assign if missing
331
+ value[typeField] ??= castTo(config.discriminatedType); // Assign if missing
329
332
  }
330
- return o;
333
+ return value;
331
334
  }
332
335
 
333
- getDiscriminatedConfig(): Required<Pick<SchemaClassConfig, 'discriminatedType' | 'discriminatedField' | 'discriminatedBase'>> | undefined {
336
+ getDiscriminatedConfig(): SchemaDiscriminatedInfo | undefined {
334
337
  const { discriminatedField, discriminatedType, discriminatedBase } = this.#config;
335
338
  if (discriminatedType && discriminatedField) {
336
339
  return { discriminatedType, discriminatedField, discriminatedBase: !!discriminatedBase };
@@ -1,9 +1,8 @@
1
- import { ChangeEvent, RegistrationMethods, RegistryIndex, RegistryIndexStore, Registry } from '@travetto/registry';
2
- import { AppError, castKey, castTo, Class, classConstruct, getParentClass, Util } from '@travetto/runtime';
1
+ import { RegistrationMethods, RegistryIndex, RegistryIndexStore, Registry } from '@travetto/registry';
2
+ import { AppError, castKey, castTo, Class, classConstruct, getParentClass } from '@travetto/runtime';
3
3
 
4
4
  import { SchemaFieldConfig, SchemaClassConfig } from './types.ts';
5
- import { SchemaRegistryAdapter } from './registry-adapter.ts';
6
- import { SchemaChangeListener } from './changes.ts';
5
+ import { SchemaDiscriminatedInfo, SchemaRegistryAdapter } from './registry-adapter.ts';
7
6
 
8
7
  /**
9
8
  * Schema registry index for managing schema configurations across classes
@@ -20,7 +19,7 @@ export class SchemaRegistryIndex implements RegistryIndex {
20
19
  return this.#instance.store.get(cls).get();
21
20
  }
22
21
 
23
- static getDiscriminatedConfig<T>(cls: Class<T>): Required<Pick<SchemaClassConfig, 'discriminatedType' | 'discriminatedField' | 'discriminatedBase'>> | undefined {
22
+ static getDiscriminatedConfig<T>(cls: Class<T>): SchemaDiscriminatedInfo | undefined {
24
23
  return this.#instance.store.get(cls).getDiscriminatedConfig();
25
24
  }
26
25
 
@@ -28,16 +27,12 @@ export class SchemaRegistryIndex implements RegistryIndex {
28
27
  return this.#instance.store.has(cls);
29
28
  }
30
29
 
31
- static getClassById(classId: string): Class {
32
- return this.#instance.store.getClassById(classId);
33
- }
34
-
35
30
  static getDiscriminatedTypes(cls: Class): string[] | undefined {
36
31
  return this.#instance.getDiscriminatedTypes(cls);
37
32
  }
38
33
 
39
- static resolveInstanceType<T>(cls: Class<T>, o: T): Class {
40
- return this.#instance.resolveInstanceType(cls, o);
34
+ static resolveInstanceType<T>(cls: Class<T>, item: T): Class {
35
+ return this.#instance.resolveInstanceType(cls, item);
41
36
  }
42
37
 
43
38
  static visitFields<T>(cls: Class<T>, onField: (field: SchemaFieldConfig, path: SchemaFieldConfig[]) => void): void {
@@ -68,6 +63,8 @@ export class SchemaRegistryIndex implements RegistryIndex {
68
63
  #baseSchema = new Map<Class, Class>();
69
64
  #byDiscriminatedTypes = new Map<Class, Map<string, Class>>();
70
65
 
66
+ /** @private */ constructor(source: unknown) { Registry.validateConstructor(source); }
67
+
71
68
  /**
72
69
  * Register discriminated types for a class
73
70
  */
@@ -84,44 +81,11 @@ export class SchemaRegistryIndex implements RegistryIndex {
84
81
  this.#byDiscriminatedTypes.get(base)!.set(config.discriminatedType, cls);
85
82
  }
86
83
 
87
- #onChanged(event: ChangeEvent<Class> & { type: 'changed' }): void {
88
- Util.queueMacroTask().then(() => {
89
- SchemaChangeListener.emitFieldChanges({
90
- type: 'changed',
91
- curr: this.getClassConfig(event.curr),
92
- prev: this.getClassConfig(event.prev)
93
- });
94
- });
95
- }
96
-
97
- #onRemoving(event: ChangeEvent<Class> & { type: 'removing' }): void {
98
- SchemaChangeListener.clearSchemaDependency(event.prev);
99
- }
100
-
101
- #onAdded(event: ChangeEvent<Class> & { type: 'added' }): void {
102
- Util.queueMacroTask().then(() => {
103
- SchemaChangeListener.emitFieldChanges({
104
- type: 'added',
105
- curr: this.getClassConfig(event.curr)
106
- });
107
- });
108
- }
109
-
110
- process(events: ChangeEvent<Class>[]): void {
111
- for (const event of events) {
112
- if (event.type === 'changed') {
113
- this.#onChanged(event);
114
- } else if (event.type === 'removing') {
115
- this.#onRemoving(event);
116
- } else if (event.type === 'added') {
117
- this.#onAdded(event);
118
- }
119
- }
120
-
84
+ beforeChangeSetComplete(): void {
121
85
  // Rebuild indices after every "process" batch
122
86
  this.#byDiscriminatedTypes.clear();
123
- for (const el of this.store.getClasses()) {
124
- this.#registerDiscriminatedTypes(el);
87
+ for (const cls of this.store.getClasses()) {
88
+ this.#registerDiscriminatedTypes(cls);
125
89
  }
126
90
  }
127
91
 
@@ -134,15 +98,15 @@ export class SchemaRegistryIndex implements RegistryIndex {
134
98
  */
135
99
  getBaseClass(cls: Class): Class {
136
100
  if (!this.#baseSchema.has(cls)) {
137
- let conf = this.getClassConfig(cls);
101
+ let config = this.getClassConfig(cls);
138
102
  let parent: Class | undefined = cls;
139
- while (parent && conf.discriminatedType && !conf.discriminatedBase) {
103
+ while (parent && config.discriminatedType && !config.discriminatedBase) {
140
104
  parent = getParentClass(parent);
141
105
  if (parent) {
142
- conf = this.store.getOptional(parent)?.get() ?? conf;
106
+ config = this.store.getOptional(parent)?.get() ?? config;
143
107
  }
144
108
  }
145
- this.#baseSchema.set(cls, conf.class);
109
+ this.#baseSchema.set(cls, config.class);
146
110
  }
147
111
  return this.#baseSchema.get(cls)!;
148
112
  }
@@ -150,16 +114,16 @@ export class SchemaRegistryIndex implements RegistryIndex {
150
114
  /**
151
115
  * Find the resolved type for a given instance
152
116
  * @param cls Class for instance
153
- * @param o Actual instance
117
+ * @param item Actual instance
154
118
  */
155
- resolveInstanceType<T>(cls: Class<T>, o: T): Class {
119
+ resolveInstanceType<T>(cls: Class<T>, item: T): Class {
156
120
  const { discriminatedField, discriminatedType, class: targetClass } = this.store.get(cls).get();
157
121
  if (!discriminatedField) {
158
122
  return targetClass;
159
123
  } else {
160
124
  const base = this.getBaseClass(targetClass);
161
125
  const map = this.#byDiscriminatedTypes.get(base);
162
- const type = castTo<string>(o[castKey<T>(discriminatedField)]) ?? discriminatedType;
126
+ const type = castTo<string>(item[castKey<T>(discriminatedField)]) ?? discriminatedType;
163
127
  if (!type) {
164
128
  throw new AppError(`Unable to resolve discriminated type for class ${base.name} without a type`);
165
129
  }
@@ -174,25 +138,6 @@ export class SchemaRegistryIndex implements RegistryIndex {
174
138
  }
175
139
  }
176
140
 
177
- /**
178
- * Track changes to schemas, and track the dependent changes
179
- * @param cls The root class of the hierarchy
180
- * @param curr The new class
181
- * @param path The path within the object hierarchy
182
- */
183
- trackSchemaDependencies(cls: Class, curr: Class = cls, path: SchemaFieldConfig[] = []): void {
184
- const config = this.getClassConfig(curr);
185
-
186
- SchemaChangeListener.trackSchemaDependency(curr, cls, path, this.getClassConfig(cls));
187
-
188
- // Read children
189
- for (const field of Object.values(config.fields)) {
190
- if (SchemaRegistryIndex.has(field.type) && field.type !== cls) {
191
- this.trackSchemaDependencies(cls, field.type, [...path, field]);
192
- }
193
- }
194
- }
195
-
196
141
  /**
197
142
  * Visit fields recursively
198
143
  */
@@ -3,7 +3,7 @@ import { Any, Class, Primitive } from '@travetto/runtime';
3
3
  import { MethodValidatorFn, ValidatorFn } from '../validate/types.ts';
4
4
 
5
5
  type TemplateLiteralPart = string | NumberConstructor | StringConstructor | BooleanConstructor;
6
- export type TemplateLiteral = { op: 'and' | 'or', values: (TemplateLiteralPart | TemplateLiteral)[] };
6
+ export type TemplateLiteral = { operation: 'and' | 'or', values: (TemplateLiteralPart | TemplateLiteral)[] };
7
7
 
8
8
  export const CONSTRUCTOR_PROPERTY = 'CONSTRUCTOR';
9
9
 
@@ -36,6 +36,10 @@ export type SchemaBasicType = {
36
36
  * Basic schema configuration
37
37
  */
38
38
  export interface SchemaCoreConfig {
39
+ /**
40
+ * Schema class
41
+ */
42
+ class: Class;
39
43
  /**
40
44
  * Description
41
45
  */
@@ -83,17 +87,13 @@ export interface SchemaFieldMap {
83
87
  /**
84
88
  * List of all fields
85
89
  */
86
- [key: string | symbol]: SchemaFieldConfig;
90
+ [key: string]: SchemaFieldConfig;
87
91
  }
88
92
 
89
93
  /**
90
94
  * Class configuration
91
95
  */
92
96
  export interface SchemaClassConfig extends SchemaCoreConfig {
93
- /**
94
- * Target class
95
- */
96
- class: Class;
97
97
  /**
98
98
  * List of all views
99
99
  */
@@ -121,7 +121,7 @@ export interface SchemaClassConfig extends SchemaCoreConfig {
121
121
  /**
122
122
  * Method configs
123
123
  */
124
- methods: Record<string | symbol, SchemaMethodConfig>;
124
+ methods: Record<string, SchemaMethodConfig>;
125
125
  /**
126
126
  * Interfaces that the class implements
127
127
  */
@@ -144,10 +144,6 @@ export interface SchemaInputConfig extends SchemaCoreConfig, SchemaBasicType {
144
144
  * Key name for validation when dealing with complex types
145
145
  */
146
146
  view?: string;
147
- /**
148
- * Owner class
149
- */
150
- owner: Class;
151
147
  /**
152
148
  * List of aliases
153
149
  */
@@ -167,23 +163,23 @@ export interface SchemaInputConfig extends SchemaCoreConfig, SchemaBasicType {
167
163
  /**
168
164
  * Does the field expect a match
169
165
  */
170
- match?: { re: RegExp, message?: string, template?: TemplateLiteral };
166
+ match?: { regex: RegExp, message?: string, template?: TemplateLiteral };
171
167
  /**
172
168
  * Minimum value configuration
173
169
  */
174
- min?: { n: number | Date, message?: string };
170
+ min?: { limit: number | Date, message?: string };
175
171
  /**
176
172
  * Maximum value configuration
177
173
  */
178
- max?: { n: number | Date, message?: string };
174
+ max?: { limit: number | Date, message?: string };
179
175
  /**
180
176
  * Minimum length configuration
181
177
  */
182
- minlength?: { n: number, message?: string };
178
+ minlength?: { limit: number, message?: string };
183
179
  /**
184
180
  * Maximum length configuration
185
181
  */
186
- maxlength?: { n: number, message?: string };
182
+ maxlength?: { limit: number, message?: string };
187
183
  /**
188
184
  * Enumerated values
189
185
  */
@@ -209,7 +205,7 @@ export interface SchemaParameterConfig extends SchemaInputConfig {
209
205
  /**
210
206
  * Method the parameter belongs to
211
207
  */
212
- method: string | symbol;
208
+ method: string;
213
209
  /**
214
210
  * Source text for the parameter
215
211
  */
@@ -223,7 +219,7 @@ export interface SchemaFieldConfig extends SchemaInputConfig {
223
219
  /**
224
220
  * Field name
225
221
  */
226
- name: string | symbol;
222
+ name: string;
227
223
  /**
228
224
  * Is the field readonly, or write only?, defaults to no restrictions
229
225
  */
package/src/types.ts CHANGED
@@ -3,6 +3,6 @@ export class UnknownType { }
3
3
  /**
4
4
  * Geometric Point as [number,number] with validation and binding support
5
5
  *
6
- * @concrete ./internal/types.ts#PointImpl
6
+ * @concrete ./internal/types.ts#PointContract
7
7
  */
8
8
  export type Point = [number, number];
@@ -22,6 +22,6 @@ export class TypeMismatchError extends AppError {
22
22
  }
23
23
  }
24
24
 
25
- export function isValidationError(err: unknown): err is ValidationError {
26
- return !!err && err instanceof Error && 'path' in err;
25
+ export function isValidationError(error: unknown): error is ValidationError {
26
+ return !!error && error instanceof Error && 'path' in error;
27
27
  }
@@ -5,14 +5,14 @@ export const Messages = new Map<string, string>(Object.entries({
5
5
  default: '{path} is not valid',
6
6
  type: '{path} is not a valid {type}',
7
7
  required: '{path} is required',
8
- minlength: '{path} is not long enough ({n})',
9
- maxlength: '{path} is too long ({n})',
10
- match: '{path} should match {re}',
11
- min: '{path} is less than ({n})',
12
- max: '{path} is greater than ({n})',
13
- telephone: '{path} is not a valid phone number',
14
- url: '{path} is not a valid url',
15
- simpleName: '{path} is not a proper name',
16
- postalCode: '{path} is not a valid postal code',
17
- email: '{path} is not a valid email address'
8
+ minlength: '{path} is not long enough ({limit})',
9
+ maxlength: '{path} is too long ({limit})',
10
+ match: '{path} should match {regex}',
11
+ min: '{path} is less than ({limit})',
12
+ max: '{path} is greater than ({limit})',
13
+ '[[:telephone:]]': '{path} is not a valid phone number',
14
+ '[[:url:]]': '{path} is not a valid url',
15
+ '[[:simpleName:]]': '{path} is not a proper name',
16
+ '[[:postalCode:]]': '{path} is not a valid postal code',
17
+ '[[:email:]]': '{path} is not a valid email address'
18
18
  }));
@@ -0,0 +1,22 @@
1
+ import { TypedObject } from '@travetto/runtime';
2
+
3
+ /**
4
+ * List of common regular expressions for fields
5
+ */
6
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
7
+ export const [CommonRegex, CommonRegexToName] = (() => {
8
+ const regexToName = new Map<RegExp, string>();
9
+ const regexes = {
10
+ email: /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
11
+ telephone: /^(\+?\d{1,3}(\s*-?\s*|\s+))?((\(\d{3}\))|\d{3})(\s*|-|[.])(\d{3})(\s*|-|[.])(\d{4})(\s+(x|ext[.]?)\s*\d+)?$/,
12
+ url: /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/,
13
+ simpleName: /^([a-zA-Z\u0080-\u024F]{0,100}(?:. |-| |')){0,10}[a-zA-Z\u0080-\u024F]+$/,
14
+ postalCode: /^\d{5}(?:[-\s]\d{4})?$/
15
+ };
16
+ // Rebind regexes
17
+ for (const key of TypedObject.keys(regexes)) {
18
+ const name = `[[:${key}:]]`;
19
+ regexToName.set(regexes[key], name);
20
+ }
21
+ return [regexes, regexToName];
22
+ })();
@@ -25,11 +25,11 @@ export interface ValidationError {
25
25
  /**
26
26
  * Regular expression to match
27
27
  */
28
- re?: string;
28
+ regex?: string;
29
29
  /**
30
30
  * Number to compare against
31
31
  */
32
- n?: number | Date;
32
+ limit?: number | Date;
33
33
  /**
34
34
  * The type of the field
35
35
  */
@@ -63,11 +63,11 @@ export interface ValidationResult {
63
63
  /**
64
64
  * Potential regular expression for the result
65
65
  */
66
- re?: RegExp;
66
+ regex?: RegExp;
67
67
  /**
68
68
  * Number to compare against
69
69
  */
70
- n?: number | Date;
70
+ limit?: number | Date;
71
71
  }
72
72
 
73
73
  type OrPromise<T> = T | Promise<T>;