@questpie/tanstack-query 1.1.1 → 3.0.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 +163 -222
- package/dist/index.d.mts +82 -42
- package/dist/index.mjs +317 -96
- package/package.json +25 -14
package/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# @questpie/tanstack-query
|
|
2
2
|
|
|
3
|
-
Type-safe TanStack
|
|
3
|
+
Type-safe TanStack Query option builders for QUESTPIE — collections, globals, app routes, and realtime streaming.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Query Options Factory**
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
7
|
+
- **Query Options Factory** — Pre-built `queryOptions()` and `mutationOptions()` for all CRUD operations
|
|
8
|
+
- **Route Query Options** — Typed `query()` / `mutation()` builders for app routes with nested path support
|
|
9
|
+
- **Realtime Streaming** — `streamedQuery`-based options for SSE live updates on collections and globals
|
|
10
|
+
- **Batch Operations** — `updateMany` and `deleteMany` mutation builders
|
|
11
|
+
- **SSR Ready** — Prefetch data on the server, hydrate on the client
|
|
12
|
+
- **Full Type Inference** — Types flow from your app schema through to query results
|
|
10
13
|
|
|
11
14
|
## Installation
|
|
12
15
|
|
|
@@ -18,285 +21,223 @@ bun add @questpie/tanstack-query questpie @tanstack/react-query
|
|
|
18
21
|
|
|
19
22
|
### 1. Create Query Options
|
|
20
23
|
|
|
21
|
-
```
|
|
22
|
-
// src/lib/queries.ts
|
|
24
|
+
```ts
|
|
23
25
|
import { createClient } from "questpie/client";
|
|
24
26
|
import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
|
|
25
|
-
import type {
|
|
27
|
+
import type { AppConfig } from "#questpie";
|
|
26
28
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const appClient = createClient<AppConfig>({
|
|
30
|
+
baseURL: "http://localhost:3000",
|
|
31
|
+
basePath: "/api",
|
|
30
32
|
});
|
|
31
33
|
|
|
32
|
-
export const
|
|
33
|
-
keyPrefix: ["cms"], // Optional: prefix for all query keys
|
|
34
|
-
});
|
|
34
|
+
export const appQueries = createQuestpieQueryOptions(appClient);
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
### 2. Use in Components
|
|
38
38
|
|
|
39
|
-
```
|
|
40
|
-
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
|
|
41
|
-
import {
|
|
39
|
+
```tsx
|
|
40
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
41
|
+
import { appQueries } from "@/lib/queries";
|
|
42
42
|
|
|
43
43
|
function PostsList() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
)
|
|
44
|
+
const { data } = useQuery(appQueries.collections.posts.find({ limit: 10 }));
|
|
45
|
+
|
|
46
|
+
const queryClient = useQueryClient();
|
|
47
|
+
const createPost = useMutation({
|
|
48
|
+
...appQueries.collections.posts.create(),
|
|
49
|
+
onSuccess: () => {
|
|
50
|
+
queryClient.invalidateQueries({
|
|
51
|
+
queryKey: appQueries.collections.posts.key(),
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div>
|
|
58
|
+
{data?.docs.map((post) => (
|
|
59
|
+
<div key={post.id}>{post.title}</div>
|
|
60
|
+
))}
|
|
61
|
+
<button onClick={() => createPost.mutate({ title: "New Post" })}>
|
|
62
|
+
Create
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
67
66
|
}
|
|
68
67
|
```
|
|
69
68
|
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
### Collections
|
|
69
|
+
## Collections
|
|
73
70
|
|
|
74
|
-
```
|
|
75
|
-
// Find many
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
```ts
|
|
72
|
+
// Find many (paginated)
|
|
73
|
+
appQueries.collections.posts.find({
|
|
74
|
+
where: { published: { eq: true } },
|
|
75
|
+
orderBy: { createdAt: "desc" },
|
|
76
|
+
limit: 10,
|
|
77
|
+
offset: 0,
|
|
78
|
+
with: { author: true },
|
|
82
79
|
});
|
|
83
80
|
|
|
84
81
|
// Find one
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
appQueries.collections.posts.findOne({
|
|
83
|
+
where: { id: "post-id" },
|
|
84
|
+
with: { author: true },
|
|
88
85
|
});
|
|
89
86
|
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
// Count
|
|
88
|
+
appQueries.collections.posts.count({
|
|
89
|
+
where: { published: { eq: true } },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Create (mutation)
|
|
93
|
+
appQueries.collections.posts.create();
|
|
94
|
+
|
|
95
|
+
// Update (mutation)
|
|
96
|
+
appQueries.collections.posts.update();
|
|
93
97
|
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
// Usage: mutation.mutate({ id: "...", data: { title: "..." } })
|
|
98
|
+
// Delete (mutation)
|
|
99
|
+
appQueries.collections.posts.delete();
|
|
97
100
|
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
// Usage: mutation.mutate({ id: "..." })
|
|
101
|
+
// Update many (mutation)
|
|
102
|
+
appQueries.collections.posts.updateMany();
|
|
101
103
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
// Delete many (mutation)
|
|
105
|
+
appQueries.collections.posts.deleteMany();
|
|
106
|
+
|
|
107
|
+
// Restore soft-deleted (mutation)
|
|
108
|
+
appQueries.collections.posts.restore();
|
|
109
|
+
|
|
110
|
+
// Query key for invalidation
|
|
111
|
+
appQueries.collections.posts.key();
|
|
105
112
|
```
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
## Globals
|
|
108
115
|
|
|
109
|
-
```
|
|
110
|
-
// Get
|
|
111
|
-
|
|
116
|
+
```ts
|
|
117
|
+
// Get global value
|
|
118
|
+
appQueries.globals.siteSettings.get();
|
|
112
119
|
|
|
113
|
-
// Update
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
// Update global (mutation)
|
|
121
|
+
appQueries.globals.siteSettings.update();
|
|
122
|
+
|
|
123
|
+
// Query key
|
|
124
|
+
appQueries.globals.siteSettings.key();
|
|
116
125
|
```
|
|
117
126
|
|
|
118
|
-
|
|
127
|
+
## Routes
|
|
128
|
+
|
|
129
|
+
Full type-safe query/mutation options for app routes:
|
|
119
130
|
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
```ts
|
|
132
|
+
// Query options from route
|
|
133
|
+
const { data } = useQuery(
|
|
134
|
+
appQueries.routes.dashboard.getStats.query({ period: "week" }),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Mutation options from route
|
|
138
|
+
const publish = useMutation(appQueries.routes.posts.publish.mutation());
|
|
139
|
+
publish.mutate({ id: "post_123" });
|
|
140
|
+
|
|
141
|
+
// Query key for invalidation/prefetch
|
|
142
|
+
queryClient.invalidateQueries({
|
|
143
|
+
queryKey: appQueries.routes.dashboard.getStats.key({ period: "week" }),
|
|
124
144
|
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Realtime Streaming
|
|
148
|
+
|
|
149
|
+
Collection queries support SSE-based live updates via `streamedQuery`:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
// Enable realtime on a query
|
|
153
|
+
const { data } = useQuery(
|
|
154
|
+
appQueries.collections.posts.find({ limit: 10 }, { realtime: true }),
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Topic helpers for manual subscription:
|
|
125
159
|
|
|
126
|
-
|
|
160
|
+
```ts
|
|
161
|
+
import {
|
|
162
|
+
buildCollectionTopic,
|
|
163
|
+
buildGlobalTopic,
|
|
164
|
+
} from "@questpie/tanstack-query";
|
|
165
|
+
|
|
166
|
+
const postsTopic = buildCollectionTopic("posts");
|
|
167
|
+
const settingsTopic = buildGlobalTopic("siteSettings");
|
|
127
168
|
```
|
|
128
169
|
|
|
129
170
|
## SSR Prefetching
|
|
130
171
|
|
|
131
172
|
### TanStack Start
|
|
132
173
|
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
import {
|
|
136
|
-
import {
|
|
137
|
-
import { q } from "@/lib/queries"
|
|
174
|
+
```tsx
|
|
175
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
176
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
177
|
+
import { appQueries } from "@/lib/queries";
|
|
138
178
|
|
|
139
179
|
export const Route = createFileRoute("/posts")({
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
})
|
|
180
|
+
loader: async ({ context }) => {
|
|
181
|
+
await context.queryClient.ensureQueryData(
|
|
182
|
+
appQueries.collections.posts.find({ limit: 10 }),
|
|
183
|
+
);
|
|
184
|
+
},
|
|
185
|
+
component: PostsPage,
|
|
186
|
+
});
|
|
147
187
|
|
|
148
188
|
function PostsPage() {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
)
|
|
189
|
+
const { data } = useSuspenseQuery(
|
|
190
|
+
appQueries.collections.posts.find({ limit: 10 }),
|
|
191
|
+
);
|
|
192
|
+
return (
|
|
193
|
+
<ul>
|
|
194
|
+
{data.docs.map((post) => (
|
|
195
|
+
<li key={post.id}>{post.title}</li>
|
|
196
|
+
))}
|
|
197
|
+
</ul>
|
|
198
|
+
);
|
|
160
199
|
}
|
|
161
200
|
```
|
|
162
201
|
|
|
163
202
|
### Next.js
|
|
164
203
|
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
import {
|
|
168
|
-
import {
|
|
169
|
-
import { q } from "@/lib/queries"
|
|
170
|
-
import { PostsList } from "./posts-list"
|
|
204
|
+
```tsx
|
|
205
|
+
import { HydrationBoundary, dehydrate } from "@tanstack/react-query";
|
|
206
|
+
import { getQueryClient } from "@/lib/query-client";
|
|
207
|
+
import { appQueries } from "@/lib/queries";
|
|
171
208
|
|
|
172
209
|
export default async function PostsPage() {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
</HydrationBoundary>
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## Optimistic Updates
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
const queryClient = useQueryClient();
|
|
191
|
-
|
|
192
|
-
const updatePost = useMutation({
|
|
193
|
-
...q.collections.posts.update(),
|
|
194
|
-
onMutate: async ({ id, data }) => {
|
|
195
|
-
await queryClient.cancelQueries({
|
|
196
|
-
queryKey: ["cms", "collections", "posts"],
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
const previousPosts = queryClient.getQueryData([
|
|
200
|
-
"cms",
|
|
201
|
-
"collections",
|
|
202
|
-
"posts",
|
|
203
|
-
]);
|
|
204
|
-
|
|
205
|
-
queryClient.setQueryData(["cms", "collections", "posts"], (old) => ({
|
|
206
|
-
...old,
|
|
207
|
-
docs: old.docs.map((post) =>
|
|
208
|
-
post.id === id ? { ...post, ...data } : post,
|
|
209
|
-
),
|
|
210
|
-
}));
|
|
211
|
-
|
|
212
|
-
return { previousPosts };
|
|
213
|
-
},
|
|
214
|
-
onError: (err, variables, context) => {
|
|
215
|
-
queryClient.setQueryData(
|
|
216
|
-
["cms", "collections", "posts"],
|
|
217
|
-
context?.previousPosts,
|
|
218
|
-
);
|
|
219
|
-
},
|
|
220
|
-
onSettled: () => {
|
|
221
|
-
queryClient.invalidateQueries({
|
|
222
|
-
queryKey: ["cms", "collections", "posts"],
|
|
223
|
-
});
|
|
224
|
-
},
|
|
225
|
-
});
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
## Infinite Queries
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
import { useInfiniteQuery } from "@tanstack/react-query"
|
|
232
|
-
import { cmsClient } from "@/lib/cms-client"
|
|
233
|
-
|
|
234
|
-
function InfinitePosts() {
|
|
235
|
-
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
|
|
236
|
-
queryKey: ["cms", "collections", "posts", "infinite"],
|
|
237
|
-
queryFn: ({ pageParam = 0 }) =>
|
|
238
|
-
cmsClient.collections.posts.find({
|
|
239
|
-
limit: 10,
|
|
240
|
-
offset: pageParam,
|
|
241
|
-
}),
|
|
242
|
-
getNextPageParam: (lastPage, allPages) => {
|
|
243
|
-
const totalFetched = allPages.flatMap((p) => p.docs).length
|
|
244
|
-
return lastPage.docs.length === 10 ? totalFetched : undefined
|
|
245
|
-
},
|
|
246
|
-
initialPageParam: 0,
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
return (
|
|
250
|
-
<div>
|
|
251
|
-
{data?.pages.flatMap((page) =>
|
|
252
|
-
page.docs.map((post) => <div key={post.id}>{post.title}</div>)
|
|
253
|
-
)}
|
|
254
|
-
{hasNextPage && (
|
|
255
|
-
<button onClick={() => fetchNextPage()}>Load More</button>
|
|
256
|
-
)}
|
|
257
|
-
</div>
|
|
258
|
-
)
|
|
210
|
+
const queryClient = getQueryClient();
|
|
211
|
+
await queryClient.prefetchQuery(
|
|
212
|
+
appQueries.collections.posts.find({ limit: 10 }),
|
|
213
|
+
);
|
|
214
|
+
return (
|
|
215
|
+
<HydrationBoundary state={dehydrate(queryClient)}>
|
|
216
|
+
<PostsList />
|
|
217
|
+
</HydrationBoundary>
|
|
218
|
+
);
|
|
259
219
|
}
|
|
260
220
|
```
|
|
261
221
|
|
|
262
222
|
## Query Key Structure
|
|
263
223
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
224
|
+
```ts
|
|
267
225
|
// Collections
|
|
268
|
-
[
|
|
269
|
-
[
|
|
226
|
+
["collections", collectionName, "find", options]
|
|
227
|
+
["collections", collectionName, "findOne", options]
|
|
228
|
+
["collections", collectionName, "count", options]
|
|
270
229
|
|
|
271
230
|
// Globals
|
|
272
|
-
[
|
|
273
|
-
|
|
274
|
-
// Custom
|
|
275
|
-
[...keyPrefix, ...customKey]
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
## TypeScript
|
|
279
|
-
|
|
280
|
-
Full type inference from your CMS schema:
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
import type { CollectionSelect } from "questpie";
|
|
284
|
-
import type { AppCMS } from "@/cms";
|
|
285
|
-
|
|
286
|
-
// Collection item type
|
|
287
|
-
type Post = CollectionSelect<AppCMS["config"]["collections"]["posts"]>;
|
|
231
|
+
["globals", globalName, "get"]
|
|
288
232
|
|
|
289
|
-
//
|
|
290
|
-
|
|
291
|
-
|
|
233
|
+
// Routes
|
|
234
|
+
["routes", ...segments, "query", input]
|
|
235
|
+
["routes", ...segments, "mutation"]
|
|
292
236
|
```
|
|
293
237
|
|
|
294
|
-
##
|
|
238
|
+
## Documentation
|
|
295
239
|
|
|
296
|
-
|
|
297
|
-
- [`@questpie/hono`](../hono) - Hono adapter
|
|
298
|
-
- [`@questpie/elysia`](../elysia) - Elysia adapter
|
|
299
|
-
- [`@questpie/next`](../next) - Next.js adapter
|
|
240
|
+
Full documentation: [https://questpie.com/docs/client/tanstack-query](https://questpie.com/docs/client/tanstack-query)
|
|
300
241
|
|
|
301
242
|
## License
|
|
302
243
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DefaultError, QueryKey, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
|
|
2
|
-
import {
|
|
3
|
-
import { QuestpieClient } from "questpie/client";
|
|
2
|
+
import { QuestpieApp, QuestpieClient, RealtimeAPI, TopicConfig, buildCollectionTopic, buildGlobalTopic } from "questpie/client";
|
|
4
3
|
|
|
5
4
|
//#region src/index.d.ts
|
|
6
5
|
type QuestpieQueryErrorMap = (error: unknown) => unknown;
|
|
@@ -8,56 +7,93 @@ type QuestpieQueryOptionsConfig = {
|
|
|
8
7
|
keyPrefix?: QueryKey;
|
|
9
8
|
errorMap?: QuestpieQueryErrorMap;
|
|
10
9
|
locale?: string;
|
|
10
|
+
stage?: string;
|
|
11
11
|
};
|
|
12
12
|
type AnyAsyncFn = (...args: any[]) => Promise<any>;
|
|
13
13
|
type QueryData<TFn extends AnyAsyncFn> = Awaited<ReturnType<TFn>>;
|
|
14
14
|
type FirstArg<TFn extends AnyAsyncFn> = Parameters<TFn> extends [infer TFirst, ...any[]] ? TFirst : never;
|
|
15
15
|
type HasArgs<TFn extends AnyAsyncFn> = Parameters<TFn> extends [] ? false : true;
|
|
16
16
|
type QueryBuilder<TFn extends AnyAsyncFn> = HasArgs<TFn> extends false ? () => UseQueryOptions<QueryData<TFn>> : undefined extends FirstArg<TFn> ? (options?: FirstArg<TFn>) => UseQueryOptions<QueryData<TFn>> : (options: FirstArg<TFn>) => UseQueryOptions<QueryData<TFn>>;
|
|
17
|
+
type KeyBuilder<TFn extends AnyAsyncFn> = HasArgs<TFn> extends false ? () => QueryKey : undefined extends FirstArg<TFn> ? (options?: FirstArg<TFn>) => QueryKey : (options: FirstArg<TFn>) => QueryKey;
|
|
18
|
+
type MutationVariables<TFn extends AnyAsyncFn> = HasArgs<TFn> extends false ? void : undefined extends FirstArg<TFn> ? FirstArg<TFn> | void : FirstArg<TFn>;
|
|
17
19
|
type MutationBuilder<TVariables, TData> = () => UseMutationOptions<TData, DefaultError, TVariables>;
|
|
18
20
|
/** Extract collection keys from QuestpieClient */
|
|
19
|
-
type CollectionKeys<
|
|
21
|
+
type CollectionKeys<TApp extends QuestpieApp> = Extract<keyof QuestpieClient<TApp>["collections"], string>;
|
|
20
22
|
/** Extract global keys from QuestpieClient */
|
|
21
|
-
type GlobalKeys<
|
|
22
|
-
type CollectionFind<
|
|
23
|
-
type CollectionCount<
|
|
24
|
-
type CollectionFindOne<
|
|
25
|
-
type CollectionCreate<
|
|
26
|
-
type CollectionUpdate<
|
|
27
|
-
type CollectionDelete<
|
|
28
|
-
type CollectionRestore<
|
|
29
|
-
type
|
|
23
|
+
type GlobalKeys<TApp extends QuestpieApp> = Extract<keyof QuestpieClient<TApp>["globals"], string>;
|
|
24
|
+
type CollectionFind<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["find"];
|
|
25
|
+
type CollectionCount<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["count"];
|
|
26
|
+
type CollectionFindOne<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["findOne"];
|
|
27
|
+
type CollectionCreate<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["create"];
|
|
28
|
+
type CollectionUpdate<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["update"];
|
|
29
|
+
type CollectionDelete<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["delete"];
|
|
30
|
+
type CollectionRestore<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["restore"];
|
|
31
|
+
type CollectionFindVersions<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["findVersions"];
|
|
32
|
+
type CollectionRevertToVersion<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["revertToVersion"];
|
|
33
|
+
type CollectionTransitionStage<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["transitionStage"];
|
|
34
|
+
type GlobalGet<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = QuestpieClient<TApp>["globals"][K$1] extends {
|
|
30
35
|
get: infer TGet;
|
|
31
36
|
} ? TGet extends AnyAsyncFn ? TGet : never : never;
|
|
32
|
-
type GlobalUpdate<
|
|
37
|
+
type GlobalUpdate<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = QuestpieClient<TApp>["globals"][K$1] extends {
|
|
33
38
|
update: infer TUpdate;
|
|
34
39
|
} ? TUpdate extends AnyAsyncFn ? TUpdate : never : never;
|
|
35
|
-
type
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
type GlobalFindVersions<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = QuestpieClient<TApp>["globals"][K$1] extends {
|
|
41
|
+
findVersions: infer TFindVersions;
|
|
42
|
+
} ? TFindVersions extends AnyAsyncFn ? TFindVersions : never : never;
|
|
43
|
+
type GlobalRevertToVersion<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = QuestpieClient<TApp>["globals"][K$1] extends {
|
|
44
|
+
revertToVersion: infer TRevert;
|
|
45
|
+
} ? TRevert extends AnyAsyncFn ? TRevert : never : never;
|
|
46
|
+
type GlobalTransitionStage<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = QuestpieClient<TApp>["globals"][K$1] extends {
|
|
47
|
+
transitionStage: infer TTransition;
|
|
48
|
+
} ? TTransition extends AnyAsyncFn ? TTransition : never : never;
|
|
49
|
+
type RouteLeafQueryOptionsAPI<TFn extends AnyAsyncFn> = {
|
|
50
|
+
query: QueryBuilder<TFn>;
|
|
51
|
+
mutation: MutationBuilder<MutationVariables<TFn>, QueryData<TFn>>;
|
|
52
|
+
key: KeyBuilder<TFn>;
|
|
53
|
+
};
|
|
54
|
+
type RoutesQueryOptionsAPI<TNode> = TNode extends AnyAsyncFn ? RouteLeafQueryOptionsAPI<TNode> : TNode extends Record<string, any> ? { [K in keyof TNode]: RoutesQueryOptionsAPI<TNode[K]> } : never;
|
|
55
|
+
type CollectionQueryOptionsAPI<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = {
|
|
56
|
+
find: QueryBuilder<CollectionFind<TApp, K$1>>;
|
|
57
|
+
count: QueryBuilder<CollectionCount<TApp, K$1>>;
|
|
58
|
+
findOne: QueryBuilder<CollectionFindOne<TApp, K$1>>;
|
|
59
|
+
create: MutationBuilder<FirstArg<CollectionCreate<TApp, K$1>>, QueryData<CollectionCreate<TApp, K$1>>>;
|
|
60
|
+
update: MutationBuilder<FirstArg<CollectionUpdate<TApp, K$1>>, QueryData<CollectionUpdate<TApp, K$1>>>;
|
|
61
|
+
delete: MutationBuilder<FirstArg<CollectionDelete<TApp, K$1>>, QueryData<CollectionDelete<TApp, K$1>>>;
|
|
62
|
+
restore: MutationBuilder<FirstArg<CollectionRestore<TApp, K$1>>, QueryData<CollectionRestore<TApp, K$1>>>;
|
|
63
|
+
findVersions: QueryBuilder<CollectionFindVersions<TApp, K$1>>;
|
|
64
|
+
revertToVersion: MutationBuilder<FirstArg<CollectionRevertToVersion<TApp, K$1>>, QueryData<CollectionRevertToVersion<TApp, K$1>>>;
|
|
65
|
+
transitionStage: MutationBuilder<FirstArg<CollectionTransitionStage<TApp, K$1>>, QueryData<CollectionTransitionStage<TApp, K$1>>>;
|
|
66
|
+
updateMany: MutationBuilder<{
|
|
67
|
+
where: any;
|
|
68
|
+
data: any;
|
|
69
|
+
}, QueryData<CollectionUpdate<TApp, K$1>>>;
|
|
70
|
+
deleteMany: MutationBuilder<{
|
|
71
|
+
where: any;
|
|
72
|
+
}, {
|
|
73
|
+
success: boolean;
|
|
74
|
+
count: number;
|
|
75
|
+
}>;
|
|
50
76
|
};
|
|
51
|
-
type GlobalQueryOptionsAPI<
|
|
52
|
-
get: QueryBuilder<GlobalGet<
|
|
77
|
+
type GlobalQueryOptionsAPI<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = {
|
|
78
|
+
get: QueryBuilder<GlobalGet<TApp, K$1>>;
|
|
53
79
|
update: MutationBuilder<{
|
|
54
|
-
data: Parameters<GlobalUpdate<
|
|
55
|
-
options?: Parameters<GlobalUpdate<
|
|
56
|
-
}, QueryData<GlobalUpdate<
|
|
80
|
+
data: Parameters<GlobalUpdate<TApp, K$1>>[0];
|
|
81
|
+
options?: Parameters<GlobalUpdate<TApp, K$1>>[1];
|
|
82
|
+
}, QueryData<GlobalUpdate<TApp, K$1>>>;
|
|
83
|
+
findVersions: QueryBuilder<GlobalFindVersions<TApp, K$1>>;
|
|
84
|
+
revertToVersion: MutationBuilder<{
|
|
85
|
+
params: Parameters<GlobalRevertToVersion<TApp, K$1>>[0];
|
|
86
|
+
options?: Parameters<GlobalRevertToVersion<TApp, K$1>>[1];
|
|
87
|
+
}, QueryData<GlobalRevertToVersion<TApp, K$1>>>;
|
|
88
|
+
transitionStage: MutationBuilder<{
|
|
89
|
+
params: Parameters<GlobalTransitionStage<TApp, K$1>>[0];
|
|
90
|
+
options?: Parameters<GlobalTransitionStage<TApp, K$1>>[1];
|
|
91
|
+
}, QueryData<GlobalTransitionStage<TApp, K$1>>>;
|
|
57
92
|
};
|
|
58
|
-
type QuestpieQueryOptionsProxy<
|
|
59
|
-
collections: { [K in CollectionKeys<
|
|
60
|
-
globals: { [K in GlobalKeys<
|
|
93
|
+
type QuestpieQueryOptionsProxy<TApp extends QuestpieApp = QuestpieApp> = {
|
|
94
|
+
collections: { [K in CollectionKeys<TApp>]: CollectionQueryOptionsAPI<TApp, K> };
|
|
95
|
+
globals: { [K in GlobalKeys<TApp>]: GlobalQueryOptionsAPI<TApp, K> };
|
|
96
|
+
routes: RoutesQueryOptionsAPI<QuestpieClient<TApp>["routes"]>;
|
|
61
97
|
custom: {
|
|
62
98
|
query: <TData>(config: {
|
|
63
99
|
key: QueryKey;
|
|
@@ -77,17 +113,21 @@ type QuestpieQueryOptionsProxy<T extends Questpie<any>> = {
|
|
|
77
113
|
* ```ts
|
|
78
114
|
* import { createQuestpieQueryOptions } from "@questpie/tanstack-query"
|
|
79
115
|
* import { createClient } from "questpie/client"
|
|
116
|
+
* import type { App, AppRpc } from "@/app"
|
|
80
117
|
*
|
|
81
|
-
* const client = createClient<
|
|
82
|
-
* const
|
|
118
|
+
* const client = createClient<App, AppRpc>({ baseURL: "http://localhost:3000" })
|
|
119
|
+
* const cmsQueries = createQuestpieQueryOptions(client)
|
|
83
120
|
*
|
|
84
121
|
* // Use with useQuery
|
|
85
|
-
* const { data } = useQuery(
|
|
122
|
+
* const { data } = useQuery(cmsQueries.collections.posts.find({ limit: 10 }))
|
|
86
123
|
*
|
|
87
124
|
* // Use with useMutation
|
|
88
|
-
* const mutation = useMutation(
|
|
125
|
+
* const mutation = useMutation(cmsQueries.collections.posts.create())
|
|
126
|
+
*
|
|
127
|
+
* // Use with routes
|
|
128
|
+
* const stats = useQuery(cmsQueries.routes.dashboard.getStats.query({ period: "week" }))
|
|
89
129
|
* ```
|
|
90
130
|
*/
|
|
91
|
-
declare function createQuestpieQueryOptions<
|
|
131
|
+
declare function createQuestpieQueryOptions<TApp extends QuestpieApp = QuestpieApp>(client: QuestpieClient<TApp>, config?: QuestpieQueryOptionsConfig): QuestpieQueryOptionsProxy<TApp>;
|
|
92
132
|
//#endregion
|
|
93
|
-
export { type DefaultError, type QueryKey, QuestpieQueryErrorMap, QuestpieQueryOptionsConfig, QuestpieQueryOptionsProxy, type UseMutationOptions, type UseQueryOptions, createQuestpieQueryOptions };
|
|
133
|
+
export { type DefaultError, type QueryKey, QuestpieQueryErrorMap, QuestpieQueryOptionsConfig, QuestpieQueryOptionsProxy, type RealtimeAPI, type TopicConfig, type UseMutationOptions, type UseQueryOptions, buildCollectionTopic, buildGlobalTopic, createQuestpieQueryOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { mutationOptions, queryOptions } from "@tanstack/react-query";
|
|
1
|
+
import { experimental_streamedQuery, mutationOptions, queryOptions } from "@tanstack/react-query";
|
|
2
|
+
import { buildCollectionTopic, buildCollectionTopic as buildCollectionTopic$1, buildGlobalTopic, buildGlobalTopic as buildGlobalTopic$1 } from "questpie/client";
|
|
2
3
|
|
|
3
4
|
//#region src/index.ts
|
|
4
5
|
const defaultErrorMap = (error) => error instanceof Error ? error : new Error(typeof error === "string" ? error : "Unknown error");
|
|
@@ -44,114 +45,334 @@ const wrapMutationFn = (mutationFn, errorMap) => {
|
|
|
44
45
|
* ```ts
|
|
45
46
|
* import { createQuestpieQueryOptions } from "@questpie/tanstack-query"
|
|
46
47
|
* import { createClient } from "questpie/client"
|
|
48
|
+
* import type { App, AppRpc } from "@/app"
|
|
47
49
|
*
|
|
48
|
-
* const client = createClient<
|
|
49
|
-
* const
|
|
50
|
+
* const client = createClient<App, AppRpc>({ baseURL: "http://localhost:3000" })
|
|
51
|
+
* const cmsQueries = createQuestpieQueryOptions(client)
|
|
50
52
|
*
|
|
51
53
|
* // Use with useQuery
|
|
52
|
-
* const { data } = useQuery(
|
|
54
|
+
* const { data } = useQuery(cmsQueries.collections.posts.find({ limit: 10 }))
|
|
53
55
|
*
|
|
54
56
|
* // Use with useMutation
|
|
55
|
-
* const mutation = useMutation(
|
|
57
|
+
* const mutation = useMutation(cmsQueries.collections.posts.create())
|
|
58
|
+
*
|
|
59
|
+
* // Use with routes
|
|
60
|
+
* const stats = useQuery(cmsQueries.routes.dashboard.getStats.query({ period: "week" }))
|
|
56
61
|
* ```
|
|
57
62
|
*/
|
|
58
63
|
function createQuestpieQueryOptions(client, config = {}) {
|
|
59
64
|
const keyPrefix = config.keyPrefix ?? ["questpie"];
|
|
60
65
|
const errorMap = config.errorMap ?? defaultErrorMap;
|
|
61
66
|
const locale = config.locale;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
const stage = config.stage;
|
|
68
|
+
const collections = new Proxy({}, { get: (_target, collectionName) => {
|
|
69
|
+
if (typeof collectionName !== "string") return void 0;
|
|
70
|
+
const collection = client.collections[collectionName];
|
|
71
|
+
const baseKey = ["collections", collectionName];
|
|
72
|
+
return {
|
|
73
|
+
find: (options, queryConfig) => {
|
|
74
|
+
const qKey = buildKey(keyPrefix, [
|
|
75
|
+
...baseKey,
|
|
76
|
+
"find",
|
|
77
|
+
locale,
|
|
78
|
+
stage,
|
|
79
|
+
normalizeQueryKeyOptions(options)
|
|
80
|
+
]);
|
|
81
|
+
if (queryConfig?.realtime && client.realtime) {
|
|
82
|
+
const topic = buildCollectionTopic$1(collectionName, options);
|
|
83
|
+
return queryOptions({
|
|
84
|
+
queryKey: qKey,
|
|
85
|
+
queryFn: experimental_streamedQuery({
|
|
86
|
+
streamFn: ({ signal }) => client.realtime.stream(topic, signal),
|
|
87
|
+
reducer: (_, chunk) => chunk,
|
|
88
|
+
initialValue: void 0,
|
|
89
|
+
refetchMode: "append"
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return queryOptions({
|
|
94
|
+
queryKey: qKey,
|
|
75
95
|
queryFn: wrapQueryFn(() => collection.find(options), errorMap)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
count: (options, queryConfig) => {
|
|
99
|
+
const qKey = buildKey(keyPrefix, [
|
|
100
|
+
...baseKey,
|
|
101
|
+
"count",
|
|
102
|
+
locale,
|
|
103
|
+
stage,
|
|
104
|
+
normalizeQueryKeyOptions(options)
|
|
105
|
+
]);
|
|
106
|
+
if (queryConfig?.realtime && client.realtime) {
|
|
107
|
+
const topic = buildCollectionTopic$1(collectionName, options);
|
|
108
|
+
return queryOptions({
|
|
109
|
+
queryKey: qKey,
|
|
110
|
+
queryFn: experimental_streamedQuery({
|
|
111
|
+
streamFn: ({ signal }) => client.realtime.stream(topic, signal),
|
|
112
|
+
reducer: (_, chunk) => typeof chunk?.totalDocs === "number" ? chunk.totalDocs : chunk,
|
|
113
|
+
initialValue: void 0,
|
|
114
|
+
refetchMode: "append"
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return queryOptions({
|
|
119
|
+
queryKey: qKey,
|
|
84
120
|
queryFn: wrapQueryFn(() => collection.count(options), errorMap)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
findOne: (options) => queryOptions({
|
|
124
|
+
queryKey: buildKey(keyPrefix, [
|
|
125
|
+
...baseKey,
|
|
126
|
+
"findOne",
|
|
127
|
+
locale,
|
|
128
|
+
stage,
|
|
129
|
+
normalizeQueryKeyOptions(options)
|
|
130
|
+
]),
|
|
131
|
+
queryFn: wrapQueryFn(() => collection.findOne(options), errorMap)
|
|
132
|
+
}),
|
|
133
|
+
create: () => mutationOptions({
|
|
134
|
+
mutationKey: buildKey(keyPrefix, [
|
|
135
|
+
...baseKey,
|
|
136
|
+
"create",
|
|
137
|
+
locale,
|
|
138
|
+
stage
|
|
139
|
+
]),
|
|
140
|
+
mutationFn: wrapMutationFn((data) => collection.create(data, locale || stage ? {
|
|
141
|
+
...locale ? { locale } : {},
|
|
142
|
+
...stage ? { stage } : {}
|
|
143
|
+
} : void 0), errorMap)
|
|
144
|
+
}),
|
|
145
|
+
update: () => mutationOptions({
|
|
146
|
+
mutationKey: buildKey(keyPrefix, [
|
|
147
|
+
...baseKey,
|
|
148
|
+
"update",
|
|
149
|
+
locale,
|
|
150
|
+
stage
|
|
151
|
+
]),
|
|
152
|
+
mutationFn: wrapMutationFn((variables) => collection.update(variables, locale || stage ? {
|
|
153
|
+
...locale ? { locale } : {},
|
|
154
|
+
...stage ? { stage } : {}
|
|
155
|
+
} : void 0), errorMap)
|
|
156
|
+
}),
|
|
157
|
+
delete: () => mutationOptions({
|
|
158
|
+
mutationKey: buildKey(keyPrefix, [
|
|
159
|
+
...baseKey,
|
|
160
|
+
"delete",
|
|
161
|
+
locale,
|
|
162
|
+
stage
|
|
163
|
+
]),
|
|
164
|
+
mutationFn: wrapMutationFn((variables) => collection.delete(variables, locale || stage ? {
|
|
165
|
+
...locale ? { locale } : {},
|
|
166
|
+
...stage ? { stage } : {}
|
|
167
|
+
} : void 0), errorMap)
|
|
168
|
+
}),
|
|
169
|
+
restore: () => mutationOptions({
|
|
170
|
+
mutationKey: buildKey(keyPrefix, [
|
|
171
|
+
...baseKey,
|
|
172
|
+
"restore",
|
|
173
|
+
locale,
|
|
174
|
+
stage
|
|
175
|
+
]),
|
|
176
|
+
mutationFn: wrapMutationFn((variables) => collection.restore(variables, locale || stage ? {
|
|
177
|
+
...locale ? { locale } : {},
|
|
178
|
+
...stage ? { stage } : {}
|
|
179
|
+
} : void 0), errorMap)
|
|
180
|
+
}),
|
|
181
|
+
findVersions: (params) => queryOptions({
|
|
182
|
+
queryKey: buildKey(keyPrefix, [
|
|
183
|
+
...baseKey,
|
|
184
|
+
"findVersions",
|
|
185
|
+
locale,
|
|
186
|
+
stage,
|
|
187
|
+
normalizeQueryKeyOptions(params)
|
|
188
|
+
]),
|
|
189
|
+
queryFn: wrapQueryFn(() => collection.findVersions(params, locale || stage ? {
|
|
190
|
+
...locale ? { locale } : {},
|
|
191
|
+
...stage ? { stage } : {}
|
|
192
|
+
} : void 0), errorMap)
|
|
193
|
+
}),
|
|
194
|
+
revertToVersion: () => mutationOptions({
|
|
195
|
+
mutationKey: buildKey(keyPrefix, [
|
|
196
|
+
...baseKey,
|
|
197
|
+
"revertToVersion",
|
|
198
|
+
locale,
|
|
199
|
+
stage
|
|
200
|
+
]),
|
|
201
|
+
mutationFn: wrapMutationFn((variables) => collection.revertToVersion(variables, locale || stage ? {
|
|
202
|
+
...locale ? { locale } : {},
|
|
203
|
+
...stage ? { stage } : {}
|
|
204
|
+
} : void 0), errorMap)
|
|
205
|
+
}),
|
|
206
|
+
transitionStage: () => mutationOptions({
|
|
207
|
+
mutationKey: buildKey(keyPrefix, [
|
|
208
|
+
...baseKey,
|
|
209
|
+
"transitionStage",
|
|
210
|
+
locale,
|
|
211
|
+
stage
|
|
212
|
+
]),
|
|
213
|
+
mutationFn: wrapMutationFn((variables) => collection.transitionStage(variables, locale || stage ? {
|
|
214
|
+
...locale ? { locale } : {},
|
|
215
|
+
...stage ? { stage } : {}
|
|
216
|
+
} : void 0), errorMap)
|
|
217
|
+
}),
|
|
218
|
+
updateMany: () => mutationOptions({
|
|
219
|
+
mutationKey: buildKey(keyPrefix, [
|
|
220
|
+
...baseKey,
|
|
221
|
+
"updateMany",
|
|
222
|
+
locale,
|
|
223
|
+
stage
|
|
224
|
+
]),
|
|
225
|
+
mutationFn: wrapMutationFn((variables) => collection.updateMany(variables, locale || stage ? {
|
|
226
|
+
...locale ? { locale } : {},
|
|
227
|
+
...stage ? { stage } : {}
|
|
228
|
+
} : void 0), errorMap)
|
|
229
|
+
}),
|
|
230
|
+
deleteMany: () => mutationOptions({
|
|
231
|
+
mutationKey: buildKey(keyPrefix, [
|
|
232
|
+
...baseKey,
|
|
233
|
+
"deleteMany",
|
|
234
|
+
locale,
|
|
235
|
+
stage
|
|
236
|
+
]),
|
|
237
|
+
mutationFn: wrapMutationFn((variables) => collection.deleteMany(variables, locale || stage ? {
|
|
238
|
+
...locale ? { locale } : {},
|
|
239
|
+
...stage ? { stage } : {}
|
|
240
|
+
} : void 0), errorMap)
|
|
241
|
+
})
|
|
242
|
+
};
|
|
243
|
+
} });
|
|
244
|
+
const globals = new Proxy({}, { get: (_target, globalName) => {
|
|
245
|
+
if (typeof globalName !== "string") return void 0;
|
|
246
|
+
const global = client.globals[globalName];
|
|
247
|
+
const baseKey = ["globals", globalName];
|
|
248
|
+
return {
|
|
249
|
+
get: (options, queryConfig) => {
|
|
250
|
+
const qKey = buildKey(keyPrefix, [
|
|
251
|
+
...baseKey,
|
|
252
|
+
"get",
|
|
253
|
+
locale,
|
|
254
|
+
stage,
|
|
255
|
+
normalizeQueryKeyOptions(options)
|
|
256
|
+
]);
|
|
257
|
+
if (queryConfig?.realtime && client.realtime) {
|
|
258
|
+
const topic = buildGlobalTopic$1(globalName, options);
|
|
259
|
+
return queryOptions({
|
|
260
|
+
queryKey: qKey,
|
|
261
|
+
queryFn: experimental_streamedQuery({
|
|
262
|
+
streamFn: ({ signal }) => client.realtime.stream(topic, signal),
|
|
263
|
+
reducer: (_, chunk) => chunk,
|
|
264
|
+
initialValue: void 0,
|
|
265
|
+
refetchMode: "append"
|
|
266
|
+
})
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return queryOptions({
|
|
270
|
+
queryKey: qKey,
|
|
141
271
|
queryFn: wrapQueryFn(() => global.get(options), errorMap)
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
272
|
+
});
|
|
273
|
+
},
|
|
274
|
+
update: () => mutationOptions({
|
|
275
|
+
mutationKey: buildKey(keyPrefix, [
|
|
276
|
+
...baseKey,
|
|
277
|
+
"update",
|
|
278
|
+
locale,
|
|
279
|
+
stage
|
|
280
|
+
]),
|
|
281
|
+
mutationFn: wrapMutationFn((variables) => global.update(variables.data, {
|
|
282
|
+
...variables.options,
|
|
283
|
+
...locale ? { locale } : void 0,
|
|
284
|
+
...stage ? { stage } : void 0
|
|
285
|
+
}), errorMap)
|
|
286
|
+
}),
|
|
287
|
+
findVersions: (options) => queryOptions({
|
|
288
|
+
queryKey: buildKey(keyPrefix, [
|
|
289
|
+
...baseKey,
|
|
290
|
+
"findVersions",
|
|
291
|
+
locale,
|
|
292
|
+
stage,
|
|
293
|
+
normalizeQueryKeyOptions(options)
|
|
294
|
+
]),
|
|
295
|
+
queryFn: wrapQueryFn(() => global.findVersions({
|
|
296
|
+
...options,
|
|
297
|
+
...locale ? { locale } : void 0,
|
|
298
|
+
...stage ? { stage } : void 0
|
|
299
|
+
}), errorMap)
|
|
300
|
+
}),
|
|
301
|
+
revertToVersion: () => mutationOptions({
|
|
302
|
+
mutationKey: buildKey(keyPrefix, [
|
|
303
|
+
...baseKey,
|
|
304
|
+
"revertToVersion",
|
|
305
|
+
locale,
|
|
306
|
+
stage
|
|
307
|
+
]),
|
|
308
|
+
mutationFn: wrapMutationFn((variables) => global.revertToVersion(variables.params, {
|
|
309
|
+
...variables.options,
|
|
310
|
+
...locale ? { locale } : void 0,
|
|
311
|
+
...stage ? { stage } : void 0
|
|
312
|
+
}), errorMap)
|
|
313
|
+
}),
|
|
314
|
+
transitionStage: () => mutationOptions({
|
|
315
|
+
mutationKey: buildKey(keyPrefix, [
|
|
316
|
+
...baseKey,
|
|
317
|
+
"transitionStage",
|
|
318
|
+
locale,
|
|
319
|
+
stage
|
|
320
|
+
]),
|
|
321
|
+
mutationFn: wrapMutationFn((variables) => global.transitionStage(variables.params, {
|
|
322
|
+
...variables.options,
|
|
323
|
+
...locale ? { locale } : void 0
|
|
324
|
+
}), errorMap)
|
|
325
|
+
})
|
|
326
|
+
};
|
|
327
|
+
} });
|
|
328
|
+
/**
|
|
329
|
+
* Resolve a nested route caller from the client by traversing dot segments.
|
|
330
|
+
*/
|
|
331
|
+
const callRoute = async (segments, input) => {
|
|
332
|
+
let current = client.routes;
|
|
333
|
+
for (const segment of segments) current = current?.[segment];
|
|
334
|
+
if (typeof current !== "function") throw new Error(`Route not found at path: ${segments.join(".") || "<root>"}`);
|
|
335
|
+
if (input === void 0) return current();
|
|
336
|
+
return current(input);
|
|
337
|
+
};
|
|
338
|
+
const createRouteNodeProxy = (segments) => {
|
|
339
|
+
return new Proxy({}, { get: (_target, prop) => {
|
|
340
|
+
if (prop === "query") return (input) => queryOptions({
|
|
341
|
+
queryKey: buildKey(keyPrefix, [
|
|
342
|
+
"routes",
|
|
343
|
+
...segments,
|
|
344
|
+
"query",
|
|
345
|
+
locale,
|
|
346
|
+
normalizeQueryKeyOptions(input)
|
|
347
|
+
]),
|
|
348
|
+
queryFn: wrapQueryFn(() => callRoute(segments, input), errorMap)
|
|
349
|
+
});
|
|
350
|
+
if (prop === "mutation") return () => mutationOptions({
|
|
351
|
+
mutationKey: buildKey(keyPrefix, [
|
|
352
|
+
"routes",
|
|
353
|
+
...segments,
|
|
354
|
+
"mutation",
|
|
355
|
+
locale
|
|
356
|
+
]),
|
|
357
|
+
mutationFn: wrapMutationFn((variables) => callRoute(segments, variables), errorMap)
|
|
358
|
+
});
|
|
359
|
+
if (prop === "key") return (input) => buildKey(keyPrefix, [
|
|
360
|
+
"routes",
|
|
361
|
+
...segments,
|
|
362
|
+
"query",
|
|
363
|
+
locale,
|
|
364
|
+
normalizeQueryKeyOptions(input)
|
|
365
|
+
]);
|
|
366
|
+
if (typeof prop !== "string") return void 0;
|
|
367
|
+
return createRouteNodeProxy([...segments, prop]);
|
|
368
|
+
} });
|
|
369
|
+
};
|
|
370
|
+
return {
|
|
371
|
+
collections,
|
|
372
|
+
globals,
|
|
373
|
+
routes: new Proxy({}, { get: (_target, prop) => {
|
|
374
|
+
if (typeof prop !== "string") return void 0;
|
|
375
|
+
return createRouteNodeProxy([prop]);
|
|
155
376
|
} }),
|
|
156
377
|
custom: {
|
|
157
378
|
query: (customConfig) => queryOptions({
|
|
@@ -168,4 +389,4 @@ function createQuestpieQueryOptions(client, config = {}) {
|
|
|
168
389
|
}
|
|
169
390
|
|
|
170
391
|
//#endregion
|
|
171
|
-
export { createQuestpieQueryOptions };
|
|
392
|
+
export { buildCollectionTopic, buildGlobalTopic, createQuestpieQueryOptions };
|
package/package.json
CHANGED
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@questpie/tanstack-query",
|
|
3
|
-
"version": "
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "3.0.0",
|
|
5
4
|
"repository": {
|
|
6
5
|
"type": "git",
|
|
7
|
-
"url": "https://github.com/questpie/questpie
|
|
6
|
+
"url": "https://github.com/questpie/questpie.git",
|
|
8
7
|
"directory": "packages/tanstack-query"
|
|
9
8
|
},
|
|
10
9
|
"files": [
|
|
11
10
|
"dist"
|
|
12
11
|
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.mjs",
|
|
14
|
+
"module": "./dist/index.mjs",
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
19
|
+
"default": "./dist/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
13
33
|
"scripts": {
|
|
14
34
|
"build": "tsdown",
|
|
15
35
|
"check-types": "tsc --noEmit"
|
|
@@ -19,16 +39,7 @@
|
|
|
19
39
|
"tsdown": "^0.18.3"
|
|
20
40
|
},
|
|
21
41
|
"peerDependencies": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
},
|
|
25
|
-
"exports": {
|
|
26
|
-
".": {
|
|
27
|
-
"import": "./dist/index.mjs",
|
|
28
|
-
"types": "./dist/index.d.mts"
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
"publishConfig": {
|
|
32
|
-
"access": "public"
|
|
42
|
+
"@tanstack/react-query": "^5.0.0",
|
|
43
|
+
"questpie": "^3.0.0"
|
|
33
44
|
}
|
|
34
45
|
}
|