@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,281 +0,0 @@
1
- import { HttpResponse, http } from 'msw';
2
- import { setupServer } from 'msw/node';
3
- import { afterAll, afterEach, beforeAll } from 'vitest';
4
-
5
- // Define request handlers
6
- export const handlers = [
7
- // GET /users
8
- http.get('https://api.example.com/users', () => {
9
- return HttpResponse.json({
10
- users: [
11
- { id: '1', name: 'John Doe', email: 'john@example.com' },
12
- { id: '2', name: 'Jane Smith', email: 'jane@example.com' },
13
- ],
14
- });
15
- }),
16
-
17
- // POST /users
18
- http.post('https://api.example.com/users', async ({ request }) => {
19
- const body = await request.json();
20
- return HttpResponse.json(
21
- {
22
- id: '123',
23
- name: (body as any).name,
24
- email: (body as any).email,
25
- },
26
- { status: 201 },
27
- );
28
- }),
29
-
30
- // GET /users/{id}
31
- http.get('https://api.example.com/users/:id', ({ params }) => {
32
- const { id } = params;
33
- if (id === '404') {
34
- return HttpResponse.json({ message: 'User not found' }, { status: 404 });
35
- }
36
- return HttpResponse.json({
37
- id,
38
- name: 'John Doe',
39
- email: 'john@example.com',
40
- });
41
- }),
42
-
43
- // PUT /users/{id}
44
- http.put('https://api.example.com/users/:id', async ({ params, request }) => {
45
- const { id } = params;
46
- const body = await request.json();
47
- return HttpResponse.json({
48
- id,
49
- name: (body as any).name || 'John Doe',
50
- email: (body as any).email || 'john@example.com',
51
- });
52
- }),
53
-
54
- // PATCH /users/{id}
55
- http.patch(
56
- 'https://api.example.com/users/:id',
57
- async ({ params, request }) => {
58
- const { id } = params;
59
- const body = await request.json();
60
- return HttpResponse.json({
61
- id,
62
- name: (body as any).name || 'John Doe',
63
- email: (body as any).email || 'john@example.com',
64
- });
65
- },
66
- ),
67
-
68
- // DELETE /users/{id}
69
- http.delete('https://api.example.com/users/:id', () => {
70
- return new HttpResponse(null, { status: 204 });
71
- }),
72
-
73
- // GET /posts with query parameters
74
- http.get('https://api.example.com/posts', ({ request }) => {
75
- const url = new URL(request.url);
76
- const page = parseInt(url.searchParams.get('page') || '1', 10);
77
- const limit = parseInt(url.searchParams.get('limit') || '10', 10);
78
- const sort = url.searchParams.get('sort') || 'asc';
79
-
80
- // Generate posts based on page to simulate pagination
81
- const totalPosts = 50;
82
- const startIndex = (page - 1) * limit;
83
- const endIndex = Math.min(startIndex + limit, totalPosts);
84
-
85
- const posts = Array.from({ length: endIndex - startIndex }, (_, i) => ({
86
- id: `post-${startIndex + i + 1}`,
87
- title: `Test Post ${startIndex + i + 1}`,
88
- content: `Test content for post ${startIndex + i + 1}`,
89
- authorId: `author-${((startIndex + i) % 5) + 1}`,
90
- createdAt: new Date(
91
- Date.now() - (startIndex + i) * 3600000,
92
- ).toISOString(),
93
- }));
94
-
95
- return HttpResponse.json({
96
- posts,
97
- pagination: {
98
- page,
99
- limit,
100
- total: totalPosts,
101
- },
102
- sort,
103
- });
104
- }),
105
-
106
- // GET /posts/{postId}
107
- http.get('https://api.example.com/posts/:postId', ({ params, request }) => {
108
- const { postId } = params;
109
- const url = new URL(request.url);
110
- const includeAuthor = url.searchParams.get('includeAuthor') === 'true';
111
-
112
- const response = {
113
- id: postId,
114
- title: 'Test Post',
115
- content: 'Test content',
116
- authorId: '123',
117
- };
118
-
119
- if (includeAuthor) {
120
- return HttpResponse.json({
121
- ...response,
122
- author: { id: '123', name: 'John' },
123
- });
124
- }
125
-
126
- return HttpResponse.json(response);
127
- }),
128
-
129
- // Error endpoint for testing
130
- http.get('https://api.example.com/error', () => {
131
- return HttpResponse.json(
132
- { message: 'Internal server error' },
133
- { status: 500 },
134
- );
135
- }),
136
-
137
- // Unauthorized endpoint
138
- http.get('https://api.example.com/protected', ({ request }) => {
139
- const auth = request.headers.get('Authorization');
140
- if (!auth || !auth.includes('valid-token')) {
141
- return HttpResponse.json({ message: 'Unauthorized' }, { status: 401 });
142
- }
143
- return HttpResponse.json({ message: 'Protected data' });
144
- }),
145
-
146
- // Search endpoint
147
- http.get('https://api.example.com/search', ({ request }) => {
148
- const url = new URL(request.url);
149
- const tags = url.searchParams.getAll('tags');
150
- return HttpResponse.json({
151
- items: tags,
152
- results: tags.map((tag, i) => ({ id: i, tag })),
153
- });
154
- }),
155
-
156
- // Products endpoint with filters
157
- http.get('https://api.example.com/products', ({ request }) => {
158
- const url = new URL(request.url);
159
- const params: Record<string, string> = {};
160
- url.searchParams.forEach((value, key) => {
161
- params[key] = value;
162
- });
163
- return HttpResponse.json({
164
- results: [],
165
- filters: params,
166
- });
167
- }),
168
-
169
- // Advanced search endpoint
170
- http.get('https://api.example.com/advanced-search', ({ request }) => {
171
- const url = new URL(request.url);
172
- const params: Record<string, string> = {};
173
- url.searchParams.forEach((value, key) => {
174
- params[key] = value;
175
- });
176
- return HttpResponse.json({
177
- results: [],
178
- query: params,
179
- });
180
- }),
181
-
182
- // Paginated users endpoint for infinite queries
183
- http.get('https://api.example.com/users/paginated', ({ request }) => {
184
- const url = new URL(request.url);
185
- const page = parseInt(url.searchParams.get('page') || '1', 10);
186
- const limit = parseInt(url.searchParams.get('limit') || '10', 10);
187
-
188
- const allUsers = Array.from({ length: 50 }, (_, i) => ({
189
- id: `user-${i + 1}`,
190
- name: `User ${i + 1}`,
191
- email: `user${i + 1}@example.com`,
192
- }));
193
-
194
- const startIndex = (page - 1) * limit;
195
- const endIndex = startIndex + limit;
196
- const users = allUsers.slice(startIndex, endIndex);
197
- const hasMore = endIndex < allUsers.length;
198
-
199
- return HttpResponse.json({
200
- users,
201
- pagination: {
202
- page,
203
- limit,
204
- total: allUsers.length,
205
- hasMore,
206
- },
207
- });
208
- }),
209
-
210
- // Cursor-based pagination endpoint for infinite queries
211
- http.get('https://api.example.com/messages', ({ request }) => {
212
- const url = new URL(request.url);
213
- const cursor = url.searchParams.get('cursor');
214
- const limit = parseInt(url.searchParams.get('limit') || '10', 10);
215
-
216
- const allMessages = Array.from({ length: 100 }, (_, i) => ({
217
- id: `msg-${i + 1}`,
218
- text: `Message ${i + 1}`,
219
- timestamp: new Date(Date.now() - i * 60000).toISOString(),
220
- }));
221
-
222
- let startIndex = 0;
223
- if (cursor) {
224
- const cursorIndex = allMessages.findIndex((m) => m.id === cursor);
225
- startIndex = cursorIndex !== -1 ? cursorIndex + 1 : 0;
226
- }
227
-
228
- const messages = allMessages.slice(startIndex, startIndex + limit);
229
- const nextCursor =
230
- messages.length === limit ? messages[messages.length - 1].id : null;
231
-
232
- return HttpResponse.json({
233
- messages,
234
- nextCursor,
235
- });
236
- }),
237
-
238
- // Echo endpoint that returns all query parameters
239
- http.get('https://api.example.com/echo', ({ request }) => {
240
- const url = new URL(request.url);
241
- const queryParams: Record<string, string> = {};
242
-
243
- // Collect all query parameters
244
- url.searchParams.forEach((value, key) => {
245
- queryParams[key] = value;
246
- });
247
-
248
- return HttpResponse.json({
249
- queryParams,
250
- // Also include some pagination data for infinite query testing
251
- data: Array.from({ length: 5 }, (_, i) => ({
252
- id: `item-${i + 1}`,
253
- value: `Value ${i + 1}`,
254
- })),
255
- pagination: {
256
- page: parseInt(queryParams.page || '1', 10),
257
- limit: parseInt(queryParams.limit || '10', 10),
258
- total: 50,
259
- hasMore: parseInt(queryParams.page || '1', 10) < 5,
260
- },
261
- });
262
- }),
263
- ];
264
-
265
- export const server = setupServer(...handlers);
266
-
267
- // Establish API mocking before all tests
268
- beforeAll(() => {
269
- server.listen({ onUnhandledRequest: 'error' });
270
- });
271
-
272
- // Reset any request handlers that we may add during the tests,
273
- // so they don't affect other tests
274
- afterEach(() => {
275
- server.resetHandlers();
276
- });
277
-
278
- // Clean up after the tests are finished
279
- afterAll(() => {
280
- server.close();
281
- });
@@ -1,134 +0,0 @@
1
- import { describe, expectTypeOf, it } from 'vitest';
2
- import type { paths } from '../openapi-types';
3
- import type {
4
- ExtractEndpointConfig,
5
- ExtractEndpointResponse,
6
- FilteredRequestConfig,
7
- TypedEndpoint,
8
- ValidEndpoint,
9
- } from '../types';
10
-
11
- describe('Type utilities', () => {
12
- it('should extract valid endpoints from paths', () => {
13
- type ValidEndpoints = TypedEndpoint<paths>;
14
-
15
- // Test that valid endpoints are correctly generated
16
- expectTypeOf<ValidEndpoints>().toExtend<
17
- | 'GET /users'
18
- | 'POST /users'
19
- | 'GET /users/{id}'
20
- | 'PUT /users/{id}'
21
- | 'DELETE /users/{id}'
22
- | 'GET /posts'
23
- | 'GET /protected'
24
- | 'GET /error'
25
- >();
26
- });
27
-
28
- it('should create typed endpoint strings', () => {
29
- type Endpoints = TypedEndpoint<paths>;
30
-
31
- // Test that TypedEndpoint resolves to the same as ValidEndpoint
32
- expectTypeOf<Endpoints>().toEqualTypeOf<ValidEndpoint<paths>>();
33
- });
34
-
35
- it('should extract response types correctly', () => {
36
- type UserResponse = ExtractEndpointResponse<paths, 'GET /users/{id}'>;
37
- type UsersResponse = ExtractEndpointResponse<paths, 'GET /users'>;
38
- type PostsResponse = ExtractEndpointResponse<paths, 'GET /posts'>;
39
-
40
- expectTypeOf<UserResponse>().toEqualTypeOf<{
41
- id: string;
42
- name: string;
43
- email: string;
44
- }>();
45
-
46
- expectTypeOf<UsersResponse>().toEqualTypeOf<{
47
- users: Array<{
48
- id: string;
49
- name: string;
50
- email: string;
51
- }>;
52
- }>();
53
-
54
- expectTypeOf<PostsResponse>().toEqualTypeOf<{
55
- posts: Array<{
56
- id: string;
57
- title: string;
58
- content: string;
59
- authorId: string;
60
- createdAt: string;
61
- }>;
62
- pagination: {
63
- page: number;
64
- limit: number;
65
- total: number;
66
- };
67
- sort: 'asc' | 'desc';
68
- }>();
69
- });
70
-
71
- it('should extract config types correctly', () => {
72
- type GetUserConfig = ExtractEndpointConfig<paths, 'GET /users/{id}'>;
73
- type PostUserConfig = ExtractEndpointConfig<paths, 'POST /users'>;
74
- type GetPostsConfig = ExtractEndpointConfig<paths, 'GET /posts'>;
75
-
76
- expectTypeOf<GetUserConfig>().toEqualTypeOf<{
77
- params?: { id: string };
78
- query?: never;
79
- body?: never;
80
- headers?: Record<string, string>;
81
- }>();
82
-
83
- expectTypeOf<PostUserConfig>().toEqualTypeOf<{
84
- params?: never;
85
- query?: never;
86
- body?: { name: string; email: string };
87
- headers?: Record<string, string>;
88
- }>();
89
-
90
- expectTypeOf<GetPostsConfig>().toEqualTypeOf<{
91
- params?: never;
92
- query?: {
93
- page?: number;
94
- limit?: number;
95
- sort?: 'asc' | 'desc';
96
- };
97
- body?: never;
98
- headers?: Record<string, string>;
99
- }>();
100
- });
101
-
102
- it('should filter config to only required properties', () => {
103
- type GetUserFiltered = FilteredRequestConfig<paths, 'GET /users/{id}'>;
104
- type PostUserFiltered = FilteredRequestConfig<paths, 'POST /users'>;
105
- type GetUsersFiltered = FilteredRequestConfig<paths, 'GET /users'>;
106
-
107
- // GET /users/{id} should require params
108
- expectTypeOf<GetUserFiltered>().toEqualTypeOf<{
109
- params?: { id: string };
110
- headers?: Record<string, string>;
111
- }>();
112
-
113
- // POST /users should allow body
114
- expectTypeOf<PostUserFiltered>().toEqualTypeOf<{
115
- body?: { name: string; email: string };
116
- headers?: Record<string, string>;
117
- }>();
118
-
119
- // GET /users should only allow headers (no params, query, or body)
120
- expectTypeOf<GetUsersFiltered>().toEqualTypeOf<{
121
- headers?: Record<string, string>;
122
- }>();
123
- });
124
-
125
- it('should handle endpoints with multiple parameter types', () => {
126
- type PutUserConfig = FilteredRequestConfig<paths, 'PUT /users/{id}'>;
127
-
128
- expectTypeOf<PutUserConfig>().toEqualTypeOf<{
129
- params?: { id: string };
130
- body?: { name?: string; email?: string };
131
- headers?: Record<string, string>;
132
- }>();
133
- });
134
- });
@@ -1,196 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { createTypedFetcher } from '../fetcher';
3
-
4
- describe('URL Path Parameter Parsing', () => {
5
- it('should correctly parse single path parameter', async () => {
6
- const mockFetch = vi.fn().mockResolvedValue(
7
- new Response(JSON.stringify({ success: true }), {
8
- status: 200,
9
- headers: { 'Content-Type': 'application/json' },
10
- }),
11
- );
12
-
13
- const client = createTypedFetcher<any>({
14
- baseURL: 'https://api.example.com',
15
- fetch: mockFetch,
16
- });
17
-
18
- await client('GET /users/{userId}' as any, {
19
- params: { userId: '12345' },
20
- });
21
-
22
- expect(mockFetch).toHaveBeenCalledWith(
23
- 'https://api.example.com/users/12345',
24
- expect.any(Object),
25
- );
26
- });
27
-
28
- it('should correctly parse multiple path parameters', async () => {
29
- const mockFetch = vi.fn().mockResolvedValue(
30
- new Response(JSON.stringify({ success: true }), {
31
- status: 200,
32
- headers: { 'Content-Type': 'application/json' },
33
- }),
34
- );
35
-
36
- const client = createTypedFetcher<any>({
37
- fetch: mockFetch,
38
- baseURL: 'https://api.example.com',
39
- });
40
-
41
- await client(
42
- 'GET /organizations/{orgId}/projects/{projectId}/tasks/{taskId}' as any,
43
- {
44
- params: {
45
- orgId: 'org-123',
46
- projectId: 'proj-456',
47
- taskId: 'task-789',
48
- },
49
- },
50
- );
51
-
52
- expect(mockFetch).toHaveBeenCalledWith(
53
- 'https://api.example.com/organizations/org-123/projects/proj-456/tasks/task-789',
54
- expect.any(Object),
55
- );
56
- });
57
-
58
- it('should URL encode special characters in path parameters', async () => {
59
- const mockFetch = vi.fn().mockResolvedValue(
60
- new Response(JSON.stringify({ success: true }), {
61
- status: 200,
62
- headers: { 'Content-Type': 'application/json' },
63
- }),
64
- );
65
-
66
- const client = createTypedFetcher<any>({
67
- baseURL: 'https://api.example.com',
68
- fetch: mockFetch,
69
- });
70
-
71
- await client('GET /files/{filename}' as any, {
72
- params: {
73
- filename: 'my file with spaces & special#characters.txt',
74
- },
75
- });
76
-
77
- expect(mockFetch).toHaveBeenCalledWith(
78
- 'https://api.example.com/files/my%20file%20with%20spaces%20%26%20special%23characters.txt',
79
- expect.any(Object),
80
- );
81
- });
82
-
83
- it('should handle path parameters with forward slashes', async () => {
84
- const mockFetch = vi.fn().mockResolvedValue(
85
- new Response(JSON.stringify({ success: true }), {
86
- status: 200,
87
- headers: { 'Content-Type': 'application/json' },
88
- }),
89
- );
90
-
91
- const client = createTypedFetcher<any>({
92
- baseURL: 'https://api.example.com',
93
- fetch: mockFetch,
94
- });
95
-
96
- await client('GET /repositories/{repoPath}' as any, {
97
- params: {
98
- repoPath: 'owner/repo/branch',
99
- },
100
- });
101
-
102
- expect(mockFetch).toHaveBeenCalledWith(
103
- 'https://api.example.com/repositories/owner%2Frepo%2Fbranch',
104
- expect.any(Object),
105
- );
106
- });
107
-
108
- it('should handle path parameters and query parameters together', async () => {
109
- const mockFetch = vi.fn().mockResolvedValue(
110
- new Response(JSON.stringify({ success: true }), {
111
- status: 200,
112
- headers: { 'Content-Type': 'application/json' },
113
- }),
114
- );
115
- const client = createTypedFetcher<any>({
116
- baseURL: 'https://api.example.com',
117
- fetch: mockFetch,
118
- });
119
-
120
- await client('GET /users/{userId}/posts' as any, {
121
- params: { userId: 'user-123' },
122
- query: { page: 2, limit: 10, sort: 'desc' },
123
- });
124
-
125
- expect(mockFetch).toHaveBeenCalledWith(
126
- 'https://api.example.com/users/user-123/posts?page=2&limit=10&sort=desc',
127
- expect.any(Object),
128
- );
129
- });
130
-
131
- it('should handle numeric path parameters', async () => {
132
- const mockFetch = vi.fn().mockResolvedValue(
133
- new Response(JSON.stringify({ success: true }), {
134
- status: 200,
135
- headers: { 'Content-Type': 'application/json' },
136
- }),
137
- );
138
- const client = createTypedFetcher<any>({
139
- baseURL: 'https://api.example.com',
140
- fetch: mockFetch,
141
- });
142
-
143
- await client('GET /api/v{version}/users/{id}' as any, {
144
- params: { version: 2, id: 12345 },
145
- });
146
-
147
- expect(mockFetch).toHaveBeenCalledWith(
148
- 'https://api.example.com/api/v2/users/12345',
149
- expect.any(Object),
150
- );
151
- });
152
-
153
- it('should handle empty baseURL', async () => {
154
- const mockFetch = vi.fn().mockResolvedValue(
155
- new Response(JSON.stringify({ success: true }), {
156
- status: 200,
157
- headers: { 'Content-Type': 'application/json' },
158
- }),
159
- );
160
- const client = createTypedFetcher<any>({
161
- baseURL: '',
162
- fetch: mockFetch,
163
- });
164
-
165
- await client('GET /users/{id}' as any, {
166
- params: { id: '123' },
167
- });
168
-
169
- expect(mockFetch).toHaveBeenCalledWith('/users/123', expect.any(Object));
170
- });
171
-
172
- it('should not replace parameters that are not provided', async () => {
173
- const mockFetch = vi.fn().mockResolvedValue(
174
- new Response(JSON.stringify({ success: true }), {
175
- status: 200,
176
- headers: { 'Content-Type': 'application/json' },
177
- }),
178
- );
179
-
180
- const client = createTypedFetcher<any>({
181
- baseURL: 'https://api.example.com',
182
- fetch: mockFetch,
183
- });
184
-
185
- // Missing the userId parameter
186
- await client('GET /users/{userId}/posts/{postId}' as any, {
187
- params: { postId: '456' },
188
- });
189
-
190
- // The {userId} should remain in the URL unchanged
191
- expect(mockFetch).toHaveBeenCalledWith(
192
- 'https://api.example.com/users/{userId}/posts/456',
193
- expect.any(Object),
194
- );
195
- });
196
- });