@travetto/schema 7.0.0-rc.4 → 7.0.0
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 +4 -4
- package/package.json +4 -3
- package/src/decorator/field.ts +3 -2
- package/src/service/registry-adapter.ts +13 -11
- package/support/transformer/util.ts +11 -11
- package/support/transformer.schema.ts +23 -10
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ User:
|
|
|
64
64
|
|
|
65
65
|
### Fields
|
|
66
66
|
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:
|
|
67
|
-
* [@Field](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#
|
|
67
|
+
* [@Field](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L24) defines a field that will be serialized.
|
|
68
68
|
* [@Required](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L49) defines a that field should be required
|
|
69
69
|
* [@Enum](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L58) defines the allowable values that a field can have
|
|
70
70
|
* [@Match](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L84) defines a regular expression that the field value should match
|
|
@@ -81,9 +81,9 @@ This schema provides a powerful base for data binding and validation at runtime.
|
|
|
81
81
|
* [@Currency](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L187) provides support for standard currency
|
|
82
82
|
* [@Text](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L68) 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/input.ts#L75) same as text, but expects longer form content
|
|
84
|
-
* [@Readonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#
|
|
85
|
-
* [@Writeonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#
|
|
86
|
-
* [@Secret](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#
|
|
84
|
+
* [@Readonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L40) defines a that field should not be bindable external to the class
|
|
85
|
+
* [@Writeonly](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L33) defines a that field should not be exported in serialization, but that it can be bound to
|
|
86
|
+
* [@Secret](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/field.ts#L48) marks a field as being sensitive. This is used by certain logging activities to ensure sensitive information is not logged out.
|
|
87
87
|
* [@Specifier](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L195) attributes additional specifiers to a field, allowing for more specification beyond just the field's type.
|
|
88
88
|
* [@DiscriminatorField](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L202) allows for promoting a given field as the owner of the sub type discriminator.
|
|
89
89
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/schema",
|
|
3
|
-
"version": "7.0.0
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Data type registry for runtime validation, reflection and binding.",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"schema",
|
|
@@ -27,10 +28,10 @@
|
|
|
27
28
|
"directory": "module/schema"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@travetto/registry": "^7.0.0
|
|
31
|
+
"@travetto/registry": "^7.0.0"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
|
-
"@travetto/transformer": "^7.0.0
|
|
34
|
+
"@travetto/transformer": "^7.0.0"
|
|
34
35
|
},
|
|
35
36
|
"peerDependenciesMeta": {
|
|
36
37
|
"@travetto/transformer": {
|
package/src/decorator/field.ts
CHANGED
|
@@ -18,10 +18,11 @@ function field<V>(...configs: Partial<SchemaFieldConfig>[]): PropType<V> {
|
|
|
18
18
|
* @param type The type for the field
|
|
19
19
|
* @param configs The field configuration
|
|
20
20
|
* @augments `@travetto/schema:Input`
|
|
21
|
+
* @augments `@travetto/schema:Field`
|
|
21
22
|
* @kind decorator
|
|
22
23
|
*/
|
|
23
|
-
export function Field(type
|
|
24
|
-
return field(type
|
|
24
|
+
export function Field(type?: Pick<SchemaFieldConfig, 'type' | 'array'>, ...configs: Partial<SchemaFieldConfig>[]): PropType<unknown> {
|
|
25
|
+
return field(type!, ...configs);
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -34,17 +34,19 @@ function combineCore<T extends SchemaCoreConfig>(base: T, config: Partial<T>): T
|
|
|
34
34
|
|
|
35
35
|
function combineInputs<T extends SchemaInputConfig>(base: T, configs: Partial<T>[]): T {
|
|
36
36
|
for (const config of configs) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
enum
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
if (config) {
|
|
38
|
+
safeAssign(base, {
|
|
39
|
+
...config,
|
|
40
|
+
...config.aliases ? { aliases: [...base.aliases ?? [], ...config.aliases ?? []] } : {},
|
|
41
|
+
...config.specifiers ? { specifiers: [...base.specifiers ?? [], ...config.specifiers ?? []] } : {},
|
|
42
|
+
...config.enum ? {
|
|
43
|
+
enum: {
|
|
44
|
+
message: config.enum?.message ?? base.enum?.message,
|
|
45
|
+
values: (config.enum?.values ?? base.enum?.values ?? []).toSorted()
|
|
46
|
+
}
|
|
47
|
+
} : {},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
48
50
|
combineCore(base, config);
|
|
49
51
|
}
|
|
50
52
|
return base;
|
|
@@ -214,19 +214,19 @@ class ${uniqueId} extends ${type.mappedClassName} {
|
|
|
214
214
|
params.push(state.fromLiteral(attrs));
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
217
|
+
const resolved = this.toConcreteType(state, typeExpr, node, config?.root ?? node);
|
|
218
|
+
const type = typeExpr.key === 'foreign' ? state.getConcreteType(node) :
|
|
219
|
+
ts.isArrayLiteralExpression(resolved) ? resolved.elements[0] : resolved;
|
|
220
|
+
|
|
221
|
+
params.unshift(LiteralUtil.fromLiteral(state.factory, {
|
|
222
|
+
array: ts.isArrayLiteralExpression(resolved),
|
|
223
|
+
type
|
|
224
|
+
}));
|
|
225
|
+
|
|
226
|
+
if (existing) {
|
|
227
227
|
const args = DecoratorUtil.getArguments(existing) ?? [];
|
|
228
228
|
if (args.length > 0) {
|
|
229
|
-
params
|
|
229
|
+
params[0] = args[0]; // Overwrite
|
|
230
230
|
}
|
|
231
231
|
if (args.length > 1) {
|
|
232
232
|
params.push(...args.slice(1));
|
|
@@ -2,18 +2,20 @@ import ts from 'typescript';
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
TransformerState, OnProperty, OnClass, AfterClass, DocUtil, DeclarationUtil,
|
|
5
|
-
OnGetter, OnSetter, OnMethod, DecoratorUtil, OnStaticMethod
|
|
5
|
+
OnGetter, OnSetter, OnMethod, DecoratorUtil, OnStaticMethod, type DecoratorMeta
|
|
6
6
|
} from '@travetto/transformer';
|
|
7
7
|
|
|
8
8
|
import { SchemaTransformUtil } from './transformer/util.ts';
|
|
9
9
|
|
|
10
10
|
const CONSTRUCTOR_PROPERTY = 'CONSTRUCTOR';
|
|
11
|
-
const
|
|
11
|
+
const InSchema = Symbol();
|
|
12
|
+
const IsOptIn = Symbol();
|
|
12
13
|
const AccessorsSymbol = Symbol();
|
|
13
14
|
const AutoEnrollMethods = Symbol();
|
|
14
15
|
|
|
15
16
|
interface AutoState {
|
|
16
|
-
[
|
|
17
|
+
[InSchema]?: boolean;
|
|
18
|
+
[IsOptIn]?: boolean;
|
|
17
19
|
[AutoEnrollMethods]?: Set<string>;
|
|
18
20
|
[AccessorsSymbol]?: Set<string>;
|
|
19
21
|
}
|
|
@@ -23,7 +25,11 @@ interface AutoState {
|
|
|
23
25
|
*/
|
|
24
26
|
export class SchemaTransformer {
|
|
25
27
|
|
|
26
|
-
static isInvisible(state: AutoState & TransformerState, node: ts.Declaration): boolean {
|
|
28
|
+
static isInvisible(state: AutoState & TransformerState, node: ts.Declaration, isStatic?: boolean): boolean {
|
|
29
|
+
if (!state[InSchema] && !isStatic) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
const ignore = state.findDecorator(this, node, 'Ignore');
|
|
28
34
|
if (ignore) {
|
|
29
35
|
return true;
|
|
@@ -31,6 +37,7 @@ export class SchemaTransformer {
|
|
|
31
37
|
|
|
32
38
|
const manuallyOpted = !!(
|
|
33
39
|
state.findDecorator(this, node, 'Input') ??
|
|
40
|
+
state.findDecorator(this, node, 'Field') ??
|
|
34
41
|
state.findDecorator(this, node, 'Method')
|
|
35
42
|
);
|
|
36
43
|
if (manuallyOpted) {
|
|
@@ -41,7 +48,7 @@ export class SchemaTransformer {
|
|
|
41
48
|
return true;
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
|
-
if (
|
|
51
|
+
if (state[IsOptIn] || !DeclarationUtil.isPublic(node)) {
|
|
45
52
|
return true;
|
|
46
53
|
}
|
|
47
54
|
return false;
|
|
@@ -52,15 +59,17 @@ export class SchemaTransformer {
|
|
|
52
59
|
*/
|
|
53
60
|
@OnClass('Schema')
|
|
54
61
|
static startSchema(state: AutoState & TransformerState, node: ts.ClassDeclaration): ts.ClassDeclaration {
|
|
55
|
-
state[InSchemaSymbol] = true;
|
|
56
62
|
state[AccessorsSymbol] = new Set();
|
|
57
63
|
state[AutoEnrollMethods] = new Set();
|
|
64
|
+
state[InSchema] = true;
|
|
58
65
|
|
|
59
66
|
// Determine auto enrol methods
|
|
60
67
|
for (const item of state.getDecoratorList(node)) {
|
|
61
68
|
if (item.targets?.includes('@travetto/schema:Schema')) {
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
state[IsOptIn] ||= item.options?.includes('opt-in') ?? false;
|
|
70
|
+
const methodEnrolls = item.options?.filter(item => item.startsWith('method:'))?.map(item => item.replace('method:', '')) ?? [];
|
|
71
|
+
for (const method of methodEnrolls) {
|
|
72
|
+
state[AutoEnrollMethods].add(method);
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
}
|
|
@@ -117,8 +126,10 @@ export class SchemaTransformer {
|
|
|
117
126
|
params = [...params, state.fromLiteral(attrs)];
|
|
118
127
|
}
|
|
119
128
|
|
|
120
|
-
delete state[
|
|
129
|
+
delete state[InSchema];
|
|
130
|
+
delete state[IsOptIn];
|
|
121
131
|
delete state[AccessorsSymbol];
|
|
132
|
+
delete state[AutoEnrollMethods];
|
|
122
133
|
|
|
123
134
|
return state.factory.updateClassDeclaration(
|
|
124
135
|
node,
|
|
@@ -138,7 +149,9 @@ export class SchemaTransformer {
|
|
|
138
149
|
@OnMethod()
|
|
139
150
|
@OnStaticMethod()
|
|
140
151
|
static processSchemaMethod(state: TransformerState & AutoState, node: ts.MethodDeclaration): ts.MethodDeclaration {
|
|
141
|
-
if (
|
|
152
|
+
if (
|
|
153
|
+
this.isInvisible(state, node, node.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword)) &&
|
|
154
|
+
!state[AutoEnrollMethods]?.has(node.name.getText())) {
|
|
142
155
|
return node;
|
|
143
156
|
}
|
|
144
157
|
|