@geekmidas/client 9.0.2 → 10.0.0-alpha.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 (81) hide show
  1. package/dist/auth-fetcher-CBYuL6rx.d.cts +158 -0
  2. package/dist/auth-fetcher-CBYuL6rx.d.cts.map +1 -0
  3. package/dist/auth-fetcher-DOj0iz21.mjs +77 -0
  4. package/dist/auth-fetcher-DOj0iz21.mjs.map +1 -0
  5. package/dist/auth-fetcher-DxS8zOLc.d.mts +158 -0
  6. package/dist/auth-fetcher-DxS8zOLc.d.mts.map +1 -0
  7. package/dist/auth-fetcher-HILABmws.cjs +82 -0
  8. package/dist/auth-fetcher-HILABmws.cjs.map +1 -0
  9. package/dist/auth-fetcher.cjs +3 -76
  10. package/dist/auth-fetcher.d.cts +3 -158
  11. package/dist/auth-fetcher.d.mts +3 -158
  12. package/dist/auth-fetcher.mjs +3 -76
  13. package/dist/endpoint-hooks.d.mts +1 -1
  14. package/dist/fetcher-C1xtCKpT.d.mts +25 -0
  15. package/dist/fetcher-C1xtCKpT.d.mts.map +1 -0
  16. package/dist/fetcher-cDrfwN-Y.d.cts +25 -0
  17. package/dist/fetcher-cDrfwN-Y.d.cts.map +1 -0
  18. package/dist/fetcher.d.cts +3 -25
  19. package/dist/fetcher.d.mts +3 -25
  20. package/dist/index.cjs +8 -0
  21. package/dist/index.d.cts +5 -0
  22. package/dist/index.d.mts +5 -0
  23. package/dist/index.mjs +6 -0
  24. package/dist/infer-6KKCgmg1.cjs +0 -0
  25. package/{src/infer.ts → dist/infer-DfRq5kIb.d.cts} +54 -83
  26. package/dist/infer-DfRq5kIb.d.cts.map +1 -0
  27. package/dist/infer-bTirNeNW.d.mts +133 -0
  28. package/dist/infer-bTirNeNW.d.mts.map +1 -0
  29. package/dist/infer-uCUq1whM.mjs +0 -0
  30. package/dist/infer.cjs +1 -0
  31. package/dist/infer.d.cts +2 -133
  32. package/dist/infer.d.mts +2 -133
  33. package/dist/infer.mjs +1 -0
  34. package/dist/openapi-hooks.cjs.map +1 -1
  35. package/dist/openapi-hooks.d.cts +3 -3
  36. package/dist/openapi-hooks.d.cts.map +1 -1
  37. package/dist/openapi-hooks.d.mts +1 -1
  38. package/dist/openapi-hooks.d.mts.map +1 -1
  39. package/dist/openapi-hooks.mjs.map +1 -1
  40. package/dist/react-query.d.cts +7 -7
  41. package/dist/react-query.d.mts +1 -1
  42. package/dist/types-BH8WgGrm.mjs +0 -0
  43. package/dist/{types-D8Jrl4o3.d.mts → types-BMGM6sZc.d.mts} +1 -1
  44. package/dist/{types-D8Jrl4o3.d.mts.map → types-BMGM6sZc.d.mts.map} +1 -1
  45. package/dist/types-a8gm_IaQ.cjs +0 -0
  46. package/dist/types.cjs +1 -0
  47. package/dist/types.d.mts +1 -1
  48. package/dist/types.mjs +1 -0
  49. package/package.json +8 -5
  50. package/CHANGELOG.md +0 -146
  51. package/dist/auth-fetcher.cjs.map +0 -1
  52. package/dist/auth-fetcher.d.cts.map +0 -1
  53. package/dist/auth-fetcher.d.mts.map +0 -1
  54. package/dist/auth-fetcher.mjs.map +0 -1
  55. package/dist/fetcher.d.cts.map +0 -1
  56. package/dist/fetcher.d.mts.map +0 -1
  57. package/dist/infer.d.cts.map +0 -1
  58. package/dist/infer.d.mts.map +0 -1
  59. package/src/__tests__/auth-fetcher.spec.ts +0 -505
  60. package/src/__tests__/endpoint-hooks.spec.tsx +0 -374
  61. package/src/__tests__/fetcher.spec.ts +0 -580
  62. package/src/__tests__/infer.integration.spec.ts +0 -188
  63. package/src/__tests__/infer.spec.ts +0 -189
  64. package/src/__tests__/method-restrictions.spec.tsx +0 -227
  65. package/src/__tests__/mutation-inference.spec.tsx +0 -343
  66. package/src/__tests__/openapi-hooks.spec.tsx +0 -557
  67. package/src/__tests__/react-query-infinite.spec.tsx +0 -1003
  68. package/src/__tests__/react-query-invalidation.spec.tsx +0 -239
  69. package/src/__tests__/react-query.spec.tsx +0 -582
  70. package/src/__tests__/setup.ts +0 -281
  71. package/src/__tests__/types.spec.ts +0 -134
  72. package/src/__tests__/url-parsing.spec.ts +0 -196
  73. package/src/auth-fetcher.ts +0 -288
  74. package/src/endpoint-hooks.ts +0 -346
  75. package/src/fetcher.ts +0 -171
  76. package/src/openapi-hooks.ts +0 -193
  77. package/src/openapi-types.d.ts +0 -440
  78. package/src/openapi.json +0 -595
  79. package/src/react-query.ts +0 -341
  80. package/src/types.ts +0 -226
  81. package/tsconfig.json +0 -12
