@cushin/api-codegen 5.0.0 → 5.0.2

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 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 { z } from "zod";
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 inferParams = this.inferNonNull(
220
- `typeof apiConfig.endpoints.${name}.params`
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 (endpoint.params) {
232
- params.push(`params: ${inferParams}`);
234
+ if (paramsType) {
235
+ params.push(`params: ${paramsType}`);
233
236
  optionParams.push("params");
234
237
  }
235
- if (endpoint.query) {
236
- params.push(`filters?: ${inferQuery}`);
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 = ${inferResponse}>(data: ${inferResponse}) => 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 inferParams = this.inferNonNull(
268
- `typeof apiConfig.endpoints.${name}.params`
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 (endpoint.params && endpoint.body) {
280
- inputType = `{ params: ${inferParams}; body: ${inferBody}; }`;
276
+ if (paramsType && bodyType) {
277
+ inputType = `{ params: ${paramsType}; body: ${bodyType}; }`;
281
278
  fnBody = `({ params, body }: ${inputType}) => apiClient.${name}(params, body)`;
282
- } else if (endpoint.params) {
283
- inputType = `${inferParams}`;
279
+ } else if (paramsType) {
280
+ inputType = paramsType;
284
281
  fnBody = `(params: ${inputType}) => apiClient.${name}(params)`;
285
- } else if (endpoint.body) {
286
- inputType = `${inferBody}`;
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
- export function ${hookName}(options?: {
298
- onSuccess?: (data: ${inferResponse}, variables: ${inputType}, context: unknown) => void;
299
- onError?: (error: Error, variables: ${inputType}, context: unknown) => void;
300
- onSettled?: (data: ${inferResponse} | undefined, error: Error | null, variables: ${inputType}, context: unknown) => void;
301
- onMutate?: (variables: ${inputType}) => Promise<unknown> | unknown;
302
- }) {
303
- ${invalidate ? "const queryClient = useQueryClient();" : ""}
304
- return useMutation({
305
- mutationFn: ${fnBody},
306
- onSuccess: (data, variables, context) => {
307
- ${invalidate}
308
- options?.onSuccess?.(data, variables, context);
309
- },
310
- onError: options?.onError,
311
- onSettled: options?.onSettled,
312
- onMutate: options?.onMutate,
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 { z } from 'zod';
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 (signature.hasParams && signature.hasBody) {
361
- inputType = `input: { params: ${signature.paramType}; body: ${signature.bodyType} }`;
355
+ if (paramsType && bodyType) {
356
+ inputType = `input: { params: ${paramsType}; body: ${bodyType} }`;
362
357
  callArgs = "input.params, input.body";
363
- } else if (signature.hasParams) {
364
- inputType = `params: ${signature.paramType}`;
358
+ } else if (paramsType) {
359
+ inputType = `params: ${paramsType}`;
365
360
  callArgs = "params";
366
- } else if (signature.hasBody) {
367
- inputType = `body: ${signature.bodyType}`;
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<${signature.responseType}>> {
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 { z } from 'zod';
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 paramDef = signature.hasParams ? `params: ${signature.paramType}` : "";
431
- const queryDef = signature.hasQuery ? `query?: ${signature.queryType}` : "";
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 (signature.hasParams && signature.hasQuery) {
427
+ if (paramsType && queryType) {
435
428
  clientCall = `(serverClient as any).${name}(params, query)`;
436
- } else if (signature.hasParams) {
429
+ } else if (paramsType) {
437
430
  clientCall = `(serverClient as any).${name}(params)`;
438
- } else if (signature.hasQuery) {
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 (signature.hasParams) cacheKeyParts.push("JSON.stringify(params)");
445
- if (signature.hasQuery)
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<${signature.responseType}> => {
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
- if (endpoint.response)
499
- types.push(
500
- `export type ${cap}Response = ${this.inferNonNull(`typeof apiConfig.endpoints.${name}.response`)};`
501
- );
502
- if (endpoint.body)
491
+ types.push(
492
+ `export type ${cap}Response = z.infer<typeof apiConfig.endpoints.${name}.response>;`
493
+ );
494
+ if (endpoint.body) {
503
495
  types.push(
504
- `export type ${cap}Input = ${this.inferNonNull(`typeof apiConfig.endpoints.${name}.body`)};`
496
+ `export type ${cap}Input = z.infer<typeof apiConfig.endpoints.${name}.body>;`
505
497
  );
506
- if (endpoint.query)
498
+ }
499
+ if (endpoint.query) {
507
500
  types.push(
508
- `export type ${cap}Query = ${this.inferNonNull(`typeof apiConfig.endpoints.${name}.query`)};`
501
+ `export type ${cap}Query = z.infer<typeof apiConfig.endpoints.${name}.query>;`
509
502
  );
510
- if (endpoint.params)
503
+ }
504
+ if (endpoint.params) {
511
505
  types.push(
512
- `export type ${cap}Params = ${this.inferNonNull(`typeof apiConfig.endpoints.${name}.params`)};`
506
+ `export type ${cap}Params = z.infer<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 { z } from 'zod';
549
+ import type * as Types from './types';
555
550
 
556
- // Type the methods based on endpoints
551
+ // Type the methods based on generated types
557
552
  type APIClientMethods = {
558
- [K in keyof typeof apiConfig.endpoints]: (typeof apiConfig.endpoints)[K] extends infer E
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 { z } from 'zod';
597
+ import type * as Types from './types';
622
598
 
623
- // Type the methods based on endpoints
599
+ // Type the methods based on generated types
624
600
  type APIClientMethods = {
625
- [K in keyof typeof apiConfig.endpoints]: (typeof apiConfig.endpoints)[K] extends infer E
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 inferParams = this.inferNonNull(
658
- `typeof apiConfig.endpoints.${name}.params`
659
- );
660
- const inferQuery = this.inferNonNull(
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 (endpoint.params && endpoint.query) {
671
- methods.push(` ${name}: (params: ${inferParams}, query?: ${inferQuery}): Promise<${inferResponse}> =>
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 (endpoint.params) {
674
- methods.push(` ${name}: (params: ${inferParams}): Promise<${inferResponse}> =>
658
+ } else if (paramsType) {
659
+ methods.push(` ${name}: (params: ${paramsType}): Promise<${responseType}> =>
675
660
  (baseClient as any).${name}(params),`);
676
- } else if (endpoint.query) {
677
- methods.push(` ${name}: (query?: ${inferQuery}): Promise<${inferResponse}> =>
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<${inferResponse}> =>
665
+ methods.push(` ${name}: (): Promise<${responseType}> =>
681
666
  (baseClient as any).${name}(),`);
682
667
  }
683
668
  } else {
684
- if (endpoint.params && endpoint.body) {
685
- methods.push(` ${name}: (params: ${inferParams}, body: ${inferBody}): Promise<${inferResponse}> =>
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 (endpoint.params) {
688
- methods.push(` ${name}: (params: ${inferParams}): Promise<${inferResponse}> =>
672
+ } else if (paramsType) {
673
+ methods.push(` ${name}: (params: ${paramsType}): Promise<${responseType}> =>
689
674
  (baseClient as any).${name}(params),`);
690
- } else if (endpoint.body) {
691
- methods.push(` ${name}: (body: ${inferBody}): Promise<${inferResponse}> =>
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<${inferResponse}> =>
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 { z } from 'zod';
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) params.push(`params?: ${inferParams}`);
753
- if (endpoint.query) params.push(`query?: ${inferQuery}`);
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 { z } from 'zod';
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 inferParams = this.inferNonNull(
815
- `typeof apiConfig.endpoints.${name}.params`
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 (endpoint.params && endpoint.query) {
826
- params.push(`params: ${inferParams}`, `filters?: ${inferQuery}`);
795
+ if (paramsType && queryType) {
796
+ params.push(`params: ${paramsType}`, `filters?: ${queryType}`);
827
797
  apiCall = `apiClient.${name}(params, filters)`;
828
- } else if (endpoint.params) {
829
- params.push(`params: ${inferParams}`);
798
+ } else if (paramsType) {
799
+ params.push(`params: ${paramsType}`);
830
800
  apiCall = `apiClient.${name}(params)`;
831
- } else if (endpoint.query) {
832
- params.push(`filters?: ${inferQuery}`);
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<${inferResponse}> => ${apiCall},
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 { z } from 'zod';
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: ${inferParams}`);
874
+ params.push(`params: Types.${this.getParamsTypeName(name)}`);
912
875
  optionParams.push("params");
913
876
  }
914
877
  if (endpoint.query) {
915
- params.push(`filters?: ${inferQuery}`);
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 ")}) => {
@@ -1012,6 +975,9 @@ var CodegenCore = class {
1012
975
  'Invalid API config: must export an object with "endpoints" property'
1013
976
  );
1014
977
  }
978
+ if (this.config.acceptEncoding) {
979
+ apiConfig.acceptEncoding = this.config.acceptEncoding;
980
+ }
1015
981
  return apiConfig;
1016
982
  } catch (error) {
1017
983
  throw new Error(