Thin MongoDB ODM built for Standard Schema
mongodb
zod
deno
1import type { ClientSession, TransactionOptions } from "mongodb";
2import { getConnection } from "./connection.ts";
3import { ConnectionError } from "../errors.ts";
4
5/**
6 * Transaction management module
7 *
8 * Provides session and transaction management functionality including
9 * automatic transaction handling and manual session control.
10 */
11
12/**
13 * Start a new client session for transactions
14 *
15 * Sessions must be ended when done using `endSession()`
16 *
17 * @returns New MongoDB ClientSession
18 * @throws {ConnectionError} If not connected
19 *
20 * @example
21 * ```ts
22 * const session = startSession();
23 * try {
24 * // use session
25 * } finally {
26 * await endSession(session);
27 * }
28 * ```
29 */
30export function startSession(): ClientSession {
31 const connection = getConnection();
32 if (!connection) {
33 throw new ConnectionError("MongoDB not connected. Call connect() first.");
34 }
35 return connection.client.startSession();
36}
37
38/**
39 * End a client session
40 *
41 * @param session - The session to end
42 */
43export async function endSession(session: ClientSession): Promise<void> {
44 await session.endSession();
45}
46
47/**
48 * Execute a function within a transaction
49 *
50 * Automatically handles session creation, transaction start/commit/abort, and cleanup.
51 * If the callback throws an error, the transaction is automatically aborted.
52 *
53 * @param callback - Async function to execute within the transaction. Receives the session as parameter.
54 * @param options - Optional transaction options (read/write concern, etc.)
55 * @returns The result from the callback function
56 *
57 * @example
58 * ```ts
59 * const result = await withTransaction(async (session) => {
60 * await UserModel.insertOne({ name: "Alice" }, { session });
61 * await OrderModel.insertOne({ userId: "123", total: 100 }, { session });
62 * return { success: true };
63 * });
64 * ```
65 */
66export async function withTransaction<T>(
67 callback: (session: ClientSession) => Promise<T>,
68 options?: TransactionOptions,
69): Promise<T> {
70 const session = startSession();
71
72 try {
73 let result: T;
74
75 await session.withTransaction(async () => {
76 result = await callback(session);
77 }, options);
78
79 return result!;
80 } finally {
81 await endSession(session);
82 }
83}