UNPKG

@feathersjs/knex

Version:

Feathers SQL service adapter using KnexJS

103 lines (81 loc) 2.71 kB
import { createDebug } from '@feathersjs/commons' import { HookContext } from '@feathersjs/feathers' import { Knex } from 'knex' import { KnexAdapterTransaction } from './declarations' const debug = createDebug('feathers-knex-transaction') const ROLLBACK = { rollback: true } export const getKnex = (context: HookContext): Knex => { const knex = context.params?.knex ? context.params.knex : typeof context.service.getModel === 'function' && context.service.getModel(context.params) return knex && typeof knex.transaction === 'function' ? knex : undefined } export const start = () => async (context: HookContext): Promise<void> => { const { transaction } = context.params const parent = transaction const knex: Knex = transaction ? transaction.trx : getKnex(context) if (!knex) { return } return new Promise<void>((resolve, reject) => { const transaction: KnexAdapterTransaction = { starting: true } if (parent) { transaction.parent = parent transaction.committed = parent.committed } else { transaction.committed = new Promise((resolve) => { transaction.resolve = resolve }) } transaction.starting = true transaction.promise = knex .transaction((trx) => { transaction.trx = trx transaction.id = Date.now() context.params = { ...context.params, transaction } debug('started a new transaction %s', transaction.id) resolve() }) .catch((error) => { if (transaction.starting) { reject(error) } else if (error !== ROLLBACK) { throw error } }) }) } export const end = () => (context: HookContext) => { const { transaction } = context.params if (!transaction) { return } const { trx, id, promise, parent } = transaction context.params = { ...context.params, transaction: parent } transaction.starting = false return trx .commit() .then(() => promise) .then(() => transaction.resolve && transaction.resolve(true)) .then(() => debug('ended transaction %s', id)) .then(() => context) } export const rollback = () => (context: HookContext) => { const { transaction } = context.params if (!transaction) { return } const { trx, id, promise, parent } = transaction context.params = { ...context.params, transaction: parent } transaction.starting = false return trx .rollback(ROLLBACK) .then(() => promise) .then(() => transaction.resolve && transaction.resolve(false)) .then(() => debug('rolled back transaction %s', id)) .then(() => context) }