@questpie/tanstack-query 3.16.0 → 3.18.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 CHANGED
@@ -219,6 +219,13 @@ export default async function PostsPage() {
219
219
  }
220
220
  ```
221
221
 
222
+ TanStack Query's dehydrated state remains a JavaScript object and retains
223
+ QUESTPIE `Date` values. TanStack Start's Seroval hydration preserves them across
224
+ its serialization boundary. Other hosts must use their documented Date-aware
225
+ transport. If you move the state through an application-owned JSON-only
226
+ boundary, use a Date-aware serializer; never revive all ISO-looking strings
227
+ heuristically because `f.date()` and ordinary string fields must remain strings.
228
+
222
229
  ## Query Key Structure
223
230
 
224
231
  ```ts
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DefaultError, QueryKey, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
2
- import { ApplyQuery, CollectionRelations, CollectionSelect, FindManyOptions, FindOneOptionsBase, FindResult, GetCollection, GetGlobal, GlobalRelations, GlobalSelect, QuestpieApp, QuestpieClient, RealtimeAPI, ResolveRelationsDeep, TopicConfig, With, buildCollectionTopic, buildGlobalTopic } from "questpie/client";
2
+ import { ApplyQuery, CollectionRelations, CollectionSelect, FindManyOptions, FindOneOptionsBase, FindResult, GetCollection, GetGlobal, GlobalRelations, GlobalSelect, QuestpieApp, QuestpieClient, RealtimeAPI, ResolveRelationsDeep, TopicConfig, With, applyRealtimeFindEvent, applyRealtimeScalarEvent, applyRealtimeSingleEvent, buildCollectionTopic, buildGlobalTopic } from "questpie/client";
3
3
  import { AnyChannelDefinition, ChannelParamsOf, ChannelPresenceOf } from "questpie/channels";
4
4
 
5
5
  //#region src/index.d.ts
@@ -18,11 +18,11 @@ type QueryBuilder<TFn extends AnyAsyncFn> = HasArgs<TFn> extends false ? () => U
18
18
  /**
19
19
  * Per-query realtime flag — the second argument to `find` / `count` / `get`.
20
20
  */
21
- type RealtimeQueryConfig = {
21
+ type RealtimeQueryConfig<TData = unknown> = Omit<UseQueryOptions<TData>, "queryFn" | "queryKey"> & {
22
22
  /**
23
- * Subscribe the query to live snapshots over the multiplexed SSE stream.
24
- * The server supplies both the initial value and later full snapshots through
25
- * the same stream (via `experimental_streamedQuery`).
23
+ * Subscribe the query to the multiplexed realtime stream. The initial value
24
+ * and later keyed changes share one stream, so realtime mode performs no
25
+ * separate REST fetch.
26
26
  */
27
27
  realtime?: boolean;
28
28
  };
@@ -30,7 +30,7 @@ type RealtimeQueryConfig = {
30
30
  * Builder for reads that also have a live form — same as `QueryBuilder`
31
31
  * plus the optional `{ realtime }` second argument.
32
32
  */
33
- type LiveQueryBuilder<TFn extends AnyAsyncFn> = undefined extends FirstArg<TFn> ? (options?: FirstArg<TFn>, queryConfig?: RealtimeQueryConfig) => UseQueryOptions<QueryData<TFn>> : (options: FirstArg<TFn>, queryConfig?: RealtimeQueryConfig) => UseQueryOptions<QueryData<TFn>>;
33
+ type LiveQueryBuilder<TFn extends AnyAsyncFn> = undefined extends FirstArg<TFn> ? (options?: FirstArg<TFn>, queryConfig?: RealtimeQueryConfig<QueryData<TFn>>) => UseQueryOptions<QueryData<TFn>> : (options: FirstArg<TFn>, queryConfig?: RealtimeQueryConfig<QueryData<TFn>>) => UseQueryOptions<QueryData<TFn>>;
34
34
  type KeyBuilder<TFn extends AnyAsyncFn> = HasArgs<TFn> extends false ? () => QueryKey : undefined extends FirstArg<TFn> ? (options?: FirstArg<TFn>) => QueryKey : (options: FirstArg<TFn>) => QueryKey;
35
35
  type MutationVariables<TFn extends AnyAsyncFn> = HasArgs<TFn> extends false ? void : undefined extends FirstArg<TFn> ? FirstArg<TFn> | void : FirstArg<TFn>;
36
36
  type MutationBuilder<TVariables, TData> = () => UseMutationOptions<TData, DefaultError, TVariables>;
@@ -64,6 +64,9 @@ type CollectionCreate<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>
64
64
  type CollectionUpdate<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["update"];
65
65
  type CollectionDelete<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["delete"];
66
66
  type CollectionRestore<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["restore"];
67
+ type CollectionPurgeById<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1] extends {
68
+ purgeById: infer TPurge extends AnyAsyncFn;
69
+ } ? TPurge : never;
67
70
  type CollectionFindVersions<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["findVersions"];
68
71
  type CollectionRevertToVersion<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["revertToVersion"];
69
72
  type CollectionTransitionStage<TApp extends QuestpieApp, K$1 extends CollectionKeys<TApp>> = QuestpieClient<TApp>["collections"][K$1]["transitionStage"];
@@ -91,7 +94,7 @@ type CollectionQueryOptionsAPI<TApp extends QuestpieApp, K$1 extends CollectionK
91
94
  * client's `find()` (a `ReturnType`-based extraction would instantiate the
92
95
  * client generic at its constraint and collapse docs to `{}`).
