@feathersjs/schema 0.0.1-alpha.4 → 5.0.0-pre.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/CHANGELOG.md +22 -10
- package/LICENSE +3 -2
- package/README.md +23 -0
- package/lib/hooks.d.ts +8 -0
- package/lib/hooks.js +101 -0
- package/lib/hooks.js.map +1 -0
- package/lib/index.d.ts +13 -9
- package/lib/index.js +14 -20
- package/lib/index.js.map +1 -1
- package/lib/query.d.ts +29 -0
- package/lib/query.js +37 -0
- package/lib/query.js.map +1 -0
- package/lib/resolver.d.ts +24 -0
- package/lib/resolver.js +70 -0
- package/lib/resolver.js.map +1 -0
- package/lib/schema.d.ts +18 -0
- package/lib/schema.js +42 -0
- package/lib/schema.js.map +1 -0
- package/package.json +34 -23
- package/src/hooks.ts +117 -0
- package/src/index.ts +9 -20
- package/src/query.ts +34 -0
- package/src/resolver.ts +108 -0
- package/src/schema.ts +49 -0
- package/lib/core.d.ts +0 -34
- package/lib/core.js +0 -89
- package/lib/core.js.map +0 -1
- package/lib/decorator.d.ts +0 -8
- package/lib/decorator.js +0 -35
- package/lib/decorator.js.map +0 -1
- package/lib/resolve.d.ts +0 -1
- package/lib/resolve.js +0 -29
- package/lib/resolve.js.map +0 -1
- package/readme.md +0 -1
- package/src/core.ts +0 -133
- package/src/decorator.ts +0 -40
- package/src/resolve.ts +0 -33
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { HookContext, NextFunction } from '@feathersjs/feathers';
|
|
2
|
+
import { BadRequest } from '../../errors/lib';
|
|
3
|
+
import { Resolver } from './resolver';
|
|
4
|
+
import { Schema } from './schema';
|
|
5
|
+
|
|
6
|
+
const getContext = (context: HookContext) => {
|
|
7
|
+
return {
|
|
8
|
+
...context,
|
|
9
|
+
params: {
|
|
10
|
+
...context.params,
|
|
11
|
+
query: {}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const resolveQuery = <T> (resolver: Resolver<T, HookContext>) =>
|
|
17
|
+
async (context: HookContext, next: NextFunction) => {
|
|
18
|
+
const ctx = getContext(context);
|
|
19
|
+
const data = context?.params?.query || {};
|
|
20
|
+
const query = await resolver.resolve(data, ctx, {
|
|
21
|
+
originalContext: context
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
context.params = {
|
|
25
|
+
...context.params,
|
|
26
|
+
query
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return next();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const resolveData = <T> (resolver: Resolver<T, HookContext>) =>
|
|
33
|
+
async (context: HookContext, next: NextFunction) => {
|
|
34
|
+
const ctx = getContext(context);
|
|
35
|
+
const data = context.data;
|
|
36
|
+
const status = {
|
|
37
|
+
originalContext: context
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (Array.isArray(data)) {
|
|
41
|
+
context.data = await Promise.all(data.map(current =>
|
|
42
|
+
resolver.resolve(current, ctx, status)
|
|
43
|
+
));
|
|
44
|
+
} else {
|
|
45
|
+
context.data = await resolver.resolve(data, ctx, status);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return next();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const resolveResult = <T> (resolver: Resolver<T, HookContext>) =>
|
|
52
|
+
async (context: HookContext, next: NextFunction) => {
|
|
53
|
+
const { $resolve: properties, ...query } = context.params?.query || {};
|
|
54
|
+
const { resolve } = context.params;
|
|
55
|
+
const status = {
|
|
56
|
+
originalContext: context,
|
|
57
|
+
...resolve,
|
|
58
|
+
properties
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
context.params = {
|
|
62
|
+
...context.params,
|
|
63
|
+
query
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await next();
|
|
67
|
+
|
|
68
|
+
const ctx = getContext(context);
|
|
69
|
+
const data = context.method === 'find' && context.result.data
|
|
70
|
+
? context.result.data
|
|
71
|
+
: context.result;
|
|
72
|
+
|
|
73
|
+
if (Array.isArray(data)) {
|
|
74
|
+
context.result = await Promise.all(data.map(current =>
|
|
75
|
+
resolver.resolve(current, ctx, status)
|
|
76
|
+
));
|
|
77
|
+
} else {
|
|
78
|
+
context.result = await resolver.resolve(data, ctx, status);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const validateQuery = (schema: Schema<any>) =>
|
|
83
|
+
async (context: HookContext, next: NextFunction) => {
|
|
84
|
+
const data = context?.params?.query || {};
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const query = await schema.validate(data);
|
|
88
|
+
|
|
89
|
+
context.params = {
|
|
90
|
+
...context.params,
|
|
91
|
+
query
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return next();
|
|
95
|
+
} catch (error: any) {
|
|
96
|
+
throw (error.ajv ? new BadRequest(error.message, error.errors) : error);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const validateData = (schema: Schema<any>) =>
|
|
101
|
+
async (context: HookContext, next: NextFunction) => {
|
|
102
|
+
const data = context.data;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
if (Array.isArray(data)) {
|
|
106
|
+
context.data = await Promise.all(data.map(current =>
|
|
107
|
+
schema.validate(current)
|
|
108
|
+
));
|
|
109
|
+
} else {
|
|
110
|
+
context.data = await schema.validate(data);
|
|
111
|
+
}
|
|
112
|
+
} catch (error: any) {
|
|
113
|
+
throw (error.ajv ? new BadRequest(error.message, error.errors) : error);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return next();
|
|
117
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { schemaDecorator, propertyDecorator } from './decorator';
|
|
1
|
+
import { ResolverStatus } from './resolver';
|
|
3
2
|
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
3
|
+
export * from './schema';
|
|
4
|
+
export * from './resolver';
|
|
5
|
+
export * from './hooks';
|
|
6
|
+
export * from './query';
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export type Infer<S extends { _type: any }> = S['_type'];
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export function schema (...args: any[]) {
|
|
14
|
-
if (args.length === 1) {
|
|
15
|
-
return schemaDecorator(args[0]);
|
|
10
|
+
declare module '@feathersjs/feathers/lib/declarations' {
|
|
11
|
+
interface Params {
|
|
12
|
+
resolve?: ResolverStatus<any, HookContext>;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
|
-
const target = args.length === 3 ? args.shift() : null;
|
|
19
|
-
const [ schemaMeta, schemaProperties ] = args;
|
|
20
|
-
const schema = new Schema(schemaMeta, schemaProperties);
|
|
21
|
-
|
|
22
|
-
setSchema(schema, target);
|
|
23
|
-
|
|
24
|
-
return schema;
|
|
25
14
|
}
|
package/src/query.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { JSONSchema } from 'json-schema-to-ts';
|
|
2
|
+
|
|
3
|
+
export const queryProperty = <T extends JSONSchema> (definition: T) => ({
|
|
4
|
+
oneOf: [
|
|
5
|
+
definition,
|
|
6
|
+
{
|
|
7
|
+
type: 'object',
|
|
8
|
+
additionalProperties: false,
|
|
9
|
+
properties: {
|
|
10
|
+
$gt: definition,
|
|
11
|
+
$gte: definition,
|
|
12
|
+
$lt: definition,
|
|
13
|
+
$lte: definition,
|
|
14
|
+
$ne: definition,
|
|
15
|
+
$in: {
|
|
16
|
+
type: 'array',
|
|
17
|
+
items: definition
|
|
18
|
+
},
|
|
19
|
+
$nin: {
|
|
20
|
+
type: 'array',
|
|
21
|
+
items: definition
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
} as const);
|
|
27
|
+
|
|
28
|
+
export const queryArray = <T extends readonly string[]> (fields: T) => ({
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
enum: fields
|
|
33
|
+
}
|
|
34
|
+
} as const);
|
package/src/resolver.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { BadRequest } from '@feathersjs/errors';
|
|
2
|
+
import { Schema } from './schema';
|
|
3
|
+
|
|
4
|
+
export type PropertyResolver<T, V, C> = (
|
|
5
|
+
value: V|undefined,
|
|
6
|
+
obj: any,
|
|
7
|
+
context: C,
|
|
8
|
+
status: ResolverStatus<T, C>
|
|
9
|
+
) => Promise<V|undefined>;
|
|
10
|
+
|
|
11
|
+
export type PropertyResolverMap<T, C> = {
|
|
12
|
+
[key in keyof T]?: PropertyResolver<T, T[key], C>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ResolverConfig<T, C> {
|
|
16
|
+
schema?: Schema<any>,
|
|
17
|
+
validate?: 'before'|'after'|false,
|
|
18
|
+
properties: PropertyResolverMap<T, C>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ResolverStatus<T, C> {
|
|
22
|
+
path: string[];
|
|
23
|
+
originalContext?: C;
|
|
24
|
+
properties?: (keyof T)[];
|
|
25
|
+
stack: PropertyResolver<T, any, C>[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class Resolver<T, C> {
|
|
29
|
+
readonly _type!: T;
|
|
30
|
+
|
|
31
|
+
constructor (public options: ResolverConfig<T, C>) {
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async resolveProperty<D, K extends keyof T> (
|
|
35
|
+
name: K,
|
|
36
|
+
data: D,
|
|
37
|
+
context: C,
|
|
38
|
+
status: Partial<ResolverStatus<T, C>> = {}
|
|
39
|
+
): Promise<T[K]> {
|
|
40
|
+
const resolver = this.options.properties[name];
|
|
41
|
+
const value = (data as any)[name];
|
|
42
|
+
const { path = [], stack = [] } = status || {};
|
|
43
|
+
|
|
44
|
+
// This prevents circular dependencies
|
|
45
|
+
if (stack.includes(resolver)) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const resolverStatus = {
|
|
50
|
+
...status,
|
|
51
|
+
path: [...path, name as string],
|
|
52
|
+
stack: [...stack, resolver]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return resolver(value, data, context, resolverStatus);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async resolve<D> (_data: D, context: C, status?: Partial<ResolverStatus<T, C>>): Promise<T> {
|
|
59
|
+
const { properties: resolvers, schema, validate } = this.options;
|
|
60
|
+
const data = schema && validate === 'before' ? await schema.validate(_data) : _data;
|
|
61
|
+
const propertyList = (Array.isArray(status?.properties)
|
|
62
|
+
? status?.properties
|
|
63
|
+
// By default get all data and resolver keys but remove duplicates
|
|
64
|
+
: [...new Set(Object.keys(data).concat(Object.keys(resolvers)))]
|
|
65
|
+
) as (keyof T)[];
|
|
66
|
+
|
|
67
|
+
const result: any = {};
|
|
68
|
+
const errors: any = {};
|
|
69
|
+
let hasErrors = false;
|
|
70
|
+
|
|
71
|
+
// Not the most elegant but better performance
|
|
72
|
+
await Promise.all(propertyList.map(async name => {
|
|
73
|
+
const value = data[name];
|
|
74
|
+
|
|
75
|
+
if (resolvers[name]) {
|
|
76
|
+
try {
|
|
77
|
+
const resolved = await this.resolveProperty(name, data, context, status);
|
|
78
|
+
|
|
79
|
+
if (resolved !== undefined) {
|
|
80
|
+
result[name] = resolved;
|
|
81
|
+
}
|
|
82
|
+
} catch (error: any) {
|
|
83
|
+
// TODO add error stacks
|
|
84
|
+
const convertedError = typeof error.toJSON === 'function'
|
|
85
|
+
? error.toJSON()
|
|
86
|
+
: { message: error.message || error };
|
|
87
|
+
|
|
88
|
+
errors[name] = convertedError;
|
|
89
|
+
hasErrors = true;
|
|
90
|
+
}
|
|
91
|
+
} else if (value !== undefined) {
|
|
92
|
+
result[name] = value;
|
|
93
|
+
}
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
if (hasErrors) {
|
|
97
|
+
throw new BadRequest(`Error resolving data ${status?.properties.join('.')}`, errors);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return schema && validate === 'after'
|
|
101
|
+
? await schema.validate(result)
|
|
102
|
+
: result;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function resolve <T, C> (options: ResolverConfig<T, C>) {
|
|
107
|
+
return new Resolver<T, C>(options);
|
|
108
|
+
}
|
package/src/schema.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Ajv, { AsyncValidateFunction } from 'ajv';
|
|
2
|
+
import { JSONSchema6 } from 'json-schema';
|
|
3
|
+
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
|
4
|
+
|
|
5
|
+
export const AJV = new Ajv({
|
|
6
|
+
coerceTypes: true
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type JSONSchemaDefinition = JSONSchema & { $id: string };
|
|
10
|
+
|
|
11
|
+
export class Schema<S extends JSONSchemaDefinition> {
|
|
12
|
+
ajv: Ajv;
|
|
13
|
+
validate: AsyncValidateFunction<FromSchema<S>>;
|
|
14
|
+
definition: JSONSchema6;
|
|
15
|
+
propertyNames: string[];
|
|
16
|
+
readonly _type!: FromSchema<S>;
|
|
17
|
+
|
|
18
|
+
constructor (definition: S, ajv: Ajv = AJV) {
|
|
19
|
+
this.ajv = ajv;
|
|
20
|
+
this.definition = definition as JSONSchema6;
|
|
21
|
+
this.propertyNames = Object.keys(this.definition.properties)
|
|
22
|
+
this.validate = this.ajv.compile({
|
|
23
|
+
$async: true,
|
|
24
|
+
...this.definition
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
extend <D extends JSONSchemaDefinition> (definition: D) {
|
|
29
|
+
const def = definition as JSONSchema6;
|
|
30
|
+
const extended = {
|
|
31
|
+
...this.definition,
|
|
32
|
+
...def,
|
|
33
|
+
properties: {
|
|
34
|
+
...this.definition.properties,
|
|
35
|
+
...def.properties
|
|
36
|
+
}
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
return new Schema <D & S> (extended as any, this.ajv);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
toJSON () {
|
|
43
|
+
return this.definition;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function schema <S extends JSONSchemaDefinition> (definition: S) {
|
|
48
|
+
return new Schema(definition);
|
|
49
|
+
}
|
package/lib/core.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/// <reference types="hapi__joi" />
|
|
2
|
-
import Joi from '@hapi/joi';
|
|
3
|
-
export declare const Type: Joi.Root;
|
|
4
|
-
export declare const typeMap: WeakMap<any, any>;
|
|
5
|
-
export declare const nameMap: {
|
|
6
|
-
[key: string]: Schema;
|
|
7
|
-
};
|
|
8
|
-
export declare let id: number;
|
|
9
|
-
export declare type SchemaTypes = Schema | string | Joi.AnySchema | typeof String | typeof Number | typeof Boolean;
|
|
10
|
-
export declare type SchemaPropertyType = SchemaTypes | SchemaTypes[] | Function;
|
|
11
|
-
export interface SchemaPropertyDefinition {
|
|
12
|
-
type: SchemaPropertyType;
|
|
13
|
-
[key: string]: any;
|
|
14
|
-
}
|
|
15
|
-
export interface SchemaMeta {
|
|
16
|
-
name: string;
|
|
17
|
-
[key: string]: any;
|
|
18
|
-
}
|
|
19
|
-
export interface SchemaProperties {
|
|
20
|
-
[key: string]: SchemaPropertyDefinition;
|
|
21
|
-
}
|
|
22
|
-
export declare const validatorFromType: (type: string | Function | StringConstructor | BooleanConstructor | NumberConstructor | Joi.AnySchema | Schema | SchemaTypes[] | (() => Joi.AnySchema)) => Joi.AnySchema;
|
|
23
|
-
export declare function getValidator(properties: SchemaProperties): Joi.ObjectSchema<any>;
|
|
24
|
-
export declare class Schema {
|
|
25
|
-
meta: SchemaMeta;
|
|
26
|
-
properties: SchemaProperties;
|
|
27
|
-
validator: Joi.ObjectSchema;
|
|
28
|
-
constructor(schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties);
|
|
29
|
-
validate(value: any, options?: Joi.AsyncValidationOptions): Promise<any>;
|
|
30
|
-
addProperties(schemaProperties: SchemaProperties): this;
|
|
31
|
-
addMetadata(schemaMeta: Partial<SchemaMeta>): this;
|
|
32
|
-
}
|
|
33
|
-
export declare function setSchema(schema: Schema, target: any): Schema;
|
|
34
|
-
export declare function getSchema(target: any): Schema | null;
|
package/lib/core.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const joi_1 = __importDefault(require("@hapi/joi"));
|
|
7
|
-
exports.Type = joi_1.default;
|
|
8
|
-
exports.typeMap = new WeakMap();
|
|
9
|
-
exports.nameMap = {};
|
|
10
|
-
exports.id = 0;
|
|
11
|
-
exports.typeMap.set(String, joi_1.default.string());
|
|
12
|
-
exports.typeMap.set(Number, joi_1.default.number());
|
|
13
|
-
exports.typeMap.set(Boolean, joi_1.default.boolean());
|
|
14
|
-
exports.validatorFromType = (type) => {
|
|
15
|
-
const value = exports.typeMap.get(type) || type;
|
|
16
|
-
if (Array.isArray(value) && value.length === 1) {
|
|
17
|
-
const [arrayValue] = value;
|
|
18
|
-
return joi_1.default.array().items(exports.validatorFromType(arrayValue));
|
|
19
|
-
}
|
|
20
|
-
const valueSchema = value instanceof Schema ? value : getSchema(value);
|
|
21
|
-
if (valueSchema !== null) {
|
|
22
|
-
return valueSchema.validator;
|
|
23
|
-
}
|
|
24
|
-
return value;
|
|
25
|
-
};
|
|
26
|
-
function getValidator(properties) {
|
|
27
|
-
const validators = Object.keys(properties).reduce((current, key) => {
|
|
28
|
-
const { type } = properties[key];
|
|
29
|
-
return {
|
|
30
|
-
...current,
|
|
31
|
-
[key]: exports.validatorFromType(type)
|
|
32
|
-
};
|
|
33
|
-
}, {});
|
|
34
|
-
return joi_1.default.object(validators);
|
|
35
|
-
}
|
|
36
|
-
exports.getValidator = getValidator;
|
|
37
|
-
class Schema {
|
|
38
|
-
constructor(schemaMeta, schemaProperties) {
|
|
39
|
-
this.properties = {};
|
|
40
|
-
this.meta = {
|
|
41
|
-
name: `schema-${++exports.id}`
|
|
42
|
-
};
|
|
43
|
-
this.addMetadata(schemaMeta);
|
|
44
|
-
this.addProperties(schemaProperties);
|
|
45
|
-
}
|
|
46
|
-
async validate(value, options) {
|
|
47
|
-
return this.validator.validateAsync(value, options);
|
|
48
|
-
}
|
|
49
|
-
addProperties(schemaProperties) {
|
|
50
|
-
this.properties = Object.assign(this.properties, schemaProperties);
|
|
51
|
-
this.validator = getValidator(this.properties);
|
|
52
|
-
return this;
|
|
53
|
-
}
|
|
54
|
-
addMetadata(schemaMeta) {
|
|
55
|
-
const oldName = this.meta.name;
|
|
56
|
-
this.meta = Object.assign(this.meta, schemaMeta);
|
|
57
|
-
delete exports.nameMap[oldName];
|
|
58
|
-
exports.nameMap[this.meta.name] = this;
|
|
59
|
-
return this;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
exports.Schema = Schema;
|
|
63
|
-
function setSchema(schema, target) {
|
|
64
|
-
exports.typeMap.set(target !== null ? target : schema, schema);
|
|
65
|
-
return schema;
|
|
66
|
-
}
|
|
67
|
-
exports.setSchema = setSchema;
|
|
68
|
-
function getSchema(target) {
|
|
69
|
-
if (target instanceof Schema) {
|
|
70
|
-
return target;
|
|
71
|
-
}
|
|
72
|
-
if (typeof target === 'string') {
|
|
73
|
-
return exports.nameMap[target] || null;
|
|
74
|
-
}
|
|
75
|
-
if (!target) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
let p = target;
|
|
79
|
-
do {
|
|
80
|
-
const schema = exports.typeMap.get(p);
|
|
81
|
-
if (schema !== undefined) {
|
|
82
|
-
return schema;
|
|
83
|
-
}
|
|
84
|
-
p = p.prototype;
|
|
85
|
-
} while (!!p);
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
exports.getSchema = getSchema;
|
|
89
|
-
//# sourceMappingURL=core.js.map
|
package/lib/core.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/lib/decorator.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/// <reference types="hapi__joi" />
|
|
2
|
-
import 'reflect-metadata';
|
|
3
|
-
import Joi, { AnySchema } from '@hapi/joi';
|
|
4
|
-
import { SchemaPropertyDefinition } from './index';
|
|
5
|
-
import { SchemaMeta } from './core';
|
|
6
|
-
export declare type TypeInitializer<T> = (type: T) => T;
|
|
7
|
-
export declare function propertyDecorator<T extends AnySchema = Joi.AnySchema>(definition?: Partial<SchemaPropertyDefinition> | TypeInitializer<T>, propDef?: Partial<SchemaPropertyDefinition>): (target: any, propertyName: string) => void;
|
|
8
|
-
export declare function schemaDecorator(definition: Partial<SchemaMeta>): (target: any) => void;
|
package/lib/decorator.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("reflect-metadata");
|
|
4
|
-
const index_1 = require("./index");
|
|
5
|
-
function propertyDecorator(definition = {}, propDef = {}) {
|
|
6
|
-
return (target, propertyName) => {
|
|
7
|
-
const type = Reflect.getMetadata('design:type', target, propertyName);
|
|
8
|
-
const targetSchema = index_1.getSchema(target) || index_1.schema(target, {}, {});
|
|
9
|
-
if (typeof definition === 'function') {
|
|
10
|
-
targetSchema.addProperties({
|
|
11
|
-
[propertyName]: {
|
|
12
|
-
type: definition(index_1.validatorFromType(type)),
|
|
13
|
-
...propDef
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
targetSchema.addProperties({
|
|
19
|
-
[propertyName]: {
|
|
20
|
-
type,
|
|
21
|
-
...definition
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
exports.propertyDecorator = propertyDecorator;
|
|
28
|
-
function schemaDecorator(definition) {
|
|
29
|
-
return (target) => {
|
|
30
|
-
const targetSchema = index_1.getSchema(target) || index_1.schema(target, {}, {});
|
|
31
|
-
targetSchema.addMetadata(definition);
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
exports.schemaDecorator = schemaDecorator;
|
|
35
|
-
//# sourceMappingURL=decorator.js.map
|
package/lib/decorator.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decorator.js","sourceRoot":"","sources":["../src/decorator.ts"],"names":[],"mappings":";;AAAA,4BAA0B;AAE1B,mCAAyF;AAKzF,SAAgB,iBAAiB,CAC/B,aAAmE,EAAE,EACrE,UAA6C,EAAE;IAE/C,OAAO,CAAC,MAAW,EAAE,YAAoB,EAAE,EAAE;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACtE,MAAM,YAAY,GAAG,iBAAS,CAAC,MAAM,CAAC,IAAI,cAAM,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAEjE,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE;YACpC,YAAY,CAAC,aAAa,CAAC;gBACzB,CAAC,YAAY,CAAC,EAAE;oBACd,IAAI,EAAE,UAAU,CAAC,yBAAiB,CAAC,IAAI,CAAM,CAAC;oBAC9C,GAAG,OAAO;iBACX;aACF,CAAC,CAAC;SACJ;aAAM;YACL,YAAY,CAAC,aAAa,CAAC;gBACzB,CAAC,YAAY,CAAC,EAAE;oBACd,IAAI;oBACJ,GAAG,UAAU;iBACd;aACF,CAAC,CAAC;SACJ;IACH,CAAC,CAAC;AACJ,CAAC;AAxBD,8CAwBC;AAED,SAAgB,eAAe,CAAE,UAA+B;IAC9D,OAAO,CAAC,MAAW,EAAE,EAAE;QACrB,MAAM,YAAY,GAAG,iBAAS,CAAC,MAAM,CAAC,IAAI,cAAM,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAEjE,YAAY,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC;AACJ,CAAC;AAND,0CAMC"}
|
package/lib/resolve.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function resolve<T = any>(source: T, schemaTarget: any, context: any, path?: any[]): Promise<T | T[]>;
|
package/lib/resolve.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const core_1 = require("./core");
|
|
4
|
-
async function resolve(source, schemaTarget, context, path = []) {
|
|
5
|
-
if (Array.isArray(source)) {
|
|
6
|
-
return Promise.all(source.map((current) => resolve(current, schemaTarget, context, path)));
|
|
7
|
-
}
|
|
8
|
-
const isArray = Array.isArray(schemaTarget);
|
|
9
|
-
const schema = core_1.getSchema(isArray ? schemaTarget[0] : schemaTarget);
|
|
10
|
-
const { properties } = schema;
|
|
11
|
-
const resolveKeys = Object.keys(properties).filter(key => typeof properties[key].resolve === 'function' && !path.includes(properties[key]));
|
|
12
|
-
if (resolveKeys.length) {
|
|
13
|
-
const entities = await Promise.all(resolveKeys.map(async (key) => {
|
|
14
|
-
const property = properties[key];
|
|
15
|
-
const { resolve: resolver, type } = property;
|
|
16
|
-
const entity = await resolver(source, context);
|
|
17
|
-
return resolve(entity, type, context, path.concat(property));
|
|
18
|
-
}));
|
|
19
|
-
return resolveKeys.reduce((result, key, index) => {
|
|
20
|
-
return {
|
|
21
|
-
...result,
|
|
22
|
-
[key]: entities[index]
|
|
23
|
-
};
|
|
24
|
-
}, source);
|
|
25
|
-
}
|
|
26
|
-
return source;
|
|
27
|
-
}
|
|
28
|
-
exports.resolve = resolve;
|
|
29
|
-
//# sourceMappingURL=resolve.js.map
|
package/lib/resolve.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":";;AAAA,iCAAmC;AAE5B,KAAK,UAAU,OAAO,CAAW,MAAS,EAAE,YAAiB,EAAE,OAAY,EAAE,OAAc,EAAE;IAClG,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;KACjG;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,gBAAS,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACnE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;IAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACvD,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,KAAK,UAAU,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CACjF,CAAC;IAEF,IAAI,WAAW,CAAC,MAAM,EAAE;QACtB,MAAM,QAAQ,GAAU,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAC,GAAG,EAAC,EAAE;YACpE,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;YAC7C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE/C,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC,CAAC;QAEJ,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YAC/C,OAAO;gBACL,GAAG,MAAM;gBACT,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;aACvB,CAAC;QACJ,CAAC,EAAE,MAAM,CAAC,CAAC;KACZ;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AA9BD,0BA8BC"}
|
package/readme.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# @feathersjs/schema
|