eden-tanstack-query 0.0.3 → 0.0.6

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
@@ -160,19 +160,37 @@ const eden = createEdenQuery<App>('http://localhost:8080', {
160
160
  })
161
161
  ```
162
162
 
163
- ### Known Limitation: `onSuccess` Data Type
163
+ ### Type-Safe Data Narrowing
164
164
 
165
- When using `throwOnError: true`, errors are thrown before reaching `onSuccess`. However, TypeScript cannot narrow the data type at compile-time since `throwOnError` is a runtime configuration. This means the `data` parameter in `onSuccess` may still include error union types from your response schema.
165
+ When `throwOnError` is `true` (the default), errors are thrown before reaching callbacks like `select` and `onSuccess`. The library automatically narrows the data type to exclude error shapes:
166
166
 
167
- **Workaround**: Use the `vars` parameter instead of `data` when you only need input values (e.g., for cache invalidation):
167
+ ```typescript
168
+ // Default: throwOnError = true
169
+ // Data type in select/onSuccess excludes { error: string } shapes
170
+ const eden = createEdenQuery<App>('http://localhost:8080')
171
+
172
+ useQuery(eden.users.get.queryOptions(undefined, {
173
+ select: (data) => data.users, // TypeScript knows data doesn't have error shape
174
+ onSuccess: (data) => {
175
+ console.log(data.users) // No need for type guards
176
+ }
177
+ }))
178
+ ```
179
+
180
+ When `throwOnError` is `false` or a function, the full union type is preserved:
168
181
 
169
182
  ```typescript
