@cushin/api-codegen 5.0.1 → 5.0.3
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.
- package/dist/cli.js +164 -201
- package/dist/cli.js.map +1 -1
- package/dist/index.js +164 -201
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -171,6 +171,19 @@ var BaseGenerator = class {
|
|
|
171
171
|
(e) => e.method === "GET"
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
|
+
// Helper methods to get named type references
|
|
175
|
+
getResponseTypeName(name) {
|
|
176
|
+
return `${this.capitalize(name)}Response`;
|
|
177
|
+
}
|
|
178
|
+
getInputTypeName(name) {
|
|
179
|
+
return `${this.capitalize(name)}Input`;
|
|
180
|
+
}
|
|
181
|
+
getQueryTypeName(name) {
|
|
182
|
+
return `${this.capitalize(name)}Query`;
|
|
183
|
+
}
|
|
184
|
+
getParamsTypeName(name) {
|
|
185
|
+
return `${this.capitalize(name)}Params`;
|
|
186
|
+
}
|
|
174
187
|
};
|
|
175
188
|
|
|
176
189
|
// src/generators/hooks.ts
|
|
@@ -183,16 +196,12 @@ var HooksGenerator = class extends BaseGenerator {
|
|
|
183
196
|
}
|
|
184
197
|
generateContent() {
|
|
185
198
|
const useClientDirective = this.context.config.options?.useClientDirective ?? true;
|
|
186
|
-
const outputPath = path2.join(this.context.config.outputDir, "types.ts");
|
|
187
|
-
const endpointsPath = path2.join(this.context.config.endpointsPath);
|
|
188
|
-
const relativePath = path2.relative(path2.dirname(outputPath), endpointsPath).replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
189
199
|
const content = `${useClientDirective ? "'use client';\n" : ""}
|
|
190
200
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
191
201
|
import { apiClient } from "./client";
|
|
192
202
|
import { queryKeys } from "./query-keys";
|
|
193
203
|
import { apiQueryOptions } from "./query-options";
|
|
194
|
-
import
|
|
195
|
-
import { apiConfig } from "${relativePath}";
|
|
204
|
+
import type * as Types from "./types";
|
|
196
205
|
|
|
197
206
|
${this.generateQueryHooks()}
|
|
198
207
|
${this.generateMutationHooks()}
|
|
@@ -213,29 +222,23 @@ ${this.generateMutationHooks()}
|
|
|
213
222
|
const hookName = `use${this.capitalize(name)}`;
|
|
214
223
|
const resource = this.getResourceFromEndpoint(name, endpoint);
|
|
215
224
|
const optionName = this.getEndpointKeyName(name);
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
);
|
|
219
|
-
const inferQuery = this.inferNonNull(
|
|
220
|
-
`typeof apiConfig.endpoints.${name}.query`
|
|
221
|
-
);
|
|
222
|
-
const inferResponse = this.inferNonNull(
|
|
223
|
-
`typeof apiConfig.endpoints.${name}.response`
|
|
224
|
-
);
|
|
225
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
226
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
227
|
+
const queryType = endpoint.query ? `Types.${this.getQueryTypeName(name)}` : null;
|
|
225
228
|
const params = [];
|
|
226
229
|
const optionParams = [];
|
|
227
230
|
const queryTags = this.getQueryTags(endpoint);
|
|
228
|
-
if (
|
|
229
|
-
params.push(`params: ${
|
|
231
|
+
if (paramsType) {
|
|
232
|
+
params.push(`params: ${paramsType}`);
|
|
230
233
|
optionParams.push("params");
|
|
231
234
|
}
|
|
232
|
-
if (
|
|
233
|
-
params.push(`filters?: ${
|
|
235
|
+
if (queryType) {
|
|
236
|
+
params.push(`filters?: ${queryType}`);
|
|
234
237
|
optionParams.push("filters");
|
|
235
238
|
}
|
|
236
239
|
params.push(`options?: {
|
|
237
240
|
enabled?: boolean;
|
|
238
|
-
select?: <TData = ${
|
|
241
|
+
select?: <TData = ${responseType}>(data: ${responseType}) => TData;
|
|
239
242
|
}`);
|
|
240
243
|
return `/**
|
|
241
244
|
* ${endpoint.description || `Query hook for ${name}`}
|
|
@@ -261,26 +264,20 @@ export function ${hookName}(${params.join(",\n ")}) {
|
|
|
261
264
|
generateMutationHook(name, endpoint) {
|
|
262
265
|
const hookName = `use${this.capitalize(name)}`;
|
|
263
266
|
const resource = this.getResourceFromEndpoint(name, endpoint);
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
);
|
|
267
|
-
const inferBody = this.inferNonNull(
|
|
268
|
-
`typeof apiConfig.endpoints.${name}.body`
|
|
269
|
-
);
|
|
270
|
-
const inferResponse = this.inferNonNull(
|
|
271
|
-
`typeof apiConfig.endpoints.${name}.response`
|
|
272
|
-
);
|
|
267
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
268
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
269
|
+
const bodyType = endpoint.body ? `Types.${this.getInputTypeName(name)}` : null;
|
|
273
270
|
const resourceHasQueries = this.resourceHasQueryEndpoints(resource);
|
|
274
271
|
let inputType;
|
|
275
272
|
let fnBody;
|
|
276
|
-
if (
|
|
277
|
-
inputType = `{ params: ${
|
|
273
|
+
if (paramsType && bodyType) {
|
|
274
|
+
inputType = `{ params: ${paramsType}; body: ${bodyType}; }`;
|
|
278
275
|
fnBody = `({ params, body }: ${inputType}) => apiClient.${name}(params, body)`;
|
|
279
|
-
} else if (
|
|
280
|
-
inputType =
|
|
276
|
+
} else if (paramsType) {
|
|
277
|
+
inputType = paramsType;
|
|
281
278
|
fnBody = `(params: ${inputType}) => apiClient.${name}(params)`;
|
|
282
|
-
} else if (
|
|
283
|
-
inputType =
|
|
279
|
+
} else if (bodyType) {
|
|
280
|
+
inputType = bodyType;
|
|
284
281
|
fnBody = `(body: ${inputType}) => apiClient.${name}(body)`;
|
|
285
282
|
} else {
|
|
286
283
|
inputType = "void";
|
|
@@ -291,24 +288,24 @@ export function ${hookName}(${params.join(",\n ")}) {
|
|
|
291
288
|
* ${endpoint.description || `Mutation hook for ${name}`}
|
|
292
289
|
* @tags ${endpoint.tags?.join(", ") || "none"}
|
|
293
290
|
*/
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
291
|
+
export function ${hookName}(options?: {
|
|
292
|
+
onSuccess?: (data: ${responseType}, variables: ${inputType}, context: unknown) => void;
|
|
293
|
+
onError?: (error: Error, variables: ${inputType}, context: unknown) => void;
|
|
294
|
+
onSettled?: (data: ${responseType} | undefined, error: Error | null, variables: ${inputType}, context: unknown) => void;
|
|
295
|
+
onMutate?: (variables: ${inputType}) => Promise<unknown> | unknown;
|
|
296
|
+
}) {
|
|
297
|
+
${invalidate ? "const queryClient = useQueryClient();" : ""}
|
|
298
|
+
return useMutation({
|
|
299
|
+
mutationFn: ${fnBody},
|
|
300
|
+
onSuccess: (data, variables, context) => {
|
|
301
|
+
${invalidate}
|
|
302
|
+
options?.onSuccess?.(data, variables, context);
|
|
303
|
+
},
|
|
304
|
+
onError: options?.onError,
|
|
305
|
+
onSettled: options?.onSettled,
|
|
306
|
+
onMutate: options?.onMutate,
|
|
307
|
+
});
|
|
308
|
+
}`;
|
|
312
309
|
}
|
|
313
310
|
};
|
|
314
311
|
|
|
@@ -323,15 +320,11 @@ var ServerActionsGenerator = class extends BaseGenerator {
|
|
|
323
320
|
await fs2.writeFile(outputPath, content, "utf-8");
|
|
324
321
|
}
|
|
325
322
|
generateContent() {
|
|
326
|
-
const outputPath = path3.join(this.context.config.outputDir, "types.ts");
|
|
327
|
-
const endpointsPath = path3.join(this.context.config.endpointsPath);
|
|
328
|
-
const relativePath = path3.relative(path3.dirname(outputPath), endpointsPath).replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
329
323
|
const imports = `'use server';
|
|
330
324
|
|
|
331
325
|
import { revalidateTag, revalidatePath } from 'next/cache';
|
|
332
326
|
import { serverClient } from './server-client';
|
|
333
|
-
import
|
|
334
|
-
import { apiConfig } from '${relativePath}';
|
|
327
|
+
import type * as Types from './types';
|
|
335
328
|
|
|
336
329
|
export type ActionResult<T> =
|
|
337
330
|
| { success: true; data: T }
|
|
@@ -350,18 +343,20 @@ export type ActionResult<T> =
|
|
|
350
343
|
generateServerAction(name, endpoint) {
|
|
351
344
|
const actionSuffix = this.context.config.options?.actionSuffix || "Action";
|
|
352
345
|
const actionName = `${name}${actionSuffix}`;
|
|
353
|
-
const signature = this.getEndpointSignature(name, endpoint);
|
|
354
346
|
const invalidationTags = this.getInvalidationTags(endpoint);
|
|
347
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
348
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
349
|
+
const bodyType = endpoint.body ? `Types.${this.getInputTypeName(name)}` : null;
|
|
355
350
|
let inputType = "";
|
|
356
351
|
let callArgs = "";
|
|
357
|
-
if (
|
|
358
|
-
inputType = `input: { params: ${
|
|
352
|
+
if (paramsType && bodyType) {
|
|
353
|
+
inputType = `input: { params: ${paramsType}; body: ${bodyType} }`;
|
|
359
354
|
callArgs = "input.params, input.body";
|
|
360
|
-
} else if (
|
|
361
|
-
inputType = `params: ${
|
|
355
|
+
} else if (paramsType) {
|
|
356
|
+
inputType = `params: ${paramsType}`;
|
|
362
357
|
callArgs = "params";
|
|
363
|
-
} else if (
|
|
364
|
-
inputType = `body: ${
|
|
358
|
+
} else if (bodyType) {
|
|
359
|
+
inputType = `body: ${bodyType}`;
|
|
365
360
|
callArgs = "body";
|
|
366
361
|
}
|
|
367
362
|
const revalidateStatements = invalidationTags.length > 0 ? invalidationTags.map((tag) => ` revalidateTag('${tag}');`).join("\n") : " // No automatic revalidations";
|
|
@@ -371,7 +366,7 @@ export type ActionResult<T> =
|
|
|
371
366
|
*/
|
|
372
367
|
export async function ${actionName}(
|
|
373
368
|
${inputType}
|
|
374
|
-
): Promise<ActionResult<${
|
|
369
|
+
): Promise<ActionResult<${responseType}>> {
|
|
375
370
|
try {
|
|
376
371
|
const result = await (serverClient as any).${name}(${callArgs});
|
|
377
372
|
|
|
@@ -401,14 +396,10 @@ var ServerQueriesGenerator = class extends BaseGenerator {
|
|
|
401
396
|
await fs3.writeFile(outputPath, content, "utf-8");
|
|
402
397
|
}
|
|
403
398
|
generateContent() {
|
|
404
|
-
const outputPath = path4.join(this.context.config.outputDir, "types.ts");
|
|
405
|
-
const endpointsPath = path4.join(this.context.config.endpointsPath);
|
|
406
|
-
const relativePath = path4.relative(path4.dirname(outputPath), endpointsPath).replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
407
399
|
const imports = `import { cache } from 'react';
|
|
408
400
|
import { unstable_cache } from 'next/cache';
|
|
409
401
|
import { serverClient } from './server-client';
|
|
410
|
-
import
|
|
411
|
-
import { apiConfig } from '${relativePath}';
|
|
402
|
+
import type * as Types from './types';
|
|
412
403
|
`;
|
|
413
404
|
const queries = [];
|
|
414
405
|
Object.entries(this.context.apiConfig.endpoints).forEach(
|
|
@@ -422,24 +413,26 @@ import { apiConfig } from '${relativePath}';
|
|
|
422
413
|
}
|
|
423
414
|
generateServerQuery(name, endpoint) {
|
|
424
415
|
const queryName = `${name}Query`;
|
|
425
|
-
const signature = this.getEndpointSignature(name, endpoint);
|
|
426
416
|
const queryTags = this.getQueryTags(endpoint);
|
|
427
|
-
const
|
|
428
|
-
const
|
|
417
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
418
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
419
|
+
const queryType = endpoint.query ? `Types.${this.getQueryTypeName(name)}` : null;
|
|
420
|
+
const paramDef = paramsType ? `params: ${paramsType}` : "";
|
|
421
|
+
const queryDef = queryType ? `query?: ${queryType}` : "";
|
|
429
422
|
const paramsList = [paramDef, queryDef].filter(Boolean).join(",\n ");
|
|
430
423
|
let clientCall = "";
|
|
431
|
-
if (
|
|
424
|
+
if (paramsType && queryType) {
|
|
432
425
|
clientCall = `(serverClient as any).${name}(params, query)`;
|
|
433
|
-
} else if (
|
|
426
|
+
} else if (paramsType) {
|
|
434
427
|
clientCall = `(serverClient as any).${name}(params)`;
|
|
435
|
-
} else if (
|
|
428
|
+
} else if (queryType) {
|
|
436
429
|
clientCall = `(serverClient as any).${name}(query)`;
|
|
437
430
|
} else {
|
|
438
431
|
clientCall = `(serverClient as any).${name}()`;
|
|
439
432
|
}
|
|
440
433
|
const cacheKeyParts = [`'${name}'`];
|
|
441
|
-
if (
|
|
442
|
-
if (
|
|
434
|
+
if (paramsType) cacheKeyParts.push("JSON.stringify(params)");
|
|
435
|
+
if (queryType)
|
|
443
436
|
cacheKeyParts.push("query ? JSON.stringify(query) : 'no-query'");
|
|
444
437
|
return `/**
|
|
445
438
|
* ${endpoint.description || `Server query for ${name}`}
|
|
@@ -447,7 +440,7 @@ import { apiConfig } from '${relativePath}';
|
|
|
447
440
|
*/
|
|
448
441
|
export const ${queryName} = cache(async (
|
|
449
442
|
${paramsList}
|
|
450
|
-
): Promise<${
|
|
443
|
+
): Promise<${responseType}> => {
|
|
451
444
|
return unstable_cache(
|
|
452
445
|
async () => ${clientCall},
|
|
453
446
|
[${cacheKeyParts.join(", ")}],
|
|
@@ -492,22 +485,24 @@ ${this.generateEndpointTypes()}
|
|
|
492
485
|
Object.entries(this.context.apiConfig.endpoints).forEach(
|
|
493
486
|
([name, endpoint]) => {
|
|
494
487
|
const cap = this.capitalize(name);
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (endpoint.body)
|
|
488
|
+
types.push(
|
|
489
|
+
`export type ${cap}Response = z.infer<NonNullable<typeof apiConfig.endpoints.${name}.response>>;`
|
|
490
|
+
);
|
|
491
|
+
if (endpoint.body) {
|
|
500
492
|
types.push(
|
|
501
|
-
`export type ${cap}Input =
|
|
493
|
+
`export type ${cap}Input = z.infer<NonNullable<typeof apiConfig.endpoints.${name}.body>>;`
|
|
502
494
|
);
|
|
503
|
-
|
|
495
|
+
}
|
|
496
|
+
if (endpoint.query) {
|
|
504
497
|
types.push(
|
|
505
|
-
`export type ${cap}Query =
|
|
498
|
+
`export type ${cap}Query = z.infer<NonNullable<typeof apiConfig.endpoints.${name}.query>>;`
|
|
506
499
|
);
|
|
507
|
-
|
|
500
|
+
}
|
|
501
|
+
if (endpoint.params) {
|
|
508
502
|
types.push(
|
|
509
|
-
`export type ${cap}Params =
|
|
503
|
+
`export type ${cap}Params = z.infer<NonNullable<typeof apiConfig.endpoints.${name}.params>>;`
|
|
510
504
|
);
|
|
505
|
+
}
|
|
511
506
|
}
|
|
512
507
|
);
|
|
513
508
|
return types.join("\n");
|
|
@@ -548,32 +543,13 @@ var ClientGenerator = class extends BaseGenerator {
|
|
|
548
543
|
import { createAPIClient } from '@cushin/api-runtime';
|
|
549
544
|
import type { AuthCallbacks } from '@cushin/api-runtime';
|
|
550
545
|
import { apiConfig } from '${relativePath}';
|
|
551
|
-
import
|
|
546
|
+
import type * as Types from './types';
|
|
552
547
|
|
|
553
|
-
// Type the methods based on
|
|
548
|
+
// Type the methods based on generated types
|
|
554
549
|
type APIClientMethods = {
|
|
555
|
-
|
|
556
|
-
? E extends { method: "GET"; params: infer P; query: infer Q; response: infer R }
|
|
557
|
-
? (params: P extends z.ZodType ? z.infer<P> : never, query?: Q extends z.ZodType ? z.infer<Q> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
558
|
-
: E extends { method: "GET"; params: infer P; response: infer R }
|
|
559
|
-
? (params: P extends z.ZodType ? z.infer<P> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
560
|
-
: E extends { method: "GET"; query: infer Q; response: infer R }
|
|
561
|
-
? (query?: Q extends z.ZodType ? z.infer<Q> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
562
|
-
: E extends { method: "GET"; response: infer R }
|
|
563
|
-
? () => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
564
|
-
: E extends { method: string; params: infer P; body: infer B; response: infer R }
|
|
565
|
-
? (params: P extends z.ZodType ? z.infer<P> : never, body: B extends z.ZodType ? z.infer<B> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
566
|
-
: E extends { method: string; params: infer P; response: infer R }
|
|
567
|
-
? (params: P extends z.ZodType ? z.infer<P> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
568
|
-
: E extends { method: string; body: infer B; response: infer R }
|
|
569
|
-
? (body: B extends z.ZodType ? z.infer<B> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
570
|
-
: E extends { method: string; response: infer R }
|
|
571
|
-
? () => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
572
|
-
: never
|
|
573
|
-
: never;
|
|
550
|
+
${this.generateAPIClientMethodTypes()}
|
|
574
551
|
};
|
|
575
552
|
|
|
576
|
-
|
|
577
553
|
// Export singleton instance (will be initialized later)
|
|
578
554
|
export let baseClient: APIClientMethods & {
|
|
579
555
|
refreshAuth: () => Promise<void>;
|
|
@@ -587,7 +563,7 @@ ${this.generateApiClientMethods()}
|
|
|
587
563
|
/**
|
|
588
564
|
* Initialize API client with auth callbacks
|
|
589
565
|
* Call this function in your auth provider setup
|
|
590
|
-
*
|
|
566
|
+
*
|
|
591
567
|
* @example
|
|
592
568
|
* const authCallbacks = {
|
|
593
569
|
* getTokens: () => getStoredTokens(),
|
|
@@ -596,7 +572,7 @@ ${this.generateApiClientMethods()}
|
|
|
596
572
|
* await refreshAccessToken();
|
|
597
573
|
* },
|
|
598
574
|
* };
|
|
599
|
-
*
|
|
575
|
+
*
|
|
600
576
|
* initializeAPIClient(authCallbacks);
|
|
601
577
|
*/
|
|
602
578
|
export const initializeAPIClient = (authCallbacks: AuthCallbacks) => {
|
|
@@ -615,29 +591,11 @@ export type { AuthCallbacks };
|
|
|
615
591
|
const relativePath = path6.relative(path6.dirname(outputPath), endpointsPath).replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
616
592
|
return `import { createAPIClient } from '@cushin/api-runtime';
|
|
617
593
|
import { apiConfig } from '${relativePath}';
|
|
618
|
-
import
|
|
594
|
+
import type * as Types from './types';
|
|
619
595
|
|
|
620
|
-
// Type the methods based on
|
|
596
|
+
// Type the methods based on generated types
|
|
621
597
|
type APIClientMethods = {
|
|
622
|
-
|
|
623
|
-
? E extends { method: "GET"; params: infer P; query: infer Q; response: infer R }
|
|
624
|
-
? (params: P extends z.ZodType ? z.infer<P> : never, query?: Q extends z.ZodType ? z.infer<Q> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
625
|
-
: E extends { method: "GET"; params: infer P; response: infer R }
|
|
626
|
-
? (params: P extends z.ZodType ? z.infer<P> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
627
|
-
: E extends { method: "GET"; query: infer Q; response: infer R }
|
|
628
|
-
? (query?: Q extends z.ZodType ? z.infer<Q> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
629
|
-
: E extends { method: "GET"; response: infer R }
|
|
630
|
-
? () => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
631
|
-
: E extends { method: string; params: infer P; body: infer B; response: infer R }
|
|
632
|
-
? (params: P extends z.ZodType ? z.infer<P> : never, body: B extends z.ZodType ? z.infer<B> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
633
|
-
: E extends { method: string; params: infer P; response: infer R }
|
|
634
|
-
? (params: P extends z.ZodType ? z.infer<P> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
635
|
-
: E extends { method: string; body: infer B; response: infer R }
|
|
636
|
-
? (body: B extends z.ZodType ? z.infer<B> : never) => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
637
|
-
: E extends { method: string; response: infer R }
|
|
638
|
-
? () => Promise<R extends z.ZodType ? z.infer<R> : never>
|
|
639
|
-
: never
|
|
640
|
-
: never;
|
|
598
|
+
${this.generateAPIClientMethodTypes()}
|
|
641
599
|
};
|
|
642
600
|
|
|
643
601
|
/**
|
|
@@ -647,48 +605,75 @@ type APIClientMethods = {
|
|
|
647
605
|
export const serverClient = createAPIClient(apiConfig) as APIClientMethods;
|
|
648
606
|
`;
|
|
649
607
|
}
|
|
608
|
+
generateAPIClientMethodTypes() {
|
|
609
|
+
const methods = [];
|
|
610
|
+
Object.entries(this.context.apiConfig.endpoints).forEach(
|
|
611
|
+
([name, endpoint]) => {
|
|
612
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
613
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
614
|
+
const queryType = endpoint.query ? `Types.${this.getQueryTypeName(name)}` : null;
|
|
615
|
+
const bodyType = endpoint.body ? `Types.${this.getInputTypeName(name)}` : null;
|
|
616
|
+
let signature = "";
|
|
617
|
+
if (endpoint.method === "GET") {
|
|
618
|
+
if (paramsType && queryType) {
|
|
619
|
+
signature = `(params: ${paramsType}, query?: ${queryType}) => Promise<${responseType}>`;
|
|
620
|
+
} else if (paramsType) {
|
|
621
|
+
signature = `(params: ${paramsType}) => Promise<${responseType}>`;
|
|
622
|
+
} else if (queryType) {
|
|
623
|
+
signature = `(query?: ${queryType}) => Promise<${responseType}>`;
|
|
624
|
+
} else {
|
|
625
|
+
signature = `() => Promise<${responseType}>`;
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
if (paramsType && bodyType) {
|
|
629
|
+
signature = `(params: ${paramsType}, body: ${bodyType}) => Promise<${responseType}>`;
|
|
630
|
+
} else if (paramsType) {
|
|
631
|
+
signature = `(params: ${paramsType}) => Promise<${responseType}>`;
|
|
632
|
+
} else if (bodyType) {
|
|
633
|
+
signature = `(body: ${bodyType}) => Promise<${responseType}>`;
|
|
634
|
+
} else {
|
|
635
|
+
signature = `() => Promise<${responseType}>`;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
methods.push(` ${name}: ${signature};`);
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
return methods.join("\n");
|
|
642
|
+
}
|
|
650
643
|
generateApiClientMethods() {
|
|
651
644
|
const methods = [];
|
|
652
645
|
Object.entries(this.context.apiConfig.endpoints).forEach(
|
|
653
646
|
([name, endpoint]) => {
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
);
|
|
657
|
-
const
|
|
658
|
-
`typeof apiConfig.endpoints.${name}.query`
|
|
659
|
-
);
|
|
660
|
-
const inferBody = this.inferNonNull(
|
|
661
|
-
`typeof apiConfig.endpoints.${name}.body`
|
|
662
|
-
);
|
|
663
|
-
const inferResponse = this.inferNonNull(
|
|
664
|
-
`typeof apiConfig.endpoints.${name}.response`
|
|
665
|
-
);
|
|
647
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
648
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
649
|
+
const queryType = endpoint.query ? `Types.${this.getQueryTypeName(name)}` : null;
|
|
650
|
+
const bodyType = endpoint.body ? `Types.${this.getInputTypeName(name)}` : null;
|
|
666
651
|
if (endpoint.method === "GET") {
|
|
667
|
-
if (
|
|
668
|
-
methods.push(` ${name}: (params: ${
|
|
652
|
+
if (paramsType && queryType) {
|
|
653
|
+
methods.push(` ${name}: (params: ${paramsType}, query?: ${queryType}): Promise<${responseType}> =>
|
|
669
654
|
(baseClient as any).${name}(params, query),`);
|
|
670
|
-
} else if (
|
|
671
|
-
methods.push(` ${name}: (params: ${
|
|
655
|
+
} else if (paramsType) {
|
|
656
|
+
methods.push(` ${name}: (params: ${paramsType}): Promise<${responseType}> =>
|
|
672
657
|
(baseClient as any).${name}(params),`);
|
|
673
|
-
} else if (
|
|
674
|
-
methods.push(` ${name}: (query?: ${
|
|
658
|
+
} else if (queryType) {
|
|
659
|
+
methods.push(` ${name}: (query?: ${queryType}): Promise<${responseType}> =>
|
|
675
660
|
(baseClient as any).${name}(query),`);
|
|
676
661
|
} else {
|
|
677
|
-
methods.push(` ${name}: (): Promise<${
|
|
662
|
+
methods.push(` ${name}: (): Promise<${responseType}> =>
|
|
678
663
|
(baseClient as any).${name}(),`);
|
|
679
664
|
}
|
|
680
665
|
} else {
|
|
681
|
-
if (
|
|
682
|
-
methods.push(` ${name}: (params: ${
|
|
666
|
+
if (paramsType && bodyType) {
|
|
667
|
+
methods.push(` ${name}: (params: ${paramsType}, body: ${bodyType}): Promise<${responseType}> =>
|
|
683
668
|
(baseClient as any).${name}(params, body),`);
|
|
684
|
-
} else if (
|
|
685
|
-
methods.push(` ${name}: (params: ${
|
|
669
|
+
} else if (paramsType) {
|
|
670
|
+
methods.push(` ${name}: (params: ${paramsType}): Promise<${responseType}> =>
|
|
686
671
|
(baseClient as any).${name}(params),`);
|
|
687
|
-
} else if (
|
|
688
|
-
methods.push(` ${name}: (body: ${
|
|
672
|
+
} else if (bodyType) {
|
|
673
|
+
methods.push(` ${name}: (body: ${bodyType}): Promise<${responseType}> =>
|
|
689
674
|
(baseClient as any).${name}(body),`);
|
|
690
675
|
} else {
|
|
691
|
-
methods.push(` ${name}: (): Promise<${
|
|
676
|
+
methods.push(` ${name}: (): Promise<${responseType}> =>
|
|
692
677
|
(baseClient as any).${name}(),`);
|
|
693
678
|
}
|
|
694
679
|
}
|
|
@@ -716,8 +701,7 @@ var QueryKeysGenerator = class extends BaseGenerator {
|
|
|
716
701
|
const endpointsPath = path7.join(this.context.config.endpointsPath);
|
|
717
702
|
const relativePath = path7.relative(path7.dirname(outputPath), endpointsPath).replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
718
703
|
const content = `// Auto-generated query keys
|
|
719
|
-
import
|
|
720
|
-
import { apiConfig } from '${relativePath}';
|
|
704
|
+
import type * as Types from './types';
|
|
721
705
|
|
|
722
706
|
export const queryKeys = {
|
|
723
707
|
${this.generateQueryKeysContent()}
|
|
@@ -738,16 +722,12 @@ ${this.generateQueryKeysContent()}
|
|
|
738
722
|
queryEndpoints.forEach(({ name, endpoint }) => {
|
|
739
723
|
const keyName = this.getEndpointKeyName(name);
|
|
740
724
|
if (added.has(keyName)) return;
|
|
741
|
-
const inferParams = this.inferNonNull(
|
|
742
|
-
`typeof apiConfig.endpoints.${name}.params`
|
|
743
|
-
);
|
|
744
|
-
const inferQuery = this.inferNonNull(
|
|
745
|
-
`typeof apiConfig.endpoints.${name}.query`
|
|
746
|
-
);
|
|
747
725
|
if (endpoint.params || endpoint.query) {
|
|
748
726
|
const params = [];
|
|
749
|
-
if (endpoint.params)
|
|
750
|
-
|
|
727
|
+
if (endpoint.params)
|
|
728
|
+
params.push(`params?: Types.${this.getParamsTypeName(name)}`);
|
|
729
|
+
if (endpoint.query)
|
|
730
|
+
params.push(`query?: Types.${this.getQueryTypeName(name)}`);
|
|
751
731
|
resourceKeys.push(` ${keyName}: (${params.join(", ")}) =>
|
|
752
732
|
['${resource}', '${keyName}', ${endpoint.params ? "params" : "undefined"}, ${endpoint.query ? "query" : "undefined"}] as const,`);
|
|
753
733
|
} else {
|
|
@@ -779,15 +759,11 @@ var QueryOptionsGenerator = class extends BaseGenerator {
|
|
|
779
759
|
await fs7.writeFile(outputPath, content, "utf-8");
|
|
780
760
|
}
|
|
781
761
|
generateContent() {
|
|
782
|
-
const outputPath = path8.join(this.context.config.outputDir, "types.ts");
|
|
783
|
-
const endpointsPath = path8.join(this.context.config.endpointsPath);
|
|
784
|
-
const relativePath = path8.relative(path8.dirname(outputPath), endpointsPath).replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
785
762
|
const content = `// Auto-generated query options
|
|
786
763
|
import { queryOptions } from '@tanstack/react-query';
|
|
787
764
|
import { apiClient } from './client';
|
|
788
765
|
import { queryKeys } from './query-keys';
|
|
789
|
-
import
|
|
790
|
-
import { apiConfig } from '${relativePath}';
|
|
766
|
+
import type * as Types from './types';
|
|
791
767
|
|
|
792
768
|
${this.generateQueryOptionsContent()}
|
|
793
769
|
|
|
@@ -808,25 +784,19 @@ ${this.generateQueryOptionsExports()}
|
|
|
808
784
|
const resourceOptions = [];
|
|
809
785
|
queries.forEach(({ name, endpoint }) => {
|
|
810
786
|
const optionName = this.getEndpointKeyName(name);
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
);
|
|
814
|
-
const inferQuery = this.inferNonNull(
|
|
815
|
-
`typeof apiConfig.endpoints.${name}.query`
|
|
816
|
-
);
|
|
817
|
-
const inferResponse = this.inferNonNull(
|
|
818
|
-
`typeof apiConfig.endpoints.${name}.response`
|
|
819
|
-
);
|
|
787
|
+
const responseType = `Types.${this.getResponseTypeName(name)}`;
|
|
788
|
+
const paramsType = endpoint.params ? `Types.${this.getParamsTypeName(name)}` : null;
|
|
789
|
+
const queryType = endpoint.query ? `Types.${this.getQueryTypeName(name)}` : null;
|
|
820
790
|
const params = [];
|
|
821
791
|
let apiCall = "";
|
|
822
|
-
if (
|
|
823
|
-
params.push(`params: ${
|
|
792
|
+
if (paramsType && queryType) {
|
|
793
|
+
params.push(`params: ${paramsType}`, `filters?: ${queryType}`);
|
|
824
794
|
apiCall = `apiClient.${name}(params, filters)`;
|
|
825
|
-
} else if (
|
|
826
|
-
params.push(`params: ${
|
|
795
|
+
} else if (paramsType) {
|
|
796
|
+
params.push(`params: ${paramsType}`);
|
|
827
797
|
apiCall = `apiClient.${name}(params)`;
|
|
828
|
-
} else if (
|
|
829
|
-
params.push(`filters?: ${
|
|
798
|
+
} else if (queryType) {
|
|
799
|
+
params.push(`filters?: ${queryType}`);
|
|
830
800
|
apiCall = `apiClient.${name}(filters)`;
|
|
831
801
|
} else {
|
|
832
802
|
apiCall = `apiClient.${name}()`;
|
|
@@ -835,7 +805,7 @@ ${this.generateQueryOptionsExports()}
|
|
|
835
805
|
resourceOptions.push(` ${optionName}: (${params.join(", ")}) =>
|
|
836
806
|
queryOptions({
|
|
837
807
|
queryKey: ${keyCall},
|
|
838
|
-
queryFn: (): Promise<${
|
|
808
|
+
queryFn: (): Promise<${responseType}> => ${apiCall},
|
|
839
809
|
staleTime: 1000 * 60 * 5,
|
|
840
810
|
}),`);
|
|
841
811
|
});
|
|
@@ -875,8 +845,7 @@ var PrefetchGenerator = class extends BaseGenerator {
|
|
|
875
845
|
const content = `// Auto-generated prefetch utilities
|
|
876
846
|
import { type QueryClient } from '@tanstack/react-query';
|
|
877
847
|
${this.hasQueryOptions() ? "import { apiQueryOptions } from './query-options';" : ""}
|
|
878
|
-
import
|
|
879
|
-
import { apiConfig } from '../config/endpoints';
|
|
848
|
+
import type * as Types from './types';
|
|
880
849
|
|
|
881
850
|
${this.generatePrefetchFunctions()}
|
|
882
851
|
`;
|
|
@@ -896,20 +865,14 @@ ${this.generatePrefetchFunctions()}
|
|
|
896
865
|
const prefetchName = `prefetch${this.capitalize(name)}`;
|
|
897
866
|
const resource = this.getResourceFromEndpoint(name, endpoint);
|
|
898
867
|
const optionName = this.getEndpointKeyName(name);
|
|
899
|
-
const inferParams = this.inferNonNull(
|
|
900
|
-
`typeof apiConfig.endpoints.${name}.params`
|
|
901
|
-
);
|
|
902
|
-
const inferQuery = this.inferNonNull(
|
|
903
|
-
`typeof apiConfig.endpoints.${name}.query`
|
|
904
|
-
);
|
|
905
868
|
const params = ["queryClient: QueryClient"];
|
|
906
869
|
const optionParams = [];
|
|
907
870
|
if (endpoint.params) {
|
|
908
|
-
params.push(`params:
|
|
871
|
+
params.push(`params: Types.${this.getParamsTypeName(name)}`);
|
|
909
872
|
optionParams.push("params");
|
|
910
873
|
}
|
|
911
874
|
if (endpoint.query) {
|
|
912
|
-
params.push(`filters?:
|
|
875
|
+
params.push(`filters?: Types.${this.getQueryTypeName(name)}`);
|
|
913
876
|
optionParams.push("filters");
|
|
914
877
|
}
|
|
915
878
|
return `export const ${prefetchName} = async (${params.join(",\n ")}) => {
|