Skip to content

Instantly share code, notes, and snippets.

View kanian's full-sized avatar

Patrick Adou kanian

  • Abidjan, Ivory Coast
View GitHub Profile
@kanian
kanian / paramsSchema.ts
Created February 6, 2020 14:33
Parameter decorator
function paramSchema(schema: Schema) {
return function setParamSchemaMetadata(
target: Object,
propertyKey: string | symbol,
parameterIndex: number
) {
// If no property is given, we assume that we are trying to annotate a constructor parameter
propertyKey =
typeof propertyKey === "undefined" ? "constructor" : propertyKey;
// Collect metadata entries that mark parameters as constrained by a schema
@kanian
kanian / schemas.ts
Created February 6, 2020 14:06
Person schema
const personNameSchema = Joi.string().min(3)
const personAgeSchema = Joi.number().min(1)
const personSchema = Joi.object({
name: personNameSchema,
age: personAgeSchema
})
@kanian
kanian / personClassValidation.ts
Last active February 6, 2020 14:10
Use schema decorator to validate a Person object
@schema(personSchema)
class Person {
age: number
name: string
constructor(name: string, age: number) {
this.age = age
this.name = name
}
}
const p = new Person('Jake', 50)
@kanian
kanian / schema.ts
Last active July 7, 2021 19:22
Class schema decorator
function schema(schema: Schema) {
return function validateArgs(target: any) {
// save a reference to the original constructor
var original = target;
// wrap orginal constructor with validation behaviour
var f: any = function(...args) {
const instance = new original(...args);
const { error } = schema.validate(instance);
if (error instanceof Error) {
throw error;
const Joi = require('@hapi/joi')
const personNameSchema = Joi.string().min(3)
const personAgeSchema = Joi.number().min(1)
const personGroupName = Joi.string().min(3)
const personSchema = Joi.object({
name: personNameSchema,
age: personAgeSchema
})
private buildValidObject(p: ObjectArgumentDescriptor, value: object) {
if ((value as ValidObject).__className === 'ValidObject') {
return new (p.type as IValidObjectConstructor<typeof p.type>)(
'ValidObject',
(value as ValidObject).schema,
...this.buildValidObjectArguments(value as ValidObject)
)
} else {
// We have a derived class from ValidObject
return new (p.type as IDerivedValidObjectConstructor<typeof p.type>)(
@kanian
kanian / ArgumentDescriptor.ts
Created February 3, 2020 11:27
ArgumentDescriptor
type PrimitiveArgumentDescriptor<
T extends Primitive<PrimitiveType> = any
> = {
__className: 'PrimitiveArgumentDescriptor'
type: IPrimitiveConstructor<T>
name: string
value: PrimitiveType
}
type ObjectArgumentDescriptor<T extends ValidObject = any> = {
@kanian
kanian / setProperties.ts
Created February 3, 2020 10:47
setProperties(...x: AnyArgumentDescriptor[])
// Generate Getter and Setter for each property
setProperties(...x: AnyArgumentDescriptor[]) {
x.forEach(p => {
// initialise private property counterpart
this[`_${p.name}`] =
p.__className === 'ObjectArgumentDescriptor'
? p.value
: p.__className === 'PrimitiveArgumentDescriptor'
? new p.type(p.value)
: undefined
@kanian
kanian / _init.ts
Last active February 3, 2020 10:23
VaildObject._init(...x: AnyArgumentDescriptor[])
// Initialise the Object
private _init(...x: AnyArgumentDescriptor[]) {
this.params = x.map(arg =>
arg.__className === 'PrimitiveArgumentDescriptor'
? PrimitiveParameterDescriptorFactory(arg.type, arg.name)
: ObjectParameterDescriptorFactory(arg.type, arg.name)
)
this.setProperties(...x)
this._value = this.getValidable()
}
class ValidObject {
params: AnyParameterDescriptor[]
private _value: PrimitiveType | object = {}
constructor(
public readonly __className: string = 'ValidObject',private schema: Schema,...x: AnyArgumentDescriptor[]) {
this._init(...x)
const result = this.validate()
if (result instanceof Error) {
this.handleError(result)
}