@idb-orm/react-query 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -35
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +20 -19
- package/dist/index.es.js +1 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> ## THIS PACKAGE IS BRAND-NEW AND UNSTABLE. DO NOT USE
|
|
4
4
|
|
|
5
|
-
A React adapter for [Tanstack's Query library](https://tanstack.com/query/latest) for @idb-orm. It essentially offers easy to use shortcuts to manage querying idb-orm data and caching.
|
|
5
|
+
A React adapter for [Tanstack's Query library](https://tanstack.com/query/latest) for @idb-orm. It essentially offers easy to use shortcuts to manage querying idb-orm data and caching. This package is an extension of `@idb-orm/react`.
|
|
6
6
|
|
|
7
7
|
## Example
|
|
8
8
|
|
|
@@ -36,18 +36,30 @@ npm i @idb-orm/react-query
|
|
|
36
36
|
|
|
37
37
|
## Getting Started
|
|
38
38
|
|
|
39
|
-
Define your @idb-orm schema in any file. Then, create the
|
|
39
|
+
Define your @idb-orm schema in any file. Then, call the factory function. This function will create a React Context, a Provider component for the context, and a series of hooks used to access the context's value.
|
|
40
40
|
|
|
41
41
|
```tsx
|
|
42
42
|
// idb-query.ts
|
|
43
43
|
|
|
44
|
-
import {
|
|
45
|
-
|
|
46
|
-
// File that creates the @idb-orm database
|
|
47
|
-
import {
|
|
48
|
-
|
|
49
|
-
const {
|
|
50
|
-
|
|
44
|
+
import { queryClientProviderFactory } from "@idb-orm/react-query";
|
|
45
|
+
|
|
46
|
+
// File that creates the @idb-orm database
|
|
47
|
+
import { db } from "./db";
|
|
48
|
+
|
|
49
|
+
export const {
|
|
50
|
+
// Primitive React Context object
|
|
51
|
+
Context,
|
|
52
|
+
// Hook to acquire the IDB-ORM client object
|
|
53
|
+
useDbClient,
|
|
54
|
+
// Hook to acquire the Tanstack-Query QueryClient object
|
|
55
|
+
useQueryClient,
|
|
56
|
+
// Hook to acquire the auto-generated query functions.
|
|
57
|
+
useQueryInterface,
|
|
58
|
+
// Hook to acquire the contents of the 3 hooks above in one.
|
|
59
|
+
useIDBQuery,
|
|
60
|
+
// Provider that will allow the above hooks to function and populate the context.
|
|
61
|
+
DbClientProvider,
|
|
62
|
+
} = queryClientProviderFactory(db);
|
|
51
63
|
```
|
|
52
64
|
|
|
53
65
|
Then, in your project's root, wrap your application in the provider:
|
|
@@ -55,52 +67,62 @@ Then, in your project's root, wrap your application in the provider:
|
|
|
55
67
|
```tsx
|
|
56
68
|
// App.tsx
|
|
57
69
|
|
|
58
|
-
import {
|
|
70
|
+
import { DbClientProvider } from "./idb-query";
|
|
59
71
|
|
|
60
72
|
function App(){
|
|
61
73
|
return (
|
|
62
|
-
<
|
|
74
|
+
<DbClientProvider version={2} fallback={<>Waiting for client creation...</>}>
|
|
63
75
|
{/* Appliation */}
|
|
64
|
-
<
|
|
76
|
+
<DbClientProvider>
|
|
65
77
|
)
|
|
66
78
|
}
|
|
67
79
|
```
|
|
68
80
|
|
|
81
|
+
The fallback prop is an optional prop you can give to the provider to render while the client is building. Building the `@idb-orm` client is an asynchronous operation, so while that is being done its children are not rendered. This may be changed in a future update.
|
|
82
|
+
|
|
69
83
|
## Usage
|
|
70
84
|
|
|
71
85
|
Anywhere inside a component, you can call one of three hooks for each store:
|
|
72
86
|
|
|
73
87
|
```ts
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
import { useQueryInterface } from "./idb-query";
|
|
89
|
+
|
|
90
|
+
function MyComponent(){
|
|
91
|
+
const stores = useQueryInterface();
|
|
92
|
+
|
|
93
|
+
// Will find all documents that matches the filter/selector
|
|
94
|
+
stores.users.useFind({
|
|
95
|
+
query: {
|
|
96
|
+
/* Selector Object */
|
|
97
|
+
},
|
|
98
|
+
/* Additional options */
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Will find the first document that matches the filter/selector
|
|
102
|
+
stores.users.useFindFirst({
|
|
103
|
+
query: {
|
|
104
|
+
/* Selector Object */
|
|
105
|
+
},
|
|
106
|
+
/* Additional options */
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Will find the first document that matches the filter/selector
|
|
110
|
+
stores.users.useGet({
|
|
111
|
+
key: /* Primary Key */
|
|
112
|
+
/* Additional options */
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return <>My Favorite Component</>
|
|
116
|
+
}
|
|
89
117
|
|
|
90
|
-
// Will find the first document that matches the filter/selector
|
|
91
|
-
stores.users.useGet({
|
|
92
|
-
key: /* Primary Key */
|
|
93
|
-
/* Additional options */
|
|
94
|
-
});
|
|
95
118
|
```
|
|
96
119
|
|
|
97
120
|
These hooks return the same type as the result of the Tanstack [useQuery](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery) hook. Check out their documentation for more information as well as additional options.
|
|
98
121
|
|
|
99
122
|
Some things to note:
|
|
100
123
|
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
- The provider component already has the Tanstack `QueryClientProvider` included!
|
|
124
|
+
- Fields passed into the `query` key of a hook input will be used to determine query invalidation. These query objects are serialized into JSON by Tanstack, so any TS/JS types that are not serializable into JSON (functions, files, undefined) will be omitted from the serialized representation. So if any of these types of values change, the query will **NOT** be automatically invalidated.
|
|
125
|
+
- The `DbClientProvider` component already has the Tanstack `QueryClientProvider` included, you do not need to add another!
|
|
104
126
|
|
|
105
127
|
## Disclaimer
|
|
106
128
|
|
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@tanstack/react-query"),t=require("react");class
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@tanstack/react-query"),t=require("react"),r="Query Client Context not found. Please ensure this component is wrapped in a <DbClientProvider /> component.";class n extends e.QueryClient{constructor(e,t){super(t),this.db=e}createInterface(r){const n={},o=this.db.getStoreNames(),i=this.db.stores;for(const t of o)n[t]={useFind:(r,n=[])=>e.useQuery({...r,queryKey:[t,"find",r.query,...n],queryFn:()=>i[t].find(r.query)}),useFindFirst:(r,n=[])=>e.useQuery({...r,queryKey:[t,"findFirst",r.query,...n],queryFn:()=>i[t].findFirst(r.query)}),useGet:(r,n=[])=>{e.useQuery({...r,queryKey:[t,"get",r.key,...n],queryFn:()=>i[t].get(r.key)})}};return{...n,useClient:()=>{const e=t.useContext(r);if(!e)throw new Error("Query Context Not Found. Make sure you wrap your application in the <Provider/> Component.");return e}}}}exports.IDBQueryClient=n,exports.queryClientProviderFactory=function(o,i){const u=t.createContext(null);return{Context:u,useDbClient:()=>{const e=t.useContext(u);if(!e)throw new Error(r);return e.client},useQueryClient:()=>{const e=t.useContext(u);if(!e)throw new Error(r);return e.queryClient},useQueryInterface:()=>{const e=t.useContext(u);if(!e)throw new Error(r);return e.stores},useIDBQuery:()=>{const e=t.useContext(u);if(!e)throw new Error(r);return e},DbClientProvider:({fallback:r,children:s,version:a})=>{const[c,l]=t.useState(null);return t.useEffect(()=>{o.createClientAsync(a).then(e=>{const t=new n(e,i);function r(e){return{invalidate:()=>t.invalidateQueries({queryKey:e})}}const o=r([]),u=t.db.getStoreNames();for(const n of u)"invalidate"===n&&console.warn("Model name 'invalidate' causes the invalidate() function of useClient() to not work. Please fix by renaming the model."),o[n]={...r([n]),get:r([n,"get"]),find:r([n,"find"]),findFirst:r([n,"findFirst"])};l({client:e,queryClient:t,stores:o})}).catch(e=>{throw new Error(`@idb-orm Query Client Creation Failed: ${e}`)})},[a]),c?t.createElement(e.QueryClientProvider,{client:c.queryClient},t.createElement(u.Provider,{value:c},s)):r}}};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { core, Model } from '@idb-orm/core';
|
|
2
2
|
import { QueryClient, DefinedUseQueryResult, UndefinedInitialDataOptions, QueryClientConfig } from '@tanstack/react-query';
|
|
3
|
-
import { default as React } from 'react';
|
|
4
|
-
|
|
3
|
+
import { default as React, Context, PropsWithChildren, ReactNode } from 'react';
|
|
4
|
+
import { ClientProviderProps } from '@idb-orm/react';
|
|
5
|
+
export interface QueryOptions<O> extends Omit<UndefinedInitialDataOptions<O>, "queryFn" | "queryKey"> {
|
|
5
6
|
}
|
|
6
|
-
interface ModelQueryInterface<Name extends Names, Names extends string, Models extends core.CollectionObject<Names>> {
|
|
7
|
+
export interface ModelQueryInterface<Name extends Names, Names extends string, Models extends core.CollectionObject<Names>> {
|
|
7
8
|
/**
|
|
8
9
|
* Query instance on a particular primary key. This query will acquire **only** the given document and no related documents.
|
|
9
10
|
*/
|
|
@@ -17,7 +18,7 @@ interface ModelQueryInterface<Name extends Names, Names extends string, Models e
|
|
|
17
18
|
query: I;
|
|
18
19
|
}, deps?: React.DependencyList) => DefinedUseQueryResult<O | undefined>;
|
|
19
20
|
}
|
|
20
|
-
interface ModelQueryClient {
|
|
21
|
+
export interface ModelQueryClient {
|
|
21
22
|
invalidate(): Promise<void>;
|
|
22
23
|
}
|
|
23
24
|
type IDBClientInterface<Names extends string, _Models extends core.CollectionObject<Names>> = core.Simplify<{
|
|
@@ -27,21 +28,21 @@ type IDBClientInterface<Names extends string, _Models extends core.CollectionObj
|
|
|
27
28
|
find: ModelQueryClient;
|
|
28
29
|
} & core.Simplify<ModelQueryClient>;
|
|
29
30
|
} & ModelQueryClient>;
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
declare class IDBQueryClient<Names extends string, Models extends core.CollectionObject<Names>> extends QueryClient {
|
|
31
|
+
export interface UseQueryClientReturn<Name extends string, ModelNames extends string, Models extends core.CollectionObject<ModelNames>> {
|
|
32
|
+
client: core.DbClient<Name, ModelNames, Models>;
|
|
33
|
+
queryClient: IDBQueryClient<ModelNames, Models>;
|
|
34
|
+
stores: IDBClientInterface<ModelNames, Models>;
|
|
35
|
+
}
|
|
36
|
+
export interface QueryClientProviderFactoryReturn<Name extends string, ModelNames extends string, Models extends core.CollectionObject<ModelNames>> {
|
|
37
|
+
Context: Context<UseQueryClientReturn<Name, ModelNames, Models> | null>;
|
|
38
|
+
useDbClient: () => core.DbClient<Name, ModelNames, Models>;
|
|
39
|
+
useQueryClient: () => IDBQueryClient<ModelNames, Models>;
|
|
40
|
+
useQueryInterface: () => IDBClientInterface<ModelNames, Models>;
|
|
41
|
+
useIDBQuery: () => UseQueryClientReturn<Name, ModelNames, Models>;
|
|
42
|
+
DbClientProvider: (props: PropsWithChildren<ClientProviderProps>) => ReactNode;
|
|
43
|
+
}
|
|
44
|
+
export declare function queryClientProviderFactory<Name extends string, ModelNames extends string, Models extends core.CollectionObject<ModelNames>>(db: core.CompiledDb<Name, ModelNames, Models>, config?: QueryClientConfig): QueryClientProviderFactoryReturn<Name, ModelNames, Models>;
|
|
45
|
+
export declare class IDBQueryClient<Names extends string, Models extends core.CollectionObject<Names>> extends QueryClient {
|
|
45
46
|
readonly db: core.DbClient<string, Names, Models>;
|
|
46
47
|
constructor(db: core.DbClient<string, Names, Models>, config?: QueryClientConfig);
|
|
47
48
|
createInterface(context: React.Context<IDBClientInterface<Names, Models>>): IDBQueryInterface<Names, Models>;
|
package/dist/index.es.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import{QueryClientProvider as e,QueryClient as
|
|
2
|
-
return n.createElement(e,{client:t},/* @__PURE__ */n.createElement(s.Provider,{value:o},r))},stores:o.createInterface(s)}}class i extends t{constructor(e,t){super(t),this.db=e}createInterface(e){const t={},o=this.db.getStoreNames(),i=this.db.stores;for(const n of o)t[n]={useFind:(e,t=[])=>r({...e,queryKey:[n,"find",e.query,...t],queryFn:()=>i[n].find(e.query)}),useFindFirst:(e,t=[])=>r({...e,queryKey:[n,"findFirst",e.query,...t],queryFn:()=>i[n].findFirst(e.query)}),useGet:(e,t=[])=>{r({...e,queryKey:[n,"get",e.key,...t],queryFn:()=>i[n].get(e.key)})}};return{...t,useClient:()=>{const t=n.useContext(e);if(!t)throw new Error("Query Context Not Found. Make sure you wrap your application in the <Provider/> Component.");return t}}}}export{o as createIDBQueryClient};
|
|
1
|
+
import{QueryClientProvider as e,QueryClient as r,useQuery as t}from"@tanstack/react-query";import n,{createContext as o,useState as i,useEffect as s,useContext as u}from"react";const a="Query Client Context not found. Please ensure this component is wrapped in a <DbClientProvider /> component.";function c(r,t){const c=o(null);return{Context:c,useDbClient:()=>{const e=u(c);if(!e)throw new Error(a);return e.client},useQueryClient:()=>{const e=u(c);if(!e)throw new Error(a);return e.queryClient},useQueryInterface:()=>{const e=u(c);if(!e)throw new Error(a);return e.stores},useIDBQuery:()=>{const e=u(c);if(!e)throw new Error(a);return e},DbClientProvider:({fallback:o,children:u,version:a})=>{const[d,y]=i(null);return s(()=>{r.createClientAsync(a).then(e=>{const r=new l(e,t);function n(e){return{invalidate:()=>r.invalidateQueries({queryKey:e})}}const o=n([]),i=r.db.getStoreNames();for(const t of i)"invalidate"===t&&console.warn("Model name 'invalidate' causes the invalidate() function of useClient() to not work. Please fix by renaming the model."),o[t]={...n([t]),get:n([t,"get"]),find:n([t,"find"]),findFirst:n([t,"findFirst"])};y({client:e,queryClient:r,stores:o})}).catch(e=>{throw new Error(`@idb-orm Query Client Creation Failed: ${e}`)})},[a]),d?/* @__PURE__ */n.createElement(e,{client:d.queryClient},/* @__PURE__ */n.createElement(c.Provider,{value:d},u)):o}}}class l extends r{constructor(e,r){super(r),this.db=e}createInterface(e){const r={},o=this.db.getStoreNames(),i=this.db.stores;for(const n of o)r[n]={useFind:(e,r=[])=>t({...e,queryKey:[n,"find",e.query,...r],queryFn:()=>i[n].find(e.query)}),useFindFirst:(e,r=[])=>t({...e,queryKey:[n,"findFirst",e.query,...r],queryFn:()=>i[n].findFirst(e.query)}),useGet:(e,r=[])=>{t({...e,queryKey:[n,"get",e.key,...r],queryFn:()=>i[n].get(e.key)})}};return{...r,useClient:()=>{const r=n.useContext(e);if(!r)throw new Error("Query Context Not Found. Make sure you wrap your application in the <Provider/> Component.");return r}}}}export{l as IDBQueryClient,c as queryClientProviderFactory};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idb-orm/react-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "An adapter for the Tanstack React-Query library for @idb-orm",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"@idb-orm/core": "^1.0.7",
|
|
27
27
|
"@tanstack/react-query": "^5.90.11",
|
|
28
|
+
"@idb-orm/react": "^0.0.1",
|
|
28
29
|
"react": "^19.2.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|