Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/plugins/tanstack-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
},
"devDependencies": {
"@tanstack/react-query": "^4.29.7",
"@tanstack/react-query-v5": "npm:@tanstack/react-query@^5.0.0",
"@tanstack/react-query-v5": "npm:@tanstack/react-query@5.56.x",
"@tanstack/svelte-query": "^4.29.7",
"@tanstack/svelte-query-v5": "npm:@tanstack/svelte-query@^5.0.0",
"@tanstack/vue-query": "^4.37.0",
Expand Down
21 changes: 19 additions & 2 deletions packages/plugins/tanstack-query/src/runtime/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,20 @@ async function optimisticUpdate(
state: { data, error },
} = cacheItem;

if (!isZenStackQueryKey(queryKey)) {
// skip non-zenstack queries
continue;
}

if (error) {
if (logging) {
console.warn(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to error:`, error);
}
continue;
}

const [_, queryModel, queryOperation, queryArgs, { optimisticUpdate }] = queryKey as QueryKey;
if (!optimisticUpdate) {
const [_, queryModel, queryOperation, queryArgs, queryOptions] = queryKey;
if (!queryOptions?.optimisticUpdate) {
if (logging) {
console.log(`Skipping optimistic update for ${JSON.stringify(queryKey)} due to opt-out`);
}
Expand Down Expand Up @@ -450,3 +455,15 @@ async function optimisticUpdate(
}
}
}

function isZenStackQueryKey(queryKey: readonly unknown[]): queryKey is QueryKey {
if (queryKey.length < 5) {
return false;
}

if (queryKey[0] !== QUERY_KEY_PREFIX) {
return false;
}

return true;
}
2 changes: 1 addition & 1 deletion packages/plugins/tanstack-query/tests/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ ${sharedModel}
{
provider: 'postgresql',
pushDb: false,
extraDependencies: ['[email protected]', '@types/[email protected]', '@tanstack/react-query@^5.0.0'],
extraDependencies: ['[email protected]', '@types/[email protected]', '@tanstack/react-query@5.56.x'],
copyDependencies: [path.resolve(__dirname, '../dist')],
compile: true,
extraSourceFiles: [
Expand Down
67 changes: 66 additions & 1 deletion packages/plugins/tanstack-query/tests/react-hooks-v5.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { QueryClient, QueryClientProvider } from '@tanstack/react-query-v5';
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query-v5';
import { act, renderHook, waitFor } from '@testing-library/react';
import nock from 'nock';
import React from 'react';
Expand Down Expand Up @@ -863,4 +863,69 @@ describe('Tanstack Query React Hooks V5 Test', () => {
expect(cacheData[0].name).toBe('foohooray');
});
});

it('optimistic update mixed with non-zenstack queries', async () => {
const { queryClient, wrapper } = createWrapper();

// non-zenstack query
const { result: myQueryResult } = renderHook(
() => useQuery({ queryKey: ['myQuery'], queryFn: () => ({ data: 'myData' }) }),
{
wrapper,
}
);
await waitFor(() => {
expect(myQueryResult.current.data).toEqual({ data: 'myData' });
});

const data: any[] = [];

nock(makeUrl('User', 'findMany'))
.get(/.*/)
.reply(200, () => {
console.log('Querying data:', JSON.stringify(data));
return { data };
})
.persist();

const { result } = renderHook(
() => useModelQuery('User', makeUrl('User', 'findMany'), undefined, { optimisticUpdate: true }),
{
wrapper,
}
);
await waitFor(() => {
expect(result.current.data).toHaveLength(0);
});

nock(makeUrl('User', 'create'))
.post(/.*/)
.reply(200, () => {
console.log('Not mutating data');
return { data: null };
});

const { result: mutationResult } = renderHook(
() =>
useModelMutation('User', 'POST', makeUrl('User', 'create'), modelMeta, {
optimisticUpdate: true,
invalidateQueries: false,
}),
{
wrapper,
}
);

act(() => mutationResult.current.mutate({ data: { name: 'foo' } }));

await waitFor(() => {
const cacheData: any = queryClient.getQueryData(
getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true })
);
expect(cacheData).toHaveLength(1);
expect(cacheData[0].$optimistic).toBe(true);
expect(cacheData[0].id).toBeTruthy();
expect(cacheData[0].name).toBe('foo');
});
});
});
41 changes: 23 additions & 18 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/integration/tests/cli/plugins.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('CLI Plugins Tests', () => {
'[email protected]',
'react',
'swr',
'@tanstack/react-query@^5.0.0',
'@tanstack/react-query@5.56.x',
'@trpc/server',
'@prisma/[email protected]',
`${path.join(__dirname, '../../../../.build/zenstackhq-language-' + ver + '.tgz')}`,
Expand Down
Loading