@travetto/schema 3.1.0-rc.1 → 3.1.0-rc.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
@@ -62,25 +62,25 @@ User:
62
62
 
63
63
  ### Fields
64
64
  This schema provides a powerful base for data binding and validation at runtime. Additionally there may be types that cannot be detected, or some information that the programmer would like to override. Below are the supported field decorators:
65
- * [@Field](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L38) defines a field that will be serialized.
66
- * [@Required](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L78) defines a that field should be required
67
- * [@Enum](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L85) defines the allowable values that a field can have
68
- * [@Match](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L106) defines a regular expression that the field value should match
69
- * [@MinLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L114) enforces min length of a string
70
- * [@MaxLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L124) enforces max length of a string
71
- * [@Min](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L114) enforces min value for a date or a number
72
- * [@Max](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L124) enforces max value for a date or a number
73
- * [@Email](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L151) ensures string field matches basic email regex
74
- * [@Telephone](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L158) ensures string field matches basic telephone regex
75
- * [@Url](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L165) ensures string field matches basic url regex
76
- * [@Ignore](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L204) exclude from auto schema registration
77
- * [@Integer](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L179) ensures number passed in is only a whole number
78
- * [@Float](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L185) ensures number passed in allows fractional values
79
- * [@Currency](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L197) provides support for standard currency
80
- * [@Text](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L93) indicates that a field is expecting natural language input, not just discrete values
81
- * [@LongText](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L98) same as text, but expects longer form content
82
- * [@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
83
- * [@Writeonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L59) defines a that field should not be exported in serialization, but that it can be bound to
65
+ * [@Field](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L31) defines a field that will be serialized.
66
+ * [@Required](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L71) defines a that field should be required
67
+ * [@Enum](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L78) defines the allowable values that a field can have
68
+ * [@Match](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L99) defines a regular expression that the field value should match
69
+ * [@MinLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L107) enforces min length of a string
70
+ * [@MaxLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L117) enforces max length of a string
71
+ * [@Min](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L107) enforces min value for a date or a number
72
+ * [@Max](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L117) enforces max value for a date or a number
73
+ * [@Email](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L144) ensures string field matches basic email regex
74
+ * [@Telephone](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L151) ensures string field matches basic telephone regex
75
+ * [@Url](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L158) ensures string field matches basic url regex
76
+ * [@Ignore](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L197) exclude from auto schema registration
77
+ * [@Integer](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L172) ensures number passed in is only a whole number
78
+ * [@Float](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L178) ensures number passed in allows fractional values
79
+ * [@Currency](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L190) provides support for standard currency
80
+ * [@Text](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L86) indicates that a field is expecting natural language input, not just discrete values
81
+ * [@LongText](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L91) same as text, but expects longer form content
82
+ * [@Readonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L58) defines a that field should not be bindable external to the class
83
+ * [@Writeonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L52) defines a that field should not be exported in serialization, but that it can be bound to
84
84
  Additionally, schemas can be nested to form more complex data structures that are able to bound and validated.
85
85
 
86
86
  Just like the class, all fields can be defined with
@@ -88,6 +88,22 @@ Just like the class, all fields can be defined with
88
88
  * `examples` - A set of examples as [JSON](https://www.json.org) or [YAML](https://en.wikipedia.org/wiki/YAML)
89
89
  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.
90
90
 
91
+ ### Parameters
92
+ Parameters are available in certain scenarios (e.g. [RESTful API](https://github.com/travetto/travetto/tree/main/module/rest#readme "Declarative api for RESTful APIs with support for the dependency injection module.") endpoints and [Command Line Interface](https://github.com/travetto/travetto/tree/main/module/cli#readme "CLI infrastructure for Travetto framework") main methods). In these scenarios, all of the field decorators are valid, but need to be called slightly differently to pass the typechecker. The simple solution is to use the `Arg` field of the decorator to convince Typescript its the correct type.
93
+
94
+ **Code: Sample Parameter Usage**
95
+ ```typescript
96
+ import { Match, Min } from '../__index__';
97
+
98
+ const NAME_REGEX = /[A-Z][a-z]+(\s+[A-Z][a-z]+)*/;
99
+
100
+ export class ParamUsage {
101
+ main(@Match(NAME_REGEX).Param name: string, @Min(20).Param age?: number) {
102
+ console.log('Valid name and age!', { name, age });
103
+ }
104
+ }
105
+ ```
106
+
91
107
  ## Binding/Validation
92
108
  At runtime, once a schema is registered, a programmer can utilize this structure to perform specific operations. Specifically binding and validation.
93
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/schema",
3
- "version": "3.1.0-rc.1",
3
+ "version": "3.1.0-rc.2",
4
4
  "description": "Data type registry for runtime validation, reflection and binding.",
5
5
  "keywords": [
6
6
  "schema",
@@ -30,7 +30,7 @@
30
30
  "@travetto/registry": "^3.1.0-rc.0"
31
31
  },
32
32
  "peerDependencies": {
33
- "@travetto/transformer": "^3.1.0-rc.0"
33
+ "@travetto/transformer": "^3.1.0-rc.1"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@travetto/transformer": {
@@ -4,30 +4,23 @@ import { SchemaRegistry } from '../service/registry';
4
4
  import { CommonRegExp } from '../validate/regexp';
5
5
  import { ClassList, FieldConfig } from '../service/types';
6
6
 
7
- function prop(obj: Partial<FieldConfig>) {
8
- return (t: ClassInstance, k: string, idx?: number | PropertyDescriptor): void => {
7
+ type PropType<V> = (<T extends Partial<Record<K, V>>, K extends string>(t: T, k: K, idx?: number) => void) & {
8
+ Param: (t: unknown, k: string, idx: number) => void;
9
+ };
10
+
11
+ function prop<V>(obj: Partial<FieldConfig>): PropType<V> {
12
+ const fn = (t: ClassInstance, k: string, idx?: number): void => {
9
13
  if (idx !== undefined && typeof idx === 'number') {
10
14
  SchemaRegistry.registerPendingParamFacet(t.constructor, k, idx, obj);
11
15
  } else {
12
16
  SchemaRegistry.registerPendingFieldFacet(t.constructor, k, obj);
13
17
  }
14
18
  };
15
- }
16
-
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
-
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;
19
+ fn.Param = fn; // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
22
20
 
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
-
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
-
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;
21
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
22
+ return fn as PropType<V>;
23
+ }
31
24
 
32
25
  /**
33
26
  * Registering a field
@@ -36,7 +29,7 @@ const dateNumberProp: (obj: Partial<FieldConfig>) => <T extends Partial<Record<K
36
29
  * @augments `@travetto/schema:Field`
37
30
  */
38
31
  export function Field(type: ClassList, config?: Partial<FieldConfig>) {
39
- return (f: ClassInstance, k: string, idx?: number | PropertyDescriptor): void => {
32
+ return (f: ClassInstance, k: string, idx?: number): void => {
40
33
  if (idx !== undefined && typeof idx === 'number') {
41
34
  SchemaRegistry.registerPendingParamConfig(f.constructor, k, idx, type, config);
42
35
  } else {
@@ -50,52 +43,52 @@ export function Field(type: ClassList, config?: Partial<FieldConfig>) {
50
43
  * @param aliases List of all aliases for a field
51
44
  * @augments `@travetto/schema:Field`
52
45
  */
53
- export function Alias(...aliases: string[]): ReturnType<typeof prop> { return prop({ aliases }); }
46
+ export function Alias(...aliases: string[]): PropType<unknown> { return prop({ aliases }); }
54
47
  /**
55
48
  * Mark a field as writeonly
56
49
  * @param active This determines if this field is readonly or not.
57
50
  * @augments `@travetto/schema:Field`
58
51
  */
59
- export function Writeonly(active = true): ReturnType<typeof prop> { return prop({ access: 'writeonly' }); }
52
+ export function Writeonly(active = true): PropType<unknown> { return prop({ access: 'writeonly' }); }
60
53
  /**
61
54
  * Mark a field as readonly
62
55
  * @param active This determines if this field is readonly or not.
63
56
  * @augments `@travetto/schema:Field`
64
57
  */
65
- export function Readonly(active = true): ReturnType<typeof prop> { return prop({ access: 'readonly' }); }
58
+ export function Readonly(active = true): PropType<unknown> { return prop({ access: 'readonly' }); }
66
59
  /**
67
60
  * Mark a field as sensitive
68
61
  * @param active This determines if this field is sensitive or not.
69
62
  * @augments `@travetto/schema:Field`
70
63
  */
71
- export function Secret(active = true): ReturnType<typeof prop> { return prop({ secret: active }); }
64
+ export function Secret(active = true): PropType<unknown> { return prop({ secret: active }); }
72
65
  /**
73
66
  * Mark a field as required
74
67
  * @param active This determines if this field is required or not.
75
68
  * @param message The error message when a the constraint fails.
76
69
  * @augments `@travetto/schema:Field`
77
70
  */
78
- export function Required(active = true, message?: string): ReturnType<typeof prop> { return prop({ required: { active, message } }); }
71
+ export function Required(active = true, message?: string): PropType<unknown> { return prop({ required: { active, message } }); }
79
72
  /**
80
73
  * Define a field as a set of enumerated values
81
74
  * @param values The list of values allowed for the enumeration
82
75
  * @param message The error message to show when the constraint fails
83
76
  * @augments `@travetto/schema:Field`
84
77
  */
85
- export function Enum(values: string[], message?: string): ReturnType<typeof stringNumberProp> {
78
+ export function Enum(values: string[], message?: string): PropType<string | number> {
86
79
  message = message || `{path} is only allowed to be "${values.join('" or "')}"`;
87
- return stringNumberProp({ enum: { values, message } });
80
+ return prop({ enum: { values, message } });
88
81
  }
89
82
  /**
90
83
  * Mark the field as indicating it's storing textual data
91
84
  * @augments `@travetto/schema:Field`
92
85
  */
93
- export function Text(): ReturnType<typeof stringArrStringProp> { return stringArrStringProp({ specifier: 'text' }); }
86
+ export function Text(): PropType<string | string[]> { return prop({ specifier: 'text' }); }
94
87
  /**
95
88
  * Mark the field to indicate it's for long form text
96
89
  * @augments `@travetto/schema:Field`
97
90
  */
98
- export function LongText(): ReturnType<typeof stringArrStringProp> { return stringArrStringProp({ specifier: 'text-long' }); }
91
+ export function LongText(): PropType<string | string[]> { return prop({ specifier: 'text-long' }); }
99
92
 
100
93
  /**
101
94
  * Require the field to match a specific RegExp
@@ -103,7 +96,7 @@ export function LongText(): ReturnType<typeof stringArrStringProp> { return stri
103
96
  * @param message The message to show when the constraint fails
104
97
  * @augments `@travetto/schema:Field`
105
98
  */
106
- export function Match(re: RegExp, message?: string): ReturnType<typeof stringArrStringProp> { return stringArrStringProp({ match: { re, message } }); }
99
+ export function Match(re: RegExp, message?: string): PropType<string | string[]> { return prop({ match: { re, message } }); }
107
100
 
108
101
  /**
109
102
  * The minimum length for the string or array
@@ -111,8 +104,8 @@ export function Match(re: RegExp, message?: string): ReturnType<typeof stringArr
111
104
  * @param message The message to show when the constraint fails
112
105
  * @augments `@travetto/schema:Field`
113
106
  */
114
- export function MinLength(n: number, message?: string): ReturnType<typeof stringArrProp> {
115
- return stringArrProp({ minlength: { n, message }, ...(n === 0 ? { required: { active: false } } : {}) });
107
+ export function MinLength(n: number, message?: string): PropType<string | unknown[]> {
108
+ return prop({ minlength: { n, message }, ...(n === 0 ? { required: { active: false } } : {}) });
116
109
  }
117
110
 
118
111
  /**
@@ -121,7 +114,7 @@ export function MinLength(n: number, message?: string): ReturnType<typeof string
121
114
  * @param message The message to show when the constraint fails
122
115
  * @augments `@travetto/schema:Field`
123
116
  */
124
- export function MaxLength(n: number, message?: string): ReturnType<typeof stringArrProp> { return stringArrProp({ maxlength: { n, message } }); }
117
+ export function MaxLength(n: number, message?: string): PropType<string | unknown[]> { return prop({ maxlength: { n, message } }); }
125
118
 
126
119
  /**
127
120
  * The minimum value
@@ -129,8 +122,8 @@ export function MaxLength(n: number, message?: string): ReturnType<typeof string
129
122
  * @param message The message to show when the constraint fails
130
123
  * @augments `@travetto/schema:Field`
131
124
  */
132
- export function Min<T extends number | Date>(n: T, message?: string): ReturnType<typeof dateNumberProp> {
133
- return dateNumberProp({ min: { n, message } });
125
+ export function Min<T extends number | Date>(n: T, message?: string): PropType<Date | number> {
126
+ return prop({ min: { n, message } });
134
127
  }
135
128
 
136
129
  /**
@@ -139,8 +132,8 @@ export function Min<T extends number | Date>(n: T, message?: string): ReturnType
139
132
  * @param message The message to show when the constraint fails
140
133
  * @augments `@travetto/schema:Field`
141
134
  */
142
- export function Max<T extends number | Date>(n: T, message?: string): ReturnType<typeof dateNumberProp> {
143
- return dateNumberProp({ max: { n, message } });
135
+ export function Max<T extends number | Date>(n: T, message?: string): PropType<Date | number> {
136
+ return prop({ max: { n, message } });
144
137
  }
145
138
 
146
139
  /**
@@ -148,21 +141,21 @@ export function Max<T extends number | Date>(n: T, message?: string): ReturnType
148
141
  * @param message The message to show when the constraint fails
149
142
  * @augments `@travetto/schema:Field`
150
143
  */
151
- export function Email(message?: string): ReturnType<typeof Match> { return Match(CommonRegExp.email, message); }
144
+ export function Email(message?: string): PropType<string | string[]> { return Match(CommonRegExp.email, message); }
152
145
 
153
146
  /**
154
147
  * Mark a field as an telephone number
155
148
  * @param message The message to show when the constraint fails
156
149
  * @augments `@travetto/schema:Field`
157
150
  */
158
- export function Telephone(message?: string): ReturnType<typeof Match> { return Match(CommonRegExp.telephone, message); }
151
+ export function Telephone(message?: string): PropType<string | string[]> { return Match(CommonRegExp.telephone, message); }
159
152
 
160
153
  /**
161
154
  * Mark a field as a url
162
155
  * @param message The message to show when the constraint fails
163
156
  * @augments `@travetto/schema:Field`
164
157
  */
165
- export function Url(message?: string): ReturnType<typeof Match> { return Match(CommonRegExp.url, message); }
158
+ export function Url(message?: string): PropType<string | string[]> { return Match(CommonRegExp.url, message); }
166
159
 
167
160
  /**
168
161
  * Determine the numeric precision of the value
@@ -170,31 +163,31 @@ export function Url(message?: string): ReturnType<typeof Match> { return Match(C
170
163
  * @param decimals The number of decimal digits to support
171
164
  * @augments `@travetto/schema:Field`
172
165
  */
173
- export function Precision(digits: number, decimals?: number): ReturnType<typeof numberProp> { return numberProp({ precision: [digits, decimals] }); }
166
+ export function Precision(digits: number, decimals?: number): PropType<number> { return prop({ precision: [digits, decimals] }); }
174
167
 
175
168
  /**
176
169
  * Mark a number as an integer
177
170
  * @augments `@travetto/schema:Field`
178
171
  */
179
- export function Integer(): ReturnType<typeof numberProp> { return Precision(0); }
172
+ export function Integer(): PropType<number> { return Precision(0); }
180
173
 
181
174
  /**
182
175
  * Mark a number as a float
183
176
  * @augments `@travetto/schema:Field`
184
177
  */
185
- export function Float(): ReturnType<typeof numberProp> { return Precision(10, 7); }
178
+ export function Float(): PropType<number> { return Precision(10, 7); }
186
179
 
187
180
  /**
188
181
  * Mark a number as a long value
189
182
  * @augments `@travetto/schema:Field`
190
183
  */
191
- export function Long(): ReturnType<typeof numberProp> { return Precision(19, 0); }
184
+ export function Long(): PropType<number> { return Precision(19, 0); }
192
185
 
193
186
  /**
194
187
  * Mark a number as a currency
195
188
  * @augments `@travetto/schema:Field`
196
189
  */
197
- export function Currency(): ReturnType<typeof numberProp> { return Precision(13, 2); }
190
+ export function Currency(): PropType<number> { return Precision(13, 2); }
198
191
 
199
192
  /**
200
193
  * Mark a field as ignored