@7nohe/openapi-react-query-codegen 2.1.0 → 3.0.0-beta.1

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.
@@ -0,0 +1,237 @@
1
+ import { StructureKind, VariableDeclarationKind, } from "ts-morph";
2
+ /**
3
+ * Get the error type string based on client type.
4
+ */
5
+ function getErrorType(op, ctx) {
6
+ const errorTypeName = `${op.capitalizedMethodName}Error`;
7
+ // Operations without error responses have no generated Error type
8
+ const errorType = ctx.modelNames.includes(errorTypeName)
9
+ ? errorTypeName
10
+ : "unknown";
11
+ if (ctx.client === "@hey-api/client-axios") {
12
+ return `AxiosError<${errorType}>`;
13
+ }
14
+ return errorType;
15
+ }
16
+ /**
17
+ * Get the data type based on hook type.
18
+ */
19
+ function getDataTypeDefault(op, hookType) {
20
+ const baseType = `Common.${op.capitalizedMethodName}DefaultResponse`;
21
+ if (hookType === "useSuspenseQuery") {
22
+ return `NonNullable<${baseType}>`;
23
+ }
24
+ if (hookType === "useInfiniteQuery") {
25
+ return `InfiniteData<${baseType}>`;
26
+ }
27
+ return baseType;
28
+ }
29
+ /**
30
+ * Get the options type name.
31
+ */
32
+ function getOptionsTypeName(hookType) {
33
+ switch (hookType) {
34
+ case "useSuspenseQuery":
35
+ return "UseSuspenseQueryOptions";
36
+ case "useInfiniteQuery":
37
+ return "UseInfiniteQueryOptions";
38
+ default:
39
+ return "UseQueryOptions";
40
+ }
41
+ }
42
+ /**
43
+ * Build the client options parameter string.
44
+ */
45
+ function buildClientOptionsParam(op, ctx) {
46
+ const dataTypeName = ctx.modelNames.includes(`${op.capitalizedMethodName}Data`)
47
+ ? `${op.capitalizedMethodName}Data`
48
+ : "unknown";
49
+ const hasParams = op.parameters.length > 0;
50
+ if (!hasParams) {
51
+ return `clientOptions: Options<${dataTypeName}, true> = {}`;
52
+ }
53
+ const defaultValue = op.allParamsOptional ? " = {}" : "";
54
+ return `clientOptions: Options<${dataTypeName}, true>${defaultValue}`;
55
+ }
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 }).then(response => response.data as TData) as TData,
66
+ * ...options
67
+ * });
68
+ */
69
+ export function buildUseQueryHook(op, ctx) {
70
+ const hookName = `use${op.capitalizedMethodName}`;
71
+ const errorType = getErrorType(op, ctx);
72
+ const dataTypeDefault = getDataTypeDefault(op, "useQuery");
73
+ const clientOptionsParam = buildClientOptionsParam(op, ctx);
74
+ const hasParams = op.parameters.length > 0;
75
+ // Build the queryFn body
76
+ const callArgs = hasParams ? "{ ...clientOptions }" : "{ ...clientOptions }";
77
+ const queryFn = `() => ${op.methodName}(${callArgs}).then(response => response.data as TData) as TData`;
78
+ const body = `useQuery<TData, TError>({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ...options })`;
79
+ return {
80
+ kind: StructureKind.VariableStatement,
81
+ // Copy the operation's JSDoc (description and @deprecated) from the SDK function
82
+ leadingTrivia: op.jsDoc ? `${op.jsDoc}\n` : undefined,
83
+ isExported: true,
84
+ declarationKind: VariableDeclarationKind.Const,
85
+ declarations: [
86
+ {
87
+ name: hookName,
88
+ initializer: `<TData = ${dataTypeDefault}, TError = ${errorType}, TQueryKey extends Array<unknown> = unknown[]>(${clientOptionsParam}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => ${body}`,
89
+ },
90
+ ],
91
+ };
92
+ }
93
+ /**
94
+ * Build useSuspenseQuery hook.
95
+ */
96
+ export function buildUseSuspenseQueryHook(op, ctx) {
97
+ const hookName = `use${op.capitalizedMethodName}Suspense`;
98
+ const errorType = getErrorType(op, ctx);
99
+ const dataTypeDefault = getDataTypeDefault(op, "useSuspenseQuery");
100
+ const clientOptionsParam = buildClientOptionsParam(op, ctx);
101
+ const hasParams = op.parameters.length > 0;
102
+ const callArgs = hasParams ? "{ ...clientOptions }" : "{ ...clientOptions }";
103
+ const queryFn = `() => ${op.methodName}(${callArgs}).then(response => response.data as TData) as TData`;
104
+ const body = `useSuspenseQuery<TData, TError>({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ...options })`;
105
+ return {
106
+ kind: StructureKind.VariableStatement,
107
+ // Copy the operation's JSDoc (description and @deprecated) from the SDK function
108
+ leadingTrivia: op.jsDoc ? `${op.jsDoc}\n` : undefined,
109
+ isExported: true,
110
+ declarationKind: VariableDeclarationKind.Const,
111
+ declarations: [
112
+ {
113
+ name: hookName,
114
+ initializer: `<TData = ${dataTypeDefault}, TError = ${errorType}, TQueryKey extends Array<unknown> = unknown[]>(${clientOptionsParam}, queryKey?: TQueryKey, options?: Omit<UseSuspenseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => ${body}`,
115
+ },
116
+ ],
117
+ };
118
+ }
119
+ /**
120
+ * Build the nested type for getNextPageParam.
121
+ * E.g., "meta.next" becomes "{ meta: { next: number } }"
122
+ */
123
+ function buildNestedNextPageType(nextPageParam) {
124
+ const segments = nextPageParam.split(".");
125
+ return segments.reduceRight((acc, segment) => {
126
+ return `{ ${segment}: ${acc} }`;
127
+ }, "number");
128
+ }
129
+ /**
130
+ * Build useInfiniteQuery hook.
131
+ */
132
+ export function buildUseInfiniteQueryHook(op, ctx) {
133
+ if (!op.isPaginatable) {
134
+ return null;
135
+ }
136
+ const hookName = `use${op.capitalizedMethodName}Infinite`;
137
+ const errorType = getErrorType(op, ctx);
138
+ const baseDataType = `Common.${op.capitalizedMethodName}DefaultResponse`;
139
+ const dataTypeName = ctx.modelNames.includes(`${op.capitalizedMethodName}Data`)
140
+ ? `${op.capitalizedMethodName}Data`
141
+ : "unknown";
142
+ const defaultValue = op.allParamsOptional ? " = {}" : "";
143
+ const clientOptionsParam = `clientOptions: Options<${dataTypeName}, true>${defaultValue}`;
144
+ // Build the queryFn with pageParam handling
145
+ const queryFn = `({ pageParam }) => ${op.methodName}({ ...clientOptions, query: { ...clientOptions.query, ${ctx.pageParam}: pageParam as number } }).then(response => response.data as TData) as TData`;
146
+ // Build getNextPageParam with nested type
147
+ const nestedType = buildNestedNextPageType(ctx.nextPageParam);
148
+ const getNextPageParam = `getNextPageParam: (response) => (response as ${nestedType}).${ctx.nextPageParam}`;
149
+ // initialPageParam is a string literal
150
+ const infiniteOptions = `initialPageParam: "${ctx.initialPageParam}", ${getNextPageParam}`;
151
+ const body = `useInfiniteQuery({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions, queryKey), queryFn: ${queryFn}, ${infiniteOptions}, ...options })`;
152
+ return {
153
+ kind: StructureKind.VariableStatement,
154
+ // Copy the operation's JSDoc (description and @deprecated) from the SDK function
155
+ leadingTrivia: op.jsDoc ? `${op.jsDoc}\n` : undefined,
156
+ isExported: true,
157
+ declarationKind: VariableDeclarationKind.Const,
158
+ declarations: [
159
+ {
160
+ name: hookName,
161
+ initializer: `<TData = InfiniteData<${baseDataType}>, TError = ${errorType}, TQueryKey extends Array<unknown> = unknown[]>(${clientOptionsParam}, queryKey?: TQueryKey, options?: Omit<UseInfiniteQueryOptions<TData, TError>, "queryKey" | "queryFn">) => ${body}`,
162
+ },
163
+ ],
164
+ };
165
+ }
166
+ /**
167
+ * Build prefetch function.
168
+ * Example:
169
+ * export const prefetchUseFindPets = (queryClient: QueryClient, clientOptions: Options<FindPetsData, true> = {}) =>
170
+ * queryClient.prefetchQuery({
171
+ * queryKey: Common.UseFindPetsKeyFn(clientOptions),
172
+ * queryFn: () => findPets({ ...clientOptions }).then(response => response.data)
173
+ * });
174
+ */
175
+ export function buildPrefetchFn(op, ctx) {
176
+ const fnName = `prefetchUse${op.capitalizedMethodName}`;
177
+ const dataTypeName = ctx.modelNames.includes(`${op.capitalizedMethodName}Data`)
178
+ ? `${op.capitalizedMethodName}Data`
179
+ : "unknown";
180
+ const hasParams = op.parameters.length > 0;
181
+ const defaultValue = op.allParamsOptional ? " = {}" : "";
182
+ const clientOptionsParam = hasParams
183
+ ? `clientOptions: Options<${dataTypeName}, true>${defaultValue}`
184
+ : `clientOptions: Options<${dataTypeName}, true> = {}`;
185
+ const callArgs = "{ ...clientOptions }";
186
+ const queryFn = `() => ${op.methodName}(${callArgs}).then(response => response.data)`;
187
+ const body = `queryClient.prefetchQuery({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions), queryFn: ${queryFn} })`;
188
+ return {
189
+ kind: StructureKind.VariableStatement,
190
+ // Copy the operation's JSDoc (description and @deprecated) from the SDK function
191
+ leadingTrivia: op.jsDoc ? `${op.jsDoc}\n` : undefined,
192
+ isExported: true,
193
+ declarationKind: VariableDeclarationKind.Const,
194
+ declarations: [
195
+ {
196
+ name: fnName,
197
+ initializer: `(queryClient: QueryClient, ${clientOptionsParam}) => ${body}`,
198
+ },
199
+ ],
200
+ };
201
+ }
202
+ /**
203
+ * Build ensureQueryData function.
204
+ * Example:
205
+ * export const ensureUseFindPetsData = (queryClient: QueryClient, clientOptions: Options<FindPetsData, true> = {}) =>
206
+ * queryClient.ensureQueryData({
207
+ * queryKey: Common.UseFindPetsKeyFn(clientOptions),
208
+ * queryFn: () => findPets({ ...clientOptions }).then(response => response.data)
209
+ * });
210
+ */
211
+ export function buildEnsureQueryDataFn(op, ctx) {
212
+ const fnName = `ensureUse${op.capitalizedMethodName}Data`;
213
+ const dataTypeName = ctx.modelNames.includes(`${op.capitalizedMethodName}Data`)
214
+ ? `${op.capitalizedMethodName}Data`
215
+ : "unknown";
216
+ const hasParams = op.parameters.length > 0;
217
+ const defaultValue = op.allParamsOptional ? " = {}" : "";
218
+ const clientOptionsParam = hasParams
219
+ ? `clientOptions: Options<${dataTypeName}, true>${defaultValue}`
220
+ : `clientOptions: Options<${dataTypeName}, true> = {}`;
221
+ const callArgs = "{ ...clientOptions }";
222
+ const queryFn = `() => ${op.methodName}(${callArgs}).then(response => response.data)`;
223
+ const body = `queryClient.ensureQueryData({ queryKey: Common.Use${op.capitalizedMethodName}KeyFn(clientOptions), queryFn: ${queryFn} })`;
224
+ return {
225
+ kind: StructureKind.VariableStatement,
226
+ // Copy the operation's JSDoc (description and @deprecated) from the SDK function
227
+ leadingTrivia: op.jsDoc ? `${op.jsDoc}\n` : undefined,
228
+ isExported: true,
229
+ declarationKind: VariableDeclarationKind.Const,
230
+ declarations: [
231
+ {
232
+ name: fnName,
233
+ initializer: `(queryClient: QueryClient, ${clientOptionsParam}) => ${body}`,
234
+ },
235
+ ],
236
+ };
237
+ }
@@ -0,0 +1,205 @@
1
+ import { StructureKind, } from "ts-morph";
2
+ import { OpenApiRqFiles } from "../constants.mjs";
3
+ import { buildDefaultResponseType, buildMutationKeyConst, buildMutationKeyFn, buildMutationResultType, buildQueryKeyConst, buildQueryKeyFn, buildQueryResultType, } from "./buildCommon.mjs";
4
+ import { buildUseMutationHook } from "./buildMutationHooks.mjs";
5
+ import { buildEnsureQueryDataFn, buildPrefetchFn, buildUseInfiniteQueryHook, buildUseQueryHook, buildUseSuspenseQueryHook, } from "./buildQueryHooks.mjs";
6
+ import { buildAxiosErrorImport, buildClientImport, buildCommonImport, buildModelImport, buildQueryImport, buildServiceImport, createGenerationProject, } from "./projectFactory.mjs";
7
+ /**
8
+ * Build imports for common.ts file.
9
+ */
10
+ function buildCommonFileImports(ctx) {
11
+ const imports = [
12
+ buildClientImport(ctx),
13
+ buildQueryImport(),
14
+ buildServiceImport(ctx),
15
+ ];
16
+ const modelImport = buildModelImport(ctx);
17
+ if (modelImport) {
18
+ imports.push(modelImport);
19
+ }
20
+ if (ctx.client === "@hey-api/client-axios") {
21
+ imports.push(buildAxiosErrorImport());
22
+ }
23
+ return imports;
24
+ }
25
+ /**
26
+ * Build imports for hook files (queries, suspense, infinite, prefetch, ensure).
27
+ */
28
+ function buildHookFileImports(ctx) {
29
+ return [buildCommonImport(), ...buildCommonFileImports(ctx)];
30
+ }
31
+ /**
32
+ * Generate the index.ts file content.
33
+ */
34
+ function generateIndexFile(ctx) {
35
+ const project = createGenerationProject();
36
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.index}.ts`, undefined, { overwrite: true });
37
+ const exports = [
38
+ {
39
+ kind: StructureKind.ExportDeclaration,
40
+ moduleSpecifier: "./common",
41
+ },
42
+ {
43
+ kind: StructureKind.ExportDeclaration,
44
+ moduleSpecifier: "./queries",
45
+ },
46
+ ];
47
+ sourceFile.addExportDeclarations(exports);
48
+ return sourceFile.getFullText();
49
+ }
50
+ /**
51
+ * Generate the common.ts file content.
52
+ */
53
+ function generateCommonFile(operations, ctx) {
54
+ const project = createGenerationProject();
55
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.common}.ts`, undefined, { overwrite: true });
56
+ // Add imports
57
+ sourceFile.addImportDeclarations(buildCommonFileImports(ctx));
58
+ // Group operations by HTTP method
59
+ const getOperations = operations.filter((op) => op.httpMethod === "GET");
60
+ const mutationOperations = operations.filter((op) => ["POST", "PUT", "PATCH", "DELETE"].includes(op.httpMethod));
61
+ // Add query types and keys
62
+ for (const op of getOperations) {
63
+ sourceFile.addTypeAlias(buildDefaultResponseType(op));
64
+ sourceFile.addTypeAlias(buildQueryResultType(op));
65
+ sourceFile.addVariableStatement(buildQueryKeyConst(op));
66
+ sourceFile.addVariableStatement(buildQueryKeyFn(op, ctx));
67
+ }
68
+ // Add mutation types and keys
69
+ for (const op of mutationOperations) {
70
+ sourceFile.addTypeAlias(buildMutationResultType(op));
71
+ sourceFile.addVariableStatement(buildMutationKeyConst(op));
72
+ sourceFile.addVariableStatement(buildMutationKeyFn(op));
73
+ }
74
+ return sourceFile.getFullText();
75
+ }
76
+ /**
77
+ * Generate the queries.ts file content.
78
+ */
79
+ function generateQueriesFile(operations, ctx) {
80
+ const project = createGenerationProject();
81
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.queries}.ts`, undefined, { overwrite: true });
82
+ // Add imports
83
+ sourceFile.addImportDeclarations(buildHookFileImports(ctx));
84
+ // Group operations
85
+ const getOperations = operations.filter((op) => op.httpMethod === "GET");
86
+ const mutationOperations = operations.filter((op) => ["POST", "PUT", "PATCH", "DELETE"].includes(op.httpMethod));
87
+ // Add useQuery hooks
88
+ for (const op of getOperations) {
89
+ sourceFile.addVariableStatement(buildUseQueryHook(op, ctx));
90
+ }
91
+ // Add useMutation hooks
92
+ for (const op of mutationOperations) {
93
+ sourceFile.addVariableStatement(buildUseMutationHook(op, ctx));
94
+ }
95
+ return sourceFile.getFullText();
96
+ }
97
+ /**
98
+ * Generate the suspense.ts file content.
99
+ */
100
+ function generateSuspenseFile(operations, ctx) {
101
+ const project = createGenerationProject();
102
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.suspense}.ts`, undefined, { overwrite: true });
103
+ // Add imports
104
+ sourceFile.addImportDeclarations(buildHookFileImports(ctx));
105
+ // Only GET operations for suspense
106
+ const getOperations = operations.filter((op) => op.httpMethod === "GET");
107
+ // Add useSuspenseQuery hooks
108
+ for (const op of getOperations) {
109
+ sourceFile.addVariableStatement(buildUseSuspenseQueryHook(op, ctx));
110
+ }
111
+ return sourceFile.getFullText();
112
+ }
113
+ /**
114
+ * Generate the infiniteQueries.ts file content.
115
+ */
116
+ function generateInfiniteQueriesFile(operations, ctx) {
117
+ const project = createGenerationProject();
118
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.infiniteQueries}.ts`, undefined, { overwrite: true });
119
+ // Add imports
120
+ sourceFile.addImportDeclarations(buildHookFileImports(ctx));
121
+ // Only paginatable GET operations
122
+ const paginatableOperations = operations.filter((op) => op.httpMethod === "GET" && op.isPaginatable);
123
+ // Add useInfiniteQuery hooks
124
+ for (const op of paginatableOperations) {
125
+ const hook = buildUseInfiniteQueryHook(op, ctx);
126
+ if (hook) {
127
+ sourceFile.addVariableStatement(hook);
128
+ }
129
+ }
130
+ return sourceFile.getFullText();
131
+ }
132
+ /**
133
+ * Generate the prefetch.ts file content.
134
+ */
135
+ function generatePrefetchFile(operations, ctx) {
136
+ const project = createGenerationProject();
137
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.prefetch}.ts`, undefined, { overwrite: true });
138
+ // Add imports
139
+ sourceFile.addImportDeclarations(buildHookFileImports(ctx));
140
+ // Only GET operations for prefetch
141
+ const getOperations = operations.filter((op) => op.httpMethod === "GET");
142
+ // Add prefetch functions
143
+ for (const op of getOperations) {
144
+ sourceFile.addVariableStatement(buildPrefetchFn(op, ctx));
145
+ }
146
+ return sourceFile.getFullText();
147
+ }
148
+ /**
149
+ * Generate the ensureQueryData.ts file content.
150
+ */
151
+ function generateEnsureQueryDataFile(operations, ctx) {
152
+ const project = createGenerationProject();
153
+ const sourceFile = project.createSourceFile(`${OpenApiRqFiles.ensureQueryData}.ts`, undefined, { overwrite: true });
154
+ // Add imports
155
+ sourceFile.addImportDeclarations(buildHookFileImports(ctx));
156
+ // Only GET operations for ensure
157
+ const getOperations = operations.filter((op) => op.httpMethod === "GET");
158
+ // Add ensureQueryData functions
159
+ for (const op of getOperations) {
160
+ sourceFile.addVariableStatement(buildEnsureQueryDataFn(op, ctx));
161
+ }
162
+ return sourceFile.getFullText();
163
+ }
164
+ /**
165
+ * Add the generated header comment to file content.
166
+ */
167
+ function addHeaderComment(content, version) {
168
+ const comment = `// generated with @7nohe/openapi-react-query-codegen@${version} \n\n`;
169
+ return comment + content;
170
+ }
171
+ /**
172
+ * Generate all files using ts-morph.
173
+ */
174
+ export function generateAllFiles(operations, ctx) {
175
+ return [
176
+ {
177
+ name: `${OpenApiRqFiles.index}.ts`,
178
+ content: addHeaderComment(generateIndexFile(ctx), ctx.version),
179
+ },
180
+ {
181
+ name: `${OpenApiRqFiles.common}.ts`,
182
+ content: addHeaderComment(generateCommonFile(operations, ctx), ctx.version),
183
+ },
184
+ {
185
+ name: `${OpenApiRqFiles.queries}.ts`,
186
+ content: addHeaderComment(generateQueriesFile(operations, ctx), ctx.version),
187
+ },
188
+ {
189
+ name: `${OpenApiRqFiles.suspense}.ts`,
190
+ content: addHeaderComment(generateSuspenseFile(operations, ctx), ctx.version),
191
+ },
192
+ {
193
+ name: `${OpenApiRqFiles.infiniteQueries}.ts`,
194
+ content: addHeaderComment(generateInfiniteQueriesFile(operations, ctx), ctx.version),
195
+ },
196
+ {
197
+ name: `${OpenApiRqFiles.prefetch}.ts`,
198
+ content: addHeaderComment(generatePrefetchFile(operations, ctx), ctx.version),
199
+ },
200
+ {
201
+ name: `${OpenApiRqFiles.ensureQueryData}.ts`,
202
+ content: addHeaderComment(generateEnsureQueryDataFile(operations, ctx), ctx.version),
203
+ },
204
+ ];
205
+ }
@@ -0,0 +1,5 @@
1
+ export { generateAllFiles } from "./generateFiles.mjs";
2
+ export { createGenerationProject } from "./projectFactory.mjs";
3
+ export * from "./buildCommon.mjs";
4
+ export * from "./buildQueryHooks.mjs";
5
+ export * from "./buildMutationHooks.mjs";
@@ -0,0 +1,121 @@
1
+ import { IndentationText, NewLineKind, Project, QuoteKind, StructureKind, } from "ts-morph";
2
+ /**
3
+ * Create a shared ts-morph Project for code generation.
4
+ * Uses consistent formatting settings to match existing output.
5
+ */
6
+ export function createGenerationProject() {
7
+ return new Project({
8
+ useInMemoryFileSystem: true,
9
+ compilerOptions: {
10
+ strict: true,
11
+ },
12
+ manipulationSettings: {
13
+ indentationText: IndentationText.TwoSpaces,
14
+ newLineKind: NewLineKind.LineFeed,
15
+ quoteKind: QuoteKind.Double,
16
+ useTrailingCommas: true,
17
+ },
18
+ });
19
+ }
20
+ /**
21
+ * Build import structure for the Options type.
22
+ * sdk.gen re-exports Options extended with `client` and `meta`, which the
23
+ * base client Options lacks; hooks must accept those properties.
24
+ */
25
+ export function buildClientImport(_ctx) {
26
+ return {
27
+ kind: StructureKind.ImportDeclaration,
28
+ moduleSpecifier: "../requests/sdk.gen",
29
+ namedImports: [{ name: "Options", isTypeOnly: true }],
30
+ };
31
+ }
32
+ /**
33
+ * Build import structure for TanStack Query.
34
+ */
35
+ export function buildQueryImport() {
36
+ return {
37
+ kind: StructureKind.ImportDeclaration,
38
+ moduleSpecifier: "@tanstack/react-query",
39
+ namedImports: [
40
+ { name: "QueryClient", isTypeOnly: true },
41
+ { name: "useQuery" },
42
+ { name: "useSuspenseQuery" },
43
+ { name: "useInfiniteQuery" },
44
+ { name: "useMutation" },
45
+ { name: "UseQueryResult" },
46
+ { name: "UseQueryOptions" },
47
+ { name: "UseInfiniteQueryOptions" },
48
+ { name: "UseMutationOptions" },
49
+ { name: "UseMutationResult" },
50
+ { name: "UseSuspenseQueryOptions" },
51
+ { name: "InfiniteData" },
52
+ ],
53
+ };
54
+ }
55
+ /**
56
+ * Build import structure for services.
57
+ */
58
+ export function buildServiceImport(ctx) {
59
+ return {
60
+ kind: StructureKind.ImportDeclaration,
61
+ moduleSpecifier: "../requests/sdk.gen",
62
+ namedImports: ctx.serviceNames.map((name) => ({ name })),
63
+ };
64
+ }
65
+ /**
66
+ * Build import structure for models.
67
+ */
68
+ export function buildModelImport(ctx) {
69
+ if (ctx.modelNames.length === 0) {
70
+ return null;
71
+ }
72
+ return {
73
+ kind: StructureKind.ImportDeclaration,
74
+ moduleSpecifier: "../requests/types.gen",
75
+ namedImports: ctx.modelNames.map((name) => ({ name })),
76
+ };
77
+ }
78
+ /**
79
+ * Build import structure for axios error type.
80
+ */
81
+ export function buildAxiosErrorImport() {
82
+ return {
83
+ kind: StructureKind.ImportDeclaration,
84
+ moduleSpecifier: "axios",
85
+ namedImports: [{ name: "AxiosError" }],
86
+ };
87
+ }
88
+ /**
89
+ * Build import for Common namespace.
90
+ */
91
+ export function buildCommonImport() {
92
+ return {
93
+ kind: StructureKind.ImportDeclaration,
94
+ moduleSpecifier: "./common",
95
+ namespaceImport: "Common",
96
+ };
97
+ }
98
+ /**
99
+ * Build all imports needed for the common file.
100
+ */
101
+ export function buildCommonFileImports(ctx) {
102
+ const imports = [
103
+ buildClientImport(ctx),
104
+ buildQueryImport(),
105
+ buildServiceImport(ctx),
106
+ ];
107
+ const modelImport = buildModelImport(ctx);
108
+ if (modelImport) {
109
+ imports.push(modelImport);
110
+ }
111
+ if (ctx.client === "@hey-api/client-axios") {
112
+ imports.push(buildAxiosErrorImport());
113
+ }
114
+ return imports;
115
+ }
116
+ /**
117
+ * Build all imports needed for hook files (queries, suspense, infinite).
118
+ */
119
+ export function buildHookFileImports(ctx) {
120
+ return [buildCommonImport(), ...buildCommonFileImports(ctx)];
121
+ }
package/dist/types.mjs ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7nohe/openapi-react-query-codegen",
3
- "version": "2.1.0",
3
+ "version": "3.0.0-beta.1",
4
4
  "description": "OpenAPI React Query Codegen",
