Skip to content

Commit 1626573

Browse files
committed
fix: local collection manual transactions
Signed-off-by: Marc MacLeod <marbemac+gh@gmail.com>
1 parent ac42951 commit 1626573

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

.changeset/metal-results-float.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@tanstack/db": patch
3+
---
4+
5+
Fixed local collection manual transactions

packages/db/src/local-only.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ export function localOnlyCollectionOptions<
179179
): LocalOnlyCollectionOptionsResult<T, TKey, TSchema> & {
180180
schema?: StandardSchemaV1
181181
} {
182-
const { initialData, onInsert, onUpdate, onDelete, ...restConfig } = config
182+
const { initialData, onInsert, onUpdate, onDelete, id, ...restConfig } =
183+
config
184+
185+
const collectionId = id ?? crypto.randomUUID()
183186

184187
// Create the sync configuration with transaction confirmation capability
185188
const syncResult = createLocalOnlySync<T, TKey>(initialData)
@@ -245,11 +248,9 @@ export function localOnlyCollectionOptions<
245248
const acceptMutations = (transaction: {
246249
mutations: Array<PendingMutation<Record<string, unknown>>>
247250
}) => {
248-
// Filter mutations that belong to this collection
251+
// Filter mutations that belong to this collection by collection ID
249252
const collectionMutations = transaction.mutations.filter(
250-
(m) =>
251-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
252-
m.collection === syncResult.collection
253+
(m) => m.collection.id === collectionId
253254
)
254255

255256
if (collectionMutations.length === 0) {
@@ -264,6 +265,7 @@ export function localOnlyCollectionOptions<
264265

265266
return {
266267
...restConfig,
268+
id: collectionId,
267269
sync: syncResult.sync,
268270
onInsert: wrappedOnInsert,
269271
onUpdate: wrappedOnUpdate,

packages/db/tests/local-only.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ describe(`LocalOnly Collection`, () => {
481481
})
482482

483483
describe(`Manual transactions with acceptMutations`, () => {
484-
it(`should accept and persist mutations from manual transactions`, () => {
484+
it(`should accept and persist mutations from manual transactions`, async () => {
485485
const tx = createTransaction({
486486
mutationFn: async ({ transaction }: any) => {
487487
// Simulate API call success
@@ -510,6 +510,39 @@ describe(`LocalOnly Collection`, () => {
510510
id: 101,
511511
name: `Manual Tx Insert 2`,
512512
})
513+
514+
// Verify that the item is still present after async operations complete
515+
await new Promise((resolve) => setTimeout(resolve, 1))
516+
expect(collection.get(100)).toEqual({ id: 100, name: `Manual Tx Insert` })
517+
})
518+
519+
it(`should work without explicit collection ID`, async () => {
520+
// Create a collection without an explicit ID
521+
const noIdCollection = createCollection<
522+
TestItem,
523+
number,
524+
LocalOnlyCollectionUtils
525+
>(
526+
localOnlyCollectionOptions({
527+
getKey: (item) => item.id,
528+
})
529+
)
530+
531+
const tx = createTransaction({
532+
mutationFn: async ({ transaction }: any) => {
533+
noIdCollection.utils.acceptMutations(transaction)
534+
},
535+
autoCommit: false,
536+
})
537+
538+
tx.mutate(() => {
539+
noIdCollection.insert({ id: 999, name: `No ID Test` })
540+
})
541+
542+
await tx.commit()
543+
544+
// Data should persist even without explicit ID
545+
expect(noIdCollection.get(999)).toEqual({ id: 999, name: `No ID Test` })
513546
})
514547

515548
it(`should only accept mutations for the specific collection`, () => {

0 commit comments

Comments
 (0)