fork of hey-api/openapi-ts because I need some additional things

Merge pull request #893 from hey-api/chore/tanstack-query-wip-5

chore: progress on TanStack Query plugin

authored by

Lubos and committed by
GitHub
c1b76029 f29d83ad

+447 -201
+1 -1
packages/openapi-ts/src/compiler/classes.ts
··· 1 1 import ts from 'typescript'; 2 2 3 3 import { createCallExpression } from './module'; 4 - import { createTypeNode } from './typedef'; 5 4 import { 6 5 type AccessLevel, 6 + createTypeNode, 7 7 type FunctionParameter, 8 8 type FunctionTypeParameter, 9 9 toAccessLevelModifiers,
+6 -2
packages/openapi-ts/src/compiler/index.ts
··· 146 146 binaryExpression: transform.createBinaryExpression, 147 147 callExpression: module.createCallExpression, 148 148 classDeclaration: classes.createClassDeclaration, 149 + conditionalExpression: types.createConditionalExpression, 149 150 constVariable: module.createConstVariable, 150 151 constructorDeclaration: classes.createConstructorDeclaration, 151 152 elementAccessExpression: transform.createElementAccessExpression, ··· 169 170 returnFunctionCall: _return.createReturnFunctionCall, 170 171 returnVariable: _return.createReturnVariable, 171 172 safeAccessExpression: transform.createSafeAccessExpression, 173 + stringLiteral: types.createStringLiteral, 172 174 stringToTsNodes: utils.stringToTsNodes, 173 175 transformArrayMap: transform.createArrayMapTransform, 174 176 transformArrayMutation: transform.createArrayTransformMutation, 175 177 transformDateMutation: transform.createDateTransformMutation, 176 178 transformFunctionMutation: transform.createFunctionTransformMutation, 177 179 transformNewDate: transform.createDateTransformerExpression, 178 - typeAliasDeclaration: typedef.createTypeAliasDeclaration, 180 + typeAliasDeclaration: types.createTypeAliasDeclaration, 179 181 typeArrayNode: typedef.createTypeArrayNode, 180 182 typeInterfaceNode: typedef.createTypeInterfaceNode, 181 183 typeIntersectNode: typedef.createTypeIntersectNode, 182 - typeNode: typedef.createTypeNode, 184 + typeNode: types.createTypeNode, 185 + typeOfExpression: types.createTypeOfExpression, 183 186 typeRecordNode: typedef.createTypeRecordNode, 187 + typeReferenceNode: types.createTypeReferenceNode, 184 188 typeTupleNode: typedef.createTypeTupleNode, 185 189 typeUnionNode: typedef.createTypeUnionNode, 186 190 };
+11 -6
packages/openapi-ts/src/compiler/module.ts
··· 1 1 import ts from 'typescript'; 2 2 3 + import { createTypeReferenceNode } from './types'; 3 4 import { 4 5 addLeadingComments, 5 6 type Comments, ··· 94 95 /** 95 96 * Create a const variable. Optionally, it can use const assertion or export 96 97 * statement. Example: `export x = {} as const`. 97 - * @param constAssertion use const assertion? 98 + * @param assertion use const assertion? 98 99 * @param exportConst export created variable? 99 100 * @param expression expression for the variable. 100 101 * @param name name of the variable. ··· 102 103 */ 103 104 export const createConstVariable = ({ 104 105 comment, 105 - constAssertion, 106 + assertion, 106 107 destructure, 107 108 exportConst, 108 109 expression, 109 110 name, 110 111 typeName, 111 112 }: { 113 + assertion?: 'const' | ts.TypeNode; 112 114 comment?: Comments; 113 - constAssertion?: boolean; 114 115 destructure?: boolean; 115 116 exportConst?: boolean; 116 117 expression: ts.Expression; ··· 118 119 // TODO: support a more intuitive definition of generics for example 119 120 typeName?: string | ts.IndexedAccessTypeNode; 120 121 }): ts.VariableStatement => { 121 - const initializer = constAssertion 122 + const initializer = assertion 122 123 ? ts.factory.createAsExpression( 123 124 expression, 124 - ts.factory.createTypeReferenceNode('const'), 125 + typeof assertion === 'string' 126 + ? createTypeReferenceNode({ 127 + typeName: assertion, 128 + }) 129 + : assertion, 125 130 ) 126 131 : expression; 127 132 const nameIdentifier = createIdentifier({ text: name }); ··· 139 144 undefined, 140 145 typeName 141 146 ? typeof typeName === 'string' 142 - ? ts.factory.createTypeReferenceNode(typeName) 147 + ? createTypeReferenceNode({ typeName }) 143 148 : typeName 144 149 : undefined, 145 150 initializer,
+2 -1
packages/openapi-ts/src/compiler/return.ts
··· 1 1 import ts from 'typescript'; 2 2 3 3 import { createCallExpression } from './module'; 4 + import { createTypeReferenceNode } from './types'; 4 5 import { createIdentifier, isType } from './utils'; 5 6 6 7 const createReturnStatement = ({ ··· 27 28 types?: string[]; 28 29 }) => { 29 30 const typeArguments = types.map((type) => 30 - ts.factory.createTypeReferenceNode(type), 31 + createTypeReferenceNode({ typeName: type }), 31 32 ); 32 33 const argumentsArray = args 33 34 .map((arg) =>
+7 -1
packages/openapi-ts/src/compiler/transform.ts
··· 63 63 64 64 export const createBinaryExpression = ({ 65 65 left, 66 + operator = '=', 66 67 right, 67 68 }: { 68 69 left: ts.Expression; 70 + operator?: '=' | '===' | 'in'; 69 71 right: ts.Expression | string; 70 72 }) => { 71 73 const expression = ts.factory.createBinaryExpression( 72 74 left, 73 75 // TODO: add support for other tokens 74 - ts.SyntaxKind.EqualsToken, 76 + operator === '=' 77 + ? ts.SyntaxKind.EqualsToken 78 + : operator === '===' 79 + ? ts.SyntaxKind.EqualsEqualsEqualsToken 80 + : ts.SyntaxKind.InKeyword, 75 81 typeof right === 'string' ? createIdentifier({ text: right }) : right, 76 82 ); 77 83 return expression;
+7 -64
packages/openapi-ts/src/compiler/typedef.ts
··· 1 1 import ts from 'typescript'; 2 2 3 - import { 4 - addLeadingComments, 5 - type Comments, 6 - createIdentifier, 7 - ots, 8 - tsNodeToString, 9 - } from './utils'; 10 - 11 - const nullNode = ts.factory.createTypeReferenceNode('null'); 12 - 13 - export const createTypeNode = ( 14 - base: any | ts.TypeNode, 15 - args?: (any | ts.TypeNode)[], 16 - ): ts.TypeNode => { 17 - if (ts.isTypeNode(base)) { 18 - return base; 19 - } 20 - 21 - if (typeof base === 'number') { 22 - return ts.factory.createLiteralTypeNode(ots.number(base)); 23 - } 24 - 25 - return ts.factory.createTypeReferenceNode( 26 - base, 27 - args?.map((arg) => createTypeNode(arg)), 28 - ); 29 - }; 30 - 31 - /** 32 - * Create a type alias declaration. Example `export type X = Y;`. 33 - * @param comment (optional) comments to add 34 - * @param name the name of the type 35 - * @param type the type 36 - * @returns ts.TypeAliasDeclaration 37 - */ 38 - export const createTypeAliasDeclaration = ({ 39 - comment, 40 - exportType, 41 - name, 42 - type, 43 - }: { 44 - comment?: Comments; 45 - exportType?: boolean; 46 - name: string; 47 - type: string | ts.TypeNode; 48 - }): ts.TypeAliasDeclaration => { 49 - const node = ts.factory.createTypeAliasDeclaration( 50 - exportType 51 - ? [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)] 52 - : undefined, 53 - createIdentifier({ text: name }), 54 - [], 55 - createTypeNode(type), 56 - ); 57 - 58 - addLeadingComments({ 59 - comments: comment, 60 - node, 61 - }); 3 + import { createTypeNode, createTypeReferenceNode } from './types'; 4 + import { addLeadingComments, type Comments, tsNodeToString } from './utils'; 62 5 63 - return node; 64 - }; 6 + const nullNode = createTypeReferenceNode({ typeName: 'null' }); 65 7 66 8 // Property of a interface type node. 67 9 export type Property = { ··· 221 163 types: (any | ts.TypeNode)[], 222 164 isNullable: boolean = false, 223 165 ) => { 224 - const node = ts.factory.createTypeReferenceNode('Array', [ 225 - createTypeUnionNode(types), 226 - ]); 166 + const node = createTypeReferenceNode({ 167 + typeArguments: [createTypeUnionNode(types)], 168 + typeName: 'Array', 169 + }); 227 170 return maybeNullable({ isNullable, node }); 228 171 };
+117 -8
packages/openapi-ts/src/compiler/types.ts
··· 1 1 import ts from 'typescript'; 2 2 3 - import { createTypeNode } from './typedef'; 4 3 import { 5 4 addLeadingComments, 6 5 type Comments, ··· 27 26 28 27 export interface FunctionTypeParameter { 29 28 default?: any; 30 - extends?: any | ts.TypeNode; 31 - name: string; 29 + extends?: string | ts.TypeNode; 30 + name: string | ts.Identifier; 32 31 } 32 + 33 + export const createTypeNode = ( 34 + base: any | ts.TypeNode, 35 + args?: (any | ts.TypeNode)[], 36 + ): ts.TypeNode => { 37 + if (ts.isTypeNode(base)) { 38 + return base; 39 + } 40 + 41 + if (typeof base === 'number') { 42 + return ts.factory.createLiteralTypeNode(ots.number(base)); 43 + } 44 + 45 + return createTypeReferenceNode({ 46 + typeArguments: args?.map((arg) => createTypeNode(arg)), 47 + typeName: base, 48 + }); 49 + }; 33 50 34 51 export const createPropertyAccessExpression = ({ 35 52 expression, ··· 226 243 undefined, 227 244 type.name, 228 245 // TODO: support other extends values 229 - type.extends ? createKeywordTypeNode({ keyword: 'boolean' }) : undefined, 246 + type.extends 247 + ? typeof type.extends === 'string' 248 + ? createKeywordTypeNode({ keyword: 'boolean' }) 249 + : type.extends 250 + : undefined, 230 251 // TODO: support other default types 231 252 type.default !== undefined 232 - ? ts.factory.createLiteralTypeNode( 233 - type.default ? ts.factory.createTrue() : ts.factory.createFalse(), 234 - ) 253 + ? isTsNode(type.default) 254 + ? (type.default as unknown as ts.TypeNode) 255 + : ts.factory.createLiteralTypeNode( 256 + type.default ? ts.factory.createTrue() : ts.factory.createFalse(), 257 + ) 235 258 : undefined, 236 259 ), 237 260 ); ··· 307 330 308 331 export type ObjectValue = 309 332 | { 333 + assertion?: 'any'; 310 334 comments?: Comments; 311 335 spread: string; 312 336 } ··· 375 399 } 376 400 let assignment: ObjectAssignment; 377 401 if ('spread' in value) { 402 + const nameIdentifier = createIdentifier({ text: value.spread }); 378 403 assignment = ts.factory.createSpreadAssignment( 379 - createIdentifier({ text: value.spread }), 404 + value.assertion 405 + ? ts.factory.createAsExpression( 406 + nameIdentifier, 407 + createKeywordTypeNode({ keyword: value.assertion }), 408 + ) 409 + : nameIdentifier, 380 410 ); 381 411 } else if (shorthand && canShorthand) { 382 412 assignment = ts.factory.createShorthandPropertyAssignment( ··· 548 578 const node = ts.factory.createIndexedAccessTypeNode(objectType, indexType); 549 579 return node; 550 580 }; 581 + 582 + export const createStringLiteral = ({ text }: { text: string }) => { 583 + const node = ts.factory.createStringLiteral(text); 584 + return node; 585 + }; 586 + 587 + export const createConditionalExpression = ({ 588 + condition, 589 + whenFalse, 590 + whenTrue, 591 + }: { 592 + condition: ts.Expression; 593 + whenFalse: ts.Expression; 594 + whenTrue: ts.Expression; 595 + }) => { 596 + const expression = ts.factory.createConditionalExpression( 597 + condition, 598 + ts.factory.createToken(ts.SyntaxKind.QuestionToken), 599 + whenTrue, 600 + ts.factory.createToken(ts.SyntaxKind.ColonToken), 601 + whenFalse, 602 + ); 603 + return expression; 604 + }; 605 + 606 + export const createTypeOfExpression = ({ text }: { text: string }) => { 607 + const expression = ts.factory.createTypeOfExpression( 608 + createIdentifier({ text }), 609 + ); 610 + return expression; 611 + }; 612 + 613 + /** 614 + * Create a type alias declaration. Example `export type X = Y;`. 615 + * @param comment (optional) comments to add 616 + * @param name the name of the type 617 + * @param type the type 618 + * @returns ts.TypeAliasDeclaration 619 + */ 620 + export const createTypeAliasDeclaration = ({ 621 + comment, 622 + exportType, 623 + name, 624 + type, 625 + typeParameters = [], 626 + }: { 627 + comment?: Comments; 628 + exportType?: boolean; 629 + name: string; 630 + type: string | ts.TypeNode; 631 + typeParameters?: FunctionTypeParameter[]; 632 + }): ts.TypeAliasDeclaration => { 633 + const node = ts.factory.createTypeAliasDeclaration( 634 + exportType 635 + ? [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)] 636 + : undefined, 637 + createIdentifier({ text: name }), 638 + toTypeParameters(typeParameters), 639 + createTypeNode(type), 640 + ); 641 + 642 + addLeadingComments({ 643 + comments: comment, 644 + node, 645 + }); 646 + 647 + return node; 648 + }; 649 + 650 + export const createTypeReferenceNode = ({ 651 + typeArguments, 652 + typeName, 653 + }: { 654 + typeArguments?: ts.TypeNode[]; 655 + typeName: string | ts.EntityName; 656 + }) => { 657 + const node = ts.factory.createTypeReferenceNode(typeName, typeArguments); 658 + return node; 659 + };
+156 -60
packages/openapi-ts/src/generate/plugins.ts
··· 81 81 const createQueryKeyParamsFn = 'createQueryKeyParams'; 82 82 const infiniteQueryOptionsFn = 'infiniteQueryOptions'; 83 83 const mutationsType = 'UseMutationOptions'; 84 + const optionsType = 'Options'; 84 85 const queryKeyName = 'QueryKey'; 85 86 const queryOptionsFn = 'queryOptions'; 87 + const TOptionsType = 'TOptions'; 86 88 87 89 // TODO: `addTanStackQueryImport()` should be a method of file class to create 88 90 // unique imports. It could be made more performant too ··· 122 124 const createQueryKeyParamsFunction = () => { 123 125 hasCreateQueryKeyParamsFunction = true; 124 126 127 + const returnType = compiler.indexedAccessTypeNode({ 128 + indexType: ts.factory.createLiteralTypeNode( 129 + compiler.stringLiteral({ text: 'params' }), 130 + ), 131 + objectType: compiler.indexedAccessTypeNode({ 132 + indexType: compiler.typeNode(0), 133 + objectType: compiler.typeNode(queryKeyName, [ 134 + compiler.typeNode(TOptionsType), 135 + ]), 136 + }), 137 + }); 138 + 125 139 const queryKeyParamsFunction = compiler.constVariable({ 126 140 expression: compiler.arrowFunction({ 127 141 multiLine: true, ··· 129 143 { 130 144 isRequired: false, 131 145 name: 'options', 132 - type: compiler.typeNode('Options', [compiler.typeNode('T')]), 146 + type: compiler.typeNode(TOptionsType), 133 147 }, 134 148 ], 149 + returnType, 135 150 statements: [ 136 151 compiler.constVariable({ 152 + assertion: returnType, 137 153 expression: compiler.objectExpression({ 138 154 multiLine: false, 139 155 obj: [], 140 156 }), 141 157 name: 'params', 142 - typeName: compiler.indexedAccessTypeNode({ 143 - indexType: ts.factory.createLiteralTypeNode( 144 - ts.factory.createStringLiteral('params'), 145 - ), 146 - objectType: compiler.indexedAccessTypeNode({ 147 - indexType: compiler.typeNode(0), 148 - objectType: compiler.typeNode('QueryKey'), 149 - }), 150 - }), 158 + typeName: returnType, 151 159 }), 152 160 compiler.ifStatement({ 153 161 expression: compiler.propertyAccessExpression({ 154 - expression: 'options', 162 + expression: compiler.identifier({ text: 'options' }), 155 163 isOptional: true, 156 - name: 'body', 164 + name: compiler.identifier({ text: 'body' }), 157 165 }), 158 166 thenStatement: ts.factory.createBlock( 159 167 [ ··· 175 183 }), 176 184 compiler.ifStatement({ 177 185 expression: compiler.propertyAccessExpression({ 178 - expression: 'options', 186 + expression: compiler.identifier({ text: 'options' }), 179 187 isOptional: true, 180 - name: 'headers', 188 + name: compiler.identifier({ text: 'headers' }), 181 189 }), 182 190 thenStatement: ts.factory.createBlock( 183 191 [ ··· 199 207 }), 200 208 compiler.ifStatement({ 201 209 expression: compiler.propertyAccessExpression({ 202 - expression: 'options', 210 + expression: compiler.identifier({ text: 'options' }), 203 211 isOptional: true, 204 - name: 'path', 212 + name: compiler.identifier({ text: 'path' }), 205 213 }), 206 214 thenStatement: ts.factory.createBlock( 207 215 [ ··· 223 231 }), 224 232 compiler.ifStatement({ 225 233 expression: compiler.propertyAccessExpression({ 226 - expression: 'options', 234 + expression: compiler.identifier({ text: 'options' }), 227 235 isOptional: true, 228 - name: 'query', 236 + name: compiler.identifier({ text: 'query' }), 229 237 }), 230 238 thenStatement: ts.factory.createBlock( 231 239 [ ··· 251 259 ], 252 260 types: [ 253 261 { 254 - name: 'T', 262 + extends: compiler.typeReferenceNode({ 263 + typeName: compiler.identifier({ text: optionsType }), 264 + }), 265 + name: TOptionsType, 255 266 }, 256 267 ], 257 268 }), ··· 304 315 }, 305 316 { 306 317 name: 'params', 307 - type: compiler.typeInterfaceNode({ 308 - properties: [ 309 - { 310 - isRequired: false, 311 - name: 'body', 312 - type: compiler.keywordTypeNode({ 313 - keyword: 'any', 314 - }), 315 - }, 316 - { 317 - isRequired: false, 318 - name: 'headers', 319 - type: compiler.keywordTypeNode({ 320 - keyword: 'any', 321 - }), 322 - }, 323 - { 324 - isRequired: false, 325 - name: 'path', 326 - type: compiler.keywordTypeNode({ 327 - keyword: 'any', 328 - }), 329 - }, 330 - { 331 - isRequired: false, 332 - name: 'query', 333 - type: compiler.keywordTypeNode({ 334 - keyword: 'any', 335 - }), 336 - }, 318 + type: compiler.typeReferenceNode({ 319 + typeArguments: [ 320 + compiler.typeReferenceNode({ 321 + typeName: compiler.identifier({ text: TOptionsType }), 322 + }), 323 + compiler.typeUnionNode( 324 + ['body', 'headers', 'path', 'query'].map((key) => 325 + ts.factory.createLiteralTypeNode( 326 + compiler.stringLiteral({ text: key }), 327 + ), 328 + ), 329 + ), 337 330 ], 331 + typeName: compiler.identifier({ text: 'Pick' }), 338 332 }), 339 333 }, 340 334 { ··· 350 344 type: compiler.typeTupleNode({ 351 345 types: [compiler.typeInterfaceNode({ properties })], 352 346 }), 347 + typeParameters: [ 348 + { 349 + extends: compiler.typeReferenceNode({ 350 + typeName: compiler.identifier({ text: optionsType }), 351 + }), 352 + name: TOptionsType, 353 + }, 354 + ], 353 355 }); 354 356 files[plugin.name].add(queryKeyType); 355 357 }; ··· 607 609 operation.parameters, 608 610 ); 609 611 612 + const typeQueryKey = `${queryKeyName}<${optionsType}<${nameTypeData}>>`; 613 + const typePageObjectParam = `${typeQueryKey}[0]['params']`; 614 + const typePageParam = `${paginationField.base} | ${typePageObjectParam}`; 615 + 610 616 const expression = compiler.arrowFunction({ 611 617 parameters: [ 612 618 { ··· 645 651 ], 646 652 statements: [ 647 653 compiler.constVariable({ 654 + comment: [ 655 + { 656 + jsdoc: false, 657 + lines: ['@ts-ignore'], 658 + }, 659 + ], 660 + expression: compiler.conditionalExpression({ 661 + condition: compiler.binaryExpression({ 662 + left: compiler.typeOfExpression({ 663 + text: 'pageParam', 664 + }), 665 + operator: '===', 666 + right: compiler.stringLiteral({ 667 + text: 'object', 668 + }), 669 + }), 670 + whenFalse: compiler.objectExpression({ 671 + multiLine: true, 672 + obj: [ 673 + { 674 + key: getPaginationIn( 675 + paginationParameter, 676 + ), 677 + value: compiler.objectExpression({ 678 + multiLine: true, 679 + obj: [ 680 + { 681 + key: paginationField.name, 682 + value: compiler.identifier({ 683 + text: 'pageParam', 684 + }), 685 + }, 686 + ], 687 + }), 688 + }, 689 + ], 690 + }), 691 + whenTrue: compiler.identifier({ 692 + text: 'pageParam', 693 + }), 694 + }), 695 + name: 'page', 696 + typeName: typePageObjectParam, 697 + }), 698 + compiler.constVariable({ 648 699 destructure: true, 649 700 expression: compiler.awaitExpression({ 650 701 expression: compiler.callExpression({ ··· 657 708 spread: 'options', 658 709 }, 659 710 { 660 - spread: 'queryKey[0].params', 711 + key: 'body', 712 + value: compiler.objectExpression({ 713 + multiLine: true, 714 + obj: [ 715 + { 716 + assertion: 'any', 717 + spread: 718 + 'queryKey[0].params.body', 719 + }, 720 + { 721 + assertion: 'any', 722 + spread: 'page.body', 723 + }, 724 + ], 725 + }), 661 726 }, 662 727 { 663 - key: getPaginationIn( 664 - paginationParameter, 665 - ), 728 + key: 'headers', 666 729 value: compiler.objectExpression({ 667 730 multiLine: true, 668 731 obj: [ 669 732 { 670 - spread: `queryKey[0].params.${getPaginationIn(paginationParameter)}`, 733 + spread: 734 + 'queryKey[0].params.headers', 671 735 }, 672 736 { 673 - key: paginationField.name, 674 - value: compiler.identifier({ 675 - text: 'pageParam', 676 - }), 737 + spread: 'page.headers', 738 + }, 739 + ], 740 + }), 741 + }, 742 + { 743 + key: 'path', 744 + value: compiler.objectExpression({ 745 + multiLine: true, 746 + obj: [ 747 + { 748 + spread: 749 + 'queryKey[0].params.path', 750 + }, 751 + { 752 + spread: 'page.path', 753 + }, 754 + ], 755 + }), 756 + }, 757 + { 758 + key: 'query', 759 + value: compiler.objectExpression({ 760 + multiLine: true, 761 + obj: [ 762 + { 763 + spread: 764 + 'queryKey[0].params.query', 765 + }, 766 + { 767 + spread: 'page.query', 677 768 }, 678 769 ], 679 770 }), ··· 707 798 ], 708 799 name: infiniteQueryOptionsFn, 709 800 // TODO: better types syntax 710 - // TODO: detect pageParam type 711 801 types: [ 712 - `${typeResponse}, ${typeof typeError === 'string' ? typeError : typeError.name}, ${typeof typeInfiniteData === 'string' ? typeInfiniteData : typeInfiniteData.name}<${typeResponse}>, ${queryKeyName}, unknown`, 802 + typeResponse, 803 + typeof typeError === 'string' 804 + ? typeError 805 + : typeError.name, 806 + `${typeof typeInfiniteData === 'string' ? typeInfiniteData : typeInfiniteData.name}<${typeResponse}>`, 807 + typeQueryKey, 808 + typePageParam, 713 809 ], 714 810 }), 715 811 ],
+1 -1
packages/openapi-ts/src/generate/schemas.ts
··· 75 75 const obj = ensureValidSchemaOutput(schema); 76 76 const expression = compiler.objectExpression({ obj }); 77 77 const statement = compiler.constVariable({ 78 - constAssertion: true, 78 + assertion: 'const', 79 79 exportConst: true, 80 80 expression, 81 81 name: validName,
+1 -1
packages/openapi-ts/src/generate/types.ts
··· 210 210 unescape: true, 211 211 }); 212 212 const node = compiler.constVariable({ 213 + assertion: 'const', 213 214 comment, 214 - constAssertion: true, 215 215 exportConst: true, 216 216 expression, 217 217 name,
+65 -19
packages/openapi-ts/test/__snapshots__/test/generated/v3-hey-api-client-axios-plugin-tanstack-react-query/@tanstack/query.gen.ts.snap
··· 5 5 import { export_, import_, apiVVersionOdataControllerCount, getCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, deleteCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, deleteFoo, callWithDescriptions, deprecatedCall, callWithParameters, callWithWeirdParameterNames, getCallWithOptionalParam, postCallWithOptionalParam, postApiVbyApiVersionRequestBody, postApiVbyApiVersionFormData, callWithDefaultParameters, callWithDefaultOptionalParameters, callToTestOrderOfParams, duplicateName, duplicateName1, duplicateName2, duplicateName3, callWithNoContentResponse, callWithResponseAndNoContentResponse, dummyA, dummyB, callWithResponse, callWithDuplicateResponses, callWithResponses, collectionFormat, types, uploadFile, fileResponse, complexTypes, multipartRequest, multipartResponse, complexParams, callWithResultFromHeader, testErrorCode, nonAsciiæøåÆøÅöôêÊ字符串, putWithFormUrlEncoded } from '../services.gen'; 6 6 import type { ImportData, ImportError, ImportResponse, DeleteFooData3, CallWithDescriptionsData, DeprecatedCallData, CallWithParametersData, CallWithWeirdParameterNamesData, GetCallWithOptionalParamData, PostCallWithOptionalParamData, PostCallWithOptionalParamError, PostCallWithOptionalParamResponse, PostApiVbyApiVersionRequestBodyData, PostApiVbyApiVersionFormDataData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithResponsesError, CallWithResponsesResponse, CollectionFormatData, TypesData, UploadFileData, UploadFileError, UploadFileResponse, FileResponseData, ComplexTypesData, MultipartRequestData, ComplexParamsError, ComplexParamsData, ComplexParamsResponse, CallWithResultFromHeaderError, CallWithResultFromHeaderResponse, TestErrorCodeData, TestErrorCodeError, TestErrorCodeResponse, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Error, NonAsciiæøåÆøÅöôêÊ字符串Response, PutWithFormUrlEncodedData } from '../types.gen'; 7 7 8 - type QueryKey = [ 8 + type QueryKey<TOptions extends Options> = [ 9 9 { 10 10 infinite?: boolean; 11 - params: { 12 - body?: any; 13 - headers?: any; 14 - path?: any; 15 - query?: any; 16 - }; 11 + params: Pick<TOptions, "body" | "headers" | "path" | "query">; 17 12 scope: string; 18 13 } 19 14 ]; 20 15 21 - const createQueryKeyParams = <T>(options?: Options<T>) => { 22 - const params: QueryKey[0]["params"] = {}; 16 + const createQueryKeyParams = <TOptions extends Options>(options?: TOptions): QueryKey<TOptions>[0]["params"] => { 17 + const params: QueryKey<TOptions>[0]["params"] = {} as QueryKey<TOptions>[0]["params"]; 23 18 if (options?.body) { 24 19 params.body = options.body; 25 20 } ··· 251 246 ] 252 247 }); }; 253 248 254 - export const callWithParametersInfiniteOptions = (options: Options<CallWithParametersData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey, unknown>( 249 + export const callWithParametersInfiniteOptions = (options: Options<CallWithParametersData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey<Options<CallWithParametersData>>, string | QueryKey<Options<CallWithParametersData>>[0]['params']>( 255 250 // @ts-ignore 256 251 { 257 252 queryFn: async ({ pageParam, queryKey }) => { 253 + // @ts-ignore 254 + const page: QueryKey<Options<CallWithParametersData>>[0]['params'] = typeof pageParam === "object" ? pageParam : { 255 + query: { 256 + cursor: pageParam 257 + } 258 + }; 258 259 const { data } = await callWithParameters({ 259 260 ...options, 260 - ...queryKey[0].params, 261 + body: { 262 + ...queryKey[0].params.body as any, 263 + ...page.body as any 264 + }, 265 + headers: { 266 + ...queryKey[0].params.headers, 267 + ...page.headers 268 + }, 269 + path: { 270 + ...queryKey[0].params.path, 271 + ...page.path 272 + }, 261 273 query: { 262 274 ...queryKey[0].params.query, 263 - cursor: pageParam 275 + ...page.query 264 276 }, 265 277 throwOnError: true 266 278 }); ··· 329 341 ] 330 342 }); }; 331 343 332 - export const getCallWithOptionalParamInfiniteOptions = (options: Options<GetCallWithOptionalParamData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey, unknown>( 344 + export const getCallWithOptionalParamInfiniteOptions = (options: Options<GetCallWithOptionalParamData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey<Options<GetCallWithOptionalParamData>>, number | QueryKey<Options<GetCallWithOptionalParamData>>[0]['params']>( 333 345 // @ts-ignore 334 346 { 335 347 queryFn: async ({ pageParam, queryKey }) => { 348 + // @ts-ignore 349 + const page: QueryKey<Options<GetCallWithOptionalParamData>>[0]['params'] = typeof pageParam === "object" ? pageParam : { 350 + query: { 351 + page: pageParam 352 + } 353 + }; 336 354 const { data } = await getCallWithOptionalParam({ 337 355 ...options, 338 - ...queryKey[0].params, 356 + body: { 357 + ...queryKey[0].params.body as any, 358 + ...page.body as any 359 + }, 360 + headers: { 361 + ...queryKey[0].params.headers, 362 + ...page.headers 363 + }, 364 + path: { 365 + ...queryKey[0].params.path, 366 + ...page.path 367 + }, 339 368 query: { 340 369 ...queryKey[0].params.query, 341 - page: pageParam 370 + ...page.query 342 371 }, 343 372 throwOnError: true 344 373 }); ··· 370 399 ] 371 400 }); }; 372 401 373 - export const postCallWithOptionalParamInfiniteOptions = (options: Options<PostCallWithOptionalParamData>) => { return infiniteQueryOptions<PostCallWithOptionalParamResponse, PostCallWithOptionalParamError, InfiniteData<PostCallWithOptionalParamResponse>, QueryKey, unknown>( 402 + export const postCallWithOptionalParamInfiniteOptions = (options: Options<PostCallWithOptionalParamData>) => { return infiniteQueryOptions<PostCallWithOptionalParamResponse, PostCallWithOptionalParamError, InfiniteData<PostCallWithOptionalParamResponse>, QueryKey<Options<PostCallWithOptionalParamData>>, number | QueryKey<Options<PostCallWithOptionalParamData>>[0]['params']>( 374 403 // @ts-ignore 375 404 { 376 405 queryFn: async ({ pageParam, queryKey }) => { 406 + // @ts-ignore 407 + const page: QueryKey<Options<PostCallWithOptionalParamData>>[0]['params'] = typeof pageParam === "object" ? pageParam : { 408 + body: { 409 + offset: pageParam 410 + } 411 + }; 377 412 const { data } = await postCallWithOptionalParam({ 378 413 ...options, 379 - ...queryKey[0].params, 380 414 body: { 381 - ...queryKey[0].params.body, 382 - offset: pageParam 415 + ...queryKey[0].params.body as any, 416 + ...page.body as any 417 + }, 418 + headers: { 419 + ...queryKey[0].params.headers, 420 + ...page.headers 421 + }, 422 + path: { 423 + ...queryKey[0].params.path, 424 + ...page.path 425 + }, 426 + query: { 427 + ...queryKey[0].params.query, 428 + ...page.query 383 429 }, 384 430 throwOnError: true 385 431 });
+4 -9
packages/openapi-ts/test/__snapshots__/test/generated/v3-hey-api-client-axios-plugin-tanstack-react-query_transform/@tanstack/query.gen.ts.snap
··· 5 5 import { parentModelWithDates, modelWithDates, modelWithDatesArray, arrayOfDates, date, multipleResponses } from '../services.gen'; 6 6 import type { ParentModelWithDatesError, ParentModelWithDatesResponse, ModelWithDatesError, ModelWithDatesResponse, ModelWithDatesArrayError, ModelWithDatesArrayResponse, ArrayOfDatesError, ArrayOfDatesResponse, DateError, DateResponse, MultipleResponsesError, MultipleResponsesResponse } from '../types.gen'; 7 7 8 - type QueryKey = [ 8 + type QueryKey<TOptions extends Options> = [ 9 9 { 10 10 infinite?: boolean; 11 - params: { 12 - body?: any; 13 - headers?: any; 14 - path?: any; 15 - query?: any; 16 - }; 11 + params: Pick<TOptions, "body" | "headers" | "path" | "query">; 17 12 scope: string; 18 13 } 19 14 ]; 20 15 21 - const createQueryKeyParams = <T>(options?: Options<T>) => { 22 - const params: QueryKey[0]["params"] = {}; 16 + const createQueryKeyParams = <TOptions extends Options>(options?: TOptions): QueryKey<TOptions>[0]["params"] => { 17 + const params: QueryKey<TOptions>[0]["params"] = {} as QueryKey<TOptions>[0]["params"]; 23 18 if (options?.body) { 24 19 params.body = options.body; 25 20 }
+65 -19
packages/openapi-ts/test/__snapshots__/test/generated/v3-hey-api-client-fetch-plugin-tanstack-react-query/@tanstack/query.gen.ts.snap
··· 5 5 import { export_, import_, apiVVersionOdataControllerCount, getCallWithoutParametersAndResponse, putCallWithoutParametersAndResponse, postCallWithoutParametersAndResponse, deleteCallWithoutParametersAndResponse, patchCallWithoutParametersAndResponse, deleteFoo, callWithDescriptions, deprecatedCall, callWithParameters, callWithWeirdParameterNames, getCallWithOptionalParam, postCallWithOptionalParam, postApiVbyApiVersionRequestBody, postApiVbyApiVersionFormData, callWithDefaultParameters, callWithDefaultOptionalParameters, callToTestOrderOfParams, duplicateName, duplicateName1, duplicateName2, duplicateName3, callWithNoContentResponse, callWithResponseAndNoContentResponse, dummyA, dummyB, callWithResponse, callWithDuplicateResponses, callWithResponses, collectionFormat, types, uploadFile, fileResponse, complexTypes, multipartRequest, multipartResponse, complexParams, callWithResultFromHeader, testErrorCode, nonAsciiæøåÆøÅöôêÊ字符串, putWithFormUrlEncoded } from '../services.gen'; 6 6 import type { ImportData, ImportError, ImportResponse, DeleteFooData3, CallWithDescriptionsData, DeprecatedCallData, CallWithParametersData, CallWithWeirdParameterNamesData, GetCallWithOptionalParamData, PostCallWithOptionalParamData, PostCallWithOptionalParamError, PostCallWithOptionalParamResponse, PostApiVbyApiVersionRequestBodyData, PostApiVbyApiVersionFormDataData, CallWithDefaultParametersData, CallWithDefaultOptionalParametersData, CallToTestOrderOfParamsData, CallWithDuplicateResponsesError, CallWithDuplicateResponsesResponse, CallWithResponsesError, CallWithResponsesResponse, CollectionFormatData, TypesData, UploadFileData, UploadFileError, UploadFileResponse, FileResponseData, ComplexTypesData, MultipartRequestData, ComplexParamsError, ComplexParamsData, ComplexParamsResponse, CallWithResultFromHeaderError, CallWithResultFromHeaderResponse, TestErrorCodeData, TestErrorCodeError, TestErrorCodeResponse, NonAsciiæøåÆøÅöôêÊ字符串Data, NonAsciiæøåÆøÅöôêÊ字符串Error, NonAsciiæøåÆøÅöôêÊ字符串Response, PutWithFormUrlEncodedData } from '../types.gen'; 7 7 8 - type QueryKey = [ 8 + type QueryKey<TOptions extends Options> = [ 9 9 { 10 10 infinite?: boolean; 11 - params: { 12 - body?: any; 13 - headers?: any; 14 - path?: any; 15 - query?: any; 16 - }; 11 + params: Pick<TOptions, "body" | "headers" | "path" | "query">; 17 12 scope: string; 18 13 } 19 14 ]; 20 15 21 - const createQueryKeyParams = <T>(options?: Options<T>) => { 22 - const params: QueryKey[0]["params"] = {}; 16 + const createQueryKeyParams = <TOptions extends Options>(options?: TOptions): QueryKey<TOptions>[0]["params"] => { 17 + const params: QueryKey<TOptions>[0]["params"] = {} as QueryKey<TOptions>[0]["params"]; 23 18 if (options?.body) { 24 19 params.body = options.body; 25 20 } ··· 251 246 ] 252 247 }); }; 253 248 254 - export const callWithParametersInfiniteOptions = (options: Options<CallWithParametersData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey, unknown>( 249 + export const callWithParametersInfiniteOptions = (options: Options<CallWithParametersData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey<Options<CallWithParametersData>>, string | QueryKey<Options<CallWithParametersData>>[0]['params']>( 255 250 // @ts-ignore 256 251 { 257 252 queryFn: async ({ pageParam, queryKey }) => { 253 + // @ts-ignore 254 + const page: QueryKey<Options<CallWithParametersData>>[0]['params'] = typeof pageParam === "object" ? pageParam : { 255 + query: { 256 + cursor: pageParam 257 + } 258 + }; 258 259 const { data } = await callWithParameters({ 259 260 ...options, 260 - ...queryKey[0].params, 261 + body: { 262 + ...queryKey[0].params.body as any, 263 + ...page.body as any 264 + }, 265 + headers: { 266 + ...queryKey[0].params.headers, 267 + ...page.headers 268 + }, 269 + path: { 270 + ...queryKey[0].params.path, 271 + ...page.path 272 + }, 261 273 query: { 262 274 ...queryKey[0].params.query, 263 - cursor: pageParam 275 + ...page.query 264 276 }, 265 277 throwOnError: true 266 278 }); ··· 329 341 ] 330 342 }); }; 331 343 332 - export const getCallWithOptionalParamInfiniteOptions = (options: Options<GetCallWithOptionalParamData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey, unknown>( 344 + export const getCallWithOptionalParamInfiniteOptions = (options: Options<GetCallWithOptionalParamData>) => { return infiniteQueryOptions<void, DefaultError, InfiniteData<void>, QueryKey<Options<GetCallWithOptionalParamData>>, number | QueryKey<Options<GetCallWithOptionalParamData>>[0]['params']>( 333 345 // @ts-ignore 334 346 { 335 347 queryFn: async ({ pageParam, queryKey }) => { 348 + // @ts-ignore 349 + const page: QueryKey<Options<GetCallWithOptionalParamData>>[0]['params'] = typeof pageParam === "object" ? pageParam : { 350 + query: { 351 + page: pageParam 352 + } 353 + }; 336 354 const { data } = await getCallWithOptionalParam({ 337 355 ...options, 338 - ...queryKey[0].params, 356 + body: { 357 + ...queryKey[0].params.body as any, 358 + ...page.body as any 359 + }, 360 + headers: { 361 + ...queryKey[0].params.headers, 362 + ...page.headers 363 + }, 364 + path: { 365 + ...queryKey[0].params.path, 366 + ...page.path 367 + }, 339 368 query: { 340 369 ...queryKey[0].params.query, 341 - page: pageParam 370 + ...page.query 342 371 }, 343 372 throwOnError: true 344 373 }); ··· 370 399 ] 371 400 }); }; 372 401 373 - export const postCallWithOptionalParamInfiniteOptions = (options: Options<PostCallWithOptionalParamData>) => { return infiniteQueryOptions<PostCallWithOptionalParamResponse, PostCallWithOptionalParamError, InfiniteData<PostCallWithOptionalParamResponse>, QueryKey, unknown>( 402 + export const postCallWithOptionalParamInfiniteOptions = (options: Options<PostCallWithOptionalParamData>) => { return infiniteQueryOptions<PostCallWithOptionalParamResponse, PostCallWithOptionalParamError, InfiniteData<PostCallWithOptionalParamResponse>, QueryKey<Options<PostCallWithOptionalParamData>>, number | QueryKey<Options<PostCallWithOptionalParamData>>[0]['params']>( 374 403 // @ts-ignore 375 404 { 376 405 queryFn: async ({ pageParam, queryKey }) => { 406 + // @ts-ignore 407 + const page: QueryKey<Options<PostCallWithOptionalParamData>>[0]['params'] = typeof pageParam === "object" ? pageParam : { 408 + body: { 409 + offset: pageParam 410 + } 411 + }; 377 412 const { data } = await postCallWithOptionalParam({ 378 413 ...options, 379 - ...queryKey[0].params, 380 414 body: { 381 - ...queryKey[0].params.body, 382 - offset: pageParam 415 + ...queryKey[0].params.body as any, 416 + ...page.body as any 417 + }, 418 + headers: { 419 + ...queryKey[0].params.headers, 420 + ...page.headers 421 + }, 422 + path: { 423 + ...queryKey[0].params.path, 424 + ...page.path 425 + }, 426 + query: { 427 + ...queryKey[0].params.query, 428 + ...page.query 383 429 }, 384 430 throwOnError: true 385 431 });
+4 -9
packages/openapi-ts/test/__snapshots__/test/generated/v3-hey-api-client-fetch-plugin-tanstack-react-query_transform/@tanstack/query.gen.ts.snap
··· 5 5 import { parentModelWithDates, modelWithDates, modelWithDatesArray, arrayOfDates, date, multipleResponses } from '../services.gen'; 6 6 import type { ParentModelWithDatesError, ParentModelWithDatesResponse, ModelWithDatesError, ModelWithDatesResponse, ModelWithDatesArrayError, ModelWithDatesArrayResponse, ArrayOfDatesError, ArrayOfDatesResponse, DateError, DateResponse, MultipleResponsesError, MultipleResponsesResponse } from '../types.gen'; 7 7 8 - type QueryKey = [ 8 + type QueryKey<TOptions extends Options> = [ 9 9 { 10 10 infinite?: boolean; 11 - params: { 12 - body?: any; 13 - headers?: any; 14 - path?: any; 15 - query?: any; 16 - }; 11 + params: Pick<TOptions, "body" | "headers" | "path" | "query">; 17 12 scope: string; 18 13 } 19 14 ]; 20 15 21 - const createQueryKeyParams = <T>(options?: Options<T>) => { 22 - const params: QueryKey[0]["params"] = {}; 16 + const createQueryKeyParams = <TOptions extends Options>(options?: TOptions): QueryKey<TOptions>[0]["params"] => { 17 + const params: QueryKey<TOptions>[0]["params"] = {} as QueryKey<TOptions>[0]["params"]; 23 18 if (options?.body) { 24 19 params.body = options.body; 25 20 }