@falcondev-oss/trpc-vue-query 0.4.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/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/index.cjs +91 -0
- package/dist/index.d.cts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.mjs +68 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 falconDev IT GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# tRPC Vue Query
|
|
2
|
+
|
|
3
|
+
<a href="https://npmjs.org/package/@falcondev-oss/trpc-vue-query" title="View this project on NPM"><img src="https://img.shields.io/npm/v/@falcondev-oss/trpc-vue-query.svg" alt="NPM version" /></a>
|
|
4
|
+
|
|
5
|
+
A tRPC wrapper around @tanstack/vue-query. This package provides a set of hooks to use tRPC with Vue Query.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @falcondev-oss/trpc-vue-query
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage with Vue
|
|
14
|
+
|
|
15
|
+
### 1. Create client & composable
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createTRPCVueQueryClient } from '@falcondev-oss/trpc-vue-query'
|
|
19
|
+
import type { AppRouter } from '../your_server/trpc'
|
|
20
|
+
import { VueQueryPlugin, useQueryClient } from '@tanstack/vue-query'
|
|
21
|
+
|
|
22
|
+
app.use(VueQueryPlugin)
|
|
23
|
+
app.use({
|
|
24
|
+
install(app) {
|
|
25
|
+
const queryClient = useQueryClient()
|
|
26
|
+
const trpc = createTRPCVueQueryClient<AppRouter>({
|
|
27
|
+
queryClient,
|
|
28
|
+
trpc: {
|
|
29
|
+
links: [
|
|
30
|
+
httpBatchLink({
|
|
31
|
+
url: '/api/trpc',
|
|
32
|
+
}),
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
app.provide('trpc', trpc)
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { createTRPCVueQueryClient } from '@falcondev-oss/trpc-vue-query'
|
|
44
|
+
import type { AppRouter } from '../your_server/trpc'
|
|
45
|
+
|
|
46
|
+
export function useTRPC() {
|
|
47
|
+
return inject('trpc') as ReturnType<typeof createTRPCVueQueryClient<AppRouter>>
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Use it in your components
|
|
52
|
+
|
|
53
|
+
```vue
|
|
54
|
+
<script lang="ts" setup>
|
|
55
|
+
const { data: greeting } = useTRPC().hello.useQuery({ name: 'World' })
|
|
56
|
+
</script>
|
|
57
|
+
<template>
|
|
58
|
+
<div>
|
|
59
|
+
<h1>{{ greeting }}</h1>
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Passing vue-query options
|
|
65
|
+
|
|
66
|
+
```vue
|
|
67
|
+
<script lang="ts" setup>
|
|
68
|
+
const { data: greeting } = useTRPC().hello.useQuery(
|
|
69
|
+
{ name: 'World' },
|
|
70
|
+
{
|
|
71
|
+
refetchOnMount: false,
|
|
72
|
+
refetchOnReconnect: false,
|
|
73
|
+
refetchOnWindowFocus: false,
|
|
74
|
+
staleTime: 1000 * 60 * 5,
|
|
75
|
+
},
|
|
76
|
+
)
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<div>
|
|
81
|
+
<h1>{{ greeting }}</h1>
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 4. Using the `useMutation` hook
|
|
87
|
+
|
|
88
|
+
```vue
|
|
89
|
+
<script lang="ts" setup>
|
|
90
|
+
const name = ref('')
|
|
91
|
+
const { mutate: updateGreeting } = useTRPC().hello.update.useMutation({
|
|
92
|
+
onSuccess: () => {
|
|
93
|
+
console.log('Greeting updated')
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
<template>
|
|
99
|
+
<div>
|
|
100
|
+
<input v-model="name" type="text" />
|
|
101
|
+
<button @click="updateGreeting({ name })">Update greeting</button>
|
|
102
|
+
</div>
|
|
103
|
+
</template>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Usage with `trpc-nuxt`
|
|
107
|
+
|
|
108
|
+
Setup `trpc-nuxt` as described in their [documentation](https://trpc-nuxt.vercel.app/get-started/usage/recommended). Then update the `plugins/client.ts` file:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { createTRPCVueQueryClient } from '@falcondev-oss/trpc-vue-query'
|
|
112
|
+
import { useQueryClient } from '@tanstack/vue-query'
|
|
113
|
+
import { httpBatchLink } from 'trpc-nuxt/client'
|
|
114
|
+
import type { AppRouter } from '~/server/trpc/routers'
|
|
115
|
+
|
|
116
|
+
export default defineNuxtPlugin(() => {
|
|
117
|
+
const queryClient = useQueryClient()
|
|
118
|
+
|
|
119
|
+
// ⬇️ use `createTRPCVueQueryClient` instead of `createTRPCNuxtClient` ⬇️
|
|
120
|
+
const trpc = createTRPCVueQueryClient<AppRouter>({
|
|
121
|
+
queryClient,
|
|
122
|
+
trpc: {
|
|
123
|
+
links: [
|
|
124
|
+
httpBatchLink({
|
|
125
|
+
url: '/api/trpc',
|
|
126
|
+
}),
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
provide: {
|
|
133
|
+
trpc,
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
export function useTRPC() {
|
|
141
|
+
return useNuxtApp().$trpc
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Acknowledgements
|
|
146
|
+
|
|
147
|
+
Huge thanks to [Robert Soriano](https://github.com/wobsoriano) for creating `nuxt-trpc`! We just adapted his work to work with Vue Query.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
createTRPCVueQueryClient: () => createTRPCVueQueryClient
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(src_exports);
|
|
26
|
+
var import_vue_query = require("@tanstack/vue-query");
|
|
27
|
+
var import_client = require("@trpc/client");
|
|
28
|
+
var import_shared = require("@trpc/server/shared");
|
|
29
|
+
var import_core = require("@vueuse/core");
|
|
30
|
+
var import_vue = require("vue");
|
|
31
|
+
function getQueryKey(path, input) {
|
|
32
|
+
return input === void 0 ? path : [...path, input];
|
|
33
|
+
}
|
|
34
|
+
function maybeToRefs(obj) {
|
|
35
|
+
return (0, import_vue.isReactive)(obj) ? (0, import_core.toRefs)(obj) : (0, import_core.toRefs)((0, import_core.toRef)(obj));
|
|
36
|
+
}
|
|
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();
|
|
42
|
+
const joinedPath = path.join(".");
|
|
43
|
+
const [firstParam, secondParam] = args;
|
|
44
|
+
if (lastProperty === "_def") {
|
|
45
|
+
return { path };
|
|
46
|
+
}
|
|
47
|
+
if (lastProperty === "useQuery") {
|
|
48
|
+
const { trpc, ...queryOptions } = secondParam || {};
|
|
49
|
+
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), {
|
|
52
|
+
signal,
|
|
53
|
+
...trpc
|
|
54
|
+
}),
|
|
55
|
+
...maybeToRefs(queryOptions)
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (lastProperty === "invalidate") {
|
|
59
|
+
return queryClient.invalidateQueries({
|
|
60
|
+
queryKey: getQueryKey(path, (0, import_core.toValue)(firstParam))
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (lastProperty === "setQueryData") {
|
|
64
|
+
return queryClient.setQueryData(getQueryKey(path, (0, import_core.toValue)(secondParam)), firstParam);
|
|
65
|
+
}
|
|
66
|
+
if (lastProperty === "key") {
|
|
67
|
+
return getQueryKey(path, (0, import_core.toValue)(firstParam));
|
|
68
|
+
}
|
|
69
|
+
if (lastProperty === "useMutation") {
|
|
70
|
+
const { trpc, ...mutationOptions } = firstParam || {};
|
|
71
|
+
return (0, import_vue_query.useMutation)({
|
|
72
|
+
mutationFn: (payload) => client[joinedPath].mutate(payload, {
|
|
73
|
+
...trpc
|
|
74
|
+
}),
|
|
75
|
+
...maybeToRefs(mutationOptions)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return client[joinedPath][lastProperty](...args);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
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);
|
|
85
|
+
});
|
|
86
|
+
return decoratedClient;
|
|
87
|
+
}
|
|
88
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
89
|
+
0 && (module.exports = {
|
|
90
|
+
createTRPCVueQueryClient
|
|
91
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
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';
|
|
6
|
+
import { MaybeRefOrGetter, UnwrapRef } from 'vue';
|
|
7
|
+
|
|
8
|
+
type TRPCSubscriptionObserver<TValue, TError> = {
|
|
9
|
+
onStarted: () => void;
|
|
10
|
+
onData: (value: TValue) => void;
|
|
11
|
+
onError: (err: TError) => void;
|
|
12
|
+
onStopped: () => void;
|
|
13
|
+
onComplete: () => void;
|
|
14
|
+
};
|
|
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: <ResT = inferTransformedProcedureOutput<TProcedure>, DataE = TRPCClientErrorLike<TProcedure>, DataT = ResT, KeyT extends QueryKey = QueryKey>(input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseQueryOptions<ResT, DataT>>, 'queryKey'> & {
|
|
22
|
+
trpc?: TRPCRequestOptions;
|
|
23
|
+
queryKey?: KeyT;
|
|
24
|
+
}>) => UseQueryReturnType<DataT, DataE>;
|
|
25
|
+
query: Resolver<TProcedure>;
|
|
26
|
+
invalidate: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => Promise<void>;
|
|
27
|
+
setQueryData: (updater: inferTransformedProcedureOutput<TProcedure>, input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => ReturnType<QueryClient['setQueryData']>;
|
|
28
|
+
key: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => QueryKey;
|
|
29
|
+
} : TProcedure extends AnyMutationProcedure ? {
|
|
30
|
+
mutate: Resolver<TProcedure>;
|
|
31
|
+
useMutation: <ResT = inferTransformedProcedureOutput<TProcedure>, DataE = TRPCClientErrorLike<TProcedure>, DataT = ResT, VariablesT = inferProcedureInput<TProcedure>, ContextT = unknown>(opts?: MaybeRefOrGetter<UseMutationOptions<DataT, DataE, VariablesT, ContextT> & {
|
|
32
|
+
trpc?: TRPCRequestOptions;
|
|
33
|
+
}>) => UseMutationReturnType<DataT, DataE, VariablesT, ContextT>;
|
|
34
|
+
} : TProcedure extends AnySubscriptionProcedure ? {
|
|
35
|
+
subscribe: SubscriptionResolver<TProcedure, TRouter>;
|
|
36
|
+
} : never;
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
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;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
declare function createTRPCVueQueryClient<TRouter extends AnyRouter>(opts: {
|
|
45
|
+
queryClient: QueryClient;
|
|
46
|
+
trpc: CreateTRPCClientOptions<TRouter>;
|
|
47
|
+
}): DecoratedProcedureRecord<TRouter["_def"]["record"], TRouter>;
|
|
48
|
+
|
|
49
|
+
export { createTRPCVueQueryClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
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';
|
|
6
|
+
import { MaybeRefOrGetter, UnwrapRef } from 'vue';
|
|
7
|
+
|
|
8
|
+
type TRPCSubscriptionObserver<TValue, TError> = {
|
|
9
|
+
onStarted: () => void;
|
|
10
|
+
onData: (value: TValue) => void;
|
|
11
|
+
onError: (err: TError) => void;
|
|
12
|
+
onStopped: () => void;
|
|
13
|
+
onComplete: () => void;
|
|
14
|
+
};
|
|
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: <ResT = inferTransformedProcedureOutput<TProcedure>, DataE = TRPCClientErrorLike<TProcedure>, DataT = ResT, KeyT extends QueryKey = QueryKey>(input: MaybeRefOrGetter<inferProcedureInput<TProcedure>>, opts?: MaybeRefOrGetter<Omit<UnwrapRef<UseQueryOptions<ResT, DataT>>, 'queryKey'> & {
|
|
22
|
+
trpc?: TRPCRequestOptions;
|
|
23
|
+
queryKey?: KeyT;
|
|
24
|
+
}>) => UseQueryReturnType<DataT, DataE>;
|
|
25
|
+
query: Resolver<TProcedure>;
|
|
26
|
+
invalidate: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => Promise<void>;
|
|
27
|
+
setQueryData: (updater: inferTransformedProcedureOutput<TProcedure>, input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => ReturnType<QueryClient['setQueryData']>;
|
|
28
|
+
key: (input?: MaybeRefOrGetter<inferProcedureInput<TProcedure>>) => QueryKey;
|
|
29
|
+
} : TProcedure extends AnyMutationProcedure ? {
|
|
30
|
+
mutate: Resolver<TProcedure>;
|
|
31
|
+
useMutation: <ResT = inferTransformedProcedureOutput<TProcedure>, DataE = TRPCClientErrorLike<TProcedure>, DataT = ResT, VariablesT = inferProcedureInput<TProcedure>, ContextT = unknown>(opts?: MaybeRefOrGetter<UseMutationOptions<DataT, DataE, VariablesT, ContextT> & {
|
|
32
|
+
trpc?: TRPCRequestOptions;
|
|
33
|
+
}>) => UseMutationReturnType<DataT, DataE, VariablesT, ContextT>;
|
|
34
|
+
} : TProcedure extends AnySubscriptionProcedure ? {
|
|
35
|
+
subscribe: SubscriptionResolver<TProcedure, TRouter>;
|
|
36
|
+
} : never;
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
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;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
declare function createTRPCVueQueryClient<TRouter extends AnyRouter>(opts: {
|
|
45
|
+
queryClient: QueryClient;
|
|
46
|
+
trpc: CreateTRPCClientOptions<TRouter>;
|
|
47
|
+
}): DecoratedProcedureRecord<TRouter["_def"]["record"], TRouter>;
|
|
48
|
+
|
|
49
|
+
export { createTRPCVueQueryClient };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { useMutation, useQuery } from "@tanstack/vue-query";
|
|
3
|
+
import {
|
|
4
|
+
createTRPCProxyClient
|
|
5
|
+
} from "@trpc/client";
|
|
6
|
+
import { createFlatProxy, createRecursiveProxy } from "@trpc/server/shared";
|
|
7
|
+
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];
|
|
11
|
+
}
|
|
12
|
+
function maybeToRefs(obj) {
|
|
13
|
+
return isReactive(obj) ? toRefs(obj) : toRefs(toRef(obj));
|
|
14
|
+
}
|
|
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();
|
|
20
|
+
const joinedPath = path.join(".");
|
|
21
|
+
const [firstParam, secondParam] = args;
|
|
22
|
+
if (lastProperty === "_def") {
|
|
23
|
+
return { path };
|
|
24
|
+
}
|
|
25
|
+
if (lastProperty === "useQuery") {
|
|
26
|
+
const { trpc, ...queryOptions } = secondParam || {};
|
|
27
|
+
return useQuery({
|
|
28
|
+
queryKey: computed(() => getQueryKey(path, toValue(firstParam))),
|
|
29
|
+
queryFn: ({ queryKey, signal }) => client[joinedPath].query(queryKey.at(-1), {
|
|
30
|
+
signal,
|
|
31
|
+
...trpc
|
|
32
|
+
}),
|
|
33
|
+
...maybeToRefs(queryOptions)
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (lastProperty === "invalidate") {
|
|
37
|
+
return queryClient.invalidateQueries({
|
|
38
|
+
queryKey: getQueryKey(path, toValue(firstParam))
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (lastProperty === "setQueryData") {
|
|
42
|
+
return queryClient.setQueryData(getQueryKey(path, toValue(secondParam)), firstParam);
|
|
43
|
+
}
|
|
44
|
+
if (lastProperty === "key") {
|
|
45
|
+
return getQueryKey(path, toValue(firstParam));
|
|
46
|
+
}
|
|
47
|
+
if (lastProperty === "useMutation") {
|
|
48
|
+
const { trpc, ...mutationOptions } = firstParam || {};
|
|
49
|
+
return useMutation({
|
|
50
|
+
mutationFn: (payload) => client[joinedPath].mutate(payload, {
|
|
51
|
+
...trpc
|
|
52
|
+
}),
|
|
53
|
+
...maybeToRefs(mutationOptions)
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return client[joinedPath][lastProperty](...args);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function createTRPCVueQueryClient(opts) {
|
|
60
|
+
const client = createTRPCProxyClient(opts.trpc);
|
|
61
|
+
const decoratedClient = createFlatProxy((key) => {
|
|
62
|
+
return createVueQueryProxyDecoration(key, client, opts.queryClient);
|
|
63
|
+
});
|
|
64
|
+
return decoratedClient;
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
createTRPCVueQueryClient
|
|
68
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@falcondev-oss/trpc-vue-query",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"packageManager": "pnpm@8.15.3",
|
|
6
|
+
"description": "A tRPC wrapper around '@tanstack/vue-query'",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": "github:falcondev-oss/trpc-vue-query",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/falcondev-oss/trpc-vue-query/issues"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"trpc",
|
|
14
|
+
"vue-query",
|
|
15
|
+
"trpc-client",
|
|
16
|
+
"tanstack-query",
|
|
17
|
+
"typescript"
|
|
18
|
+
],
|
|
19
|
+
"main": "dist/index.cjs",
|
|
20
|
+
"module": "dist/index.mjs",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@tanstack/vue-query": "^5.22.2",
|
|
27
|
+
"@trpc/client": "^10.45.1",
|
|
28
|
+
"@trpc/server": "^10.45.1",
|
|
29
|
+
"vue": "^3.4.19"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@vueuse/core": "^10.9.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@commitlint/cli": "^19.0.3",
|
|
36
|
+
"@eslint/eslintrc": "^3.0.2",
|
|
37
|
+
"@louishaftmann/commitlint-config": "^3.0.1",
|
|
38
|
+
"@louishaftmann/eslint-config": "^3.0.1",
|
|
39
|
+
"@louishaftmann/lintstaged-config": "^3.0.1",
|
|
40
|
+
"@louishaftmann/prettier-config": "^3.0.1",
|
|
41
|
+
"@tanstack/vue-query": "^5.25.0",
|
|
42
|
+
"@trpc/client": "^10.45.1",
|
|
43
|
+
"@trpc/server": "^10.45.1",
|
|
44
|
+
"@types/eslint": "^8.56.5",
|
|
45
|
+
"@types/eslint__eslintrc": "^2.1.1",
|
|
46
|
+
"@vitest/ui": "^1.3.1",
|
|
47
|
+
"eslint": "^8.57.0",
|
|
48
|
+
"happy-dom": "^13.7.0",
|
|
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.1",
|
|
55
|
+
"typescript": "^5.4.2",
|
|
56
|
+
"vitest": "^1.3.1",
|
|
57
|
+
"vue": "^3.4.21",
|
|
58
|
+
"vue-demi": "^0.14.7"
|
|
59
|
+
},
|
|
60
|
+
"changelogithub": {
|
|
61
|
+
"extends": "gh:falcondev-it/configs/changelogithub"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"lint": "eslint --cache . && prettier --check --cache .",
|
|
66
|
+
"lint:ci": "eslint --cache --cache-strategy content . && prettier --check --cache --cache-strategy content .",
|
|
67
|
+
"lint:fix": "eslint --fix --cache . && prettier --write --cache .",
|
|
68
|
+
"type-check": "tsc -p tsconfig.json --noEmit",
|
|
69
|
+
"test": "start-server-and-test test:server http-get://localhost:3000/ping vitest",
|
|
70
|
+
"test:server": "tsx ./test/trpc/index.ts"
|
|
71
|
+
}
|
|
72
|
+
}
|