@feathersjs/schema 5.0.0-pre.21 → 5.0.0-pre.24

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/resolver.ts CHANGED
@@ -1,23 +1,26 @@
1
- import { BadRequest } from '@feathersjs/errors';
2
- import { Schema } from './schema';
1
+ import { BadRequest } from '@feathersjs/errors'
2
+ import { Schema } from './schema'
3
3
 
4
4
  export type PropertyResolver<T, V, C> = (
5
- value: V|undefined,
5
+ value: V | undefined,
6
6
  obj: T,
7
7
  context: C,
8
8
  status: ResolverStatus<T, C>
9
- ) => Promise<V|undefined>;
9
+ ) => Promise<V | undefined>
10
10
 
11
11
  export type PropertyResolverMap<T, C> = {
12
12
  [key in keyof T]?: PropertyResolver<T, T[key], C>
13
13
  }
14
14
 
15
- export type ResolverConverter<T, C> = (obj: any, context: C, status: ResolverStatus<T, C>)
16
- => Promise<T|undefined>
15
+ export type ResolverConverter<T, C> = (
16
+ obj: any,
17
+ context: C,
18
+ status: ResolverStatus<T, C>
19
+ ) => Promise<T | undefined>
17
20
 
18
21
  export interface ResolverConfig<T, C> {
19
- schema?: Schema<T>,
20
- validate?: 'before'|'after'|false,
22
+ schema?: Schema<T>
23
+ validate?: 'before' | 'after' | false
21
24
  properties: PropertyResolverMap<T, C>
22
25
  converter?: ResolverConverter<T, C>
23
26
  }
@@ -30,24 +33,23 @@ export interface ResolverStatus<T, C> {
30
33
  }
31
34
 
