phantasy-mysql
Version:
94 lines (79 loc) • 2.88 kB
Flow
// @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);
}