* Commit the transaction and execute the mutation function * @returns Promise that resolves to this transaction when complete * @example * // Manual commit (when autoCommit is false) * const tx = createTransaction({ * autoCommit: false, * mutationFn: async ({ transaction }) =>
()
| 491 | * console.log(tx.state) // "completed" or "failed" |
| 492 | */ |
| 493 | async commit(): Promise<Transaction<T>> { |
| 494 | if (this.state !== `pending`) { |
| 495 | throw new TransactionNotPendingCommitError() |
| 496 | } |
| 497 | |
| 498 | this.setState(`persisting`) |
| 499 | |
| 500 | if (this.mutations.length === 0) { |
| 501 | this.setState(`completed`) |
| 502 | this.isPersisted.resolve(this) |
| 503 | |
| 504 | return this |
| 505 | } |
| 506 | |
| 507 | // Run mutationFn |
| 508 | try { |
| 509 | // At this point we know there's at least one mutation |
| 510 | // We've already verified mutations is non-empty, so this cast is safe |
| 511 | // Use a direct type assertion instead of object spreading to preserve the original type |
| 512 | await this.mutationFn({ |
| 513 | transaction: this as unknown as TransactionWithMutations<T>, |
| 514 | }) |
| 515 | |
| 516 | this.setState(`completed`) |
| 517 | this.touchCollection() |
| 518 | |
| 519 | this.isPersisted.resolve(this) |
| 520 | } catch (error) { |
| 521 | // Preserve the original error for rethrowing |
| 522 | const originalError = |
| 523 | error instanceof Error ? error : new Error(String(error)) |
| 524 | |
| 525 | // Update transaction with error information |
| 526 | this.error = { |
| 527 | message: originalError.message, |
| 528 | error: originalError, |
| 529 | } |
| 530 | |
| 531 | // rollback the transaction |
| 532 | this.rollback() |
| 533 | |
| 534 | // Re-throw the original error to preserve identity and stack |
| 535 | throw originalError |
| 536 | } |
| 537 | |
| 538 | return this |
| 539 | } |
| 540 | |
| 541 | /** |
| 542 | * Compare two transactions by their createdAt time and sequence number in order |