170
- useMutation(eden.users.post.mutationOptions({
171
- onSuccess: (_, vars) => {
172
- // Use vars instead of data for invalidation
173
- queryClient.invalidateQueries({
174
- queryKey: eden.users({ id: vars.userId }).get.queryKey()
175
- })
183
+ // Explicit: throwOnError = false
184
+ // Data type includes all response shapes (success and error)
185
+ const eden = createEdenQuery<App>('http://localhost:8080', {
186
+ throwOnError: false
187
+ })
188
+
189
+ useQuery(eden.users.get.queryOptions(undefined, {
190
+ select: (data) => {
191
+ // Need to handle both success and error shapes
192
+ if ('error' in data) return null
193
+ return data.users
176
194
  }
177
195
  }))
178
196
  ```
package/dist/index.d.ts CHANGED
@@ -14,6 +14,8 @@ interface EdenThrowOnErrorContext {
14
14
  input: unknown;
15
15
  }
16
16
  type EdenThrowOnError = ((queryKey: readonly unknown[], status: number) => boolean) | ((context: EdenThrowOnErrorContext) => boolean);
17
+ /** Union type for throwOnError config option */
18
+ type ThrowOnErrorOption = boolean | EdenThrowOnError;
17
19
  interface EdenErrorContext {
18
20
  error: _elysiajs_eden.EdenFetchError;
19
21
  queryKey: readonly unknown[];
@@ -22,11 +24,19 @@ interface EdenErrorContext {
22
24
  input: unknown;
23
25
  type: 'query' | 'mutation';
24
26
  }
25
- interface EdenQueryConfig {
26
- throwOnError?: boolean | EdenThrowOnError;
27
+ interface EdenQueryConfig<TThrowOnError extends ThrowOnErrorOption = true> {
28
+ throwOnError?: TThrowOnError;
27
29
  queryKeyPrefix?: string | string[];
28
30
  onError?: (context: EdenErrorContext) => void;
29
31
  }
32
+ /**
33
+ * Narrows data type by excluding error-shaped objects when throwOnError is true.
34
+ * When throwOnError is true, errors are thrown before reaching callbacks like
35
+ * `select` or `onSuccess`, so the data type should exclude error shapes.
36
+ */
37
+ type NarrowedData<TData, TThrowOnError> = TThrowOnError extends true ? Exclude<TData, {
38
+ error: string;
39
+ }> : TData;
30
40
  interface EdenOptions<TEden = unknown> {
31
41
  eden?: TEden;
32
42
  }
@@ -43,27 +53,46 @@ type EdenData<T> = Extract<AwaitedReturn<T>, {
43
53
  }> extends {
44
54
  data: infer D;
45
55
  } ? D : never;
46
- type EdenQueryMethod<TMethod extends Extract<HTTPMethod, 'get' | 'head'>, TCall extends (...args: any[]) => Promise<any>> = TCall & {
56
+ type EdenQueryMethod<TMethod extends Extract<HTTPMethod, 'get' | 'head'>, TCall extends (...args: any[]) => Promise<any>, TThrowOnError extends ThrowOnErrorOption = true> = TCall & {
47
57
  queryKey: (input?: FirstArg<TCall>) => EdenQueryKey<FirstArg<TCall>, TMethod>;
48
58
  queryFilter: (input?: FirstArg<TCall>) => QueryFilters<EdenQueryKey<FirstArg<TCall>, TMethod>>;
49
- 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>>>> & {
59
+ queryOptions: (input?: FirstArg<TCall>, options?: EdenQueryOptions<NarrowedData<EdenData<TCall>, TThrowOnError>, EdenFetchError | Error, NarrowedData<EdenData<TCall>, TThrowOnError>, EdenQueryKey<FirstArg<TCall>, TMethod>, EdenPartial<NonNullable<FirstArg<TCall>>>>) => EdenQueryOptions<NarrowedData<EdenData<TCall>, TThrowOnError>, EdenFetchError | Error, NarrowedData<EdenData<TCall>, TThrowOnError>, EdenQueryKey<FirstArg<TCall>, TMethod>, EdenPartial<NonNullable<FirstArg<TCall>>>> & {
50
60
  queryKey: EdenQueryKey<FirstArg<TCall>, TMethod>;
51
- queryFn: (context: QueryFunctionContext<EdenQueryKey<FirstArg<TCall>, TMethod>>) => Promise<EdenData<TCall>>;
61
+ queryFn: (context: QueryFunctionContext<EdenQueryKey<FirstArg<TCall>, TMethod>>) => Promise<NarrowedData<EdenData<TCall>, TThrowOnError>>;
52
62
  };
53
63
  };
54
- type EdenMutationMethod<TMethod extends Extract<HTTPMethod, 'post' | 'put' | 'patch' | 'delete'>, TCall extends (...args: any[]) => Promise<any>> = TCall & {
55
- 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>>>> & {
64
+ type EdenMutationMethod<TMethod extends Extract<HTTPMethod, 'post' | 'put' | 'patch' | 'delete'>, TCall extends (...args: any[]) => Promise<any>, TThrowOnError extends ThrowOnErrorOption = true> = TCall & {
65
+ mutationOptions: (options?: EdenMutationOptions<NarrowedData<EdenData<TCall>, TThrowOnError>, EdenFetchError | Error, FirstArg<TCall>, unknown, EdenPartial<NonNullable<SecondArg<TCall>>>>) => EdenMutationOptions<NarrowedData<EdenData<TCall>, TThrowOnError>, EdenFetchError | Error, FirstArg<TCall>, unknown, EdenPartial<NonNullable<SecondArg<TCall>>>> & {
56
66
  mutationKey: EdenQueryKey<undefined, TMethod>;
57
- mutationFn: (variables: FirstArg<TCall>) => Promise<EdenData<TCall>>;
67
+ mutationFn: (variables: FirstArg<TCall>) => Promise<NarrowedData<EdenData<TCall>, TThrowOnError>>;
58
68
  };
59
69
  };
60
- type EdenQueryify<T> = (T extends (...args: infer A) => infer R ? (...args: A) => EdenQueryify<R> : unknown) & (T extends object ? {
61
- [K in keyof T]: EdenQueryifyValue<K, T[K]>;
70
+ type EdenQueryify<T, TThrowOnError extends ThrowOnErrorOption = true> = (T extends (...args: infer A) => infer R ? (...args: A) => EdenQueryify<R, TThrowOnError> : unknown) & (T extends object ? {
71
+ [K in keyof T]: EdenQueryifyValue<K, T[K], TThrowOnError>;
62
72
  } : unknown);
63
- 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>;
73
+ type EdenQueryifyValue<K, V, TThrowOnError extends ThrowOnErrorOption = true> = K extends 'get' | 'head' ? V extends (...args: any[]) => Promise<any> ? EdenQueryMethod<Extract<K, 'get' | 'head'>, V, TThrowOnError> : V : K extends 'post' | 'put' | 'patch' | 'delete' ? V extends (...args: any[]) => Promise<any> ? EdenMutationMethod<Extract<K, 'post' | 'put' | 'patch' | 'delete'>, V, TThrowOnError> : V : EdenQueryify<V, TThrowOnError>;
64
74
 
65
- declare function createEdenQuery<App extends Elysia<any, any, any, any, any, any, any>>(domain: string, options?: EdenQueryConfig & {
75
+ /**
76
+ * Creates an Eden Query client with TanStack Query integration.
77
+ *
78
+ * @typeParam App - Your Elysia application type
79
+ * @typeParam TThrowOnError - Whether to throw on errors (inferred from options, defaults to true)
80
+ *
81
+ * When `throwOnError` is `true` (default), error-shaped objects are excluded from
82
+ * the data type in callbacks like `select` and `onSuccess`, since errors are thrown
83
+ * before reaching those callbacks.
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // Default: throwOnError = true, data types exclude error shapes
88
+ * const eden = createEdenQuery<App>('http://localhost:8080')
89
+ *
90
+ * // Explicit: throwOnError = false, data types include full union
91
+ * const eden = createEdenQuery<App>('http://localhost:8080', { throwOnError: false })
92
+ * ```
93
+ */
94
+ declare function createEdenQuery<App extends Elysia<any, any, any, any, any, any, any>, const TThrowOnError extends ThrowOnErrorOption = true>(domain: string, options?: EdenQueryConfig<TThrowOnError> & {
66
95
  treaty?: Treaty.Config;
67
- }): EdenQueryify<Treaty.Create<App>>;
96
+ }): EdenQueryify<Treaty.Create<App>, TThrowOnError>;
68
97
 
69
- export { type EdenErrorContext, 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 };
98
+ export { type EdenErrorContext, type EdenInfiniteQueryOptions, type EdenMutationMethod, type EdenMutationOptions, type EdenOptions, type EdenQueryConfig, type EdenQueryKey, type EdenQueryMethod, type EdenQueryOptions, type EdenQueryify, type EdenThrowOnError, type EdenThrowOnErrorContext, type HTTPMethod, type NarrowedData, type ThrowOnErrorOption, createEdenQuery };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eden-tanstack-query",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "description": "TanStack Query integration for Eden Treaty",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,12 +21,12 @@
21
21
  },
22
22
  "peerDependencies": {
23
23
  "@elysiajs/eden": ">=1.0.0",
24
- "@tanstack/query-core": "^5.90.12"
24
+ "@tanstack/query-core": "^5.90.16"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@elysiajs/eden": "^1.4.6",
28
- "@tanstack/react-query": "^5.90.12",
29
- "@tanstack/svelte-query": "^5.90.2",
28
+ "@tanstack/react-query": "^5.90.16",
29
+ "@tanstack/svelte-query": "^6.0.14",
30
30
  "bun-types": "latest",
31
31
  "typescript": "^5.9.3"
32
32
  },