@7nohe/openapi-react-query-codegen 1.2.1 → 1.3.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/README.md +107 -0
- package/dist/cli.mjs +4 -4
- package/dist/common.mjs +7 -5
- package/dist/createExports.mjs +22 -19
- package/dist/createImports.mjs +2 -1
- package/dist/createPrefetch.mjs +2 -4
- package/dist/createSource.mjs +3 -3
- package/dist/createUseMutation.mjs +6 -15
- package/dist/createUseQuery.mjs +51 -23
- package/dist/generate.mjs +3 -3
- package/dist/print.mjs +2 -2
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -160,6 +160,80 @@ function App() {
|
|
|
160
160
|
export default App;
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
##### Using Mutation hooks
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
// App.tsx
|
|
167
|
+
import { usePetServiceAddPet } from "../openapi/queries";
|
|
168
|
+
|
|
169
|
+
function App() {
|
|
170
|
+
const { mutate } = usePetServiceAddPet();
|
|
171
|
+
|
|
172
|
+
const handleAddPet = () => {
|
|
173
|
+
mutate({ name: "Fluffy", status: "available" });
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div className="App">
|
|
178
|
+
<h1>Add Pet</h1>
|
|
179
|
+
<button onClick={handleAddPet}>Add Pet</button>
|
|
180
|
+
</div>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export default App;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
##### Invalidating queries after mutation
|
|
188
|
+
|
|
189
|
+
Invalidating queries after a mutation is important to ensure the cache is updated with the new data. This is done by calling the `queryClient.invalidateQueries` function with the query key used by the query hook.
|
|
190
|
+
|
|
191
|
+
Learn more about invalidating queries [here](https://tanstack.com/query/latest/docs/framework/react/guides/query-invalidation).
|
|
192
|
+
|
|
193
|
+
To ensure the query key is created the same way as the query hook, you can use the query key function exported by the generated query hooks.
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
import {
|
|
197
|
+
usePetServiceFindPetsByStatus,
|
|
198
|
+
usePetServiceAddPet,
|
|
199
|
+
UsePetServiceFindPetsByStatusKeyFn,
|
|
200
|
+
} from "../openapi/queries";
|
|
201
|
+
|
|
202
|
+
// App.tsx
|
|
203
|
+
function App() {
|
|
204
|
+
const [status, setStatus] = React.useState(["available"]);
|
|
205
|
+
const { data } = usePetServiceFindPetsByStatus({ status });
|
|
206
|
+
const { mutate } = usePetServiceAddPet({
|
|
207
|
+
onSuccess: () => {
|
|
208
|
+
queryClient.invalidateQueries({
|
|
209
|
+
// Call the query key function to get the query key
|
|
210
|
+
// This is important to ensure the query key is created the same way as the query hook
|
|
211
|
+
// This insures the cache is invalidated correctly and is typed correctly
|
|
212
|
+
queryKey: [UsePetServiceFindPetsByStatusKeyFn({
|
|
213
|
+
status
|
|
214
|
+
})],
|
|
215
|
+
});
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<div className="App">
|
|
221
|
+
<h1>Pet List</h1>
|
|
222
|
+
<ul>{data?.map((pet) => <li key={pet.id}>{pet.name}</li>)}</ul>
|
|
223
|
+
<button
|
|
224
|
+
onClick={() => {
|
|
225
|
+
mutate({ name: "Fluffy", status: "available" });
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
228
|
+
Add Pet
|
|
229
|
+
</button>
|
|
230
|
+
</div>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export default App;
|
|
235
|
+
```
|
|
236
|
+
|
|
163
237
|
##### Runtime Configuration
|
|
164
238
|
|
|
165
239
|
You can modify the default values used by the generated service calls by modifying the OpenAPI configuration singleton object.
|
|
@@ -188,6 +262,39 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
|
|
188
262
|
|
|
189
263
|
```
|
|
190
264
|
|
|
265
|
+
## Development
|
|
266
|
+
|
|
267
|
+
### Install dependencies
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
pnpm install
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Run tests
|
|
274
|
+
```bash
|
|
275
|
+
pnpm test
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Run linter
|
|
279
|
+
```bash
|
|
280
|
+
pnpm lint
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Run linter and fix
|
|
284
|
+
```bash
|
|
285
|
+
pnpm lint:fix
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Update snapshots
|
|
289
|
+
```bash
|
|
290
|
+
pnpm snapshot
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Build example and validate generated code
|
|
294
|
+
```bash
|
|
295
|
+
npm run build && pnpm --filter @7nohe/react-app generate:api && pnpm --filter @7nohe/react-app test:generated
|
|
296
|
+
```
|
|
297
|
+
|
|
191
298
|
## License
|
|
192
299
|
|
|
193
300
|
MIT
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { readFile } from "fs/promises";
|
|
5
|
-
import { dirname, join } from "path";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
6
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Command, Option } from "commander";
|
|
7
6
|
import { defaultOutputPath } from "./constants.mjs";
|
|
7
|
+
import { generate } from "./generate.mjs";
|
|
8
8
|
const program = new Command();
|
|
9
9
|
async function setupProgram() {
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
package/dist/common.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { stat } from "fs/promises";
|
|
1
|
+
import { stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
import ts from "typescript";
|
|
3
|
-
import path from "path";
|
|
4
4
|
import { queriesOutputPath, requestsOutputPath } from "./constants.mjs";
|
|
5
5
|
export const TData = ts.factory.createIdentifier("TData");
|
|
6
6
|
export const TError = ts.factory.createIdentifier("TError");
|
|
7
7
|
export const TContext = ts.factory.createIdentifier("TContext");
|
|
8
|
+
export const EqualsOrGreaterThanToken = ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken);
|
|
9
|
+
export const QuestionToken = ts.factory.createToken(ts.SyntaxKind.QuestionToken);
|
|
8
10
|
export const queryKeyGenericType = ts.factory.createTypeReferenceNode("TQueryKey");
|
|
9
11
|
export const queryKeyConstraint = ts.factory.createTypeReferenceNode("Array", [
|
|
10
12
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword),
|
|
@@ -49,10 +51,10 @@ export function BuildCommonTypeName(name) {
|
|
|
49
51
|
*/
|
|
50
52
|
export function safeParseNumber(value) {
|
|
51
53
|
const parsed = Number(value);
|
|
52
|
-
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
54
|
+
if (!Number.isNaN(parsed) && Number.isFinite(parsed)) {
|
|
53
55
|
return parsed;
|
|
54
56
|
}
|
|
55
|
-
return NaN;
|
|
57
|
+
return Number.NaN;
|
|
56
58
|
}
|
|
57
59
|
export function extractPropertiesFromObjectParam(param) {
|
|
58
60
|
const referenced = param.findReferences()[0];
|
|
@@ -117,7 +119,7 @@ export function formatOptions(options) {
|
|
|
117
119
|
else if (value === "false" || value === false) {
|
|
118
120
|
acc[typedKey] = false;
|
|
119
121
|
}
|
|
120
|
-
else if (!isNaN(parsedNumber)) {
|
|
122
|
+
else if (!Number.isNaN(parsedNumber)) {
|
|
121
123
|
acc[typedKey] = parsedNumber;
|
|
122
124
|
}
|
|
123
125
|
else {
|
package/dist/createExports.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createUseQuery } from "./createUseQuery.mjs";
|
|
2
|
-
import { createUseMutation } from "./createUseMutation.mjs";
|
|
3
1
|
import { createPrefetch } from "./createPrefetch.mjs";
|
|
2
|
+
import { createUseMutation } from "./createUseMutation.mjs";
|
|
3
|
+
import { createUseQuery } from "./createUseQuery.mjs";
|
|
4
4
|
export const createExports = (service) => {
|
|
5
5
|
const { klasses } = service;
|
|
6
|
-
const methods = klasses.
|
|
6
|
+
const methods = klasses.flatMap((k) => k.methods);
|
|
7
7
|
const allGet = methods.filter((m) => m.httpMethodName.toUpperCase().includes("GET"));
|
|
8
8
|
const allPost = methods.filter((m) => m.httpMethodName.toUpperCase().includes("POST"));
|
|
9
9
|
const allPut = methods.filter((m) => m.httpMethodName.toUpperCase().includes("PUT"));
|
|
@@ -22,25 +22,28 @@ export const createExports = (service) => {
|
|
|
22
22
|
...allPatchMutations,
|
|
23
23
|
...allDeleteMutations,
|
|
24
24
|
];
|
|
25
|
-
const commonInQueries = allQueries
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const commonInQueries = allQueries.flatMap(({ apiResponse, returnType, key, queryKeyFn }) => [
|
|
26
|
+
apiResponse,
|
|
27
|
+
returnType,
|
|
28
|
+
key,
|
|
29
|
+
queryKeyFn,
|
|
30
|
+
]);
|
|
31
|
+
const commonInMutations = allMutations.flatMap(({ mutationResult }) => [
|
|
32
|
+
mutationResult,
|
|
33
|
+
]);
|
|
31
34
|
const allCommon = [...commonInQueries, ...commonInMutations];
|
|
32
|
-
const mainQueries = allQueries.
|
|
33
|
-
const mainMutations = allMutations
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const mainQueries = allQueries.flatMap(({ queryHook }) => [queryHook]);
|
|
36
|
+
const mainMutations = allMutations.flatMap(({ mutationHook }) => [
|
|
37
|
+
mutationHook,
|
|
38
|
+
]);
|
|
36
39
|
const mainExports = [...mainQueries, ...mainMutations];
|
|
37
|
-
const suspenseQueries = allQueries
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
const suspenseQueries = allQueries.flatMap(({ suspenseQueryHook }) => [
|
|
41
|
+
suspenseQueryHook,
|
|
42
|
+
]);
|
|
40
43
|
const suspenseExports = [...suspenseQueries];
|
|
41
|
-
const allPrefetches = allPrefetchQueries
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
const allPrefetches = allPrefetchQueries.flatMap(({ prefetchHook }) => [
|
|
45
|
+
prefetchHook,
|
|
46
|
+
]);
|
|
44
47
|
const allPrefetchExports = [...allPrefetches];
|
|
45
48
|
return {
|
|
46
49
|
/**
|
package/dist/createImports.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
1
2
|
import ts from "typescript";
|
|
2
|
-
import { posix } from "path";
|
|
3
3
|
import { modalsFileName, serviceFileName } from "./constants.mjs";
|
|
4
4
|
const { join } = posix;
|
|
5
5
|
export const createImports = ({ serviceEndName, project, }) => {
|
|
@@ -19,6 +19,7 @@ export const createImports = ({ serviceEndName, project, }) => {
|
|
|
19
19
|
const serviceNames = serviceExports.filter((name) => name.endsWith(serviceEndName));
|
|
20
20
|
const imports = [
|
|
21
21
|
ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
|
|
22
|
+
ts.factory.createImportSpecifier(true, undefined, ts.factory.createIdentifier("QueryClient")),
|
|
22
23
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useQuery")),
|
|
23
24
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useSuspenseQuery")),
|
|
24
25
|
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("useMutation")),
|
package/dist/createPrefetch.mjs
CHANGED
|
@@ -25,8 +25,7 @@ function createPrefetchHook({ requestParams, method, className, }) {
|
|
|
25
25
|
? ts.factory.createArrayLiteralExpression([
|
|
26
26
|
ts.factory.createObjectLiteralExpression(method
|
|
27
27
|
.getParameters()
|
|
28
|
-
.
|
|
29
|
-
.flat()),
|
|
28
|
+
.flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
|
|
30
29
|
])
|
|
31
30
|
: ts.factory.createArrayLiteralExpression([]),
|
|
32
31
|
], false)),
|
|
@@ -34,8 +33,7 @@ function createPrefetchHook({ requestParams, method, className, }) {
|
|
|
34
33
|
? [
|
|
35
34
|
ts.factory.createObjectLiteralExpression(method
|
|
36
35
|
.getParameters()
|
|
37
|
-
.
|
|
38
|
-
.flat()),
|
|
36
|
+
.flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
|
|
39
37
|
]
|
|
40
38
|
: undefined))),
|
|
41
39
|
]),
|
package/dist/createSource.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { join } from "node:path";
|
|
2
2
|
import { Project } from "ts-morph";
|
|
3
|
-
import
|
|
3
|
+
import ts from "typescript";
|
|
4
4
|
import { OpenApiRqFiles } from "./constants.mjs";
|
|
5
|
-
import { createImports } from "./createImports.mjs";
|
|
6
5
|
import { createExports } from "./createExports.mjs";
|
|
6
|
+
import { createImports } from "./createImports.mjs";
|
|
7
7
|
import { getServices } from "./service.mjs";
|
|
8
8
|
const createSourceFile = async (outputPath, serviceEndName) => {
|
|
9
9
|
const project = new Project({
|
|
@@ -20,15 +20,12 @@ export const createUseMutation = ({ className, method, jsDoc, }) => {
|
|
|
20
20
|
const mutationResult = ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(`${className}${capitalizeFirstLetter(methodName)}MutationResult`), undefined, awaitedResponseDataType);
|
|
21
21
|
const responseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData, undefined, ts.factory.createTypeReferenceNode(BuildCommonTypeName(mutationResult.name)));
|
|
22
22
|
const methodParameters = method.getParameters().length !== 0
|
|
23
|
-
? ts.factory.createTypeLiteralNode(method
|
|
24
|
-
.getParameters()
|
|
25
|
-
.map((param) => {
|
|
23
|
+
? ts.factory.createTypeLiteralNode(method.getParameters().flatMap((param) => {
|
|
26
24
|
const paramNodes = extractPropertiesFromObjectParam(param);
|
|
27
25
|
return paramNodes.map((refParam) => ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(refParam.name), refParam.optional
|
|
28
26
|
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
|
|
29
27
|
: undefined, ts.factory.createTypeReferenceNode(getShortType(refParam.type.getText(param)))));
|
|
30
|
-
})
|
|
31
|
-
.flat())
|
|
28
|
+
}))
|
|
32
29
|
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
|
|
33
30
|
const exportHook = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
34
31
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier(`use${className}${capitalizeFirstLetter(methodName)}`), undefined, undefined, ts.factory.createArrowFunction(undefined, ts.factory.createNodeArray([
|
|
@@ -54,23 +51,17 @@ export const createUseMutation = ({ className, method, jsDoc, }) => {
|
|
|
54
51
|
ts.factory.createObjectLiteralExpression([
|
|
55
52
|
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("mutationFn"), ts.factory.createArrowFunction(undefined, undefined, method.getParameters().length !== 0
|
|
56
53
|
? [
|
|
57
|
-
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(method
|
|
58
|
-
.getParameters()
|
|
59
|
-
.map((param) => {
|
|
54
|
+
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(method.getParameters().flatMap((param) => {
|
|
60
55
|
const paramNodes = extractPropertiesFromObjectParam(param);
|
|
61
56
|
return paramNodes.map((refParam) => ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(refParam.name), undefined));
|
|
62
|
-
})
|
|
63
|
-
.flat()), undefined, undefined, undefined),
|
|
57
|
+
})), undefined, undefined, undefined),
|
|
64
58
|
]
|
|
65
59
|
: [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createAsExpression(ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(className), ts.factory.createIdentifier(methodName)), undefined, method.getParameters().length !== 0
|
|
66
60
|
? [
|
|
67
|
-
ts.factory.createObjectLiteralExpression(method
|
|
68
|
-
.getParameters()
|
|
69
|
-
.map((params) => {
|
|
61
|
+
ts.factory.createObjectLiteralExpression(method.getParameters().flatMap((params) => {
|
|
70
62
|
const paramNodes = extractPropertiesFromObjectParam(params);
|
|
71
63
|
return paramNodes.map((refParam) => ts.factory.createShorthandPropertyAssignment(refParam.name));
|
|
72
|
-
})
|
|
73
|
-
.flat()),
|
|
64
|
+
})),
|
|
74
65
|
]
|
|
75
66
|
: []), ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Promise"), [ts.factory.createTypeReferenceNode(TData)])))),
|
|
76
67
|
ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
|
package/dist/createUseQuery.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
-
import { BuildCommonTypeName, capitalizeFirstLetter, extractPropertiesFromObjectParam, getNameFromMethod, getShortType, queryKeyConstraint, queryKeyGenericType,
|
|
2
|
+
import { BuildCommonTypeName, EqualsOrGreaterThanToken, QuestionToken, TData, TError, capitalizeFirstLetter, extractPropertiesFromObjectParam, getNameFromMethod, getShortType, queryKeyConstraint, queryKeyGenericType, } from "./common.mjs";
|
|
3
3
|
import { addJSDocToNode } from "./util.mjs";
|
|
4
4
|
export const createApiResponseType = ({ className, methodName, }) => {
|
|
5
5
|
/** Awaited<ReturnType<typeof myClass.myMethod>> */
|
|
@@ -14,12 +14,15 @@ export const createApiResponseType = ({ className, methodName, }) => {
|
|
|
14
14
|
const apiResponse = ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(`${capitalizeFirstLetter(className)}${capitalizeFirstLetter(methodName)}DefaultResponse`), undefined, awaitedResponseDataType);
|
|
15
15
|
const responseDataType = ts.factory.createTypeParameterDeclaration(undefined, TData.text, undefined, ts.factory.createTypeReferenceNode(BuildCommonTypeName(apiResponse.name)));
|
|
16
16
|
return {
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* DefaultResponseDataType
|
|
19
|
+
*
|
|
18
20
|
* export type MyClassMethodDefaultResponse = Awaited<ReturnType<typeof myClass.myMethod>>
|
|
19
21
|
*/
|
|
20
22
|
apiResponse,
|
|
21
23
|
/**
|
|
22
|
-
* will be the name of the type of the response type of the method
|
|
24
|
+
* This will be the name of the type of the response type of the method
|
|
25
|
+
*
|
|
23
26
|
* MyClassMethodDefaultResponse
|
|
24
27
|
*/
|
|
25
28
|
responseDataType,
|
|
@@ -29,17 +32,14 @@ export function getRequestParamFromMethod(method) {
|
|
|
29
32
|
if (!method.getParameters().length) {
|
|
30
33
|
return null;
|
|
31
34
|
}
|
|
32
|
-
const params = method
|
|
33
|
-
.getParameters()
|
|
34
|
-
.map((param) => {
|
|
35
|
+
const params = method.getParameters().flatMap((param) => {
|
|
35
36
|
const paramNodes = extractPropertiesFromObjectParam(param);
|
|
36
37
|
return paramNodes.map((refParam) => ({
|
|
37
38
|
name: refParam.name,
|
|
38
39
|
typeName: getShortType(refParam.type.getText()),
|
|
39
40
|
optional: refParam.optional,
|
|
40
41
|
}));
|
|
41
|
-
})
|
|
42
|
-
.flat();
|
|
42
|
+
});
|
|
43
43
|
const areAllPropertiesOptional = params.every((param) => param.optional);
|
|
44
44
|
return ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(params.map((refParam) => ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(refParam.name), undefined))), undefined, ts.factory.createTypeLiteralNode(params.map((refParam) => {
|
|
45
45
|
return ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(refParam.name), refParam.optional
|
|
@@ -54,6 +54,7 @@ export function getRequestParamFromMethod(method) {
|
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
56
|
* Return Type
|
|
57
|
+
*
|
|
57
58
|
* export const classNameMethodNameQueryResult<TData = MyClassMethodDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
|
|
58
59
|
*/
|
|
59
60
|
export function createReturnTypeExport({ className, methodName, defaultApiResponse, }) {
|
|
@@ -109,28 +110,24 @@ export function createQueryHook({ queryString, suffix, responseDataType, request
|
|
|
109
110
|
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("queryFn")),
|
|
110
111
|
]),
|
|
111
112
|
])),
|
|
112
|
-
], undefined,
|
|
113
|
+
], undefined, EqualsOrGreaterThanToken, ts.factory.createCallExpression(ts.factory.createIdentifier(queryString), [
|
|
113
114
|
ts.factory.createTypeReferenceNode(TData),
|
|
114
115
|
ts.factory.createTypeReferenceNode(TError),
|
|
115
116
|
], [
|
|
116
117
|
ts.factory.createObjectLiteralExpression([
|
|
117
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryKey"), ts.factory.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
ts.factory.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
: ts.factory.createArrayLiteralExpression([])))),
|
|
127
|
-
], false)),
|
|
128
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryFn"), ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(className), ts.factory.createIdentifier(methodName)), undefined, method.getParameters().length
|
|
118
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryKey"), ts.factory.createCallExpression(BuildCommonTypeName(getQueryKeyFnName(queryKey)), undefined, method.getParameters().length
|
|
119
|
+
? [
|
|
120
|
+
ts.factory.createObjectLiteralExpression(method
|
|
121
|
+
.getParameters()
|
|
122
|
+
.flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
|
|
123
|
+
ts.factory.createIdentifier("queryKey"),
|
|
124
|
+
]
|
|
125
|
+
: [])),
|
|
126
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier("queryFn"), ts.factory.createArrowFunction(undefined, undefined, [], undefined, EqualsOrGreaterThanToken, ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(className), ts.factory.createIdentifier(methodName)), undefined, method.getParameters().length
|
|
129
127
|
? [
|
|
130
128
|
ts.factory.createObjectLiteralExpression(method
|
|
131
129
|
.getParameters()
|
|
132
|
-
.
|
|
133
|
-
.flat()),
|
|
130
|
+
.flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
|
|
134
131
|
]
|
|
135
132
|
: undefined), ts.factory.createTypeReferenceNode(TData)))),
|
|
136
133
|
ts.factory.createSpreadAssignment(ts.factory.createIdentifier("options")),
|
|
@@ -176,11 +173,42 @@ export const createUseQuery = ({ className, method, jsDoc, }) => {
|
|
|
176
173
|
methodName,
|
|
177
174
|
queryKey,
|
|
178
175
|
});
|
|
176
|
+
const queryKeyFn = createQueryKeyFnExport(queryKey, method);
|
|
179
177
|
return {
|
|
180
178
|
apiResponse: defaultApiResponse,
|
|
181
179
|
returnType: returnTypeExport,
|
|
182
180
|
key: queryKeyExport,
|
|
183
181
|
queryHook: hookWithJsDoc,
|
|
184
182
|
suspenseQueryHook: suspenseHookWithJsDoc,
|
|
183
|
+
queryKeyFn,
|
|
185
184
|
};
|
|
186
185
|
};
|
|
186
|
+
function getQueryKeyFnName(queryKey) {
|
|
187
|
+
return `${capitalizeFirstLetter(queryKey)}Fn`;
|
|
188
|
+
}
|
|
189
|
+
function createQueryKeyFnExport(queryKey, method) {
|
|
190
|
+
const params = getRequestParamFromMethod(method);
|
|
191
|
+
// override key is used to allow the user to override the the queryKey values
|
|
192
|
+
const overrideKey = ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier("queryKey"), QuestionToken, ts.factory.createTypeReferenceNode("Array<unknown>", []));
|
|
193
|
+
return ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
194
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier(getQueryKeyFnName(queryKey)), undefined, undefined, ts.factory.createArrowFunction(undefined, undefined, params ? [params, overrideKey] : [], undefined, EqualsOrGreaterThanToken, queryKeyFn(queryKey, method))),
|
|
195
|
+
], ts.NodeFlags.Const));
|
|
196
|
+
}
|
|
197
|
+
function queryKeyFn(queryKey, method) {
|
|
198
|
+
const params = getRequestParamFromMethod(method);
|
|
199
|
+
if (!params) {
|
|
200
|
+
return ts.factory.createArrayLiteralExpression([
|
|
201
|
+
ts.factory.createIdentifier(queryKey),
|
|
202
|
+
]);
|
|
203
|
+
}
|
|
204
|
+
return ts.factory.createArrayLiteralExpression([
|
|
205
|
+
ts.factory.createIdentifier(queryKey),
|
|
206
|
+
ts.factory.createSpreadElement(ts.factory.createParenthesizedExpression(ts.factory.createBinaryExpression(ts.factory.createIdentifier("queryKey"), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), method.getParameters().length
|
|
207
|
+
? ts.factory.createArrayLiteralExpression([
|
|
208
|
+
ts.factory.createObjectLiteralExpression(method
|
|
209
|
+
.getParameters()
|
|
210
|
+
.flatMap((param) => extractPropertiesFromObjectParam(param).map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name))))),
|
|
211
|
+
])
|
|
212
|
+
: ts.factory.createArrayLiteralExpression([])))),
|
|
213
|
+
], false);
|
|
214
|
+
}
|
package/dist/generate.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createClient } from "@hey-api/openapi-ts";
|
|
2
|
-
import { print } from "./print.mjs";
|
|
3
|
-
import { createSource } from "./createSource.mjs";
|
|
4
2
|
import { buildQueriesOutputPath, buildRequestsOutputPath, formatOptions, } from "./common.mjs";
|
|
3
|
+
import { createSource } from "./createSource.mjs";
|
|
5
4
|
import { formatOutput } from "./format.mjs";
|
|
5
|
+
import { print } from "./print.mjs";
|
|
6
6
|
export async function generate(options, version) {
|
|
7
7
|
const openApiOutputPath = buildRequestsOutputPath(options.output);
|
|
8
8
|
const formattedOptions = formatOptions(options);
|
|
@@ -11,7 +11,6 @@ export async function generate(options, version) {
|
|
|
11
11
|
client: formattedOptions.client,
|
|
12
12
|
debug: formattedOptions.debug,
|
|
13
13
|
dryRun: false,
|
|
14
|
-
enums: formattedOptions.enums,
|
|
15
14
|
exportCore: true,
|
|
16
15
|
format: formattedOptions.format,
|
|
17
16
|
input: formattedOptions.input,
|
|
@@ -29,6 +28,7 @@ export async function generate(options, version) {
|
|
|
29
28
|
types: {
|
|
30
29
|
dates: formattedOptions.useDateType,
|
|
31
30
|
export: true,
|
|
31
|
+
enums: formattedOptions.enums,
|
|
32
32
|
},
|
|
33
33
|
useOptions: true,
|
|
34
34
|
};
|
package/dist/print.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
2
|
-
import path from "path";
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
3
|
import { buildQueriesOutputPath, exists } from "./common.mjs";
|
|
4
4
|
async function printGeneratedTS(result, options) {
|
|
5
5
|
const dir = buildQueriesOutputPath(options.output);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7nohe/openapi-react-query-codegen",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "OpenAPI React Query Codegen",
|
|
5
5
|
"bin": {
|
|
6
6
|
"openapi-rq": "dist/cli.mjs"
|
|
@@ -30,19 +30,22 @@
|
|
|
30
30
|
],
|
|
31
31
|
"author": "Daiki Urata (@7nohe)",
|
|
32
32
|
"license": "MIT",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@hey-api/openapi-ts": "0.43.0"
|
|
35
|
+
},
|
|
33
36
|
"devDependencies": {
|
|
34
|
-
"@
|
|
37
|
+
"@biomejs/biome": "^1.7.2",
|
|
35
38
|
"@types/node": "^20.10.6",
|
|
36
39
|
"@vitest/coverage-v8": "^1.5.0",
|
|
37
40
|
"commander": "^12.0.0",
|
|
38
41
|
"glob": "^10.3.10",
|
|
42
|
+
"lefthook": "^1.6.10",
|
|
39
43
|
"rimraf": "^5.0.5",
|
|
40
44
|
"ts-morph": "^22.0.0",
|
|
41
45
|
"typescript": "^5.3.3",
|
|
42
46
|
"vitest": "^1.5.0"
|
|
43
47
|
},
|
|
44
48
|
"peerDependencies": {
|
|
45
|
-
"@hey-api/openapi-ts": "0.42.1",
|
|
46
49
|
"commander": "12.x",
|
|
47
50
|
"glob": "10.x",
|
|
48
51
|
"ts-morph": "22.x",
|
|
@@ -53,8 +56,11 @@
|
|
|
53
56
|
},
|
|
54
57
|
"scripts": {
|
|
55
58
|
"build": "rimraf dist && tsc -p tsconfig.json",
|
|
59
|
+
"lint": "biome check .",
|
|
60
|
+
"lint:fix": "biome check --apply .",
|
|
56
61
|
"preview": "npm run build && npm -C examples/react-app run generate:api",
|
|
57
62
|
"release": "npx git-ensure -a && npx bumpp --commit --tag --push",
|
|
58
|
-
"test": "vitest --coverage.enabled true"
|
|
63
|
+
"test": "vitest --coverage.enabled true",
|
|
64
|
+
"snapshot": "vitest --update"
|
|
59
65
|
}
|
|
60
66
|
}
|