32
35
  export class Resolver<T, C> {
33
- readonly _type!: T;
36
+ readonly _type!: T
34
37
 
35
- constructor (public options: ResolverConfig<T, C>) {
36
- }
38
+ constructor(public options: ResolverConfig<T, C>) {}
37
39
 
38
- async resolveProperty<D, K extends keyof T> (
40
+ async resolveProperty<D, K extends keyof T>(
39
41
  name: K,
40
42
  data: D,
41
43
  context: C,
42
44
  status: Partial<ResolverStatus<T, C>> = {}
43
45
  ): Promise<T[K]> {
44
- const resolver = this.options.properties[name];
45
- const value = (data as any)[name];
46
- const { path = [], stack = [] } = status || {};
46
+ const resolver = this.options.properties[name]
47
+ const value = (data as any)[name]
48
+ const { path = [], stack = [] } = status || {}
47
49
 
48
50
  // This prevents circular dependencies
49
51
  if (stack.includes(resolver)) {
50
- return undefined;
52
+ return undefined
51
53
  }
52
54
 
53
55
  const resolverStatus = {
@@ -56,10 +58,10 @@ export class Resolver<T, C> {
56
58
  stack: [...stack, resolver]
57
59
  }
58
60
 
59
- return resolver(value, data as any, context, resolverStatus);
61
+ return resolver(value, data as any, context, resolverStatus)
60
62
  }
61
63
 
62
- async convert <D> (data: D, context: C, status?: Partial<ResolverStatus<T, C>>) {
64
+ async convert<D>(data: D, context: C, status?: Partial<ResolverStatus<T, C>>) {
63
65
  if (this.options.converter) {
64
66
  const { path = [], stack = [] } = status || {}
65
67
 
@@ -69,57 +71,57 @@ export class Resolver<T, C> {
69
71
  return data
70
72
  }
71
73
 
72
- async resolve<D> (_data: D, context: C, status?: Partial<ResolverStatus<T, C>>): Promise<T> {
73
- const { properties: resolvers, schema, validate } = this.options;
74
- const payload = await this.convert(_data, context, status);
75
- const data = schema && validate === 'before' ? await schema.validate(payload) : payload;
76
- const propertyList = (Array.isArray(status?.properties)
77
- ? status?.properties
78
- // By default get all data and resolver keys but remove duplicates
79
- : [...new Set(Object.keys(data).concat(Object.keys(resolvers)))]
80
- ) as (keyof T)[];
81
-
82
- const result: any = {};
83
- const errors: any = {};
84
- let hasErrors = false;
74
+ async resolve<D>(_data: D, context: C, status?: Partial<ResolverStatus<T, C>>): Promise<T> {
75
+ const { properties: resolvers, schema, validate } = this.options
76
+ const payload = await this.convert(_data, context, status)
77
+ const data = schema && validate === 'before' ? await schema.validate(payload) : payload
78
+ const propertyList = (
79
+ Array.isArray(status?.properties)
80
+ ? status?.properties
81
+ : // By default get all data and resolver keys but remove duplicates
82
+ [...new Set(Object.keys(data).concat(Object.keys(resolvers)))]
83
+ ) as (keyof T)[]
84
+
85
+ const result: any = {}
86
+ const errors: any = {}
87
+ let hasErrors = false
85
88
 
86
89
  // Not the most elegant but better performance
87
- await Promise.all(propertyList.map(async name => {
88
- const value = (data as any)[name];
89
-
90
- if (resolvers[name]) {
91
- try {
92
- const resolved = await this.resolveProperty(name, data, context, status);
93
-
94
- if (resolved !== undefined) {
95
- result[name] = resolved;
90
+ await Promise.all(
91
+ propertyList.map(async (name) => {
92
+ const value = (data as any)[name]
93
+
94
+ if (resolvers[name]) {
95
+ try {
96
+ const resolved = await this.resolveProperty(name, data, context, status)
97
+
98
+ if (resolved !== undefined) {
99
+ result[name] = resolved
100
+ }
101
+ } catch (error: any) {
102
+ // TODO add error stacks
103
+ const convertedError =
104
+ typeof error.toJSON === 'function' ? error.toJSON() : { message: error.message || error }
105
+
106
+ errors[name] = convertedError
107
+ hasErrors = true
96
108
  }
97
- } catch (error: any) {
98
- // TODO add error stacks
99
- const convertedError = typeof error.toJSON === 'function'
100
- ? error.toJSON()
101
- : { message: error.message || error };
102
-
103
- errors[name] = convertedError;
104
- hasErrors = true;
109
+ } else if (value !== undefined) {
110
+ result[name] = value
105
111
  }
106
- } else if (value !== undefined) {
107
- result[name] = value;
108
- }
109
- }));
112
+ })
113
+ )
110
114
 
111
115
  if (hasErrors) {
112
- const propertyName = status?.properties ? ` ${status.properties.join('.')}` : '';
116
+ const propertyName = status?.properties ? ` ${status.properties.join('.')}` : ''
113
117
 
114
- throw new BadRequest('Error resolving data' + (propertyName ? ` ${propertyName}` : ''), errors);
118
+ throw new BadRequest('Error resolving data' + (propertyName ? ` ${propertyName}` : ''), errors)
115
119
  }
116
120
 
117
- return schema && validate === 'after'
118
- ? await schema.validate(result)
119
- : result;
121
+ return schema && validate === 'after' ? await schema.validate(result) : result
120
122
  }
121
123
  }
122
124
 
123
- export function resolve <T, C> (options: ResolverConfig<T, C>) {
124
- return new Resolver<T, C>(options);
125
+ export function resolve<T, C>(options: ResolverConfig<T, C>) {
126
+ return new Resolver<T, C>(options)
125
127
  }
package/src/schema.ts CHANGED
@@ -1,60 +1,60 @@
1
- import Ajv, { AsyncValidateFunction, ValidateFunction } from 'ajv';
2
- import { FromSchema, JSONSchema } from 'json-schema-to-ts';
3
- import { BadRequest } from '@feathersjs/errors';
1
+ import Ajv, { AsyncValidateFunction, ValidateFunction } from 'ajv'
2
+ import { FromSchema, JSONSchema } from 'json-schema-to-ts'
3
+ import { BadRequest } from '@feathersjs/errors'
4
4
 
5
5
  export const DEFAULT_AJV = new Ajv({
6
6
  coerceTypes: true
7
- });
7
+ })
8
8
 
9
- export { Ajv };
9
+ export { Ajv }
10
10
 
11
11
  export type JSONSchemaDefinition = JSONSchema & {
12
- $id: string,
13
- $async?: boolean,
12
+ $id: string
13
+ $async?: boolean
14
14
  properties?: { [key: string]: JSONSchema }
15
15
  required?: readonly string[]
16
- };
16
+ }
17
17
 
18
18
  export interface Schema<T> {
19
- validate <X = T> (...args: Parameters<ValidateFunction<X>>): Promise<X>;
19
+ validate<X = T>(...args: Parameters<ValidateFunction<X>>): Promise<X>
20
20
  }
21
21
 
22
22
  export class SchemaWrapper<S extends JSONSchemaDefinition> implements Schema<FromSchema<S>> {
23
- ajv: Ajv;
24
- validator: AsyncValidateFunction;
25
- readonly _type!: FromSchema<S>;
23
+ ajv: Ajv
24
+ validator: AsyncValidateFunction
25
+ readonly _type!: FromSchema<S>
26
26
 
27
- constructor (public definition: S, ajv: Ajv = DEFAULT_AJV) {
28
- this.ajv = ajv;
27
+ constructor(public definition: S, ajv: Ajv = DEFAULT_AJV) {
28
+ this.ajv = ajv
29
29
  this.validator = this.ajv.compile({
30
30
  $async: true,
31
31
  ...(this.definition as any)
32
- }) as AsyncValidateFunction;
32
+ }) as AsyncValidateFunction
33
33
  }
34
34
 
35
- get properties () {
36
- return this.definition.properties as S['properties'];
35
+ get properties() {
36
+ return this.definition.properties as S['properties']
37
37
  }
38
38
 
39
- get required () {
40
- return this.definition.required as S['required'];
39
+ get required() {
40
+ return this.definition.required as S['required']
41
41
  }
42
42
 
43
- async validate <T = FromSchema<S>> (...args: Parameters<ValidateFunction<T>>) {
43
+ async validate<T = FromSchema<S>>(...args: Parameters<ValidateFunction<T>>) {
44
44
  try {
45
- const validated = await this.validator(...args) as T;
45
+ const validated = (await this.validator(...args)) as T
46
46
 
47
- return validated;
47
+ return validated
48
48
  } catch (error: any) {
49
- throw new BadRequest(error.message, error.errors);
49
+ throw new BadRequest(error.message, error.errors)
50
50
  }
51
51
  }
52
52
 
53
- toJSON () {
54
- return this.definition;
53
+ toJSON() {
54
+ return this.definition
55
55
  }
56
56
  }
57
57
 
58
- export function schema <S extends JSONSchemaDefinition> (definition: S, ajv: Ajv = DEFAULT_AJV) {
59
- return new SchemaWrapper(definition, ajv);
58
+ export function schema<S extends JSONSchemaDefinition>(definition: S, ajv: Ajv = DEFAULT_AJV) {
59
+ return new SchemaWrapper(definition, ajv)
60
60
  }