@tanstack/offline-transactions
Version:
Offline-first transaction capabilities for TanStack DB
66 lines (57 loc) • 1.84 kB
text/typescript
import { OnMutateMustBeSynchronousError } from '@tanstack/db'
import { OfflineTransaction } from './OfflineTransaction'
import type { Transaction } from '@tanstack/db'
import type {
CreateOfflineActionOptions,
OfflineMutationFn,
OfflineTransaction as OfflineTransactionType,
} from '../types'
function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
return (
!!value &&
(typeof value === `object` || typeof value === `function`) &&
typeof (value as { then?: unknown }).then === `function`
)
}
export function createOfflineAction<T>(
options: CreateOfflineActionOptions<T>,
mutationFn: OfflineMutationFn,
persistTransaction: (tx: OfflineTransactionType) => Promise<void>,
executor: any,
): (variables: T) => Transaction {
const { mutationFnName, onMutate } = options
console.log(`createOfflineAction 2`, options)
return (variables: T): Transaction => {
const offlineTransaction = new OfflineTransaction(
{
mutationFnName,
autoCommit: false,
},
mutationFn,
persistTransaction,
executor,
)
const transaction = offlineTransaction.mutate(() => {
console.log(`mutate`)
const maybePromise = onMutate(variables) as unknown
if (isPromiseLike(maybePromise)) {
throw new OnMutateMustBeSynchronousError()
}
})
// Immediately commit
const commitPromise = (async () => {
try {
await transaction.commit()
console.log(`offlineAction committed - success`)
} catch {
console.log(`offlineAction commit failed - error`)
}
})()
// Don't await - this is fire-and-forget for optimistic actions
// But catch to prevent unhandled rejection
commitPromise.catch(() => {
// Already handled in try/catch above
})
return transaction
}
}