@feathersjs/schema
Advanced tools
Comparing version 0.0.1-alpha.0 to 0.0.1-alpha.1
@@ -6,2 +6,14 @@ # Change Log | ||
## [0.0.1-alpha.1](https://github.com/feathersjs/schema/compare/v0.0.1-alpha.0...v0.0.1-alpha.1) (2019-12-13) | ||
### Features | ||
* Allow references by name and prevent circular resolvers ([#3](https://github.com/feathersjs/schema/issues/3)) ([bb34edd](https://github.com/feathersjs/schema/commit/bb34edd36f47b375871ddbde86a089ae65391dda)) | ||
* First cut of working Sequelize model converter ([#4](https://github.com/feathersjs/schema/issues/4)) ([3187896](https://github.com/feathersjs/schema/commit/3187896304cf32043f5b5b569e2976b986e5eca4)) | ||
## 0.0.1-alpha.0 (2019-12-05) | ||
@@ -8,0 +20,0 @@ |
@@ -5,2 +5,5 @@ /// <reference types="hapi__joi" /> | ||
export declare const typeMap: WeakMap<any, any>; | ||
export declare const nameMap: { | ||
[key: string]: Schema; | ||
}; | ||
export declare let id: number; | ||
@@ -11,6 +14,8 @@ export declare type SchemaTypes = Schema | string | Joi.AnySchema | typeof String | typeof Number | typeof Boolean; | ||
type: SchemaPropertyType; | ||
resolve?: <T = any, C = any>(entity: T, context: C) => any; | ||
[key: string]: any; | ||
} | ||
export interface SchemaMeta { | ||
name?: string; | ||
name: string; | ||
[key: string]: any; | ||
} | ||
@@ -20,2 +25,3 @@ export interface SchemaProperties { | ||
} | ||
export declare const validatorFromType: (type: string | Function | StringConstructor | BooleanConstructor | NumberConstructor | Joi.AnySchema | Schema | SchemaTypes[] | (() => Joi.AnySchema)) => Joi.AnySchema; | ||
export declare function getValidator(properties: SchemaProperties): Joi.ObjectSchema<any>; | ||
@@ -26,8 +32,8 @@ export declare class Schema { | ||
validator: Joi.ObjectSchema; | ||
constructor(schemaMeta: SchemaMeta, schemaProperties: SchemaProperties); | ||
constructor(schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties); | ||
validate(value: any, options?: Joi.AsyncValidationOptions): Promise<any>; | ||
addProperties(schemaProperties: SchemaProperties): this; | ||
addMetadata(schemaMeta: SchemaMeta): this; | ||
addMetadata(schemaMeta: Partial<SchemaMeta>): this; | ||
} | ||
export declare function setSchema(schema: Schema, target: any): Schema; | ||
export declare function getSchema(target: any): Schema | null; |
@@ -9,2 +9,3 @@ "use strict"; | ||
exports.typeMap = new WeakMap(); | ||
exports.nameMap = {}; | ||
exports.id = 0; | ||
@@ -14,7 +15,7 @@ exports.typeMap.set(String, joi_1.default.string()); | ||
exports.typeMap.set(Boolean, joi_1.default.boolean()); | ||
const validatorFromType = (type) => { | ||
exports.validatorFromType = (type) => { | ||
const value = exports.typeMap.get(type) || type; | ||
if (Array.isArray(value) && value.length === 1) { | ||
const [arrayValue] = value; | ||
return joi_1.default.array().items(validatorFromType(arrayValue)); | ||
return joi_1.default.array().items(exports.validatorFromType(arrayValue)); | ||
} | ||
@@ -32,3 +33,3 @@ const valueSchema = value instanceof Schema ? value : getSchema(value); | ||
...current, | ||
[key]: validatorFromType(type) | ||
[key]: exports.validatorFromType(type) | ||
}; | ||
@@ -41,6 +42,6 @@ }, {}); | ||
constructor(schemaMeta, schemaProperties) { | ||
this.properties = {}; | ||
this.meta = { | ||
name: `schema-${++exports.id}` | ||
}; | ||
this.properties = {}; | ||
this.addMetadata(schemaMeta); | ||
@@ -58,3 +59,6 @@ this.addProperties(schemaProperties); | ||
addMetadata(schemaMeta) { | ||
const oldName = this.meta.name; | ||
this.meta = Object.assign(this.meta, schemaMeta); | ||
delete exports.nameMap[oldName]; | ||
exports.nameMap[this.meta.name] = this; | ||
return this; | ||
@@ -73,2 +77,5 @@ } | ||
} | ||
if (typeof target === 'string') { | ||
return exports.nameMap[target] || null; | ||
} | ||
let p = target; | ||
@@ -75,0 +82,0 @@ do { |
@@ -0,5 +1,8 @@ | ||
/// <reference types="hapi__joi" /> | ||
import 'reflect-metadata'; | ||
import Joi, { AnySchema } from '@hapi/joi'; | ||
import { SchemaPropertyDefinition } from './index'; | ||
import { SchemaMeta } from './core'; | ||
export declare function propertyDecorator(definition?: Partial<SchemaPropertyDefinition>): (target: any, propertyName: string) => void; | ||
export declare type TypeInitializer<T> = (type: T) => T; | ||
export declare function propertyDecorator<T extends AnySchema = Joi.AnySchema>(definition?: Partial<SchemaPropertyDefinition> | TypeInitializer<T>, propDef?: Partial<SchemaPropertyDefinition>): (target: any, propertyName: string) => void; | ||
export declare function schemaDecorator(definition: Partial<SchemaMeta>): (target: any) => void; |
@@ -5,12 +5,22 @@ "use strict"; | ||
const index_1 = require("./index"); | ||
function propertyDecorator(definition = {}) { | ||
function propertyDecorator(definition = {}, propDef = {}) { | ||
return (target, propertyName) => { | ||
const type = Reflect.getMetadata('design:type', target, propertyName); | ||
const targetSchema = index_1.getSchema(target) || index_1.schema(target, {}, {}); | ||
targetSchema.addProperties({ | ||
[propertyName]: { | ||
type, | ||
...definition | ||
} | ||
}); | ||
if (typeof definition === 'function') { | ||
targetSchema.addProperties({ | ||
[propertyName]: { | ||
type: definition(index_1.validatorFromType(type)), | ||
...propDef | ||
} | ||
}); | ||
} | ||
else { | ||
targetSchema.addProperties({ | ||
[propertyName]: { | ||
type, | ||
...definition | ||
} | ||
}); | ||
} | ||
}; | ||
@@ -17,0 +27,0 @@ } |
@@ -8,4 +8,4 @@ import { SchemaMeta, SchemaProperties, Schema } from './core'; | ||
export declare function validate(data: any, target: any): Promise<any>; | ||
export declare function schema(schemaMeta: SchemaMeta, schemaProperties: SchemaProperties): Schema; | ||
export declare function schema(target: any, schemaMeta: SchemaMeta, schemaProperties: SchemaProperties): Schema; | ||
export declare function schema(schemaMeta: SchemaMeta): (target: any) => void; | ||
export declare function schema(schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties): Schema; | ||
export declare function schema(target: any, schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties): Schema; | ||
export declare function schema(schemaMeta: Partial<SchemaMeta>): (target: any) => void; |
@@ -1,1 +0,1 @@ | ||
export declare function resolve<T = any>(source: T, schemaTarget: any, context: any): Promise<T>; | ||
export declare function resolve<T = any>(source: T, schemaTarget: any, context: any, path?: any[]): Promise<T | T[]>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const core_1 = require("./core"); | ||
async function resolve(source, schemaTarget, context) { | ||
const schema = core_1.getSchema(schemaTarget); | ||
async function resolve(source, schemaTarget, context, path = []) { | ||
if (Array.isArray(source)) { | ||
return Promise.all(source.map((current) => resolve(current, schemaTarget, context, path))); | ||
} | ||
const isArray = Array.isArray(schemaTarget); | ||
const schema = core_1.getSchema(isArray ? schemaTarget[0] : schemaTarget); | ||
const { properties } = schema; | ||
const resolveKeys = Object.keys(properties).filter(key => typeof properties[key].resolve === 'function'); | ||
const resolveKeys = Object.keys(properties).filter(key => typeof properties[key].resolve === 'function' && !path.includes(properties[key])); | ||
if (resolveKeys.length) { | ||
@@ -13,3 +17,3 @@ const entities = await Promise.all(resolveKeys.map(async (key) => { | ||
const entity = await resolver(source, context); | ||
return resolve(entity, type, context); | ||
return resolve(entity, type, context, path.concat(property)); | ||
})); | ||
@@ -16,0 +20,0 @@ return resolveKeys.reduce((result, key, index) => { |
{ | ||
"name": "@feathersjs/schema", | ||
"version": "0.0.1-alpha.0", | ||
"version": "0.0.1-alpha.1", | ||
"description": "Core Feathers schema", | ||
@@ -35,3 +35,4 @@ "homepage": "https://feathersjs.com", | ||
"compile": "shx rm -rf lib/ && tsc", | ||
"test": "mocha --opts ../../mocha.opts --recursive test/**.test.ts test/**/*.test.ts" | ||
"test": "npm run compile && npm run mocha", | ||
"mocha": "mocha --opts ../../mocha.opts --recursive test/**.test.ts test/**/*.test.ts" | ||
}, | ||
@@ -57,3 +58,3 @@ "directories": { | ||
}, | ||
"gitHead": "6fc1b0b85fef4ea5bd02bdd1024e51e47a2e587d" | ||
"gitHead": "c05f38bcd346c035e433834f426ce0a84ee65671" | ||
} |
@@ -6,2 +6,3 @@ import Joi from '@hapi/joi'; | ||
export const typeMap = new WeakMap<any, any>(); | ||
export const nameMap: { [key: string]: Schema } = {}; | ||
@@ -20,2 +21,3 @@ export let id = 0; | ||
type: SchemaPropertyType; | ||
resolve?: <T = any, C = any> (entity: T, context: C) => any; | ||
[key: string]: any; | ||
@@ -25,3 +27,4 @@ } | ||
export interface SchemaMeta { | ||
name?: string; | ||
name: string; | ||
[key: string]: any; | ||
} | ||
@@ -33,3 +36,3 @@ | ||
const validatorFromType = (type: Schema|SchemaPropertyType|(() => Joi.AnySchema)): Joi.AnySchema => { | ||
export const validatorFromType = (type: Schema|SchemaPropertyType|(() => Joi.AnySchema)): Joi.AnySchema => { | ||
const value = typeMap.get(type) || type; | ||
@@ -70,7 +73,7 @@ | ||
constructor (schemaMeta: SchemaMeta, schemaProperties: SchemaProperties) { | ||
constructor (schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties) { | ||
this.properties = {}; | ||
this.meta = { | ||
name: `schema-${++id}` | ||
}; | ||
this.properties = {}; | ||
@@ -92,5 +95,10 @@ this.addMetadata(schemaMeta); | ||
addMetadata (schemaMeta: SchemaMeta) { | ||
addMetadata (schemaMeta: Partial<SchemaMeta>) { | ||
const oldName = this.meta.name; | ||
this.meta = Object.assign(this.meta, schemaMeta); | ||
delete nameMap[oldName]; | ||
nameMap[this.meta.name] = this; | ||
return this; | ||
@@ -111,2 +119,6 @@ } | ||
if (typeof target === 'string') { | ||
return nameMap[target] || null; | ||
} | ||
let p = target; | ||
@@ -113,0 +125,0 @@ |
import 'reflect-metadata'; | ||
import { getSchema, schema, SchemaPropertyDefinition } from './index'; | ||
import Joi, { AnySchema } from '@hapi/joi'; | ||
import { getSchema, schema, SchemaPropertyDefinition, validatorFromType } from './index'; | ||
import { SchemaMeta } from './core'; | ||
export function propertyDecorator (definition: Partial<SchemaPropertyDefinition> = {}) { | ||
export type TypeInitializer<T> = (type: T) => T; | ||
export function propertyDecorator<T extends AnySchema = Joi.AnySchema> ( | ||
definition: Partial<SchemaPropertyDefinition>|TypeInitializer<T> = {}, | ||
propDef: Partial<SchemaPropertyDefinition> = {} | ||
) { | ||
return (target: any, propertyName: string) => { | ||
@@ -10,8 +16,17 @@ const type = Reflect.getMetadata('design:type', target, propertyName); | ||
targetSchema.addProperties({ | ||
[propertyName]: { | ||
type, | ||
...definition | ||
} | ||
}); | ||
if (typeof definition === 'function') { | ||
targetSchema.addProperties({ | ||
[propertyName]: { | ||
type: definition(validatorFromType(type) as T), | ||
...propDef | ||
} | ||
}); | ||
} else { | ||
targetSchema.addProperties({ | ||
[propertyName]: { | ||
type, | ||
...definition | ||
} | ||
}); | ||
} | ||
}; | ||
@@ -18,0 +33,0 @@ } |
@@ -20,5 +20,5 @@ import { SchemaMeta, SchemaProperties, Schema, setSchema, getSchema } from './core'; | ||
export function schema (schemaMeta: SchemaMeta, schemaProperties: SchemaProperties): Schema; | ||
export function schema (target: any, schemaMeta: SchemaMeta, schemaProperties: SchemaProperties): Schema; | ||
export function schema (schemaMeta: SchemaMeta): (target: any) => void; | ||
export function schema (schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties): Schema; | ||
export function schema (target: any, schemaMeta: Partial<SchemaMeta>, schemaProperties: SchemaProperties): Schema; | ||
export function schema (schemaMeta: Partial<SchemaMeta>): (target: any) => void; | ||
export function schema (...args: any[]) { | ||
@@ -25,0 +25,0 @@ if (args.length === 1) { |
import { getSchema } from './core'; | ||
export async function resolve<T = any> (source: T, schemaTarget: any, context: any) { | ||
const schema = getSchema(schemaTarget); | ||
export async function resolve<T = any> (source: T, schemaTarget: any, context: any, path: any[] = []): Promise<T|T[]> { | ||
if (Array.isArray(source)) { | ||
return Promise.all(source.map((current: any) => resolve(current, schemaTarget, context, path))); | ||
} | ||
const isArray = Array.isArray(schemaTarget); | ||
const schema = getSchema(isArray ? schemaTarget[0] : schemaTarget); | ||
const { properties } = schema; | ||
const resolveKeys = Object.keys(properties).filter(key => typeof properties[key].resolve === 'function'); | ||
const resolveKeys = Object.keys(properties).filter(key => | ||
typeof properties[key].resolve === 'function' && !path.includes(properties[key]) | ||
); | ||
@@ -14,3 +21,3 @@ if (resolveKeys.length) { | ||
return resolve(entity, type, context); | ||
return resolve(entity, type, context, path.concat(property)); | ||
})); | ||
@@ -17,0 +24,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25083
413