@geekmidas/client 0.4.0 → 0.5.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.
Files changed (71) hide show
  1. package/dist/auth-fetcher.cjs +0 -1
  2. package/dist/auth-fetcher.cjs.map +1 -1
  3. package/dist/auth-fetcher.d.cts +1 -1
  4. package/dist/auth-fetcher.d.cts.map +1 -1
  5. package/dist/auth-fetcher.d.mts +1 -1
  6. package/dist/auth-fetcher.d.mts.map +1 -1
  7. package/dist/auth-fetcher.mjs +0 -1
  8. package/dist/auth-fetcher.mjs.map +1 -1
  9. package/dist/endpoint-hooks.cjs +10 -5
  10. package/dist/endpoint-hooks.cjs.map +1 -1
  11. package/dist/endpoint-hooks.d.cts +2 -2
  12. package/dist/endpoint-hooks.d.cts.map +1 -1
  13. package/dist/endpoint-hooks.d.mts +2 -2
  14. package/dist/endpoint-hooks.d.mts.map +1 -1
  15. package/dist/endpoint-hooks.mjs +10 -5
  16. package/dist/endpoint-hooks.mjs.map +1 -1
  17. package/dist/fetcher-5fnBE7Dk.mjs.map +1 -1
  18. package/dist/fetcher-CgLEaIAC.cjs.map +1 -1
  19. package/dist/fetcher.d.cts +1 -1
  20. package/dist/fetcher.d.cts.map +1 -1
  21. package/dist/fetcher.d.mts +1 -1
  22. package/dist/fetcher.d.mts.map +1 -1
  23. package/dist/infer.d.cts.map +1 -1
  24. package/dist/infer.d.mts.map +1 -1
  25. package/dist/openapi-hooks.cjs.map +1 -1
  26. package/dist/openapi-hooks.d.cts +2 -2
  27. package/dist/openapi-hooks.d.cts.map +1 -1
  28. package/dist/openapi-hooks.d.mts +2 -2
  29. package/dist/openapi-hooks.d.mts.map +1 -1
  30. package/dist/openapi-hooks.mjs.map +1 -1
  31. package/dist/openapi-types.d.cts.map +1 -1
  32. package/dist/openapi-types.d.mts.map +1 -1
  33. package/dist/openapi.cjs.map +1 -1
  34. package/dist/openapi.mjs.map +1 -1
  35. package/dist/react-query.cjs.map +1 -1
  36. package/dist/react-query.d.cts +1 -1
  37. package/dist/react-query.d.cts.map +1 -1
  38. package/dist/react-query.d.mts +1 -1
  39. package/dist/react-query.d.mts.map +1 -1
  40. package/dist/react-query.mjs.map +1 -1
  41. package/dist/{types-FxummKaL.d.mts → types-4K4N-Fl1.d.cts} +2 -2
  42. package/dist/types-4K4N-Fl1.d.cts.map +1 -0
  43. package/dist/{types-vutATyWv.d.cts → types-hhkZWjQn.d.mts} +2 -2
  44. package/dist/types-hhkZWjQn.d.mts.map +1 -0
  45. package/dist/types.d.cts +1 -1
  46. package/dist/types.d.mts +1 -1
  47. package/package.json +3 -3
  48. package/src/__tests__/auth-fetcher.spec.ts +476 -476
  49. package/src/__tests__/endpoint-hooks.spec.tsx +348 -348
  50. package/src/__tests__/fetcher.spec.ts +403 -403
  51. package/src/__tests__/infer.integration.spec.ts +171 -171
  52. package/src/__tests__/infer.spec.ts +182 -182
  53. package/src/__tests__/method-restrictions.spec.tsx +165 -165
  54. package/src/__tests__/openapi-hooks.spec.tsx +536 -536
  55. package/src/__tests__/react-query-infinite.spec.tsx +989 -989
  56. package/src/__tests__/react-query-invalidation.spec.tsx +223 -222
  57. package/src/__tests__/react-query.spec.tsx +567 -567
  58. package/src/__tests__/setup.ts +260 -260
  59. package/src/__tests__/types.spec.ts +127 -127
  60. package/src/__tests__/url-parsing.spec.ts +191 -191
  61. package/src/auth-fetcher.ts +160 -162
  62. package/src/endpoint-hooks.ts +151 -156
  63. package/src/fetcher.ts +163 -163
  64. package/src/infer.ts +64 -63
  65. package/src/openapi-hooks.ts +146 -146
  66. package/src/openapi-types.d.ts +428 -428
  67. package/src/openapi.json +593 -593
  68. package/src/react-query.ts +281 -281
  69. package/src/types.ts +121 -124
  70. package/dist/types-FxummKaL.d.mts.map +0 -1
  71. package/dist/types-vutATyWv.d.cts.map +0 -1
