@7nohe/openapi-react-query-codegen 2.0.0-beta.3 → 2.1.0
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/common.mjs +10 -15
- package/dist/constants.mjs +1 -1
- package/dist/createExports.mjs +11 -9
- package/dist/createImports.mjs +7 -6
- package/dist/createUseMutation.mjs +11 -5
- package/dist/createUseQuery.mjs +33 -10
- package/dist/generate.mjs +38 -23
- package/dist/service.mjs +45 -26
- package/package.json +7 -7
package/dist/common.mjs
CHANGED
|
@@ -160,9 +160,11 @@ export function createQueryKeyExport({ methodName, queryKey, }) {
|
|
|
160
160
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier(queryKey), undefined, undefined, ts.factory.createStringLiteral(`${capitalizeFirstLetter(methodName)}`)),
|
|
161
161
|
], ts.NodeFlags.Const));
|
|
162
162
|
}
|
|
163
|
-
export function createQueryKeyFnExport(queryKey, method, type = "query") {
|
|
163
|
+
export function createQueryKeyFnExport(queryKey, method, type = "query", modelNames = []) {
|
|
164
164
|
// Mutation keys don't require clientOptions
|
|
165
|
-
const params = type === "query"
|
|
165
|
+
const params = type === "query"
|
|
166
|
+
? getRequestParamFromMethod(method, undefined, modelNames)
|
|
167
|
+
: null;
|
|
166
168
|
// override key is used to allow the user to override the the queryKey values
|
|
167
169
|
const overrideKey = ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier(type === "query" ? "queryKey" : "mutationKey"), QuestionToken, ts.factory.createTypeReferenceNode("Array<unknown>", []));
|
|
168
170
|
return ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
@@ -190,22 +192,15 @@ function mutationKeyFn(mutationKey) {
|
|
|
190
192
|
], false);
|
|
191
193
|
}
|
|
192
194
|
export function getRequestParamFromMethod(method, pageParam, modelNames = []) {
|
|
193
|
-
|
|
195
|
+
const sdkParams = getVariableArrowFunctionParameters(method);
|
|
196
|
+
if (!sdkParams.length) {
|
|
194
197
|
return null;
|
|
195
198
|
}
|
|
196
199
|
const methodName = getNameFromVariable(method);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
.map((refParam) => ({
|
|
202
|
-
name: refParam.name,
|
|
203
|
-
// TODO: Client<Request, Response, unknown, RequestOptions> -> Client<Request, Response, unknown>
|
|
204
|
-
typeName: getShortType(refParam.type?.getText() ?? ""),
|
|
205
|
-
optional: refParam.optional,
|
|
206
|
-
}));
|
|
207
|
-
});
|
|
208
|
-
const areAllPropertiesOptional = params.every((param) => param.optional);
|
|
200
|
+
// Use the SDK function's parameter optionality as the authoritative check.
|
|
201
|
+
// Generic types like Options<XData, ThrowOnError> may not resolve correctly
|
|
202
|
+
// via extractPropertiesFromObjectParam for type alias properties (path, url).
|
|
203
|
+
const areAllPropertiesOptional = sdkParams[0].isOptional();
|
|
209
204
|
return ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("clientOptions"), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Options"), [
|
|
210
205
|
ts.factory.createTypeReferenceNode(modelNames.includes(`${capitalizeFirstLetter(methodName)}Data`)
|
|
211
206
|
? `${capitalizeFirstLetter(methodName)}Data`
|
package/dist/constants.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const defaultOutputPath = "openapi";
|
|
2
2
|
export const queriesOutputPath = "queries";
|
|
3
3
|
export const requestsOutputPath = "requests";
|
|
4
|
-
export const serviceFileName = "
|
|
4
|
+
export const serviceFileName = "sdk.gen";
|
|
5
5
|
export const modelsFileName = "types.gen";
|
|
6
6
|
export const OpenApiRqFiles = {
|
|
7
7
|
queries: "queries",
|
package/dist/createExports.mjs
CHANGED
|
@@ -24,14 +24,16 @@ export const createExports = ({ service, client, project, pageParam, nextPagePar
|
|
|
24
24
|
if (ts.isTypeAliasDeclaration(node) && methodDataNames[key] !== undefined) {
|
|
25
25
|
// get the type alias declaration
|
|
26
26
|
const typeAliasDeclaration = node.type;
|
|
27
|
-
if (
|
|
28
|
-
const query = typeAliasDeclaration.members.find((m) => m.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
if (ts.isTypeLiteralNode(typeAliasDeclaration)) {
|
|
28
|
+
const query = typeAliasDeclaration.members.find((m) => ts.isPropertySignature(m) && m.name?.getText() === "query");
|
|
29
|
+
if (query) {
|
|
30
|
+
const queryType = query.type;
|
|
31
|
+
const members = queryType && ts.isTypeLiteralNode(queryType)
|
|
32
|
+
? queryType.members
|
|
33
|
+
: undefined;
|
|
34
|
+
if (members?.map((m) => m.name?.getText()).includes(pageParam)) {
|
|
35
|
+
paginatableMethods.push(methodDataNames[key]);
|
|
36
|
+
}
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -82,7 +84,7 @@ export const createExports = ({ service, client, project, pageParam, nextPagePar
|
|
|
82
84
|
const mainExports = [...mainQueries, ...mainMutations];
|
|
83
85
|
const infiniteQueriesExports = allQueries
|
|
84
86
|
.flatMap(({ infiniteQueryHook }) => [infiniteQueryHook])
|
|
85
|
-
.filter(
|
|
87
|
+
.filter((x) => x != null);
|
|
86
88
|
const suspenseQueries = allQueries.flatMap(({ suspenseQueryHook }) => [
|
|
87
89
|
suspenseQueryHook,
|
|
88
90
|
]);
|
package/dist/createImports.mjs
CHANGED
|
@@ -16,13 +16,13 @@ export const createImports = ({ project, client, }) => {
|
|
|
16
16
|
? Array.from(modelsFile.getExportedDeclarations().keys())
|
|
17
17
|
: [];
|
|
18
18
|
const serviceExports = Array.from(serviceFile.getExportedDeclarations().keys());
|
|
19
|
-
|
|
19
|
+
// Filter out type-only exports (e.g. Options) to avoid duplicate imports,
|
|
20
|
+
// since Options is already imported separately from the client module.
|
|
21
|
+
const serviceNames = serviceExports.filter((name) => name !== "Options");
|
|
20
22
|
const imports = [
|
|
21
|
-
ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(
|
|
22
|
-
ts.factory.createImportSpecifier(
|
|
23
|
-
])), ts.factory.createStringLiteral(
|
|
24
|
-
? "@hey-api/client-axios"
|
|
25
|
-
: "@hey-api/client-fetch"), undefined),
|
|
23
|
+
ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(true, undefined, ts.factory.createNamedImports([
|
|
24
|
+
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("Options")),
|
|
25
|
+
])), ts.factory.createStringLiteral(join("../requests", serviceFileName)), undefined),
|
|
26
26
|
ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
|
|
27
27
|
ts.factory.createImportSpecifier(true, undefined, ts.factory.createIdentifier("QueryClient")),
|
|
28
28
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useQuery")),
|
|
@@ -32,6 +32,7 @@ export const createImports = ({ project, client, }) => {
|
|
|
32
32
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("UseQueryOptions")),
|
|
33
33
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("UseMutationOptions")),
|
|
34
34
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("UseMutationResult")),
|
|
35
|
+
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("UseSuspenseQueryOptions")),
|
|
35
36
|
])), ts.factory.createStringLiteral("@tanstack/react-query"), undefined),
|
|
36
37
|
ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
|
|
37
38
|
// import all class names from service file
|
|
@@ -23,11 +23,17 @@ export const createUseMutation = ({ functionDescription: { method, jsDoc }, mode
|
|
|
23
23
|
const responseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData, undefined, ts.factory.createTypeReferenceNode(BuildCommonTypeName(mutationResult.name)));
|
|
24
24
|
// @hey-api/client-axios -> `TError = AxiosError<AddPetError>`
|
|
25
25
|
// @hey-api/client-fetch -> `TError = AddPetError`
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
const errorTypeName = `${capitalizeFirstLetter(methodName)}Error`;
|
|
27
|
+
const hasErrorType = modelNames.includes(errorTypeName);
|
|
28
|
+
const responseErrorType = ts.factory.createTypeParameterDeclaration(undefined, TError, undefined, hasErrorType
|
|
29
|
+
? client === "@hey-api/client-axios"
|
|
30
|
+
? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("AxiosError"), [
|
|
31
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(errorTypeName)),
|
|
32
|
+
])
|
|
33
|
+
: ts.factory.createTypeReferenceNode(errorTypeName)
|
|
34
|
+
: client === "@hey-api/client-axios"
|
|
35
|
+
? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("AxiosError"), [ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)])
|
|
36
|
+
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
|
|
31
37
|
const methodParameters = getVariableArrowFunctionParameters(method).length !== 0
|
|
32
38
|
? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Options"), [
|
|
33
39
|
ts.factory.createTypeReferenceNode(modelNames.includes(`${capitalizeFirstLetter(methodName)}Data`)
|
package/dist/createUseQuery.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { BuildCommonTypeName, EqualsOrGreaterThanToken, TData, TError, capitalizeFirstLetter, createQueryKeyExport, createQueryKeyFnExport, getNameFromVariable, getQueryKeyFnName, getRequestParamFromMethod, getVariableArrowFunctionParameters, queryKeyConstraint, queryKeyGenericType, } from "./common.mjs";
|
|
3
3
|
import { addJSDocToNode } from "./util.mjs";
|
|
4
|
-
const createApiResponseType = ({ methodName, client, }) => {
|
|
4
|
+
const createApiResponseType = ({ methodName, client, modelNames, }) => {
|
|
5
5
|
/** Awaited<ReturnType<typeof myClass.myMethod>> */
|
|
6
6
|
const awaitedResponseDataType = ts.factory.createIndexedAccessTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Awaited"), [
|
|
7
7
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("ReturnType"), [
|
|
@@ -13,11 +13,21 @@ const createApiResponseType = ({ methodName, client, }) => {
|
|
|
13
13
|
*/
|
|
14
14
|
const apiResponse = ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(`${capitalizeFirstLetter(methodName)}DefaultResponse`), undefined, awaitedResponseDataType);
|
|
15
15
|
const responseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData.text, undefined, ts.factory.createTypeReferenceNode(BuildCommonTypeName(apiResponse.name)));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
// Response data type for suspense - wrap with NonNullable to exclude undefined
|
|
17
|
+
const suspenseResponseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData.text, undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("NonNullable"), [
|
|
18
|
+
ts.factory.createTypeReferenceNode(BuildCommonTypeName(apiResponse.name)),
|
|
19
|
+
]));
|
|
20
|
+
const errorTypeName = `${capitalizeFirstLetter(methodName)}Error`;
|
|
21
|
+
const hasErrorType = modelNames.includes(errorTypeName);
|
|
22
|
+
const responseErrorType = ts.factory.createTypeParameterDeclaration(undefined, TError.text, undefined, hasErrorType
|
|
23
|
+
? client === "@hey-api/client-axios"
|
|
24
|
+
? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("AxiosError"), [
|
|
25
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(errorTypeName)),
|
|
26
|
+
])
|
|
27
|
+
: ts.factory.createTypeReferenceNode(errorTypeName)
|
|
28
|
+
: client === "@hey-api/client-axios"
|
|
29
|
+
? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("AxiosError"), [ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)])
|
|
30
|
+
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
|
|
21
31
|
return {
|
|
22
32
|
/**
|
|
23
33
|
* DefaultResponseDataType
|
|
@@ -31,6 +41,12 @@ const createApiResponseType = ({ methodName, client, }) => {
|
|
|
31
41
|
* MyClassMethodDefaultResponse
|
|
32
42
|
*/
|
|
33
43
|
responseDataType,
|
|
44
|
+
/**
|
|
45
|
+
* ResponseDataType for suspense - wrap with NonNullable to exclude undefined
|
|
46
|
+
*
|
|
47
|
+
* NonNullable<MyClassMethodDefaultResponse>
|
|
48
|
+
*/
|
|
49
|
+
suspenseResponseDataType,
|
|
34
50
|
/**
|
|
35
51
|
* ErrorDataType
|
|
36
52
|
*
|
|
@@ -76,6 +92,10 @@ function createQueryHook({ queryString, suffix, responseDataType, responseErrorT
|
|
|
76
92
|
throw new Error("pageParam and nextPageParam are required for infinite queries");
|
|
77
93
|
}
|
|
78
94
|
const isInfiniteQuery = queryString === "useInfiniteQuery";
|
|
95
|
+
const isSuspenseQuery = queryString === "useSuspenseQuery";
|
|
96
|
+
// ts.TypeParameterDeclaration.default is ts.TypeNode | undefined.
|
|
97
|
+
// We know it's a TypeReferenceNode with an Identifier typeName because we created it
|
|
98
|
+
// via ts.factory in createApiResponseType, but TypeScript cannot infer the specific subtype.
|
|
79
99
|
const responseDataTypeRef = responseDataType.default;
|
|
80
100
|
const responseDataTypeIdentifier = responseDataTypeRef.typeName;
|
|
81
101
|
const hookExport = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
@@ -93,7 +113,9 @@ function createQueryHook({ queryString, suffix, responseDataType, responseErrorT
|
|
|
93
113
|
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("options"), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [
|
|
94
114
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(isInfiniteQuery
|
|
95
115
|
? "UseInfiniteQueryOptions"
|
|
96
|
-
:
|
|
116
|
+
: isSuspenseQuery
|
|
117
|
+
? "UseSuspenseQueryOptions"
|
|
118
|
+
: "UseQueryOptions"), [
|
|
97
119
|
ts.factory.createTypeReferenceNode(TData),
|
|
98
120
|
ts.factory.createTypeReferenceNode(TError),
|
|
99
121
|
]),
|
|
@@ -153,9 +175,10 @@ function createQueryHook({ queryString, suffix, responseDataType, responseErrorT
|
|
|
153
175
|
export const createUseQuery = ({ functionDescription: { method, jsDoc }, client, pageParam, nextPageParam, initialPageParam, paginatableMethods, modelNames, }) => {
|
|
154
176
|
const methodName = getNameFromVariable(method);
|
|
155
177
|
const queryKey = createQueryKeyFromMethod({ method });
|
|
156
|
-
const { apiResponse: defaultApiResponse, responseDataType, responseErrorType, } = createApiResponseType({
|
|
178
|
+
const { apiResponse: defaultApiResponse, responseDataType, suspenseResponseDataType, responseErrorType, } = createApiResponseType({
|
|
157
179
|
methodName,
|
|
158
180
|
client,
|
|
181
|
+
modelNames,
|
|
159
182
|
});
|
|
160
183
|
const requestParam = getRequestParamFromMethod(method, undefined, modelNames);
|
|
161
184
|
const infiniteRequestParam = getRequestParamFromMethod(method, pageParam, modelNames);
|
|
@@ -171,7 +194,7 @@ export const createUseQuery = ({ functionDescription: { method, jsDoc }, client,
|
|
|
171
194
|
const suspenseQueryHook = createQueryHook({
|
|
172
195
|
queryString: "useSuspenseQuery",
|
|
173
196
|
suffix: "Suspense",
|
|
174
|
-
responseDataType,
|
|
197
|
+
responseDataType: suspenseResponseDataType,
|
|
175
198
|
responseErrorType,
|
|
176
199
|
requestParams,
|
|
177
200
|
method,
|
|
@@ -203,7 +226,7 @@ export const createUseQuery = ({ functionDescription: { method, jsDoc }, client,
|
|
|
203
226
|
methodName,
|
|
204
227
|
queryKey,
|
|
205
228
|
});
|
|
206
|
-
const queryKeyFn = createQueryKeyFnExport(queryKey, method);
|
|
229
|
+
const queryKeyFn = createQueryKeyFnExport(queryKey, method, "query", modelNames);
|
|
207
230
|
return {
|
|
208
231
|
apiResponse: defaultApiResponse,
|
|
209
232
|
returnType: returnTypeExport,
|
package/dist/generate.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import { createClient } from "@hey-api/openapi-ts";
|
|
2
4
|
import { buildQueriesOutputPath, buildRequestsOutputPath, formatOptions, } from "./common.mjs";
|
|
3
5
|
import { createSource } from "./createSource.mjs";
|
|
@@ -6,34 +8,47 @@ import { print } from "./print.mjs";
|
|
|
6
8
|
export async function generate(options, version) {
|
|
7
9
|
const openApiOutputPath = buildRequestsOutputPath(options.output);
|
|
8
10
|
const formattedOptions = formatOptions(options);
|
|
11
|
+
// Map CLI options to new plugins system
|
|
12
|
+
const clientPlugin = formattedOptions.client === "@hey-api/client-axios"
|
|
13
|
+
? "@hey-api/client-axios"
|
|
14
|
+
: "@hey-api/client-fetch";
|
|
15
|
+
const typescriptPlugin = formattedOptions.enums
|
|
16
|
+
? {
|
|
17
|
+
name: "@hey-api/typescript",
|
|
18
|
+
enums: formattedOptions.enums,
|
|
19
|
+
}
|
|
20
|
+
: "@hey-api/typescript";
|
|
21
|
+
const sdkPlugin = formattedOptions.noOperationId
|
|
22
|
+
? {
|
|
23
|
+
name: "@hey-api/sdk",
|
|
24
|
+
operationId: false,
|
|
25
|
+
}
|
|
26
|
+
: "@hey-api/sdk";
|
|
27
|
+
const plugins = [
|
|
28
|
+
clientPlugin,
|
|
29
|
+
typescriptPlugin,
|
|
30
|
+
sdkPlugin,
|
|
31
|
+
];
|
|
32
|
+
// Conditionally add schemas plugin
|
|
33
|
+
if (!formattedOptions.noSchemas) {
|
|
34
|
+
plugins.push(formattedOptions.schemaType
|
|
35
|
+
? {
|
|
36
|
+
name: "@hey-api/schemas",
|
|
37
|
+
type: formattedOptions.schemaType,
|
|
38
|
+
}
|
|
39
|
+
: "@hey-api/schemas");
|
|
40
|
+
}
|
|
9
41
|
const config = {
|
|
10
|
-
client: formattedOptions.client,
|
|
11
|
-
debug: formattedOptions.debug,
|
|
12
42
|
dryRun: false,
|
|
13
|
-
exportCore: true,
|
|
14
|
-
output: {
|
|
15
|
-
format: formattedOptions.format,
|
|
16
|
-
lint: formattedOptions.lint,
|
|
17
|
-
path: openApiOutputPath,
|
|
18
|
-
},
|
|
19
43
|
input: formattedOptions.input,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type: formattedOptions.schemaType,
|
|
23
|
-
},
|
|
24
|
-
services: {
|
|
25
|
-
export: true,
|
|
26
|
-
asClass: false,
|
|
27
|
-
operationId: !formattedOptions.noOperationId,
|
|
28
|
-
},
|
|
29
|
-
types: {
|
|
30
|
-
dates: formattedOptions.useDateType,
|
|
31
|
-
export: true,
|
|
32
|
-
enums: formattedOptions.enums,
|
|
33
|
-
},
|
|
34
|
-
useOptions: true,
|
|
44
|
+
output: openApiOutputPath,
|
|
45
|
+
plugins,
|
|
35
46
|
};
|
|
36
47
|
await createClient(config);
|
|
48
|
+
// Generate backward-compatible services.gen.ts shim
|
|
49
|
+
// client.gen.ts has the `client` instance; sdk.gen.ts has SDK functions
|
|
50
|
+
const shimContent = `// This file is auto-generated for backward compatibility\nexport * from './client.gen.js';\nexport * from './sdk.gen.js';\n`;
|
|
51
|
+
await writeFile(path.join(openApiOutputPath, "services.gen.ts"), shimContent);
|
|
37
52
|
const source = await createSource({
|
|
38
53
|
outputPath: openApiOutputPath,
|
|
39
54
|
client: formattedOptions.client,
|
package/dist/service.mjs
CHANGED
|
@@ -15,36 +15,55 @@ export async function getServices(project) {
|
|
|
15
15
|
}
|
|
16
16
|
export function getMethodsFromService(node) {
|
|
17
17
|
const variableStatements = node.getVariableStatements();
|
|
18
|
-
//
|
|
19
|
-
|
|
18
|
+
// Filter to only exported variable statements that contain arrow functions
|
|
19
|
+
const exportedStatements = variableStatements.filter((statement) => {
|
|
20
|
+
if (!statement.isExported())
|
|
21
|
+
return false;
|
|
22
|
+
const declarations = statement.getDeclarations();
|
|
23
|
+
return declarations.some((decl) => {
|
|
24
|
+
const initializer = decl.getInitializer();
|
|
25
|
+
return initializer && ts.isArrowFunction(initializer.compilerNode);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
return exportedStatements.flatMap((variableStatement) => {
|
|
20
29
|
const declarations = variableStatement.getDeclarations();
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
throw new Error("Variable declaration not found");
|
|
24
|
-
}
|
|
30
|
+
// Filter to only arrow function declarations within the statement
|
|
31
|
+
const arrowDeclarations = declarations.filter((declaration) => {
|
|
25
32
|
const initializer = declaration.getInitializer();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
return initializer && ts.isArrowFunction(initializer.compilerNode);
|
|
34
|
+
});
|
|
35
|
+
return arrowDeclarations.map((declaration) => {
|
|
36
|
+
const initializer = declaration.getInitializerOrThrow();
|
|
37
|
+
const compilerNode = initializer.compilerNode;
|
|
38
|
+
const arrowBody = compilerNode.body;
|
|
39
|
+
// Find the call expression - either from block's return statement or direct expression
|
|
40
|
+
let callExpression;
|
|
41
|
+
let methodBlockNode;
|
|
42
|
+
if (ts.isBlock(arrowBody)) {
|
|
43
|
+
// Old style: arrow function with block body
|
|
44
|
+
methodBlockNode = arrowBody;
|
|
45
|
+
const returnStatement = arrowBody.statements.find(ts.isReturnStatement);
|
|
46
|
+
if (!returnStatement) {
|
|
47
|
+
throw new Error("Return statement not found");
|
|
48
|
+
}
|
|
49
|
+
if (!returnStatement.expression) {
|
|
50
|
+
throw new Error("Call expression not found");
|
|
51
|
+
}
|
|
52
|
+
callExpression = returnStatement.expression;
|
|
35
53
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
else {
|
|
55
|
+
// New style: arrow function with expression body (no block)
|
|
56
|
+
// The body is a call expression like: (options?.client ?? client).post<...>({...})
|
|
57
|
+
callExpression = arrowBody;
|
|
39
58
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
59
|
+
// Navigate to find the HTTP method name (get, post, put, delete, etc.)
|
|
60
|
+
let httpMethodName;
|
|
61
|
+
if (ts.isCallExpression(callExpression)) {
|
|
62
|
+
const expr = callExpression.expression;
|
|
63
|
+
if (ts.isPropertyAccessExpression(expr)) {
|
|
64
|
+
httpMethodName = expr.name.text;
|
|
65
|
+
}
|
|
44
66
|
}
|
|
45
|
-
const callExpression = foundCallExpression;
|
|
46
|
-
const propertyAccessExpression = callExpression.expression;
|
|
47
|
-
const httpMethodName = propertyAccessExpression.name.getText();
|
|
48
67
|
if (!httpMethodName) {
|
|
49
68
|
throw new Error("httpMethodName not found");
|
|
50
69
|
}
|
|
@@ -56,7 +75,7 @@ export function getMethodsFromService(node) {
|
|
|
56
75
|
}
|
|
57
76
|
return [tsNode];
|
|
58
77
|
};
|
|
59
|
-
const children = getAllChildren(
|
|
78
|
+
const children = getAllChildren(variableStatement.compilerNode);
|
|
60
79
|
// get all JSDoc comments
|
|
61
80
|
// this should be an array of 1 or 0
|
|
62
81
|
const jsDocs = children
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7nohe/openapi-react-query-codegen",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "OpenAPI React Query Codegen",
|
|
5
5
|
"bin": {
|
|
6
6
|
"openapi-rq": "dist/cli.mjs"
|
|
@@ -39,29 +39,29 @@
|
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"author": "Daiki Urata (@7nohe)",
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@hey-api/
|
|
43
|
-
"@hey-api/openapi-ts": "0.53.8",
|
|
42
|
+
"@hey-api/openapi-ts": "0.92.3",
|
|
44
43
|
"cross-spawn": "^7.0.3"
|
|
45
44
|
},
|
|
46
45
|
"devDependencies": {
|
|
47
46
|
"@biomejs/biome": "^1.9.3",
|
|
48
47
|
"@types/cross-spawn": "^6.0.6",
|
|
49
48
|
"@types/node": "^22.7.4",
|
|
49
|
+
"@types/semver": "^7.7.1",
|
|
50
50
|
"@vitest/coverage-v8": "^1.5.0",
|
|
51
51
|
"commander": "^12.0.0",
|
|
52
52
|
"lefthook": "^1.6.10",
|
|
53
53
|
"rimraf": "^5.0.5",
|
|
54
|
-
"ts-morph": "^
|
|
55
|
-
"typescript": "^5.
|
|
54
|
+
"ts-morph": "^27.0.2",
|
|
55
|
+
"typescript": "^5.9.3",
|
|
56
56
|
"vitest": "^1.5.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"commander": "12.x",
|
|
60
|
-
"ts-morph": "
|
|
60
|
+
"ts-morph": "27.x",
|
|
61
61
|
"typescript": "5.x"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
|
-
"node": ">=
|
|
64
|
+
"node": ">=20.19.0",
|
|
65
65
|
"pnpm": ">=9"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|