@travetto/schema 5.0.14 → 5.0.15

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": "5.0.14",
3
+ "version": "5.0.15",
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": "^5.0.14"
30
+ "@travetto/registry": "^5.0.15"
31
31
  },
32
32
  "peerDependencies": {
33
- "@travetto/transformer": "^5.0.11"
33
+ "@travetto/transformer": "^5.0.12"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@travetto/transformer": {
package/src/bind-util.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { castTo, Class, classConstruct, asFull, TypedObject, castKey } from '@travetto/runtime';
2
2
 
3
3
  import { DataUtil } from './data';
4
- import { AllViewⲐ } from './internal/types';
4
+ import { AllViewSymbol } from './internal/types';
5
5
  import { SchemaRegistry } from './service/registry';
6
6
  import { FieldConfig } from './service/types';
7
7
 
8
8
  type BindConfig = {
9
- view?: string | typeof AllViewⲐ;
9
+ view?: string | typeof AllViewSymbol;
10
10
  filterField?: (field: FieldConfig) => boolean;
11
11
  filterValue?: (value: unknown, field: FieldConfig) => boolean;
12
12
  };
@@ -169,7 +169,7 @@ export class BindUtil {
169
169
  * @param cfg The bind configuration
170
170
  */
171
171
  static bindSchemaToObject<T>(cons: Class<T>, obj: T, data?: object, cfg: BindConfig = {}): T {
172
- const view = cfg.view ?? AllViewⲐ; // Does not convey
172
+ const view = cfg.view ?? AllViewSymbol; // Does not convey
173
173
  delete cfg.view;
174
174
 
175
175
  if (!!data && isInstance<T>(data)) {
@@ -42,7 +42,6 @@ export function MethodValidator<T extends (...args: Any[]) => Any>(fn: MethodVal
42
42
  };
43
43
  }
44
44
 
45
-
46
45
  /**
47
46
  * Register a specific view for a class
48
47
  * @param name The name of the view
package/src/global.d.ts CHANGED
@@ -4,23 +4,11 @@ declare global {
4
4
  interface Function {
5
5
  /**
6
6
  * Will produce a new instance of this class with the provided data bound to it
7
+ *
8
+ * NOTE: Only applies to Schema-based classes, will throw a runtime error otherwise
7
9
  * @param data The data to bind
8
10
  * @param view The optional view to limit the bind to
9
11
  */
10
12
  from<T>(this: Class<T>, data: DeepPartial<T>, view?: string): T;
11
13
  }
12
-
13
- namespace NodeJS {
14
- /**
15
- * @concrete node:stream#Readable
16
- */
17
- interface ReadableStream { }
18
- }
19
- }
20
-
21
- declare module 'stream' {
22
- /**
23
- * @concrete node:stream#Readable
24
- */
25
- interface Readable { }
26
- }
14
+ }
@@ -1,2 +1,2 @@
1
- export const AllViewⲐ: unique symbol = Symbol.for('@travetto/schema:all');
1
+ export const AllViewSymbol: unique symbol = Symbol.for('@travetto/schema:all');
2
2
  export class UnknownType { }
package/src/name.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { describeFunction } from '@travetto/runtime';
2
1
  import { ClassConfig } from './service/types';
3
2
 
4
- const SYN_RE = /(__)(\d+)Ⲑsyn$/;
3
+ const ID_RE = /(\d{1,100})Δ$/;
5
4
 
6
5
  /**
7
6
  * Name resolver, specifically for synthetic types
@@ -10,23 +9,22 @@ export class SchemaNameResolver {
10
9
 
11
10
  #schemaIdToName = new Map<string, string>();
12
11
  #digits: number;
13
- #base: number;
14
12
 
15
13
  constructor(digits = 5) {
16
14
  this.#digits = digits;
17
- this.#base = 10 ** this.#digits;
18
15
  }
19
16
 
20
17
  getName(schema: ClassConfig): string {
21
- const id = schema.class.Ⲑid;
22
- if (describeFunction(schema.class)?.synthetic && SYN_RE.test(schema.class.name)) {
18
+ const cls = schema.class;
19
+ const id = cls.Ⲑid;
20
+ if (ID_RE.test(cls.name)) {
23
21
  if (!this.#schemaIdToName.has(id)) {
24
- const name = schema.class.name.replace(SYN_RE, (_, pref, uid) => `__${(+uid % this.#base).toString().padStart(this.#digits, '0')}`);
22
+ const name = cls.name.replace(ID_RE, (_, uid) => uid.slice(-this.#digits));
25
23
  this.#schemaIdToName.set(id, name);
26
24
  }
27
25
  return this.#schemaIdToName.get(id)!;
28
26
  } else {
29
- return schema.class.name.replace('Ⲑsyn', '');
27
+ return cls.name;
30
28
  }
31
29
  }
32
30
  }
@@ -4,7 +4,7 @@ import { Class } from '@travetto/runtime';
4
4
  import { ChangeEvent } from '@travetto/registry';
5
5
 
6
6
  import { FieldConfig, ClassConfig } from './types';
7
- import { AllViewⲐ } from '../internal/types';
7
+ import { AllViewSymbol } from '../internal/types';
8
8
 
9
9
  const id = (c: Class | string): string => typeof c === 'string' ? c : c.Ⲑid;
10
10
 
@@ -111,8 +111,8 @@ class $SchemaChangeListener {
111
111
  */