@@ -8,231 +8,232 @@ import React from 'react';
8
8
  import { beforeEach, describe, expect, it, vi } from 'vitest';
9
9
  import type { paths } from '../openapi-types';
10
10
  import { TypedQueryClient, useTypedInvalidateQueries } from '../react-query';
11
+
11
12
  // Mock the fetcher module
12
13
  vi.mock('../fetcher', () => ({
13
- createTypedFetcher: () => vi.fn(),
14
+ createTypedFetcher: () => vi.fn(),
14
15
  }));
15
16
 
16
17
  describe('TypedQueryClient - Query Invalidation', () => {
17
- let queryClient: QueryClient;
18
- let typedClient: TypedQueryClient<paths>;
19
-
20
- beforeEach(() => {
21
- queryClient = new QueryClient({
22
- defaultOptions: {
23
- queries: { retry: false },
24
- },
25
- });
26
- typedClient = new TypedQueryClient({ queryClient });
27
- });
28
-
29
- describe('buildQueryKey', () => {
30
- it('should build query key with endpoint only', () => {
31
- const key = typedClient.buildQueryKey('GET /users');
32
- expect(key).toEqual(['GET /users']);
33
- });
34
-
35
- it('should build query key with params', () => {
36
- const key = typedClient.buildQueryKey('GET /users/{id}', {
37
- params: { id: '123' },
38
- });
39
- expect(key).toEqual(['GET /users/{id}', { params: { id: '123' } }]);
40
- });
41
-
42
- it('should build query key with query params', () => {
43
- const key = typedClient.buildQueryKey('GET /users', {
44
- query: { page: 1, limit: 10 },
45
- });
46
- expect(key).toEqual(['GET /users', { query: { page: 1, limit: 10 } }]);
47
- });
48
-
49
- it('should build query key with params only for paths without query support', () => {
50
- const key = typedClient.buildQueryKey('GET /users/{id}', {
51
- params: { id: '123' },
52
- });
53
- expect(key).toEqual(['GET /users/{id}', { params: { id: '123' } }]);
54
- });
55
- });
56
-
57
- describe('invalidateQueries', () => {
58
- it('should invalidate queries with endpoint only (partial match)', async () => {
59
- const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
60
-
61
- await typedClient.invalidateQueries('GET /users');
62
-
63
- expect(invalidateSpy).toHaveBeenCalledWith({
64
- queryKey: ['GET /users'],
65
- exact: false,
66
- });
67
- });
68
-
69
- it('should invalidate queries with config (exact match)', async () => {
70
- const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
71
-
72
- await typedClient.invalidateQueries('GET /users/{id}', {
73
- params: { id: '123' },
74
- });
75
-
76
- expect(invalidateSpy).toHaveBeenCalledWith({
77
- queryKey: ['GET /users/{id}', { params: { id: '123' } }],
78
- exact: true,
79
- });
80
- });
81
-
82
- it('should invalidate queries with query params', async () => {
83
- const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
84
-
85
- await typedClient.invalidateQueries('GET /posts', {
86
- query: { sort: 'asc' },
87
- });
88
-
89
- expect(invalidateSpy).toHaveBeenCalledWith({
90
- queryKey: ['GET /posts', { query: { sort: 'asc' } }],
91
- exact: true,
92
- });
93
- });
94
- });
95
-
96
- describe('invalidateAllQueries', () => {
97
- it('should invalidate all queries', async () => {
98
- const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
99
-
100
- await typedClient.invalidateAllQueries();
101
-
102
- expect(invalidateSpy).toHaveBeenCalledWith();
103
- });
104
- });
105
-
106
- describe('getQueryClient / setQueryClient', () => {
107
- it('should return the query client when provided in constructor', () => {
108
- const client = typedClient.getQueryClient();
109
- expect(client).toBe(queryClient);
110
- });
111
-
112
- it('should throw error when no query client is set', () => {
113
- const clientWithoutQC = new TypedQueryClient();
114
-
115
- expect(() => clientWithoutQC.getQueryClient()).toThrow(
116
- 'No QueryClient set, please provide a QueryClient via the queryClient option or ensure you are within a QueryClientProvider',
117
- );
118
- });
119
-
120
- it('should allow setting query client after construction', () => {
121
- const clientWithoutQC = new TypedQueryClient();
122
- const newQueryClient = new QueryClient();
123
-
124
- clientWithoutQC.setQueryClient(newQueryClient);
125
-
126
- expect(clientWithoutQC.getQueryClient()).toBe(newQueryClient);
127
- });
128
- });
129
-
130
- describe('useTypedInvalidateQueries hook', () => {
131
- const wrapper = ({ children }: { children: React.ReactNode }) => (
132
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
133
- );
134
-
135
- it('should provide invalidateQueries function', async () => {
136
- const { result } = renderHook(
137
- () => useTypedInvalidateQueries(typedClient),
138
- { wrapper },
139
- );
140
-
141
- const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
142
-
143
- await result.current.invalidateQueries('GET /users/{id}', {
144
- params: { id: '456' },
145
- });
146
-
147
- expect(invalidateSpy).toHaveBeenCalledWith({
148
- queryKey: ['GET /users/{id}', { params: { id: '456' } }],
149
- exact: true,
150
- });
151
- });
152
-
153
- it('should provide invalidateAllQueries function', async () => {
154
- const { result } = renderHook(
155
- () => useTypedInvalidateQueries(typedClient),
156
- { wrapper },
157
- );
158
-
159
- const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
160
-
161
- await result.current.invalidateAllQueries();
162
-
163
- expect(invalidateSpy).toHaveBeenCalledWith();
164
- });
165
- });
166
-
167
- describe('Integration test: Query invalidation with real queries', () => {
168
- it('should invalidate matching queries after mutation', async () => {
169
- // Set up some queries in the cache
170
- queryClient.setQueryData(
171
- ['GET /users'],
172
- [
173
- { id: '1', name: 'User 1' },
174
- { id: '2', name: 'User 2' },
175
- ],
176
- );
177
- queryClient.setQueryData(['GET /users/{id}', { params: { id: '1' } }], {
178
- id: '1',
179
- name: 'User 1',
180
- });
181
- queryClient.setQueryData(
182
- ['GET /users', { query: { page: 1 } }],
183
- [{ id: '1', name: 'User 1' }],
184
- );
185
-
186
- // Verify data is in cache
187
- expect(queryClient.getQueryData(['GET /users'])).toBeDefined();
188
- expect(
189
- queryClient.getQueryData(['GET /users/{id}', { params: { id: '1' } }]),
190
- ).toBeDefined();
191
- expect(
192
- queryClient.getQueryData(['GET /users', { query: { page: 1 } }]),
193
- ).toBeDefined();
194
-
195
- // Invalidate all user queries (partial match)
196
- await typedClient.invalidateQueries('GET /users');
197
-
198
- // All queries starting with 'GET /users' should be invalidated
199
- await waitFor(() => {
200
- const cache = queryClient.getQueryCache();
201
- const queries = cache.findAll({ queryKey: ['GET /users'] });
202
- queries.forEach((query) => {
203
- expect(query.state.isInvalidated).toBe(true);
204
- });
205
- });
206
- });
207
-
208
- it('should only invalidate exact matches when config is provided', async () => {
209
- // Set up queries
210
- queryClient.setQueryData(
211
- ['GET /users', { query: { page: 1 } }],
212
- [{ id: '1', name: 'User 1' }],
213
- );
214
- queryClient.setQueryData(
215
- ['GET /users', { query: { page: 2 } }],
216
- [{ id: '2', name: 'User 2' }],
217
- );
218
-
219
- // Invalidate only page 1
220
- await typedClient.invalidateQueries('GET /users', {
221
- query: { page: 1 },
222
- });
223
-
224
- await waitFor(() => {
225
- const cache = queryClient.getQueryCache();
226
- const page1Query = cache.find({
227
- queryKey: ['GET /users', { query: { page: 1 } }],
228
- });
229
- const page2Query = cache.find({
230
- queryKey: ['GET /users', { query: { page: 2 } }],
231
- });
232
-
233
- expect(page1Query?.state.isInvalidated).toBe(true);
234
- expect(page2Query?.state.isInvalidated).toBe(false);
235
- });
236
- });
237
- });
18
+ let queryClient: QueryClient;
19
+ let typedClient: TypedQueryClient<paths>;
20
+
21
+ beforeEach(() => {
22
+ queryClient = new QueryClient({
23
+ defaultOptions: {
24
+ queries: { retry: false },
25
+ },
26
+ });
27
+ typedClient = new TypedQueryClient({ queryClient });
28
+ });
29
+
30
+ describe('buildQueryKey', () => {
31
+ it('should build query key with endpoint only', () => {
32
+ const key = typedClient.buildQueryKey('GET /users');
33
+ expect(key).toEqual(['GET /users']);
34
+ });
35
+
36
+ it('should build query key with params', () => {
37
+ const key = typedClient.buildQueryKey('GET /users/{id}', {
38
+ params: { id: '123' },
39
+ });
40
+ expect(key).toEqual(['GET /users/{id}', { params: { id: '123' } }]);
41
+ });
42
+
43
+ it('should build query key with query params', () => {
44
+ const key = typedClient.buildQueryKey('GET /users', {
45
+ query: { page: 1, limit: 10 },
46
+ });
47
+ expect(key).toEqual(['GET /users', { query: { page: 1, limit: 10 } }]);
48
+ });
49
+
50
+ it('should build query key with params only for paths without query support', () => {
51
+ const key = typedClient.buildQueryKey('GET /users/{id}', {
52
+ params: { id: '123' },
53
+ });
54
+ expect(key).toEqual(['GET /users/{id}', { params: { id: '123' } }]);
55
+ });
56
+ });
57
+
58
+ describe('invalidateQueries', () => {
59
+ it('should invalidate queries with endpoint only (partial match)', async () => {
60
+ const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
61
+
62
+ await typedClient.invalidateQueries('GET /users');
63
+
64
+ expect(invalidateSpy).toHaveBeenCalledWith({
65
+ queryKey: ['GET /users'],
66
+ exact: false,
67
+ });
68
+ });
69
+
70
+ it('should invalidate queries with config (exact match)', async () => {
71
+ const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
72
+
73
+ await typedClient.invalidateQueries('GET /users/{id}', {
74
+ params: { id: '123' },
75
+ });
76
+
77
+ expect(invalidateSpy).toHaveBeenCalledWith({
78
+ queryKey: ['GET /users/{id}', { params: { id: '123' } }],
79
+ exact: true,
80
+ });
81
+ });
82
+
83
+ it('should invalidate queries with query params', async () => {
84
+ const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
85
+
86
+ await typedClient.invalidateQueries('GET /posts', {
87
+ query: { sort: 'asc' },
88
+ });
89
+
90
+ expect(invalidateSpy).toHaveBeenCalledWith({
91
+ queryKey: ['GET /posts', { query: { sort: 'asc' } }],
92
+ exact: true,
93
+ });
94
+ });
95
+ });
96
+
97
+ describe('invalidateAllQueries', () => {
98
+ it('should invalidate all queries', async () => {
99
+ const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
100
+
101
+ await typedClient.invalidateAllQueries();
102
+
103
+ expect(invalidateSpy).toHaveBeenCalledWith();
104
+ });
105
+ });
106
+
107
+ describe('getQueryClient / setQueryClient', () => {
108
+ it('should return the query client when provided in constructor', () => {
109
+ const client = typedClient.getQueryClient();
110
+ expect(client).toBe(queryClient);
111
+ });
112
+
113
+ it('should throw error when no query client is set', () => {
114
+ const clientWithoutQC = new TypedQueryClient();
115
+
116
+ expect(() => clientWithoutQC.getQueryClient()).toThrow(
117
+ 'No QueryClient set, please provide a QueryClient via the queryClient option or ensure you are within a QueryClientProvider',
118
+ );
119
+ });
120
+
121
+ it('should allow setting query client after construction', () => {
122
+ const clientWithoutQC = new TypedQueryClient();
123
+ const newQueryClient = new QueryClient();
124
+
125
+ clientWithoutQC.setQueryClient(newQueryClient);
126
+
127
+ expect(clientWithoutQC.getQueryClient()).toBe(newQueryClient);
128
+ });
129
+ });
130
+
131
+ describe('useTypedInvalidateQueries hook', () => {
132
+ const wrapper = ({ children }: { children: React.ReactNode }) => (
133
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
134
+ );
135
+
136
+ it('should provide invalidateQueries function', async () => {
137
+ const { result } = renderHook(
138
+ () => useTypedInvalidateQueries(typedClient),
139
+ { wrapper },
140
+ );
141
+
142
+ const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
143
+
144
+ await result.current.invalidateQueries('GET /users/{id}', {
145
+ params: { id: '456' },
146
+ });
147
+
148
+ expect(invalidateSpy).toHaveBeenCalledWith({
149
+ queryKey: ['GET /users/{id}', { params: { id: '456' } }],
150
+ exact: true,
151
+ });
152
+ });
153
+
154
+ it('should provide invalidateAllQueries function', async () => {
155
+ const { result } = renderHook(
156
+ () => useTypedInvalidateQueries(typedClient),
157
+ { wrapper },
158
+ );
159
+
160
+ const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
161
+
162
+ await result.current.invalidateAllQueries();
163
+
164
+ expect(invalidateSpy).toHaveBeenCalledWith();
165
+ });
166
+ });
167
+
168
+ describe('Integration test: Query invalidation with real queries', () => {
169
+ it('should invalidate matching queries after mutation', async () => {
170
+ // Set up some queries in the cache
171
+ queryClient.setQueryData(
172
+ ['GET /users'],
173
+ [
174
+ { id: '1', name: 'User 1' },
175
+ { id: '2', name: 'User 2' },
176
+ ],
177
+ );
178
+ queryClient.setQueryData(['GET /users/{id}', { params: { id: '1' } }], {
179
+ id: '1',
180
+ name: 'User 1',
181
+ });
182
+ queryClient.setQueryData(
183
+ ['GET /users', { query: { page: 1 } }],
184
+ [{ id: '1', name: 'User 1' }],
185
+ );
186
+
187
+ // Verify data is in cache
188
+ expect(queryClient.getQueryData(['GET /users'])).toBeDefined();
189
+ expect(
190
+ queryClient.getQueryData(['GET /users/{id}', { params: { id: '1' } }]),
191
+ ).toBeDefined();
192
+ expect(
193
+ queryClient.getQueryData(['GET /users', { query: { page: 1 } }]),
194
+ ).toBeDefined();
195
+
196
+ // Invalidate all user queries (partial match)
197
+ await typedClient.invalidateQueries('GET /users');
198
+
199
+ // All queries starting with 'GET /users' should be invalidated
200
+ await waitFor(() => {
201
+ const cache = queryClient.getQueryCache();
202
+ const queries = cache.findAll({ queryKey: ['GET /users'] });
203
+ queries.forEach((query) => {
204
+ expect(query.state.isInvalidated).toBe(true);
205
+ });
206
+ });
207
+ });
208
+
209
+ it('should only invalidate exact matches when config is provided', async () => {
210
+ // Set up queries
211
+ queryClient.setQueryData(
212
+ ['GET /users', { query: { page: 1 } }],
213
+ [{ id: '1', name: 'User 1' }],
214
+ );
215
+ queryClient.setQueryData(
216
+ ['GET /users', { query: { page: 2 } }],
217
+ [{ id: '2', name: 'User 2' }],
218
+ );
219
+
220
+ // Invalidate only page 1
221
+ await typedClient.invalidateQueries('GET /users', {
222
+ query: { page: 1 },
223
+ });
224
+
225
+ await waitFor(() => {
226
+ const cache = queryClient.getQueryCache();
227
+ const page1Query = cache.find({
228
+ queryKey: ['GET /users', { query: { page: 1 } }],
229
+ });
230
+ const page2Query = cache.find({
231
+ queryKey: ['GET /users', { query: { page: 2 } }],
232
+ });
233
+
234
+ expect(page1Query?.state.isInvalidated).toBe(true);
235
+ expect(page2Query?.state.isInvalidated).toBe(false);
236
+ });
237
+ });
238
+ });
238
239
  });