"use strict";const{cppdb}=require("../util"),controllers=new WeakMap;module.exports=function(e){if("function"!=typeof e)throw new TypeError("Expected first argument to be a function");const r=this[cppdb],t=getController(r,this),{apply:a}=Function.prototype,n={default:{value:wrapTransaction(a,e,r,t.default)},deferred:{value:wrapTransaction(a,e,r,t.deferred)},immediate:{value:wrapTransaction(a,e,r,t.immediate)},exclusive:{value:wrapTransaction(a,e,r,t.exclusive)},database:{value:this,enumerable:!0}};return Object.defineProperties(n.default.value,n),Object.defineProperties(n.deferred.value,n),Object.defineProperties(n.immediate.value,n),Object.defineProperties(n.exclusive.value,n),n.default.value};const getController=(e,r)=>{let t=controllers.get(e);if(!t){const a={commit:e.prepare("COMMIT",r,!1),rollback:e.prepare("ROLLBACK",r,!1),savepoint:e.prepare("SAVEPOINT `\t_bs3.\t`",r,!1),release:e.prepare("RELEASE `\t_bs3.\t`",r,!1),rollbackTo:e.prepare("ROLLBACK TO `\t_bs3.\t`",r,!1)};controllers.set(e,t={default:Object.assign({begin:e.prepare("BEGIN",r,!1)},a),deferred:Object.assign({begin:e.prepare("BEGIN DEFERRED",r,!1)},a),immediate:Object.assign({begin:e.prepare("BEGIN IMMEDIATE",r,!1)},a),exclusive:Object.assign({begin:e.prepare("BEGIN EXCLUSIVE",r,!1)},a)})}return t},wrapTransaction=(e,r,t,{begin:a,commit:n,rollback:i,savepoint:o,release:c,rollbackTo:s})=>function(){let l,p,u;t.inTransaction?(l=o,p=c,u=s):(l=a,p=n,u=i),l.run();try{const t=e.call(r,this,arguments);if(t&&"function"==typeof t.then)throw new TypeError("Transaction function cannot return a promise");return p.run(),t}catch(e){throw t.inTransaction&&(u.run(),u!==i&&p.run()),e}};