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