diff --git a/package.json b/package.json index e6ade94..66dba96 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "commander": "^11.1.0", "glob": "^10.2.5", "openapi-typescript-codegen": "^0.25.0", - "typescript": "^5.0.4" + "typescript": "^5.2.2" }, "peerDependencies": { "commander": ">= 11 < 12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 382c95c..bbd6da2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,7 +21,7 @@ importers: specifier: ^0.25.0 version: 0.25.0 typescript: - specifier: ^5.0.4 + specifier: ^5.2.2 version: 5.2.2 dist: @@ -2105,7 +2105,7 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true dependencies: - minimist: 1.2.6 + minimist: 1.2.8 dev: true /ms@2.1.2: diff --git a/src/createExports.ts b/src/createExports.ts index 183ea37..2acbcd5 100644 --- a/src/createExports.ts +++ b/src/createExports.ts @@ -29,7 +29,6 @@ export const createExports = (generatedClientsPath: string) => { ) as ts.MethodDeclaration[]; return methods .map((method) => { - const methodName = method.name?.getText(node)!; const methodBlock = method .getChildren(node) .find((child) => child.kind === ts.SyntaxKind.Block) as ts.Block; diff --git a/src/createImports.ts b/src/createImports.ts index 01a873c..7e8e470 100644 --- a/src/createImports.ts +++ b/src/createImports.ts @@ -24,6 +24,11 @@ export const createImports = (generatedClientsPath: string) => { undefined, ts.factory.createIdentifier("useMutation") ), + ts.factory.createImportSpecifier( + false, + undefined, + ts.factory.createIdentifier("UseQueryResult") + ), ts.factory.createImportSpecifier( false, undefined, @@ -34,6 +39,11 @@ export const createImports = (generatedClientsPath: string) => { undefined, ts.factory.createIdentifier("UseMutationOptions") ), + ts.factory.createImportSpecifier( + false, + undefined, + ts.factory.createIdentifier("UseMutationResult") + ), ]) ), ts.factory.createStringLiteral("@tanstack/react-query"), diff --git a/src/createSource.ts b/src/createSource.ts index 7c60414..bc46820 100644 --- a/src/createSource.ts +++ b/src/createSource.ts @@ -1,6 +1,7 @@ import ts from "typescript"; import { createImports } from "./createImports"; import { createExports } from "./createExports"; +import { version } from "../package.json"; const createSourceFile = (outputPath: string) => { return ts.factory.createSourceFile( @@ -18,13 +19,16 @@ export const createSource = (outputPath: string) => { false, ts.ScriptKind.TS ); - const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); + const printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + removeComments: false, + }); - const result = printer.printNode( - ts.EmitHint.Unspecified, - createSourceFile(outputPath), - resultFile - ); + const node = createSourceFile(outputPath); + + const result = `// generated with openapi-generator@${version} \n` + printer.printNode(ts.EmitHint.Unspecified, node, resultFile); + + return result; }; diff --git a/src/createUseMutation.ts b/src/createUseMutation.ts index 7909ee0..247a80f 100644 --- a/src/createUseMutation.ts +++ b/src/createUseMutation.ts @@ -7,6 +7,48 @@ export const createUseMutation = ( method: ts.MethodDeclaration ) => { const methodName = method.name?.getText(node)!; + // Awaited> + const awaitedResponseDataType = ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("Awaited"), + [ + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("ReturnType"), + [ + ts.factory.createTypeQueryNode( + ts.factory.createQualifiedName( + ts.factory.createIdentifier(className), + ts.factory.createIdentifier(methodName) + ), + undefined + ), + ] + ), + ] + ); + + const responseDataType = ts.factory.createTypeParameterDeclaration( + undefined, + "ResponseData", + undefined, + awaitedResponseDataType + ); + + const methodParameters = + method.parameters.length !== 0 + ? ts.factory.createTypeLiteralNode( + method.parameters.map((param) => { + return ts.factory.createPropertySignature( + undefined, + ts.factory.createIdentifier(param.name.getText(node)), + param.questionToken ?? param.initializer + ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) + : param.questionToken, + param.type + ); + }) + ) + : ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword); + return ts.factory.createVariableStatement( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList( @@ -19,7 +61,7 @@ export const createUseMutation = ( undefined, ts.factory.createArrowFunction( undefined, - undefined, + ts.factory.createNodeArray([responseDataType]), [ ts.factory.createParameterDeclaration( undefined, @@ -32,40 +74,11 @@ export const createUseMutation = ( ts.factory.createTypeReferenceNode( ts.factory.createIdentifier("UseMutationOptions"), [ - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("Awaited"), - [ - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("ReturnType"), - [ - ts.factory.createTypeQueryNode( - ts.factory.createQualifiedName( - ts.factory.createIdentifier(className), - ts.factory.createIdentifier(methodName) - ), - undefined - ), - ] - ), - ] - ), + awaitedResponseDataType, ts.factory.createKeywordTypeNode( ts.SyntaxKind.UnknownKeyword ), - method.parameters.length !== 0 ? ts.factory.createTypeLiteralNode( - method.parameters.map((param) => { - return ts.factory.createPropertySignature( - undefined, - ts.factory.createIdentifier( - param.name.getText(node) - ), - param.questionToken ?? param.initializer ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : param.questionToken, - param.type - ); - }) - ) : ts.factory.createKeywordTypeNode( - ts.SyntaxKind.VoidKeyword - ), + methodParameters, ts.factory.createKeywordTypeNode( ts.SyntaxKind.UnknownKeyword ), @@ -81,56 +94,99 @@ export const createUseMutation = ( ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), - ts.factory.createCallExpression( - ts.factory.createIdentifier("useMutation"), - undefined, - [ - ts.factory.createObjectLiteralExpression([ - ts.factory.createPropertyAssignment( - ts.factory.createIdentifier("mutationFn"), - ts.factory.createArrowFunction( - undefined, - undefined, - method.parameters.length !== 0 ? [ - ts.factory.createParameterDeclaration( - undefined, - undefined, - ts.factory.createObjectBindingPattern( - method.parameters.map((param) => { - return ts.factory.createBindingElement( + ts.factory.createAsExpression( + ts.factory.createCallExpression( + ts.factory.createIdentifier("useMutation"), + undefined, + [ + ts.factory.createObjectLiteralExpression([ + ts.factory.createPropertyAssignment( + ts.factory.createIdentifier("mutationFn"), + ts.factory.createArrowFunction( + undefined, + undefined, + method.parameters.length !== 0 + ? [ + ts.factory.createParameterDeclaration( undefined, undefined, - ts.factory.createIdentifier( - param.name.getText(node) + ts.factory.createObjectBindingPattern( + method.parameters.map((param) => { + return ts.factory.createBindingElement( + undefined, + undefined, + ts.factory.createIdentifier( + param.name.getText(node) + ), + undefined + ); + }) ), + undefined, + undefined, undefined - ); - }) + ), + ] + : [], + undefined, + ts.factory.createToken( + ts.SyntaxKind.EqualsGreaterThanToken + ), + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(className), + ts.factory.createIdentifier(methodName) ), undefined, - undefined, - undefined - ), - ] : [], - undefined, - ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(className), - ts.factory.createIdentifier(methodName) - ), - undefined, - method.parameters.map((params) => - ts.factory.createIdentifier(params.name.getText(node)) + method.parameters.map((params) => + ts.factory.createIdentifier( + params.name.getText(node) + ) + ) ) ) + ), + ts.factory.createSpreadAssignment( + ts.factory.createIdentifier("options") + ), + ]), + ] + ), + // Omit, 'data'> & { data: ResponseData }; + ts.factory.createIntersectionTypeNode([ + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("Omit"), + [ + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("UseMutationResult"), + [ + awaitedResponseDataType, + ts.factory.createKeywordTypeNode( + ts.SyntaxKind.UnknownKeyword + ), + methodParameters, + ts.factory.createKeywordTypeNode( + ts.SyntaxKind.UnknownKeyword + ), + ] + ), + ts.factory.createLiteralTypeNode( + ts.factory.createStringLiteral("data") + ), + ] + ), + ts.factory.createTypeLiteralNode([ + ts.factory.createPropertySignature( + undefined, + ts.factory.createIdentifier("data"), + undefined, + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("ResponseData"), + undefined ) ), - ts.factory.createSpreadAssignment( - ts.factory.createIdentifier("options") - ), ]), - ] + ]) ) ) ), diff --git a/src/createUseQuery.ts b/src/createUseQuery.ts index edd3bf2..b80cdba 100644 --- a/src/createUseQuery.ts +++ b/src/createUseQuery.ts @@ -29,22 +29,56 @@ export const createUseQuery = ( ts.factory.createPropertySignature( undefined, ts.factory.createIdentifier(param.name.getText(node)), - param.questionToken ?? param.initializer ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : param.questionToken, + param.questionToken ?? param.initializer + ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) + : param.questionToken, param.type ) ) - ), - ), + ) + ) ); } const customHookName = `use${className}${capitalizeFirstLetter(methodName)}`; const queryKey = `${customHookName}Key`; - const queryKeyGenericType = ts.factory.createTypeReferenceNode('TQueryKey', undefined); - const queryKeyConstraint = ts.factory.createTypeReferenceNode('Array', [ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)]); + const queryKeyGenericType = ts.factory.createTypeReferenceNode( + "TQueryKey", + undefined + ); + const queryKeyConstraint = ts.factory.createTypeReferenceNode("Array", [ + ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword), + ]); + + // Awaited> + const awaitedResponseDataType = ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("Awaited"), + [ + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("ReturnType"), + [ + ts.factory.createTypeQueryNode( + ts.factory.createQualifiedName( + ts.factory.createIdentifier(className), + ts.factory.createIdentifier(methodName) + ), + undefined + ), + ] + ), + ] + ); + + const responseDataType = ts.factory.createTypeParameterDeclaration( + undefined, + "ResponseData", + undefined, + awaitedResponseDataType + ); return [ + // QueryKey ts.factory.createVariableStatement( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList( @@ -61,6 +95,7 @@ export const createUseQuery = ( ts.NodeFlags.Const ) ), + // Custom hook ts.factory.createVariableStatement( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList( @@ -82,6 +117,7 @@ export const createUseQuery = ( ) ) ), + responseDataType, ]), [ ...requestParam, @@ -103,43 +139,11 @@ export const createUseQuery = ( ts.factory.createTypeReferenceNode( ts.factory.createIdentifier("UseQueryOptions"), [ - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("Awaited"), - [ - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("ReturnType"), - [ - ts.factory.createTypeQueryNode( - ts.factory.createQualifiedName( - ts.factory.createIdentifier(className), - ts.factory.createIdentifier(methodName) - ), - undefined - ), - ] - ), - ] - ), + awaitedResponseDataType, ts.factory.createKeywordTypeNode( ts.SyntaxKind.UnknownKeyword ), - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("Awaited"), - [ - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("ReturnType"), - [ - ts.factory.createTypeQueryNode( - ts.factory.createQualifiedName( - ts.factory.createIdentifier(className), - ts.factory.createIdentifier(methodName) - ), - undefined - ), - ] - ), - ] - ), + awaitedResponseDataType, ts.factory.createArrayTypeNode( ts.factory.createKeywordTypeNode( ts.SyntaxKind.UnknownKeyword @@ -164,72 +168,105 @@ export const createUseQuery = ( ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), - ts.factory.createCallExpression( - ts.factory.createIdentifier("useQuery"), - undefined, - [ - ts.factory.createObjectLiteralExpression([ - ts.factory.createPropertyAssignment( - ts.factory.createIdentifier("queryKey"), - ts.factory.createArrayLiteralExpression( - [ - ts.factory.createIdentifier(queryKey), - ts.factory.createSpreadElement( - ts.factory.createParenthesizedExpression( - ts.factory.createBinaryExpression( - ts.factory.createIdentifier("queryKey"), - ts.factory.createToken( - ts.SyntaxKind.QuestionQuestionToken - ), - method.parameters.length - ? ts.factory.createArrayLiteralExpression([ - ts.factory.createObjectLiteralExpression( - method.parameters.map((param) => - ts.factory.createShorthandPropertyAssignment( - ts.factory.createIdentifier( - param.name.getText(node) + ts.factory.createAsExpression( + ts.factory.createCallExpression( + ts.factory.createIdentifier("useQuery"), + undefined, + [ + ts.factory.createObjectLiteralExpression([ + ts.factory.createPropertyAssignment( + ts.factory.createIdentifier("queryKey"), + ts.factory.createArrayLiteralExpression( + [ + ts.factory.createIdentifier(queryKey), + ts.factory.createSpreadElement( + ts.factory.createParenthesizedExpression( + ts.factory.createBinaryExpression( + ts.factory.createIdentifier("queryKey"), + ts.factory.createToken( + ts.SyntaxKind.QuestionQuestionToken + ), + method.parameters.length + ? ts.factory.createArrayLiteralExpression([ + ts.factory.createObjectLiteralExpression( + method.parameters.map((param) => + ts.factory.createShorthandPropertyAssignment( + ts.factory.createIdentifier( + param.name.getText(node) + ) ) ) - ) - ), - ]) - : ts.factory.createArrayLiteralExpression([]) + ), + ]) + : ts.factory.createArrayLiteralExpression([]) + ) ) - ) - ), - ], - false - ) - ), - ts.factory.createPropertyAssignment( - ts.factory.createIdentifier("queryFn"), - ts.factory.createArrowFunction( - undefined, - undefined, - [], - undefined, - ts.factory.createToken( - ts.SyntaxKind.EqualsGreaterThanToken - ), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(className), - ts.factory.createIdentifier(methodName) - ), + ), + ], + false + ) + ), + ts.factory.createPropertyAssignment( + ts.factory.createIdentifier("queryFn"), + ts.factory.createArrowFunction( + undefined, + undefined, + [], undefined, - method.parameters.map((param) => - ts.factory.createIdentifier( - param.name.getText(node) + ts.factory.createToken( + ts.SyntaxKind.EqualsGreaterThanToken + ), + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(className), + ts.factory.createIdentifier(methodName) + ), + undefined, + method.parameters.map((param) => + ts.factory.createIdentifier( + param.name.getText(node) + ) ) ) ) - ) + ), + ts.factory.createSpreadAssignment( + ts.factory.createIdentifier("options") + ), + ]), + ] + ), + // Omit, 'data'> & { data: ResponseData }; + ts.factory.createIntersectionTypeNode([ + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("Omit"), + [ + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("UseQueryResult"), + [ + awaitedResponseDataType, + ts.factory.createKeywordTypeNode( + ts.SyntaxKind.UnknownKeyword + ), + ] ), - ts.factory.createSpreadAssignment( - ts.factory.createIdentifier("options") + ts.factory.createLiteralTypeNode( + ts.factory.createStringLiteral("data") ), - ]), - ] + ] + ), + ts.factory.createTypeLiteralNode([ + ts.factory.createPropertySignature( + undefined, + ts.factory.createIdentifier("data"), + undefined, + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier("ResponseData"), + undefined + ) + ), + ]), + ]) ) ) ),