@geekmidas/client 9.0.2 → 10.0.0-alpha.1

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 (79) 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.map +1 -1
  36. package/dist/openapi-hooks.d.mts +1 -1
  37. package/dist/openapi-hooks.d.mts.map +1 -1
  38. package/dist/openapi-hooks.mjs.map +1 -1
  39. package/dist/react-query.d.mts +1 -1
  40. package/dist/types-BH8WgGrm.mjs +0 -0
  41. package/dist/{types-D8Jrl4o3.d.mts → types-BMGM6sZc.d.mts} +1 -1
  42. package/dist/{types-D8Jrl4o3.d.mts.map → types-BMGM6sZc.d.mts.map} +1 -1
  43. package/dist/types-a8gm_IaQ.cjs +0 -0
  44. package/dist/types.cjs +1 -0
  45. package/dist/types.d.mts +1 -1
  46. package/dist/types.mjs +1 -0
  47. package/package.json +8 -5
  48. package/CHANGELOG.md +0 -146
  49. package/dist/auth-fetcher.cjs.map +0 -1
  50. package/dist/auth-fetcher.d.cts.map +0 -1
  51. package/dist/auth-fetcher.d.mts.map +0 -1
  52. package/dist/auth-fetcher.mjs.map +0 -1
  53. package/dist/fetcher.d.cts.map +0 -1
  54. package/dist/fetcher.d.mts.map +0 -1
  55. package/dist/infer.d.cts.map +0 -1
  56. package/dist/infer.d.mts.map +0 -1
  57. package/src/__tests__/auth-fetcher.spec.ts +0 -505
  58. package/src/__tests__/endpoint-hooks.spec.tsx +0 -374
  59. package/src/__tests__/fetcher.spec.ts +0 -580
  60. package/src/__tests__/infer.integration.spec.ts +0 -188
  61. package/src/__tests__/infer.spec.ts +0 -189
  62. package/src/__tests__/method-restrictions.spec.tsx +0 -227
  63. package/src/__tests__/mutation-inference.spec.tsx +0 -343
  64. package/src/__tests__/openapi-hooks.spec.tsx +0 -557
  65. package/src/__tests__/react-query-infinite.spec.tsx +0 -1003
  66. package/src/__tests__/react-query-invalidation.spec.tsx +0 -239
  67. package/src/__tests__/react-query.spec.tsx +0 -582
  68. package/src/__tests__/setup.ts +0 -281
  69. package/src/__tests__/types.spec.ts +0 -134
  70. package/src/__tests__/url-parsing.spec.ts +0 -196
  71. package/src/auth-fetcher.ts +0 -288
  72. package/src/endpoint-hooks.ts +0 -346
  73. package/src/fetcher.ts +0 -171
  74. package/src/openapi-hooks.ts +0 -193
  75. package/src/openapi-types.d.ts +0 -440
  76. package/src/openapi.json +0 -595
  77. package/src/react-query.ts +0 -341
  78. package/src/types.ts +0 -226
  79. package/tsconfig.json +0 -12
