@7nohe/openapi-react-query-codegen 2.2.0 → 3.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,256 +0,0 @@
1
- import ts from "typescript";
2
- import { BuildCommonTypeName, EqualsOrGreaterThanToken, TData, TError, capitalizeFirstLetter, createQueryKeyExport, createQueryKeyFnExport, getNameFromVariable, getQueryKeyFnName, getRequestParamFromMethod, getVariableArrowFunctionParameters, queryKeyConstraint, queryKeyGenericType, } from "./common.mjs";
3
- import { addJSDocToNode } from "./util.mjs";
4
- const createApiResponseType = ({ methodName, client, modelNames, }) => {
5
- /** Awaited<ReturnType<typeof myClass.myMethod>> */
6
- const awaitedResponseDataType = ts.factory.createIndexedAccessTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Awaited"), [
7
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("ReturnType"), [
8
- ts.factory.createTypeQueryNode(ts.factory.createIdentifier(methodName), undefined),
9
- ]),
10
- ]), ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("data")));
11
- /** DefaultResponseDataType
12
- * export type MyClassMethodDefaultResponse = Awaited<ReturnType<typeof myClass.myMethod>>
13
- */
14
- const apiResponse = ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(`${capitalizeFirstLetter(methodName)}DefaultResponse`), undefined, awaitedResponseDataType);
15
- const responseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData.text, undefined, ts.factory.createTypeReferenceNode(BuildCommonTypeName(apiResponse.name)));
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));
31
- return {
32
- /**
33
- * DefaultResponseDataType
34
- *
35
- * export type MyClassMethodDefaultResponse = Awaited<ReturnType<typeof myClass.myMethod>>
36
- */
37
- apiResponse,
38
- /**
39
- * This will be the name of the type of the response type of the method
40
- *
41
- * MyClassMethodDefaultResponse
42
- */
43
- responseDataType,
44
- /**
45
- * ResponseDataType for suspense - wrap with NonNullable to exclude undefined
46
- *
47
- * NonNullable<MyClassMethodDefaultResponse>
48
- */
49
- suspenseResponseDataType,
50
- /**
51
- * ErrorDataType
52
- *
53
- * MyClassMethodError
54
- */
55
- responseErrorType,
56
- };
57
- };
58
- /**
59
- * Return Type
60
- *
61
- * export const classNameMethodNameQueryResult<TData = MyClassMethodDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
62
- */
63
- function createReturnTypeExport({ methodName, defaultApiResponse, }) {
64
- return ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(`${capitalizeFirstLetter(methodName)}QueryResult`), [
65
- ts.factory.createTypeParameterDeclaration(undefined, TData, undefined, ts.factory.createTypeReferenceNode(defaultApiResponse.name)),
66
- ts.factory.createTypeParameterDeclaration(undefined, TError, undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)),
67
- ], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("UseQueryResult"), [
68
- ts.factory.createTypeReferenceNode(TData),
69
- ts.factory.createTypeReferenceNode(TError),
70
- ]));
71
- }
72
- export function hookNameFromMethod({ method, }) {
73
- const methodName = getNameFromVariable(method);
74
- return `use${capitalizeFirstLetter(methodName)}`;
75
- }
76
- export function createQueryKeyFromMethod({ method, }) {
77
- const customHookName = hookNameFromMethod({ method });
78
- const queryKey = `${customHookName}Key`;
79
- return queryKey;
80
- }
81
- /**
82
- * Creates a custom hook for a query
83
- * @param queryString The type of query to use from react-query
84
- * @param suffix The suffix to append to the hook name
85
- */
86
- function createQueryHook({ queryString, suffix, responseDataType, responseErrorType, requestParams, method, pageParam, nextPageParam, initialPageParam, }) {
87
- const methodName = getNameFromVariable(method);
88
- const customHookName = hookNameFromMethod({ method });
89
- const queryKey = createQueryKeyFromMethod({ method });
90
- if (queryString === "useInfiniteQuery" &&
91
- (pageParam === undefined || nextPageParam === undefined)) {
92
- throw new Error("pageParam and nextPageParam are required for infinite queries");
93
- }
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.
99
- const responseDataTypeRef = responseDataType.default;
100
- const responseDataTypeIdentifier = responseDataTypeRef.typeName;
101
- const hookExport = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
102
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier(`${customHookName}${suffix}`), undefined, undefined, ts.factory.createArrowFunction(undefined, ts.factory.createNodeArray([
103
- isInfiniteQuery
104
- ? ts.factory.createTypeParameterDeclaration(undefined, TData, undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("InfiniteData"), [
105
- ts.factory.createTypeReferenceNode(responseDataTypeIdentifier),
106
- ]))
107
- : responseDataType,
108
- responseErrorType,
109
- ts.factory.createTypeParameterDeclaration(undefined, "TQueryKey", queryKeyConstraint, ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword))),
110
- ]), [
111
- ...requestParams,
112
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("queryKey"), ts.factory.createToken(ts.SyntaxKind.QuestionToken), queryKeyGenericType),
113
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("options"), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [
114
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(isInfiniteQuery
115
- ? "UseInfiniteQueryOptions"
116
- : isSuspenseQuery
117
- ? "UseSuspenseQueryOptions"
118
- : "UseQueryOptions"), [
119
- ts.factory.createTypeReferenceNode(TData),
120
- ts.factory.createTypeReferenceNode(TError),
121
- ]),
122
- ts.factory.createUnionTypeNode([
123
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("queryKey")),
124
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("queryFn")),
125
- ]),
126
- ])),
127
- ], undefined, EqualsOrGreaterThanToken, ts.factory.createCallExpression(ts.factory.createIdentifier(queryString), isInfiniteQuery
128
- ? []
129
- : [
130
- ts.factory.createTypeReferenceNode(TData),
131
- ts.factory.createTypeReferenceNode(TError),
132
- ], [
133
- ts.factory.createObjectLiteralExpression([
134
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryKey"), ts.factory.createCallExpression(BuildCommonTypeName(getQueryKeyFnName(queryKey)), undefined, [
135
- ts.factory.createIdentifier("clientOptions"),
136
- ts.factory.createIdentifier("queryKey"),
137
- ])),
138
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryFn"), ts.factory.createArrowFunction(undefined, undefined, isInfiniteQuery
139
- ? [
140
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern([
141
- ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier("pageParam"), undefined),
142
- ]), undefined, undefined),
143
- ]
144
- : [], undefined, EqualsOrGreaterThanToken, ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createIdentifier(methodName), undefined, pageParam && isInfiniteQuery
145
- ? [
146
- // { ...clientOptions, query: { ...clientOptions.query, page: pageParam as number } }
147
- ts.factory.createObjectLiteralExpression([
148
- ts.factory.createSpreadAssignment(ts.factory.createIdentifier("clientOptions")),
149
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier("query"), ts.factory.createObjectLiteralExpression([
150
- ts.factory.createSpreadAssignment(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("clientOptions"), ts.factory.createIdentifier("query"))),
151
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier(pageParam), ts.factory.createAsExpression(ts.factory.createIdentifier("pageParam"), ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword))),
152
- ])),
153
- ]),
154
- ]
155
- : // { ...clientOptions }
156
- getVariableArrowFunctionParameters(method)
157
- .length > 0
158
- ? [
159
- ts.factory.createObjectLiteralExpression([
160
- ts.factory.createSpreadAssignment(ts.factory.createIdentifier("clientOptions")),
161
- ]),
162
- ]
163
- : undefined), ts.factory.createIdentifier("then")), undefined, [
164
- ts.factory.createArrowFunction(undefined, undefined, [
165
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("response"), undefined, undefined, undefined),
166
- ], undefined, EqualsOrGreaterThanToken, ts.factory.createAsExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("response"), ts.factory.createIdentifier("data")), ts.factory.createTypeReferenceNode(TData))),
167
- ]), ts.factory.createTypeReferenceNode(TData)))),
168
- ...createInfiniteQueryParams(pageParam, nextPageParam, initialPageParam),
169
- ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
170
- ]),
171
- ]))),
172
- ], ts.NodeFlags.Const));
173
- return hookExport;
174
- }
175
- export const createUseQuery = ({ functionDescription: { method, jsDoc }, client, pageParam, nextPageParam, initialPageParam, paginatableMethods, modelNames, }) => {
176
- const methodName = getNameFromVariable(method);
177
- const queryKey = createQueryKeyFromMethod({ method });
178
- const { apiResponse: defaultApiResponse, responseDataType, suspenseResponseDataType, responseErrorType, } = createApiResponseType({
179
- methodName,
180
- client,
181
- modelNames,
182
- });
183
- const requestParam = getRequestParamFromMethod(method, undefined, modelNames);
184
- const infiniteRequestParam = getRequestParamFromMethod(method, pageParam, modelNames);
185
- const requestParams = requestParam ? [requestParam] : [];
186
- const queryHook = createQueryHook({
187
- queryString: "useQuery",
188
- suffix: "",
189
- responseDataType,
190
- responseErrorType,
191
- requestParams,
192
- method,
193
- });
194
- const suspenseQueryHook = createQueryHook({
195
- queryString: "useSuspenseQuery",
196
- suffix: "Suspense",
197
- responseDataType: suspenseResponseDataType,
198
- responseErrorType,
199
- requestParams,
200
- method,
201
- });
202
- const isInfiniteQuery = paginatableMethods.includes(methodName);
203
- const infiniteQueryHook = isInfiniteQuery
204
- ? createQueryHook({
205
- queryString: "useInfiniteQuery",
206
- suffix: "Infinite",
207
- responseDataType,
208
- responseErrorType,
209
- requestParams: infiniteRequestParam ? [infiniteRequestParam] : [],
210
- method,
211
- pageParam,
212
- nextPageParam,
213
- initialPageParam,
214
- })
215
- : undefined;
216
- const hookWithJsDoc = addJSDocToNode(queryHook, jsDoc);
217
- const suspenseHookWithJsDoc = addJSDocToNode(suspenseQueryHook, jsDoc);
218
- const infiniteHookWithJsDoc = infiniteQueryHook
219
- ? addJSDocToNode(infiniteQueryHook, jsDoc)
220
- : undefined;
221
- const returnTypeExport = createReturnTypeExport({
222
- methodName,
223
- defaultApiResponse,
224
- });
225
- const queryKeyExport = createQueryKeyExport({
226
- methodName,
227
- queryKey,
228
- });
229
- const queryKeyFn = createQueryKeyFnExport(queryKey, method, "query", modelNames);
230
- return {
231
- apiResponse: defaultApiResponse,
232
- returnType: returnTypeExport,
233
- key: queryKeyExport,
234
- queryHook: hookWithJsDoc,
235
- suspenseQueryHook: suspenseHookWithJsDoc,
236
- infiniteQueryHook: infiniteHookWithJsDoc,
237
- queryKeyFn,
238
- };
239
- };
240
- function createInfiniteQueryParams(pageParam, nextPageParam, initialPageParam = "1") {
241
- if (pageParam === undefined || nextPageParam === undefined) {
242
- return [];
243
- }
244
- return [
245
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier("initialPageParam"), ts.factory.createStringLiteral(initialPageParam)),
246
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier("getNextPageParam"),
247
- // (response) => (response as { nextPage: number }).nextPage,
248
- ts.factory.createArrowFunction(undefined, undefined, [
249
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("response"), undefined, undefined),
250
- ], undefined, EqualsOrGreaterThanToken, ts.factory.createPropertyAccessExpression(ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(ts.factory.createIdentifier("response"), nextPageParam.split(".").reduceRight((acc, segment) => {
251
- return ts.factory.createTypeLiteralNode([
252
- ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(segment), undefined, acc),
253
- ]);
254
- }, ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)))), ts.factory.createIdentifier(nextPageParam)))),
255
- ];
256
- }