@7nohe/openapi-react-query-codegen 3.0.0-beta.3 → 3.0.0-beta.5

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.d.mts ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ export type LimitedUserConfig = {
3
+ input: string;
4
+ output: string;
5
+ client?: "@hey-api/client-fetch" | "@hey-api/client-axios";
6
+ format?: "biome" | "prettier";
7
+ lint?: "biome" | "eslint";
8
+ noOperationId?: boolean;
9
+ enums?: "javascript" | "typescript" | false;
10
+ useDateType?: boolean;
11
+ debug?: boolean;
12
+ noSchemas?: boolean;
13
+ schemaType?: "form" | "json";
14
+ pageParam: string;
15
+ nextPageParam: string;
16
+ initialPageParam: string | number;
17
+ omitInitialPageParam?: boolean;
18
+ };
package/dist/cli.mjs CHANGED
@@ -25,13 +25,14 @@ async function setupProgram() {
25
25
  .addOption(new Option("--lint <value>", "Process output folder with linter?").choices(["biome", "eslint"]))
26
26
  .option("--noOperationId", "Do not use operationId to generate operation names")
27
27
  .addOption(new Option("--enums <value>", "Generate JavaScript objects from enum definitions?").choices(["javascript", "typescript"]))
28
- .option("--useDateType", "Use Date type instead of string for date types for models, this will not convert the data to a Date object")
28
+ .option("--useDateType", "Use Date for date/date-time model properties and convert response values to Date objects")
29
29
  .option("--debug", "Run in debug mode?")
30
30
  .option("--noSchemas", "Disable generating JSON schemas")
31
31
  .addOption(new Option("--schemaType <value>", "Type of JSON schema [Default: 'json']").choices(["form", "json"]))
32
32
  .option("--pageParam <value>", "Name of the query parameter used for pagination", "page")
33
33
  .option("--nextPageParam <value>", "Name of the response parameter used for next page", "nextPage")
34
34
  .option("--initialPageParam <value>", "Initial page value to query", "1")
35
+ .option("--omitInitialPageParam", "Send no initial page parameter at all (overrides --initialPageParam)")
35
36
  .parse();
36
37
  const options = program.opts();
37
38
  await generate(options, version);
@@ -0,0 +1,51 @@
1
+ import type { PathLike } from "node:fs";
2
+ import { type ClassDeclaration, type ParameterDeclaration, type SourceFile, type VariableDeclaration } from "ts-morph";
3
+ import ts from "typescript";
4
+ import type { LimitedUserConfig } from "./cli.mjs";
5
+ export declare const capitalizeFirstLetter: (str: string) => string;
6
+ export declare const lowercaseFirstLetter: (str: string) => string;
7
+ export declare const getVariableArrowFunctionParameters: (variable: VariableDeclaration) => ParameterDeclaration[];
8
+ export declare const getNameFromVariable: (variable: VariableDeclaration) => string;
9
+ export type FunctionDescription = {
10
+ node: SourceFile;
11
+ method: VariableDeclaration;
12
+ methodBlock?: ts.Block;
13
+ httpMethodName: string;
14
+ jsDoc: string;
15
+ isDeprecated: boolean;
16
+ };
17
+ export declare function exists(f: PathLike): Promise<boolean>;
18
+ /**
19
+ * Build a common type name by prepending the Common namespace.
20
+ */
21
+ export declare function BuildCommonTypeName(name: string | ts.Identifier): ts.Identifier;
22
+ /**
23
+ * Safely parse a value into a number. Checks for NaN and Infinity.
24
+ * Returns NaN if the string is not a valid number.
25
+ * @param value The value to parse.
26
+ * @returns The parsed number or NaN if the value is not a valid number.
27
+ */
28
+ export declare function safeParseNumber(value: unknown): number;
29
+ export declare function extractPropertiesFromObjectParam(param: ParameterDeclaration): {
30
+ name: string;
31
+ optional: boolean;
32
+ type: import("ts-morph").Type<import("ts-morph").ts.Type> | undefined;
33
+ }[];
34
+ /**
35
+ * Replace the import("...") surrounding the type if there is one.
36
+ * This can happen when the type is imported from another file, but
37
+ * we are already importing all the types from that file.
38
+ *
39
+ * https://regex101.com/r/3DyHaQ/1
40
+ *
41
+ * TODO: Replace with a more robust solution.
42
+ */
43
+ export declare function getShortType(type: string): string;
44
+ export declare function getClassesFromService(node: SourceFile): {
45
+ className: string;
46
+ klass: ClassDeclaration;
47
+ }[];
48
+ export declare function getClassNameFromClassNode(klass: ClassDeclaration): string;
49
+ export declare function formatOptions(options: LimitedUserConfig): LimitedUserConfig;
50
+ export declare function buildRequestsOutputPath(outputPath: string): string;
51
+ export declare function buildQueriesOutputPath(outputPath: string): string;
package/dist/common.mjs CHANGED
@@ -52,6 +52,12 @@ export function BuildCommonTypeName(name) {
52
52
  * @returns The parsed number or NaN if the value is not a valid number.
53
53
  */
54
54
  export function safeParseNumber(value) {
55
+ // `Number("")` is 0, which would silently turn a blank option such as
56
+ // `--initialPageParam ""` into a numeric 0. Treat blank strings as NaN so
57
+ // callers keep the original value.
58
+ if (typeof value === "string" && value.trim() === "") {
59
+ return Number.NaN;
60
+ }
55
61
  const parsed = Number(value);
56
62
  if (!Number.isNaN(parsed) && Number.isFinite(parsed)) {
57
63
  return parsed;
@@ -0,0 +1,15 @@
1
+ export declare const defaultOutputPath = "openapi";
2
+ export declare const queriesOutputPath = "queries";
3
+ export declare const requestsOutputPath = "requests";
4
+ export declare const serviceFileName = "sdk.gen";
5
+ export declare const modelsFileName = "types.gen";
6
+ export declare const OpenApiRqFiles: {
7
+ readonly queries: "queries";
8
+ readonly queryOptions: "queryOptions";
9
+ readonly infiniteQueries: "infiniteQueries";
10
+ readonly common: "common";
11
+ readonly suspense: "suspense";
12
+ readonly index: "index";
13
+ readonly prefetch: "prefetch";
14
+ readonly ensureQueryData: "ensureQueryData";
15
+ };
@@ -0,0 +1,15 @@
1
+ import type { GeneratedFile } from "./types.mjs";
2
+ type ClientType = "@hey-api/client-fetch" | "@hey-api/client-axios";
3
+ /**
4
+ * Create source files using ts-morph based generation.
5
+ */
6
+ export declare const createSource: ({ outputPath, client, version, pageParam, nextPageParam, initialPageParam, omitInitialPageParam, }: {
7
+ outputPath: string;
8
+ client: ClientType;
9
+ version: string;
10
+ pageParam: string;
11
+ nextPageParam: string;
12
+ initialPageParam: string;
13
+ omitInitialPageParam: boolean;
14
+ }) => Promise<GeneratedFile[]>;
15
+ export {};
@@ -5,7 +5,7 @@ import { generateAllFiles } from "./tsmorph/index.mjs";
5
5
  /**
6
6
  * Create source files using ts-morph based generation.
7
7
  */
8
- export const createSource = async ({ outputPath, client, version, pageParam, nextPageParam, initialPageParam, }) => {
8
+ export const createSource = async ({ outputPath, client, version, pageParam, nextPageParam, initialPageParam, omitInitialPageParam, }) => {
9
9
  // Initialize ts-morph project to read the generated OpenAPI client
10
10
  const project = new Project({
11
11
  skipAddingFilesFromTsConfig: true,
@@ -15,7 +15,7 @@ export const createSource = async ({ outputPath, client, version, pageParam, nex
15
15
  // Parse operations from the service file
16
16
  const operations = await parseOperations(project, pageParam);
17
17
  // Build generation context
18
- const ctx = buildGenerationContext(project, client, pageParam, nextPageParam, initialPageParam, version);
18
+ const ctx = buildGenerationContext(project, client, pageParam, nextPageParam, initialPageParam, omitInitialPageParam, version);
19
19
  // Generate all files using ts-morph
20
20
  return generateAllFiles(operations, ctx);
21
21
  };
@@ -0,0 +1,6 @@
1
+ export declare const formatOutput: (outputPath: string) => Promise<void>;
2
+ export declare const processOutput: ({ output, format, lint, }: {
3
+ output: string;
4
+ format?: "prettier" | "biome";
5
+ lint?: "biome" | "eslint";
6
+ }) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { LimitedUserConfig } from "./cli.mjs";
2
+ export declare function generate(options: LimitedUserConfig, version: string): Promise<void>;
package/dist/generate.mjs CHANGED
@@ -18,20 +18,31 @@ export async function generate(options, version) {
18
18
  enums: formattedOptions.enums,
19
19
  }
20
20
  : "@hey-api/typescript";
21
- const sdkPlugin = formattedOptions.noOperationId
22
- ? {
23
- name: "@hey-api/sdk",
24
- // `operationId: false` was deprecated in favor of `operations.nesting`
25
- operations: {
26
- nesting: "id",
27
- },
28
- }
29
- : "@hey-api/sdk";
21
+ const sdkPlugin = {
22
+ name: "@hey-api/sdk",
23
+ ...(formattedOptions.noOperationId
24
+ ? {
25
+ // `operationId: false` was deprecated in favor of `operations.nesting`
26
+ operations: {
27
+ nesting: "id",
28
+ },
29
+ }
30
+ : {}),
31
+ ...(formattedOptions.useDateType
32
+ ? { transformer: "@hey-api/transformers" }
33
+ : {}),
34
+ };
30
35
  const plugins = [
31
36
  clientPlugin,
32
37
  typescriptPlugin,
33
38
  sdkPlugin,
34
39
  ];
40
+ if (formattedOptions.useDateType) {
41
+ plugins.push({
42
+ name: "@hey-api/transformers",
43
+ dates: "date",
44
+ });
45
+ }
35
46
  // Conditionally add schemas plugin
36
47
  if (!formattedOptions.noSchemas) {
37
48
  plugins.push(formattedOptions.schemaType
@@ -59,6 +70,7 @@ export async function generate(options, version) {
59
70
  pageParam: formattedOptions.pageParam,
60
71
  nextPageParam: formattedOptions.nextPageParam,
61
72
  initialPageParam: formattedOptions.initialPageParam.toString(),
73
+ omitInitialPageParam: formattedOptions.omitInitialPageParam ?? false,
62
74
  });
63
75
  await print(source, formattedOptions);
64
76
  const queriesOutputPath = buildQueriesOutputPath(options.output);
@@ -0,0 +1,10 @@
1
+ import type { Project } from "ts-morph";
2
+ import type { GenerationContext, OperationInfo } from "./types.mjs";
3
+ /**
4
+ * Parse operations from the OpenAPI-generated service file and return normalized DTOs.
5
+ */
6
+ export declare function parseOperations(project: Project, pageParam: string): Promise<OperationInfo[]>;
7
+ /**
8
+ * Build generation context from project configuration.
9
+ */
10
+ export declare function buildGenerationContext(project: Project, client: GenerationContext["client"], pageParam: string, nextPageParam: string, initialPageParam: string, omitInitialPageParam: boolean, version: string): GenerationContext;
@@ -2,6 +2,20 @@ import ts from "typescript";
2
2
  import { capitalizeFirstLetter, extractPropertiesFromObjectParam, getNameFromVariable, getShortType, getVariableArrowFunctionParameters, } from "./common.mjs";
3
3
  import { modelsFileName, serviceFileName } from "./constants.mjs";
4
4
  import { getServices } from "./service.mjs";
5
+ function getPageParamTypeKind(type) {
6
+ const types = type.isUnion()
7
+ ? type.types.filter((item) => !(item.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)))
8
+ : [type];
9
+ if (types.length > 0 &&
10
+ types.every((item) => item.flags & ts.TypeFlags.StringLike)) {
11
+ return "string";
12
+ }
13
+ if (types.length > 0 &&
14
+ types.every((item) => item.flags & ts.TypeFlags.NumberLike)) {
15
+ return "number";
16
+ }
17
+ return "other";
18
+ }
5
19
  /**
6
20
  * Extract parameter information from a method's variable declaration.
7
21
  */
@@ -30,8 +44,9 @@ function getPaginatableMethods(project, pageParam) {
30
44
  .getSourceFiles()
31
45
  .find((sf) => sf.getFilePath().includes(modelsFileName));
32
46
  if (!modelsFile)
33
- return [];
34
- const paginatableMethods = [];
47
+ return new Map();
48
+ const paginatableMethods = new Map();
49
+ const typeChecker = project.getTypeChecker().compilerObject;
35
50
  const modelDeclarations = modelsFile.getExportedDeclarations();
36
51
  const entries = modelDeclarations.entries();
37
52
  for (const [key, value] of entries) {
@@ -53,13 +68,18 @@ function getPaginatableMethods(project, pageParam) {
53
68
  const queryType = query.type;
54
69
  if (!queryType || queryType.kind !== ts.SyntaxKind.TypeLiteral)
55
70
  continue;
56
- const hasPageParam = queryType.members.some((m) => m.name?.getText() === pageParam);
57
- if (hasPageParam) {
71
+ const pageParamNode = queryType.members.find((m) => ts.isPropertySignature(m) && m.name?.getText() === pageParam);
72
+ if (pageParamNode) {
58
73
  // Extract method name from Data type name (e.g., "FindPetsData" -> "findPets")
59
74
  const methodName = key.slice(0, -4); // Remove "Data" suffix
60
75
  // Convert first letter to lowercase
61
76
  const methodNameLower = methodName.charAt(0).toLowerCase() + methodName.slice(1);
62
- paginatableMethods.push(methodNameLower);
77
+ const pageParamType = pageParamNode.type?.getText(modelsFile.compilerNode);
78
+ const resolvedType = typeChecker.getTypeAtLocation(pageParamNode.type ?? pageParamNode);
79
+ paginatableMethods.set(methodNameLower, {
80
+ type: pageParamType ?? "unknown",
81
+ typeKind: getPageParamTypeKind(resolvedType),
82
+ });
63
83
  }
64
84
  }
65
85
  return paginatableMethods;
@@ -80,7 +100,8 @@ export async function parseOperations(project, pageParam) {
80
100
  // via extractPropertiesFromObjectParam for type alias properties (path, url).
81
101
  const sdkParams = getVariableArrowFunctionParameters(desc.method);
82
102
  const allParamsOptional = sdkParams.length === 0 || sdkParams[0].isOptional();
83
- const isPaginatable = httpMethod === "GET" && paginatableMethods.includes(methodName);
103
+ const pageParamInfo = paginatableMethods.get(methodName);
104
+ const isPaginatable = httpMethod === "GET" && pageParamInfo !== undefined;
84
105
  return {
85
106
  methodName,
86
107
  capitalizedMethodName: capitalizeFirstLetter(methodName),
@@ -90,13 +111,15 @@ export async function parseOperations(project, pageParam) {
90
111
  parameters,
91
112
  allParamsOptional,
92
113
  isPaginatable,
114
+ pageParamType: isPaginatable ? pageParamInfo.type : undefined,
115
+ pageParamTypeKind: isPaginatable ? pageParamInfo.typeKind : undefined,
93
116
  };
94
117
  });
95
118
  }
96
119
  /**
97
120
  * Build generation context from project configuration.
98
121
  */
99
- export function buildGenerationContext(project, client, pageParam, nextPageParam, initialPageParam, version) {
122
+ export function buildGenerationContext(project, client, pageParam, nextPageParam, initialPageParam, omitInitialPageParam, version) {
100
123
  const modelsFile = project
101
124
  .getSourceFiles()
102
125
  .find((sf) => sf.getFilePath().includes(modelsFileName));
@@ -117,6 +140,7 @@ export function buildGenerationContext(project, client, pageParam, nextPageParam
117
140
  pageParam,
118
141
  nextPageParam,
119
142
  initialPageParam,
143
+ omitInitialPageParam,
120
144
  version,
121
145
  };
122
146
  }
@@ -0,0 +1,5 @@
1
+ import type { LimitedUserConfig } from "./cli.mjs";
2
+ export declare function print(results: {
3
+ name: string;
4
+ content: string;
5
+ }[], options: Pick<LimitedUserConfig, "output">): Promise<void>;
@@ -0,0 +1,8 @@
1
+ import type { Project, SourceFile } from "ts-morph";
2
+ import type { FunctionDescription } from "./common.mjs";
3
+ export type Service = {
4
+ node: SourceFile;
5
+ methods: Array<FunctionDescription>;
6
+ };
7
+ export declare function getServices(project: Project): Promise<Service>;
8
+ export declare function getMethodsFromService(node: SourceFile): FunctionDescription[];
@@ -0,0 +1,66 @@
1
+ import { type TypeAliasDeclarationStructure, type VariableStatementStructure } from "ts-morph";
2
+ import type { GenerationContext, OperationInfo } from "../types.mjs";
3
+ /**
4
+ * Build the default response type alias.
5
+ * Example: export type FindPetsDefaultResponse = Awaited<ReturnType<typeof findPets>>["data"];
6
+ */
7
+ export declare function buildDefaultResponseType(op: OperationInfo): TypeAliasDeclarationStructure;
8
+ /**
9
+ * Build the query result type alias.
10
+ * Example: export type FindPetsQueryResult<TData = FindPetsDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
11
+ */
12
+ export declare function buildQueryResultType(op: OperationInfo): TypeAliasDeclarationStructure;
13
+ /**
14
+ * Build the mutation result type alias.
15
+ * Example: export type AddPetMutationResult = Awaited<ReturnType<typeof addPet>>;
16
+ */
17
+ export declare function buildMutationResultType(op: OperationInfo): TypeAliasDeclarationStructure;
18
+ /**
19
+ * Build query key constant.
20
+ * Example: export const useFindPetsKey = "FindPets";
21
+ */
22
+ export declare function buildQueryKeyConst(op: OperationInfo): VariableStatementStructure;
23
+ /**
24
+ * Build mutation key constant.
25
+ * Example: export const useAddPetKey = "AddPet";
26
+ */
27
+ export declare function buildMutationKeyConst(op: OperationInfo): VariableStatementStructure;
28
+ /**
29
+ * Build query key function.
30
+ * Example: export const UseFindPetsKeyFn = (clientOptions: Options<FindPetsData, true> = {}, queryKey?: Array<unknown>) =>
31
+ * [useFindPetsKey, ...(queryKey ?? [clientOptions])];
32
+ */
33
+ export declare function buildQueryKeyFn(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
34
+ /**
35
+ * Build mutation key function.
36
+ * Example: export const UseAddPetKeyFn = (mutationKey?: Array<unknown>) =>
37
+ * [useAddPetKey, ...(mutationKey ?? [])];
38
+ */
39
+ export declare function buildMutationKeyFn(op: OperationInfo): VariableStatementStructure;
40
+ /**
41
+ * Build the client options type for infinite queries.
42
+ * The page parameter is excluded because TanStack Query supplies it via the
43
+ * pageParam mechanism (#140).
44
+ * Example:
45
+ * export type FindPaginatedPetsInfiniteClientOptions = Omit<Options<FindPaginatedPetsData, true>, "query"> &
46
+ * { query?: Omit<NonNullable<FindPaginatedPetsData["query"]>, "page"> };
47
+ */
48
+ export declare function buildInfiniteClientOptionsType(op: OperationInfo, ctx: GenerationContext): TypeAliasDeclarationStructure;
49
+ /**
50
+ * Build the infinite query key constant.
51
+ * Shares the plain query key as its first segment so a single
52
+ * `invalidateQueries({ queryKey: [useXKey] })` matches both the plain and the
53
+ * infinite cache entries of an operation (#174), while the extra "infinite"
54
+ * segment keeps cached InfiniteData from colliding with plain query data (#140).
55
+ * Example: export const useFindPaginatedPetsInfiniteKey = [useFindPaginatedPetsKey, "infinite"] as const;
56
+ */
57
+ export declare function buildInfiniteQueryKeyConst(op: OperationInfo): VariableStatementStructure;
58
+ /**
59
+ * Build the infinite query key function.
60
+ * The custom queryKey argument only replaces the params segment — the
61
+ * hierarchical [opKey, "infinite"] prefix is always preserved so
62
+ * prefix-based invalidation keeps working.
63
+ * Example: export const UseFindPaginatedPetsInfiniteKeyFn = (clientOptions: FindPaginatedPetsInfiniteClientOptions = {}, queryKey?: Array<unknown>) =>
64
+ * [...useFindPaginatedPetsInfiniteKey, ...(queryKey ?? [clientOptions])];
65
+ */
66
+ export declare function buildInfiniteQueryKeyFn(op: OperationInfo): VariableStatementStructure;
@@ -0,0 +1,42 @@
1
+ import { type VariableStatementStructure } from "ts-morph";
2
+ import type { GenerationContext, OperationInfo } from "../types.mjs";
3
+ /**
4
+ * Build query key constant name (e.g., "findPetsQueryKey").
5
+ */
6
+ export declare function getQueryKeyName(op: OperationInfo): string;
7
+ /**
8
+ * Build mutation key constant name (e.g., "addPetMutationKey").
9
+ */
10
+ export declare function getMutationKeyName(op: OperationInfo): string;
11
+ /**
12
+ * Build query key fn name (e.g., "FindPetsQueryKeyFn").
13
+ */
14
+ export declare function getQueryKeyFnName(op: OperationInfo): string;
15
+ /**
16
+ * Build mutation key fn name (e.g., "AddPetMutationKeyFn").
17
+ */
18
+ export declare function getMutationKeyFnName(op: OperationInfo): string;
19
+ /**
20
+ * Build the query key constant export.
21
+ * Example: export const findPetsQueryKey = "FindPets";
22
+ */
23
+ export declare function buildQueryKeyExport(op: OperationInfo): VariableStatementStructure;
24
+ /**
25
+ * Build the mutation key constant export.
26
+ * Example: export const addPetMutationKey = "AddPet";
27
+ */
28
+ export declare function buildMutationKeyExport(op: OperationInfo): VariableStatementStructure;
29
+ /**
30
+ * Build the query key function export.
31
+ * Example:
32
+ * export const FindPetsQueryKeyFn = (clientOptions: Options<FindPetsData, true>, queryKey?: Array<unknown>) =>
33
+ * [findPetsQueryKey, ...(queryKey ?? [clientOptions])] as const;
34
+ */
35
+ export declare function buildQueryKeyFnExport(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
36
+ /**
37
+ * Build the mutation key function export.
38
+ * Example:
39
+ * export const AddPetMutationKeyFn = (mutationKey?: Array<unknown>) =>
40
+ * [addPetMutationKey, ...(mutationKey ?? [])] as const;
41
+ */
42
+ export declare function buildMutationKeyFnExport(op: OperationInfo): VariableStatementStructure;
@@ -0,0 +1,15 @@
1
+ import { type VariableStatementStructure } from "ts-morph";
2
+ import type { GenerationContext, OperationInfo } from "../types.mjs";
3
+ /**
4
+ * Build useMutation hook.
5
+ * Example:
6
+ * export const useAddPet = <TData = Common.AddPetMutationResult, TError = AddPetError, TQueryKey extends Array<unknown> = unknown[], TContext = unknown>(
7
+ * mutationKey?: TQueryKey,
8
+ * options?: Omit<UseMutationOptions<TData, TError, Options<AddPetData, true>, TContext>, "mutationKey" | "mutationFn">
9
+ * ) => useMutation<TData, TError, Options<AddPetData, true>, TContext>({
10
+ * mutationKey: Common.UseAddPetKeyFn(mutationKey),
11
+ * mutationFn: clientOptions => addPet(clientOptions) as unknown as Promise<TData>,
12
+ * ...options
13
+ * });
14
+ */
15
+ export declare function buildUseMutationHook(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
@@ -0,0 +1,116 @@
1
+ import { type VariableStatementStructure } from "ts-morph";
2
+ import type { GenerationContext, OperationInfo } from "../types.mjs";
3
+ /**
4
+ * Resolve the generated Data type name for an operation, falling back to
5
+ * unknown when the operation has no generated Data type.
6
+ */
7
+ export declare function getDataTypeName(op: OperationInfo, ctx: GenerationContext): string;
8
+ /**
9
+ * SDK call arguments shared by every generated queryFn/mutationFn.
10
+ * throwOnError: true forces the SDK call to reject on error responses; the
11
+ * hey-api runtime default is false, which would resolve undefined data and
12
+ * swallow the error instead of surfacing it to TanStack Query (#172).
13
+ */
14
+ export declare const SDK_CALL_ARGS = "{ ...clientOptions, throwOnError: true }";
15
+ /** SDK call arguments for TanStack query functions with cancellation. */
16
+ export declare const QUERY_SDK_CALL_ARGS = "{ ...clientOptions, signal, throwOnError: true }";
17
+ /** Resolve the OpenAPI page parameter type, preserving older numeric output. */
18
+ export declare function getPageParamType(op: OperationInfo): string;
19
+ /**
20
+ * Build the client options parameter string.
21
+ */
22
+ export declare function buildClientOptionsParam(op: OperationInfo, ctx: GenerationContext): string;
23
+ /**
24
+ * Build the clientOptions parameter typed with the page-less infinite
25
+ * options type — the page parameter is supplied by TanStack Query's
26
+ * pageParam mechanism.
27
+ */
28
+ export declare function buildInfiniteClientOptionsParam(op: OperationInfo): string;
29
+ /**
30
+ * Build the paginated SDK call shared by every infinite query builder.
31
+ */
32
+ export declare function buildPagedQueryFn(op: OperationInfo, ctx: GenerationContext, castTData: boolean): string;
33
+ /**
34
+ * Format the initialPageParam literal. Emits `undefined` when the caller opted
35
+ * to omit it (#177); otherwise a numeric literal when possible so the inferred
36
+ * pageParam type matches what getNextPageParam returns.
37
+ */
38
+ export declare function formatInitialPageParam(ctx: GenerationContext, op?: OperationInfo): string;
39
+ /**
40
+ * Build the nested type for getNextPageParam.
41
+ * E.g., "meta.next" becomes "{ meta: { next: number } }"
42
+ */
43
+ export declare function buildNestedNextPageType(nextPageParam: string, pageParamType?: string): string;
44
+ /**
45
+ * Build the getNextPageParam expression. The parameter is annotated because
46
+ * not every TanStack entry point contextually types it (prefetchInfiniteQuery
47
+ * does not, which would fail noImplicitAny).
48
+ */
49
+ export declare function buildGetNextPageParamExpr(ctx: GenerationContext, op?: OperationInfo): string;
50
+ /**
51
+ * Build an options type where the pagination fields TanStack Query marks as
52
+ * required become optional overrides: the generator supplies them, and
53
+ * callers may replace them for custom pagination schemes (#156, #146).
54
+ */
55
+ export declare function buildOverridableInfiniteOptionsType(optionsTypeName: string): string;
56
+ /**
57
+ * Build useQuery hook.
58
+ * Example:
59
+ * export const useFindPets = <TData = Common.FindPetsDefaultResponse, TError = FindPetsError, TQueryKey extends Array<unknown> = unknown[]>(
60
+ * clientOptions: Options<FindPetsData, true> = {},
61
+ * queryKey?: TQueryKey,
62
+ * options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">
63
+ * ) => useQuery<TData, TError>({
64
+ * queryKey: Common.UseFindPetsKeyFn(clientOptions, queryKey),
65
+ * queryFn: () => findPets({ ...clientOptions, throwOnError: true }).then(response => response.data as TData) as TData,
66
+ * ...options
67
+ * });
68
+ */
69
+ export declare function buildUseQueryHook(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
70
+ /**
71
+ * Build useSuspenseQuery hook.
72
+ */
73
+ export declare function buildUseSuspenseQueryHook(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
74
+ /**
75
+ * Build useInfiniteQuery hook.
76
+ */
77
+ export declare function buildUseInfiniteQueryHook(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure | null;
78
+ /**
79
+ * Build useSuspenseInfiniteQuery hook.
80
+ */
81
+ export declare function buildUseSuspenseInfiniteQueryHook(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure | null;
82
+ /**
83
+ * Build prefetch function.
84
+ * Example:
85
+ * export const prefetchUseFindPets = (queryClient: QueryClient, clientOptions: Options<FindPetsData, true> = {}, options?: Omit<FetchQueryOptions<Common.FindPetsDefaultResponse>, "queryKey" | "queryFn">) =>
86
+ * queryClient.prefetchQuery({
87
+ * queryKey: Common.UseFindPetsKeyFn(clientOptions),
88
+ * queryFn: () => findPets({ ...clientOptions, throwOnError: true }).then(response => response.data),
89
+ * ...options
90
+ * });
91
+ */
92
+ export declare function buildPrefetchFn(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
93
+ /**
94
+ * Build prefetchInfiniteQuery function for a paginatable operation.
95
+ * Example:
96
+ * export const prefetchUseFindPaginatedPetsInfinite = (queryClient: QueryClient, clientOptions: Common.FindPaginatedPetsInfiniteClientOptions = {}, options?: Omit<FetchInfiniteQueryOptions<Common.FindPaginatedPetsDefaultResponse>, "queryKey" | "queryFn" | "initialPageParam" | "getNextPageParam">) =>
97
+ * queryClient.prefetchInfiniteQuery({
98
+ * queryKey: Common.UseFindPaginatedPetsInfiniteKeyFn(clientOptions),
99
+ * queryFn: ({ pageParam }) => findPaginatedPets({ ...clientOptions, query: { ...clientOptions.query, page: pageParam as number }, throwOnError: true } as Options<FindPaginatedPetsData, true>).then(response => response.data),
100
+ * initialPageParam: 1,
101
+ * getNextPageParam: (response: unknown) => (response as { nextPage: number }).nextPage,
102
+ * ...options
103
+ * });
104
+ */
105
+ export declare function buildPrefetchInfiniteQueryFn(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure | null;
106
+ /**
107
+ * Build ensureQueryData function.
108
+ * Example:
109
+ * export const ensureUseFindPetsData = (queryClient: QueryClient, clientOptions: Options<FindPetsData, true> = {}, options?: Omit<EnsureQueryDataOptions<Common.FindPetsDefaultResponse>, "queryKey" | "queryFn">) =>
110
+ * queryClient.ensureQueryData({
111
+ * queryKey: Common.UseFindPetsKeyFn(clientOptions),
112
+ * queryFn: () => findPets({ ...clientOptions, throwOnError: true }).then(response => response.data),
113
+ * ...options
114
+ * });
115
+ */
116
+ export declare function buildEnsureQueryDataFn(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
@@ -29,6 +29,12 @@ export function getDataTypeName(op, ctx) {
29
29
  * swallow the error instead of surfacing it to TanStack Query (#172).
30
30
  */
31
31
  export const SDK_CALL_ARGS = "{ ...clientOptions, throwOnError: true }";
32
+ /** SDK call arguments for TanStack query functions with cancellation. */
33
+ export const QUERY_SDK_CALL_ARGS = "{ ...clientOptions, signal, throwOnError: true }";
34
+ /** Resolve the OpenAPI page parameter type, preserving older numeric output. */
35
+ export function getPageParamType(op) {
36
+ return op.pageParamType ?? "number";
37
+ }
32
38
  /**
33
39
  * Build the client options parameter string.
34
40
  */
@@ -58,13 +64,31 @@ export function buildPagedQueryFn(op, ctx, castTData) {
58
64
  const thenClause = castTData
59
65
  ? ".then(response => response.data as TData) as TData"
60
66
  : ".then(response => response.data)";
61
- return `({ pageParam }) => ${op.methodName}({ ...clientOptions, query: { ...clientOptions.query, ${ctx.pageParam}: pageParam as number }, throwOnError: true } as Options<${dataTypeName}, true>)${thenClause}`;
67
+ const pageParamType = getPageParamType(op);
68
+ // When the initial page param is omitted, the first request must send no
69
+ // page param at all, so spread it in only once TanStack Query provides one.
70
+ const pageQuery = ctx.omitInitialPageParam
71
+ ? `...(pageParam === undefined ? {} : { ${ctx.pageParam}: pageParam as ${pageParamType} })`
72
+ : `${ctx.pageParam}: pageParam as ${pageParamType}`;
73
+ return `({ pageParam, signal }) => ${op.methodName}({ ...clientOptions, query: { ...clientOptions.query, ${pageQuery} }, signal, throwOnError: true } as Options<${dataTypeName}, true>)${thenClause}`;
62
74
  }
63
75
  /**
64
- * Format the initialPageParam literal. Emits a numeric literal when possible
65
- * so the inferred pageParam type matches what getNextPageParam returns.
76
+ * Format the initialPageParam literal. Emits `undefined` when the caller opted
77
+ * to omit it (#177); otherwise a numeric literal when possible so the inferred
78
+ * pageParam type matches what getNextPageParam returns.
66
79
  */
67
- export function formatInitialPageParam(ctx) {
80
+ export function formatInitialPageParam(ctx, op) {
81
+ if (ctx.omitInitialPageParam) {
82
+ return "undefined";
83
+ }
84
+ const isStringPageParam = op
85
+ ? op.pageParamTypeKind === "string" ||
86
+ (op.pageParamTypeKind === undefined &&
87
+ /\bstring\b/.test(getPageParamType(op)))
88
+ : false;
89
+ if (isStringPageParam) {
90
+ return JSON.stringify(ctx.initialPageParam);
91
+ }
68
92
  return /^-?\d+$/.test(ctx.initialPageParam)
69
93
  ? ctx.initialPageParam
70
94
  : JSON.stringify(ctx.initialPageParam);
@@ -73,19 +97,19 @@ export function formatInitialPageParam(ctx) {
73
97
  * Build the nested type for getNextPageParam.
74
98
  * E.g., "meta.next" becomes "{ meta: { next: number } }"
75
99
  */
76
- export function buildNestedNextPageType(nextPageParam) {
100
+ export function buildNestedNextPageType(nextPageParam, pageParamType = "number") {
77
101
  const segments = nextPageParam.split(".");
78
102
  return segments.reduceRight((acc, segment) => {
79
103
  return `{ ${segment}: ${acc} }`;
80
- }, "number");
104
+ }, pageParamType);
81
105
  }
82
106
  /**
83
107
  * Build the getNextPageParam expression. The parameter is annotated because
84
108
  * not every TanStack entry point contextually types it (prefetchInfiniteQuery
85
109
  * does not, which would fail noImplicitAny).
86
110
  */
87
- export function buildGetNextPageParamExpr(ctx) {
88
- const nestedType = buildNestedNextPageType(ctx.nextPageParam);
111
+ export function buildGetNextPageParamExpr(ctx, op) {
112
+ const nestedType = buildNestedNextPageType(ctx.nextPageParam, op ? getPageParamType(op) : "number");
89
113
  return `(response: unknown) => (response as ${nestedType}).${ctx.nextPageParam}`;
90
114
  }
91
115
  /**
@@ -115,7 +139,7 @@ export function buildUseQueryHook(op, ctx) {
115
139
  const errorType = getErrorType(op, ctx);
116
140
  const dataTypeDefault = `Common.${op.capitalizedMethodName}DefaultResponse`;
117
141
  const clientOptionsParam = buildClientOptionsParam(op, ctx);
118
- const queryFn = `() => ${op.methodName}(${SDK_CALL_ARGS}).then(response => response.data as TData) as TData`;
142
+ const queryFn = `({ signal }) => ${op.methodName}(${QUERY_SDK_CALL_ARGS}).then(response => response.data as TData) as TData`;
119
143
  const body = `useQuery<TData, TError>({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ...options })`;
120
144
  return {
121
145
  kind: StructureKind.VariableStatement,
@@ -139,7 +163,7 @@ export function buildUseSuspenseQueryHook(op, ctx) {
139
163
  const errorType = getErrorType(op, ctx);
140
164
  const dataTypeDefault = `NonNullable<Common.${op.capitalizedMethodName}DefaultResponse>`;
141
165
  const clientOptionsParam = buildClientOptionsParam(op, ctx);
142
- const queryFn = `() => ${op.methodName}(${SDK_CALL_ARGS}).then(response => response.data as TData) as TData`;
166
+ const queryFn = `({ signal }) => ${op.methodName}(${QUERY_SDK_CALL_ARGS}).then(response => response.data as TData) as TData`;
143
167
  const body = `useSuspenseQuery<TData, TError>({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ...options })`;
144
168
  return {
145
169
  kind: StructureKind.VariableStatement,
@@ -178,7 +202,7 @@ function buildInfiniteHook(op, ctx, suspense) {
178
202
  ? `InfiniteData<NonNullable<${baseDataType}>>`
179
203
  : `InfiniteData<${baseDataType}>`;
180
204
  const queryFn = buildPagedQueryFn(op, ctx, true);
181
- const infiniteOptions = `initialPageParam: ${formatInitialPageParam(ctx)}, getNextPageParam: ${buildGetNextPageParamExpr(ctx)}`;
205
+ const infiniteOptions = `initialPageParam: ${formatInitialPageParam(ctx, op)}, getNextPageParam: ${buildGetNextPageParamExpr(ctx, op)}`;
182
206
  const body = `${hookCall}({ queryKey: Common.Use${op.capitalizedMethodName}InfiniteKeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ${infiniteOptions}, ...options })`;
183
207
  return {
184
208
  kind: StructureKind.VariableStatement,
@@ -218,7 +242,7 @@ export function buildUseSuspenseInfiniteQueryHook(op, ctx) {
218
242
  */
219
243
  export function buildPrefetchFn(op, ctx) {
220
244
  const fnName = `prefetchUse${op.capitalizedMethodName}`;
221
- const queryFn = `() => ${op.methodName}(${SDK_CALL_ARGS}).then(response => response.data)`;
245
+ const queryFn = `({ signal }) => ${op.methodName}(${QUERY_SDK_CALL_ARGS}).then(response => response.data)`;
222
246
  const optionsParam = `options?: Omit<FetchQueryOptions<Common.${op.capitalizedMethodName}DefaultResponse>, "queryKey" | "queryFn">`;
223
247
  const body = `queryClient.prefetchQuery({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions), queryFn: ${queryFn}, ...options })`;
224
248
  return {
@@ -253,7 +277,7 @@ export function buildPrefetchInfiniteQueryFn(op, ctx) {
253
277
  }
254
278
  const fnName = `prefetchUse${op.capitalizedMethodName}Infinite`;
255
279
  const queryFn = buildPagedQueryFn(op, ctx, false);
256
- const infiniteOptions = `initialPageParam: ${formatInitialPageParam(ctx)}, getNextPageParam: ${buildGetNextPageParamExpr(ctx)}`;
280
+ const infiniteOptions = `initialPageParam: ${formatInitialPageParam(ctx, op)}, getNextPageParam: ${buildGetNextPageParamExpr(ctx, op)}`;
257
281
  const optionsParam = `options?: Omit<FetchInfiniteQueryOptions<Common.${op.capitalizedMethodName}DefaultResponse>, "queryKey" | "queryFn" | "initialPageParam" | "getNextPageParam">`;
258
282
  const body = `queryClient.prefetchInfiniteQuery({ queryKey: Common.Use${op.capitalizedMethodName}InfiniteKeyFn(clientOptions), queryFn: ${queryFn}, ${infiniteOptions}, ...options })`;
259
283
  return {
@@ -282,7 +306,7 @@ export function buildPrefetchInfiniteQueryFn(op, ctx) {
282
306
  */
283
307
  export function buildEnsureQueryDataFn(op, ctx) {
284
308
  const fnName = `ensureUse${op.capitalizedMethodName}Data`;
285
- const queryFn = `() => ${op.methodName}(${SDK_CALL_ARGS}).then(response => response.data)`;
309
+ const queryFn = `({ signal }) => ${op.methodName}(${QUERY_SDK_CALL_ARGS}).then(response => response.data)`;
286
310
  const optionsParam = `options?: Omit<EnsureQueryDataOptions<Common.${op.capitalizedMethodName}DefaultResponse>, "queryKey" | "queryFn">`;
287
311
  const body = `queryClient.ensureQueryData({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions), queryFn: ${queryFn}, ...options })`;
288
312
  return {
@@ -0,0 +1,28 @@
1
+ import { type VariableStatementStructure } from "ts-morph";
2
+ import type { GenerationContext, OperationInfo } from "../types.mjs";
3
+ /**
4
+ * Build a queryOptions factory for a GET operation.
5
+ * The factory centralizes queryKey and queryFn so they can be reused with
6
+ * every TanStack Query utility (useQuery, useQueries, prefetchQuery,
7
+ * ensureQueryData, setQueryData, ...) with full type safety.
8
+ * Example:
9
+ * export const findPetsOptions = (clientOptions: Options<FindPetsData, true> = {}, queryKey?: Array<unknown>) =>
10
+ * queryOptions({
11
+ * queryKey: Common.UseFindPetsKeyFn(clientOptions, queryKey),
12
+ * queryFn: () => findPets({ ...clientOptions, throwOnError: true }).then(response => response.data),
13
+ * });
14
+ */
15
+ export declare function buildQueryOptionsFn(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure;
16
+ /**
17
+ * Build an infiniteQueryOptions factory for a paginatable GET operation.
18
+ * Uses the dedicated infinite query key and page-less options type.
19
+ * Example:
20
+ * export const findPaginatedPetsInfiniteOptions = (clientOptions: Common.FindPaginatedPetsInfiniteClientOptions = {}, queryKey?: Array<unknown>) =>
21
+ * infiniteQueryOptions({
22
+ * queryKey: Common.UseFindPaginatedPetsInfiniteKeyFn(clientOptions, queryKey),
23
+ * queryFn: ({ pageParam }) => findPaginatedPets({ ...clientOptions, query: { ...clientOptions.query, page: pageParam as number }, throwOnError: true } as Options<FindPaginatedPetsData, true>).then(response => response.data),
24
+ * initialPageParam: 1,
25
+ * getNextPageParam: (response: unknown) => (response as { nextPage: number }).nextPage,
26
+ * });
27
+ */
28
+ export declare function buildInfiniteQueryOptionsFn(op: OperationInfo, ctx: GenerationContext): VariableStatementStructure | null;
@@ -1,5 +1,5 @@
1
1
  import { StructureKind, VariableDeclarationKind, } from "ts-morph";
2
- import { buildClientOptionsParam, buildGetNextPageParamExpr, buildInfiniteClientOptionsParam, buildPagedQueryFn, formatInitialPageParam, SDK_CALL_ARGS, } from "./buildQueryHooks.mjs";
2
+ import { buildClientOptionsParam, buildGetNextPageParamExpr, buildInfiniteClientOptionsParam, buildPagedQueryFn, formatInitialPageParam, QUERY_SDK_CALL_ARGS, } from "./buildQueryHooks.mjs";
3
3
  /**
4
4
  * Build a queryOptions factory for a GET operation.
5
5
  * The factory centralizes queryKey and queryFn so they can be reused with
@@ -15,7 +15,7 @@ import { buildClientOptionsParam, buildGetNextPageParamExpr, buildInfiniteClient
15
15
  export function buildQueryOptionsFn(op, ctx) {
16
16
  const fnName = `${op.methodName}Options`;
17
17
  const clientOptionsParam = buildClientOptionsParam(op, ctx);
18
- const queryFn = `() => ${op.methodName}(${SDK_CALL_ARGS}).then(response => response.data)`;
18
+ const queryFn = `({ signal }) => ${op.methodName}(${QUERY_SDK_CALL_ARGS}).then(response => response.data)`;
19
19
  const body = `queryOptions({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions, queryKey), queryFn: ${queryFn} })`;
20
20
  return {
21
21
  kind: StructureKind.VariableStatement,
@@ -49,7 +49,7 @@ export function buildInfiniteQueryOptionsFn(op, ctx) {
49
49
  }
50
50
  const fnName = `${op.methodName}InfiniteOptions`;
51
51
  const queryFn = buildPagedQueryFn(op, ctx, false);
52
- const infiniteOptions = `initialPageParam: ${formatInitialPageParam(ctx)}, getNextPageParam: ${buildGetNextPageParamExpr(ctx)}`;
52
+ const infiniteOptions = `initialPageParam: ${formatInitialPageParam(ctx, op)}, getNextPageParam: ${buildGetNextPageParamExpr(ctx, op)}`;
53
53
  const body = `infiniteQueryOptions({ queryKey: Common.Use${op.capitalizedMethodName}InfiniteKeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ${infiniteOptions} })`;
54
54
  return {
55
55
  kind: StructureKind.VariableStatement,
@@ -0,0 +1,5 @@
1
+ import type { GeneratedFile, GenerationContext, OperationInfo } from "../types.mjs";
2
+ /**
3
+ * Generate all files using ts-morph.
4
+ */
5
+ export declare function generateAllFiles(operations: OperationInfo[], ctx: GenerationContext): GeneratedFile[];
@@ -0,0 +1,5 @@
1
+ export * from "./buildCommon.mjs";
2
+ export * from "./buildMutationHooks.mjs";
3
+ export * from "./buildQueryHooks.mjs";
4
+ export { generateAllFiles } from "./generateFiles.mjs";
5
+ export { createGenerationProject } from "./projectFactory.mjs";
@@ -0,0 +1,45 @@
1
+ import { type ImportDeclarationStructure, Project } from "ts-morph";
2
+ import type { GenerationContext } from "../types.mjs";
3
+ /**
4
+ * Create a shared ts-morph Project for code generation.
5
+ * Uses consistent formatting settings to match existing output.
6
+ */
7
+ export declare function createGenerationProject(): Project;
8
+ /**
9
+ * Build import structure for the Options type.
10
+ * sdk.gen re-exports Options extended with `client` and `meta`, which the
11
+ * base client Options lacks; hooks must accept those properties.
12
+ */
13
+ export declare function buildClientImport(_ctx: GenerationContext): ImportDeclarationStructure;
14
+ /**
15
+ * Build import structure for TanStack Query.
16
+ */
17
+ export declare function buildQueryImport(): ImportDeclarationStructure;
18
+ /**
19
+ * Build import structure for the queryOptions/infiniteQueryOptions helpers.
20
+ */
21
+ export declare function buildQueryOptionsImport(): ImportDeclarationStructure;
22
+ /**
23
+ * Build import structure for services.
24
+ */
25
+ export declare function buildServiceImport(ctx: GenerationContext): ImportDeclarationStructure;
26
+ /**
27
+ * Build import structure for models.
28
+ */
29
+ export declare function buildModelImport(ctx: GenerationContext): ImportDeclarationStructure | null;
30
+ /**
31
+ * Build import structure for axios error type.
32
+ */
33
+ export declare function buildAxiosErrorImport(): ImportDeclarationStructure;
34
+ /**
35
+ * Build import for Common namespace.
36
+ */
37
+ export declare function buildCommonImport(): ImportDeclarationStructure;
38
+ /**
39
+ * Build all imports needed for the common file.
40
+ */
41
+ export declare function buildCommonFileImports(ctx: GenerationContext): ImportDeclarationStructure[];
42
+ /**
43
+ * Build all imports needed for hook files (queries, suspense, infinite).
44
+ */
45
+ export declare function buildHookFileImports(ctx: GenerationContext): ImportDeclarationStructure[];
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Normalized operation information extracted from the OpenAPI service.
3
+ * This is a pure JSON-serializable structure that can be consumed by generators.
4
+ */
5
+ export interface OperationInfo {
6
+ /** Method/function name as defined in service (e.g., "findPets") */
7
+ methodName: string;
8
+ /** Capitalized method name (e.g., "FindPets") */
9
+ capitalizedMethodName: string;
10
+ /** HTTP method (e.g., "GET", "POST", "PUT", "PATCH", "DELETE") */
11
+ httpMethod: string;
12
+ /** JSDoc comment string (if present) */
13
+ jsDoc?: string;
14
+ /** Whether the operation is deprecated */
15
+ isDeprecated: boolean;
16
+ /** Parameter information for the operation */
17
+ parameters: OperationParameter[];
18
+ /** Whether all parameters are optional */
19
+ allParamsOptional: boolean;
20
+ /** Whether this operation supports pagination (for infinite queries) */
21
+ isPaginatable: boolean;
22
+ /** Type of the configured page query parameter */
23
+ pageParamType?: string;
24
+ /** Resolved primitive kind of the configured page query parameter */
25
+ pageParamTypeKind?: PageParamTypeKind;
26
+ }
27
+ export type PageParamTypeKind = "string" | "number" | "other";
28
+ export interface OperationParameter {
29
+ /** Parameter name */
30
+ name: string;
31
+ /** TypeScript type as string */
32
+ typeName: string;
33
+ /** Whether this parameter is optional */
34
+ optional: boolean;
35
+ }
36
+ /**
37
+ * Context for generating hooks and utilities.
38
+ * Contains shared information needed across all generators.
39
+ */
40
+ export interface GenerationContext {
41
+ /** Client type: "@hey-api/client-fetch" or "@hey-api/client-axios" */
42
+ client: "@hey-api/client-fetch" | "@hey-api/client-axios";
43
+ /** Model type names exported from the models file */
44
+ modelNames: string[];
45
+ /** Service function names exported from the service file */
46
+ serviceNames: string[];
47
+ /** Page param name for infinite queries (e.g., "page") */
48
+ pageParam: string;
49
+ /** Next page param name for infinite queries (e.g., "nextPage") */
50
+ nextPageParam: string;
51
+ /** Initial page param value for infinite queries */
52
+ initialPageParam: string;
53
+ /** Omit the initial page param entirely (sends no page param on the first request) */
54
+ omitInitialPageParam: boolean;
55
+ /** Package version for generated comment */
56
+ version: string;
57
+ }
58
+ /**
59
+ * Generated output for a single file.
60
+ */
61
+ export interface GeneratedFile {
62
+ /** Filename without path (e.g., "queries.ts") */
63
+ name: string;
64
+ /** File content as string */
65
+ content: string;
66
+ }
@@ -0,0 +1,2 @@
1
+ import ts from "typescript";
2
+ export declare function addJSDocToNode<T extends ts.Node>(node: T, jsDoc: string | undefined): T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7nohe/openapi-react-query-codegen",
3
- "version": "3.0.0-beta.3",
3
+ "version": "3.0.0-beta.5",
4
4
  "description": "OpenAPI React Query Codegen",
5
5
  "bin": {
6
6
  "openapi-rq": "dist/cli.mjs"