Skip to content

Instantly share code, notes, and snippets.

@fatihky
Created January 13, 2018 16:32
Show Gist options
  • Save fatihky/26f7bbc193a9752bae614fe620cc7cdd to your computer and use it in GitHub Desktop.
Save fatihky/26f7bbc193a9752bae614fe620cc7cdd to your computer and use it in GitHub Desktop.
validator typescript
// import vald from './src'
// const res = vald
// .base('string')
// .step('json')
// .base('object')
// .step('keys', {
// foo: vald.base('string').step('min', 10)
// })
// .validate('{"foo": "bar bar bar"}')
// console.log(res)
import { Map } from 'immutable'
enum ValidationInsertType {
HEAD = 1,
TAIL
}
interface Validator {
func: string
insertType: ValidationInsertType
}
interface Step {
func: string,
baseName: string
}
class SchemaBase {
methods: Map<string, Validator>
defaultValidator: Validator // protected sub schema bases
constructor(methods: Map<string, Validator>) {
this.methods = methods
}
clone(): SchemaBase {
const clone = new SchemaBase(this.methods)
clone.defaultValidator = this.defaultValidator
return clone
}
extend(methods: Map<string, Validator>): SchemaBase {
const clone = this.clone()
clone.methods = clone.methods.merge(methods)
return clone
}
merge(base: SchemaBase): SchemaBase {
return this.extend(base.methods)
}
setDefaultValidator(func: Validator): SchemaBase {
const clone = this.clone()
clone.defaultValidator = func
return clone
}
set(name, func: Validator): SchemaBase {
return this.extend(Map<string, Validator>().set(name, func))
}
has(name: string) {
return this.methods.has(name)
}
get(name: string): Validator {
if (!this.has(name)) {
throw new Error(`method ${name} does not exist`)
}
return this.methods.get(name)
}
toString(): string {
return `'[SchemaBase {${this.methods.valueSeq().toArray().join(', ')}}]'`
}
}
class Schema {
bases: Map<string, SchemaBase>
steps: Array<Step>
private currentBase: SchemaBase = null
private currentBaseName: string = null
constructor() {
this.bases = Map<string, SchemaBase>()
this.steps = new Array<Step>()
}
static clone(bases: Map<string, SchemaBase>, steps: Array<Step>): Schema {
const clone = new Schema()
clone.bases = bases
clone.steps = steps.slice()
return clone
}
extend(name: string, base: SchemaBase): Schema {
console.log(`.extend(${name})`)
if (this.bases.has(name)) {
console.log('merge current base')
return Schema.clone(this.bases.set(name, this.bases.get(name).merge(base)), this.steps.slice())
}
console.log('insert a new base')
return Schema.clone(this.bases.set(name, base), this.steps.slice())
}
private _addStep(validatorDefinition: Validator) {
const {func, insertType} = validatorDefinition
const step: Step = {
func,
baseName: this.currentBaseName
}
if (insertType === ValidationInsertType.HEAD) {
if (this.steps.length === 0) {
this.steps.push(step)
} else {
for (let i = this.steps.length - 1; i >= 0; i--) {
if (this.steps[i].baseName !== this.currentBaseName) {
this.steps.splice(i + 1, 0, step)
break
}
}
}
} else {
console.log('_addStep(): add step to the tail')
this.steps.push(step)
}
}
base(name: string): Schema {
if (!this.bases.has(name)) {
throw new Error(`base "${name}" does not exist`)
}
if (name === this.currentBaseName) {
return
}
this.currentBase = this.bases.get(name)
this.currentBaseName = name
if (this.currentBase.defaultValidator) {
console.log('insert default validation step for the new validator base')
this._addStep(this.currentBase.defaultValidator)
}
return this
}
step(name: string): Schema {
if (this.currentBase === null) {
throw new Error('no base selected')
}
if (!this.currentBase.has(name)) {
throw new Error(`method ${this.currentBaseName}.${name} does not exist`)
}
this._addStep(this.currentBase.get(name))
return this
}
}
const anyBase = new SchemaBase(Map<string, Validator>())
const stringBase = anyBase
.setDefaultValidator({
func: '.stringDefault()',
insertType: ValidationInsertType.HEAD
})
.set('min', {
func: '.min()',
insertType: ValidationInsertType.TAIL
})
const arrayBase = anyBase
.setDefaultValidator({
func: '.arrayDefault()',
insertType: ValidationInsertType.HEAD
})
.set('items', {
func: 'items()',
insertType: ValidationInsertType.TAIL
})
const vald = new Schema()
.extend('any', anyBase)
.extend('string', stringBase)
.extend('array', arrayBase)
const schema = vald
.base('string')
.step('min')
.base('array')
console.log(schema)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment