Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into powersync-sqlite-core…
Browse files Browse the repository at this point in the history
…-030
  • Loading branch information
rkistner committed Oct 10, 2024
2 parents a51b1d9 + 8047546 commit 12ec71f
Show file tree
Hide file tree
Showing 19 changed files with 5,474 additions and 4,109 deletions.
5 changes: 0 additions & 5 deletions .changeset/smart-jobs-change.md

This file was deleted.

1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ docs/react-native-sdk/
docs/react-sdk/
docs/vue-sdk/
docs/web-sdk/
docs/tanstack-react-query-sdk

.env
10 changes: 9 additions & 1 deletion docs/utils/packageMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ enum Packages {
ReactSdk = 'react-sdk',
VueSdk = 'vue-sdk',
AttachmentsSdk = 'attachments-sdk',
WebSdk = 'web-sdk'
WebSdk = 'web-sdk',
TanstackReactQuerySdk = 'tanstack-react-query-sdk'
}

interface Package {
Expand Down Expand Up @@ -55,5 +56,12 @@ export const packageMap: PackageMap = {
entryPoints: ['../packages/web/src/index.ts'],
tsconfig: '../packages/web/tsconfig.json',
id: Packages.WebSdk
},
[Packages.TanstackReactQuerySdk]: {
name: 'Tanstack React Query SDK',
dirName: Packages.TanstackReactQuerySdk,
entryPoints: ['../packages/tanstack-react-query/src/index.ts'],
tsconfig: '../packages/tanstack-react-query/tsconfig.json',
id: Packages.TanstackReactQuerySdk
}
};
7 changes: 7 additions & 0 deletions packages/react-native/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @powersync/react-native

## 1.12.4

### Patch Changes

- Updated dependencies [f8ac369]
- @powersync/react@1.4.5

## 1.12.3

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powersync/react-native",
"version": "1.12.3",
"version": "1.12.4",
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
Expand Down
6 changes: 6 additions & 0 deletions packages/react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @powersync/react

## 1.4.5

### Patch Changes

- f8ac369: Ensuring that `useQuery`'s `isFetching` becomes true immediately after the query changes.

## 1.4.4

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powersync/react",
"version": "1.4.4",
"version": "1.4.5",
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
Expand Down
19 changes: 16 additions & 3 deletions packages/react/src/hooks/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,33 @@ export const useQuery = <T = any>(
const memoizedOptions = React.useMemo(() => options, [JSON.stringify(options)]);
const abortController = React.useRef(new AbortController());

const previousQueryRef = React.useRef({ sqlStatement, memoizedParams });

// Indicates that the query will be re-fetched due to a change in the query.
// Used when `isFetching` hasn't been set to true yet due to React execution.
const shouldFetch = React.useMemo(
() =>
previousQueryRef.current.sqlStatement !== sqlStatement ||
JSON.stringify(previousQueryRef.current.memoizedParams) != JSON.stringify(memoizedParams),
[powerSync, sqlStatement, memoizedParams, isFetching]
);

const handleResult = (result: T[]) => {
setData(result);
setIsLoading(false);
setIsFetching(false);
setData(result);
setError(undefined);
previousQueryRef.current = { sqlStatement, memoizedParams };
};

const handleError = (e: Error) => {
setData([]);
setIsLoading(false);
setIsFetching(false);
setData([]);
const wrappedError = new Error('PowerSync failed to fetch data: ' + e.message);
wrappedError.cause = e;
setError(wrappedError);
previousQueryRef.current = { sqlStatement, memoizedParams };
};

const fetchData = async () => {
Expand Down Expand Up @@ -139,5 +152,5 @@ export const useQuery = <T = any>(
};
}, [powerSync, sqlStatement, memoizedParams, memoizedOptions, tables]);

return { isLoading, isFetching, data, error, refresh: fetchData };
return { isLoading, isFetching: isFetching || shouldFetch, data, error, refresh: fetchData };
};
48 changes: 24 additions & 24 deletions packages/react/tests/useQuery.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as commonSdk from '@powersync/common';
import { renderHook, waitFor } from '@testing-library/react';
import { cleanup, renderHook, waitFor } from '@testing-library/react';
import React from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { PowerSyncContext } from '../src/hooks/PowerSyncContext';
import { useQuery } from '../src/hooks/useQuery';

Expand All @@ -12,16 +12,17 @@ const mockPowerSync = {
})),
resolveTables: vi.fn(() => ['table1', 'table2']),
onChangeWithCallback: vi.fn(),
getAll: vi.fn(() => ['list1', 'list2'])
getAll: vi.fn(() => Promise.resolve(['list1', 'list2']))
};

vi.mock('./PowerSyncContext', () => ({
useContext: vi.fn(() => mockPowerSync)
}));

describe('useQuery', () => {
afterEach(() => {
vi.resetAllMocks();
beforeEach(() => {
vi.clearAllMocks();
cleanup(); // Cleanup the DOM after each test
});

it('should error when PowerSync is not set', async () => {
Expand All @@ -48,14 +49,14 @@ describe('useQuery', () => {
);

const { result } = renderHook(() => useQuery('SELECT * from lists', [], { runQueryOnce: true }), { wrapper });
const currentResult = result.current;
expect(currentResult.isLoading).toEqual(true);
expect(result.current.isLoading).toEqual(true);

waitFor(
await waitFor(
async () => {
expect(currentResult.isLoading).toEqual(false);
const currentResult = result.current;
expect(currentResult.data).toEqual(['list1', 'list2']);
expect(currentResult.isLoading).toEqual(false);
expect(currentResult.isFetching).toEqual(false);
expect(mockPowerSync.onChangeWithCallback).not.toHaveBeenCalled();
expect(mockPowerSync.getAll).toHaveBeenCalledTimes(1);
},
Expand All @@ -69,13 +70,14 @@ describe('useQuery', () => {
);

const { result } = renderHook(() => useQuery('SELECT * from lists', [], { runQueryOnce: true }), { wrapper });
const currentResult = result.current;
expect(currentResult.isLoading).toEqual(true);

expect(result.current.isLoading).toEqual(true);

let refresh;

waitFor(
await waitFor(
async () => {
const currentResult = result.current;
refresh = currentResult.refresh;
expect(currentResult.isLoading).toEqual(false);
expect(mockPowerSync.getAll).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -105,11 +107,10 @@ describe('useQuery', () => {
);

const { result } = renderHook(() => useQuery('SELECT * from lists', [], { runQueryOnce: true }), { wrapper });
const currentResult = result.current;

waitFor(
await waitFor(
async () => {
expect(currentResult.error).toEqual(Error('PowerSync failed to fetch data: some error'));
expect(result.current.error).toEqual(Error('PowerSync failed to fetch data: some error'));
},
{ timeout: 100 }
);
Expand All @@ -133,11 +134,10 @@ describe('useQuery', () => {
);

const { result } = renderHook(() => useQuery('SELECT * from lists', []), { wrapper });
const currentResult = result.current;

waitFor(
await waitFor(
async () => {
expect(currentResult.error).toEqual(Error('PowerSync failed to fetch data: some error'));
expect(result.current.error).toEqual(Error('PowerSync failed to fetch data: some error'));
},
{ timeout: 100 }
);
Expand Down Expand Up @@ -173,13 +173,13 @@ describe('useQuery', () => {
});
});

// The test returns unhandled errors when run with all the others.
// TODO: Fix the test so that there are no unhandled errors (this may be a vitest or @testing-library/react issue)
it.skip('should show an error if parsing the query results in an error', async () => {
it('should show an error if parsing the query results in an error', async () => {
const wrapper = ({ children }) => (
<PowerSyncContext.Provider value={mockPowerSync as any}>{children}</PowerSyncContext.Provider>
);
vi.spyOn(commonSdk, 'parseQuery').mockReturnValue(Error('error') as any);
vi.spyOn(commonSdk, 'parseQuery').mockImplementation(() => {
throw new Error('error');
});

const { result } = renderHook(
() =>
Expand All @@ -189,10 +189,10 @@ describe('useQuery', () => {
}),
{ wrapper }
);
const currentResult = result.current;

waitFor(
await waitFor(
async () => {
const currentResult = result.current;
expect(currentResult.isLoading).toEqual(false);
expect(currentResult.isFetching).toEqual(false);
expect(currentResult.data).toEqual([]);
Expand Down
7 changes: 7 additions & 0 deletions packages/tanstack-react-query/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# @powersync/tanstack-react-query

## 0.0.1

### Patch Changes

- c4e183a: Initial Alpha version.
Loading

0 comments on commit 12ec71f

Please sign in to comment.