eden-tanstack-query 0.0.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 +218 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +196 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# @elysiajs/eden-tanstack-query
|
|
2
|
+
|
|
3
|
+
A TanStack Query integration for [Eden Treaty](https://eden.ts), the type-safe client for [Elysia](https://elysiajs.com).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔗 **Type-safe** - Full TypeScript inference from Elysia server types
|
|
8
|
+
- ⚡ **Framework-agnostic** - Works with React Query, Svelte Query, Solid Query, Vue Query
|
|
9
|
+
- 🎯 **queryOptions** - Reusable, type-safe query configurations
|
|
10
|
+
- 🔄 **mutationOptions** - Type-safe mutation configurations
|
|
11
|
+
- 🔑 **Query keys** - Auto-generated, type-safe query keys for cache operations
|
|
12
|
+
- ⚠️ **Error handling** - Configurable error throwing
|
|
13
|
+
- 🛠️ **Eden integration** - Seamlessly integrates with existing Treaty clients
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add @elysiajs/eden-tanstack-query @tanstack/query-core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Basic Usage
|
|
22
|
+
|
|
23
|
+
### Setup
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { treaty } from '@elysiajs/eden/treaty2'
|
|
27
|
+
import { createEdenQuery } from '@elysiajs/eden-tanstack-query'
|
|
28
|
+
import { useQuery } from '@tanstack/svelte-query'
|
|
29
|
+
|
|
30
|
+
// Your Elysia app type
|
|
31
|
+
type App = {
|
|
32
|
+
users: {
|
|
33
|
+
get: {
|
|
34
|
+
query: { page?: number }
|
|
35
|
+
response: { users: User[] }
|
|
36
|
+
}
|
|
37
|
+
post: {
|
|
38
|
+
body: { name: string, email: string }
|
|
39
|
+
response: { user: User }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Create Eden Query client
|
|
45
|
+
const eden = createEdenQuery<App>('http://localhost:8080')
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Queries
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// Basic query (auto-generated query key)
|
|
52
|
+
const query = useQuery(eden.users.get.queryOptions())
|
|
53
|
+
|
|
54
|
+
// Query with parameters
|
|
55
|
+
const query = useQuery(
|
|
56
|
+
eden.users.get.queryOptions({ query: { page: 1 } })
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
// Access the data
|
|
60
|
+
query.data?.users // Fully typed from your Elysia response
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Mutations
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { useMutation } from '@tanstack/svelte-query'
|
|
67
|
+
|
|
68
|
+
// Basic mutation
|
|
69
|
+
const mutation = useMutation(eden.users.post.mutationOptions())
|
|
70
|
+
|
|
71
|
+
// Using the mutation
|
|
72
|
+
mutation.mutate({ name: 'John', email: 'john@example.com' })
|
|
73
|
+
|
|
74
|
+
// Access the response
|
|
75
|
+
mutation.data?.user // Fully typed
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Query Keys
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// Get type-safe query keys for cache operations
|
|
82
|
+
const usersKey = eden.users.get.queryKey()
|
|
83
|
+
|
|
84
|
+
// Invalidate queries
|
|
85
|
+
const queryClient = useQueryClient()
|
|
86
|
+
queryClient.invalidateQueries({ queryKey: usersKey })
|
|
87
|
+
|
|
88
|
+
// Get query data type-safely
|
|
89
|
+
const data = queryClient.getQueryData(eden.users.get.queryKey())
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Error Handling
|
|
93
|
+
|
|
94
|
+
### Throw on Error (Default for most apps)
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const eden = createEdenQuery<App>('http://localhost:8080', {
|
|
98
|
+
throwOnError: true
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
useQuery(eden.users.get.queryOptions(undefined, {
|
|
102
|
+
onError: (error: EdenFetchError) => {
|
|
103
|
+
// error.status and error.value are available
|
|
104
|
+
// extra context is attached: error.queryKey, error.method, error.path, error.input
|
|
105
|
+
if (error.status === 401) {
|
|
106
|
+
router.push('/login')
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}))
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Conditional Throwing
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const eden = createEdenQuery<App>('http://localhost:8080', {
|
|
116
|
+
throwOnError: (queryKey, status) => {
|
|
117
|
+
// Don't throw on 404 (not found)
|
|
118
|
+
if (status === 404) return false
|
|
119
|
+
// Throw on server errors
|
|
120
|
+
if (status >= 500) return true
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Advanced Usage
|
|
127
|
+
|
|
128
|
+
### Custom Eden Treaty Options
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const eden = createEdenQuery<App>('http://localhost:8080', {
|
|
132
|
+
treaty: {
|
|
133
|
+
headers: { authorization: 'Bearer token' },
|
|
134
|
+
fetch: customFetch
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
useQuery(eden.users.get.queryOptions(
|
|
139
|
+
{ query: { page: 1 } },
|
|
140
|
+
{
|
|
141
|
+
eden: {
|
|
142
|
+
headers: { 'X-Custom': 'value' }
|
|
143
|
+
},
|
|
144
|
+
staleTime: 5000
|
|
145
|
+
}
|
|
146
|
+
))
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Query Key Prefix
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const eden = createEdenQuery<App>('http://localhost:8080', {
|
|
153
|
+
queryKeyPrefix: 'my-api'
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Keys will be prefixed: ['my-api', 'users', 'get']
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Using with React Query
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
163
|
+
|
|
164
|
+
const query = useQuery(eden.users.get.queryOptions())
|
|
165
|
+
const mutation = useMutation(eden.users.post.mutationOptions())
|
|
166
|
+
const queryClient = useQueryClient()
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Using with Solid Query
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { createQuery, createMutation } from '@tanstack/solid-query'
|
|
173
|
+
|
|
174
|
+
const query = createQuery(() => eden.users.get.queryOptions())
|
|
175
|
+
const mutation = createMutation(() => eden.users.post.mutationOptions())
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Using with Vue Query
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/vue-query'
|
|
182
|
+
|
|
183
|
+
const query = useQuery(eden.users.get.queryOptions())
|
|
184
|
+
const mutation = useMutation(eden.users.post.mutationOptions())
|
|
185
|
+
const queryClient = useQueryClient()
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Query Key Structure
|
|
189
|
+
|
|
190
|
+
Query keys are auto-generated from your API paths:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Simple path
|
|
194
|
+
eden.users.get.queryKey()
|
|
195
|
+
// → ['users', 'get']
|
|
196
|
+
|
|
197
|
+
// Path with parameters
|
|
198
|
+
eden.users({ id: '123' }).get.queryKey()
|
|
199
|
+
// → ['users', { id: '123' }, 'get']
|
|
200
|
+
|
|
201
|
+
// Nested paths
|
|
202
|
+
eden.users.posts({ userId: '123' }).get.queryKey()
|
|
203
|
+
// → ['users', 'posts', { userId: '123' }, 'get']
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Type Safety
|
|
207
|
+
|
|
208
|
+
All types are fully inferred from your Elysia server:
|
|
209
|
+
|
|
210
|
+
- ✅ Query data type (from success responses)
|
|
211
|
+
- ✅ Error type (from EdenFetchError or Treaty response)
|
|
212
|
+
- ✅ Input validation (query params, body)
|
|
213
|
+
- ✅ Query keys (type-safe, auto-generated)
|
|
214
|
+
- ✅ Framework-agnostic (works with all TanStack Query variants)
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { QueryFilters, QueryKey, QueryObserverOptions, QueryFunctionContext, MutationOptions, InfiniteQueryObserverOptions } from '@tanstack/query-core';
|
|
2
|
+
import { EdenFetchError } from '@elysiajs/eden';
|
|
3
|
+
import { Elysia } from 'elysia';
|
|
4
|
+
import { Treaty } from '@elysiajs/eden/treaty2';
|
|
5
|
+
export { Treaty, treaty } from '@elysiajs/eden/treaty2';
|
|
6
|
+
|
|
7
|
+
type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options';
|
|
8
|
+
interface EdenThrowOnErrorContext {
|
|
9
|
+
queryKey: readonly unknown[];
|
|
10
|
+
status: number;
|
|
11
|
+
method: HTTPMethod;
|
|
12
|
+
path: string[];
|
|
13
|
+
input: unknown;
|
|
14
|
+
}
|
|
15
|
+
type EdenThrowOnError = ((queryKey: readonly unknown[], status: number) => boolean) | ((context: EdenThrowOnErrorContext) => boolean);
|
|
16
|
+
interface EdenQueryConfig {
|
|
17
|
+
throwOnError?: boolean | EdenThrowOnError;
|
|
18
|
+
queryKeyPrefix?: string | string[];
|
|
19
|
+
}
|
|
20
|
+
interface EdenOptions<TEden = unknown> {
|
|
21
|
+
eden?: TEden;
|
|
22
|
+
}
|
|
23
|
+
type EdenQueryKey<TInput = unknown, TMethod extends HTTPMethod = HTTPMethod> = readonly [...string[], TInput, TMethod];
|
|
24
|
+
type EdenQueryOptions<TQueryFnData, TError = Error, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TEden = unknown> = Omit<QueryObserverOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, 'queryKey' | 'queryFn'> & EdenOptions<TEden>;
|
|
25
|
+
type EdenMutationOptions<TData, TError = Error, TVariables = void, TContext = unknown, TEden = unknown> = Omit<MutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> & EdenOptions<TEden>;
|
|
26
|
+
type EdenInfiniteQueryOptions<TQueryFnData, TError = Error, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown, TEden = unknown> = Omit<InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, 'queryKey' | 'queryFn'> & EdenOptions<TEden>;
|
|
27
|
+
type EdenPartial<T> = T extends object ? Partial<T> : never;
|
|
28
|
+
type AwaitedReturn<T> = T extends (...args: any[]) => infer R ? Awaited<R> : never;
|
|
29
|
+
type FirstArg<T> = T extends (arg1: infer A, ...args: any[]) => any ? A : never;
|
|
30
|
+
type SecondArg<T> = T extends (arg1: any, arg2: infer B, ...args: any[]) => any ? B : never;
|
|
31
|
+
type EdenData<T> = Extract<AwaitedReturn<T>, {
|
|
32
|
+
error: null;
|
|
33
|
+
}> extends {
|
|
34
|
+
data: infer D;
|
|
35
|
+
} ? D : never;
|
|
36
|
+
type EdenQueryMethod<TMethod extends Extract<HTTPMethod, 'get' | 'head'>, TCall extends (...args: any[]) => Promise<any>> = TCall & {
|
|
37
|
+
queryKey: (input?: FirstArg<TCall>) => EdenQueryKey<FirstArg<TCall>, TMethod>;
|
|
38
|
+
queryFilter: (input?: FirstArg<TCall>) => QueryFilters<EdenQueryKey<FirstArg<TCall>, TMethod>>;
|
|
39
|
+
queryOptions: (input?: FirstArg<TCall>, options?: EdenQueryOptions<EdenData<TCall>, EdenFetchError | Error, EdenData<TCall>, EdenQueryKey<FirstArg<TCall>, TMethod>, EdenPartial<NonNullable<FirstArg<TCall>>>>) => EdenQueryOptions<EdenData<TCall>, EdenFetchError | Error, EdenData<TCall>, EdenQueryKey<FirstArg<TCall>, TMethod>, EdenPartial<NonNullable<FirstArg<TCall>>>> & {
|
|
40
|
+
queryKey: EdenQueryKey<FirstArg<TCall>, TMethod>;
|
|
41
|
+
queryFn: (context: QueryFunctionContext<EdenQueryKey<FirstArg<TCall>, TMethod>>) => Promise<EdenData<TCall>>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
type EdenMutationMethod<TMethod extends Extract<HTTPMethod, 'post' | 'put' | 'patch' | 'delete'>, TCall extends (...args: any[]) => Promise<any>> = TCall & {
|
|
45
|
+
mutationOptions: (options?: EdenMutationOptions<EdenData<TCall>, EdenFetchError | Error, FirstArg<TCall>, unknown, EdenPartial<NonNullable<SecondArg<TCall>>>>) => EdenMutationOptions<EdenData<TCall>, EdenFetchError | Error, FirstArg<TCall>, unknown, EdenPartial<NonNullable<SecondArg<TCall>>>> & {
|
|
46
|
+
mutationKey: EdenQueryKey<undefined, TMethod>;
|
|
47
|
+
mutationFn: (variables: FirstArg<TCall>) => Promise<EdenData<TCall>>;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
type EdenQueryify<T> = (T extends (...args: infer A) => infer R ? (...args: A) => EdenQueryify<R> : unknown) & (T extends object ? {
|
|
51
|
+
[K in keyof T]: EdenQueryifyValue<K, T[K]>;
|
|
52
|
+
} : unknown);
|
|
53
|
+
type EdenQueryifyValue<K, V> = K extends 'get' | 'head' ? V extends (...args: any[]) => Promise<any> ? EdenQueryMethod<Extract<K, 'get' | 'head'>, V> : V : K extends 'post' | 'put' | 'patch' | 'delete' ? V extends (...args: any[]) => Promise<any> ? EdenMutationMethod<Extract<K, 'post' | 'put' | 'patch' | 'delete'>, V> : V : EdenQueryify<V>;
|
|
54
|
+
|
|
55
|
+
declare function createEdenQuery<App extends Elysia<any, any, any, any, any, any, any>>(domain: string, options?: EdenQueryConfig & {
|
|
56
|
+
treaty?: Treaty.Config;
|
|
57
|
+
}): EdenQueryify<Treaty.Create<App>>;
|
|
58
|
+
|
|
59
|
+
export { type EdenInfiniteQueryOptions, type EdenMutationMethod, type EdenMutationOptions, type EdenOptions, type EdenQueryConfig, type EdenQueryKey, type EdenQueryMethod, type EdenQueryOptions, type EdenQueryify, type EdenThrowOnError, type EdenThrowOnErrorContext, type HTTPMethod, createEdenQuery };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { treaty } from "@elysiajs/eden/treaty2";
|
|
3
|
+
|
|
4
|
+
// src/query-options.ts
|
|
5
|
+
import { EdenFetchError } from "@elysiajs/eden";
|
|
6
|
+
|
|
7
|
+
// src/query-key.ts
|
|
8
|
+
function buildQueryKey(paths, input, method, prefix) {
|
|
9
|
+
if (prefix) {
|
|
10
|
+
return typeof prefix === "string" ? [prefix, ...paths, input, method] : [...prefix, ...paths, input, method];
|
|
11
|
+
}
|
|
12
|
+
return [...paths, input, method];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/query-options.ts
|
|
16
|
+
function shouldThrowOnError(config, context) {
|
|
17
|
+
if (typeof config.throwOnError === "boolean") return config.throwOnError;
|
|
18
|
+
if (typeof config.throwOnError === "function") {
|
|
19
|
+
const fn = config.throwOnError;
|
|
20
|
+
return fn.length >= 2 ? fn(
|
|
21
|
+
context.queryKey,
|
|
22
|
+
context.status
|
|
23
|
+
) : fn(context);
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
function toEdenFetchError(error, status) {
|
|
28
|
+
if (error instanceof EdenFetchError) return error;
|
|
29
|
+
if (error && typeof error === "object" && "value" in error) {
|
|
30
|
+
return new EdenFetchError(status, error.value);
|
|
31
|
+
}
|
|
32
|
+
return new EdenFetchError(status, error);
|
|
33
|
+
}
|
|
34
|
+
function createQueryOptions(treatyCall, paths, method, globalConfig) {
|
|
35
|
+
return (input, options) => {
|
|
36
|
+
const eden = options?.eden;
|
|
37
|
+
const finalInput = input === void 0 && eden === void 0 ? void 0 : { ...input, ...eden };
|
|
38
|
+
const queryKey = buildQueryKey(paths, finalInput, method, globalConfig.queryKeyPrefix);
|
|
39
|
+
const { eden: _eden, ...tanstackOptions } = options ?? {};
|
|
40
|
+
return {
|
|
41
|
+
...tanstackOptions,
|
|
42
|
+
queryKey,
|
|
43
|
+
queryFn: async (_context) => {
|
|
44
|
+
const result = await treatyCall(finalInput);
|
|
45
|
+
if (result.error) {
|
|
46
|
+
const error = toEdenFetchError(result.error, result.status);
|
|
47
|
+
error.queryKey = queryKey;
|
|
48
|
+
error.method = method;
|
|
49
|
+
error.path = paths;
|
|
50
|
+
error.input = finalInput;
|
|
51
|
+
error.response = result.response;
|
|
52
|
+
error.headers = result.headers;
|
|
53
|
+
if (shouldThrowOnError(globalConfig, {
|
|
54
|
+
queryKey,
|
|
55
|
+
status: result.status,
|
|
56
|
+
method,
|
|
57
|
+
path: paths,
|
|
58
|
+
input: finalInput
|
|
59
|
+
})) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return result.data;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/mutation-options.ts
|
|
71
|
+
import { EdenFetchError as EdenFetchError2 } from "@elysiajs/eden";
|
|
72
|
+
function shouldThrowOnError2(config, context) {
|
|
73
|
+
if (typeof config.throwOnError === "boolean") return config.throwOnError;
|
|
74
|
+
if (typeof config.throwOnError === "function") {
|
|
75
|
+
const fn = config.throwOnError;
|
|
76
|
+
return fn.length >= 2 ? fn(
|
|
77
|
+
context.queryKey,
|
|
78
|
+
context.status
|
|
79
|
+
) : fn(context);
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
function toEdenFetchError2(error, status) {
|
|
84
|
+
if (error instanceof EdenFetchError2) return error;
|
|
85
|
+
if (error && typeof error === "object" && "value" in error) {
|
|
86
|
+
return new EdenFetchError2(status, error.value);
|
|
87
|
+
}
|
|
88
|
+
return new EdenFetchError2(status, error);
|
|
89
|
+
}
|
|
90
|
+
function createMutationOptions(treatyCall, paths, method, globalConfig) {
|
|
91
|
+
return (options) => {
|
|
92
|
+
const eden = options?.eden;
|
|
93
|
+
const mutationKey = buildQueryKey(
|
|
94
|
+
paths,
|
|
95
|
+
void 0,
|
|
96
|
+
method,
|
|
97
|
+
globalConfig.queryKeyPrefix
|
|
98
|
+
);
|
|
99
|
+
const { eden: _eden, ...tanstackOptions } = options ?? {};
|
|
100
|
+
return {
|
|
101
|
+
...tanstackOptions,
|
|
102
|
+
mutationKey,
|
|
103
|
+
mutationFn: async (variables) => {
|
|
104
|
+
const result = await treatyCall(variables, eden);
|
|
105
|
+
if (result.error) {
|
|
106
|
+
const error = toEdenFetchError2(result.error, result.status);
|
|
107
|
+
error.queryKey = mutationKey;
|
|
108
|
+
error.method = method;
|
|
109
|
+
error.path = paths;
|
|
110
|
+
error.input = variables;
|
|
111
|
+
error.response = result.response;
|
|
112
|
+
error.headers = result.headers;
|
|
113
|
+
if (shouldThrowOnError2(globalConfig, {
|
|
114
|
+
queryKey: mutationKey,
|
|
115
|
+
status: result.status,
|
|
116
|
+
method,
|
|
117
|
+
path: paths,
|
|
118
|
+
input: variables
|
|
119
|
+
})) {
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return result.data;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/query-key-helpers.ts
|
|
131
|
+
function createQueryKeyGetter(paths, method, prefix) {
|
|
132
|
+
return (input) => buildQueryKey(paths, input, method, prefix);
|
|
133
|
+
}
|
|
134
|
+
function createQueryFilter(paths, method, prefix) {
|
|
135
|
+
return (input) => ({
|
|
136
|
+
queryKey: buildQueryKey(paths, input, method, prefix),
|
|
137
|
+
exact: true
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/proxy.ts
|
|
142
|
+
var HTTP_METHODS = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
143
|
+
function extendProxy(proxy, paths, config) {
|
|
144
|
+
return new Proxy(proxy, {
|
|
145
|
+
get(target, prop) {
|
|
146
|
+
if (typeof prop === "symbol") return target[prop];
|
|
147
|
+
const value = target[prop];
|
|
148
|
+
if (typeof value === "function" && HTTP_METHODS.includes(prop)) {
|
|
149
|
+
const httpMethod = prop;
|
|
150
|
+
const callable = (...args) => value(...args);
|
|
151
|
+
return Object.assign(callable, {
|
|
152
|
+
...httpMethod === "get" || httpMethod === "head" ? {
|
|
153
|
+
queryOptions: createQueryOptions(
|
|
154
|
+
callable,
|
|
155
|
+
paths,
|
|
156
|
+
httpMethod,
|
|
157
|
+
config
|
|
158
|
+
),
|
|
159
|
+
queryKey: createQueryKeyGetter(paths, httpMethod, config.queryKeyPrefix),
|
|
160
|
+
queryFilter: createQueryFilter(paths, httpMethod, config.queryKeyPrefix)
|
|
161
|
+
} : {},
|
|
162
|
+
...httpMethod === "post" || httpMethod === "put" || httpMethod === "patch" || httpMethod === "delete" ? {
|
|
163
|
+
mutationOptions: createMutationOptions(
|
|
164
|
+
callable,
|
|
165
|
+
paths,
|
|
166
|
+
httpMethod,
|
|
167
|
+
config
|
|
168
|
+
)
|
|
169
|
+
} : {}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
173
|
+
return extendProxy(value, [...paths, prop], config);
|
|
174
|
+
}
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/index.ts
|
|
181
|
+
import { treaty as treaty2 } from "@elysiajs/eden/treaty2";
|
|
182
|
+
function createEdenQuery(domain, options) {
|
|
183
|
+
const treatyInstance = treaty(domain, options?.treaty);
|
|
184
|
+
return extendProxy(
|
|
185
|
+
treatyInstance,
|
|
186
|
+
[],
|
|
187
|
+
{
|
|
188
|
+
throwOnError: options?.throwOnError ?? true,
|
|
189
|
+
queryKeyPrefix: options?.queryKeyPrefix
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
export {
|
|
194
|
+
createEdenQuery,
|
|
195
|
+
treaty2 as treaty
|
|
196
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eden-tanstack-query",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "TanStack Query integration for Eden Treaty",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"test": "bun test",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"@elysiajs/eden": ">=1.0.0",
|
|
24
|
+
"@tanstack/query-core": "^5.0.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@elysiajs/eden": "file:../..",
|
|
28
|
+
"@tanstack/react-query": "^5.0.0",
|
|
29
|
+
"@tanstack/svelte-query": "^5.0.0",
|
|
30
|
+
"bun-types": "latest",
|
|
31
|
+
"typescript": "^5.0.0"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"elysia",
|
|
35
|
+
"eden",
|
|
36
|
+
"tanstack",
|
|
37
|
+
"query",
|
|
38
|
+
"react-query",
|
|
39
|
+
"svelte-query",
|
|
40
|
+
"typescript"
|
|
41
|
+
]
|
|
42
|
+
}
|