@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,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
- });