teqo-backup/src/utilities/payloadTransaction.ts
Francisco Ignácio Fontoura Solla bcac665cb5 Ship /campanha nuclei MVP with RBAC, invites, and vote estimates.
Adds electoral nuclei, leaderships, updates, and WhatsApp invite flows behind campaign auth, plus the consolidated schema migration that Vercel applies on deploy.
2026-07-18 15:01:56 -03:00

66 lines
1.7 KiB
TypeScript

import 'server-only'
import type { Payload } from 'payload'
export type PayloadTransactionRequest = {
transactionID: number | string
}
export type PayloadTransactionContext = {
transactionID: number | string
req: PayloadTransactionRequest
}
type TransactionPayload = Pick<Payload, 'db'>
export type PayloadTransactionOptions = {
beginFailureMessage?: string
}
const DEFAULT_BEGIN_FAILURE_MESSAGE = 'Não foi possível iniciar a transação.'
const rollbackOrAggregate = async (
payload: TransactionPayload,
transactionID: number | string,
originalError: unknown,
): Promise<never> => {
try {
await payload.db.rollbackTransaction(transactionID)
} catch (rollbackError) {
throw new AggregateError(
[originalError, rollbackError],
'A operação e o rollback da transação falharam.',
{ cause: originalError },
)
}
throw originalError
}
export const withPayloadTransaction = async <Result>(
payload: TransactionPayload,
callback: (context: PayloadTransactionContext) => Promise<Result>,
options: PayloadTransactionOptions = {},
): Promise<Result> => {
const transactionID = await payload.db.beginTransaction()
if (transactionID === null) {
throw new Error(options.beginFailureMessage ?? DEFAULT_BEGIN_FAILURE_MESSAGE)
}
const req: PayloadTransactionRequest = { transactionID }
let result: Result
try {
result = await callback({ transactionID, req })
} catch (error) {
return rollbackOrAggregate(payload, transactionID, error)
}
try {
await payload.db.commitTransaction(transactionID)
} catch (error) {
return rollbackOrAggregate(payload, transactionID, error)
}
return result
}