112
112
  emitFieldChanges({ prev, curr }: ChangeEvent<ClassConfig>): void {
113
113
 
114
- const prevView = prev?.views[AllViewⲐ] || { fields: [], schema: {} };
115
- const currView = curr!.views[AllViewⲐ];
114
+ const prevView = prev?.views[AllViewSymbol] || { fields: [], schema: {} };
115
+ const currView = curr!.views[AllViewSymbol];
116
116
 
117
117
  const prevFields = new Set(prevView.fields);
118
118
  const currFields = new Set(currView.fields);
@@ -132,7 +132,7 @@ class $SchemaChangeListener {
132
132
  }
133
133
 
134
134
  // Handle class references changing, but keeping same id
135
- const compareTypes = (a: Class, b: Class): boolean => 'Ⲑid' in a ? a.Ⲑid === b.Ⲑid : a === b;
135
+ const compareTypes = (a: Class, b: Class): boolean => a.Ⲑid ? a.Ⲑid === b.Ⲑid : a === b;
136
136
 
137
137
  for (const c of currFields) {
138
138
  if (prevFields.has(c)) {
@@ -1,9 +1,9 @@
1
- import { Class, AppError, describeFunction, castTo, classConstruct, asFull, castKey, Any } from '@travetto/runtime';
1
+ import { Class, AppError, describeFunction, castTo, classConstruct, asFull, castKey } from '@travetto/runtime';
2
2
  import { MetadataRegistry, RootRegistry, ChangeEvent } from '@travetto/registry';
3
3
 
4
4
  import { ClassList, FieldConfig, ClassConfig, SchemaConfig, ViewFieldsConfig, ViewConfig, SchemaMethodConfig } from './types';
5
5
  import { SchemaChangeListener } from './changes';
6
- import { AllViewⲐ } from '../internal/types';
6
+ import { AllViewSymbol } from '../internal/types';
7
7
  import { MethodValidatorFn } from '../validate/types';
8
8
 
9
9
  const classToSubTypeName = (cls: Class): string => cls.name
@@ -73,7 +73,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
73
73
  ensureInstanceTypeField<T>(cls: Class, o: T): void {
74
74
  const schema = this.get(cls);
75
75
  const typeField = castKey<T>(schema.subTypeField);
76
- if (schema.subTypeName && typeField in schema.views[AllViewⲐ].schema && !o[typeField]) { // Do we have a type field defined
76
+ if (schema.subTypeName && typeField in schema.views[AllViewSymbol].schema && !o[typeField]) { // Do we have a type field defined
77
77
  o[typeField] = castTo(schema.subTypeName); // Assign if missing
78
78
  }
79
79
  }
@@ -149,7 +149,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
149
149
  this.#subTypes.get(base)!.set(config.subTypeName!, cls);
150
150
  }
151
151
  if (base !== cls) {
152
- while (base && ('Ⲑid' in base)) {
152
+ while (base && base.Ⲑid) {
153
153
  this.#subTypes.get(base)!.set(config.subTypeName!, cls);
154
154
  const parent = this.getParentClass(base);
155
155
  base = parent ? this.getBaseSchema(parent) : undefined;
@@ -169,7 +169,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
169
169
  SchemaChangeListener.trackSchemaDependency(curr, cls, path, this.get(cls));
170
170
 
171
171
  // Read children
172
- const view = config.views[AllViewⲐ];
172
+ const view = config.views[AllViewSymbol];
173
173
  for (const k of view.fields) {
174
174
  if (this.has(view.schema[k].type) && view.schema[k].type !== cls) {
175
175
  this.trackSchemaDependencies(cls, view.schema[k].type, [...path, view.schema[k]]);
@@ -186,7 +186,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
186
186
  metadata: {},
187
187
  methods: {},
188
188
  views: {
189
- [AllViewⲐ]: {
189
+ [AllViewSymbol]: {
190
190
  schema: {},
191
191
  fields: []
192
192
  }
@@ -199,8 +199,8 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
199
199
  * @param cls The class to retrieve the schema for
200
200
  * @param view The view name
201
201
  */
202
- getViewSchema<T>(cls: Class<T>, view?: string | typeof AllViewⲐ): ViewConfig {
203
- view = view ?? AllViewⲐ;
202
+ getViewSchema<T>(cls: Class<T>, view?: string | typeof AllViewSymbol): ViewConfig {
203
+ view = view ?? AllViewSymbol;
204
204
 
205
205
  const schema = this.get(cls)!;
206
206
  if (!schema) {
@@ -296,7 +296,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
296
296
  * @param config The config to register
297
297
  */
298
298
  registerPendingFieldFacet(target: Class, prop: string, config: Partial<FieldConfig>): Class {
299
- const allViewConf = this.getOrCreatePending(target).views![AllViewⲐ];
299
+ const allViewConf = this.getOrCreatePending(target).views![AllViewSymbol];
300
300
 
301
301
  if (!allViewConf.schema[prop]) {
302
302
  allViewConf.fields.push(prop);
@@ -359,9 +359,9 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
359
359
  * @param src Source config
360
360
  */
361
361
  mergeConfigs(dest: ClassConfig, src: Partial<ClassConfig>, inherited = false): ClassConfig {
362
- dest.views[AllViewⲐ] = {
363
- schema: { ...dest.views[AllViewⲐ].schema, ...src.views?.[AllViewⲐ].schema },
364
- fields: [...dest.views[AllViewⲐ].fields, ...src.views?.[AllViewⲐ].fields ?? []]
362
+ dest.views[AllViewSymbol] = {
363
+ schema: { ...dest.views[AllViewSymbol].schema, ...src.views?.[AllViewSymbol].schema },
364
+ fields: [...dest.views[AllViewSymbol].fields, ...src.views?.[AllViewSymbol].fields ?? []]
365
365
  };
366
366
  if (!inherited) {
367
367
  dest.baseType = src.baseType ?? dest.baseType;
@@ -381,7 +381,7 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
381
381
  * @param conf The class config
382
382
  */
383
383
  finalizeViews<T>(target: Class<T>, conf: ClassConfig): ClassConfig {
384
- const allViewConf = conf.views![AllViewⲐ];
384
+ const allViewConf = conf.views![AllViewSymbol];
385
385
  const pending = this.#pendingViews.get(target) ?? new Map<string, ViewFieldsConfig<string>>();
386
386
  this.#pendingViews.delete(target);
387
387
 
@@ -427,9 +427,9 @@ class $SchemaRegistry extends MetadataRegistry<ClassConfig, FieldConfig> {
427
427
  // Write views out
428
428
  config = this.finalizeViews(cls, config);
429
429
 
430
- if (config.subTypeName && config.subTypeField in config.views[AllViewⲐ].schema) {
431
- const field = config.views[AllViewⲐ].schema[config.subTypeField];
432
- config.views[AllViewⲐ].schema[config.subTypeField] = {
430
+ if (config.subTypeName && config.subTypeField in config.views[AllViewSymbol].schema) {
431
+ const field = config.views[AllViewSymbol].schema[config.subTypeField];
432
+ config.views[AllViewSymbol].schema[config.subTypeField] = {
433
433
  ...field,
434
434
  enum: {
435
435
  values: [config.subTypeName],
@@ -1,6 +1,6 @@
1
1
  import { Any, Class, Primitive } from '@travetto/runtime';
2
2
 
3
- import { AllViewⲐ } from '../internal/types';
3
+ import { AllViewSymbol } from '../internal/types';
4
4
  import { MethodValidatorFn, ValidatorFn } from '../validate/types';
5
5
 
6
6
  export type ClassList = Class | [Class];
@@ -69,7 +69,7 @@ export interface ClassConfig extends DescribableConfig {
69
69
  /**
70
70
  * List of all views
71
71
  */
72
- views: Record<string, ViewConfig> & { [AllViewⲐ]: ViewConfig };
72
+ views: Record<string, ViewConfig> & { [AllViewSymbol]: ViewConfig };
73
73
  /**
74
74
  * Global validators
75
75
  */
@@ -1,12 +1,6 @@
1
1
  import { TypedObject } from '@travetto/runtime';
2
2
  import { Messages } from './messages';
3
3
 
4
- declare global {
5
- interface RegExp {
6
- name?: string;
7
- }
8
- }
9
-
10
4
  /**
11
5
  * List of common regular expressions for fields
12
6
  */
@@ -18,8 +12,11 @@ export const CommonRegExp = {
18
12
  postalCode: /^\d{5}(?:[-\s]\d{4})?$/
19
13
  };
20
14
 
15
+ export const CommonRegExpToName = new Map<RegExp, string>();
16
+
21
17
  // Rebind regexes
22
18
  for (const k of TypedObject.keys(CommonRegExp)) {
23
- CommonRegExp[k].name = `[[:${k}:]]`;
24
- Messages.set(CommonRegExp[k].name!, Messages.get(k)!);
19
+ const name = `[[:${k}:]]`;
20
+ CommonRegExpToName.set(CommonRegExp[k], name);
21
+ Messages.set(name, Messages.get(k)!);
25
22
  }
@@ -6,6 +6,7 @@ import { ValidationError, ValidationKindCore, ValidationResult } from './types';
6
6
  import { Messages } from './messages';
7
7
  import { isValidationError, TypeMismatchError, ValidationResultError } from './error';
8
8
  import { DataUtil } from '../data';
9
+ import { CommonRegExpToName } from './regexp';
9
10
 
10
11
  /**
11
12
  * Get the schema config for Class/Schema config, including support for polymorphism
@@ -26,12 +27,6 @@ function isRangeValue(o: unknown): o is number | string | Date {
26
27
  return typeof o === 'string' || typeof o === 'number' || o instanceof Date;
27
28
  }
28
29
 
29
- declare global {
30
- interface RegExp {
31
- name?: string;
32
- }
33
- }
34
-
35
30
  /**
36
31
  * The schema validator applies the schema constraints to a given object and looks
37
32
  * for errors
@@ -195,7 +190,7 @@ export class SchemaValidator {
195
190
  kind: res.kind,
196
191
  value: res.value,
197
192
  message: '',
198
- re: res.re?.name ?? res.re?.source ?? '',
193
+ re: CommonRegExpToName.get(res.re!) ?? res.re?.source ?? '',
199
194
  path,
200
195
  type: (typeof res.type === 'function' ? res.type.name : res.type)
201
196
  };
@@ -1,7 +1,7 @@
1
1
  import ts from 'typescript';
2
2
  import {
3
3
  type AnyType, DeclarationUtil, LiteralUtil,
4
- DecoratorUtil, DocUtil, ParamDocumentation, TransformerState, transformCast
4
+ DecoratorUtil, DocUtil, ParamDocumentation, TransformerState, transformCast,
5
5
  } from '@travetto/transformer';
6
6
 
7
7
  const SCHEMA_MOD = '@travetto/schema/src/decorator/schema';
@@ -33,10 +33,10 @@ export class SchemaTransformUtil {
33
33
  return state.createAccess(imp.ident, 'UnknownType');
34
34
  }
35
35
  case 'shape': {
36
- const uniqueId = state.generateUniqueIdentifier(node, type);
36
+ const uniqueId = state.generateUniqueIdentifier(node, type, 'Δ');
37
37
 
38
38
  // Build class on the fly
39
- const [id, existing] = state.createSyntheticIdentifier(uniqueId);
39
+ const [id, existing] = state.registerIdentifier(uniqueId);
40
40
  if (!existing) {
41
41
  const cls = state.factory.createClassDeclaration(
42
42
  [
@@ -52,7 +52,7 @@ export class SchemaTransformUtil {
52
52
  Object.entries(type.fieldTypes)
53
53
  .map(([k, v]) =>
54
54
  this.computeField(state, state.factory.createPropertyDeclaration(
55
- [], k,
55
+ [], /\W/.test(k) ? state.factory.createComputedPropertyName(state.fromLiteral(k)) : k,
56
56
  v.undefinable || v.nullable ? state.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
57
57
  v.key === 'unknown' ? state.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) : undefined, undefined
58
58
  ), { type: v, root })
@@ -68,7 +68,7 @@ export class SchemaTransformUtil {
68
68
  }
69
69
  return id;
70
70
  }
71
- case 'union': {
71
+ case 'composition': {
72
72
  if (type.commonType) {
73
73
  return this.toConcreteType(state, type.commonType, node, root);
74
74
  }
@@ -127,8 +127,8 @@ export class SchemaTransformUtil {
127
127
  const primaryExpr = typeExpr.key === 'literal' && typeExpr.typeArguments?.[0] ? typeExpr.typeArguments[0] : typeExpr;
128
128
 
129
129
  // We need to ensure we aren't being tripped up by the wrapper for arrays, sets, etc.
130
- // If we have a union type
131
- if (primaryExpr.key === 'union') {
130
+ // If we have a composition type
131
+ if (primaryExpr.key === 'composition') {
132
132
  const values = primaryExpr.subTypes.map(x => x.key === 'literal' ? x.value : undefined)
133
133
  .filter(x => x !== undefined && x !== null);
134
134