93
96
  */
94
- find: <TQuery extends FindManyOptions<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>> | undefined = undefined>(options?: TQuery, queryConfig?: RealtimeQueryConfig) => UseQueryOptions<FindResult<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>, TQuery>>;
97
+ find: <TQuery extends FindManyOptions<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>> | undefined = undefined>(options?: TQuery, queryConfig?: RealtimeQueryConfig<FindResult<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>, TQuery>>) => UseQueryOptions<FindResult<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>, TQuery>>;
95
98
  count: LiveQueryBuilder<CollectionCount<TApp, K$1>>;
96
99
  findOne: <TQuery extends FindOneOptionsBase<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>> | undefined = undefined>(options?: TQuery) => UseQueryOptions<ApplyQuery<CollectionSelectOf<TApp, K$1>, CollectionRelationsOf<TApp, K$1>, TQuery> | null>;
97
100
  create: MutationBuilder<FirstArg<CollectionCreate<TApp, K$1>>, QueryData<CollectionCreate<TApp, K$1>>>;
@@ -111,7 +114,9 @@ type CollectionQueryOptionsAPI<TApp extends QuestpieApp, K$1 extends CollectionK
111
114
  success: boolean;
112
115
  count: number;
113
116
  }>;
114
- };
117
+ } & ([CollectionPurgeById<TApp, K$1>] extends [never] ? {} : {
118
+ purgeById: MutationBuilder<FirstArg<CollectionPurgeById<TApp, K$1>>, QueryData<CollectionPurgeById<TApp, K$1>>>;
119
+ });
115
120
  type GlobalQueryOptionsAPI<TApp extends QuestpieApp, K$1 extends GlobalKeys<TApp>> = {
116
121
  /** Generic per call — mirrors the direct client's `get()` narrowing. */
117
122
  get: <TQuery extends {
@@ -176,4 +181,4 @@ type QuestpieQueryOptionsProxy<TApp extends QuestpieApp = QuestpieApp> = {
176
181
  */
177
182
  declare function createQuestpieQueryOptions<TApp extends QuestpieApp = QuestpieApp>(client: QuestpieClient<TApp>, config?: QuestpieQueryOptionsConfig): QuestpieQueryOptionsProxy<TApp>;
178
183
  //#endregion
179
- export { type DefaultError, type QueryKey, QuestpieQueryErrorMap, QuestpieQueryOptionsConfig, QuestpieQueryOptionsProxy, type RealtimeAPI, RealtimeQueryConfig, type TopicConfig, type UseMutationOptions, type UseQueryOptions, buildCollectionTopic, buildGlobalTopic, createQuestpieQueryOptions };
184
+ export { type DefaultError, type QueryKey, QuestpieQueryErrorMap, QuestpieQueryOptionsConfig, QuestpieQueryOptionsProxy, type RealtimeAPI, RealtimeQueryConfig, type TopicConfig, type UseMutationOptions, type UseQueryOptions, applyRealtimeFindEvent, applyRealtimeScalarEvent, applyRealtimeSingleEvent, buildCollectionTopic, buildGlobalTopic, createQuestpieQueryOptions };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
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
+ import { applyRealtimeFindEvent, applyRealtimeFindEvent as applyRealtimeFindEvent$1, applyRealtimeScalarEvent, applyRealtimeScalarEvent as applyRealtimeScalarEvent$1, applyRealtimeSingleEvent, applyRealtimeSingleEvent as applyRealtimeSingleEvent$1, buildCollectionTopic, buildCollectionTopic as buildCollectionTopic$1, buildGlobalTopic, buildGlobalTopic as buildGlobalTopic$1 } from "questpie/client";
3
3
 
4
4
  //#region src/index.ts
5
5
  const defaultErrorMap = (error) => error instanceof Error ? error : new Error(typeof error === "string" ? error : "Unknown error");
@@ -60,7 +60,7 @@ const wrapMutationFn = (mutationFn, errorMap) => {
60
60
  async function* streamRealtimeQuery(options) {
61
61
  const { realtime, topic, signal, errorMap } = options;
62
62
  try {
63
- for await (const snapshot of realtime.stream(topic, signal)) yield snapshot;
63
+ for await (const event of realtime.streamEvents(topic, signal)) yield event;
64
64
  } catch (error) {
65
65
  throw mapRealtimeError(error, errorMap);
66
66
  }
@@ -106,10 +106,14 @@ function createQuestpieQueryOptions(client, config = {}) {
106
106
  normalizeQueryKeyOptions(options)
107
107
  ]);
108
108
  if (queryConfig?.realtime && client.realtime) {
109
+ const { realtime: _realtime, ...overrides } = queryConfig;
109
110
  const topic = buildCollectionTopic$1(collectionName, options);
110
111
  return queryOptions({
111
112
  queryKey: qKey,
112
113
  retry: realtimeRetry,
114
+ staleTime: 0,
115
+ refetchOnMount: "always",
116
+ ...overrides,
113
117
  queryFn: experimental_streamedQuery({
114
118
  streamFn: ({ signal }) => streamRealtimeQuery({
115
119
  realtime: client.realtime,
@@ -117,7 +121,7 @@ function createQuestpieQueryOptions(client, config = {}) {
117
121
  signal,
118
122
  errorMap
119
123
  }),
120
- reducer: (_, chunk) => chunk,
124
+ reducer: applyRealtimeFindEvent$1,
121
125
  initialValue: void 0,
122
126
  refetchMode: "append"
123
127
  })
@@ -137,10 +141,14 @@ function createQuestpieQueryOptions(client, config = {}) {
137
141
  normalizeQueryKeyOptions(options)
138
142
  ]);
139
143
  if (queryConfig?.realtime && client.realtime) {
144
+ const { realtime: _realtime, ...overrides } = queryConfig;
140
145
  const topic = buildCollectionTopic$1(collectionName, options, "count");
141
146
  return queryOptions({
142
147
  queryKey: qKey,
143
148
  retry: realtimeRetry,
149
+ staleTime: 0,
150
+ refetchOnMount: "always",
151
+ ...overrides,
144
152
  queryFn: experimental_streamedQuery({
145
153
  streamFn: ({ signal }) => streamRealtimeQuery({
146
154
  realtime: client.realtime,
@@ -148,7 +156,7 @@ function createQuestpieQueryOptions(client, config = {}) {
148
156
  signal,
149
157
  errorMap
150
158
  }),
151
- reducer: (_, chunk) => chunk,
159
+ reducer: (current, event) => applyRealtimeScalarEvent$1(current, event),
152
160
  initialValue: void 0,
153
161
  refetchMode: "append"
154
162
  })
@@ -217,6 +225,18 @@ function createQuestpieQueryOptions(client, config = {}) {
217
225
  ...stage ? { stage } : {}
218
226
  } : void 0), errorMap)
219
227
  }),
228
+ purgeById: () => mutationOptions({
229
+ mutationKey: buildKey(keyPrefix, [
230
+ ...baseKey,
231
+ "purgeById",
232
+ locale,
233
+ stage
234
+ ]),
235
+ mutationFn: wrapMutationFn((variables) => collection.purgeById(variables, locale || stage ? {
236
+ ...locale ? { locale } : {},
237
+ ...stage ? { stage } : {}
238
+ } : void 0), errorMap)
239
+ }),
220
240
  findVersions: (params) => queryOptions({
221
241
  queryKey: buildKey(keyPrefix, [
222
242
  ...baseKey,
@@ -294,10 +314,14 @@ function createQuestpieQueryOptions(client, config = {}) {
294
314
  normalizeQueryKeyOptions(options)
295
315
  ]);
296
316
  if (queryConfig?.realtime && client.realtime) {
317
+ const { realtime: _realtime, ...overrides } = queryConfig;
297
318
  const topic = buildGlobalTopic$1(globalName, options);
298
319
  return queryOptions({
299
320
  queryKey: qKey,
300
321
  retry: realtimeRetry,
322
+ staleTime: 0,
323
+ refetchOnMount: "always",
324
+ ...overrides,
301
325
  queryFn: experimental_streamedQuery({
302
326
  streamFn: ({ signal }) => streamRealtimeQuery({
303
327
  realtime: client.realtime,
@@ -305,7 +329,7 @@ function createQuestpieQueryOptions(client, config = {}) {
305
329
  signal,
306
330
  errorMap
307
331
  }),
308
- reducer: (_, chunk) => chunk,
332
+ reducer: (current, event) => applyRealtimeSingleEvent$1(current, event),
309
333
  initialValue: void 0,
310
334
  refetchMode: "append"
311
335
  })
@@ -473,4 +497,4 @@ function createQuestpieQueryOptions(client, config = {}) {
473
497
  }
474
498
 
475
499
  //#endregion
476
- export { buildCollectionTopic, buildGlobalTopic, createQuestpieQueryOptions };
500
+ export { applyRealtimeFindEvent, applyRealtimeScalarEvent, applyRealtimeSingleEvent, buildCollectionTopic, buildGlobalTopic, createQuestpieQueryOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@questpie/tanstack-query",
3
- "version": "3.16.0",
3
+ "version": "3.18.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/questpie/questpie.git",
@@ -32,15 +32,17 @@
32
32
  },
33
33
  "scripts": {
34
34
  "build": "tsdown",
35
- "check-types": "tsc --noEmit"
35
+ "check-types": "tsc --noEmit",
36
+ "test": "bun test"
36
37
  },
37
38
  "devDependencies": {
38
39
  "bun-types": "latest",
40
+ "seroval": "1.5.4",
39
41
  "tsdown": "^0.18.3",
40
42
  "zod": "^4.2.1"
41
43
  },
42
44
  "peerDependencies": {
43
45
  "@tanstack/react-query": "^5.0.0",
44
- "questpie": "^3.0.0"
46
+ "questpie": "^3.18.0"
45
47
  }
46
48
  }