Skip to content

Commit

Permalink
feat: Add JsonSchema package.
Browse files Browse the repository at this point in the history
All class decorated with JsonProperty generate a JsonSchema. This
JsonSchema can be used with validators and swagger.
  • Loading branch information
Romakita committed Oct 23, 2017
1 parent 35b1280 commit a64741a
Show file tree
Hide file tree
Showing 45 changed files with 1,531 additions and 550 deletions.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@
},
"homepage": "https://romakita.github.io/ts-express-decorators/#/",
"dependencies": {
"@types/json-schema": "^4.0.0",
"@types/swagger-schema-official": "^2.0.6",
"glob": "^7.0.3",
"json-schema": "^0.2.3",
"reflect-metadata": "^0.1.8",
"source-map-support": "^0.5.0",
"ts-httpexceptions": "^2.2.1",
"ts-log-debug": "^3.0.0",
"tslib": "^1.7.1",
"@types/swagger-schema-official": "^2.0.6"
"tslib": "^1.7.1"
},
"devDependencies": {
"@types/chai": "^4.0.1",
Expand Down Expand Up @@ -110,4 +112,4 @@
"debug": false,
"branch": "production"
}
}
}
12 changes: 0 additions & 12 deletions src/converters/class/PropertyMetadata.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/converters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ export * from "./interfaces";

// decorators
export * from "./decorators/converter";
export * from "./decorators/jsonProperty";

// services
export * from "./services/ConverterService";

import "./components/ArrayConverter";
import "./components/DateConverter";
import "./components/MapConverter";
// filters
import "./components/PrimitiveConverter";
import "./components/SetConverter";
import "./components/SymbolConverter";
4 changes: 2 additions & 2 deletions src/converters/services/ConverterService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import {getClass, isArrayOrArrayClass, isEmpty, isPrimitiveOrPrimitiveClass} fro
import {InjectorService} from "../../di";
import {Service} from "../../di/decorators/service";
import {ServerSettingsService} from "../../server/services/ServerSettingsService";
import {PropertyMetadata} from "../class/PropertyMetadata";
import {PropertyMetadata} from "../../jsonschema/class/PropertyMetadata";
import {PropertyRegistry} from "../../jsonschema/registries/PropertyRegistry";
import {CONVERTER} from "../constants/index";
import {ConverterDeserializationError} from "../errors/ConverterDeserializationError";
import {ConverterSerializationError} from "../errors/ConverterSerializationError";
import {RequiredPropertyError} from "../errors/RequiredPropertyError";
import {UnknowPropertyError} from "../errors/UnknowPropertyError";
import {IConverter} from "../interfaces/index";
import {PropertyRegistry} from "../registries/PropertyRegistry";

