UNPKG

phantasy-mysql

Version:
94 lines (79 loc) 2.88 kB
// @flow import type { DeleteQuery, SelectQuery, UpdateQuery } from './builder'; import type { $MYSQL, DbPool, QueryResult, ResultInfo } from './effect'; import type { DictOf } from 'flow-helpers'; import type { RuntimeType, ValidationError } from 'phantasy-validation'; import * as t from 'phantasy-validation'; import { Delete, Insert, Replace, Select, Update } from './builder'; import { EffTask, Result } from 'phantasy'; import { poolQuery } from './main'; /** * `Schema` class */ export class Schema<Fields: {}> { table: string fieldValidators: DictOf<RuntimeType<any>> validate: (v: mixed) => Result<Fields, Error> constructor(table: string, validate: DictOf<RuntimeType<any>>): void { this.table = table; this.fieldValidators = validate; this.validate = (v: mixed): Result<Fields, Error> => t.validateValue(t.obj(validate), v).handleError(e => Result.Err(e.originalError)); } /** * Select records from the table */ select(q: (q: SelectQuery<*>) => SelectQuery<*>, pool: DbPool): EffTask<{ MYSQL: $MYSQL }, Array<Fields>, Error> { return poolQuery(q(Select()).from(this.table), pool) .andThen(results => { return ((t.validateValue(t.array(t.obj(this.fieldValidators)), results): any): Result<Array<Fields>, ValidationError>) .cases({ Val: v => EffTask.Success(v), Err: e => EffTask.Fail(e.originalError) }); }); } /** * Insert records into the table */ insert(values: Array<Fields>, pool: DbPool): EffTask<{ MYSQL: $MYSQL }, ResultInfo, Error> { return poolQuery(Insert(...values).into(this.table), pool) .andThen(validateInfo); } /** * Replace records in the table */ replace(values: Array<Fields>, pool: DbPool): EffTask<{ MYSQL: $MYSQL }, ResultInfo, Error> { return poolQuery(Replace(...values).into(this.table), pool) .andThen(validateInfo); } /** * Update records in the table */ update(q: (q: UpdateQuery<*>) => UpdateQuery<*>, pool: DbPool): EffTask<{ MYSQL: $MYSQL }, ResultInfo, Error> { return poolQuery(q(Update()).table(this.table), pool) .andThen(validateInfo); } /** * Delete records from the table */ delete(q: (q: DeleteQuery<*>) => DeleteQuery<*>, pool: DbPool): EffTask<{ MYSQL: $MYSQL }, ResultInfo, Error> { return poolQuery(q(Delete()).from(this.table), pool) .andThen(validateInfo); } } const resultInfoSchema = { affectedRows: t.num }; function validateInfo(results: QueryResult) { return t.validateValue(t.obj(resultInfoSchema), results) .cases({ Val: v => EffTask.Success(v), Err: e => EffTask.Fail(e.originalError) }); } /** * `schema :: ((DictOf (RuntimeType any)) t) => string -> t -> Schema ($ObjMap t (RuntimeType v -> v))` */ export function schema<Fields: DictOf<RuntimeType<any>>>(table: string, fields: Fields): Schema<$ObjMap<Fields, <V>(v: RuntimeType<V>) => V>> { return new Schema(table, fields); }