@@ -1,557 +0,0 @@
1
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
- /**
3
- * @vitest-environment jsdom
4
- */
5
- import { renderHook, waitFor } from '@testing-library/react';
6
- import { afterEach, describe, expect, it, vi } from 'vitest';
7
- import { createOpenAPIHooks } from '../openapi-hooks';
8
- import './setup';
9
-
10
- // Test OpenAPI types
11
- interface TestPaths {
12
- '/users': {
13
- get: {
14
- operationId: 'listUsers';
15
- parameters?: {
16
- query?: {
17
- page?: number;
18
- limit?: number;
19
- search?: string;
20
- };
21
- };
22
- responses: {
23
- 200: {
24
- content: {
25
- 'application/json': {
26
- users: Array<{
27
- id: string;
28
- name: string;
29
- email: string;
30
- }>;
31
- total: number;
32
- };
33
- };
34
- };
35
- };
36
- };
37
- post: {
38
- operationId: 'createUser';
39
- requestBody: {
40
- content: {
41
- 'application/json': {
42
- name: string;
43
- email: string;
44
- password: string;
45
- };
46
- };
47
- };
48
- responses: {
49
- 201: {
50
- content: {
51
- 'application/json': {
52
- id: string;
53
- name: string;
54
- email: string;
55
- };
56
- };
57
- };
58
- };
59
- };
60
- };
61
- '/users/{id}': {
62
- parameters: {
63
- path: {
64
- id: string;
65
- };
66
- };
67
- get: {
68
- operationId: 'getUser';
69
- responses: {
70
- 200: {
71
- content: {
72
- 'application/json': {
73
- id: string;
74
- name: string;
75
- email: string;
76
- createdAt: string;
77
- };
78
- };
79
- };
80
- };
81
- };
82
- patch: {
83
- operationId: 'updateUser';
84
- requestBody: {
85
- content: {
86
- 'application/json': {
87
- name?: string;
88
- email?: string;
89
- };
90
- };
91
- };
92
- responses: {
93
- 200: {
94
- content: {
95
- 'application/json': {
96
- id: string;
97
- name: string;
98
- email: string;
99
- };
100
- };
101
- };
102
- };
103
- };
104
- delete: {
105
- operationId: 'deleteUser';
106
- responses: {
107
- 204: {};
108
- };
109
- };
110
- };
111
- '/posts/{postId}': {
112
- get: {
113
- operationId: 'getPost';
114
- parameters: {
115
- path: {
116
- postId: string;
117
- };
118
- query?: {
119
- includeAuthor?: boolean;
120
- };
121
- };
122
- responses: {
123
- 200: {
124
- content: {
125
- 'application/json': {
126
- id: string;
127
- title: string;
128
- content: string;
129
- authorId: string;
130
- author?: {
131
- id: string;
132
- name: string;
133
- };
134
- };
135
- };
136
- };
137
- };
138
- };
139
- };
140
- }
141
-
142
- // Note: fetch is mocked by MSW in setup.ts
143
-
144
- // Test wrapper
145
- function createWrapper() {
146
- const queryClient = new QueryClient({
147
- defaultOptions: {
148
- queries: { retry: false },
149
- mutations: { retry: false },
150
- },
151
- });
152
-
153
- return ({ children }: { children: any }) => (
154
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
155
- );
156
- }
157
-
158
- describe('createOpenAPIHooks', () => {
159
- const operations = {
160
- listUsers: { path: '/users', method: 'get' },
161
- createUser: { path: '/users', method: 'post' },
162
- getUser: { path: '/users/{id}', method: 'get' },
163
- updateUser: { path: '/users/{id}', method: 'patch' },
164
- deleteUser: { path: '/users/{id}', method: 'delete' },
165
- getPost: { path: '/posts/{postId}', method: 'get' },
166
- };
167
-
168
- afterEach(() => {
169
- vi.clearAllMocks();
170
- });
171
-
172
- describe('useQuery', () => {
173
- it('should fetch data for simple GET operation', async () => {
174
- // MSW will return the predefined response from setup.ts
175
-
176
- const api = createOpenAPIHooks<TestPaths>({
177
- baseURL: 'https://api.example.com',
178
- operations,
179
- });
180
-
181
- const { result } = renderHook(() => api.useQuery('listUsers'), {
182
- wrapper: createWrapper(),
183
- });
184
-
185
- await waitFor(() => {
186
- expect(result.current.isSuccess).toBe(true);
187
- });
188
-
189
- expect(result.current.data).toEqual({
190
- users: [
191
- { id: '1', name: 'John Doe', email: 'john@example.com' },
192
- { id: '2', name: 'Jane Smith', email: 'jane@example.com' },
193
- ],
194
- });
195
- });
196
-
197
- it('should handle query parameters', async () => {
198
- // MSW will return the predefined response from setup.ts
199
-
200
- const api = createOpenAPIHooks<TestPaths>({
201
- baseURL: 'https://api.example.com',
202
- operations,
203
- });
204
-
205
- const { result } = renderHook(
206
- () =>
207
- api.useQuery('listUsers', {
208
- // query: { page: 2, limit: 10, search: 'john' },
209
- }),
210
- { wrapper: createWrapper() },
211
- );
212
-
213
- await waitFor(() => {
214
- expect(result.current.isSuccess).toBe(true);
215
- });
216
-
217
- // Query parameters are handled by MSW, verify data structure
218
- expect(result.current.data).toBeDefined();
219
- });
220
-
221
- it('should handle path parameters', async () => {
222
- // MSW will return the predefined response from setup.ts
223
-
224
- const api = createOpenAPIHooks<TestPaths>({
225
- baseURL: 'https://api.example.com',
226
- operations,
227
- });
228
-
229
- const { result } = renderHook(
230
- () =>
231
- api.useQuery('getUser', {
232
- params: { id: '123' },
233
- }),
234
- { wrapper: createWrapper() },
235
- );
236
-
237
- await waitFor(() => {
238
- expect(result.current.isSuccess).toBe(true);
239
- });
240
-
241
- expect(result.current.data).toEqual({
242
- id: '123',
243
- name: 'John Doe',
244
- email: 'john@example.com',
245
- });
246
- });
247
-
248
- it('should handle both path and query parameters', async () => {
249
- // MSW will return the predefined response from setup.ts
250
-
251
- const api = createOpenAPIHooks<TestPaths>({
252
- baseURL: 'https://api.example.com',
253
- operations,
254
- });
255
-
256
- const { result } = renderHook(
257
- () =>
258
- api.useQuery('getPost', {
259
- params: { postId: '456' },
260
- query: { includeAuthor: true },
261
- }),
262
- { wrapper: createWrapper() },
263
- );
264
-
265
- await waitFor(() => {
266
- expect(result.current.isSuccess).toBe(true);
267
- });
268
-
269
- expect(result.current.data).toEqual({
270
- id: '456',
271
- title: 'Test Post',
272
- content: 'Test content',
273
- authorId: '123',
274
- author: { id: '123', name: 'John' },
275
- });
276
- });
277
-
278
- it('should use proper query key for caching', async () => {
279
- // MSW will handle the responses
280
-
281
- const api = createOpenAPIHooks<TestPaths>({
282
- baseURL: 'https://api.example.com',
283
- operations,
284
- });
285
-
286
- const { result: result1 } = renderHook(
287
- () =>
288
- api.useQuery('listUsers', {
289
- query: { page: 1 },
290
- }),
291
- { wrapper: createWrapper() },
292
- );
293
-
294
- const { result: result2 } = renderHook(
295
- () =>
296
- api.useQuery('listUsers', {
297
- query: { page: 1 },
298
- }),
299
- { wrapper: createWrapper() },
300
- );
301
-
302
- await waitFor(() => {
303
- expect(result1.current.isSuccess).toBe(true);
304
- expect(result2.current.isSuccess).toBe(true);
305
- });
306
-
307
- // Both queries should have the same data due to caching
308
- expect(result1.current.data).toEqual(result2.current.data);
309
- });
310
- });
311
-
312
- describe('useMutation', () => {
313
- it('should handle POST mutation', async () => {
314
- // MSW will return the predefined response from setup.ts
315
-
316
- const api = createOpenAPIHooks<TestPaths>({
317
- baseURL: 'https://api.example.com',
318
- operations,
319
- });
320
-
321
- const { result } = renderHook(() => api.useMutation('createUser'), {
322
- wrapper: createWrapper(),
323
- });
324
-
325
- result.current.mutate({
326
- body: {
327
- name: 'New User',
328
- email: 'new@example.com',
329
- password: 'secret123',
330
- },
331
- });
332
-
333
- await waitFor(() => {
334
- expect(result.current.isSuccess).toBe(true);
335
- });
336
-
337
- expect(result.current.data).toEqual({
338
- id: '123',
339
- name: 'New User',
340
- email: 'new@example.com',
341
- });
342
- });
343
-
344
- it('should handle PATCH mutation with path params', async () => {
345
- // MSW will return the predefined response from setup.ts
346
-
347
- const api = createOpenAPIHooks<TestPaths>({
348
- baseURL: 'https://api.example.com',
349
- operations,
350
- });
351
-
352
- const { result } = renderHook(() => api.useMutation('updateUser'), {
353
- wrapper: createWrapper(),
354
- });
355
-
356
- result.current.mutate({
357
- params: { id: '123' },
358
- body: { name: 'Updated Name' },
359
- });
360
-
361
- await waitFor(() => {
362
- expect(result.current.isSuccess).toBe(true);
363
- });
364
-
365
- expect(result.current.data).toEqual({
366
- id: '123',
367
- name: 'Updated Name',
368
- email: 'john@example.com',
369
- });
370
- });
371
-
372
- it('should handle DELETE mutation returning void', async () => {
373
- // MSW will return 204 No Content for DELETE
374
-
375
- const api = createOpenAPIHooks<TestPaths>({
376
- baseURL: 'https://api.example.com',
377
- operations,
378
- });
379
-
380
- const { result } = renderHook(() => api.useMutation('deleteUser'), {
381
- wrapper: createWrapper(),
382
- });
383
-
384
- result.current.mutate({
385
- params: { id: '123' },
386
- });
387
-
388
- await waitFor(() => {
389
- expect(result.current.isSuccess).toBe(true);
390
- });
391
-
392
- expect(result.current.data).toBeUndefined();
393
- });
394
-
395
- it('should handle mutation options', async () => {
396
- // MSW will handle the response
397
-
398
- const onSuccess = vi.fn();
399
- const onError = vi.fn();
400
-
401
- const api = createOpenAPIHooks<TestPaths>({
402
- baseURL: 'https://api.example.com',
403
- operations,
404
- });
405
-
406
- const { result } = renderHook(
407
- () =>
408
- api.useMutation('createUser', {
409
- onSuccess,
410
- onError,
411
- }),
412
- { wrapper: createWrapper() },
413
- );
414
-
415
- result.current.mutate({
416
- body: {
417
- name: 'Test',
418
- email: 'test@test.com',
419
- password: 'password',
420
- },
421
- });
422
-
423
- await waitFor(() => {
424
- expect(result.current.isSuccess).toBe(true);
425
- });
426
-
427
- expect(onSuccess).toHaveBeenCalled();
428
- expect(onSuccess.mock.calls[0]?.[0]).toEqual({
429
- id: '123',
430
- name: 'Test',
431
- email: 'test@test.com',
432
- });
433
- expect(onError).not.toHaveBeenCalled();
434
- });
435
- });
436
-
437
- describe('buildEndpoint', () => {
438
- it('should use operation registry when provided', () => {
439
- const api = createOpenAPIHooks<TestPaths>({
440
- baseURL: 'https://api.example.com',
441
- operations,
442
- });
443
-
444
- // The endpoint should be built correctly based on the registry
445
- const { result } = renderHook(() => api.useQuery('listUsers'), {
446
- wrapper: createWrapper(),
447
- });
448
-
449
- // Wait for the query to be initiated
450
- expect(result.current.isLoading).toBe(true);
451
- });
452
-
453
- it('should work without operation registry', () => {
454
- const api = createOpenAPIHooks<TestPaths>({
455
- baseURL: 'https://api.example.com',
456
- });
457
-
458
- // Without registry, it should use operationId as fallback
459
- const { result } = renderHook(() => api.useQuery('listUsers'), {
460
- wrapper: createWrapper(),
461
- });
462
-
463
- expect(result.current.isLoading).toBe(true);
464
- });
465
- });
466
-
467
- describe('type inference', () => {
468
- it('should infer correct response types', () => {
469
- const api = createOpenAPIHooks<TestPaths>({
470
- baseURL: 'https://api.example.com',
471
- operations,
472
- });
473
-
474
- const { result } = renderHook(() => api.useQuery('listUsers'), {
475
- wrapper: createWrapper(),
476
- });
477
-
478
- // Type test - this should compile without errors
479
- if (result.current.data) {
480
- const users: Array<{ id: string; name: string; email: string }> =
481
- result.current.data.users;
482
- const total: number = result.current.data.total;
483
- expect(users).toBeDefined();
484
- expect(total).toBeDefined();
485
- }
486
- });
487
-
488
- it('should enforce required parameters', () => {
489
- const api = createOpenAPIHooks<TestPaths>({
490
- baseURL: 'https://api.example.com',
491
- operations,
492
- });
493
-
494
- // This test is about type checking, not runtime behavior
495
- // The TypeScript compiler enforces these constraints:
496
-
497
- // ✓ This compiles - no params required for listUsers
498
- const listUsersHook = () => api.useQuery('listUsers');
499
-
500
- // ✓ This compiles - params are provided for getUser
501
- const getUserHook = () =>
502
- api.useQuery('getUser', { params: { id: '123' } });
503
-
504
- // ✗ This would not compile - missing required params
505
- // const invalidHook = () => api.useQuery('getUser');
506
-
507
- expect(listUsersHook).toBeDefined();
508
- expect(getUserHook).toBeDefined();
509
- });
510
-
511
- it('should handle optional parameters correctly', () => {
512
- const api = createOpenAPIHooks<TestPaths>({
513
- baseURL: 'https://api.example.com',
514
- operations,
515
- });
516
-
517
- // All valid ways to call listUsers - wrapped in functions
518
- const hook1 = () => api.useQuery('listUsers');
519
- const hook2 = () => api.useQuery('listUsers', {});
520
- const hook3 = () => api.useQuery('listUsers', { query: {} });
521
- const hook4 = () => api.useQuery('listUsers', { query: { page: 1 } });
522
- const hook5 = () =>
523
- api.useQuery('listUsers', { query: { page: 1, limit: 10 } });
524
-
525
- expect(hook1).toBeDefined();
526
- expect(hook2).toBeDefined();
527
- expect(hook3).toBeDefined();
528
- expect(hook4).toBeDefined();
529
- expect(hook5).toBeDefined();
530
- });
531
- });
532
-
533
- describe('error handling', () => {
534
- it.skip('should handle fetch errors', async () => {
535
- // This test is skipped because we need a way to trigger actual fetch errors
536
- // The current implementation always returns successful responses from MSW
537
- });
538
-
539
- it('should handle non-ok responses', async () => {
540
- // MSW will return 404 for user id '404'
541
-
542
- const api = createOpenAPIHooks<TestPaths>({
543
- baseURL: 'https://api.example.com',
544
- operations,
545
- });
546
-
547
- const { result } = renderHook(
548
- () => api.useQuery('getUser', { params: { id: '404' } }),
549
- { wrapper: createWrapper() },
550
- );
551
-
552
- await waitFor(() => {
553
- expect(result.current.isError).toBe(true);
554
- });
555
- });
556
- });
557
- });