@@ -1,188 +0,0 @@
1
- import { e } from '@geekmidas/constructs/endpoints';
2
- import { describe, expectTypeOf, it } from 'vitest';
3
- import { z } from 'zod';
4
- import type { InferOpenApi } from '../infer';
5
-
6
- describe('InferOpenApi - TypedFetcher Integration', () => {
7
- it('should generate paths structure compatible with TypedFetcher', () => {
8
- // Define some endpoints
9
- const getUserEndpoint = e
10
- .get('/users/{id}')
11
- .params(z.object({ id: z.string() }))
12
- .output(z.object({ id: z.string(), name: z.string(), email: z.string() }))
13
- .handle(async ({ params }) => ({
14
- id: params.id,
15
- name: 'John Doe',
16
- email: 'john@example.com',
17
- }));
18
-
19
- const createUserEndpoint = e
20
- .post('/users')
21
- .body(z.object({ name: z.string(), email: z.string() }))
22
- .output(z.object({ id: z.string(), name: z.string(), email: z.string() }))
23
- .handle(async ({ body }) => ({
24
- id: '123',
25
- name: body.name,
26
- email: body.email,
27
- }));
28
-
29
- const listUsersEndpoint = e
30
- .get('/users')
31
- .query(z.object({ page: z.coerce.number().optional() }))
32
- .output(
33
- z.object({
34
- users: z.array(
35
- z.object({ id: z.string(), name: z.string(), email: z.string() }),
36
- ),
37
- }),
38
- )
39
- .handle(async ({ query }) => ({
40
- users: [],
41
- }));
42
-
43
- // Infer paths from endpoints
44
- const endpoints = [
45
- getUserEndpoint,
46
- createUserEndpoint,
47
- listUsersEndpoint,
48
- ] as const;
49
- type Paths = InferOpenApi<typeof endpoints>['paths'];
50
-
51
- // Verify the structure matches TypedFetcher expectations
52
- expectTypeOf<Paths>().toMatchTypeOf<{
53
- '/users/{id}': {
54
- get: {
55
- parameters: {
56
- path: { id: string };
57
- };
58
- responses: {
59
- 200: {
60
- content: {
61
- 'application/json': {
62
- id: string;
63
- name: string;
64
- email: string;
65
- };
66
- };
67
- };
68
- };
69
- };
70
- };
71
- '/users': {
72
- get: {
73
- parameters: {
74
- query: { page?: number };
75
- };
76
- responses: {
77
- 200: {
78
- content: {
79
- 'application/json': {
80
- users: Array<{ id: string; name: string; email: string }>;
81
- };
82
- };
83
- };
84
- };
85
- };
86
- post: {
87
- requestBody: {
88
- content: {
89
- 'application/json': {
90
- name: string;
91
- email: string;
92
- };
93
- };
94
- };
95
- responses: {
96
- 200: {
97
- content: {
98
- 'application/json': {
99
- id: string;
100
- name: string;
101
- email: string;
102
- };
103
- };
104
- };
105
- };
106
- };
107
- };
108
- }>();
109
- });
110
-
111
- it('should handle endpoints with multiple parameter types', () => {
112
- const updateUserEndpoint = e
113
- .put('/users/{id}')
114
- .params(z.object({ id: z.string() }))
115
- .query(z.object({ notify: z.coerce.boolean().optional() }))
116
- .body(z.object({ name: z.string() }))
117
- .output(z.object({ id: z.string(), name: z.string() }))
118
- .handle(async ({ params, query, body }) => ({
119
- id: params.id,
120
- name: body.name,
121
- }));
122
-
123
- type Paths = InferOpenApi<[typeof updateUserEndpoint]>['paths'];
124
-
125
- // Verify all parameter types are present
126
- expectTypeOf<Paths>().toMatchTypeOf<{
127
- '/users/{id}': {
128
- parameters: {
129
- path: { id: string };
130
- query: { notify?: boolean };
131
- };
132
- put: {
133
- parameters: {
134
- path: { id: string };
135
- query: { notify?: boolean };
136
- };
137
- requestBody: {
138
- content: {
139
- 'application/json': {
140
- name: string;
141
- };
142
- };
143
- };
144
- responses: {
145
- 200: {
146
- content: {
147
- 'application/json': {
148
- id: string;
149
- name: string;
150
- };
151
- };
152
- };
153
- };
154
- };
155
- };
156
- }>();
157
- });
158
-
159
- it('should handle endpoints without output schema', () => {
160
- const deleteUserEndpoint = e
161
- .delete('/users/{id}')
162
- .params(z.object({ id: z.string() }))
163
- .handle(async ({ params }) => {
164
- // No return value
165
- });
166
-
167
- type Paths = InferOpenApi<[typeof deleteUserEndpoint]>['paths'];
168
-
169
- // Verify response content is never when no output schema
170
- expectTypeOf<Paths>().toMatchTypeOf<{
171
- '/users/{id}': {
172
- parameters: {
173
- path: { id: string };
174
- };
175
- delete: {
176
- parameters: {
177
- path: { id: string };
178
- };
179
- responses: {
180
- 200: {
181
- content: never;
182
- };
183
- };
184
- };
185
- };
186
- }>();
187
- });
188
- });
@@ -1,189 +0,0 @@
1
- import { e } from '@geekmidas/constructs/endpoints';
2
- import { describe, expectTypeOf, it } from 'vitest';
3
- import { z } from 'zod';
4
- import type { InferOpenApi, InferOpenApiFromEndpoint } from '../infer';
5
-
6
- describe('InferOpenApi', () => {
7
- describe('single endpoint', () => {
8
- it('should infer OpenAPI structure for GET endpoint', () => {
9
- const endpoint = e
10
- .get('/users/{id}')
11
- .params(z.object({ id: z.string() }))
12
- .output(z.object({ id: z.string(), name: z.string() }))
13
- .handle(async ({ params }) => ({
14
- id: params.id,
15
- name: 'John',
16
- }));
17
-
18
- type API = InferOpenApiFromEndpoint<typeof endpoint>;
19
-
20
- expectTypeOf<API>().toMatchTypeOf<{
21
- paths: {
22
- '/users/{id}': {
23
- get: {
24
- responses: {
25
- '200': {
26
- description: string;
27
- };
28
- };
29
- };
30
- };
31
- };
32
- }>();
33
- });
34
-
35
- it('should infer OpenAPI structure for POST endpoint with body', () => {
36
- const endpoint = e
37
- .post('/users')
38
- .body(z.object({ name: z.string(), email: z.string() }))
39
- .output(z.object({ id: z.string(), name: z.string() }))
40
- .handle(async ({ body }) => ({
41
- id: '123',
42
- name: body.name,
43
- }));
44
-
45
- type API = InferOpenApiFromEndpoint<typeof endpoint>;
46
-
47
- expectTypeOf<API>().toMatchTypeOf<{
48
- paths: {
49
- '/users': {
50
- post: {
51
- responses: {
52
- '200': {
53
- description: string;
54
- };
55
- };
56
- };
57
- };
58
- };
59
- }>();
60
- });
61
- });
62
-
63
- describe('multiple endpoints', () => {
64
- it('should merge OpenAPI specs from multiple endpoints', () => {
65
- const getUserEndpoint = e
66
- .get('/users/{id}')
67
- .params(z.object({ id: z.string() }))
68
- .output(z.object({ id: z.string(), name: z.string() }))
69
- .handle(async ({ params }) => ({
70
- id: params.id,
71
- name: 'John',
72
- }));
73
-
74
- const createUserEndpoint = e
75
- .post('/users')
76
- .body(z.object({ name: z.string() }))
77
- .output(z.object({ id: z.string(), name: z.string() }))
78
- .handle(async ({ body }) => ({
79
- id: '123',
80
- name: body.name,
81
- }));
82
-
83
- const endpoints = [getUserEndpoint, createUserEndpoint] as const;
84
-
85
- type API = InferOpenApi<typeof endpoints>;
86
-
87
- // Should have both paths
88
- expectTypeOf<API>().toMatchTypeOf<{
89
- paths: {
90
- '/users/{id}': {
91
- get: unknown;
92
- };
93
- '/users': {
94
- post: unknown;
95
- };
96
- };
97
- }>();
98
- });
99
-
100
- it('should handle endpoints with different HTTP methods on same path', () => {
101
- const getUserEndpoint = e
102
- .get('/users')
103
- .output(z.object({ users: z.array(z.object({ id: z.string() })) }))
104
- .handle(async () => ({
105
- users: [],
106
- }));
107
-
108
- const createUserEndpoint = e
109
- .post('/users')
110
- .body(z.object({ name: z.string() }))
111
- .output(z.object({ id: z.string() }))
112
- .handle(async ({ body }) => ({
113
- id: '123',
114
- }));
115
-
116
- const endpoints = [getUserEndpoint, createUserEndpoint] as const;
117
-
118
- type API = InferOpenApi<typeof endpoints>;
119
-
120
- // Should have both methods on same path
121
- expectTypeOf<API>().toMatchTypeOf<{
122
- paths: {
123
- '/users': {
124
- get: unknown;
125
- post: unknown;
126
- };
127
- };
128
- }>();
129
- });
130
- });
131
-
132
- describe('complex schemas', () => {
133
- it('should handle endpoints with query parameters', () => {
134
- const endpoint = e
135
- .get('/users')
136
- .query(
137
- z.object({
138
- page: z.coerce.number().optional(),
139
- limit: z.coerce.number().optional(),
140
- }),
141
- )
142
- .output(z.object({ users: z.array(z.object({ id: z.string() })) }))
143
- .handle(async ({ query }) => ({
144
- users: [],
145
- }));
146
-
147
- type API = InferOpenApiFromEndpoint<typeof endpoint>;
148
-
149
- expectTypeOf<API>().toMatchTypeOf<{
150
- paths: {
151
- '/users': {
152
- get: {
153
- responses: {
154
- '200': unknown;
155
- };
156
- };
157
- };
158
- };
159
- }>();
160
- });
161
-
162
- it('should handle endpoints with body, params, and query', () => {
163
- const endpoint = e
164
- .put('/users/{id}')
165
- .params(z.object({ id: z.string() }))
166
- .query(z.object({ notify: z.coerce.boolean().optional() }))
167
- .body(z.object({ name: z.string() }))
168
- .output(z.object({ id: z.string(), name: z.string() }))
169
- .handle(async ({ params, body }) => ({
170
- id: params.id,
171
- name: body.name,
172
- }));
173
-
174
- type API = InferOpenApiFromEndpoint<typeof endpoint>;
175
-
176
- expectTypeOf<API>().toMatchTypeOf<{
177
- paths: {
178
- '/users/{id}': {
179
- put: {
180
- responses: {
181
- '200': unknown;
182
- };
183
- };
184
- };
185
- };
186
- }>();
187
- });
188
- });
189
- });
@@ -1,227 +0,0 @@
1
- /**
2
- * @vitest-environment jsdom
3
- */
4
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
- import { renderHook } from '@testing-library/react';
6
- // biome-ignore lint/style/useImportType: <explanation>
7
- import React from 'react';
8
- import { describe, expect, it } from 'vitest';
9
- import type { paths } from '../openapi-types';
10
- import { createTypedQueryClient } from '../react-query';
11
- import './setup';
12
-
13
- describe('Method Restrictions', () => {
14
- const queryClient = new QueryClient({
15
- defaultOptions: {
16
- queries: {
17
- retry: false,
18
- },
19
- },
20
- });
21
-
22
- const wrapper = ({ children }: { children: React.ReactNode }) => (
23
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
24
- );
25
-
26
- describe('useQuery', () => {
27
- it('should accept GET endpoints', () => {
28
- const typedClient = createTypedQueryClient<paths>({
29
- baseURL: 'https://api.example.com',
30
- });
31
-
32
- // This should compile - GET endpoints are allowed
33
- const { result } = renderHook(() => typedClient.useQuery('GET /users'), {
34
- wrapper,
35
- });
36
-
37
- expect(result.current).toBeDefined();
38
- });
39
-
40
- it('should accept GET endpoints with parameters', () => {
41
- const typedClient = createTypedQueryClient<paths>({
42
- baseURL: 'https://api.example.com',
43
- });
44
-
45
- // This should compile - GET endpoints with params are allowed
46
- const { result } = renderHook(
47
- () =>
48
- typedClient.useQuery('GET /users/{id}', {
49
- params: { id: '123' },
50
- }),
51
- { wrapper },
52
- );
53
-
54
- expect(result.current).toBeDefined();
55
- });
56
-
57
- it('should accept GET endpoints with query parameters', () => {
58
- const typedClient = createTypedQueryClient<paths>({
59
- baseURL: 'https://api.example.com',
60
- });
61
-
62
- // This should compile - GET endpoints with query params are allowed
63
- const { result } = renderHook(
64
- () =>
65
- typedClient.useQuery('GET /posts', {
66
- query: { page: 1, limit: 10 },
67
- }),
68
- { wrapper },
69
- );
70
-
71
- expect(result.current).toBeDefined();
72
- });
73
-
74
- // The following tests would fail TypeScript compilation if uncommented
75
- // They are left here as documentation of what should NOT work
76
-
77
- /*
78
- it('should NOT accept POST endpoints', () => {
79
- const typedClient = createTypedQueryClient<paths>({
80
- baseURL: 'https://api.example.com',
81
- });
82
-
83
- // @ts-expect-error - POST endpoints should not be allowed in useQuery
84
- const { result } = renderHook(
85
- () => typedClient.useQuery('POST /users'),
86
- { wrapper },
87
- );
88
- });
89
-
90
- it('should NOT accept PUT endpoints', () => {
91
- const typedClient = createTypedQueryClient<paths>({
92
- baseURL: 'https://api.example.com',
93
- });
94
-
95
- // @ts-expect-error - PUT endpoints should not be allowed in useQuery
96
- const { result } = renderHook(
97
- () => typedClient.useQuery('PUT /users/{id}', { params: { id: '123' } }),
98
- { wrapper },
99
- );
100
- });
101
-
102
- it('should NOT accept DELETE endpoints', () => {
103
- const typedClient = createTypedQueryClient<paths>({
104
- baseURL: 'https://api.example.com',
105
- });
106
-
107
- // @ts-expect-error - DELETE endpoints should not be allowed in useQuery
108
- const { result } = renderHook(
109
- () => typedClient.useQuery('DELETE /users/{id}', { params: { id: '123' } }),
110
- { wrapper },
111
- );
112
- });
113
- */
114
- });
115
-
116
- describe('useMutation', () => {
117
- it('should accept POST endpoints', () => {
118
- const typedClient = createTypedQueryClient<paths>({
119
- baseURL: 'https://api.example.com',
120
- });
121
-
122
- // This should compile - POST endpoints are allowed
123
- const { result } = renderHook(
124
- () => typedClient.useMutation('POST /users'),
125
- { wrapper },
126
- );
127
-
128
- expect(result.current).toBeDefined();
129
- });
130
-
131
- it('should accept PUT endpoints', () => {
132
- const typedClient = createTypedQueryClient<paths>({
133
- baseURL: 'https://api.example.com',
134
- });
135
-
136
- // This should compile - PUT endpoints are allowed
137
- const { result } = renderHook(
138
- () => typedClient.useMutation('PUT /users/{id}'),
139
- { wrapper },
140
- );
141
-
142
- expect(result.current).toBeDefined();
143
- });
144
-
145
- it('should accept DELETE endpoints', () => {
146
- const typedClient = createTypedQueryClient<paths>({
147
- baseURL: 'https://api.example.com',
148
- });
149
-
150
- // This should compile - DELETE endpoints are allowed
151
- const { result } = renderHook(
152
- () => typedClient.useMutation('DELETE /users/{id}'),
153
- { wrapper },
154
- );
155
-
156
- expect(result.current).toBeDefined();
157
- });
158
-
159
- // The following test would fail TypeScript compilation if uncommented
160
- // It is left here as documentation of what should NOT work
161
-
162
- /*
163
- it('should NOT accept GET endpoints', () => {
164
- const typedClient = createTypedQueryClient<paths>({
165
- baseURL: 'https://api.example.com',
166
- });
167
-
168
- // @ts-expect-error - GET endpoints should not be allowed in useMutation
169
- const { result } = renderHook(
170
- () => typedClient.useMutation('GET /users'),
171
- { wrapper },
172
- );
173
- });
174
- */
175
- });
176
-
177
- describe('Type inference', () => {
178
- it('should correctly infer response types for GET requests', () => {
179
- const typedClient = createTypedQueryClient<paths>({
180
- baseURL: 'https://api.example.com',
181
- });
182
-
183
- const { result } = renderHook(() => typedClient.useQuery('GET /users'), {
184
- wrapper,
185
- });
186
-
187
- // TypeScript should infer this type correctly
188
- type ResponseType = typeof result.current.data;
189
- type ExpectedType =
190
- | { users: Array<{ id: string; name: string; email: string }> }
191
- | undefined;
192
-
193
- // This assertion validates that the types match at compile time
194
- const _typeCheck: ResponseType extends ExpectedType ? true : false = true;
195
- const _typeCheck2: ExpectedType extends ResponseType ? true : false =
196
- true;
197
-
198
- expect(_typeCheck).toBe(true);
199
- expect(_typeCheck2).toBe(true);
200
- });
201
-
202
- it('should correctly infer response types for POST requests', () => {
203
- const typedClient = createTypedQueryClient<paths>({
204
- baseURL: 'https://api.example.com',
205
- });
206
-
207
- const { result } = renderHook(
208
- () => typedClient.useMutation('POST /users'),
209
- { wrapper },
210
- );
211
-
212
- // TypeScript should infer this type correctly
213
- type ResponseType = typeof result.current.data;
214
- type ExpectedType =
215
- | { id: string; name: string; email: string }
216
- | undefined;
217
-
218
- // This assertion validates that the types match at compile time
219
- const _typeCheck: ResponseType extends ExpectedType ? true : false = true;
220
- const _typeCheck2: ExpectedType extends ResponseType ? true : false =
221
- true;
222
-
223
- expect(_typeCheck).toBe(true);
224
- expect(_typeCheck2).toBe(true);
225
- });
226
- });
227
- });