UNPKG

@resin/pinejs

Version:

Pine.js is a sophisticated rules-driven API engine that enables you to define rules in a structured subset of English. Those rules are used in order for Pine.js to generate a database schema and the associated [OData](http://www.odata.org/) API. This make

80 lines (69 loc) 1.8 kB
import * as _ from 'lodash' import * as Promise from 'bluebird' import { settleMapSeries } from './control-flow' export type RollbackAction = () => void | Promise<void> export type HookFn = (...args: any[]) => any type HookBluePrint = { HOOK: HookFn effects: boolean } export class Hook { constructor( private hookFn: HookFn ) {} run(...args: any[]) { return Promise.try(() => { return this.hookFn(...args) }) } } export class SideEffectHook extends Hook { private rollbackFns: RollbackAction[] = [] private rolledBack: boolean = false constructor(hookFn: HookFn) { super(hookFn) } registerRollback(fn: RollbackAction) { if (this.rolledBack) { Promise.try(fn) } else { this.rollbackFns.push(fn) } } rollback() { // Don't try to call the rollback functions twice if (this.rolledBack) { return } // set rolledBack to true straight away, so that if any rollback action // is registered after the rollback call, we will immediately execute it this.rolledBack = true return settleMapSeries(this.rollbackFns, (fn) => fn()).return() } } // The execution order of rollback actions is unspecified const undoHooks = function (request: any) { return settleMapSeries(_.flatten(_.values(request.hooks)), (hook) => { if (hook instanceof SideEffectHook) { return hook.rollback() } }) } export const rollbackRequestHooks = function (request: any) { if (_.isArray(request)) { return settleMapSeries(request, undoHooks) } else { return undoHooks(request) } } export const instantiateHooks = function (hooks: any) { return _.mapValues(hooks, (typeHooks) => { return _.map(typeHooks, (hook: HookBluePrint) => { if (hook.effects) { return new SideEffectHook(hook.HOOK) } else { return new Hook(hook.HOOK) } }) }) }