@Service()
export class ConverterService {
Expand Down
140 changes: 46 additions & 94 deletions src/core/class/EntityDescription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@ import {Type} from "../interfaces";
* @module common/core
*/
/** */
import {getClass, isArrayOrArrayClass, isCollection, isPrimitiveOrPrimitiveClass, isPromise, nameOf} from "../utils";
import {
getClass,
isArrayOrArrayClass,
isClass,
isCollection,
isDate,
isObject,
isPrimitiveOrPrimitiveClass,
nameOf
} from "../utils";
import {Metadata} from "./Metadata";

/**
Expand Down Expand Up @@ -35,19 +44,6 @@ export abstract class EntityDescription {
@NotEnumerable()
protected _index: number;

/**
* Required entity.
*/
@NotEnumerable()
protected _required: boolean = false;

/**
* Allowed value when the entity is required.
* @type {Array}
*/
@NotEnumerable()
private _allowedValues: any[] = [];

constructor(protected _target: Type<any>,
protected _propertyKey: string | symbol,
index?: number | PropertyDescriptor) {
Expand All @@ -62,71 +58,55 @@ export abstract class EntityDescription {
* Return the index of the parameters.
* @returns {any}
*/
public get index(): number {
get index(): number {
return this._index;
}

/**
* Class of the entity.
* @returns {Type<any>}
*/
public get target(): Type<any> {
get target(): Type<any> {
return getClass(this._target);
}

/**
*
* @param {Type<any>} target
*/
public set target(target: Type<any>) {
this._target = target;
let type;

if (typeof this._index === "number") {
type = Metadata.getParamTypes(this._target, this._propertyKey)[this._index];
} else {
type = Metadata.getType(this._target, this._propertyKey);
}

if (isCollection(type)) {
this._collectionType = type;
this._type = Object;
} else {
this._type = type;
}

this._name = nameOf(this._propertyKey);
set target(target: Type<any>) {
this.setTarget(target);
}

/**
* Return the class name of the entity.
* @returns {string}
*/
public get targetName(): string {
get targetName(): string {
return nameOf(this.target);
}

/**
* Name of the method or attribute related to the class.
* @returns {string|symbol}
*/
public get propertyKey(): string | symbol {
get propertyKey(): string | symbol {
return this._propertyKey;
}

/**
*
* @param value
*/
public set type(value: Type<any>) {
set type(value: Type<any>) {
this._type = value || Object;
}

/**
*
* @returns {Type<any>}
*/
public get type(): Type<any> {
get type(): Type<any> {
return this._type;
}

Expand All @@ -142,15 +122,15 @@ export abstract class EntityDescription {
*
* @returns {any}
*/
public get collectionType(): Type<any> {
get collectionType(): Type<any> {
return this._collectionType;
}

/**
*
* @param {Type<any>} collectionType
*/
public set collectionType(collectionType: Type<any>) {
set collectionType(collectionType: Type<any>) {
this._collectionType = collectionType;
}

Expand All @@ -167,111 +147,83 @@ export abstract class EntityDescription {
*
* @returns {boolean}
*/
public get isCollection(): boolean {
get isCollection(): boolean {
return !!this._collectionType;
}

/**
*
* @returns {boolean}
*/
public get isArray() {
get isArray() {
return isArrayOrArrayClass(this._collectionType);
}

/**
*
* @returns {boolean}
*/
public get isPrimitive() {
get isPrimitive() {
return isPrimitiveOrPrimitiveClass(this._type);
}

/**
*
* @returns {boolean}
*/
public get isDate() {
return this._type === Date || this._type instanceof Date;
get isDate() {
return isDate(this._type);
}

/**
*
* @returns {boolean}
*/
public get isObject() {
return this.type === Object;
get isObject() {
return isObject(this.type);
}

/**
*
* @returns {boolean}
*/
public get isClass() {
return !this.isPrimitive && !this.isObject && !this.isDate && this.type !== undefined && !isPromise(this.type);
get isClass() {
return isClass(this.type);
}

/**
*
* @returns {string}
*/
public get name(): string {
get name(): string {
return this._name;
}

/**
*
* @param {string} value
*/
public set name(value: string) {
set name(value: string) {
this._name = value;
}

/**
* Return the required state.
* @returns {boolean}
*/
get required(): boolean {
return this._required;
}

/**
* Change the state of the required data.
* @param value
*/
set required(value: boolean) {
this._required = value;
}

/**
* Return the allowed values.
* @returns {any[]}
*/
get allowedValues(): any[] {
return this._allowedValues;
}
protected setTarget(target: Type<any>): void {
this._target = target;
let type;

/**
* Set the allowed values when the value is required.
* @param {any[]} value
*/
set allowedValues(value: any[]) {
this._allowedValues = value;
}
if (typeof this._index === "number") {
type = Metadata.getParamTypes(this._target, this._propertyKey)[this._index];
} else {
type = Metadata.getType(this._target, this._propertyKey);
}

/**
* This method use `EntityDescription.required` and `allowedValues` to validate the value.
* @param value
* @returns {boolean}
*/
isValidValue(value: any): boolean {
if (this.required) {
if (value === undefined || value === null || value === "") {
if (this.allowedValues.indexOf(value) === -1) {
return false;
}
}
if (isCollection(type)) {
this._collectionType = type;
this._type = Object;
} else {
this._type = type;
}
return true;

this._name = nameOf(this._propertyKey);
}
}
2 changes: 1 addition & 1 deletion src/core/class/ProxyRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export abstract class ProxyRegistry<T, I> {

}

abstract invoke<T>(target: any, locals?: Map<Function, any>, designParamTypes?: any[]): T;
// abstract invoke<T>(target: any, locals?: Map<Function, any>, designParamTypes?: any[]): T;
/**
*
* @param callbackfn
Expand Down
7 changes: 5 additions & 2 deletions src/core/decorators/configurable.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/**
* @module common/core
*/
import {descriptorOf} from "../utils";

/** */

export function Configurable(value: boolean = true): Function {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor = {writable: true, enumerable: true}) => {
return (target: any, propertyKey: string) => {
const descriptor = descriptorOf(target, propertyKey) || {writable: true, enumerable: true};
descriptor.configurable = value;
return descriptor;
Object.defineProperty(target && target.prototype || target, propertyKey, descriptor);
};
}
10 changes: 5 additions & 5 deletions src/core/decorators/enumerable.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/**
* @module common/core
*/
import {descriptorOf} from "../utils";

/** */

export function Enumerable(value: boolean = true): Function {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor = {
writable: true,
configurable: true
}) => {
return (target: any, propertyKey: string) => {
const descriptor = descriptorOf(target, propertyKey) || {writable: true, configurable: true};
descriptor.enumerable = value;
return descriptor;
Object.defineProperty(target && target.prototype || target, propertyKey, descriptor);
};
}

0 comments on commit a64741a

Please sign in to comment.