@orpc/tanstack-query 1.14.6 → 2.0.0-beta.2
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 +74 -86
- package/dist/index.d.mts +249 -151
- package/dist/index.d.ts +249 -151
- package/dist/index.mjs +398 -156
- package/package.json +17 -15
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getPathMeta } from '@orpc/contract';
|
|
2
|
+
import { sortPlugins, stringifyJSON, resolveMaybeOptionalOptions, intercept, toArray, isAsyncIteratorObject, bindMethods, getOrBind, get, isTypescriptObject } from '@orpc/shared';
|
|
3
|
+
import { RECURSIVE_CLIENT_UNWRAP_KEYS } from '@orpc/client';
|
|
2
4
|
import { skipToken } from '@tanstack/query-core';
|
|
3
5
|
|
|
4
6
|
function generateOperationKey(path, state = {}) {
|
|
@@ -9,27 +11,41 @@ function generateOperationKey(path, state = {}) {
|
|
|
9
11
|
}];
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
class CompositeRouterUtilsPlugin {
|
|
15
|
+
constructor(plugins = []) {
|
|
16
|
+
this.plugins = plugins;
|
|
17
|
+
this.plugins = sortPlugins(plugins);
|
|
18
|
+
}
|
|
19
|
+
name = "~composite";
|
|
20
|
+
init(options) {
|
|
21
|
+
for (const plugin of this.plugins) {
|
|
22
|
+
if (plugin.init) {
|
|
23
|
+
options = plugin.init(options);
|
|
24
|
+
}
|
|
16
25
|
}
|
|
17
|
-
|
|
26
|
+
return options;
|
|
27
|
+
}
|
|
28
|
+
initProcedureOptions(path, options) {
|
|
29
|
+
for (const plugin of this.plugins) {
|
|
30
|
+
if (plugin.initProcedureOptions) {
|
|
31
|
+
options = plugin.initProcedureOptions(path, options);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return options;
|
|
35
|
+
}
|
|
18
36
|
}
|
|
19
37
|
|
|
20
|
-
function
|
|
38
|
+
function liveQuery(queryFn) {
|
|
21
39
|
return async (context) => {
|
|
22
40
|
const stream = await queryFn(context);
|
|
23
41
|
let last;
|
|
24
42
|
for await (const chunk of stream) {
|
|
25
|
-
|
|
26
|
-
throw context.signal.reason;
|
|
27
|
-
}
|
|
43
|
+
context.signal?.throwIfAborted();
|
|
28
44
|
last = { chunk };
|
|
29
45
|
context.client.setQueryData(context.queryKey, chunk);
|
|
30
46
|
}
|
|
31
47
|
if (!last) {
|
|
32
|
-
throw new
|
|
48
|
+
throw new TypeError(
|
|
33
49
|
`Live query for ${stringifyJSON(context.queryKey)} did not yield any data. Ensure the query function returns an AsyncIterable with at least one chunk.`
|
|
34
50
|
);
|
|
35
51
|
}
|
|
@@ -37,7 +53,7 @@ function experimental_liveQuery(queryFn) {
|
|
|
37
53
|
};
|
|
38
54
|
}
|
|
39
55
|
|
|
40
|
-
function
|
|
56
|
+
function serializableStreamedQuery(queryFn, { refetchMode = "reset", maxChunks = Number.POSITIVE_INFINITY } = {}) {
|
|
41
57
|
return async (context) => {
|
|
42
58
|
const query = context.client.getQueryCache().find({ queryKey: context.queryKey, exact: true });
|
|
43
59
|
const hasPreviousData = !!query && query.state.data !== void 0;
|
|
@@ -93,199 +109,425 @@ function limitArraySize(items, maxSize) {
|
|
|
93
109
|
return items.slice(items.length - maxSize);
|
|
94
110
|
}
|
|
95
111
|
|
|
96
|
-
const OPERATION_CONTEXT_SYMBOL = Symbol("
|
|
112
|
+
const OPERATION_CONTEXT_SYMBOL = Symbol.for("ORPC_TANSTACK_QUERY_OPERATION_CONTEXT");
|
|
97
113
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
class ProcedureUtils {
|
|
115
|
+
constructor(path, client, options = {}) {
|
|
116
|
+
this.path = path;
|
|
117
|
+
this.options = options;
|
|
118
|
+
this.call = client;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Calling corresponding procedure client
|
|
122
|
+
*/
|
|
123
|
+
call;
|
|
124
|
+
/**
|
|
125
|
+
* Generate a **full matching** key for [Query Options](https://orpc.dev/docs/integrations/tanstack-query#query-options).
|
|
126
|
+
*/
|
|
127
|
+
queryKey(...rest) {
|
|
128
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
129
|
+
if (typeof this.options.queryKey === "function") {
|
|
130
|
+
optionsIn = this.options.queryKey(optionsIn);
|
|
131
|
+
} else if (this.options.queryKey) {
|
|
132
|
+
optionsIn = { ...this.options.queryKey, ...optionsIn };
|
|
133
|
+
}
|
|
134
|
+
const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { type: "query", input: optionsIn.input });
|
|
135
|
+
return queryKey;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generate options used for useQuery/useSuspenseQuery/prefetchQuery/...
|
|
139
|
+
*/
|
|
140
|
+
queryOptions(...rest) {
|
|
141
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
142
|
+
if (typeof this.options.queryOptions === "function") {
|
|
143
|
+
optionsIn = this.options.queryOptions(optionsIn);
|
|
144
|
+
} else if (this.options.queryOptions) {
|
|
145
|
+
optionsIn = { ...this.options.queryOptions, ...optionsIn };
|
|
146
|
+
}
|
|
147
|
+
const queryKey = this.queryKey(optionsIn);
|
|
148
|
+
return {
|
|
149
|
+
...optionsIn,
|
|
150
|
+
queryKey,
|
|
151
|
+
queryFn: (fnContext) => {
|
|
152
|
+
return intercept(
|
|
153
|
+
this.options.queryInterceptors,
|
|
154
|
+
{
|
|
155
|
+
path: this.path,
|
|
116
156
|
context: {
|
|
117
157
|
[OPERATION_CONTEXT_SYMBOL]: {
|
|
118
158
|
key: queryKey,
|
|
119
159
|
type: "query"
|
|
120
160
|
},
|
|
121
161
|
...optionsIn.context
|
|
162
|
+
},
|
|
163
|
+
input: optionsIn.input,
|
|
164
|
+
fnContext
|
|
165
|
+
},
|
|
166
|
+
({ context, input, fnContext: fnContext2 }) => {
|
|
167
|
+
if (input === skipToken || optionsIn.queryFn === skipToken) {
|
|
168
|
+
throw new Error("queryFn should not be called when skipToken used for skipping");
|
|
122
169
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
...optionsIn.input === skipToken ? { enabled: false } : {},
|
|
126
|
-
...optionsIn,
|
|
127
|
-
queryKey
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
experimental_streamedKey(...[optionsIn = {}]) {
|
|
131
|
-
optionsIn = { ...options.experimental_defaults?.experimental_streamedKey, ...optionsIn };
|
|
132
|
-
const queryKey = optionsIn.queryKey ?? generateOperationKey(options.path, { type: "streamed", input: optionsIn.input, fnOptions: optionsIn.queryFnOptions });
|
|
133
|
-
return queryKey;
|
|
134
|
-
},
|
|
135
|
-
experimental_streamedOptions(...[optionsIn = {}]) {
|
|
136
|
-
optionsIn = { ...options.experimental_defaults?.experimental_streamedOptions, ...optionsIn };
|
|
137
|
-
const queryKey = utils.experimental_streamedKey(optionsIn);
|
|
138
|
-
return {
|
|
139
|
-
queryFn: experimental_serializableStreamedQuery(
|
|
140
|
-
async ({ signal }) => {
|
|
141
|
-
if (optionsIn.input === skipToken) {
|
|
142
|
-
throw new Error("queryFn should not be called with skipToken used as input");
|
|
170
|
+
if (optionsIn.queryFn) {
|
|
171
|
+
return optionsIn.queryFn(fnContext2);
|
|
143
172
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
return this.call(input, { signal: fnContext2.signal, context });
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
...optionsIn.input === skipToken || optionsIn.queryFn === skipToken ? { enabled: false } : {}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Generate a **full matching** key for [Streamed Query Options](https://orpc.dev/docs/integrations/tanstack-query#streamed-query-options).
|
|
182
|
+
*/
|
|
183
|
+
streamedKey(...rest) {
|
|
184
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
185
|
+
if (typeof this.options.streamedKey === "function") {
|
|
186
|
+
optionsIn = this.options.streamedKey(optionsIn);
|
|
187
|
+
} else if (this.options.streamedKey) {
|
|
188
|
+
optionsIn = { ...this.options.streamedKey, ...optionsIn };
|
|
189
|
+
}
|
|
190
|
+
const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { type: "streamed", input: optionsIn.input, fnOptions: optionsIn.queryFnOptions });
|
|
191
|
+
return queryKey;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Configure queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
|
|
195
|
+
* This is built on [TanStack Query streamedQuery](https://tanstack.com/query/latest/docs/reference/streamedQuery)
|
|
196
|
+
* and works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
|
|
197
|
+
*/
|
|
198
|
+
streamedOptions(...rest) {
|
|
199
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
200
|
+
if (typeof this.options.streamedOptions === "function") {
|
|
201
|
+
optionsIn = this.options.streamedOptions(optionsIn);
|
|
202
|
+
} else if (this.options.streamedOptions) {
|
|
203
|
+
optionsIn = { ...this.options.streamedOptions, ...optionsIn };
|
|
204
|
+
}
|
|
205
|
+
const queryKey = this.streamedKey(optionsIn);
|
|
206
|
+
return {
|
|
207
|
+
...optionsIn,
|
|
208
|
+
queryKey,
|
|
209
|
+
queryFn: (fnContext) => {
|
|
210
|
+
return intercept(
|
|
211
|
+
toArray(this.options.streamedInterceptors),
|
|
212
|
+
{
|
|
213
|
+
path: this.path,
|
|
214
|
+
context: {
|
|
215
|
+
[OPERATION_CONTEXT_SYMBOL]: {
|
|
216
|
+
key: queryKey,
|
|
217
|
+
type: "streamed"
|
|
218
|
+
},
|
|
219
|
+
...optionsIn.context
|
|
220
|
+
},
|
|
221
|
+
input: optionsIn.input,
|
|
222
|
+
fnContext
|
|
158
223
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (optionsIn.input === skipToken) {
|
|
177
|
-
throw new Error("queryFn should not be called with skipToken used as input");
|
|
224
|
+
({ context, fnContext: fnContext2, input }) => {
|
|
225
|
+
if (input === skipToken || optionsIn.queryFn === skipToken) {
|
|
226
|
+
throw new Error("queryFn should not be called when skipToken used for skipping");
|
|
227
|
+
}
|
|
228
|
+
if (optionsIn.queryFn) {
|
|
229
|
+
return optionsIn.queryFn(fnContext2);
|
|
230
|
+
}
|
|
231
|
+
return serializableStreamedQuery(
|
|
232
|
+
async (queryContext) => {
|
|
233
|
+
const output = await this.call(input, { signal: queryContext.signal, context });
|
|
234
|
+
if (!isAsyncIteratorObject(output)) {
|
|
235
|
+
throw new Error("streamedQuery requires an event iterator output");
|
|
236
|
+
}
|
|
237
|
+
return output;
|
|
238
|
+
},
|
|
239
|
+
optionsIn.queryFnOptions
|
|
240
|
+
)(fnContext2);
|
|
178
241
|
}
|
|
179
|
-
|
|
180
|
-
|
|
242
|
+
);
|
|
243
|
+
},
|
|
244
|
+
...optionsIn.input === skipToken || optionsIn.queryFn === skipToken ? { enabled: false } : {}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Generate a **full matching** key for [Live Query Options](https://orpc.dev/docs/integrations/tanstack-query#live-query-options).
|
|
249
|
+
*/
|
|
250
|
+
liveKey(...rest) {
|
|
251
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
252
|
+
if (typeof this.options.liveKey === "function") {
|
|
253
|
+
optionsIn = this.options.liveKey(optionsIn);
|
|
254
|
+
} else if (this.options.liveKey) {
|
|
255
|
+
optionsIn = { ...this.options.liveKey, ...optionsIn };
|
|
256
|
+
}
|
|
257
|
+
const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { type: "live", input: optionsIn.input });
|
|
258
|
+
return queryKey;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Configure live queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
|
|
262
|
+
* Unlike `.streamedOptions` which accumulates chunks, live queries replace the entire result with each new chunk received.
|
|
263
|
+
* Works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
|
|
264
|
+
*/
|
|
265
|
+
liveOptions(...rest) {
|
|
266
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
267
|
+
if (typeof this.options.liveOptions === "function") {
|
|
268
|
+
optionsIn = this.options.liveOptions(optionsIn);
|
|
269
|
+
} else if (this.options.liveOptions) {
|
|
270
|
+
optionsIn = { ...this.options.liveOptions, ...optionsIn };
|
|
271
|
+
}
|
|
272
|
+
const queryKey = this.liveKey(optionsIn);
|
|
273
|
+
return {
|
|
274
|
+
...optionsIn,
|
|
275
|
+
queryKey,
|
|
276
|
+
queryFn: (fnContext) => {
|
|
277
|
+
return intercept(
|
|
278
|
+
toArray(this.options.liveInterceptors),
|
|
279
|
+
{
|
|
280
|
+
path: this.path,
|
|
181
281
|
context: {
|
|
182
282
|
[OPERATION_CONTEXT_SYMBOL]: {
|
|
183
283
|
key: queryKey,
|
|
184
284
|
type: "live"
|
|
185
285
|
},
|
|
186
286
|
...optionsIn.context
|
|
287
|
+
},
|
|
288
|
+
input: optionsIn.input,
|
|
289
|
+
fnContext
|
|
290
|
+
},
|
|
291
|
+
({ fnContext: fnContext2, input, context }) => {
|
|
292
|
+
if (input === skipToken || optionsIn.queryFn === skipToken) {
|
|
293
|
+
throw new Error("queryFn should not be called when skipToken used for skipping");
|
|
187
294
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const queryKey = optionsIn.queryKey ?? generateOperationKey(options.path, {
|
|
202
|
-
type: "infinite",
|
|
203
|
-
input: optionsIn.input === skipToken ? skipToken : optionsIn.input(optionsIn.initialPageParam)
|
|
204
|
-
});
|
|
205
|
-
return queryKey;
|
|
206
|
-
},
|
|
207
|
-
infiniteOptions(optionsIn) {
|
|
208
|
-
optionsIn = { ...options.experimental_defaults?.infiniteOptions, ...optionsIn };
|
|
209
|
-
const queryKey = utils.infiniteKey(optionsIn);
|
|
210
|
-
return {
|
|
211
|
-
queryFn: ({ pageParam, signal }) => {
|
|
212
|
-
if (optionsIn.input === skipToken) {
|
|
213
|
-
throw new Error("queryFn should not be called with skipToken used as input");
|
|
295
|
+
if (optionsIn.queryFn) {
|
|
296
|
+
return optionsIn.queryFn(fnContext2);
|
|
297
|
+
}
|
|
298
|
+
return liveQuery(async (queryContext) => {
|
|
299
|
+
const output = await this.call(input, {
|
|
300
|
+
signal: queryContext.signal,
|
|
301
|
+
context
|
|
302
|
+
});
|
|
303
|
+
if (!isAsyncIteratorObject(output)) {
|
|
304
|
+
throw new Error("liveQuery requires an event iterator output");
|
|
305
|
+
}
|
|
306
|
+
return output;
|
|
307
|
+
})(fnContext2);
|
|
214
308
|
}
|
|
215
|
-
|
|
216
|
-
|
|
309
|
+
);
|
|
310
|
+
},
|
|
311
|
+
...optionsIn.input === skipToken || optionsIn.queryFn === skipToken ? { enabled: false } : {}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Generate a **full matching** key for [Infinite Query Options](https://orpc.dev/docs/integrations/tanstack-query#infinite-query-options).
|
|
316
|
+
*/
|
|
317
|
+
infiniteKey(optionsIn) {
|
|
318
|
+
if (typeof this.options.infiniteKey === "function") {
|
|
319
|
+
optionsIn = this.options.infiniteKey(optionsIn);
|
|
320
|
+
} else if (this.options.infiniteKey) {
|
|
321
|
+
optionsIn = { ...this.options.infiniteKey, ...optionsIn };
|
|
322
|
+
}
|
|
323
|
+
const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, {
|
|
324
|
+
type: "infinite",
|
|
325
|
+
input: optionsIn.input === skipToken ? skipToken : optionsIn.input(optionsIn.initialPageParam)
|
|
326
|
+
});
|
|
327
|
+
return queryKey;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Generate options used for useInfiniteQuery/useSuspenseInfiniteQuery/prefetchInfiniteQuery/...
|
|
331
|
+
*/
|
|
332
|
+
infiniteOptions(optionsIn) {
|
|
333
|
+
if (typeof this.options.infiniteOptions === "function") {
|
|
334
|
+
optionsIn = this.options.infiniteOptions(optionsIn);
|
|
335
|
+
} else if (this.options.infiniteOptions) {
|
|
336
|
+
optionsIn = { ...this.options.infiniteOptions, ...optionsIn };
|
|
337
|
+
}
|
|
338
|
+
const queryKey = this.infiniteKey(optionsIn);
|
|
339
|
+
return {
|
|
340
|
+
...optionsIn,
|
|
341
|
+
queryKey,
|
|
342
|
+
queryFn: (fnContext) => {
|
|
343
|
+
return intercept(
|
|
344
|
+
toArray(this.options.infiniteInterceptors),
|
|
345
|
+
{
|
|
346
|
+
path: this.path,
|
|
217
347
|
context: {
|
|
218
348
|
[OPERATION_CONTEXT_SYMBOL]: {
|
|
219
349
|
key: queryKey,
|
|
220
350
|
type: "infinite"
|
|
221
351
|
},
|
|
222
352
|
...optionsIn.context
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
},
|
|
226
|
-
...optionsIn.input === skipToken ? { enabled: false } : {},
|
|
227
|
-
...optionsIn,
|
|
228
|
-
queryKey
|
|
229
|
-
};
|
|
230
|
-
},
|
|
231
|
-
mutationKey(...[optionsIn = {}]) {
|
|
232
|
-
optionsIn = { ...options.experimental_defaults?.mutationKey, ...optionsIn };
|
|
233
|
-
const mutationKey = optionsIn.mutationKey ?? generateOperationKey(options.path, { type: "mutation" });
|
|
234
|
-
return mutationKey;
|
|
235
|
-
},
|
|
236
|
-
mutationOptions(...[optionsIn = {}]) {
|
|
237
|
-
optionsIn = { ...options.experimental_defaults?.mutationOptions, ...optionsIn };
|
|
238
|
-
const mutationKey = utils.mutationKey(optionsIn);
|
|
239
|
-
return {
|
|
240
|
-
mutationFn: (input) => client(input, {
|
|
241
|
-
context: {
|
|
242
|
-
[OPERATION_CONTEXT_SYMBOL]: {
|
|
243
|
-
key: mutationKey,
|
|
244
|
-
type: "mutation"
|
|
245
353
|
},
|
|
246
|
-
|
|
354
|
+
input: optionsIn.input === skipToken ? skipToken : optionsIn.input(fnContext.pageParam),
|
|
355
|
+
fnContext
|
|
356
|
+
},
|
|
357
|
+
({ context, input, fnContext: fnContext2 }) => {
|
|
358
|
+
if (input === skipToken || optionsIn.queryFn === skipToken) {
|
|
359
|
+
throw new Error("queryFn should not be called when skipToken used for skipping");
|
|
360
|
+
}
|
|
361
|
+
if (optionsIn.queryFn) {
|
|
362
|
+
return optionsIn.queryFn(fnContext2);
|
|
363
|
+
}
|
|
364
|
+
return this.call(input, { signal: fnContext2.signal, context });
|
|
247
365
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
366
|
+
);
|
|
367
|
+
},
|
|
368
|
+
...optionsIn.input === skipToken || optionsIn.queryFn === skipToken ? { enabled: false } : {}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Generate a **full matching** key for [Mutation Options](https://orpc.dev/docs/integrations/tanstack-query#mutation-options).
|
|
373
|
+
*/
|
|
374
|
+
mutationKey(optionsIn = {}) {
|
|
375
|
+
if (typeof this.options.mutationKey === "function") {
|
|
376
|
+
optionsIn = this.options.mutationKey(optionsIn);
|
|
377
|
+
} else if (this.options.mutationKey) {
|
|
378
|
+
optionsIn = { ...this.options.mutationKey, ...optionsIn };
|
|
252
379
|
}
|
|
253
|
-
|
|
254
|
-
|
|
380
|
+
const mutationKey = optionsIn.mutationKey ?? generateOperationKey(this.path, { type: "mutation" });
|
|
381
|
+
return mutationKey;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Generate options used for useMutation/...
|
|
385
|
+
*/
|
|
386
|
+
mutationOptions(...rest) {
|
|
387
|
+
let optionsIn = resolveMaybeOptionalOptions(rest);
|
|
388
|
+
if (typeof this.options.mutationOptions === "function") {
|
|
389
|
+
optionsIn = this.options.mutationOptions(optionsIn);
|
|
390
|
+
} else if (this.options.mutationOptions) {
|
|
391
|
+
optionsIn = { ...this.options.mutationOptions, ...optionsIn };
|
|
392
|
+
}
|
|
393
|
+
const mutationKey = this.mutationKey(optionsIn);
|
|
394
|
+
return {
|
|
395
|
+
...optionsIn,
|
|
396
|
+
mutationKey,
|
|
397
|
+
mutationFn: (input, fnContext) => {
|
|
398
|
+
return intercept(
|
|
399
|
+
toArray(this.options.mutationInterceptors),
|
|
400
|
+
{
|
|
401
|
+
path: this.path,
|
|
402
|
+
context: {
|
|
403
|
+
[OPERATION_CONTEXT_SYMBOL]: {
|
|
404
|
+
key: mutationKey,
|
|
405
|
+
type: "mutation"
|
|
406
|
+
},
|
|
407
|
+
...optionsIn.context
|
|
408
|
+
},
|
|
409
|
+
fnContext,
|
|
410
|
+
input
|
|
411
|
+
},
|
|
412
|
+
({ input: input2, fnContext: fnContext2, context }) => {
|
|
413
|
+
if (optionsIn.mutationFn) {
|
|
414
|
+
return optionsIn.mutationFn(input2, fnContext2);
|
|
415
|
+
}
|
|
416
|
+
return this.call(input2, { context });
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
}
|
|
255
422
|
}
|
|
256
423
|
|
|
424
|
+
class SharedRouterUtils {
|
|
425
|
+
constructor(path) {
|
|
426
|
+
this.path = path;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
|
|
430
|
+
*/
|
|
431
|
+
key(options = {}) {
|
|
432
|
+
return generateOperationKey(this.path, options);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
257
435
|
function createRouterUtils(client, options = {}) {
|
|
436
|
+
const plugin = new CompositeRouterUtilsPlugin(options.plugins);
|
|
437
|
+
options = plugin.init(options);
|
|
438
|
+
return createRouterUtilsInternal(client, options, plugin);
|
|
439
|
+
}
|
|
440
|
+
function createRouterUtilsInternal(client, options = {}, plugin) {
|
|
258
441
|
const path = toArray(options.path);
|
|
259
|
-
const
|
|
260
|
-
const procedureUtils =
|
|
442
|
+
const sharedUtils = bindMethods(new SharedRouterUtils(path));
|
|
443
|
+
const procedureUtils = typeof client === "function" && (options.scoped === void 0 || isProcedureUtilsOptions(options.scoped)) ? bindMethods(new ProcedureUtils(
|
|
261
444
|
path,
|
|
262
|
-
|
|
263
|
-
|
|
445
|
+
client,
|
|
446
|
+
plugin.initProcedureOptions(path, {
|
|
447
|
+
...options.scoped,
|
|
448
|
+
queryInterceptors: [...toArray(options.queryInterceptors), ...toArray(options.scoped?.queryInterceptors)],
|
|
449
|
+
streamedInterceptors: [...toArray(options.streamedInterceptors), ...toArray(options.scoped?.streamedInterceptors)],
|
|
450
|
+
liveInterceptors: [...toArray(options.liveInterceptors), ...toArray(options.scoped?.liveInterceptors)],
|
|
451
|
+
infiniteInterceptors: [...toArray(options.infiniteInterceptors), ...toArray(options.scoped?.infiniteInterceptors)],
|
|
452
|
+
mutationInterceptors: [...toArray(options.mutationInterceptors), ...toArray(options.scoped?.mutationInterceptors)]
|
|
453
|
+
})
|
|
454
|
+
)) : void 0;
|
|
264
455
|
const recursive = new Proxy({
|
|
265
|
-
...
|
|
456
|
+
...sharedUtils,
|
|
266
457
|
...procedureUtils
|
|
267
458
|
}, {
|
|
268
459
|
get(target, prop) {
|
|
269
|
-
const value =
|
|
270
|
-
|
|
460
|
+
const value = getOrBind(target, prop);
|
|
461
|
+
const nextClient = get(client, [prop]);
|
|
462
|
+
if (typeof prop !== "string" || RECURSIVE_CLIENT_UNWRAP_KEYS.has(prop) || !isTypescriptObject(nextClient)) {
|
|
271
463
|
return value;
|
|
272
464
|
}
|
|
273
|
-
const nextUtils =
|
|
465
|
+
const nextUtils = createRouterUtilsInternal(nextClient, {
|
|
274
466
|
...options,
|
|
275
467
|
path: [...path, prop],
|
|
276
|
-
|
|
277
|
-
});
|
|
468
|
+
scoped: get(options.scoped, [prop])
|
|
469
|
+
}, plugin);
|
|
278
470
|
if (typeof value !== "function") {
|
|
279
471
|
return nextUtils;
|
|
280
472
|
}
|
|
281
473
|
return new Proxy(value, {
|
|
282
|
-
get(
|
|
283
|
-
|
|
474
|
+
get(target2, prop2) {
|
|
475
|
+
if (typeof prop2 !== "string" || RECURSIVE_CLIENT_UNWRAP_KEYS.has(prop2)) {
|
|
476
|
+
return getOrBind(target2, prop2);
|
|
477
|
+
}
|
|
478
|
+
return getOrBind(nextUtils, prop2);
|
|
284
479
|
}
|
|
285
480
|
});
|
|
286
481
|
}
|
|
287
482
|
});
|
|
288
483
|
return recursive;
|
|
289
484
|
}
|
|
485
|
+
function isProcedureUtilsOptions(value) {
|
|
486
|
+
if (!isTypescriptObject(value)) {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
if (value.queryInterceptors !== void 0 && !Array.isArray(value.queryInterceptors)) {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
if (value.streamedInterceptors !== void 0 && !Array.isArray(value.streamedInterceptors)) {
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
if (value.liveInterceptors !== void 0 && !Array.isArray(value.liveInterceptors)) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
if (value.infiniteInterceptors !== void 0 && !Array.isArray(value.infiniteInterceptors)) {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
if (value.mutationInterceptors !== void 0 && !Array.isArray(value.mutationInterceptors)) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function createContractUtilsFactory(caller, options) {
|
|
508
|
+
return (procedure) => {
|
|
509
|
+
const path = getPathMeta(procedure);
|
|
510
|
+
if (!path) {
|
|
511
|
+
throw new TypeError(
|
|
512
|
+
"ContractUtilsFactory: procedure contract must define `meta.path` that matches its path in the root router contract."
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
const scoped = get(options.scoped, path);
|
|
516
|
+
if (scoped !== void 0 && (scoped === null || typeof scoped !== "object")) {
|
|
517
|
+
throw new TypeError(
|
|
518
|
+
`ContractUtilsFactory: "scoped" at path "${path.join(".")}" must be an object or undefined, got "${scoped}".`
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
const client = (...rest) => caller(procedure, ...rest);
|
|
522
|
+
return createRouterUtils(client, {
|
|
523
|
+
...options,
|
|
524
|
+
scoped,
|
|
525
|
+
path: [...toArray(options.path), ...path]
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
function createContractJsonifiedUtilsFactory(caller, options) {
|
|
530
|
+
return createContractUtilsFactory(caller, options);
|
|
531
|
+
}
|
|
290
532
|
|
|
291
|
-
export { OPERATION_CONTEXT_SYMBOL, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL,
|
|
533
|
+
export { OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedRouterUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, serializableStreamedQuery };
|