@navios/react-query 0.1.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/dist/index.mjs ADDED
@@ -0,0 +1,325 @@
1
+ // packages/react-query/src/utils/query-key-creator.mts
2
+ import { bindUrlParams } from "@navios/common";
3
+ function queryKeyCreator(config, options, isInfinite) {
4
+ const url = config.url;
5
+ const urlParts = url.split("/").filter(Boolean);
6
+ return {
7
+ template: urlParts,
8
+ // @ts-expect-error We have correct types in return type
9
+ dataTag: (params) => {
10
+ var _a;
11
+ const queryParams = params && "querySchema" in config && "params" in params ? (_a = config.querySchema) == null ? void 0 : _a.parse(params.params) : [];
12
+ return [
13
+ ...options.keyPrefix ?? [],
14
+ ...urlParts.map(
15
+ (part) => part.startsWith("$") ? (
16
+ // @ts-expect-error TS2339 We know that the urlParams are defined only if the url has params
17
+ params.urlParams[part.slice(1)].toString()
18
+ ) : part
19
+ ),
20
+ ...options.keySuffix ?? [],
21
+ queryParams ?? []
22
+ ];
23
+ },
24
+ // @ts-expect-error We have correct types in return type
25
+ filterKey: (params) => {
26
+ return [
27
+ ...options.keyPrefix ?? [],
28
+ ...urlParts.map(
29
+ (part) => part.startsWith("$") ? (
30
+ // @ts-expect-error TS2339 We know that the urlParams are defined only if the url has params
31
+ params.urlParams[part.slice(1)].toString()
32
+ ) : part
33
+ ),
34
+ ...options.keySuffix ?? []
35
+ ];
36
+ },
37
+ bindToUrl: (params) => {
38
+ return bindUrlParams(url, params ?? {});
39
+ }
40
+ };
41
+ }
42
+
43
+ // packages/react-query/src/utils/mutation-key.creator.mts
44
+ function mutationKeyCreator(config, options = {
45
+ processResponse: (data) => data
46
+ }) {
47
+ const queryKey = queryKeyCreator(config, options, false);
48
+ return (params) => {
49
+ return queryKey.filterKey(params);
50
+ };
51
+ }
52
+
53
+ // packages/react-query/src/make-infinite-query-options.mts
54
+ import {
55
+ infiniteQueryOptions,
56
+ useInfiniteQuery,
57
+ useSuspenseInfiniteQuery
58
+ } from "@tanstack/react-query";
59
+ function makeInfiniteQueryOptions(endpoint, options, baseQuery = {}) {
60
+ const config = endpoint.config;
61
+ const queryKey = queryKeyCreator(config, options, true);
62
+ const processResponse = options.processResponse;
63
+ const res = (params) => {
64
+ return infiniteQueryOptions({
65
+ // @ts-expect-error TS2322 We know the type
66
+ queryKey: queryKey.dataTag(params),
67
+ queryFn: async ({ signal, pageParam }) => {
68
+ let result;
69
+ try {
70
+ result = await endpoint({
71
+ signal,
72
+ // @ts-expect-error TS2345 We bind the url params only if the url has params
73
+ urlParams: params.urlParams,
74
+ params: {
75
+ ..."params" in params ? params.params : {},
76
+ ...pageParam
77
+ }
78
+ });
79
+ } catch (err) {
80
+ if (options.onFail) {
81
+ options.onFail(err);
82
+ }
83
+ throw err;
84
+ }
85
+ return processResponse(result);
86
+ },
87
+ getNextPageParam: options.getNextPageParam,
88
+ initialPageParam: options.initialPageParam ?? config.querySchema.parse("params" in params ? params.params : {}),
89
+ ...baseQuery
90
+ });
91
+ };
92
+ res.queryKey = queryKey;
93
+ res.use = (params) => {
94
+ return useInfiniteQuery(res(params));
95
+ };
96
+ res.useSuspense = (params) => {
97
+ return useSuspenseInfiniteQuery(res(params));
98
+ };
99
+ res.invalidate = (queryClient, params) => {
100
+ return queryClient.invalidateQueries({
101
+ // @ts-expect-error We add additional function to the result
102
+ queryKey: res.queryKey.dataTag(params)
103
+ });
104
+ };
105
+ res.invalidateAll = (queryClient, params) => {
106
+ return queryClient.invalidateQueries({
107
+ // @ts-expect-error We add additional function to the result
108
+ queryKey: res.queryKey.filterKey(params),
109
+ exact: false
110
+ });
111
+ };
112
+ return res;
113
+ }
114
+
115
+ // packages/react-query/src/make-mutation.mts
116
+ import {
117
+ useIsMutating,
118
+ useMutation,
119
+ useQueryClient
120
+ } from "@tanstack/react-query";
121
+ function makeMutation(endpoint, options) {
122
+ const config = endpoint.config;
123
+ const mutationKey = mutationKeyCreator(config, options);
124
+ const result = (keyParams) => {
125
+ const queryClient = useQueryClient();
126
+ const {
127
+ useKey,
128
+ useContext,
129
+ onError,
130
+ onSuccess,
131
+ keyPrefix,
132
+ keySuffix,
133
+ processResponse,
134
+ ...rest
135
+ } = options;
136
+ const context = useContext == null ? void 0 : useContext();
137
+ return useMutation(
138
+ {
139
+ ...rest,
140
+ mutationKey: useKey ? mutationKey({
141
+ urlParams: keyParams
142
+ }) : void 0,
143
+ scope: useKey ? {
144
+ id: JSON.stringify(
145
+ mutationKey({
146
+ urlParams: keyParams
147
+ })
148
+ )
149
+ } : void 0,
150
+ async mutationFn(params) {
151
+ const response = await endpoint(params);
152
+ return processResponse(response);
153
+ },
154
+ onSuccess: onSuccess ? (data, variables) => {
155
+ return onSuccess == null ? void 0 : onSuccess(queryClient, data, variables, context);
156
+ } : void 0,
157
+ onError: onError ? (err, variables) => {
158
+ return onError == null ? void 0 : onError(queryClient, err, variables, context);
159
+ } : void 0
160
+ },
161
+ queryClient
162
+ );
163
+ };
164
+ result.useIsMutating = (keyParams) => {
165
+ if (!options.useKey) {
166
+ throw new Error(
167
+ "useIsMutating can only be used when useKey is set to true"
168
+ );
169
+ }
170
+ const isMutating = useIsMutating({
171
+ mutationKey: mutationKey({
172
+ urlParams: keyParams
173
+ })
174
+ });
175
+ return isMutating > 0;
176
+ };
177
+ result.mutationKey = mutationKey;
178
+ return result;
179
+ }
180
+
181
+ // packages/react-query/src/make-query-options.mts
182
+ import {
183
+ queryOptions,
184
+ useInfiniteQuery as useInfiniteQuery2,
185
+ useSuspenseInfiniteQuery as useSuspenseInfiniteQuery2
186
+ } from "@tanstack/react-query";
187
+ function makeQueryOptions(endpoint, options, baseQuery = {}) {
188
+ const config = endpoint.config;
189
+ const queryKey = queryKeyCreator(config, options, false);
190
+ const processResponse = options.processResponse;
191
+ const result = (params) => {
192
+ return queryOptions({
193
+ queryKey: queryKey.dataTag(params),
194
+ queryFn: async ({ signal }) => {
195
+ let result2;
196
+ try {
197
+ result2 = await endpoint({
198
+ signal,
199
+ ...params
200
+ });
201
+ } catch (err) {
202
+ if (options.onFail) {
203
+ options.onFail(err);
204
+ }
205
+ throw err;
206
+ }
207
+ return processResponse(result2);
208
+ },
209
+ ...baseQuery
210
+ });
211
+ };
212
+ result.queryKey = queryKey;
213
+ result.use = (params) => {
214
+ return useInfiniteQuery2(result(params));
215
+ };
216
+ result.useSuspense = (params) => {
217
+ return useSuspenseInfiniteQuery2(result(params));
218
+ };
219
+ result.invalidate = (queryClient, params) => {
220
+ return queryClient.invalidateQueries({
221
+ // @ts-expect-error We add additional function to the result
222
+ queryKey: result.queryKey.dataTag(params)
223
+ });
224
+ };
225
+ result.invalidateAll = (queryClient, params) => {
226
+ return queryClient.invalidateQueries({
227
+ // @ts-expect-error We add additional function to the result
228
+ queryKey: result.queryKey.filterKey(params),
229
+ exact: false
230
+ });
231
+ };
232
+ return result;
233
+ }
234
+
235
+ // packages/react-query/src/declare-client.mts
236
+ function declareClient({
237
+ api,
238
+ defaults = {}
239
+ }) {
240
+ function query(config) {
241
+ const endpoint = api.declareEndpoint({
242
+ // @ts-expect-error we accept only specific methods
243
+ method: config.method,
244
+ url: config.url,
245
+ querySchema: config.querySchema,
246
+ responseSchema: config.responseSchema
247
+ });
248
+ return makeQueryOptions(endpoint, {
249
+ ...defaults,
250
+ processResponse: config.processResponse ?? ((data) => data)
251
+ });
252
+ }
253
+ function queryFromEndpoint(endpoint, options) {
254
+ return makeQueryOptions(endpoint, {
255
+ ...defaults,
256
+ processResponse: (options == null ? void 0 : options.processResponse) ?? ((data) => data)
257
+ });
258
+ }
259
+ function infiniteQuery(config) {
260
+ const endpoint = api.declareEndpoint({
261
+ // @ts-expect-error we accept only specific methods
262
+ method: config.method,
263
+ url: config.url,
264
+ querySchema: config.querySchema,
265
+ responseSchema: config.responseSchema
266
+ });
267
+ return makeInfiniteQueryOptions(endpoint, {
268
+ ...defaults,
269
+ processResponse: config.processResponse ?? ((data) => data),
270
+ getNextPageParam: config.getNextPageParam,
271
+ getPreviousPageParam: config.getPreviousPageParam,
272
+ initialPageParam: config.initialPageParam
273
+ });
274
+ }
275
+ function infiniteQueryFromEndpoint(endpoint, options) {
276
+ return makeInfiniteQueryOptions(endpoint, {
277
+ ...defaults,
278
+ processResponse: (options == null ? void 0 : options.processResponse) ?? ((data) => data),
279
+ getNextPageParam: options.getNextPageParam,
280
+ getPreviousPageParam: options == null ? void 0 : options.getPreviousPageParam,
281
+ initialPageParam: options == null ? void 0 : options.initialPageParam
282
+ });
283
+ }
284
+ function mutation(config) {
285
+ const endpoint = api.declareEndpoint({
286
+ // @ts-expect-error We forgot about the DELETE method in original makeMutation
287
+ method: config.method,
288
+ url: config.url,
289
+ querySchema: config.querySchema,
290
+ requestSchema: config.requestSchema,
291
+ responseSchema: config.responseSchema
292
+ });
293
+ return makeMutation(endpoint, {
294
+ processResponse: config.processResponse ?? ((data) => data),
295
+ useContext: config.useContext,
296
+ // @ts-expect-error We forgot about the DELETE method in original makeMutation
297
+ onSuccess: config.onSuccess,
298
+ // @ts-expect-error We forgot about the DELETE method in original makeMutation
299
+ onError: config.onError,
300
+ useKey: config.useKey,
301
+ ...defaults
302
+ });
303
+ }
304
+ return {
305
+ // @ts-expect-error We simplified types here
306
+ query,
307
+ // @ts-expect-error We simplified types here
308
+ queryFromEndpoint,
309
+ // @ts-expect-error We simplified types here
310
+ infiniteQuery,
311
+ // @ts-expect-error We simplified types here
312
+ infiniteQueryFromEndpoint,
313
+ // @ts-expect-error We simplified types here
314
+ mutation
315
+ };
316
+ }
317
+ export {
318
+ declareClient,
319
+ makeInfiniteQueryOptions,
320
+ makeMutation,
321
+ makeQueryOptions,
322
+ mutationKeyCreator,
323
+ queryKeyCreator
324
+ };
325
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../packages/react-query/src/utils/query-key-creator.mts","../../../../packages/react-query/src/utils/mutation-key.creator.mts","../../../../packages/react-query/src/make-infinite-query-options.mts","../../../../packages/react-query/src/make-mutation.mts","../../../../packages/react-query/src/make-query-options.mts","../../../../packages/react-query/src/declare-client.mts"],"sourcesContent":["import type { AnyEndpointConfig, UrlHasParams, UrlParams } from '@navios/common'\nimport type { DataTag, InfiniteData } from '@tanstack/react-query'\nimport type { AnyZodObject, z } from 'zod'\n\nimport { bindUrlParams } from '@navios/common'\n\nimport type { BaseQueryParams } from '../types.mjs'\n\ntype Split<S extends string, D extends string> = string extends S\n ? string[]\n : S extends ''\n ? []\n : S extends `${infer T}${D}${infer U}`\n ? [T, ...Split<U, D>]\n : [S]\n\nexport type QueryKeyCreatorResult<\n QuerySchema = undefined,\n Url extends string = string,\n Result = unknown,\n IsInfinite extends boolean = false,\n HasParams extends UrlHasParams<Url> = UrlHasParams<Url>,\n> = {\n template: Split<Url, '/'>\n dataTag: (\n params: (HasParams extends true ? { urlParams: UrlParams<Url> } : {}) &\n (QuerySchema extends AnyZodObject\n ? { params: z.input<QuerySchema> }\n : {}),\n ) => DataTag<\n Split<Url, '/'>,\n IsInfinite extends true ? InfiniteData<Result> : Result,\n Error\n >\n filterKey: (\n params: HasParams extends true ? { urlParams: UrlParams<Url> } : {},\n ) => DataTag<\n Split<Url, '/'>,\n IsInfinite extends true ? InfiniteData<Result> : Result,\n Error\n >\n bindToUrl: (\n params: (HasParams extends true ? { urlParams: UrlParams<Url> } : {}) &\n (QuerySchema extends AnyZodObject\n ? { params: z.infer<QuerySchema> }\n : {}),\n ) => string\n}\n\nexport function queryKeyCreator<\n Config extends AnyEndpointConfig,\n Options extends BaseQueryParams<Config>,\n IsInfinite extends boolean,\n Url extends Config['url'] = Config['url'],\n HasParams extends UrlHasParams<Url> = UrlHasParams<Url>,\n>(\n config: Config,\n options: Options,\n isInfinite: IsInfinite,\n): QueryKeyCreatorResult<\n Config['querySchema'],\n Url,\n Options['processResponse'] extends (...args: any[]) => infer Result\n ? Result\n : never,\n IsInfinite,\n HasParams\n> {\n const url = config.url as Url\n const urlParts = url.split('/').filter(Boolean) as Split<Url, '/'>\n return {\n template: urlParts,\n // @ts-expect-error We have correct types in return type\n dataTag: (params) => {\n const queryParams =\n params && 'querySchema' in config && 'params' in params\n ? config.querySchema?.parse(params.params)\n : []\n return [\n ...(options.keyPrefix ?? []),\n ...urlParts.map((part) =>\n part.startsWith('$')\n ? // @ts-expect-error TS2339 We know that the urlParams are defined only if the url has params\n params.urlParams[part.slice(1)].toString()\n : part,\n ),\n ...(options.keySuffix ?? []),\n queryParams ?? [],\n ] as unknown as DataTag<\n Split<Url, '/'>,\n Options['processResponse'] extends (...args: any[]) => infer Result\n ? IsInfinite extends true\n ? InfiniteData<Result>\n : Result\n : never,\n Error\n >\n },\n // @ts-expect-error We have correct types in return type\n filterKey: (params) => {\n return [\n ...(options.keyPrefix ?? []),\n ...urlParts.map((part) =>\n part.startsWith('$')\n ? // @ts-expect-error TS2339 We know that the urlParams are defined only if the url has params\n params.urlParams[part.slice(1)].toString()\n : part,\n ),\n ...(options.keySuffix ?? []),\n ] as unknown as DataTag<\n Split<Url, '/'>,\n Options['processResponse'] extends (...args: any[]) => infer Result\n ? IsInfinite extends true\n ? InfiniteData<Result>\n : Result\n : never,\n Error\n >\n },\n\n bindToUrl: (params) => {\n return bindUrlParams<Url>(url, params ?? ({} as any))\n },\n }\n}\n","import type { AnyEndpointConfig, UrlHasParams, UrlParams } from '@navios/common'\nimport type { DataTag } from '@tanstack/react-query'\n\nimport type { BaseQueryParams } from '../types.mjs'\n\nimport { queryKeyCreator } from './query-key-creator.mjs'\n\n/**\n * Creates a mutation key for a given endpoint configuration and options.\n *\n * @param {config: Config } config - The endpoint object containing the configuration.\n * @param {Options} [options] - Optional query parameters with a default `processResponse` function that processes the response data.\n *\n * @returns {Object} An object containing the `mutationKey` function.\n *\n * The `mutationKey` function generates a mutation key based on the provided parameters:\n * - If the URL has parameters (`HasParams` is `true`), it expects an object with `urlParams`.\n * - The return type of the `mutationKey` function depends on the `processResponse` function in `options`.\n * If `processResponse` is defined, the return type is a `DataTag` containing the processed result and an error type.\n *\n * @example Example usage:\n * ```typescript\n * const createMutationKey = mutationKeyCreator(endpoint.config);\n * const mutationKey = createMutationKey({ urlParams: { id: 123 } });\n * ```\n *\n * @example Advanced usage:\n * ```ts\n * const createMutationKey = mutationKeyCreator(endpoint.config, {\n * processResponse: (data) => {\n * if (!data.success) {\n * throw new Error(data.message);\n * }\n * return data.data;\n * },\n * });\n * // We create a mutation that will be shared across the project for all passed userId\n * const mutationKey = createMutationKey({ urlParams: { projectId: 123, userId: 'wildcard' } });\n */\nexport function mutationKeyCreator<\n Config extends AnyEndpointConfig,\n Options extends BaseQueryParams<Config>,\n Url extends Config['url'] = Config['url'],\n HasParams extends UrlHasParams<Url> = UrlHasParams<Url>,\n>(\n config: Config,\n options: Options = {\n processResponse: (data) => data,\n } as Options,\n): (\n params: HasParams extends true ? { urlParams: UrlParams<Url> } : {},\n) => Options['processResponse'] extends (...args: any[]) => infer Result\n ? DataTag<[Config['url']], Result, Error>\n : never {\n const queryKey = queryKeyCreator(config, options, false)\n\n // @ts-expect-error We have correct types in return type\n return (params) => {\n return queryKey.filterKey(params)\n }\n}\n","import type {\n AbstractEndpoint,\n AnyEndpointConfig,\n UrlParams,\n} from '@navios/common'\nimport type {\n InfiniteData,\n QueryClient,\n UseInfiniteQueryOptions,\n UseSuspenseInfiniteQueryOptions,\n} from '@tanstack/react-query'\nimport type { z } from 'zod'\n\nimport {\n infiniteQueryOptions,\n useInfiniteQuery,\n useSuspenseInfiniteQuery,\n} from '@tanstack/react-query'\n\nimport type { InfiniteQueryOptions } from './types.mjs'\nimport type { ClientQueryArgs } from './types/index.mjs'\n\nimport { queryKeyCreator } from './utils/query-key-creator.mjs'\n\nexport function makeInfiniteQueryOptions<\n Config extends AnyEndpointConfig,\n Options extends InfiniteQueryOptions<Config>,\n BaseQuery extends Omit<\n UseInfiniteQueryOptions<ReturnType<Options['processResponse']>, Error, any>,\n | 'queryKey'\n | 'queryFn'\n | 'getNextPageParam'\n | 'initialPageParam'\n | 'placeholderData'\n | 'throwOnError'\n >,\n>(\n endpoint: AbstractEndpoint<Config>,\n options: Options,\n baseQuery: BaseQuery = {} as BaseQuery,\n) {\n const config = endpoint.config\n const queryKey = queryKeyCreator(config, options, true)\n\n const processResponse = options.processResponse\n const res = (\n params: ClientQueryArgs,\n ): Options['processResponse'] extends (...args: any[]) => infer Result\n ? UseSuspenseInfiniteQueryOptions<\n Result,\n Error,\n BaseQuery['select'] extends (...args: any[]) => infer T\n ? T\n : InfiniteData<Result>\n >\n : never => {\n // @ts-expect-error TS2322 We know that the processResponse is defined\n return infiniteQueryOptions({\n // @ts-expect-error TS2322 We know the type\n queryKey: queryKey.dataTag(params),\n queryFn: async ({ signal, pageParam }) => {\n let result\n try {\n result = await endpoint({\n signal,\n // @ts-expect-error TS2345 We bind the url params only if the url has params\n urlParams: params.urlParams as z.infer<UrlParams<Config['url']>>,\n params: {\n ...('params' in params ? params.params : {}),\n ...(pageParam as z.infer<Config['querySchema']>),\n },\n })\n } catch (err) {\n if (options.onFail) {\n options.onFail(err)\n }\n throw err\n }\n\n return processResponse(result)\n },\n getNextPageParam: options.getNextPageParam,\n initialPageParam:\n options.initialPageParam ??\n config.querySchema.parse('params' in params ? params.params : {}),\n ...baseQuery,\n })\n }\n res.queryKey = queryKey\n\n res.use = (params: ClientQueryArgs) => {\n return useInfiniteQuery(res(params))\n }\n\n res.useSuspense = (params: ClientQueryArgs) => {\n return useSuspenseInfiniteQuery(res(params))\n }\n\n res.invalidate = (queryClient: QueryClient, params: ClientQueryArgs) => {\n return queryClient.invalidateQueries({\n // @ts-expect-error We add additional function to the result\n queryKey: res.queryKey.dataTag(params),\n })\n }\n\n res.invalidateAll = (queryClient: QueryClient, params: ClientQueryArgs) => {\n return queryClient.invalidateQueries({\n // @ts-expect-error We add additional function to the result\n queryKey: res.queryKey.filterKey(params),\n exact: false,\n })\n }\n\n return res\n}\n","import type {\n AbstractEndpoint,\n AnyEndpointConfig,\n UrlHasParams,\n UrlParams,\n} from '@navios/common'\nimport type { UseMutationResult } from '@tanstack/react-query'\nimport type { z } from 'zod'\n\nimport {\n useIsMutating,\n useMutation,\n useQueryClient,\n} from '@tanstack/react-query'\n\nimport type { BaseMutationArgs, BaseMutationParams } from './types.mjs'\n\nimport { mutationKeyCreator } from './index.mjs'\n\nexport function makeMutation<\n Config extends AnyEndpointConfig,\n TData = unknown,\n TVariables extends BaseMutationArgs<Config> = BaseMutationArgs<Config>,\n TResponse = z.output<Config['responseSchema']>,\n TContext = unknown,\n UseKey extends boolean = false,\n>(\n endpoint: AbstractEndpoint<Config>,\n options: BaseMutationParams<\n Config,\n TData,\n TVariables,\n TResponse,\n TContext,\n UseKey\n >,\n) {\n const config = endpoint.config\n\n const mutationKey = mutationKeyCreator(config, options)\n const result = (\n keyParams: UseKey extends true\n ? UrlHasParams<Config['url']> extends true\n ? UrlParams<Config['url']>\n : never\n : never,\n ): UseMutationResult<TData, Error, BaseMutationArgs<Config>> => {\n const queryClient = useQueryClient()\n const {\n useKey,\n useContext,\n onError,\n onSuccess,\n keyPrefix,\n keySuffix,\n processResponse,\n ...rest\n } = options\n\n const context = useContext?.() as TContext\n\n // @ts-expect-error The types match\n return useMutation(\n {\n ...rest,\n mutationKey: useKey\n ? mutationKey({\n urlParams: keyParams,\n })\n : undefined,\n scope: useKey\n ? {\n id: JSON.stringify(\n mutationKey({\n urlParams: keyParams,\n }),\n ),\n }\n : undefined,\n async mutationFn(params: TVariables) {\n const response = await endpoint(params)\n\n return processResponse(response) as TData\n },\n onSuccess: onSuccess\n ? (data: TData, variables: TVariables) => {\n return onSuccess?.(queryClient, data, variables, context)\n }\n : undefined,\n onError: onError\n ? (err: Error, variables: TVariables) => {\n return onError?.(queryClient, err, variables, context)\n }\n : undefined,\n },\n queryClient,\n )\n }\n result.useIsMutating = (\n keyParams: UseKey extends true\n ? UrlHasParams<Config['url']> extends true\n ? UrlParams<Config['url']>\n : never\n : never,\n ): boolean => {\n if (!options.useKey) {\n throw new Error(\n 'useIsMutating can only be used when useKey is set to true',\n )\n }\n const isMutating = useIsMutating({\n mutationKey: mutationKey({\n urlParams: keyParams,\n }),\n })\n return isMutating > 0\n }\n result.mutationKey = mutationKey\n\n return result\n}\n","import type { AbstractEndpoint, AnyEndpointConfig } from '@navios/common'\nimport type {\n DataTag,\n QueryClient,\n UseQueryOptions,\n UseSuspenseQueryOptions,\n} from '@tanstack/react-query'\n\nimport {\n queryOptions,\n useInfiniteQuery,\n useSuspenseInfiniteQuery,\n} from '@tanstack/react-query'\n\nimport type { BaseQueryArgs, BaseQueryParams } from './types.mjs'\nimport type { ClientQueryArgs } from './types/index.mjs'\n\nimport { queryKeyCreator } from './utils/query-key-creator.mjs'\n\ntype Split<S extends string, D extends string> = string extends S\n ? string[]\n : S extends ''\n ? []\n : S extends `${infer T}${D}${infer U}`\n ? [T, ...Split<U, D>]\n : [S]\n\nexport function makeQueryOptions<\n Config extends AnyEndpointConfig,\n Options extends BaseQueryParams<Config>,\n BaseQuery extends Omit<\n UseQueryOptions<ReturnType<Options['processResponse']>, Error, any>,\n | 'queryKey'\n | 'queryFn'\n | 'getNextPageParam'\n | 'initialPageParam'\n | 'enabled'\n | 'throwOnError'\n | 'placeholderData'\n >,\n>(\n endpoint: AbstractEndpoint<Config>,\n options: Options,\n baseQuery: BaseQuery = {} as BaseQuery,\n) {\n const config = endpoint.config\n // Let's hack the url to be a string for now\n const queryKey = queryKeyCreator(config, options, false)\n const processResponse = options.processResponse\n\n const result = (\n params: BaseQueryArgs<Config>,\n ): Options['processResponse'] extends (...args: any[]) => infer Result\n ? UseSuspenseQueryOptions<\n Result,\n Error,\n BaseQuery['select'] extends (...args: any[]) => infer T ? T : Result,\n DataTag<Split<Config['url'], '/'>, Result, Error>\n >\n : never => {\n // @ts-expect-error TS2322 We know that the processResponse is defined\n return queryOptions({\n queryKey: queryKey.dataTag(params),\n queryFn: async ({ signal }) => {\n let result\n try {\n result = await endpoint({\n signal,\n ...params,\n })\n } catch (err) {\n if (options.onFail) {\n options.onFail(err)\n }\n throw err\n }\n\n return processResponse(result)\n },\n ...baseQuery,\n })\n }\n result.queryKey = queryKey\n result.use = (params: ClientQueryArgs) => {\n // @ts-expect-error We add additional function to the result\n return useInfiniteQuery(result(params))\n }\n\n result.useSuspense = (params: ClientQueryArgs) => {\n // @ts-expect-error We add additional function to the result\n return useSuspenseInfiniteQuery(result(params))\n }\n\n result.invalidate = (queryClient: QueryClient, params: ClientQueryArgs) => {\n return queryClient.invalidateQueries({\n // @ts-expect-error We add additional function to the result\n queryKey: result.queryKey.dataTag(params),\n })\n }\n\n result.invalidateAll = (\n queryClient: QueryClient,\n params: ClientQueryArgs,\n ) => {\n return queryClient.invalidateQueries({\n // @ts-expect-error We add additional function to the result\n queryKey: result.queryKey.filterKey(params),\n exact: false,\n })\n }\n\n return result\n}\n","import type {\n AbstractEndpoint,\n AnyEndpointConfig,\n HttpMethod,\n Util_FlatObject,\n} from '@navios/common'\nimport type { InfiniteData, QueryClient } from '@tanstack/react-query'\nimport type { AnyZodObject, z, ZodType } from 'zod'\n\nimport type { ClientOptions, ProcessResponseFunction } from './types.mjs'\nimport type { ClientInstance, ClientMutationArgs } from './types/index.mjs'\n\nimport { makeInfiniteQueryOptions } from './make-infinite-query-options.mjs'\nimport { makeMutation } from './make-mutation.mjs'\nimport { makeQueryOptions } from './make-query-options.mjs'\n\nexport interface ClientEndpoint<\n Method = HttpMethod,\n Url = string,\n QuerySchema = unknown,\n Response = ZodType,\n> {\n method: Method\n url: Url\n querySchema?: QuerySchema\n responseSchema: Response\n}\n\nexport interface ClientQueryConfig<\n Method = HttpMethod,\n Url = string,\n QuerySchema = AnyZodObject,\n Response extends ZodType = ZodType,\n Result = z.output<Response>,\n> extends ClientEndpoint<Method, Url, QuerySchema, Response> {\n processResponse?: (data: z.output<Response>) => Result\n}\n\nexport type ClientInfiniteQueryConfig<\n Method = HttpMethod,\n Url = string,\n QuerySchema extends AnyZodObject = AnyZodObject,\n Response extends ZodType = ZodType,\n PageResult = z.output<Response>,\n Result = InfiniteData<PageResult>,\n> = Required<ClientEndpoint<Method, Url, QuerySchema, Response>> & {\n processResponse?: (data: z.output<Response>) => PageResult\n select?: (data: InfiniteData<PageResult>) => Result\n getNextPageParam: (\n lastPage: PageResult,\n allPages: PageResult[],\n lastPageParam: z.infer<QuerySchema> | undefined,\n allPageParams: z.infer<QuerySchema>[] | undefined,\n ) => z.input<QuerySchema> | undefined\n getPreviousPageParam?: (\n firstPage: PageResult,\n allPages: PageResult[],\n lastPageParam: z.infer<QuerySchema> | undefined,\n allPageParams: z.infer<QuerySchema>[] | undefined,\n ) => z.input<QuerySchema>\n initialPageParam?: z.input<QuerySchema>\n}\n\nexport interface ClientMutationDataConfig<\n Method extends 'POST' | 'PUT' | 'PATCH' | 'DELETE' =\n | 'POST'\n | 'PUT'\n | 'PATCH'\n | 'DELETE',\n Url extends string = string,\n RequestSchema = Method extends 'DELETE' ? never : AnyZodObject,\n QuerySchema = unknown,\n Response extends ZodType = ZodType,\n ReqResult = z.output<Response>,\n Result = unknown,\n Context = unknown,\n UseKey extends boolean = false,\n> extends ClientEndpoint<Method, Url, QuerySchema, Response> {\n requestSchema?: RequestSchema\n processResponse: ProcessResponseFunction<Result, ReqResult>\n useContext?: () => Context\n onSuccess?: (\n queryClient: QueryClient,\n data: NoInfer<Result>,\n variables: Util_FlatObject<\n ClientMutationArgs<Url, RequestSchema, QuerySchema>\n >,\n context: Context,\n ) => void | Promise<void>\n onError?: (\n queryClient: QueryClient,\n error: Error,\n variables: Util_FlatObject<\n ClientMutationArgs<Url, RequestSchema, QuerySchema>\n >,\n context: Context,\n ) => void | Promise<void>\n useKey?: UseKey\n}\n\nexport function declareClient<Options extends ClientOptions>({\n api,\n defaults = {},\n}: Options): ClientInstance {\n function query(config: ClientQueryConfig) {\n const endpoint = api.declareEndpoint({\n // @ts-expect-error we accept only specific methods\n method: config.method,\n url: config.url,\n querySchema: config.querySchema,\n responseSchema: config.responseSchema,\n })\n\n return makeQueryOptions(endpoint, {\n ...defaults,\n processResponse: config.processResponse ?? ((data) => data),\n })\n }\n\n function queryFromEndpoint(\n endpoint: AbstractEndpoint<AnyEndpointConfig>,\n options?: {\n processResponse?: (\n data: z.output<AnyEndpointConfig['responseSchema']>,\n ) => unknown\n },\n ) {\n return makeQueryOptions(endpoint, {\n ...defaults,\n processResponse: options?.processResponse ?? ((data) => data),\n })\n }\n\n function infiniteQuery(config: ClientInfiniteQueryConfig) {\n const endpoint = api.declareEndpoint({\n // @ts-expect-error we accept only specific methods\n method: config.method,\n url: config.url,\n querySchema: config.querySchema,\n responseSchema: config.responseSchema,\n })\n return makeInfiniteQueryOptions(endpoint, {\n ...defaults,\n processResponse: config.processResponse ?? ((data) => data),\n getNextPageParam: config.getNextPageParam,\n getPreviousPageParam: config.getPreviousPageParam,\n initialPageParam: config.initialPageParam,\n })\n }\n\n function infiniteQueryFromEndpoint(\n endpoint: AbstractEndpoint<AnyEndpointConfig>,\n options: {\n processResponse?: (\n data: z.output<AnyEndpointConfig['responseSchema']>,\n ) => unknown\n getNextPageParam: (\n lastPage: z.infer<AnyEndpointConfig['responseSchema']>,\n allPages: z.infer<AnyEndpointConfig['responseSchema']>[],\n lastPageParam: z.infer<AnyEndpointConfig['querySchema']> | undefined,\n allPageParams: z.infer<AnyEndpointConfig['querySchema']>[] | undefined,\n ) => z.input<AnyEndpointConfig['querySchema']> | undefined\n getPreviousPageParam?: (\n firstPage: z.infer<AnyEndpointConfig['responseSchema']>,\n allPages: z.infer<AnyEndpointConfig['responseSchema']>[],\n lastPageParam: z.infer<AnyEndpointConfig['querySchema']> | undefined,\n allPageParams: z.infer<AnyEndpointConfig['querySchema']>[] | undefined,\n ) => z.input<AnyEndpointConfig['querySchema']>\n initialPageParam?: z.input<AnyEndpointConfig['querySchema']>\n },\n ) {\n return makeInfiniteQueryOptions(endpoint, {\n ...defaults,\n processResponse: options?.processResponse ?? ((data) => data),\n getNextPageParam: options.getNextPageParam,\n getPreviousPageParam: options?.getPreviousPageParam,\n initialPageParam: options?.initialPageParam,\n })\n }\n\n function mutation(config: ClientMutationDataConfig) {\n const endpoint = api.declareEndpoint({\n // @ts-expect-error We forgot about the DELETE method in original makeMutation\n method: config.method,\n url: config.url,\n querySchema: config.querySchema,\n requestSchema: config.requestSchema,\n responseSchema: config.responseSchema,\n })\n\n return makeMutation(endpoint, {\n processResponse: config.processResponse ?? ((data) => data),\n useContext: config.useContext,\n // @ts-expect-error We forgot about the DELETE method in original makeMutation\n onSuccess: config.onSuccess,\n // @ts-expect-error We forgot about the DELETE method in original makeMutation\n onError: config.onError,\n useKey: config.useKey,\n ...defaults,\n })\n }\n\n return {\n // @ts-expect-error We simplified types here\n query,\n // @ts-expect-error We simplified types here\n queryFromEndpoint,\n // @ts-expect-error We simplified types here\n infiniteQuery,\n // @ts-expect-error We simplified types here\n infiniteQueryFromEndpoint,\n // @ts-expect-error We simplified types here\n mutation,\n }\n}\n"],"mappings":"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","names":["useInfiniteQuery","useSuspenseInfiniteQuery","result","useInfiniteQuery","useSuspenseInfiniteQuery"]}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@navios/react-query",
3
+ "version": "0.1.0",
4
+ "author": {
5
+ "name": "Oleksandr Hanzha",
6
+ "email": "alex@granted.name"
7
+ },
8
+ "repository": {
9
+ "directory": "packages/react-query",
10
+ "type": "git",
11
+ "url": "https://github.com/Arilas/navios.git"
12
+ },
13
+ "license": "MIT",
14
+ "typings": "./dist/index.d.ts",
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.mjs",
17
+ "peerDependencies": {
18
+ "@navios/common": "^0.1.0",
19
+ "@tanstack/react-query": "^5.51.21",
20
+ "zod": "^3.23.8"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "import": {
25
+ "types": "./dist/index.d.mts",
26
+ "default": "./dist/index.mjs"
27
+ },
28
+ "require": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ }
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "devDependencies": {
36
+ "@navios/common": "^0.1.0",
37
+ "@tanstack/react-query": "^5.75.1",
38
+ "navios": "^0.4.0",
39
+ "react": "^19.1.0",
40
+ "typescript": "^5.8.3",
41
+ "zod": "^3.24.3"
42
+ }
43
+ }
@@ -0,0 +1,61 @@
1
+ import { builder } from '@navios/common'
2
+
3
+ import { describe, expect, it } from 'vitest'
4
+ import { z } from 'zod'
5
+
6
+ import { declareClient } from '../declare-client.mjs'
7
+
8
+ describe('client type check', () => {
9
+ const api = builder({
10
+ useDiscriminatorResponse: true,
11
+ })
12
+ const client = declareClient({
13
+ api,
14
+ })
15
+ it('simple query', () => {
16
+ const query = client.query({
17
+ url: 'test/$foo',
18
+ method: 'GET',
19
+ responseSchema: z.object({
20
+ test: z.string(),
21
+ }),
22
+ })
23
+ const options = query({
24
+ urlParams: {
25
+ foo: 'bar',
26
+ },
27
+ })
28
+ expect(options.queryKey).toEqual(['test', 'bar', []])
29
+ expect(query.use).toBeDefined()
30
+ expect(query.useSuspense).toBeDefined()
31
+ expect(query.invalidate).toBeDefined()
32
+ expect(query.invalidateAll).toBeDefined()
33
+ expect(query.queryKey).toBeDefined()
34
+ })
35
+ it('query with params', () => {
36
+ const query = client.query({
37
+ url: 'test/$foo',
38
+ method: 'GET',
39
+ querySchema: z.object({
40
+ foo: z.string(),
41
+ }),
42
+ responseSchema: z.object({
43
+ test: z.string(),
44
+ }),
45
+ })
46
+ const options = query({
47
+ urlParams: {
48
+ foo: 'bar',
49
+ },
50
+ params: {
51
+ foo: 'bar',
52
+ },
53
+ })
54
+ expect(options.queryKey).toEqual(['test', 'bar', { foo: 'bar' }])
55
+ expect(query.use).toBeDefined()
56
+ expect(query.useSuspense).toBeDefined()
57
+ expect(query.invalidate).toBeDefined()
58
+ expect(query.invalidateAll).toBeDefined()
59
+ expect(query.queryKey).toBeDefined()
60
+ })
61
+ })
@@ -0,0 +1,187 @@
1
+ import { create } from 'navios'
2
+ import { makeNaviosFakeAdapter } from 'navios/testing'
3
+
4
+ import { builder } from '@navios/common'
5
+
6
+ import { describe, expect, it, vi } from 'vitest'
7
+ import { z } from 'zod'
8
+
9
+ import { declareClient } from '../declare-client.mjs'
10
+
11
+ vi.mock('@tanstack/react-query', async (importReal) => {
12
+ const actual = await importReal<typeof import('@tanstack/react-query')>()
13
+ return {
14
+ ...actual,
15
+ useQueryClient: () => ({
16
+ getQueryData: vi.fn(),
17
+ setQueryData: vi.fn(),
18
+ invalidateQueries: vi.fn(),
19
+ removeQueries: vi.fn(),
20
+ }),
21
+ useMutation: vi.fn((req) => ({
22
+ ...req,
23
+ mutateAsync: async (data: unknown) => {
24
+ try {
25
+ const res = await req.mutationFn(data)
26
+ await req.onSuccess?.(res, data)
27
+ return res
28
+ } catch (err) {
29
+ req.onError?.(err, data)
30
+ throw err
31
+ }
32
+ },
33
+ mutate: req.mutationFn,
34
+ })),
35
+ }
36
+ })
37
+ describe('declareClient', () => {
38
+ const adapter = makeNaviosFakeAdapter()
39
+ const api = builder({})
40
+ api.provideClient(create({ adapter: adapter.fetch }))
41
+ const responseSchema = z.discriminatedUnion('success', [
42
+ z.object({ success: z.literal(true), test: z.string() }),
43
+ z.object({ success: z.literal(false), message: z.string() }),
44
+ ])
45
+ adapter.mock('/test/1/foo/2', 'GET', () => {
46
+ return new Response(
47
+ JSON.stringify({
48
+ success: true,
49
+ test: 'test',
50
+ }),
51
+ {
52
+ status: 200,
53
+ statusText: 'OK',
54
+ headers: {
55
+ 'content-type': 'application/json',
56
+ },
57
+ },
58
+ )
59
+ })
60
+ adapter.mock('/test/1/foo/2', 'POST', (str, req) => {
61
+ return new Response(
62
+ JSON.stringify({
63
+ success: true,
64
+ // @ts-expect-error this is a test
65
+ test: JSON.parse(req?.body).testId,
66
+ }),
67
+ {
68
+ status: 200,
69
+ statusText: 'OK',
70
+ headers: {
71
+ 'content-type': 'application/json',
72
+ },
73
+ },
74
+ )
75
+ })
76
+
77
+ it('should create a query with the correct options', async () => {
78
+ const client = declareClient({
79
+ api,
80
+ })
81
+
82
+ const query = client.query({
83
+ url: '/test/$id/foo/$foo' as const,
84
+ method: 'GET',
85
+ responseSchema,
86
+ querySchema: z.object({
87
+ id: z.string(),
88
+ }),
89
+ processResponse(data) {
90
+ if (!data.success) {
91
+ throw new Error(data.message)
92
+ }
93
+ return data
94
+ },
95
+ })
96
+
97
+ expect(query).toBeDefined()
98
+ })
99
+
100
+ it('should work with infinite queries', async () => {
101
+ const client = declareClient({
102
+ api,
103
+ })
104
+ const query = client.infiniteQuery({
105
+ url: '/test/$id/foo/$foo' as const,
106
+ method: 'GET',
107
+ responseSchema,
108
+ querySchema: z.object({
109
+ page: z.number(),
110
+ id: z.string(),
111
+ }),
112
+ processResponse(data) {
113
+ if (!data.success) {
114
+ throw new Error(data.message)
115
+ }
116
+ return data
117
+ },
118
+ getNextPageParam(lastPage, allPages) {
119
+ if (lastPage.success) {
120
+ return { page: allPages.length + 1, id: 'foo' }
121
+ }
122
+ return undefined
123
+ },
124
+ })
125
+
126
+ expect(query).toBeDefined()
127
+ })
128
+
129
+ it('should work with mutations', async () => {
130
+ const client = declareClient({
131
+ api,
132
+ })
133
+
134
+ const mutation = client.mutation({
135
+ url: '/test/$testId/foo/$fooId' as const,
136
+ method: 'POST',
137
+ requestSchema: z.object({
138
+ testId: z.string(),
139
+ }),
140
+ responseSchema: z.object({
141
+ success: z.literal(true),
142
+ test: z.string(),
143
+ }),
144
+ processResponse: (data) => {
145
+ if (!data.success) {
146
+ throw new Error('error')
147
+ }
148
+ return data
149
+ },
150
+ onSuccess(queryClient, data, variables) {
151
+ expect(data).toMatchObject({
152
+ success: true,
153
+ test: 'test',
154
+ })
155
+ expect(variables).toMatchObject({
156
+ urlParams: {
157
+ testId: '1',
158
+ fooId: '2',
159
+ },
160
+ data: {
161
+ testId: 'test',
162
+ },
163
+ })
164
+ },
165
+ onError: (err) => {
166
+ console.log('onError', err)
167
+ },
168
+ })
169
+
170
+ // @ts-expect-error it's internal type
171
+ const mutationResult = mutation()
172
+ const res = await mutationResult.mutateAsync({
173
+ urlParams: {
174
+ testId: '1',
175
+ fooId: '2',
176
+ },
177
+ data: {
178
+ testId: 'test',
179
+ },
180
+ })
181
+
182
+ expect(res).toMatchObject({
183
+ success: true,
184
+ test: 'test',
185
+ })
186
+ })
187
+ })