5
5
  "bin": {
6
6
  "openapi-rq": "dist/cli.mjs"
@@ -39,7 +39,7 @@
39
39
  "license": "MIT",
40
40
  "author": "Daiki Urata (@7nohe)",
41
41
  "dependencies": {
42
- "@hey-api/openapi-ts": "0.92.3",
42
+ "@hey-api/openapi-ts": "0.99.0",
43
43
  "cross-spawn": "^7.0.3"
44
44
  },
45
45
  "devDependencies": {
@@ -51,17 +51,17 @@
51
51
  "commander": "^12.0.0",
52
52
  "lefthook": "^1.6.10",
53
53
  "rimraf": "^5.0.5",
54
- "ts-morph": "^27.0.2",
55
- "typescript": "^5.9.3",
54
+ "ts-morph": "^28.0.0",
55
+ "typescript": "^6.0.3",
56
56
  "vitest": "^1.5.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "commander": "12.x",
60
- "ts-morph": "27.x",
61
- "typescript": "5.x"
60
+ "ts-morph": "28.x",
61
+ "typescript": "5.x || 6.x"
62
62
  },
63
63
  "engines": {
64
- "node": ">=20.19.0",
64
+ "node": ">=22.18.0",
65
65
  "pnpm": ">=9"
66
66
  },
67
67
  "scripts": {