@travetto/schema 7.0.0-rc.0 → 7.0.0-rc.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/schema",
|
|
3
|
-
"version": "7.0.0-rc.
|
|
3
|
+
"version": "7.0.0-rc.1",
|
|
4
4
|
"description": "Data type registry for runtime validation, reflection and binding.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"schema",
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
"directory": "module/schema"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/registry": "^7.0.0-rc.
|
|
30
|
+
"@travetto/registry": "^7.0.0-rc.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@travetto/transformer": "^7.0.0-rc.
|
|
33
|
+
"@travetto/transformer": "^7.0.0-rc.1"
|
|
34
34
|
},
|
|
35
35
|
"peerDependenciesMeta": {
|
|
36
36
|
"@travetto/transformer": {
|
package/src/bind-util.ts
CHANGED
|
@@ -133,22 +133,22 @@ export class BindUtil {
|
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
135
|
* Bind data to the schema for a class, with an optional view
|
|
136
|
-
* @param
|
|
136
|
+
* @param cls The schema class to bind against
|
|
137
137
|
* @param data The provided data to bind
|
|
138
138
|
* @param cfg The bind configuration
|
|
139
139
|
*/
|
|
140
|
-
static bindSchema<T>(
|
|
141
|
-
static bindSchema<T>(
|
|
142
|
-
static bindSchema<T>(
|
|
143
|
-
static bindSchema<T>(
|
|
140
|
+
static bindSchema<T>(cls: Class<T>, data?: undefined, cfg?: BindConfig): undefined;
|
|
141
|
+
static bindSchema<T>(cls: Class<T>, data?: null, cfg?: BindConfig): null;
|
|
142
|
+
static bindSchema<T>(cls: Class<T>, data?: object | T, cfg?: BindConfig): T;
|
|
143
|
+
static bindSchema<T>(cls: Class<T>, data?: object | T, cfg?: BindConfig): T | null | undefined {
|
|
144
144
|
if (data === null || data === undefined) {
|
|
145
145
|
return data;
|
|
146
146
|
}
|
|
147
|
-
if (data instanceof
|
|
147
|
+
if (data instanceof cls) {
|
|
148
148
|
return castTo(data);
|
|
149
149
|
} else {
|
|
150
|
-
const
|
|
151
|
-
const instance = classConstruct<T & { type?: string }>(
|
|
150
|
+
const resolvedCls = SchemaRegistryIndex.resolveInstanceType<T>(cls, asFull<T>(data));
|
|
151
|
+
const instance = classConstruct<T & { type?: string }>(resolvedCls);
|
|
152
152
|
|
|
153
153
|
for (const k of TypedObject.keys(instance)) { // Do not retain undefined fields
|
|
154
154
|
if (instance[k] === undefined) {
|
|
@@ -156,25 +156,25 @@ export class BindUtil {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
const out = this.bindSchemaToObject(
|
|
160
|
-
SchemaRegistryIndex.get(
|
|
159
|
+
const out = this.bindSchemaToObject(resolvedCls, instance, data, cfg);
|
|
160
|
+
SchemaRegistryIndex.get(resolvedCls).ensureInstanceTypeField(out);
|
|
161
161
|
return out;
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* Bind the schema to the object
|
|
167
|
-
* @param
|
|
168
|
-
* @param obj The target object (instance of
|
|
167
|
+
* @param cls The schema class
|
|
168
|
+
* @param obj The target object (instance of cls)
|
|
169
169
|
* @param data The data to bind
|
|
170
170
|
* @param cfg The bind configuration
|
|
171
171
|
*/
|
|
172
|
-
static bindSchemaToObject<T>(
|
|
172
|
+
static bindSchemaToObject<T>(cls: Class<T>, obj: T, data?: object, cfg: BindConfig = {}): T {
|
|
173
173
|
const view = cfg.view; // Does not convey
|
|
174
174
|
delete cfg.view;
|
|
175
175
|
|
|
176
176
|
if (!!data && isInstance<T>(data)) {
|
|
177
|
-
const adapter = SchemaRegistryIndex.get(
|
|
177
|
+
const adapter = SchemaRegistryIndex.get(cls);
|
|
178
178
|
const conf = adapter.get();
|
|
179
179
|
|
|
180
180
|
// If no configuration
|
|
@@ -185,7 +185,7 @@ export class BindUtil {
|
|
|
185
185
|
} else {
|
|
186
186
|
let schema: SchemaFieldMap = conf.fields;
|
|
187
187
|
if (view) {
|
|
188
|
-
schema = adapter.
|
|
188
|
+
schema = adapter.getFields(view);
|
|
189
189
|
if (!schema) {
|
|
190
190
|
throw new Error(`View not found: ${view.toString()}`);
|
|
191
191
|
}
|
|
@@ -312,7 +312,7 @@ export class BindUtil {
|
|
|
312
312
|
* @returns
|
|
313
313
|
*/
|
|
314
314
|
static coerceMethodParams<T>(cls: Class<T>, method: string | symbol, params: unknown[], applyDefaults = true): unknown[] {
|
|
315
|
-
const paramConfigs = SchemaRegistryIndex.
|
|
315
|
+
const paramConfigs = SchemaRegistryIndex.get(cls).getMethod(method).parameters;
|
|
316
316
|
return this.coerceParameters(paramConfigs, params, applyDefaults);
|
|
317
317
|
}
|
|
318
318
|
}
|
|
@@ -92,7 +92,7 @@ function combineClassWithParent<T extends SchemaClassConfig>(base: T, parent: T)
|
|
|
92
92
|
case 'Required':
|
|
93
93
|
case 'Partial': {
|
|
94
94
|
base.fields = Object.fromEntries(
|
|
95
|
-
Object.entries(
|
|
95
|
+
Object.entries(parent.fields).map(([k, v]) => [k, {
|
|
96
96
|
...v,
|
|
97
97
|
required: {
|
|
98
98
|
active: base.mappedOperation === 'Required'
|
|
@@ -294,7 +294,7 @@ export class SchemaRegistryAdapter implements RegistryAdapter<SchemaClassConfig>
|
|
|
294
294
|
return this.getMethod(method).returnType!.type;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
|
|
297
|
+
getFields(view?: string): SchemaFieldMap {
|
|
298
298
|
if (!view) {
|
|
299
299
|
return this.#config.fields;
|
|
300
300
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChangeEvent, RegistrationMethods, RegistryIndex, RegistryIndexStore, Registry } from '@travetto/registry';
|
|
2
2
|
import { AppError, castKey, castTo, Class, classConstruct, getParentClass, Util } from '@travetto/runtime';
|
|
3
3
|
|
|
4
|
-
import { SchemaFieldConfig, SchemaClassConfig
|
|
4
|
+
import { SchemaFieldConfig, SchemaClassConfig } from './types.ts';
|
|
5
5
|
import { SchemaRegistryAdapter } from './registry-adapter.ts';
|
|
6
6
|
import { SchemaChangeListener } from './changes.ts';
|
|
7
7
|
|
|
@@ -24,14 +24,6 @@ export class SchemaRegistryIndex implements RegistryIndex {
|
|
|
24
24
|
return this.#instance.store.get(cls).getDiscriminatedConfig();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
static getFieldMap(cls: Class, view?: string): SchemaFieldMap {
|
|
28
|
-
return this.#instance.store.get(cls).getSchema(view);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static getMethodConfig(cls: Class, method: string | symbol): SchemaMethodConfig {
|
|
32
|
-
return this.#instance.store.get(cls).getMethod(method);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
27
|
static has(cls: Class): boolean {
|
|
36
28
|
return this.#instance.store.has(cls);
|
|
37
29
|
}
|
|
@@ -64,8 +56,8 @@ export class SchemaRegistryIndex implements RegistryIndex {
|
|
|
64
56
|
return this.#instance.store.get(cls);
|
|
65
57
|
}
|
|
66
58
|
|
|
67
|
-
static
|
|
68
|
-
return this.#instance.store.getOptional(cls)
|
|
59
|
+
static getOptional(cls: Class): Omit<SchemaRegistryAdapter, RegistrationMethods> | undefined {
|
|
60
|
+
return this.#instance.store.getOptional(cls);
|
|
69
61
|
}
|
|
70
62
|
|
|
71
63
|
static getClasses(): Class[] {
|
|
@@ -160,14 +152,12 @@ export class SchemaRegistryIndex implements RegistryIndex {
|
|
|
160
152
|
* @param cls Class for instance
|
|
161
153
|
* @param o Actual instance
|
|
162
154
|
*/
|
|
163
|
-
resolveInstanceType<T>(
|
|
164
|
-
const
|
|
165
|
-
const adapter = this.store.get(cls);
|
|
166
|
-
const { discriminatedField, discriminatedType } = adapter.get();
|
|
155
|
+
resolveInstanceType<T>(cls: Class<T>, o: T): Class {
|
|
156
|
+
const { discriminatedField, discriminatedType, class: targetClass } = this.store.get(cls).get();
|
|
167
157
|
if (!discriminatedField) {
|
|
168
|
-
return
|
|
158
|
+
return targetClass;
|
|
169
159
|
} else {
|
|
170
|
-
const base = this.getBaseClass(
|
|
160
|
+
const base = this.getBaseClass(targetClass);
|
|
171
161
|
const map = this.#byDiscriminatedTypes.get(base);
|
|
172
162
|
const type = castTo<string>(o[castKey<T>(discriminatedField)]) ?? discriminatedType;
|
|
173
163
|
if (!type) {
|
|
@@ -177,8 +167,8 @@ export class SchemaRegistryIndex implements RegistryIndex {
|
|
|
177
167
|
throw new AppError(`Unable to resolve discriminated type '${type}' for class ${base.name}`);
|
|
178
168
|
}
|
|
179
169
|
const requested = map.get(type)!;
|
|
180
|
-
if (!(classConstruct(requested) instanceof
|
|
181
|
-
throw new AppError(`Resolved discriminated type '${type}' for class ${base.name} is not an instance of requested type ${
|
|
170
|
+
if (!(classConstruct(requested) instanceof targetClass)) {
|
|
171
|
+
throw new AppError(`Resolved discriminated type '${type}' for class ${base.name} is not an instance of requested type ${targetClass.name}`);
|
|
182
172
|
}
|
|
183
173
|
return requested;
|
|
184
174
|
}
|
|
@@ -15,7 +15,7 @@ import { SchemaRegistryIndex } from '../service/registry-index.ts';
|
|
|
15
15
|
*/
|
|
16
16
|
function resolveFieldMap<T>(base: Class<T>, o: T): SchemaFieldMap {
|
|
17
17
|
const target = SchemaRegistryIndex.resolveInstanceType(base, o);
|
|
18
|
-
return SchemaRegistryIndex.
|
|
18
|
+
return SchemaRegistryIndex.get(target).getFields();
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function isClassInstance<T>(o: unknown): o is ClassInstance<T> {
|
|
@@ -257,7 +257,7 @@ export class SchemaValidator {
|
|
|
257
257
|
}
|
|
258
258
|
cls = SchemaRegistryIndex.resolveInstanceType(cls, o);
|
|
259
259
|
|
|
260
|
-
const fields = SchemaRegistryIndex.
|
|
260
|
+
const fields = SchemaRegistryIndex.get(cls).getFields(view);
|
|
261
261
|
|
|
262
262
|
// Validate using standard behaviors
|
|
263
263
|
const errors = [
|
|
@@ -313,7 +313,7 @@ export class SchemaValidator {
|
|
|
313
313
|
*/
|
|
314
314
|
static async validateMethod<T>(cls: Class<T>, method: string | symbol, params: unknown[], prefixes: (string | symbol | undefined)[] = []): Promise<void> {
|
|
315
315
|
const errors: ValidationError[] = [];
|
|
316
|
-
const config = SchemaRegistryIndex.
|
|
316
|
+
const config = SchemaRegistryIndex.get(cls).getMethod(method);
|
|
317
317
|
|
|
318
318
|
for (const param of config.parameters) {
|
|
319
319
|
const i = param.index;
|