picotx
Version:
A minimal library to create atomic transaction for any function
1 lines • 6.58 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/context.ts","../src/atomic.ts","../src/transaction.ts"],"sourcesContent":["export * from '@/atomic';\nexport * from '@/transaction';\nexport type { TransactionContext } from '@/context';\n","/**\n * Represents a transaction context that accumulates compensation (rollback) functions.\n *\n * @property {Array<() => Promise<void>>} compensations - An array of functions to perform rollback operations.\n */\nexport interface TransactionContext {\n compensations: Array<() => Promise<void>>;\n}\n\nconst transactionContextStack: TransactionContext[] = [];\n\nexport function getCurrentTransactionContext(): TransactionContext | undefined {\n return transactionContextStack[transactionContextStack.length - 1];\n}\n\nexport function pushTransactionContext(ctx: TransactionContext): void {\n transactionContextStack.push(ctx);\n}\n\nexport function popTransactionContext(): void {\n transactionContextStack.pop();\n}\n","import { TransactionContext, getCurrentTransactionContext } from '@/context';\n\nexport type AtomicFunction<A extends any[], R> = (...args: A) => Promise<R>;\n\n/**\n * Creates an atomic function that automatically retrieves the current transaction context.\n *\n * @template A - The type of the arguments for the action.\n * @template R - The return type of the action.\n * @param action - The asynchronous action to execute.\n * @param compensation - The asynchronous compensation (rollback) function to execute if needed.\n * @returns An atomic function that accepts the action arguments.\n */\nexport function atomic<A extends any[], R>(\n action: (...args: A) => Promise<R>,\n compensation: (result: R, ...args: A) => Promise<void>,\n): AtomicFunction<A, R> {\n return async (...args: A): Promise<R> => {\n const ctx = getCurrentTransactionContext();\n if (!ctx) {\n throw new Error('Cannot find current transaction context');\n }\n const result = await action(...args);\n ctx.compensations.push(() => compensation(result, ...args));\n return result;\n };\n}\n\nexport type ExplicitAtomicFunction<A extends any[], R> = (\n ctx: TransactionContext,\n) => (...args: A) => Promise<R>;\n\n/**\n * Creates an atomic function that requires an explicit transaction context.\n *\n * @template A - The type of the arguments for the action.\n * @template R - The return type of the action.\n * @param action - The asynchronous action to execute.\n * @param compensation - The asynchronous compensation (rollback) function to execute if needed.\n * @returns A curried atomic function that must first be invoked with a transaction context and then the action arguments.\n */\nexport function atomicExplicit<A extends any[], R>(\n action: (...args: A) => Promise<R>,\n compensation: (result: R, ...args: A) => Promise<void>,\n): ExplicitAtomicFunction<A, R> {\n return (ctx: TransactionContext) =>\n async (...args: A): Promise<R> => {\n const result = await action(...args);\n ctx.compensations.push(() => compensation(result, ...args));\n return result;\n };\n}\n","import {\n pushTransactionContext,\n popTransactionContext,\n TransactionContext,\n} from '@/context';\n\n/**\n * Executes a transactional operation by managing a global transaction context.\n * If the provided callback function expects an argument, it is called with the transaction context.\n * Otherwise, the function is invoked without arguments.\n *\n * @template T - The type of the transaction result.\n * @param fn - The asynchronous function containing transactional logic.\n * If it declares a parameter, it will be called with the transaction context.\n * @returns A promise that resolves to the transaction result.\n */\nexport async function transaction<T>(\n fn: ((ctx: TransactionContext) => Promise<T>) | (() => Promise<T>),\n): Promise<T> {\n const ctx: TransactionContext = { compensations: [] };\n pushTransactionContext(ctx);\n\n try {\n let result: T;\n if (fn.length > 0) {\n // Explicit mode: pass the transaction context\n result = await (fn as (ctx: TransactionContext) => Promise<T>)(ctx);\n } else {\n // Auto mode: do not pass any argument\n result = await (fn as () => Promise<T>)();\n }\n popTransactionContext();\n return result;\n } catch (error) {\n const rollbackErrors = [];\n for (const rollback of ctx.compensations.reverse()) {\n try {\n await rollback();\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n popTransactionContext();\n if (rollbackErrors.length > 0) {\n throw new AggregateError(\n rollbackErrors,\n 'One or more rollbacks failed',\n );\n }\n throw error;\n }\n}\n"],"mappings":"snBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,YAAAE,EAAA,mBAAAC,EAAA,gBAAAC,IAAA,eAAAC,EAAAL,GCSA,IAAMM,EAAgD,CAAC,EAEhD,SAASC,GAA+D,CAC3E,OAAOD,EAAwBA,EAAwB,OAAS,CAAC,CACrE,CAEO,SAASE,EAAuBC,EAA+B,CAClEH,EAAwB,KAAKG,CAAG,CACpC,CAEO,SAASC,GAA8B,CAC1CJ,EAAwB,IAAI,CAChC,CCRO,SAASK,EACZC,EACAC,EACoB,CACpB,MAAO,IAAUC,IAAwBC,EAAA,sBACrC,IAAMC,EAAMC,EAA6B,EACzC,GAAI,CAACD,EACD,MAAM,IAAI,MAAM,yCAAyC,EAE7D,IAAME,EAAS,MAAMN,EAAO,GAAGE,CAAI,EACnC,OAAAE,EAAI,cAAc,KAAK,IAAMH,EAAaK,EAAQ,GAAGJ,CAAI,CAAC,EACnDI,CACX,EACJ,CAeO,SAASC,EACZP,EACAC,EAC4B,CAC5B,OAAQG,GACJ,IAAUF,IAAwBC,EAAA,sBAC9B,IAAMG,EAAS,MAAMN,EAAO,GAAGE,CAAI,EACnC,OAAAE,EAAI,cAAc,KAAK,IAAMH,EAAaK,EAAQ,GAAGJ,CAAI,CAAC,EACnDI,CACX,EACR,CCnCA,SAAsBE,EAClBC,EACU,QAAAC,EAAA,sBACV,IAAMC,EAA0B,CAAE,cAAe,CAAC,CAAE,EACpDC,EAAuBD,CAAG,EAE1B,GAAI,CACA,IAAIE,EACJ,OAAIJ,EAAG,OAAS,EAEZI,EAAS,MAAOJ,EAA+CE,CAAG,EAGlEE,EAAS,MAAOJ,EAAwB,EAE5CK,EAAsB,EACfD,CACX,OAASE,EAAO,CACZ,IAAMC,EAAiB,CAAC,EACxB,QAAWC,KAAYN,EAAI,cAAc,QAAQ,EAC7C,GAAI,CACA,MAAMM,EAAS,CACnB,OAASC,EAAe,CACpBF,EAAe,KAAKE,CAAa,CACrC,CAGJ,MADAJ,EAAsB,EAClBE,EAAe,OAAS,EAClB,IAAI,eACNA,EACA,8BACJ,EAEED,CACV,CACJ","names":["index_exports","__export","atomic","atomicExplicit","transaction","__toCommonJS","transactionContextStack","getCurrentTransactionContext","pushTransactionContext","ctx","popTransactionContext","atomic","action","compensation","args","__async","ctx","getCurrentTransactionContext","result","atomicExplicit","transaction","fn","__async","ctx","pushTransactionContext","result","popTransactionContext","error","rollbackErrors","rollback","rollbackError"]}