@falcondev-oss/trpc-vue-query 0.4.2 → 0.5.0-rc.1

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
@@ -20,9 +20,10 @@ pnpm add @falcondev-oss/trpc-vue-query
20
20
 
21
21
  ```ts
22
22
  import { createTRPCVueQueryClient } from '@falcondev-oss/trpc-vue-query'
23
- import type { AppRouter } from '../your_server/trpc'
24
23
  import { VueQueryPlugin, useQueryClient } from '@tanstack/vue-query'
25
24
 
25
+ import type { AppRouter } from '../your_server/trpc'
26
+
26
27
  app.use(VueQueryPlugin)
27
28
  app.use({
28
29
  install(app) {
@@ -45,6 +46,7 @@ app.use({
45
46
 
46
47
  ```ts
47
48
  import { createTRPCVueQueryClient } from '@falcondev-oss/trpc-vue-query'
49
+
48
50
  import type { AppRouter } from '../your_server/trpc'
49
51
 
50
52
  export function useTRPC() {
@@ -58,6 +60,7 @@ export function useTRPC() {
58
60
  <script lang="ts" setup>
59
61
  const { data: greeting } = useTRPC().hello.useQuery({ name: 'World' })
60
62
  </script>
63
+
61
64
  <template>
62
65
  <div>
63
66
  <h1>{{ greeting }}</h1>
@@ -102,7 +105,7 @@ const { mutate: updateGreeting } = useTRPC().hello.update.useMutation({
102
105
  <template>
103
106
  <div>
104
107
  <input v-model="name" type="text" />
105
- <button @click="updateGreeting({ name })">Update greeting</button>
108
+ <button @click="() => updateGreeting({ name })">Update greeting</button>
106
109
  </div>
107
110
  </template>
108
111
  ```
@@ -115,6 +118,7 @@ Setup `trpc-nuxt` as described in their [documentation](https://trpc-nuxt.vercel
115
118
  import { createTRPCVueQueryClient } from '@falcondev-oss/trpc-vue-query'
116
119
  import { useQueryClient } from '@tanstack/vue-query'
117
120
  import { httpBatchLink } from 'trpc-nuxt/client'
121
+
118
122
  import type { AppRouter } from '~/server/trpc/routers'
119
123
 
120
124
  export default defineNuxtPlugin(() => {
@@ -148,4 +152,4 @@ export function useTRPC() {
148
152
 
149
153
  ## Acknowledgements
150
154
 
151
- Huge thanks to [Robert Soriano](https://github.com/wobsoriano) for creating `nuxt-trpc`! We just adapted his work to work with Vue Query.
155
+ Huge thanks to [Robert Soriano](https://github.com/wobsoriano) for creating `trpc-nuxt`! We just adapted his work to work with Vue Query.
package/dist/index.cjs CHANGED
@@ -25,63 +25,123 @@ __export(src_exports, {
25
25
  module.exports = __toCommonJS(src_exports);
26
26
  var import_vue_query = require("@tanstack/vue-query");
27
27
  var import_client = require("@trpc/client");
28
- var import_shared = require("@trpc/server/shared");
28
+ var import_server = require("@trpc/server");
29
+ var import_unstable_core_do_not_import = require("@trpc/server/unstable-core-do-not-import");
29
30
  var import_core = require("@vueuse/core");
30
31
  var import_vue = require("vue");
31
- function getQueryKey(path, input) {
32
- return input === void 0 ? path : [...path, input];
32
+ function getQueryKey(path, input, type) {
33
+ const splitPath = path.flatMap((part) => part.split("."));
34
+ if (input === void 0 && !type) {
35
+ return splitPath.length > 0 ? [splitPath] : [];
36
+ }
37
+ return [
38
+ splitPath,
39
+ {
40
+ ...input !== void 0 && input !== import_vue_query.skipToken && { input },
41
+ ...type && { type }
42
+ }
43
+ ];
33
44
  }
34
45
  function maybeToRefs(obj) {
35
46
  return (0, import_vue.isReactive)(obj) ? (0, import_core.toRefs)(obj) : (0, import_core.toRefs)((0, import_core.toRef)(obj));
36
47
  }
37
- function createVueQueryProxyDecoration(name, client, queryClient) {
38
- return (0, import_shared.createRecursiveProxy)((opts) => {
39
- const args = opts.args;
40
- const path = [name, ...opts.path];
41
- const lastProperty = path.pop();
48
+ function createVueQueryProxyDecoration(name, trpc, queryClient) {
49
+ return (0, import_unstable_core_do_not_import.createRecursiveProxy)(({ args, path: _path }) => {
50
+ const path = [name, ..._path];
51
+ const prop = path.pop();
42
52
  const joinedPath = path.join(".");
43
- const [firstParam, secondParam] = args;
44
- if (lastProperty === "_def") {
53
+ const [firstArg, ...rest] = args;
54
+ const opts = rest[0] || {};
55
+ if (prop === "_def") {
45
56
  return { path };
46
57
  }
47
- if (lastProperty === "useQuery") {
48
- const { trpc, ...queryOptions } = secondParam || {};
58
+ if (prop === "query") {
59
+ return trpc.query(joinedPath, firstArg, opts);
60
+ }
61
+ if (prop === "useQuery") {
62
+ const { trpc: trpcOptions, ...queryOptions } = opts;
49
63
  return (0, import_vue_query.useQuery)({
50
- queryKey: (0, import_vue.computed)(() => getQueryKey(path, (0, import_core.toValue)(firstParam))),
51
- queryFn: ({ queryKey, signal }) => client[joinedPath].query(queryKey.at(-1), {
64
+ queryKey: (0, import_vue.computed)(() => getQueryKey(path, (0, import_core.toValue)(firstArg), "query")),
65
+ queryFn: async ({ queryKey, signal }) => trpc.query(joinedPath, queryKey[1]?.input, {
52
66
  signal,
53
- ...trpc
67
+ ...trpcOptions
54
68
  }),
55
69
  ...maybeToRefs(queryOptions)
56
70
  });
57
71
  }
58
- if (lastProperty === "invalidate") {
72
+ if (prop === "invalidate") {
59
73
  return queryClient.invalidateQueries({
60
- queryKey: getQueryKey(path, (0, import_core.toValue)(firstParam))
74
+ queryKey: getQueryKey(path, (0, import_core.toValue)(firstArg), "query")
61
75
  });
62
76
  }
63
- if (lastProperty === "setQueryData") {
64
- return queryClient.setQueryData(getQueryKey(path, (0, import_core.toValue)(secondParam)), firstParam);
77
+ if (prop === "setQueryData") {
78
+ return queryClient.setQueryData(getQueryKey(path, (0, import_core.toValue)(opts), "query"), firstArg);
65
79
  }
66
- if (lastProperty === "key") {
67
- return getQueryKey(path, (0, import_core.toValue)(firstParam));
80
+ if (prop === "key") {
81
+ return getQueryKey(path, (0, import_core.toValue)(firstArg), "query");
68
82
  }
69
- if (lastProperty === "useMutation") {
70
- const { trpc, ...mutationOptions } = firstParam || {};
83
+ if (prop === "mutate") {
84
+ return trpc.mutation(joinedPath, firstArg, opts);
85
+ }
86
+ if (prop === "useMutation") {
87
+ const { trpc: trpcOptions, ...mutationOptions } = firstArg || {};
71
88
  return (0, import_vue_query.useMutation)({
72
- mutationFn: (payload) => client[joinedPath].mutate(payload, {
73
- ...trpc
89
+ mutationKey: (0, import_vue.computed)(() => getQueryKey(path, void 0)),
90
+ mutationFn: async (payload) => trpc.mutation(joinedPath, payload, {
91
+ ...trpcOptions
74
92
  }),
75
93
  ...maybeToRefs(mutationOptions)
76
94
  });
77
95
  }
78
- return client[joinedPath][lastProperty](...args);
96
+ if (prop === "subscribe") {
97
+ return trpc.subscription(joinedPath, firstArg, opts);
98
+ }
99
+ if (prop === "useSubscription") {
100
+ const inputData = (0, import_core.toRef)(firstArg);
101
+ const subscription = (0, import_vue.shallowRef)();
102
+ (0, import_vue.watch)(
103
+ inputData,
104
+ () => {
105
+ subscription.value?.unsubscribe();
106
+ subscription.value = trpc.subscription(joinedPath, inputData.value, {
107
+ ...opts
108
+ });
109
+ },
110
+ { immediate: true }
111
+ );
112
+ (0, import_vue.onScopeDispose)(() => {
113
+ subscription.value?.unsubscribe();
114
+ }, true);
115
+ return subscription.value;
116
+ }
117
+ if (prop === "useInfiniteQuery") {
118
+ const { trpc: trpcOptions, ...queryOptions } = opts;
119
+ return (0, import_vue_query.useInfiniteQuery)({
120
+ queryKey: (0, import_vue.computed)(() => getQueryKey(path, (0, import_core.toValue)(firstArg), "infinite")),
121
+ queryFn: async ({ queryKey, pageParam, signal }) => trpc.query(
122
+ joinedPath,
123
+ {
124
+ ...queryKey[1]?.input,
125
+ cursor: pageParam
126
+ },
127
+ {
128
+ signal,
129
+ ...trpcOptions
130
+ }
131
+ ),
132
+ ...maybeToRefs(queryOptions)
133
+ });
134
+ }
135
+ throw new Error(`Method '.${prop}()' not supported`);
79
136
  });
80
137
  }
81
- function createTRPCVueQueryClient(opts) {
82
- const client = (0, import_client.createTRPCProxyClient)(opts.trpc);
83
- const decoratedClient = (0, import_shared.createFlatProxy)((key) => {
84
- return createVueQueryProxyDecoration(key, client, opts.queryClient);
138
+ function createTRPCVueQueryClient({
139
+ trpc,
140
+ queryClient
141
+ }) {
142
+ const client = (0, import_client.createTRPCUntypedClient)(trpc);
143
+ const decoratedClient = (0, import_server.createTRPCFlatProxy)((key) => {
144
+ return createVueQueryProxyDecoration(key, client, queryClient);
85
145
  });
86
146
  return decoratedClient;
87
147
  }
package/dist/index.d.cts CHANGED
@@ -1,49 +1,61 @@
1
- import { QueryKey, UseQueryOptions, UseQueryReturnType, QueryClient, UseMutationOptions, UseMutationReturnType } from '@tanstack/vue-query';
2
- import { TRPCClientErrorLike, TRPCRequestOptions, CreateTRPCClientOptions } from '@trpc/client';
3
- import { ProcedureRouterRecord, AnyRouter, AnyProcedure, AnyQueryProcedure, inferProcedureInput, AnyMutationProcedure, AnySubscriptionProcedure, ProcedureArgs, inferProcedureOutput } from '@trpc/server';
4
- import { inferObservableValue, Unsubscribable } from '@trpc/server/observable';
5
- import { inferTransformedProcedureOutput } from '@trpc/server/shared';
1
+ import { QueryKey, UseQueryOptions, UseQueryReturnType, QueryClient, InfiniteData, UseInfiniteQueryOptions, InitialPageParam, UseInfiniteQueryReturnType, UseMutationOptions, UseMutationReturnType } from '@tanstack/vue-query';
2
+ import { TRPCClientErrorLike, TRPCRequestOptions, OperationContext, CreateTRPCClientOptions } from '@trpc/client';
3
+ import { AnyTRPCRouter, AnyTRPCProcedure, AnyTRPCQueryProcedure, inferTransformedProcedureOutput, inferProcedureInput, AnyTRPCMutationProcedure, AnyTRPCSubscriptionProcedure, inferProcedureOutput } from '@trpc/server';
4
+ import { Unsubscribable } from '@trpc/server/observable';
5
+ import { ProcedureOptions } from '@trpc/server/unstable-core-do-not-import';
6
6
  import { MaybeRefOrGetter, UnwrapRef } from 'vue';
7
7
 
8
8
  type TRPCSubscriptionObserver<TValue, TError> = {
9
- onStarted: () => void;
9
+ onStarted: (opts: {
10
+ context: OperationContext | undefined;
11
+ }) => void;
10
12
  onData: (value: TValue) => void;
11
13
  onError: (err: TError) => void;
12
14
  onStopped: () => void;
13
15
  onComplete: () => void;
14
16
  };
15
- type Resolver<TProcedure extends AnyProcedure> = (...args: ProcedureArgs<TProcedure['_def']>) => Promise<inferTransformedProcedureOutput<TProcedure>>;
16
- type SubscriptionResolver<TProcedure extends AnyProcedure, TRouter extends AnyRouter> = (...args: [
17
- input: ProcedureArgs<TProcedure['_def']>[0],
18
- opts: ProcedureArgs<TProcedure['_def']>[1] & Partial<TRPCSubscriptionObserver<inferObservableValue<inferProcedureOutput<TProcedure>>, TRPCClientErrorLike<TRouter>>>
19
- ]) => Unsubscribable;
20
- type DecorateProcedure<TProcedure extends AnyProcedure, TRouter extends AnyRouter> = TProcedure extends AnyQueryProcedure ? {
21
- useQuery: <TQueryFnData = inferTransformedProcedureOutput<TProcedure>, TError = TRPCClientErrorLike<TProcedure>, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>>, 'queryKey'> & {
17
+ type Resolver<TRouter extends AnyTRPCRouter, TProcedure extends AnyTRPCProcedure> = (input: inferProcedureInput<TProcedure>, opts?: ProcedureOptions) => Promise<inferTransformedProcedureOutput<TRouter, TProcedure>>;
18
+ type SubscriptionResolver<TProcedure extends AnyTRPCProcedure, TRouter extends AnyTRPCRouter> = (input: inferProcedureInput<TProcedure>, opts: ProcedureOptions & Partial<TRPCSubscriptionObserver<inferProcedureOutput<TProcedure>, TRPCClientErrorLike<TRouter>>>) => Unsubscribable;
19
+ type DecorateProcedure<TProcedure extends AnyTRPCProcedure, TRouter extends AnyTRPCRouter> = TProcedure extends AnyTRPCQueryProcedure ? {
20
+ useQuery: <TQueryFnData = inferTransformedProcedureOutput<TRouter, TProcedure>, TError = TRPCClientErrorLike<TRouter>, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>>, 'queryKey'> & {
22
21
  trpc?: TRPCRequestOptions;
23
22
  queryKey?: TQueryKey;
24
23
  }>) => UseQueryReturnType<TData, TError>;
25
- query: Resolver<TProcedure>;
24
+ query: Resolver<TRouter, TProcedure>;
26
25
  invalidate: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => Promise<void>;
27
- setQueryData: (updater: inferTransformedProcedureOutput<TProcedure>, input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => ReturnType<QueryClient['setQueryData']>;
26
+ setQueryData: (updater: inferTransformedProcedureOutput<TRouter, TProcedure>, input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => ReturnType<QueryClient['setQueryData']>;
28
27
  key: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => QueryKey;
29
- } : TProcedure extends AnyMutationProcedure ? {
30
- mutate: Resolver<TProcedure>;
31
- useMutation: <TData = inferTransformedProcedureOutput<TProcedure>, TError = TRPCClientErrorLike<TProcedure>, TVariables = inferProcedureInput<TProcedure>, TContext = unknown>(opts?: MaybeRefOrGetter<UseMutationOptions<TData, TError, TVariables, TContext> & {
28
+ } & (TProcedure['_def']['$types']['input'] extends {
29
+ cursor?: infer CursorType;
30
+ } ? {
31
+ useInfiniteQuery: <TQueryFnData = inferTransformedProcedureOutput<TRouter, TProcedure>, TError = TRPCClientErrorLike<TRouter>, TData = InfiniteData<TQueryFnData>, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(input: MaybeRefOrGetter<Omit<inferProcedureInput<TProcedure>, 'cursor'>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>>, 'queryKey' | keyof InitialPageParam> & {
32
+ trpc?: TRPCRequestOptions;
33
+ queryKey?: TQueryKey;
34
+ } & (undefined extends TProcedure['_def']['$types']['input']['cursor'] ? Partial<InitialPageParam<CursorType>> : InitialPageParam<CursorType>)>) => UseInfiniteQueryReturnType<TData, TError>;
35
+ } : object) : TProcedure extends AnyTRPCMutationProcedure ? {
36
+ mutate: Resolver<TRouter, TProcedure>;
37
+ useMutation: <TData = inferTransformedProcedureOutput<TRouter, TProcedure>, TError = TRPCClientErrorLike<TRouter>, TVariables = inferProcedureInput<TProcedure>, TContext = unknown>(opts?: MaybeRefOrGetter<UseMutationOptions<TData, TError, TVariables, TContext> & {
32
38
  trpc?: TRPCRequestOptions;
33
39
  }>) => UseMutationReturnType<TData, TError, TVariables, TContext>;
34
- } : TProcedure extends AnySubscriptionProcedure ? {
40
+ } : TProcedure extends AnyTRPCSubscriptionProcedure ? {
35
41
  subscribe: SubscriptionResolver<TProcedure, TRouter>;
42
+ useSubscription: (input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts: ProcedureOptions & Partial<TRPCSubscriptionObserver<inferProcedureOutput<TProcedure>, TRPCClientErrorLike<TRouter>>>) => Unsubscribable;
36
43
  } : never;
37
44
  /**
38
45
  * @internal
39
46
  */
40
- type DecoratedProcedureRecord<TProcedures extends ProcedureRouterRecord, TRouter extends AnyRouter> = {
41
- [TKey in keyof TProcedures]: TProcedures[TKey] extends AnyRouter ? DecoratedProcedureRecord<TProcedures[TKey]['_def']['record'], TRouter> : TProcedures[TKey] extends AnyProcedure ? DecorateProcedure<TProcedures[TKey], TRouter> : never;
47
+ type DecoratedProcedureRecord<TProcedures extends Record<string, any>, TRouter extends AnyTRPCRouter> = {
48
+ [K in keyof TProcedures]: TProcedures[K] extends AnyTRPCProcedure ? DecorateProcedure<TProcedures[K], TRouter> : DecoratedProcedureRecord<TProcedures[K], TRouter>;
42
49
  };
43
50
 
44
- declare function createTRPCVueQueryClient<TRouter extends AnyRouter>(opts: {
51
+ type QueryType = 'query' | 'infinite';
52
+ type TRPCQueryKey = [readonly string[], {
53
+ input?: unknown;
54
+ type?: QueryType;
55
+ }?];
56
+ declare function createTRPCVueQueryClient<TRouter extends AnyTRPCRouter>({ trpc, queryClient, }: {
45
57
  queryClient: QueryClient;
46
58
  trpc: CreateTRPCClientOptions<TRouter>;
47
59
  }): DecoratedProcedureRecord<TRouter["_def"]["record"], TRouter>;
48
60
 
49
- export { createTRPCVueQueryClient };
61
+ export { type TRPCQueryKey, createTRPCVueQueryClient };
package/dist/index.d.ts CHANGED
@@ -1,49 +1,61 @@
1
- import { QueryKey, UseQueryOptions, UseQueryReturnType, QueryClient, UseMutationOptions, UseMutationReturnType } from '@tanstack/vue-query';
2
- import { TRPCClientErrorLike, TRPCRequestOptions, CreateTRPCClientOptions } from '@trpc/client';
3
- import { ProcedureRouterRecord, AnyRouter, AnyProcedure, AnyQueryProcedure, inferProcedureInput, AnyMutationProcedure, AnySubscriptionProcedure, ProcedureArgs, inferProcedureOutput } from '@trpc/server';
4
- import { inferObservableValue, Unsubscribable } from '@trpc/server/observable';
5
- import { inferTransformedProcedureOutput } from '@trpc/server/shared';
1
+ import { QueryKey, UseQueryOptions, UseQueryReturnType, QueryClient, InfiniteData, UseInfiniteQueryOptions, InitialPageParam, UseInfiniteQueryReturnType, UseMutationOptions, UseMutationReturnType } from '@tanstack/vue-query';
2
+ import { TRPCClientErrorLike, TRPCRequestOptions, OperationContext, CreateTRPCClientOptions } from '@trpc/client';
3
+ import { AnyTRPCRouter, AnyTRPCProcedure, AnyTRPCQueryProcedure, inferTransformedProcedureOutput, inferProcedureInput, AnyTRPCMutationProcedure, AnyTRPCSubscriptionProcedure, inferProcedureOutput } from '@trpc/server';
4
+ import { Unsubscribable } from '@trpc/server/observable';
5
+ import { ProcedureOptions } from '@trpc/server/unstable-core-do-not-import';
6
6
  import { MaybeRefOrGetter, UnwrapRef } from 'vue';
7
7
 
8
8
  type TRPCSubscriptionObserver<TValue, TError> = {
9
- onStarted: () => void;
9
+ onStarted: (opts: {
10
+ context: OperationContext | undefined;
11
+ }) => void;
10
12
  onData: (value: TValue) => void;
11
13
  onError: (err: TError) => void;
12
14
  onStopped: () => void;
13
15
  onComplete: () => void;
14
16
  };
15
- type Resolver<TProcedure extends AnyProcedure> = (...args: ProcedureArgs<TProcedure['_def']>) => Promise<inferTransformedProcedureOutput<TProcedure>>;
16
- type SubscriptionResolver<TProcedure extends AnyProcedure, TRouter extends AnyRouter> = (...args: [
17
- input: ProcedureArgs<TProcedure['_def']>[0],
18
- opts: ProcedureArgs<TProcedure['_def']>[1] & Partial<TRPCSubscriptionObserver<inferObservableValue<inferProcedureOutput<TProcedure>>, TRPCClientErrorLike<TRouter>>>
19
- ]) => Unsubscribable;
20
- type DecorateProcedure<TProcedure extends AnyProcedure, TRouter extends AnyRouter> = TProcedure extends AnyQueryProcedure ? {
21
- useQuery: <TQueryFnData = inferTransformedProcedureOutput<TProcedure>, TError = TRPCClientErrorLike<TProcedure>, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>>, 'queryKey'> & {
17
+ type Resolver<TRouter extends AnyTRPCRouter, TProcedure extends AnyTRPCProcedure> = (input: inferProcedureInput<TProcedure>, opts?: ProcedureOptions) => Promise<inferTransformedProcedureOutput<TRouter, TProcedure>>;
18
+ type SubscriptionResolver<TProcedure extends AnyTRPCProcedure, TRouter extends AnyTRPCRouter> = (input: inferProcedureInput<TProcedure>, opts: ProcedureOptions & Partial<TRPCSubscriptionObserver<inferProcedureOutput<TProcedure>, TRPCClientErrorLike<TRouter>>>) => Unsubscribable;
19
+ type DecorateProcedure<TProcedure extends AnyTRPCProcedure, TRouter extends AnyTRPCRouter> = TProcedure extends AnyTRPCQueryProcedure ? {
20
+ useQuery: <TQueryFnData = inferTransformedProcedureOutput<TRouter, TProcedure>, TError = TRPCClientErrorLike<TRouter>, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>>, 'queryKey'> & {
22
21
  trpc?: TRPCRequestOptions;
23
22
  queryKey?: TQueryKey;
24
23
  }>) => UseQueryReturnType<TData, TError>;
25
- query: Resolver<TProcedure>;
24
+ query: Resolver<TRouter, TProcedure>;
26
25
  invalidate: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => Promise<void>;
27
- setQueryData: (updater: inferTransformedProcedureOutput<TProcedure>, input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => ReturnType<QueryClient['setQueryData']>;
26
+ setQueryData: (updater: inferTransformedProcedureOutput<TRouter, TProcedure>, input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => ReturnType<QueryClient['setQueryData']>;
28
27
  key: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => QueryKey;
29
- } : TProcedure extends AnyMutationProcedure ? {
30
- mutate: Resolver<TProcedure>;
31
- useMutation: <TData = inferTransformedProcedureOutput<TProcedure>, TError = TRPCClientErrorLike<TProcedure>, TVariables = inferProcedureInput<TProcedure>, TContext = unknown>(opts?: MaybeRefOrGetter<UseMutationOptions<TData, TError, TVariables, TContext> & {
28
+ } & (TProcedure['_def']['$types']['input'] extends {
29
+ cursor?: infer CursorType;
30
+ } ? {
31
+ useInfiniteQuery: <TQueryFnData = inferTransformedProcedureOutput<TRouter, TProcedure>, TError = TRPCClientErrorLike<TRouter>, TData = InfiniteData<TQueryFnData>, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(input: MaybeRefOrGetter<Omit<inferProcedureInput<TProcedure>, 'cursor'>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>>, 'queryKey' | keyof InitialPageParam> & {
32
+ trpc?: TRPCRequestOptions;
33
+ queryKey?: TQueryKey;
34
+ } & (undefined extends TProcedure['_def']['$types']['input']['cursor'] ? Partial<InitialPageParam<CursorType>> : InitialPageParam<CursorType>)>) => UseInfiniteQueryReturnType<TData, TError>;
35
+ } : object) : TProcedure extends AnyTRPCMutationProcedure ? {
36
+ mutate: Resolver<TRouter, TProcedure>;
37
+ useMutation: <TData = inferTransformedProcedureOutput<TRouter, TProcedure>, TError = TRPCClientErrorLike<TRouter>, TVariables = inferProcedureInput<TProcedure>, TContext = unknown>(opts?: MaybeRefOrGetter<UseMutationOptions<TData, TError, TVariables, TContext> & {
32
38
  trpc?: TRPCRequestOptions;
33
39
  }>) => UseMutationReturnType<TData, TError, TVariables, TContext>;
34
- } : TProcedure extends AnySubscriptionProcedure ? {
40
+ } : TProcedure extends AnyTRPCSubscriptionProcedure ? {
35
41
  subscribe: SubscriptionResolver<TProcedure, TRouter>;
42
+ useSubscription: (input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts: ProcedureOptions & Partial<TRPCSubscriptionObserver<inferProcedureOutput<TProcedure>, TRPCClientErrorLike<TRouter>>>) => Unsubscribable;
36
43
  } : never;
37
44
  /**
38
45
  * @internal
39
46
  */
40
- type DecoratedProcedureRecord<TProcedures extends ProcedureRouterRecord, TRouter extends AnyRouter> = {
41
- [TKey in keyof TProcedures]: TProcedures[TKey] extends AnyRouter ? DecoratedProcedureRecord<TProcedures[TKey]['_def']['record'], TRouter> : TProcedures[TKey] extends AnyProcedure ? DecorateProcedure<TProcedures[TKey], TRouter> : never;
47
+ type DecoratedProcedureRecord<TProcedures extends Record<string, any>, TRouter extends AnyTRPCRouter> = {
48
+ [K in keyof TProcedures]: TProcedures[K] extends AnyTRPCProcedure ? DecorateProcedure<TProcedures[K], TRouter> : DecoratedProcedureRecord<TProcedures[K], TRouter>;
42
49
  };
43
50
 
44
- declare function createTRPCVueQueryClient<TRouter extends AnyRouter>(opts: {
51
+ type QueryType = 'query' | 'infinite';
52
+ type TRPCQueryKey = [readonly string[], {
53
+ input?: unknown;
54
+ type?: QueryType;
55
+ }?];
56
+ declare function createTRPCVueQueryClient<TRouter extends AnyTRPCRouter>({ trpc, queryClient, }: {
45
57
  queryClient: QueryClient;
46
58
  trpc: CreateTRPCClientOptions<TRouter>;
47
59
  }): DecoratedProcedureRecord<TRouter["_def"]["record"], TRouter>;
48
60
 
49
- export { createTRPCVueQueryClient };
61
+ export { type TRPCQueryKey, createTRPCVueQueryClient };
package/dist/index.mjs CHANGED
@@ -1,65 +1,130 @@
1
1
  // src/index.ts
2
- import { useMutation, useQuery } from "@tanstack/vue-query";
3
2
  import {
4
- createTRPCProxyClient
3
+ skipToken,
4
+ useInfiniteQuery,
5
+ useMutation,
6
+ useQuery
7
+ } from "@tanstack/vue-query";
8
+ import {
9
+ createTRPCUntypedClient
5
10
  } from "@trpc/client";
6
- import { createFlatProxy, createRecursiveProxy } from "@trpc/server/shared";
11
+ import { createTRPCFlatProxy } from "@trpc/server";
12
+ import { createRecursiveProxy } from "@trpc/server/unstable-core-do-not-import";
7
13
  import { toRef, toRefs, toValue } from "@vueuse/core";
8
- import { computed, isReactive } from "vue";
9
- function getQueryKey(path, input) {
10
- return input === void 0 ? path : [...path, input];
14
+ import { computed, isReactive, onScopeDispose, shallowRef, watch } from "vue";
15
+ function getQueryKey(path, input, type) {
16
+ const splitPath = path.flatMap((part) => part.split("."));
17
+ if (input === void 0 && !type) {
18
+ return splitPath.length > 0 ? [splitPath] : [];
19
+ }
20
+ return [
21
+ splitPath,
22
+ {
23
+ ...input !== void 0 && input !== skipToken && { input },
24
+ ...type && { type }
25
+ }
26
+ ];
11
27
  }
12
28
  function maybeToRefs(obj) {
13
29
  return isReactive(obj) ? toRefs(obj) : toRefs(toRef(obj));
14
30
  }
15
- function createVueQueryProxyDecoration(name, client, queryClient) {
16
- return createRecursiveProxy((opts) => {
17
- const args = opts.args;
18
- const path = [name, ...opts.path];
19
- const lastProperty = path.pop();
31
+ function createVueQueryProxyDecoration(name, trpc, queryClient) {
32
+ return createRecursiveProxy(({ args, path: _path }) => {
33
+ const path = [name, ..._path];
34
+ const prop = path.pop();
20
35
  const joinedPath = path.join(".");
21
- const [firstParam, secondParam] = args;
22
- if (lastProperty === "_def") {
36
+ const [firstArg, ...rest] = args;
37
+ const opts = rest[0] || {};
38
+ if (prop === "_def") {
23
39
  return { path };
24
40
  }
25
- if (lastProperty === "useQuery") {
26
- const { trpc, ...queryOptions } = secondParam || {};
41
+ if (prop === "query") {
42
+ return trpc.query(joinedPath, firstArg, opts);
43
+ }
44
+ if (prop === "useQuery") {
45
+ const { trpc: trpcOptions, ...queryOptions } = opts;
27
46
  return useQuery({
28
- queryKey: computed(() => getQueryKey(path, toValue(firstParam))),
29
- queryFn: ({ queryKey, signal }) => client[joinedPath].query(queryKey.at(-1), {
47
+ queryKey: computed(() => getQueryKey(path, toValue(firstArg), "query")),
48
+ queryFn: async ({ queryKey, signal }) => trpc.query(joinedPath, queryKey[1]?.input, {
30
49
  signal,
31
- ...trpc
50
+ ...trpcOptions
32
51
  }),
33
52
  ...maybeToRefs(queryOptions)
34
53
  });
35
54
  }
36
- if (lastProperty === "invalidate") {
55
+ if (prop === "invalidate") {
37
56
  return queryClient.invalidateQueries({
38
- queryKey: getQueryKey(path, toValue(firstParam))
57
+ queryKey: getQueryKey(path, toValue(firstArg), "query")
39
58
  });
40
59
  }
41
- if (lastProperty === "setQueryData") {
42
- return queryClient.setQueryData(getQueryKey(path, toValue(secondParam)), firstParam);
60
+ if (prop === "setQueryData") {
61
+ return queryClient.setQueryData(getQueryKey(path, toValue(opts), "query"), firstArg);
43
62
  }
44
- if (lastProperty === "key") {
45
- return getQueryKey(path, toValue(firstParam));
63
+ if (prop === "key") {
64
+ return getQueryKey(path, toValue(firstArg), "query");
46
65
  }
47
- if (lastProperty === "useMutation") {
48
- const { trpc, ...mutationOptions } = firstParam || {};
66
+ if (prop === "mutate") {
67
+ return trpc.mutation(joinedPath, firstArg, opts);
68
+ }
69
+ if (prop === "useMutation") {
70
+ const { trpc: trpcOptions, ...mutationOptions } = firstArg || {};
49
71
  return useMutation({
50
- mutationFn: (payload) => client[joinedPath].mutate(payload, {
51
- ...trpc
72
+ mutationKey: computed(() => getQueryKey(path, void 0)),
73
+ mutationFn: async (payload) => trpc.mutation(joinedPath, payload, {
74
+ ...trpcOptions
52
75
  }),
53
76
  ...maybeToRefs(mutationOptions)
54
77
  });
55
78
  }
56
- return client[joinedPath][lastProperty](...args);
79
+ if (prop === "subscribe") {
80
+ return trpc.subscription(joinedPath, firstArg, opts);
81
+ }
82
+ if (prop === "useSubscription") {
83
+ const inputData = toRef(firstArg);
84
+ const subscription = shallowRef();
85
+ watch(
86
+ inputData,
87
+ () => {
88
+ subscription.value?.unsubscribe();
89
+ subscription.value = trpc.subscription(joinedPath, inputData.value, {
90
+ ...opts
91
+ });
92
+ },
93
+ { immediate: true }
94
+ );
95
+ onScopeDispose(() => {
96
+ subscription.value?.unsubscribe();
97
+ }, true);
98
+ return subscription.value;
99
+ }
100
+ if (prop === "useInfiniteQuery") {
101
+ const { trpc: trpcOptions, ...queryOptions } = opts;
102
+ return useInfiniteQuery({
103
+ queryKey: computed(() => getQueryKey(path, toValue(firstArg), "infinite")),
104
+ queryFn: async ({ queryKey, pageParam, signal }) => trpc.query(
105
+ joinedPath,
106
+ {
107
+ ...queryKey[1]?.input,
108
+ cursor: pageParam
109
+ },
110
+ {
111
+ signal,
112
+ ...trpcOptions
113
+ }
114
+ ),
115
+ ...maybeToRefs(queryOptions)
116
+ });
117
+ }
118
+ throw new Error(`Method '.${prop}()' not supported`);
57
119
  });
58
120
  }
59
- function createTRPCVueQueryClient(opts) {
60
- const client = createTRPCProxyClient(opts.trpc);
61
- const decoratedClient = createFlatProxy((key) => {
62
- return createVueQueryProxyDecoration(key, client, opts.queryClient);
121
+ function createTRPCVueQueryClient({
122
+ trpc,
123
+ queryClient
124
+ }) {
125
+ const client = createTRPCUntypedClient(trpc);
126
+ const decoratedClient = createTRPCFlatProxy((key) => {
127
+ return createVueQueryProxyDecoration(key, client, queryClient);
63
128
  });
64
129
  return decoratedClient;
65
130
  }
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@falcondev-oss/trpc-vue-query",
3
3
  "type": "module",
4
- "version": "0.4.2",
5
- "packageManager": "pnpm@8.15.3",
4
+ "version": "0.5.0-rc.1",
6
5
  "description": "A tRPC wrapper around '@tanstack/vue-query'",
7
6
  "license": "MIT",
8
7
  "repository": "github:falcondev-oss/trpc-vue-query",
@@ -22,6 +21,10 @@
22
21
  "files": [
23
22
  "dist"
24
23
  ],
24
+ "engines": {
25
+ "node": "20",
26
+ "pnpm": "9"
27
+ },
25
28
  "peerDependencies": {
26
29
  "@tanstack/vue-query": "^5.22.2",
27
30
  "@trpc/client": "^10.45.1",
@@ -29,33 +32,35 @@
29
32
  "vue": "^3.4.19"
30
33
  },
31
34
  "dependencies": {
32
- "@vueuse/core": "^10.9.0"
35
+ "@vueuse/core": "^11.1.0"
33
36
  },
34
37
  "devDependencies": {
35
- "@commitlint/cli": "^19.2.2",
36
- "@eslint/eslintrc": "^3.0.2",
37
- "@louishaftmann/commitlint-config": "^3.1.1",
38
- "@louishaftmann/eslint-config": "^3.1.1",
39
- "@louishaftmann/lintstaged-config": "^3.1.1",
40
- "@louishaftmann/prettier-config": "^3.1.1",
41
- "@tanstack/vue-query": "^5.29.0",
42
- "@trpc/client": "^10.45.2",
43
- "@trpc/server": "^10.45.2",
44
- "@types/eslint": "^8.56.9",
45
- "@types/eslint__eslintrc": "^2.1.1",
46
- "@vitest/ui": "^1.5.0",
47
- "eslint": "^8.57.0",
48
- "happy-dom": "^13.10.1",
49
- "husky": "^9.0.11",
50
- "lint-staged": "^15.2.2",
51
- "prettier": "^3.2.5",
52
- "start-server-and-test": "^2.0.3",
53
- "tsup": "^8.0.2",
54
- "tsx": "^4.7.2",
55
- "typescript": "^5.4.5",
56
- "vitest": "^1.5.0",
57
- "vue": "^3.4.22",
58
- "vue-demi": "^0.14.7"
38
+ "@commitlint/cli": "^19.5.0",
39
+ "@eslint/eslintrc": "^3.1.0",
40
+ "@louishaftmann/commitlint-config": "^4.0.3",
41
+ "@louishaftmann/eslint-config": "^4.0.3",
42
+ "@louishaftmann/lintstaged-config": "^4.0.3",
43
+ "@louishaftmann/prettier-config": "^4.0.3",
44
+ "@tanstack/vue-query": "^5.56.2",
45
+ "@trpc/client": "11.0.0-rc.490",
46
+ "@trpc/server": "11.0.0-rc.490",
47
+ "@types/eslint": "^9.6.1",
48
+ "@types/eslint__eslintrc": "^2.1.2",
49
+ "@types/ws": "^8.5.12",
50
+ "@vitest/ui": "^2.1.1",
51
+ "eslint": "^9.11.0",
52
+ "husky": "^9.1.6",
53
+ "lint-staged": "^15.2.10",
54
+ "prettier": "^3.3.3",
55
+ "start-server-and-test": "^2.0.8",
56
+ "tsup": "^8.3.0",
57
+ "tsx": "^4.19.1",
58
+ "type-fest": "^4.26.1",
59
+ "typescript": "^5.6.2",
60
+ "vitest": "^2.1.1",
61
+ "vue": "^3.5.7",
62
+ "ws": "^8.18.0",
63
+ "zod": "^3.23.8"
59
64
  },
60
65
  "changelogithub": {
61
66
  "extends": "gh:falcondev-it/configs/changelogithub"