@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.
package/src/data.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { isNumberObject as isNum, isBooleanObject as isBool, isStringObject as isStr } from 'node:util/types';
1
+ import { isNumberObject, isBooleanObject, isStringObject } from 'node:util/types';
2
2
 
3
3
  import { asConstructable, castTo, Class, asFull, TypedObject } from '@travetto/runtime';
4
4
  import { UnknownType } from './types.ts';
@@ -12,24 +12,26 @@ export class DataUtil {
12
12
 
13
13
  /**
14
14
  * Is a value a plain JS object, created using {}
15
- * @param obj Object to check
15
+ * @param value Object to check
16
16
  */
17
- static isPlainObject(obj: unknown): obj is Record<string, unknown> {
18
- return typeof obj === 'object' // separate from primitives
19
- && obj !== undefined
20
- && obj !== null // is obvious
21
- && obj.constructor === Object // separate instances (Array, DOM, ...)
22
- && Object.prototype.toString.call(obj) === '[object Object]'; // separate build-in like Math
17
+ static isPlainObject(value: unknown): value is Record<string, unknown> {
18
+ return typeof value === 'object' // separate from primitives
19
+ && value !== undefined
20
+ && value !== null // is obvious
21
+ && value.constructor === Object // separate instances (Array, DOM, ...)
22
+ && Object.prototype.toString.call(value) === '[object Object]'; // separate build-in like Math
23
23
  }
24
24
 
25
25
  /**
26
26
  * Is a value of primitive type
27
- * @param el Value to check
27
+ * @param value Value to check
28
28
  */
29
- static isPrimitive(el: unknown): el is (string | boolean | number | RegExp) {
30
- switch (typeof el) {
29
+ static isPrimitive(value: unknown): value is (string | boolean | number | RegExp) {
30
+ switch (typeof value) {
31
31
  case 'string': case 'boolean': case 'number': case 'bigint': return true;
32
- case 'object': return !!el && (el instanceof RegExp || el instanceof Date || isStr(el) || isNum(el) || isBool(el));
32
+ case 'object': return !!value && (
33
+ value instanceof RegExp || value instanceof Date || isStringObject(value) || isNumberObject(value) || isBooleanObject(value)
34
+ );
33
35
  default: return false;
34
36
  }
35
37
  }
@@ -37,8 +39,8 @@ export class DataUtil {
37
39
  /**
38
40
  * Is simple, as a primitive, function or class
39
41
  */
40
- static isSimpleValue(a: unknown): a is Function | Class | string | number | RegExp | Date {
41
- return this.isPrimitive(a) || typeof a === 'function';
42
+ static isSimpleValue(value: unknown): value is Function | Class | string | number | RegExp | Date {
43
+ return this.isPrimitive(value) || typeof value === 'function';
42
44
  }
43
45
 
44
46
  static #deepAssignRaw(a: unknown, b: unknown, mode: 'replace' | 'loose' | 'strict' | 'coerce' = 'loose'): unknown {
@@ -68,10 +70,10 @@ export class DataUtil {
68
70
  if (mode === 'replace') {
69
71
  value = b;
70
72
  } else {
71
- const retArr: unknown[] = castTo(value);
72
- const bArr = b;
73
- for (let i = 0; i < bArr.length; i++) {
74
- retArr[i] = this.#deepAssignRaw(retArr[i], bArr[i], mode);
73
+ const valueArray: unknown[] = castTo(value);
74
+ const bArray = b;
75
+ for (let i = 0; i < bArray.length; i++) {
76
+ valueArray[i] = this.#deepAssignRaw(valueArray[i], bArray[i], mode);
75
77
  }
76
78
  }
77
79
  } else if (isSimpB) { // Scalars
@@ -87,14 +89,14 @@ export class DataUtil {
87
89
  }
88
90
  } else { // Object merge
89
91
  value = a;
90
- const bObj: Record<string, unknown> = castTo(b);
91
- const retObj: Record<string, unknown> = castTo(value);
92
+ const bObject: Record<string, unknown> = castTo(b);
93
+ const valueObject: Record<string, unknown> = castTo(value);
92
94
 
93
- for (const key of Object.keys(bObj)) {
95
+ for (const key of Object.keys(bObject)) {
94
96
  if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
95
97
  continue;
96
98
  }
97
- retObj[key] = this.#deepAssignRaw(retObj[key], bObj[key], mode);
99
+ valueObject[key] = this.#deepAssignRaw(valueObject[key], bObject[key], mode);
98
100
  }
99
101
  }
100
102
  }
@@ -119,7 +121,7 @@ export class DataUtil {
119
121
  /**
120
122
  * Coerce an input of any type to the class provided
121
123
  * @param input Input value
122
- * @param type Class to coerce to (String, Boolean, Number, Date, RegEx, Object)
124
+ * @param type Class to coerce to (String, Boolean, Number, Date, RegExp, Object)
123
125
  * @param strict Should a failure to coerce throw an error?
124
126
  */
125
127
  static coerceType(input: unknown, type: typeof String, strict?: boolean): string;
@@ -226,10 +228,10 @@ export class DataUtil {
226
228
 
227
229
  /**
228
230
  * Clone top level properties to a new object
229
- * @param o Object to clone
231
+ * @param value Object to clone
230
232
  */
231
- static shallowClone<T>(a: T): T {
232
- return castTo(Array.isArray(a) ? a.slice(0) : (this.isSimpleValue(a) ? a : { ...castTo<object>(a) }));
233
+ static shallowClone<T>(value: T): T {
234
+ return castTo(Array.isArray(value) ? value.slice(0) : (this.isSimpleValue(value) ? value : { ...castTo<object>(value) }));
233
235
  }
234
236
 
235
237
  /**
@@ -247,29 +249,28 @@ export class DataUtil {
247
249
 
248
250
  /**
249
251
  * Filter object by excluding specific keys
250
- * @param obj A value to filter, primitives will be untouched
252
+ * @param input A value to filter, primitives will be untouched
251
253
  * @param exclude Strings or patterns to exclude against
252
254
  * @returns
253
255
  */
254
- static filterByKeys<T>(obj: T, exclude: (string | RegExp)[]): T {
255
- if (Array.isArray(obj)) {
256
- return castTo(obj.map(x => this.filterByKeys(x, exclude)));
257
- } else if (obj !== null && obj !== undefined && typeof obj === 'object') {
256
+ static filterByKeys<T>(input: T, exclude: (string | RegExp)[]): T {
257
+ if (Array.isArray(input)) {
258
+ return castTo(input.map(value => this.filterByKeys(value, exclude)));
259
+ } else if (input !== null && input !== undefined && typeof input === 'object') {
258
260
  const out: Partial<T> = {};
259
- for (const key of TypedObject.keys(obj)) {
260
- if (!exclude.some(r => typeof key === 'string' && (typeof r === 'string' ? r === key : r.test(key)))) {
261
- const val = obj[key];
262
- if (typeof val === 'object') {
263
- out[key] = this.filterByKeys(val, exclude);
261
+ for (const key of TypedObject.keys(input)) {
262
+ if (!exclude.some(toMatch => typeof key === 'string' && (typeof toMatch === 'string' ? toMatch === key : toMatch.test(key)))) {
263
+ const value = input[key];
264
+ if (typeof value === 'object') {
265
+ out[key] = this.filterByKeys(value, exclude);
264
266
  } else {
265
- out[key] = val;
267
+ out[key] = value;
266
268
  }
267
269
  }
268
270
  }
269
271
  return asFull(out);
270
272
  } else {
271
- return obj;
273
+ return input;
272
274
  }
273
275
  }
274
-
275
276
  }
@@ -10,14 +10,14 @@ import { SchemaRegistryIndex } from '../service/registry-index.ts';
10
10
  * @kind decorator
11
11
  */
12
12
  export function Describe(config: Partial<Omit<SchemaCoreConfig, 'metadata'>>) {
13
- return (instanceOrCls: Class | ClassInstance, property?: string | symbol, descOrIdx?: PropertyDescriptor | number): void => {
13
+ return (instanceOrCls: Class | ClassInstance, property?: string, descriptorOrIdx?: PropertyDescriptor | number): void => {
14
14
  const adapter = SchemaRegistryIndex.getForRegister(getClass(instanceOrCls));
15
15
  if (!property) {
16
16
  adapter.register(config);
17
17
  } else {
18
- if (descOrIdx !== undefined && typeof descOrIdx === 'number') {
19
- adapter.registerParameter(property, descOrIdx, config);
20
- } else if (typeof descOrIdx === 'object' && typeof descOrIdx.value === 'function') {
18
+ if (descriptorOrIdx !== undefined && typeof descriptorOrIdx === 'number') {
19
+ adapter.registerParameter(property, descriptorOrIdx, config);
20
+ } else if (typeof descriptorOrIdx === 'object' && typeof descriptorOrIdx.value === 'function') {
21
21
  adapter.registerMethod(property, config);
22
22
  } else {
23
23
  adapter.registerField(property, config);
@@ -31,7 +31,7 @@ export function Describe(config: Partial<Omit<SchemaCoreConfig, 'metadata'>>) {
31
31
  * @augments `@travetto/schema:Input`
32
32
  * @kind decorator
33
33
  */
34
- export const IsPrivate = (): (instanceOrCls: Class | ClassInstance, property?: string | symbol) => void => Describe({ private: true });
34
+ export const IsPrivate = (): (instanceOrCls: Class | ClassInstance, property?: string) => void => Describe({ private: true });
35
35
 
36
36
  /**
37
37
  * Mark a field/method as ignored
@@ -3,23 +3,25 @@ import { Any, ClassInstance, getClass } from '@travetto/runtime';
3
3
  import { SchemaFieldConfig } from '../service/types.ts';
4
4
  import { SchemaRegistryIndex } from '../service/registry-index.ts';
5
5
 
6
- type PropType<V> = (<T extends Partial<Record<K, V | Function>>, K extends string>(t: T, k: K, idx?: TypedPropertyDescriptor<Any> | number) => void);
6
+ type PropType<V> = (<T extends Partial<Record<K, V | Function>>, K extends string>(
7
+ instance: T, property: K, idx?: TypedPropertyDescriptor<Any> | number
8
+ ) => void);
7
9
 
8
- function field<V>(...obj: Partial<SchemaFieldConfig>[]): PropType<V> {
9
- return (instance: ClassInstance, property: string | symbol): void => {
10
- SchemaRegistryIndex.getForRegister(getClass(instance)).registerField(property, ...obj);
10
+ function field<V>(...configs: Partial<SchemaFieldConfig>[]): PropType<V> {
11
+ return (instance: ClassInstance, property: string): void => {
12
+ SchemaRegistryIndex.getForRegister(getClass(instance)).registerField(property, ...configs);
11
13
  };
12
14
  }
13
15
 
14
16
  /**
15
17
  * Registering a field
16
18
  * @param type The type for the field
17
- * @param config The field configuration
19
+ * @param configs The field configuration
18
20
  * @augments `@travetto/schema:Input`
19
21
  * @kind decorator
20
22
  */
21
- export function Field(type: Pick<SchemaFieldConfig, 'type' | 'array'>, ...config: Partial<SchemaFieldConfig>[]): PropType<unknown> {
22
- return field(type, ...config);
23
+ export function Field(type: Pick<SchemaFieldConfig, 'type' | 'array'>, ...configs: Partial<SchemaFieldConfig>[]): PropType<unknown> {
24
+ return field(type, ...configs);
23
25
  }
24
26
 
25
27
  /**
@@ -1,19 +1,21 @@
1
1
  import { Any, Class, ClassInstance, getClass } from '@travetto/runtime';
2
2
 
3
- import { CommonRegExp } from '../validate/regexp.ts';
3
+ import { CommonRegex } from '../validate/regex.ts';
4
4
  import { CONSTRUCTOR_PROPERTY, SchemaInputConfig } from '../service/types.ts';
5
5
  import { SchemaRegistryIndex } from '../service/registry-index.ts';
6
6
 
7
- type PropType<V> = (<T extends Partial<Record<K, V | Function>>, K extends string>(t: T, k: K, idx?: TypedPropertyDescriptor<Any> | number) => void);
7
+ type PropType<V> = (<T extends Partial<Record<K, V | Function>>, K extends string>(
8
+ instance: T, property: K, idx?: TypedPropertyDescriptor<Any> | number
9
+ ) => void);
8
10
 
9
- function input<V>(...obj: Partial<SchemaInputConfig>[]): PropType<V> {
10
- return (instanceOrCls: ClassInstance | Class, property: string | symbol, idx?: number | TypedPropertyDescriptor<Any>): void => {
11
+ function input<V>(...configs: Partial<SchemaInputConfig>[]): PropType<V> {
12
+ return (instanceOrCls: ClassInstance | Class, property: string, idx?: number | TypedPropertyDescriptor<Any>): void => {
11
13
  const adapter = SchemaRegistryIndex.getForRegister(getClass(instanceOrCls));
12
14
  const propertyKey = property ?? CONSTRUCTOR_PROPERTY;
13
15
  if (typeof idx === 'number') {
14
- adapter.registerParameter(propertyKey, idx, ...obj);
16
+ adapter.registerParameter(propertyKey, idx, ...configs);
15
17
  } else {
16
- adapter.registerField(propertyKey, ...obj);
18
+ adapter.registerField(propertyKey, ...configs);
17
19
  }
18
20
  };
19
21
  }
@@ -21,12 +23,12 @@ function input<V>(...obj: Partial<SchemaInputConfig>[]): PropType<V> {
21
23
  /**
22
24
  * Registering an input
23
25
  * @param type The type for the input
24
- * @param config The input configuration
26
+ * @param configs The input configuration
25
27
  * @augments `@travetto/schema:Input`
26
28
  * @kind decorator
27
29
  */
28
- export function Input(type: Pick<SchemaInputConfig, 'type' | 'array'>, ...config: Partial<SchemaInputConfig>[]): PropType<unknown> {
29
- return input(type, ...config);
30
+ export function Input(type: Pick<SchemaInputConfig, 'type' | 'array'>, ...configs: Partial<SchemaInputConfig>[]): PropType<unknown> {
31
+ return input(type, ...configs);
30
32
  }
31
33
 
32
34
  /**
@@ -74,53 +76,53 @@ export function LongText(): PropType<string | string[]> { return input({ specifi
74
76
 
75
77
  /**
76
78
  * Require the input to match a specific RegExp
77
- * @param re The regular expression to match against
79
+ * @param regex The regular expression to match against
78
80
  * @param message The message to show when the constraint fails
79
81
  * @augments `@travetto/schema:Input`
80
82
  * @kind decorator
81
83
  */
82
- export function Match(re: RegExp, message?: string): PropType<string | string[]> { return input({ match: { re, message } }); }
84
+ export function Match(regex: RegExp, message?: string): PropType<string | string[]> { return input({ match: { regex, message } }); }
83
85
 
84
86
  /**
85
87
  * The minimum length for the string or array
86
- * @param n The minimum length
88
+ * @param limit The minimum length
87
89
  * @param message The message to show when the constraint fails
88
90
  * @augments `@travetto/schema:Input`
89
91
  * @kind decorator
90
92
  */
91
- export function MinLength(n: number, message?: string): PropType<string | unknown[]> {
92
- return input({ minlength: { n, message }, ...(n === 0 ? { required: { active: false } } : {}) });
93
+ export function MinLength(limit: number, message?: string): PropType<string | unknown[]> {
94
+ return input({ minlength: { limit, message }, ...(limit === 0 ? { required: { active: false } } : {}) });
93
95
  }
94
96
 
95
97
  /**
96
98
  * The maximum length for the string or array
97
- * @param n The maximum length
99
+ * @param limit The maximum length
98
100
  * @param message The message to show when the constraint fails
99
101
  * @augments `@travetto/schema:Input`
100
102
  * @kind decorator
101
103
  */
102
- export function MaxLength(n: number, message?: string): PropType<string | unknown[]> { return input({ maxlength: { n, message } }); }
104
+ export function MaxLength(limit: number, message?: string): PropType<string | unknown[]> { return input({ maxlength: { limit, message } }); }
103
105
 
104
106
  /**
105
107
  * The minimum value
106
- * @param n The minimum value
108
+ * @param limit The minimum value
107
109
  * @param message The message to show when the constraint fails
108
110
  * @augments `@travetto/schema:Input`
109
111
  * @kind decorator
110
112
  */
111
- export function Min<T extends number | Date>(n: T, message?: string): PropType<Date | number> {
112
- return input({ min: { n, message } });
113
+ export function Min<T extends number | Date>(limit: T, message?: string): PropType<Date | number> {
114
+ return input({ min: { limit, message } });
113
115
  }
114
116
 
115
117
  /**
116
118
  * The maximum value
117
- * @param n The maximum value
119
+ * @param limit The maximum value
118
120
  * @param message The message to show when the constraint fails
119
121
  * @augments `@travetto/schema:Input`
120
122
  * @kind decorator
121
123
  */
122
- export function Max<T extends number | Date>(n: T, message?: string): PropType<Date | number> {
123
- return input({ max: { n, message } });
124
+ export function Max<T extends number | Date>(limit: T, message?: string): PropType<Date | number> {
125
+ return input({ max: { limit, message } });
124
126
  }
125
127
 
126
128
  /**
@@ -129,7 +131,7 @@ export function Max<T extends number | Date>(n: T, message?: string): PropType<D
129
131
  * @augments `@travetto/schema:Input`
130
132
  * @kind decorator
131
133
  */
132
- export function Email(message?: string): PropType<string | string[]> { return Match(CommonRegExp.email, message); }
134
+ export function Email(message?: string): PropType<string | string[]> { return Match(CommonRegex.email, message); }
133
135
 
134
136
  /**
135
137
  * Mark an input as an telephone number
@@ -137,7 +139,7 @@ export function Email(message?: string): PropType<string | string[]> { return Ma
137
139
  * @augments `@travetto/schema:Input`
138
140
  * @kind decorator
139
141
  */
140
- export function Telephone(message?: string): PropType<string | string[]> { return Match(CommonRegExp.telephone, message); }
142
+ export function Telephone(message?: string): PropType<string | string[]> { return Match(CommonRegex.telephone, message); }
141
143
 
142
144
  /**
143
145
  * Mark an input as a url
@@ -145,7 +147,7 @@ export function Telephone(message?: string): PropType<string | string[]> { retur
145
147
  * @augments `@travetto/schema:Input`
146
148
  * @kind decorator
147
149
  */
148
- export function Url(message?: string): PropType<string | string[]> { return Match(CommonRegExp.url, message); }
150
+ export function Url(message?: string): PropType<string | string[]> { return Match(CommonRegex.url, message); }
149
151
 
150
152
  /**
151
153
  * Determine the numeric precision of the value
@@ -197,7 +199,7 @@ export function Specifier(...specifiers: string[]): PropType<unknown> { return i
197
199
  * @augments `@travetto/schema:Input`
198
200
  * @kind decorator
199
201
  */
200
- export function DiscriminatorField(): ((t: ClassInstance, k: string) => void) {
202
+ export function DiscriminatorField(): ((instance: ClassInstance, property: string) => void) {
201
203
  return (instance: ClassInstance, property: string): void => {
202
204
  SchemaRegistryIndex.getForRegister(getClass(instance)).register({
203
205
  discriminatedBase: true,
@@ -4,6 +4,8 @@ import { SchemaMethodConfig } from '../service/types';
4
4
  import { SchemaRegistryIndex } from '../service/registry-index';
5
5
  import { MethodValidatorFn } from '../validate/types';
6
6
 
7
+ type MethodDecorator = (instance: ClassInstance, property: string, descriptor: PropertyDescriptor) => PropertyDescriptor | void;
8
+
7
9
  /**
8
10
  * Registering a method
9
11
  * @param config The method configuration
@@ -11,7 +13,7 @@ import { MethodValidatorFn } from '../validate/types';
11
13
  * @kind decorator
12
14
  */
13
15
  export function Method(...config: Partial<SchemaMethodConfig>[]) {
14
- return (instanceOrCls: ClassInstance, property: string | symbol): void => {
16
+ return (instanceOrCls: ClassInstance, property: string): void => {
15
17
  SchemaRegistryIndex.getForRegister(getClass(instanceOrCls)).registerMethod(property, ...config);
16
18
  };
17
19
  }
@@ -16,12 +16,12 @@ type ValidStringField<T> = { [K in Extract<keyof T, string>]: T[K] extends strin
16
16
  * @augments `@travetto/schema:Schema`
17
17
  * @kind decorator
18
18
  */
19
- export function Schema(cfg?: Partial<Pick<SchemaClassConfig, 'validators' | 'methods'>>) {
19
+ export function Schema(config?: Partial<Pick<SchemaClassConfig, 'validators' | 'methods'>>) {
20
20
  return <T, U extends Class<T>>(cls: U): void => {
21
21
  cls.from ??= function <V>(this: Class<V>, data: DeepPartial<V>, view?: string): V {
22
22
  return BindUtil.bindSchema(this, data, { view });
23
23
  };
24
- SchemaRegistryIndex.getForRegister(cls).registerClass(cfg);
24
+ SchemaRegistryIndex.getForRegister(cls).registerClass(config);
25
25
  };
26
26
  }
27
27
 
@@ -3,9 +3,9 @@ import { DataUtil } from '../data.ts';
3
3
  const InvalidSymbol = Symbol();
4
4
 
5
5
  /**
6
- * Point Implementation
6
+ * Point Contract
7
7
  */
8
- export class PointImpl {
8
+ export class PointContract {
9
9
 
10
10
  /**
11
11
  * Validate we have an actual point
@@ -20,7 +20,7 @@ export class PointImpl {
20
20
  */
21
21
  static bindSchema(input: unknown): [number, number] | typeof InvalidSymbol | undefined {
22
22
  if (Array.isArray(input) && input.length === 2) {
23
- const [a, b] = input.map(x => DataUtil.coerceType(x, Number, false));
23
+ const [a, b] = input.map(value => DataUtil.coerceType(value, Number, false));
24
24
  return [a, b];
25
25
  } else {
26
26
  return InvalidSymbol;
@@ -28,4 +28,4 @@ export class PointImpl {
28
28
  }
29
29
  }
30
30
 
31
- Object.defineProperty(PointImpl, 'name', { value: 'Point' });
31
+ Object.defineProperty(PointContract, 'name', { value: 'Point' });
package/src/name.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SchemaClassConfig } from './service/types.ts';
2
2
 
3
- const ID_RE = /(\d{1,100})Δ$/;
3
+ const ID_REGEX = /(\d{1,100})Δ$/;
4
4
 
5
5
  /**
6
6
  * Name resolver, specifically for synthetic types
@@ -17,9 +17,9 @@ export class SchemaNameResolver {
17
17
  getName(schema: SchemaClassConfig): string {
18
18
  const cls = schema.class;
19
19
  const id = cls.Ⲑid;
20
- if (ID_RE.test(cls.name)) {
20
+ if (ID_REGEX.test(cls.name)) {
21
21
  if (!this.#schemaIdToName.has(id)) {
22
- const name = cls.name.replace(ID_RE, (_, uid) => uid.slice(-this.#digits));
22
+ const name = cls.name.replace(ID_REGEX, (_, uniqueId) => uniqueId.slice(-this.#digits));
23
23
  this.#schemaIdToName.set(id, name);
24
24
  }
25
25
  return this.#schemaIdToName.get(id)!;