@travetto/schema 2.1.5 → 2.2.2

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 CHANGED
@@ -25,7 +25,7 @@ The module utilizes AST transformations to collect schema information, and facil
25
25
  * `description` - detailed description of the schema
26
26
  * `examples` - A set of examples as [JSON](https://www.json.org) or [YAML](https://en.wikipedia.org/wiki/YAML)
27
27
 
28
- The `title` will be picked up from the [JSDoc](http://usejsdoc.org/about-getting-started.html) comments, and additionally all fields can be set using the [@Describe](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/common.ts#L11) decorator.
28
+ The `title` will be picked up from the [JSDoc](http://usejsdoc.org/about-getting-started.html) comments, and additionally all fields can be set using the [@Describe](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/common.ts#L15) decorator.
29
29
 
30
30
  **Code: Sample User Schema**
31
31
  ```typescript
@@ -69,16 +69,16 @@ This schema provides a powerful base for data binding and validation at runtime.
69
69
  * [@Enum](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L79) defines the allowable values that a field can have
70
70
  * [@Match](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L100) defines a regular expression that the field value should match
71
71
  * [@MinLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L108) enforces min length of a string
72
- * [@MaxLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L116) enforces max length of a string
72
+ * [@MaxLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L118) enforces max length of a string
73
73
  * [@Min](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L108) enforces min value for a date or a number
74
- * [@Max](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L116) enforces max value for a date or a number
75
- * [@Email](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L139) ensures string field matches basic email regex
76
- * [@Telephone](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L146) ensures string field matches basic telephone regex
77
- * [@Url](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L153) ensures string field matches basic url regex
78
- * [@Ignore](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L192) exclude from auto schema registration
79
- * [@Integer](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L167) ensures number passed in is only a whole number
80
- * [@Float](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L173) ensures number passed in allows fractional values
81
- * [@Currency](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L185) provides support for standard currency
74
+ * [@Max](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L118) enforces max value for a date or a number
75
+ * [@Email](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L145) ensures string field matches basic email regex
76
+ * [@Telephone](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L152) ensures string field matches basic telephone regex
77
+ * [@Url](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L159) ensures string field matches basic url regex
78
+ * [@Ignore](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L198) exclude from auto schema registration
79
+ * [@Integer](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L173) ensures number passed in is only a whole number
80
+ * [@Float](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L179) ensures number passed in allows fractional values
81
+ * [@Currency](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L191) provides support for standard currency
82
82
  * [@Text](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L87) indicates that a field is expecting natural language input, not just discrete values
83
83
  * [@LongText](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L92) same as text, but expects longer form content
84
84
  * [@Readonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L65) defines a that field should not be bindable external to the class
@@ -92,7 +92,7 @@ Just like the class, all fields can be defined with
92
92
  * `description` - detailed description of the schema
93
93
  * `examples` - A set of examples as [JSON](https://www.json.org) or [YAML](https://en.wikipedia.org/wiki/YAML)
94
94
 
95
- And similarly, the `description` will be picked up from the [JSDoc](http://usejsdoc.org/about-getting-started.html) comments, and additionally all fields can be set using the [@Describe](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/common.ts#L11) decorator.
95
+ And similarly, the `description` will be picked up from the [JSDoc](http://usejsdoc.org/about-getting-started.html) comments, and additionally all fields can be set using the [@Describe](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/common.ts#L15) decorator.
96
96
 
97
97
  ## Binding/Validation
98
98
  At runtime, once a schema is registered, a programmer can utilize this structure to perform specific operations. Specifically binding and validation.
@@ -124,7 +124,7 @@ A binding operation could look like:
124
124
  ```typescript
125
125
  import { Person } from './person';
126
126
 
127
- export function Test() {
127
+ export function Test(): Person {
128
128
  return Person.from({
129
129
  name: 'Test',
130
130
  age: 19.999978,
@@ -181,7 +181,7 @@ import { SchemaValidator } from '@travetto/schema';
181
181
 
182
182
  import { Person } from './person';
183
183
 
184
- export async function validate() {
184
+ export async function validate(): Promise<void> {
185
185
 
186
186
  const person = Person.from({
187
187
  name: 'Test',
@@ -210,15 +210,14 @@ Validation Failed {
210
210
  "errors": [
211
211
  {
212
212
  "kind": "type",
213
- "type": "number",
213
+ "message": "age is not a valid number",
214
214
  "path": "age",
215
- "message": "age is not a valid number"
215
+ "type": "number"
216
216
  },
217
217
  {
218
218
  "kind": "required",
219
- "active": true,
220
- "path": "address.street2",
221
- "message": "address.street2 is required"
219
+ "message": "address.street2 is required",
220
+ "path": "address.street2"
222
221
  }
223
222
  ]
224
223
  }
@@ -230,9 +229,9 @@ Within the schema framework, it is possible to add custom validators class level
230
229
 
231
230
  **Code: Password Validator**
232
231
  ```typescript
233
- import { Schema, Validator } from '@travetto/schema';
232
+ import { Schema, Validator, ValidationError } from '@travetto/schema';
234
233
 
235
- const passwordValidator = (user: User) => {
234
+ const passwordValidator = (user: User): ValidationError | undefined => {
236
235
  const p = user.password;
237
236
  const hasNum = /\d/.test(p);
238
237
  const hasSpecial = /[!@#$%%^&*()<>?/,.;':"']/.test(p);
@@ -307,38 +306,41 @@ In addition to the general types, the code relies upon name matching to provide
307
306
 
308
307
  **Code: Supported Mappings**
309
308
  ```typescript
310
- static #namesToType = {
311
- string: [
312
- [/^(image|img).*url$/, () => faker.image.imageUrl()],
313
- [/^url$/, () => faker.internet.url()],
314
- [/^email(addr(ress)?)?$/, () => faker.internet.email()],
315
- [/^(tele)?phone(num|number)?$/, () => faker.phone.phoneNumber()],
316
- [/^((postal|zip)code)|zip$/, () => faker.address.zipCode()],
317
- [/f(irst)?name/, () => faker.name.firstName()],
318
- [/l(ast)?name/, () => faker.name.lastName()],
319
- [/^ip(add(ress)?)?$/, () => faker.internet.ip()],
320
- [/^ip(add(ress)?)?(v?)6$/, () => faker.internet.ipv6()],
321
- [/^username$/, () => faker.internet.userName()],
322
- [/^domain(name)?$/, () => faker.internet.domainName()],
323
- [/^file(path|name)?$/, () => faker.system.filePath()],
324
- [/^street(1)?$/, () => faker.address.streetAddress()],
325
- [/^street2$/, () => faker.address.secondaryAddress()],
326
- [/^county$/, () => faker.address.county()],
327
- [/^country$/, () => faker.address.country()],
328
- [/^state$/, () => faker.address.state()],
329
- [/^lon(gitude)?$/, () => faker.address.longitude()],
330
- [/^lat(itude)?$/, () => faker.address.latitude()],
331
- [/(profile).*(image|img)/, () => faker.image.avatar()],
332
- [/(image|img)/, () => faker.image.image()],
333
- [/^company(name)?$/, () => faker.company.companyName()],
334
- [/(desc|description)$/, () => faker.lorem.sentences(10)]
335
- ] as [RegExp, () => string][],
336
- date: [
337
- [/dob|birth/, () => faker.date.past(60)],
338
- [/creat(e|ion)/, () => between(-200, -100)],
339
- [/(update|modif(y|ied))/, () => between(-100, -50)]
340
- ] as [RegExp, () => Date][],
341
- };
309
+ static #namesToType: {
310
+ string: [RegExp, () => string][];
311
+ date: [RegExp, () => Date][];
312
+ } = {
313
+ string: [
314
+ [/^(image|img).*url$/, (): string => faker.image.imageUrl()],
315
+ [/^url$/, (): string => faker.internet.url()],
316
+ [/^email(addr(ress)?)?$/, (): string => faker.internet.email()],
317
+ [/^(tele)?phone(num|number)?$/, (): string => faker.phone.phoneNumber()],
318
+ [/^((postal|zip)code)|zip$/, (): string => faker.address.zipCode()],
319
+ [/f(irst)?name/, (): string => faker.name.firstName()],
320
+ [/l(ast)?name/, (): string => faker.name.lastName()],
321
+ [/^ip(add(ress)?)?$/, (): string => faker.internet.ip()],
322
+ [/^ip(add(ress)?)?(v?)6$/, (): string => faker.internet.ipv6()],
323
+ [/^username$/, (): string => faker.internet.userName()],
324
+ [/^domain(name)?$/, (): string => faker.internet.domainName()],
325
+ [/^file(path|name)?$/, (): string => faker.system.filePath()],
326
+ [/^street(1)?$/, (): string => faker.address.streetAddress()],
327
+ [/^street2$/, (): string => faker.address.secondaryAddress()],
328
+ [/^county$/, (): string => faker.address.county()],
329
+ [/^country$/, (): string => faker.address.country()],
330
+ [/^state$/, (): string => faker.address.state()],
331
+ [/^lon(gitude)?$/, (): string => faker.address.longitude()],
332
+ [/^lat(itude)?$/, (): string => faker.address.latitude()],
333
+ [/(profile).*(image|img)/, (): string => faker.image.avatar()],
334
+ [/(image|img)/, (): string => faker.image.image()],
335
+ [/^company(name)?$/, (): string => faker.company.companyName()],
336
+ [/(desc|description)$/, (): string => faker.lorem.sentences(10)]
337
+ ],
338
+ date: [
339
+ [/dob|birth/, (): Date => faker.date.past(60)],
340
+ [/creat(e|ion)/, (): Date => between(-200, -100)],
341
+ [/(update|modif(y|ied))/, (): Date => between(-100, -50)]
342
+ ],
343
+ };
342
344
  ```
343
345
 
344
346
  An example of this would be:
@@ -366,7 +368,7 @@ class User {
366
368
  address: Address;
367
369
  }
368
370
 
369
- export function generate() {
371
+ export function generate(): User {
370
372
  const user = SchemaFakerUtil.generate(User);
371
373
  return user;
372
374
  }
@@ -392,7 +394,7 @@ export type Point = [number, number];
392
394
  const INVALID = Symbol.for('invalid-point');
393
395
 
394
396
  export class PointImpl {
395
- static validateSchema(input: unknown) {
397
+ static validateSchema(input: unknown): 'type' | undefined {
396
398
  const ret = this.bindSchema(input);
397
399
  return ret !== INVALID && ret && !isNaN(ret[0]) && !isNaN(ret[1]) ? undefined : 'type';
398
400
  }
@@ -439,9 +441,9 @@ Validation Failed {
439
441
  "errors": [
440
442
  {
441
443
  "kind": "type",
442
- "type": "PointImpl",
444
+ "message": "point is not a valid PointImpl",
443
445
  "path": "point",
444
- "message": "point is not a valid PointImpl"
446
+ "type": "PointImpl"
445
447
  }
446
448
  ]
447
449
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@travetto/schema",
3
3
  "displayName": "Schema",
4
- "version": "2.1.5",
4
+ "version": "2.2.2",
5
5
  "description": "Data type registry for runtime validation, reflection and binding. ",
6
6
  "keywords": [
7
7
  "schema",
@@ -29,8 +29,8 @@
29
29
  "directory": "module/schema"
30
30
  },
31
31
  "dependencies": {
32
- "@travetto/registry": "^2.1.5",
33
- "@travetto/transformer": "^2.1.4"
32
+ "@travetto/registry": "^2.2.2",
33
+ "@travetto/transformer": "^2.2.2"
34
34
  },
35
35
  "optionalPeerDependencies": {
36
36
  "@types/faker": "^5.5.9",
package/src/bind-util.ts CHANGED
@@ -28,15 +28,16 @@ export class BindUtil {
28
28
  }
29
29
  }
30
30
  }
31
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
31
32
  return val as T;
32
33
  }
33
34
 
34
35
  /**
35
36
  * Register `from` on the Function prototype
36
37
  */
37
- static register() {
38
+ static register(): void {
38
39
  const proto = Object.getPrototypeOf(Function);
39
- proto.from = function (data: object | ClassInstance, view?: string) {
40
+ proto.from = function (data: object | ClassInstance, view?: string): unknown {
40
41
  return BindUtil.bindSchema(this, data, view);
41
42
  };
42
43
  }
@@ -48,10 +49,11 @@ export class BindUtil {
48
49
  *
49
50
  * @param obj The object to convert
50
51
  */
51
- static expandPaths(obj: Record<string, unknown>) {
52
+ static expandPaths(obj: Record<string, unknown>): Record<string, unknown> {
52
53
  const out: Record<string, unknown> = {};
53
54
  for (const k of Object.keys(obj)) {
54
- const val = Util.isPlainObject(obj[k]) ? this.expandPaths(obj[k] as Record<string, unknown>) : obj[k];
55
+ const objK = obj[k];
56
+ const val = Util.isPlainObject(objK) ? this.expandPaths(objK) : objK;
55
57
  const parts = k.split('.');
56
58
  const last = parts.pop()!;
57
59
  let sub = out;
@@ -65,12 +67,14 @@ export class BindUtil {
65
67
  if (!(name in sub)) {
66
68
  sub[name] = typeof key === 'number' ? [] : {};
67
69
  }
70
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
68
71
  sub = sub[name] as Record<string, unknown>;
69
72
 
70
73
  if (idx && key !== undefined) {
71
74
  if (sub[key] === undefined) {
72
75
  sub[key] = {};
73
76
  }
77
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
74
78
  sub = sub[key] as Record<string, unknown>;
75
79
  }
76
80
  }
@@ -88,8 +92,10 @@ export class BindUtil {
88
92
  let key = arr ? (/^\d+$/.test(idx) ? parseInt(idx, 10) : (idx.trim() || undefined)) : undefined;
89
93
  if (sub[name] === undefined) {
90
94
  sub[name] = (typeof key === 'string') ? {} : [];
95
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
91
96
  sub = sub[name] as Record<string, unknown>;
92
97
  if (key === undefined) {
98
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
93
99
  key = sub.length as number;
94
100
  }
95
101
  if (sub[key] && Util.isPlainObject(val) && Util.isPlainObject(sub[key])) {
@@ -108,7 +114,7 @@ export class BindUtil {
108
114
  * @param conf The object to flatten the paths for
109
115
  * @param val The starting prefix
110
116
  */
111
- static flattenPaths(data: Record<string, unknown>, prefix: string = '') {
117
+ static flattenPaths(data: Record<string, unknown>, prefix: string = ''): Record<string, unknown> {
112
118
  const out: Record<string, unknown> = {};
113
119
  for (const [key, value] of Object.entries(data)) {
114
120
  const pre = `${prefix}${key}`;
@@ -144,18 +150,23 @@ export class BindUtil {
144
150
  if (data === null || data === undefined) {
145
151
  return data;
146
152
  }
147
- const cls = SchemaRegistry.resolveSubTypeForInstance(cons, data) as Class<T>;
153
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
154
+ const cls = SchemaRegistry.resolveSubTypeForInstance<T>(cons, data as T);
148
155
  if (data instanceof cls) {
156
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
149
157
  return data as T;
150
158
  } else {
159
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
151
160
  const tgt = new (cls as ConcreteClass<T>)();
152
161
  SchemaRegistry.ensureInstanceTypeField(cls, tgt);
153
162
 
154
163
  for (const [k, v] of Object.entries(tgt)) { // Do not retain undefined fields
155
164
  if (v === undefined) {
165
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
156
166
  delete tgt[k as keyof T];
157
167
  }
158
168
  }
169
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
159
170
  return this.bindSchemaToObject(cls, tgt, data as object, view);
160
171
  }
161
172
  }
@@ -175,7 +186,8 @@ export class BindUtil {
175
186
 
176
187
  // If no configuration
177
188
  if (!conf) {
178
- for (const k of Object.keys(data) as (keyof typeof obj)[]) {
189
+ for (const k of Object.keys(data)) {
190
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
179
191
  obj[k] = data[k as keyof typeof data];
180
192
  }
181
193
  } else {
@@ -205,7 +217,8 @@ export class BindUtil {
205
217
  continue;
206
218
  }
207
219
 
208
- let v = data[inboundField as keyof typeof data] as unknown;
220
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
221
+ let v: unknown = data[inboundField as keyof typeof data];
209
222
 
210
223
  if (v !== undefined && v !== null) {
211
224
  const config = viewConf.schema[schemaFieldName];
@@ -228,6 +241,7 @@ export class BindUtil {
228
241
  }
229
242
  }
230
243
 
244
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
231
245
  obj[schemaFieldName as keyof typeof obj] = v as (typeof obj)[keyof typeof obj];
232
246
  }
233
247
  }
@@ -243,23 +257,21 @@ export class BindUtil {
243
257
  * @param applyDefaults
244
258
  * @returns
245
259
  */
246
- static coerceField(field: FieldConfig, val: unknown, applyDefaults = false) {
260
+ static coerceField(field: FieldConfig, val: unknown, applyDefaults = false): unknown {
247
261
  if ((val === undefined || val === null) && applyDefaults) {
248
262
  val = field.default;
249
263
  }
250
264
  const complex = SchemaRegistry.has(field.type);
251
265
  if (field.array) {
252
- if (!Array.isArray(val)) {
253
- val = [val];
254
- }
266
+ const valArr = !Array.isArray(val) ? [val] : val;
255
267
  if (complex) {
256
- val = (val as unknown[]).map(x => this.bindSchema(field.type, x as object, field.view));
268
+ val = valArr.map(x => this.bindSchema(field.type, x, field.view));
257
269
  } else {
258
- val = (val as unknown[]).map(x => Util.coerceType(x, field.type, false));
270
+ val = valArr.map(x => Util.coerceType(x, field.type, false));
259
271
  }
260
272
  } else {
261
273
  if (complex) {
262
- val = this.bindSchema(field.type, val as object, field.view);
274
+ val = this.bindSchema(field.type, val, field.view);
263
275
  } else {
264
276
  val = Util.coerceType(val, field.type, false);
265
277
  }
@@ -3,20 +3,24 @@ import { Class, ClassInstance } from '@travetto/base';
3
3
  import { DescribableConfig } from '../service/types';
4
4
  import { SchemaRegistry } from '../service/registry';
5
5
 
6
+ function isClassInstance(o: Class | ClassInstance, property?: string): o is ClassInstance {
7
+ return !!property;
8
+ }
9
+
6
10
  /**
7
11
  * Describe a model or a field
8
12
  * @param config The describe configuration
9
13
  * @augments `@trv:schema/Describe`
10
14
  */
11
15
  export function Describe(config: Partial<DescribableConfig>) {
12
- return (target: Class | ClassInstance, property?: string, descOrIdx?: PropertyDescriptor | number) => {
13
- if (property) {
16
+ return (target: Class | ClassInstance, property?: string, descOrIdx?: PropertyDescriptor | number): void => {
17
+ if (isClassInstance(target, property)) {
14
18
  if (descOrIdx !== undefined && typeof descOrIdx === 'number') {
15
19
  property = `${property}.${descOrIdx}`;
16
20
  }
17
- SchemaRegistry.registerPendingFieldFacet((target as ClassInstance).constructor, property!, config);
21
+ SchemaRegistry.registerPendingFieldFacet(target.constructor, property!, config);
18
22
  } else {
19
- SchemaRegistry.register(target as Class, config);
23
+ SchemaRegistry.register(target, config);
20
24
  }
21
25
  };
22
26
  }
@@ -5,7 +5,7 @@ import { CommonRegExp } from '../validate/regexp';
5
5
  import { ClassList, FieldConfig } from '../service/types';
6
6
 
7
7
  function prop(obj: Partial<FieldConfig>) {
8
- return (t: ClassInstance, k: string, idx?: number | PropertyDescriptor) => {
8
+ return (t: ClassInstance, k: string, idx?: number | PropertyDescriptor): void => {
9
9
  if (idx !== undefined && typeof idx === 'number') {
10
10
  SchemaRegistry.registerPendingParamFacet(t.constructor, k, idx, obj);
11
11
  } else {
@@ -14,20 +14,20 @@ function prop(obj: Partial<FieldConfig>) {
14
14
  };
15
15
  }
16
16
 
17
- const stringArrProp = prop as
18
- (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, string | unknown[]>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void;
17
+ // eslint-disable-next-line max-len
18
+ const stringArrProp: (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, string | unknown[]>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void = prop;
19
19
 
20
- const stringArrStringProp = prop as
21
- (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, string | string[]>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void;
20
+ // eslint-disable-next-line max-len
21
+ const stringArrStringProp: (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, string | string[]>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void = prop;
22
22
 
23
- const numberProp = prop as
24
- (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, number>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void;
23
+ // eslint-disable-next-line max-len
24
+ const numberProp: (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, number>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void = prop;
25
25
 
26
- const stringNumberProp = prop as
27
- (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, string | number>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void;
26
+ // eslint-disable-next-line max-len
27
+ const stringNumberProp: (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, string | number>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void = prop;
28
28
 
29
- const dateNumberProp = prop as
30
- (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, Date | number>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void;
29
+ // eslint-disable-next-line max-len
30
+ const dateNumberProp: (obj: Partial<FieldConfig>) => <T extends Partial<Record<K, Date | number>>, K extends string>(t: T, k: K, idx?: number | PropertyDescriptor) => void = prop;
31
31
 
32
32
  /**
33
33
  * Registering a field
@@ -36,7 +36,7 @@ const dateNumberProp = prop as
36
36
  * @augments `@trv:schema/Field`
37
37
  */
38
38
  export function Field(type: ClassList, config?: Partial<FieldConfig>) {
39
- return (f: ClassInstance, k: string, idx?: number | PropertyDescriptor) => {
39
+ return (f: ClassInstance, k: string, idx?: number | PropertyDescriptor): void => {
40
40
  if (idx !== undefined && typeof idx === 'number') {
41
41
  SchemaRegistry.registerPendingParamConfig(f.constructor, k, idx, type, config);
42
42
  } else {
@@ -50,33 +50,33 @@ export function Field(type: ClassList, config?: Partial<FieldConfig>) {
50
50
  * @param aliases List of all aliases for a field
51
51
  * @augments `@trv:schema/Field`
52
52
  */
53
- export function Alias(...aliases: string[]) { return prop({ aliases }); }
53
+ export function Alias(...aliases: string[]): ReturnType<typeof prop> { return prop({ aliases }); }
54
54
  /**
55
55
  * Mark a field as writeonly
56
56
  * @param active This determines if this field is readonly or not.
57
57
  * @augments `@trv:schema/Field`
58
58
  */
59
- export function Writeonly(active = true) { return prop({ access: 'writeonly' }); }
59
+ export function Writeonly(active = true): ReturnType<typeof prop> { return prop({ access: 'writeonly' }); }
60
60
  /**
61
61
  * Mark a field as readonly
62
62
  * @param active This determines if this field is readonly or not.
63
63
  * @augments `@trv:schema/Field`
64
64
  */
65
- export function Readonly(active = true) { return prop({ access: 'readonly' }); }
65
+ export function Readonly(active = true): ReturnType<typeof prop> { return prop({ access: 'readonly' }); }
66
66
  /**
67
67
  * Mark a field as required
68
68
  * @param active This determines if this field is required or not.
69
69
  * @param message The error message when a the constraint fails.
70
70
  * @augments `@trv:schema/Field`
71
71
  */
72
- export function Required(active = true, message?: string) { return prop({ required: { active, message } }); }
72
+ export function Required(active = true, message?: string): ReturnType<typeof prop> { return prop({ required: { active, message } }); }
73
73
  /**
74
74
  * Define a field as a set of enumerated values
75
- * @param vals The list of values allowed for the enumeration
75
+ * @param values The list of values allowed for the enumeration
76
76
  * @param message The error message to show when the constraint fails
77
77
  * @augments `@trv:schema/Field`
78
78
  */
79
- export function Enum(values: string[], message?: string) {
79
+ export function Enum(values: string[], message?: string): ReturnType<typeof stringNumberProp> {
80
80
  message = message || `{path} is only allowed to be "${values.join('" or "')}"`;
81
81
  return stringNumberProp({ enum: { values, message } });
82
82
  }
@@ -84,12 +84,12 @@ export function Enum(values: string[], message?: string) {
84
84
  * Mark the field as indicating it's storing textual data
85
85
  * @augments `@trv:schema/Field`
86
86
  */
87
- export function Text() { return stringArrStringProp({ specifier: 'text' }); }
87
+ export function Text(): ReturnType<typeof stringArrStringProp> { return stringArrStringProp({ specifier: 'text' }); }
88
88
  /**
89
89
  * Mark the field to indicate it's for long form text
90
90
  * @augments `@trv:schema/Field`
91
91
  */
92
- export function LongText() { return stringArrStringProp({ specifier: 'text-long' }); }
92
+ export function LongText(): ReturnType<typeof stringArrStringProp> { return stringArrStringProp({ specifier: 'text-long' }); }
93
93
 
94
94
  /**
95
95
  * Require the field to match a specific RegExp
@@ -97,7 +97,7 @@ export function LongText() { return stringArrStringProp({ specifier: 'text-long'
97
97
  * @param message The message to show when the constraint fails
98
98
  * @augments `@trv:schema/Field`
99
99
  */
100
- export function Match(re: RegExp, message?: string) { return stringArrStringProp({ match: { re, message } }); }
100
+ export function Match(re: RegExp, message?: string): ReturnType<typeof stringArrStringProp> { return stringArrStringProp({ match: { re, message } }); }
101
101
 
102
102
  /**
103
103
  * The minimum length for the string or array
@@ -105,7 +105,9 @@ export function Match(re: RegExp, message?: string) { return stringArrStringProp
105
105
  * @param message The message to show when the constraint fails
106
106
  * @augments `@trv:schema/Field`
107
107
  */
108
- export function MinLength(n: number, message?: string) { return stringArrProp({ minlength: { n, message }, ...(n === 0 ? { required: { active: false } } : {}) }); }
108
+ export function MinLength(n: number, message?: string): ReturnType<typeof stringArrProp> {
109
+ return stringArrProp({ minlength: { n, message }, ...(n === 0 ? { required: { active: false } } : {}) });
110
+ }
109
111
 
110
112
  /**
111
113
  * The maximum length for the string or array
@@ -113,7 +115,7 @@ export function MinLength(n: number, message?: string) { return stringArrProp({
113
115
  * @param message The message to show when the constraint fails
114
116
  * @augments `@trv:schema/Field`
115
117
  */
116
- export function MaxLength(n: number, message?: string) { return stringArrProp({ maxlength: { n, message } }); }
118
+ export function MaxLength(n: number, message?: string): ReturnType<typeof stringArrProp> { return stringArrProp({ maxlength: { n, message } }); }
117
119
 
118
120
  /**
119
121
  * The minimum value
@@ -121,7 +123,9 @@ export function MaxLength(n: number, message?: string) { return stringArrProp({
121
123
  * @param message The message to show when the constraint fails
122
124
  * @augments `@trv:schema/Field`
123
125
  */
124
- export function Min<T extends number | Date>(n: T, message?: string) { return dateNumberProp({ min: { n, message } }); }
126
+ export function Min<T extends number | Date>(n: T, message?: string): ReturnType<typeof dateNumberProp> {
127
+ return dateNumberProp({ min: { n, message } });
128
+ }
125
129
 
126
130
  /**
127
131
  * The maximum value
@@ -129,28 +133,30 @@ export function Min<T extends number | Date>(n: T, message?: string) { return da
129
133
  * @param message The message to show when the constraint fails
130
134
  * @augments `@trv:schema/Field`
131
135
  */
132
- export function Max<T extends number | Date>(n: T, message?: string) { return dateNumberProp({ max: { n, message } }); }
136
+ export function Max<T extends number | Date>(n: T, message?: string): ReturnType<typeof dateNumberProp> {
137
+ return dateNumberProp({ max: { n, message } });
138
+ }
133
139
 
134
140
  /**
135
141
  * Mark a field as an email
136
142
  * @param message The message to show when the constraint fails
137
143
  * @augments `@trv:schema/Field`
138
144
  */
139
- export function Email(message?: string) { return Match(CommonRegExp.email, message); }
145
+ export function Email(message?: string): ReturnType<typeof Match> { return Match(CommonRegExp.email, message); }
140
146
 
141
147
  /**
142
148
  * Mark a field as an telephone number
143
149
  * @param message The message to show when the constraint fails
144
150
  * @augments `@trv:schema/Field`
145
151
  */
146
- export function Telephone(message?: string) { return Match(CommonRegExp.telephone, message); }
152
+ export function Telephone(message?: string): ReturnType<typeof Match> { return Match(CommonRegExp.telephone, message); }
147
153
 
148
154
  /**
149
155
  * Mark a field as a url
150
156
  * @param message The message to show when the constraint fails
151
157
  * @augments `@trv:schema/Field`
152
158
  */
153
- export function Url(message?: string) { return Match(CommonRegExp.url, message); }
159
+ export function Url(message?: string): ReturnType<typeof Match> { return Match(CommonRegExp.url, message); }
154
160
 
155
161
  /**
156
162
  * Determine the numeric precision of the value
@@ -158,31 +164,31 @@ export function Url(message?: string) { return Match(CommonRegExp.url, message);
158
164
  * @param decimals The number of decimal digits to support
159
165
  * @augments `@trv:schema/Field`
160
166
  */
161
- export function Precision(digits: number, decimals?: number) { return numberProp({ precision: [digits, decimals] }); }
167
+ export function Precision(digits: number, decimals?: number): ReturnType<typeof numberProp> { return numberProp({ precision: [digits, decimals] }); }
162
168
 
163
169
  /**
164
170
  * Mark a number as an integer
165
171
  * @augments `@trv:schema/Field`
166
172
  */
167
- export function Integer() { return Precision(0); }
173
+ export function Integer(): ReturnType<typeof numberProp> { return Precision(0); }
168
174
 
169
175
  /**
170
176
  * Mark a number as a float
171
177
  * @augments `@trv:schema/Field`
172
178
  */
173
- export function Float() { return Precision(10, 7); }
179
+ export function Float(): ReturnType<typeof numberProp> { return Precision(10, 7); }
174
180
 
175
181
  /**
176
182
  * Mark a number as a long value
177
183
  * @augments `@trv:schema/Field`
178
184
  */
179
- export function Long() { return Precision(19, 0); }
185
+ export function Long(): ReturnType<typeof numberProp> { return Precision(19, 0); }
180
186
 
181
187
  /**
182
188
  * Mark a number as a currency
183
189
  * @augments `@trv:schema/Field`
184
190
  */
185
- export function Currency() { return Precision(13, 2); }
191
+ export function Currency(): ReturnType<typeof numberProp> { return Precision(13, 2); }
186
192
 
187
193
  /**
188
194
  * Mark a field as ignored
@@ -22,7 +22,8 @@ export function Schema() { // Auto is used during compilation
22
22
  * @param fn The validator function
23
23
  */
24
24
  export function Validator<T>(fn: ValidatorFn<T, string>) {
25
- return (target: Class<T>) => {
25
+ return (target: Class<T>): void => {
26
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
27
  SchemaRegistry.getOrCreatePending(target).validators!.push(fn as ValidatorFn<unknown, unknown>);
27
28
  };
28
29
  }
@@ -33,7 +34,7 @@ export function Validator<T>(fn: ValidatorFn<T, string>) {
33
34
  * @param fields The specific fields to add as part of a view
34
35
  */
35
36
  export function View<T>(name: string, fields: ViewFieldsConfig<Partial<T>>) {
36
- return (target: Class<Partial<T>>) => {
37
+ return (target: Class<Partial<T>>): void => {
37
38
  SchemaRegistry.registerPendingView(target, name, fields);
38
39
  };
39
40
  }
@@ -44,7 +45,7 @@ export function View<T>(name: string, fields: ViewFieldsConfig<Partial<T>>) {
44
45
  * @returns
45
46
  */
46
47
  export function SubType<T>(name: string) {
47
- return (target: Class<Partial<T>>) => {
48
+ return (target: Class<Partial<T>>): void => {
48
49
  SchemaRegistry.registerSubTypes(target, name);
49
50
  };
50
51
  }