├── .editorconfig ├── .eslintignore ├── .gitattributes ├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ └── codeStyleConfig.xml ├── modules.xml ├── nswag-react-query.iml ├── prettier.xml ├── vcs.xml └── watcherTasks.xml ├── .prettierignore ├── .prettierrc.js ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── examples ├── pet-client-angular │ ├── .gitignore │ ├── angular.json │ ├── package.json │ ├── src │ │ ├── api │ │ │ ├── axios-client.ts │ │ │ ├── axios-client.types.ts │ │ │ ├── axios-client │ │ │ │ ├── Client.ts │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ └── index.ts │ │ ├── global_styles.css │ │ ├── index.html │ │ ├── karma.conf.js │ │ ├── main.ts │ │ ├── todos.service.ts │ │ ├── tsconfig.app.json │ │ └── tsconfig.spec.json │ └── tsconfig.json ├── pet-client-v3 │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .prettierrc.js │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── api │ │ │ ├── axios-client-recommended.ts │ │ │ ├── axios-client-recommended │ │ │ │ ├── Client.ts │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── axios-client.ts │ │ │ ├── axios-client │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── fetch-client.ts │ │ │ ├── fetch-client │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ └── index.ts │ │ ├── components │ │ │ └── PetsList.tsx │ │ ├── index.css │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ └── tsconfig.json ├── pet-client-vue │ ├── .gitignore │ ├── .vscode │ │ └── extensions.json │ ├── README.md │ ├── env.d.ts │ ├── index.html │ ├── package.json │ ├── public │ │ └── favicon.ico │ ├── src │ │ ├── App.vue │ │ ├── api │ │ │ ├── axios-client-minimal.ts │ │ │ ├── axios-client-minimal.types.ts │ │ │ ├── axios-client-minimal │ │ │ │ ├── Client.ts │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── axios-client.js │ │ │ ├── axios-client.ts │ │ │ ├── axios-client │ │ │ │ ├── Client.ts │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── index.js │ │ │ └── index.ts │ │ ├── assets │ │ │ ├── base.css │ │ │ ├── logo.svg │ │ │ └── main.css │ │ ├── main.js │ │ └── main.ts │ ├── tsconfig.config.json │ ├── tsconfig.json │ └── vite.config.ts ├── pet-client │ ├── .eslintignore │ ├── .eslintrc.js │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── Infinite.tsx │ │ ├── api │ │ │ ├── axios-client-minimal-no-hooks.ts │ │ │ ├── axios-client-minimal-no-hooks.types.ts │ │ │ ├── axios-client-minimal-no-hooks │ │ │ │ ├── Client.ts │ │ │ │ └── helpers.ts │ │ │ ├── axios-client-minimal-sample.ts │ │ │ ├── axios-client-minimal-sample.types.ts │ │ │ ├── axios-client-minimal-sample │ │ │ │ ├── ArrayReturnClient.ts │ │ │ │ ├── ArrayReturnQuery.ts │ │ │ │ ├── DictionaryArrayReturnClient.ts │ │ │ │ ├── DictionaryArrayReturnQuery.ts │ │ │ │ ├── DictionaryReturnClient.ts │ │ │ │ ├── DictionaryReturnQuery.ts │ │ │ │ ├── PostClient.ts │ │ │ │ ├── PostQuery.ts │ │ │ │ ├── PrimitiveReturnClient.ts │ │ │ │ ├── PrimitiveReturnQuery.ts │ │ │ │ ├── QueryClient.ts │ │ │ │ ├── QueryQuery.ts │ │ │ │ └── helpers.ts │ │ │ ├── axios-client-minimal.ts │ │ │ ├── axios-client-minimal.types.ts │ │ │ ├── axios-client-minimal │ │ │ │ ├── Client.ts │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── axios-client-no-split.ts │ │ │ ├── axios-client-no-split │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── axios-client.ts │ │ │ ├── axios-client │ │ │ │ ├── Client.ts │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── fetch-client.ts │ │ │ ├── fetch-client │ │ │ │ ├── Query.ts │ │ │ │ └── helpers.ts │ │ │ ├── index.ts │ │ │ ├── no-hooks-client-axios.ts │ │ │ ├── no-hooks-client-axios │ │ │ │ ├── Client.ts │ │ │ │ └── helpers.ts │ │ │ ├── no-hooks-client.ts │ │ │ ├── no-hooks-client │ │ │ │ ├── Client.ts │ │ │ │ └── helpers.ts │ │ │ ├── no-hooks-no-modules.ts │ │ │ └── no-hooks-no-modules │ │ │ │ └── helpers.ts │ │ ├── components │ │ │ └── PetsList.tsx │ │ ├── index.css │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ ├── swagger.json │ └── tsconfig.json └── server │ └── DemoSwagger │ ├── .idea │ └── .idea.DemoSwagger │ │ └── .idea │ │ ├── .gitignore │ │ ├── CSharpierPlugin.xml │ │ ├── encodings.xml │ │ ├── indexLayout.xml │ │ └── vcs.xml │ ├── Controllers │ ├── ArrayReturnController.cs │ ├── DictionaryArrayReturnController.cs │ ├── DictionaryReturnController.cs │ ├── Dto │ │ ├── DummyDto.cs │ │ └── JsonInNestedDto.cs │ ├── PostController.cs │ ├── PrimitiveReturnController.cs │ └── QueryController.cs │ ├── DemoSwagger.csproj │ ├── DemoSwagger.sln │ ├── FromQueryJson │ ├── FromJsonQueryAttribute.cs │ ├── JsonQueryBinder.cs │ ├── JsonQueryNSwagOperationProcessor.cs │ └── JsonQuerySwaggerGenExtensions.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── appsettings.Development.json │ └── appsettings.json ├── package.json ├── scripts ├── patch-vue-templates.mjs └── update-nswag-templates.mjs ├── src ├── cli.js ├── package.json ├── src │ ├── QueryMetaProvider.tsx │ └── index.ts ├── templates │ ├── AxiosClient.liquid │ ├── Client.RequestBody.Serialize.liquid │ ├── Client.RequestUrl.liquid │ ├── ClientFileHeader.liquid │ ├── ConvertToClass.liquid │ ├── FetchClient.liquid │ ├── File.liquid │ ├── JsonParseReviver.liquid │ ├── PersistorHydrator.AddResultTypeFactory.liquid │ ├── PersistorHydrator.File.liquid │ ├── PersistorHydrator.liquid │ ├── ReactQuery.Imports.liquid │ ├── ReactQuery.MetaFile.liquid │ ├── ReactQuery.MetaFileFunctions.liquid │ ├── ReactQuery.liquid │ ├── ReactQueryFile.liquid │ ├── _File.liquid │ ├── modules │ │ ├── AxiosClient.liquid │ │ ├── AxiosClient_RequestConfig.liquid │ │ ├── Client.ProcessResponse.HandleStatusCode.liquid │ │ ├── Client.ProcessResponse.Return.liquid │ │ ├── Client.RequestBody.Serialize.liquid │ │ ├── Client.RequestBody.liquid │ │ ├── FetchClient.liquid │ │ ├── OperationNameSafe.liquid │ │ ├── ReactQuery.GetClientCall.liquid │ │ ├── ReactQuery.GetClientFactory.liquid │ │ └── ReactQuery.GetClientFunction.liquid │ └── original │ │ ├── AxiosClient.liquid │ │ ├── AxiosClient_RequestConfig.liquid │ │ ├── Client.ProcessResponse.HandleStatusCode.liquid │ │ ├── Client.ProcessResponse.Return.liquid │ │ ├── Client.RequestBody.liquid │ │ ├── FetchClient.liquid │ │ ├── OperationNameSafe.liquid │ │ ├── ReactQuery.GetClientCall.liquid │ │ ├── ReactQuery.GetClientFactory.liquid │ │ └── ReactQuery.GetClientFunction.liquid ├── templates_minimal │ ├── Class.liquid │ ├── ConvertToClass.liquid │ ├── ConvertToJavaScript.liquid │ ├── File.liquid │ ├── Interface.liquid │ ├── PersistorHydrator.AddResultTypeFactory.liquid │ └── modules │ │ └── Client.RequestBody.Serialize.liquid ├── templates_minimal_angular │ ├── PersistorHydrator.File.liquid │ ├── PersistorHydrator.liquid │ ├── ReactQuery.Imports.liquid │ ├── ReactQuery.MetaFile.liquid │ └── ReactQuery.MetaFileFunctions.liquid ├── templates_minimal_no_hooks │ ├── PersistorHydrator.File.liquid │ ├── PersistorHydrator.liquid │ ├── ReactQuery.Imports.liquid │ ├── ReactQuery.MetaFile.liquid │ ├── ReactQuery.MetaFileFunctions.liquid │ └── ReactQuery.liquid ├── templates_no_hooks │ ├── AxiosClient.liquid │ ├── FetchClient.liquid │ ├── File.liquid │ ├── ReactQuery.MetaFile.liquid │ ├── ReactQuery.MetaFileFunctions.liquid │ ├── ReactQuery.liquid │ └── ReactQueryFile.liquid ├── templates_v3 │ ├── File.liquid │ ├── PersistorHydrator.liquid │ ├── ReactQuery.Imports.liquid │ ├── ReactQuery.MetaFile.liquid │ ├── ReactQuery.MetaFileFunctions.liquid │ ├── ReactQuery.liquid │ └── ReactQueryFile.liquid ├── templates_vue │ ├── AxiosClient.liquid │ ├── File.liquid │ ├── ReactQuery.Imports.liquid │ ├── ReactQuery.MetaFile.liquid │ ├── ReactQuery.MetaFileFunctions.liquid │ ├── ReactQuery.liquid │ └── ReactQueryFile.liquid └── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 3 | node_modules 4 | 5 | package.json 6 | **/package.json 7 | **/build/** 8 | .idea 9 | .vscode 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.liquid text eol=lf 2 | *.ts text eol=lf 3 | *.tsx text eol=lf 4 | *.js text eol=lf 5 | *.json text eol=lf 6 | *.md text eol=lf 7 | *.css text eol=lf 8 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/nswag-react-query.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/prettier.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/watcherTasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 24 | 25 | 36 | 44 | 45 | 56 | 64 | 65 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/axios-client.ts 2 | **/fetch-client.ts 3 | **/Client.ts 4 | **/Query.ts -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | trailingComma: 'all', 4 | singleQuote: true, 5 | printWidth: 80, 6 | tabWidth: 2, 7 | proseWrap: 'never', 8 | endOfLine: 'auto', 9 | }; 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": true, 3 | "eslint.alwaysShowStatus": true, 4 | "eslint.debug": true, 5 | "eslint.format.enable": true, 6 | "eslint.packageManager": "yarn", 7 | "editor.formatOnSave": true, 8 | "editor.defaultFormatter": "esbenp.prettier-vscode", 9 | 10 | "git.pullTags": false, 11 | "git.rebaseWhenSync": true, 12 | "git.autoStash": true, 13 | "git.branchPrefix": "feature/", 14 | "git.fetchOnPull": true, 15 | "git.showActionButton": { 16 | // "sync": false 17 | }, 18 | "git.showPushSuccessNotification": true, 19 | "csharp.format.enable": true 20 | } 21 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 15.8.1 4 | 5 | Update to NSwag 13.19.0 and NJsonSchema 11.0.0 6 | 7 | ## 15.7.1 8 | 9 | Support JSON-serialized parameters in Query (see https://swagger.io/docs/specification/describing-parameters/#schema-vs-content) 10 | 11 | ## 15.6.7 12 | 13 | Use portable version of NSwag, so it's not required to have .NET installed anymore 14 | 15 | 15.6.1-15.6.6 were broken, please do NOT use them. 16 | 17 | ## 15.5.1 18 | 19 | New `/minimal` switch is introduced. 20 | 21 | It generates `Interfaces` instead of `Classes`, which minimizes the bundle size (since Interfaces are stripped off during bundling). 22 | 23 | This mode is experimental and is being tested at the moment. 24 | 25 | If you want to convert large codebase to use the `/minimal` switch, here are two regexes that helped me do that (of course there'd be still a lot of things you'd need to convert manually): 26 | 27 | - "`new \S*Dto\(([\s\S\r\n]+?)\)`" -> "`$1`" 28 | - "`I(\S*Dto)`" -> "`$1`" 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Artur Drobinskiy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/pet-client-angular/.gitignore: -------------------------------------------------------------------------------- 1 | .angular 2 | dist 3 | node_modules 4 | -------------------------------------------------------------------------------- /examples/pet-client-angular/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "cli": { 4 | "analytics": "1e1de97b-a744-405a-8b5a-0397bb3d01ce" 5 | }, 6 | "newProjectRoot": "projects", 7 | "projects": { 8 | "demo": { 9 | "architect": { 10 | "build": { 11 | "builder": "@angular-devkit/build-angular:application", 12 | "configurations": { 13 | "development": { 14 | "extractLicenses": false, 15 | "namedChunks": true, 16 | "optimization": false, 17 | "sourceMap": true 18 | }, 19 | "production": { 20 | "aot": true, 21 | "extractLicenses": true, 22 | "namedChunks": false, 23 | "optimization": true, 24 | "outputHashing": "all", 25 | "sourceMap": false 26 | } 27 | }, 28 | "options": { 29 | "assets": [], 30 | "index": "src/index.html", 31 | "browser": "src/main.ts", 32 | "outputPath": "dist/demo", 33 | "scripts": [], 34 | "styles": [ 35 | "src/global_styles.css" 36 | ], 37 | "tsConfig": "src/tsconfig.app.json" 38 | } 39 | }, 40 | "extract-i18n": { 41 | "builder": "@angular-devkit/build-angular:extract-i18n", 42 | "options": { 43 | "browserTarget": "demo:build" 44 | } 45 | }, 46 | "lint": { 47 | "builder": "@angular-devkit/build-angular:tslint", 48 | "options": { 49 | "exclude": [ 50 | "**/node_modules/**" 51 | ], 52 | "tsConfig": [ 53 | "src/tsconfig.app.json", 54 | "src/tsconfig.spec.json" 55 | ] 56 | } 57 | }, 58 | "serve": { 59 | "builder": "@angular-devkit/build-angular:dev-server", 60 | "configurations": { 61 | "development": { 62 | "buildTarget": "demo:build:development" 63 | }, 64 | "production": { 65 | "buildTarget": "demo:build:production" 66 | } 67 | }, 68 | "defaultConfiguration": "development" 69 | }, 70 | "test": { 71 | "builder": "@angular-devkit/build-angular:karma", 72 | "options": { 73 | "assets": [ 74 | "src/favicon.ico", 75 | "src/assets" 76 | ], 77 | "karmaConfig": "src/karma.conf.js", 78 | "main": "src/test.ts", 79 | "polyfills": [ 80 | "zone.js", 81 | ".zone.js/testing" 82 | ], 83 | "scripts": [], 84 | "styles": [ 85 | "styles.css" 86 | ], 87 | "tsConfig": "src/tsconfig.spec.json" 88 | } 89 | } 90 | }, 91 | "prefix": "app", 92 | "projectType": "application", 93 | "root": "", 94 | "schematics": {}, 95 | "sourceRoot": "src" 96 | } 97 | }, 98 | "version": 1 99 | } -------------------------------------------------------------------------------- /examples/pet-client-angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pet-client-angular", 3 | "version": "0.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "@angular/animations": "17.1.1", 7 | "@angular/common": "17.1.1", 8 | "@angular/compiler": "17.1.1", 9 | "@angular/core": "17.1.1", 10 | "@angular/forms": "17.1.1", 11 | "@angular/platform-browser": "17.1.1", 12 | "@angular/router": "17.1.1", 13 | "@ngneat/query": "2.0.0-beta.10", 14 | "@tanstack/query-core": "5.17.19", 15 | "react-query-swagger": "link:../../src", 16 | "rxjs": "7.8.1", 17 | "tslib": "2.6.2", 18 | "zone.js": "0.14.3" 19 | }, 20 | "scripts": { 21 | "ng": "ng", 22 | "start": "ng serve --port 4410", 23 | "build": "ng build", 24 | "test": "ng test", 25 | "lint": "ng lint", 26 | "typecheck": "tsc --noEmit --skipLibCheck", 27 | "generate-axios": "react-query-swagger /angular /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client.ts /template:Axios /serviceHost:.", 28 | "e2e": "ng e2e" 29 | }, 30 | "devDependencies": { 31 | "@angular-devkit/build-angular": "17.1.1", 32 | "@angular/cli": "17.1.1", 33 | "@angular/compiler-cli": "17.1.1", 34 | "@types/jasmine": "5.1.4", 35 | "@types/node": "20.11.8", 36 | "codelyzer": "6.0.2", 37 | "jasmine-core": "5.1.1", 38 | "jasmine-spec-reporter": "7.0.0", 39 | "karma": "6.4.2", 40 | "karma-chrome-launcher": "3.2.0", 41 | "karma-coverage": "2.2.1", 42 | "karma-jasmine": "5.1.0", 43 | "karma-jasmine-html-reporter": "2.1.0", 44 | "protractor": "7.0.0", 45 | "ts-node": "10.9.2", 46 | "tslint": "6.1.3", 47 | "typescript": "5.5.3" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/api/axios-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { injectQuery, injectMutation, QueryClient } from '@ngneat/query'; 3 | import { Observable } from 'rxjs'; 4 | import type { UndefinedInitialDataOptions } from '@ngneat/query/lib/query-options'; 5 | import type { Optional } from 'react-query-swagger'; 6 | import type { Result } from '@ngneat/query/lib/types'; 7 | import type { QueryFunctionContext, QueryObserverResult, DefaultError, MutationKey, MutateOptions, MutationObserver, MutationObserverOptions, MutationObserverResult, QueryKey } from '@tanstack/query-core'; 8 | type UseQueryResult = Result>; 9 | export type CreateMutationOptions = Omit, 'mutationFn'> & { 10 | mutationFn?: (variables: TVariables) => Promise | Observable; 11 | }; 12 | type UseMutationResultFn = ReturnType; 13 | type UseMutationResult = ReturnType; 14 | 15 | import axios from 'axios'; 16 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 17 | 18 | const _resultTypesByQueryKey: Record any> = {}; 19 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 20 | _resultTypesByQueryKey[typeName] = factory; 21 | } 22 | export function getResultTypeFactory(typeName: string) { 23 | return _resultTypesByQueryKey[typeName]; 24 | } 25 | 26 | export function trimArrayEnd(arr: T[]): T[] { 27 | let lastDefinedValueIndex = arr.length - 1; 28 | while (lastDefinedValueIndex >= 0) { 29 | if (arr[lastDefinedValueIndex] === undefined) { 30 | lastDefinedValueIndex--; 31 | } else { 32 | break; 33 | } 34 | } 35 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 36 | } 37 | 38 | /* 39 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 40 | Returns true if parameter is Object 41 | Returns false if parameter is number/string/boolean/Date or Array 42 | */ 43 | export function isParameterObject(param: unknown) { 44 | if (param === null || param === undefined) return false; 45 | if (param instanceof Array) return false; 46 | const isObject = typeof param === 'object'; 47 | if (!isObject) return false; 48 | if (param instanceof Date) return false; 49 | return true; 50 | } 51 | 52 | let _baseUrl = ''; 53 | /* 54 | Returns the base URL for http requests 55 | */ 56 | export function getBaseUrl(): string { 57 | return _baseUrl; 58 | } 59 | 60 | /* 61 | Sets the base URL for http requests 62 | */ 63 | export function setBaseUrl(baseUrl: string) { 64 | _baseUrl = baseUrl; 65 | } 66 | 67 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 68 | /* 69 | Returns an instance of Axios either created by a configured factory or a default one 70 | */ 71 | export function getAxios() { 72 | return _axiosFactory?.() ?? axios; 73 | } 74 | /* 75 | Sets the factory for Axios instances 76 | */ 77 | export function setAxiosFactory(factory: () => AxiosInstance) { 78 | _axiosFactory = factory; 79 | } 80 | 81 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client-angular/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import * as AxiosQuery from './axios-client'; 2 | 3 | export { AxiosQuery }; 4 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/global_styles.css: -------------------------------------------------------------------------------- 1 | /* Add application styles & imports to this file! */ 2 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My app 5 | 6 | 7 | 8 | Loading... 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma'), 14 | ], 15 | client: { 16 | clearContext: false, // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, './coverage/my-app'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true, 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true, 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import 'zone.js'; 2 | import { Component, inject } from '@angular/core'; 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | import { provideHttpClient } from '@angular/common/http'; 5 | import { TodosService, getToDos } from './todos.service'; 6 | import { CommonModule } from '@angular/common'; 7 | import { AxiosQuery } from './api'; 8 | import { Pet, Status } from './api/axios-client.types'; 9 | import { setBaseUrl } from './api/axios-client'; 10 | AxiosQuery.setBaseUrl('https://petstore.swagger.io/v2'); 11 | 12 | @Component({ 13 | selector: 'app-root', 14 | standalone: true, 15 | imports: [CommonModule], 16 | template: ` 17 |

ngneat/query

18 | 19 |

Signal Result

20 | 21 | @if (todosSignal().isLoading) { Loading... } @if (todosSignal().data; as 22 | data) { 23 |

{{ data[0].name }}

24 | } @if (todosSignal().isError) { 25 |

Error

26 | } 27 | 28 |

Observable Result

29 | 30 | @if (todos.result$ | async; as result) { @if (result.isLoading) { Loading... 31 | } @if (result.isSuccess) { 32 |

{{ result.data[0].name }}

33 | } @if (result.isError) { 34 |

Error

35 | } } 36 | `, 37 | }) 38 | export class App { 39 | todos = AxiosQuery.Query.useFindPetsByStatusQuery({ 40 | status: [Status.Pending, Status.Sold], 41 | }); 42 | todosSignal = this.todos.result; 43 | } 44 | 45 | bootstrapApplication(App, { 46 | providers: [provideHttpClient()], 47 | }); 48 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/todos.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { inject, Injectable } from '@angular/core'; 3 | import { 4 | injectMutation, 5 | injectQuery, 6 | injectQueryClient, 7 | QueryClient, 8 | } from '@ngneat/query'; 9 | 10 | interface Todo { 11 | id: number; 12 | title: string; 13 | } 14 | 15 | export function getToDos() { 16 | const m = injectMutation()({ 17 | mutationFn: async (d) => {}, 18 | }); 19 | const client2: QueryClient = injectQueryClient(); 20 | 21 | const r = injectQuery()<{ q: string }>({ 22 | queryKey: ['a'], 23 | queryFn: (x) => { 24 | return { 25 | q: 'qwe', 26 | }; 27 | }, 28 | }); 29 | 30 | return injectQuery()({ 31 | queryKey: ['todos'] as const, 32 | queryFn: () => { 33 | return inject(HttpClient).get( 34 | 'https://jsonplaceholder.typicode.com/todos', 35 | ); 36 | }, 37 | }); 38 | } 39 | 40 | @Injectable({ providedIn: 'root' }) 41 | export class TodosService { 42 | #query = injectQuery(); 43 | #http = inject(HttpClient); 44 | 45 | getTodos() { 46 | return this.#query({ 47 | queryKey: ['todos'] as const, 48 | queryFn: () => { 49 | return this.#http.get( 50 | 'https://jsonplaceholder.typicode.com/todos', 51 | ); 52 | }, 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": ["main.ts"], 8 | "include": ["**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/pet-client-angular/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "types": ["jasmine", "node"] 6 | }, 7 | "files": ["test.ts"], 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/pet-client-angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "outDir": "./dist/out-tsc", 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "esModuleInterop": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/pet-client-v3/.eslintignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 3 | node_modules 4 | 5 | package.json 6 | **/package.json 7 | **/build/** 8 | .idea 9 | .vscode 10 | -------------------------------------------------------------------------------- /examples/pet-client-v3/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser 3 | parserOptions: { 4 | ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features 5 | sourceType: 'module', // Allows for the use of imports 6 | ecmaFeatures: { 7 | jsx: true, // Allows for the parsing of JSX 8 | }, 9 | }, 10 | settings: { 11 | react: { 12 | version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use 13 | }, 14 | }, 15 | extends: [ 16 | 'plugin:react/recommended', // Uses the recommended rules from @eslint-plugin-react 17 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 18 | ], 19 | rules: { 20 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs 21 | // e.g. "@typescript-eslint/explicit-function-return-type": "off", 22 | 'react/prop-types': 'off', 23 | '@typescript-eslint/no-var-requires': 'off', // since in Electron we have to import styles with require 24 | '@typescript-eslint/no-use-before-define': 'off', // it's quite usual that we define helper functions somewhere at the bottom 25 | '@typescript-eslint/explicit-function-return-type': 'off', // we don't have a rule to specify return type for a function 26 | 'prefer-const': 'off', 27 | 'no-var': 'off', 28 | 'prettier/prettier': 'off', 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /examples/pet-client-v3/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | trailingComma: 'all', 4 | singleQuote: true, 5 | printWidth: 80, 6 | tabWidth: 2, 7 | proseWrap: 'never', 8 | endOfLine: 'auto', 9 | }; 10 | -------------------------------------------------------------------------------- /examples/pet-client-v3/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /examples/pet-client-v3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pet-client-v3", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^29.5.14", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^19.0.8", 12 | "@types/react-dom": "^19.0.3", 13 | "@typescript-eslint/eslint-plugin": "^6.9.1", 14 | "@typescript-eslint/parser": "^6.9.1", 15 | "axios": "^0.26.1", 16 | "eslint-config-prettier": "^8.5.0", 17 | "eslint-plugin-prettier": "^4.2.1", 18 | "react-query-swagger": "link:../../src", 19 | "prettier": "^2.2.1", 20 | "jest": "26.6.0", 21 | "react": "^19.0.0", 22 | "react-dom": "^19.0.0", 23 | "react-query": "3.39.1", 24 | "react-scripts": "5.0.1", 25 | "@types/trusted-types": "2.0.7", 26 | "replace": "1.1.5", 27 | "typescript": "5.5.3", 28 | "web-vitals": "^0.2.4" 29 | }, 30 | "scripts": { 31 | "generate-axios": "react-query-swagger /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client.ts /template:Axios /serviceHost:. /generateConstructorInterface:true /markOptionalProperties:true /generateOptionalParameters:true /nullValue:undefined", 32 | "generate-axios-recommended": "react-query-swagger /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client-recommended.ts /template:Axios /serviceHost:. /use-recommended-configuration", 33 | "generate-axios-date-only-test": "react-query-swagger /input:https://localhost:58627/swagger/v1/swagger.json /output:app/api/api-client.ts /template:Axios /serviceHost:. /generateConstructorInterface:true /generateOptionalParameters:true /markOptionalProperties:true /nullValue:undefined /typeStyle:Class && yarn replace \"this\\.(\\w*?)\\.toISOString\\(\\) : undefined\" \"this.$1.toISOString() : this.$1\" app/api/api-client.ts && yarn replace \"\\| undefined;\" \"| null;\" app/api/api-client.ts", 34 | "generate-fetch": "react-query-swagger /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/fetch-client.ts /template:Fetch /serviceHost:. /generateConstructorInterface:true /markOptionalProperties:true /generateOptionalParameters:true /nullValue:undefined", 35 | "start": "react-scripts start", 36 | "build": "react-scripts build", 37 | "test": "react-scripts test", 38 | "eject": "react-scripts eject" 39 | }, 40 | "eslintConfig": { 41 | "extends": [ 42 | "react-app", 43 | "react-app/jest" 44 | ] 45 | }, 46 | "browserslist": { 47 | "production": [ 48 | ">0.2%", 49 | "not dead", 50 | "not op_mini all" 51 | ], 52 | "development": [ 53 | "last 1 chrome version", 54 | "last 1 firefox version", 55 | "last 1 safari version" 56 | ] 57 | }, 58 | "resolutions": { 59 | "@typescript-eslint/eslint-plugin": "6.9.1", 60 | "@typescript-eslint/parser": "6.9.1" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/pet-client-v3/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client-v3/public/favicon.ico -------------------------------------------------------------------------------- /examples/pet-client-v3/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/pet-client-v3/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client-v3/public/logo192.png -------------------------------------------------------------------------------- /examples/pet-client-v3/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client-v3/public/logo512.png -------------------------------------------------------------------------------- /examples/pet-client-v3/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/pet-client-v3/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/api/axios-client-recommended/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from 'react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from 'react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | import axios from 'axios'; 8 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 9 | 10 | const _resultTypesByQueryKey: Record any> = {}; 11 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 12 | _resultTypesByQueryKey[typeName] = factory; 13 | } 14 | export function getResultTypeFactory(typeName: string) { 15 | return _resultTypesByQueryKey[typeName]; 16 | } 17 | 18 | export function trimArrayEnd(arr: T[]): T[] { 19 | let lastDefinedValueIndex = arr.length - 1; 20 | while (lastDefinedValueIndex >= 0) { 21 | if (arr[lastDefinedValueIndex] === undefined) { 22 | lastDefinedValueIndex--; 23 | } else { 24 | break; 25 | } 26 | } 27 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 28 | } 29 | 30 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 31 | if (metaContext.metaFn) { 32 | options = options ?? { } as any; 33 | options!.meta = { 34 | ...metaContext.metaFn(), 35 | ...options!.meta, 36 | }; 37 | } 38 | return options; 39 | } 40 | /* 41 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 42 | Returns true if parameter is Object 43 | Returns false if parameter is number/string/boolean/Date or Array 44 | */ 45 | export function isParameterObject(param: unknown) { 46 | if (param === null || param === undefined) return false; 47 | if (param instanceof Array) return false; 48 | const isObject = typeof param === 'object'; 49 | if (!isObject) return false; 50 | if (param instanceof Date) return false; 51 | return true; 52 | } 53 | 54 | let _baseUrl = ''; 55 | /* 56 | Returns the base URL for http requests 57 | */ 58 | export function getBaseUrl(): string { 59 | return _baseUrl; 60 | } 61 | 62 | /* 63 | Sets the base URL for http requests 64 | */ 65 | export function setBaseUrl(baseUrl: string) { 66 | _baseUrl = baseUrl; 67 | } 68 | 69 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 70 | /* 71 | Returns an instance of Axios either created by a configured factory or a default one 72 | */ 73 | export function getAxios() { 74 | return _axiosFactory?.() ?? axios; 75 | } 76 | /* 77 | Sets the factory for Axios instances 78 | */ 79 | export function setAxiosFactory(factory: () => AxiosInstance) { 80 | _axiosFactory = factory; 81 | } 82 | 83 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client-v3/src/api/axios-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from 'react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from 'react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | import axios from 'axios'; 8 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 9 | 10 | type ClientFactoryFunction = (type: (new (...params: any[]) => T)) => T; 11 | let _clientFactoryFunction: ClientFactoryFunction = (type: (new (...params: any[]) => T)) => { 12 | const params = [_baseUrl, _axiosFactory()]; 13 | return new type(...params); 14 | }; 15 | /* 16 | Overrides default Client factory function 17 | */ 18 | export function setClientFactory(value: ClientFactoryFunction) { 19 | _clientFactoryFunction = value; 20 | } 21 | 22 | /* 23 | Returns current Client factory function 24 | */ 25 | export function getClientFactory() { 26 | return _clientFactoryFunction; 27 | } 28 | 29 | /* 30 | Function that will be called from `useQuery...` methods to get a client of certain type 31 | */ 32 | export function createClient(type: (new () => T)) { 33 | return _clientFactoryFunction(type); 34 | } 35 | const _resultTypesByQueryKey: Record any> = {}; 36 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 37 | _resultTypesByQueryKey[typeName] = factory; 38 | } 39 | export function getResultTypeFactory(typeName: string) { 40 | return _resultTypesByQueryKey[typeName]; 41 | } 42 | 43 | export function trimArrayEnd(arr: T[]): T[] { 44 | let lastDefinedValueIndex = arr.length - 1; 45 | while (lastDefinedValueIndex >= 0) { 46 | if (arr[lastDefinedValueIndex] === undefined) { 47 | lastDefinedValueIndex--; 48 | } else { 49 | break; 50 | } 51 | } 52 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 53 | } 54 | 55 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 56 | if (metaContext.metaFn) { 57 | options = options ?? { } as any; 58 | options!.meta = { 59 | ...metaContext.metaFn(), 60 | ...options!.meta, 61 | }; 62 | } 63 | return options; 64 | } 65 | /* 66 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 67 | Returns true if parameter is Object 68 | Returns false if parameter is number/string/boolean/Date or Array 69 | */ 70 | export function isParameterObject(param: unknown) { 71 | if (param === null || param === undefined) return false; 72 | if (param instanceof Array) return false; 73 | const isObject = typeof param === 'object'; 74 | if (!isObject) return false; 75 | if (param instanceof Date) return false; 76 | return true; 77 | } 78 | 79 | let _baseUrl = ''; 80 | /* 81 | Returns the base URL for http requests 82 | */ 83 | export function getBaseUrl(): string { 84 | return _baseUrl; 85 | } 86 | 87 | /* 88 | Sets the base URL for http requests 89 | */ 90 | export function setBaseUrl(baseUrl: string) { 91 | _baseUrl = baseUrl; 92 | } 93 | 94 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 95 | /* 96 | Returns an instance of Axios either created by a configured factory or a default one 97 | */ 98 | export function getAxios() { 99 | return _axiosFactory?.() ?? axios; 100 | } 101 | /* 102 | Sets the factory for Axios instances 103 | */ 104 | export function setAxiosFactory(factory: () => AxiosInstance) { 105 | _axiosFactory = factory; 106 | } 107 | 108 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client-v3/src/api/fetch-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from 'react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from 'react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | 8 | type ClientFactoryFunction = (type: (new (...params: any[]) => T)) => T; 9 | let _clientFactoryFunction: ClientFactoryFunction = (type: (new (...params: any[]) => T)) => { 10 | const params = [_baseUrl, _fetchFactory()]; 11 | return new type(...params); 12 | }; 13 | /* 14 | Overrides default Client factory function 15 | */ 16 | export function setClientFactory(value: ClientFactoryFunction) { 17 | _clientFactoryFunction = value; 18 | } 19 | 20 | /* 21 | Returns current Client factory function 22 | */ 23 | export function getClientFactory() { 24 | return _clientFactoryFunction; 25 | } 26 | 27 | /* 28 | Function that will be called from `useQuery...` methods to get a client of certain type 29 | */ 30 | export function createClient(type: (new () => T)) { 31 | return _clientFactoryFunction(type); 32 | }let _jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; 33 | export function getJsonParseReviver() { 34 | return _jsonParseReviver; 35 | } 36 | export function setJsonParseReviver(value: ((key: string, value: any) => any) | undefined) { 37 | _jsonParseReviver = value; 38 | } 39 | const _resultTypesByQueryKey: Record any> = {}; 40 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 41 | _resultTypesByQueryKey[typeName] = factory; 42 | } 43 | export function getResultTypeFactory(typeName: string) { 44 | return _resultTypesByQueryKey[typeName]; 45 | } 46 | 47 | export function trimArrayEnd(arr: T[]): T[] { 48 | let lastDefinedValueIndex = arr.length - 1; 49 | while (lastDefinedValueIndex >= 0) { 50 | if (arr[lastDefinedValueIndex] === undefined) { 51 | lastDefinedValueIndex--; 52 | } else { 53 | break; 54 | } 55 | } 56 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 57 | } 58 | 59 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 60 | if (metaContext.metaFn) { 61 | options = options ?? { } as any; 62 | options!.meta = { 63 | ...metaContext.metaFn(), 64 | ...options!.meta, 65 | }; 66 | } 67 | return options; 68 | } 69 | /* 70 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 71 | Returns true if parameter is Object 72 | Returns false if parameter is number/string/boolean/Date or Array 73 | */ 74 | export function isParameterObject(param: unknown) { 75 | if (param === null || param === undefined) return false; 76 | if (param instanceof Array) return false; 77 | const isObject = typeof param === 'object'; 78 | if (!isObject) return false; 79 | if (param instanceof Date) return false; 80 | return true; 81 | } 82 | 83 | let _baseUrl = ''; 84 | /* 85 | Returns the base URL for http requests 86 | */ 87 | export function getBaseUrl(): string { 88 | return _baseUrl; 89 | } 90 | 91 | /* 92 | Sets the base URL for http requests 93 | */ 94 | export function setBaseUrl(baseUrl: string) { 95 | _baseUrl = baseUrl; 96 | } 97 | 98 | let _fetchFactory = () => window; 99 | /* 100 | Returns an instance of fetch either created by a configured factory or a default one 101 | */ 102 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 103 | return _fetchFactory?.() ?? { fetch }; 104 | } 105 | /* 106 | Sets currently used factory for fetch 107 | */ 108 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 109 | _fetchFactory = factory; 110 | } 111 | 112 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client-v3/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import * as AxiosQuery from './axios-client'; 2 | import * as FetchQuery from './fetch-client'; 3 | 4 | export { AxiosQuery, FetchQuery }; 5 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/components/PetsList.tsx: -------------------------------------------------------------------------------- 1 | import { AxiosQuery } from '../api'; 2 | import { Status } from '../api/axios-client'; 3 | import React from 'react'; 4 | 5 | export const PetsList = () => { 6 | const pets1Query = AxiosQuery.Query.useFindPetsByStatusQuery({ 7 | status: [Status.Pending, Status.Sold], 8 | }); 9 | return ( 10 |
11 |

List:

12 |
    13 | {pets1Query.data?.map((pet, index) => ( 14 |
  1. {pet.name}
  2. 15 | ))} 16 |
17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import { QueryClient, QueryClientProvider } from 'react-query'; 7 | import { AxiosQuery } from './api'; 8 | 9 | const queryClient = new QueryClient(); 10 | AxiosQuery.setBaseUrl('https://petstore.swagger.io/v2'); 11 | AxiosQuery.Query.setFindPetsByStatusDefaultOptions({ 12 | cacheTime: 10000, 13 | }); 14 | 15 | const root = ReactDOM.createRoot( 16 | document.getElementById('root') as HTMLElement, 17 | ); 18 | root.render( 19 | 20 | 21 | 22 | 23 | , 24 | ); 25 | 26 | // If you want to start measuring performance in your app, pass a function 27 | // to log results (for example: reportWebVitals(console.log)) 28 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 29 | reportWebVitals(); 30 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/pet-client-v3/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/pet-client-v3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /examples/pet-client-vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /examples/pet-client-vue/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/pet-client-vue/README.md: -------------------------------------------------------------------------------- 1 | # pet-client-vue 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Type Support for `.vue` Imports in TS 10 | 11 | TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. 12 | 13 | If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: 14 | 15 | 1. Disable the built-in TypeScript Extension 16 | 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette 17 | 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` 18 | 2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. 19 | 20 | ## Customize configuration 21 | 22 | See [Vite Configuration Reference](https://vitejs.dev/config/). 23 | 24 | ## Project Setup 25 | 26 | ```sh 27 | npm install 28 | ``` 29 | 30 | ### Compile and Hot-Reload for Development 31 | 32 | ```sh 33 | npm run dev 34 | ``` 35 | 36 | ### Type-Check, Compile and Minify for Production 37 | 38 | ```sh 39 | npm run build 40 | ``` 41 | -------------------------------------------------------------------------------- /examples/pet-client-vue/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/pet-client-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/pet-client-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pet-client-vue", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "generate-axios": "react-query-swagger /vue /modules /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client.ts /template:Axios /serviceHost:. /useRecommendedConfiguration", 8 | "generate-axios-minimal": "react-query-swagger /vue /minimal /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client-minimal.ts /template:Axios /serviceHost:.", 9 | "build": "run-p type-check build-only", 10 | "preview": "vite preview", 11 | "build-only": "vite build", 12 | "type-check": "vue-tsc --noEmit" 13 | }, 14 | "dependencies": { 15 | "vue": "^3.5.13", 16 | "@tanstack/vue-query": "5.65.0" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^22.12.0", 20 | "@vitejs/plugin-vue": "^5.2.1", 21 | "@vitejs/plugin-vue-jsx": "^4.1.1", 22 | "@vue/tsconfig": "^0.7.0", 23 | "npm-run-all": "^4.1.5", 24 | "react-query-swagger": "link:../../src", 25 | "typescript": "5.5.3", 26 | "vite": "^6.0.11", 27 | "vue-tsc": "^2.2.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/pet-client-vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client-vue/public/favicon.ico -------------------------------------------------------------------------------- /examples/pet-client-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 46 | 47 | 75 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/api/axios-client-minimal.ts: -------------------------------------------------------------------------------- 1 | import * as Types from './axios-client-minimal.types'; 2 | export * from './axios-client-minimal.types'; 3 | 4 | //---------------------- 5 | // 6 | // Generated using the NSwag toolchain v13.20.0.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) 7 | // 8 | //---------------------- 9 | 10 | /* tslint:disable */ 11 | /* eslint-disable */ 12 | // ReSharper disable InconsistentNaming 13 | 14 | import type { AxiosError } from 'axios'; 15 | import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 16 | 17 | export * as Client from './axios-client-minimal/Client'; 18 | 19 | export * as Query from './axios-client-minimal/Query'; 20 | 21 | 22 | 23 | import { addResultTypeFactory } from './axios-client-minimal/helpers'; 24 | export { setBaseUrl, getBaseUrl } from './axios-client-minimal/helpers'; 25 | export { setAxiosFactory, getAxios } from './axios-client-minimal/helpers'; 26 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/api/axios-client-minimal/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/vue-query'; 3 | import type { UseQueryReturnType, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationReturnType, QueryMeta, MutationMeta } from '@tanstack/vue-query'; 4 | type MaybeRef = Ref | T; 5 | type NoRef = C extends Ref ? T : C; 6 | type NoRefObject = { 7 | [P in keyof T]: NoRef; 8 | }; 9 | import type { Ref } from 'vue'; 10 | import axios from 'axios'; 11 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 12 | 13 | const _resultTypesByQueryKey: Record any> = {}; 14 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 15 | _resultTypesByQueryKey[typeName] = factory; 16 | } 17 | export function getResultTypeFactory(typeName: string) { 18 | return _resultTypesByQueryKey[typeName]; 19 | } 20 | 21 | export function trimArrayEnd(arr: T[]): T[] { 22 | let lastDefinedValueIndex = arr.length - 1; 23 | while (lastDefinedValueIndex >= 0) { 24 | if (arr[lastDefinedValueIndex] === undefined) { 25 | lastDefinedValueIndex--; 26 | } else { 27 | break; 28 | } 29 | } 30 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 31 | } 32 | 33 | export function addMetaToOptions() { 34 | } 35 | /* 36 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 37 | Returns true if parameter is Object 38 | Returns false if parameter is number/string/boolean/Date or Array 39 | */ 40 | export function isParameterObject(param: unknown) { 41 | if (param === null || param === undefined) return false; 42 | if (param instanceof Array) return false; 43 | const isObject = typeof param === 'object'; 44 | if (!isObject) return false; 45 | if (param instanceof Date) return false; 46 | return true; 47 | } 48 | 49 | let _baseUrl = ''; 50 | /* 51 | Returns the base URL for http requests 52 | */ 53 | export function getBaseUrl(): string { 54 | return _baseUrl; 55 | } 56 | 57 | /* 58 | Sets the base URL for http requests 59 | */ 60 | export function setBaseUrl(baseUrl: string) { 61 | _baseUrl = baseUrl; 62 | } 63 | 64 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 65 | /* 66 | Returns an instance of Axios either created by a configured factory or a default one 67 | */ 68 | export function getAxios() { 69 | return _axiosFactory?.() ?? axios; 70 | } 71 | /* 72 | Sets the factory for Axios instances 73 | */ 74 | export function setAxiosFactory(factory: () => AxiosInstance) { 75 | _axiosFactory = factory; 76 | } 77 | 78 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client-vue/src/api/axios-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/vue-query'; 3 | import type { UseQueryReturnType, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationReturnType, QueryMeta, MutationMeta } from '@tanstack/vue-query'; 4 | type MaybeRef = Ref | T; 5 | type NoRef = C extends Ref ? T : C; 6 | type NoRefObject = { 7 | [P in keyof T]: NoRef; 8 | }; 9 | import type { Ref } from 'vue'; 10 | import axios from 'axios'; 11 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 12 | 13 | const _resultTypesByQueryKey: Record any> = {}; 14 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 15 | _resultTypesByQueryKey[typeName] = factory; 16 | } 17 | export function getResultTypeFactory(typeName: string) { 18 | return _resultTypesByQueryKey[typeName]; 19 | } 20 | 21 | export function trimArrayEnd(arr: T[]): T[] { 22 | let lastDefinedValueIndex = arr.length - 1; 23 | while (lastDefinedValueIndex >= 0) { 24 | if (arr[lastDefinedValueIndex] === undefined) { 25 | lastDefinedValueIndex--; 26 | } else { 27 | break; 28 | } 29 | } 30 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 31 | } 32 | 33 | export function addMetaToOptions() { 34 | } 35 | /* 36 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 37 | Returns true if parameter is Object 38 | Returns false if parameter is number/string/boolean/Date or Array 39 | */ 40 | export function isParameterObject(param: unknown) { 41 | if (param === null || param === undefined) return false; 42 | if (param instanceof Array) return false; 43 | const isObject = typeof param === 'object'; 44 | if (!isObject) return false; 45 | if (param instanceof Date) return false; 46 | return true; 47 | } 48 | 49 | let _baseUrl = ''; 50 | /* 51 | Returns the base URL for http requests 52 | */ 53 | export function getBaseUrl(): string { 54 | return _baseUrl; 55 | } 56 | 57 | /* 58 | Sets the base URL for http requests 59 | */ 60 | export function setBaseUrl(baseUrl: string) { 61 | _baseUrl = baseUrl; 62 | } 63 | 64 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 65 | /* 66 | Returns an instance of Axios either created by a configured factory or a default one 67 | */ 68 | export function getAxios() { 69 | return _axiosFactory?.() ?? axios; 70 | } 71 | /* 72 | Sets the factory for Axios instances 73 | */ 74 | export function setAxiosFactory(factory: () => AxiosInstance) { 75 | _axiosFactory = factory; 76 | } 77 | 78 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client-vue/src/api/index.js: -------------------------------------------------------------------------------- 1 | import * as AxiosQuery from './axios-client'; 2 | export { AxiosQuery }; 3 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import * as AxiosQuery from './axios-client'; 2 | 3 | export { AxiosQuery }; 4 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | position: relative; 59 | font-weight: normal; 60 | } 61 | 62 | body { 63 | min-height: 100vh; 64 | color: var(--color-text); 65 | background: var(--color-background); 66 | transition: color 0.5s, background-color 0.5s; 67 | line-height: 1.6; 68 | font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 69 | Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 70 | font-size: 15px; 71 | text-rendering: optimizeLegibility; 72 | -webkit-font-smoothing: antialiased; 73 | -moz-osx-font-smoothing: grayscale; 74 | } 75 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | #app { 4 | max-width: 1280px; 5 | margin: 0 auto; 6 | padding: 2rem; 7 | 8 | font-weight: normal; 9 | } 10 | 11 | a, 12 | .green { 13 | text-decoration: none; 14 | color: hsla(160, 100%, 37%, 1); 15 | transition: 0.4s; 16 | } 17 | 18 | @media (hover: hover) { 19 | a:hover { 20 | background-color: hsla(160, 100%, 37%, 0.2); 21 | } 22 | } 23 | 24 | @media (min-width: 1024px) { 25 | body { 26 | display: flex; 27 | place-items: center; 28 | } 29 | 30 | #app { 31 | display: grid; 32 | grid-template-columns: 1fr 1fr; 33 | padding: 0 2rem; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | import './assets/main.css'; 4 | import { VueQueryPlugin } from '@tanstack/vue-query'; 5 | import { AxiosQuery } from './api'; 6 | AxiosQuery.setBaseUrl('https://petstore.swagger.io/v2'); 7 | createApp(App).use(VueQueryPlugin).mount('#app'); 8 | -------------------------------------------------------------------------------- /examples/pet-client-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | 4 | import './assets/main.css'; 5 | import { VueQueryPlugin } from '@tanstack/vue-query'; 6 | import { AxiosQuery } from './api'; 7 | 8 | AxiosQuery.setBaseUrl('https://petstore.swagger.io/v2'); 9 | createApp(App).use(VueQueryPlugin).mount('#app'); 10 | -------------------------------------------------------------------------------- /examples/pet-client-vue/tsconfig.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "playwright.config.*" 8 | ], 9 | "compilerOptions": { 10 | "composite": true, 11 | "types": ["node"] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/pet-client-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "importsNotUsedAsValues": "remove", 7 | "paths": { 8 | "@/*": ["./src/*"] 9 | } 10 | }, 11 | 12 | "references": [ 13 | { 14 | "path": "./tsconfig.config.json" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /examples/pet-client-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [vue(), vueJsx()], 10 | resolve: { 11 | alias: { 12 | '@': fileURLToPath(new URL('./src', import.meta.url)) 13 | } 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /examples/pet-client/.eslintignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 3 | node_modules 4 | 5 | package.json 6 | **/package.json 7 | **/build/** 8 | .idea 9 | .vscode 10 | -------------------------------------------------------------------------------- /examples/pet-client/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser 3 | parserOptions: { 4 | ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features 5 | sourceType: 'module', // Allows for the use of imports 6 | ecmaFeatures: { 7 | jsx: true, // Allows for the parsing of JSX 8 | }, 9 | }, 10 | settings: { 11 | react: { 12 | version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use 13 | }, 14 | }, 15 | extends: [ 16 | 'plugin:react/recommended', // Uses the recommended rules from @eslint-plugin-react 17 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 18 | ], 19 | rules: { 20 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs 21 | // e.g. "@typescript-eslint/explicit-function-return-type": "off", 22 | 'react/prop-types': 'off', 23 | '@typescript-eslint/no-var-requires': 'off', // since in Electron we have to import styles with require 24 | '@typescript-eslint/no-use-before-define': 'off', // it's quite usual that we define helper functions somewhere at the bottom 25 | '@typescript-eslint/explicit-function-return-type': 'off', // we don't have a rule to specify return type for a function 26 | 'prefer-const': 'off', 27 | 'no-var': 'off', 28 | 'prettier/prettier': 'off', 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /examples/pet-client/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /examples/pet-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pet-client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^29.5.14", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^19.0.8", 12 | "@types/react-dom": "^19.0.3", 13 | "@typescript-eslint/eslint-plugin": "^6.9.1", 14 | "@typescript-eslint/parser": "^6.9.1", 15 | "axios": "^0.26.1", 16 | "eslint-config-prettier": "^8.5.0", 17 | "eslint-plugin-prettier": "^4.2.1", 18 | "react-query-swagger": "link:../../src", 19 | "prettier": "^2.2.1", 20 | "jest": "26.6.0", 21 | "react": "^19.0.0", 22 | "react-dom": "^19.0.0", 23 | "@tanstack/react-query": "5.8.1", 24 | "@tanstack/query-sync-storage-persister": "5.8.1", 25 | "@tanstack/react-query-persist-client": "5.8.1", 26 | "react-scripts": "5.0.1", 27 | "@types/trusted-types": "2.0.7", 28 | "replace": "1.1.5", 29 | "typescript": "5.5.3", 30 | "web-vitals": "^0.2.4" 31 | }, 32 | "scripts": { 33 | "generate-axios-minimal-sample": "react-query-swagger /tanstack /input:./swagger.json /output:src/api/axios-client-minimal-sample.ts /template:Axios /serviceHost:. /minimal /post-queries-start-with-get", 34 | "generate-axios-minimal": "react-query-swagger /tanstack /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client-minimal.ts /template:Axios /serviceHost:. /minimal", 35 | "generate-axios-minimal-no-hooks": "react-query-swagger /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client-minimal-no-hooks.ts /template:Axios /serviceHost:. /minimal /no-hooks", 36 | "generate-axios": "react-query-swagger /tanstack /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client.ts /template:Axios /serviceHost:. /use-recommended-configuration", 37 | "generate-axios-no-split": "react-query-swagger /tanstack /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/axios-client-no-split.ts /template:Axios /serviceHost:.", 38 | "generate-axios-date-only-test": "react-query-swagger /tanstack /input:https://localhost:5001/swagger/v1/swagger.json /output:app/api/api-client.ts /template:Axios /serviceHost:. /use-recommended-configuration", 39 | "generate-fetch": "react-query-swagger /tanstack /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/fetch-client.ts /template:Fetch /serviceHost:. /generateConstructorInterface:true /markOptionalProperties:true /generateOptionalParameters:true /nullValue:undefined", 40 | "generate-no-hooks-no-modules": "react-query-swagger /no-hooks /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/no-hooks-no-modules.ts /template:Fetch /serviceHost:. /generateConstructorInterface:true /markOptionalProperties:true /generateOptionalParameters:true /nullValue:undefined", 41 | "generate-no-hooks": "react-query-swagger /no-hooks /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/no-hooks-client.ts /template:Fetch /serviceHost:. /use-recommended-configuration", 42 | "generate-no-hooks-axios": "react-query-swagger /no-hooks /input:https://petstore.swagger.io/v2/swagger.json /output:src/api/no-hooks-client-axios.ts /template:Axios /serviceHost:. /use-recommended-configuration", 43 | "start": "react-scripts start", 44 | "build": "react-scripts build", 45 | "test": "react-scripts test", 46 | "eject": "react-scripts eject", 47 | "typecheck": "tsc --noEmit" 48 | }, 49 | "eslintConfig": { 50 | "extends": [ 51 | "react-app", 52 | "react-app/jest" 53 | ] 54 | }, 55 | "browserslist": { 56 | "production": [ 57 | ">0.2%", 58 | "not dead", 59 | "not op_mini all" 60 | ], 61 | "development": [ 62 | "last 1 chrome version", 63 | "last 1 firefox version", 64 | "last 1 safari version" 65 | ] 66 | }, 67 | "resolutions": { 68 | "@typescript-eslint/eslint-plugin": "6.9.1", 69 | "@typescript-eslint/parser": "6.9.1" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /examples/pet-client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client/public/favicon.ico -------------------------------------------------------------------------------- /examples/pet-client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/pet-client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client/public/logo192.png -------------------------------------------------------------------------------- /examples/pet-client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/examples/pet-client/public/logo512.png -------------------------------------------------------------------------------- /examples/pet-client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/pet-client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/pet-client/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/pet-client/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/pet-client/src/Infinite.tsx: -------------------------------------------------------------------------------- 1 | import { useInfiniteQuery } from '@tanstack/react-query'; 2 | import React from 'react'; 3 | import { AxiosQuery } from './api'; 4 | import { Pet } from './api/axios-client'; 5 | 6 | export const Infinite = () => { 7 | const infiniteQuery = useInfiniteQuery({ 8 | initialPageParam: 0, 9 | queryKey: [...AxiosQuery.Query.findPetsByStatusQueryKey([]), 'infinite'], 10 | queryFn: async (params) => { 11 | const pageParam = (params.pageParam as number) ?? (0 as number); 12 | return [ 13 | new Pet({ name: (pageParam * 3 + 1).toString(), photoUrls: [] }), 14 | new Pet({ name: (pageParam * 3 + 2).toString(), photoUrls: [] }), 15 | new Pet({ name: (pageParam * 3 + 3).toString(), photoUrls: [] }), 16 | ]; 17 | }, 18 | getNextPageParam: (lastPage, pages) => { 19 | return pages.length; 20 | }, 21 | }); 22 | 23 | return ( 24 |
25 | data:{' '} 26 | {infiniteQuery.data?.pages 27 | .map((x) => x.map((z) => z.name).join(', ')) 28 | .join(', ')} 29 | 30 |
31 | ); 32 | }; 33 | -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client-minimal-no-hooks.ts: -------------------------------------------------------------------------------- 1 | import * as Types from './axios-client-minimal-no-hooks.types'; 2 | export * from './axios-client-minimal-no-hooks.types'; 3 | 4 | //---------------------- 5 | // 6 | // Generated using the NSwag toolchain v13.20.0.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) 7 | // 8 | //---------------------- 9 | 10 | /* tslint:disable */ 11 | /* eslint-disable */ 12 | // ReSharper disable InconsistentNaming 13 | 14 | import type { AxiosError } from 'axios'; 15 | import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 16 | 17 | export * as Client from './axios-client-minimal-no-hooks/Client'; 18 | 19 | 20 | 21 | 22 | 23 | import { addResultTypeFactory } from './axios-client-minimal-no-hooks/helpers'; 24 | export { setBaseUrl, getBaseUrl } from './axios-client-minimal-no-hooks/helpers'; 25 | export { setAxiosFactory, getAxios } from './axios-client-minimal-no-hooks/helpers'; 26 | 27 | 28 | //-----PersistorHydrator.File----- 29 | 30 | //-----/PersistorHydrator.File---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client-minimal-no-hooks/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | 3 | import axios from 'axios'; 4 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 5 | 6 | const _resultTypesByQueryKey: Record any> = {}; 7 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 8 | _resultTypesByQueryKey[typeName] = factory; 9 | } 10 | export function getResultTypeFactory(typeName: string) { 11 | return _resultTypesByQueryKey[typeName]; 12 | } 13 | 14 | export function trimArrayEnd(arr: T[]): T[] { 15 | let lastDefinedValueIndex = arr.length - 1; 16 | while (lastDefinedValueIndex >= 0) { 17 | if (arr[lastDefinedValueIndex] === undefined) { 18 | lastDefinedValueIndex--; 19 | } else { 20 | break; 21 | } 22 | } 23 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 24 | } 25 | 26 | /* 27 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 28 | Returns true if parameter is Object 29 | Returns false if parameter is number/string/boolean/Date or Array 30 | */ 31 | export function isParameterObject(param: unknown) { 32 | if (param === null || param === undefined) return false; 33 | if (param instanceof Array) return false; 34 | const isObject = typeof param === 'object'; 35 | if (!isObject) return false; 36 | if (param instanceof Date) return false; 37 | return true; 38 | } 39 | 40 | let _baseUrl = ''; 41 | /* 42 | Returns the base URL for http requests 43 | */ 44 | export function getBaseUrl(): string { 45 | return _baseUrl; 46 | } 47 | 48 | /* 49 | Sets the base URL for http requests 50 | */ 51 | export function setBaseUrl(baseUrl: string) { 52 | _baseUrl = baseUrl; 53 | } 54 | 55 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 56 | /* 57 | Returns an instance of Axios either created by a configured factory or a default one 58 | */ 59 | export function getAxios() { 60 | return _axiosFactory?.() ?? axios; 61 | } 62 | /* 63 | Sets the factory for Axios instances 64 | */ 65 | export function setAxiosFactory(factory: () => AxiosInstance) { 66 | _axiosFactory = factory; 67 | } 68 | 69 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client-minimal-sample.types.ts: -------------------------------------------------------------------------------- 1 | //-----Types.File----- 2 | export interface DummyDto { 3 | test?: string; 4 | dateOnly?: Date; 5 | dateTime?: Date; 6 | } 7 | export function deserializeDummyDto(json: string): DummyDto { 8 | const data = JSON.parse(json) as DummyDto; 9 | initDummyDto(data); 10 | return data; 11 | } 12 | export function initDummyDto(_data: DummyDto) { 13 | if (_data) { 14 | _data.dateOnly = _data["dateOnly"] ? parseDateOnly(_data["dateOnly"].toString()) : null; 15 | _data.dateTime = _data["dateTime"] ? new Date(_data["dateTime"].toString()) : null; 16 | } 17 | return _data; 18 | } 19 | export function serializeDummyDto(_data: DummyDto | undefined) { 20 | if (_data) { 21 | _data = prepareSerializeDummyDto(_data as DummyDto); 22 | } 23 | return JSON.stringify(_data); 24 | } 25 | export function prepareSerializeDummyDto(_data: DummyDto): DummyDto { 26 | const data: Record = { ..._data }; 27 | data["dateOnly"] = _data.dateOnly && formatDate(_data.dateOnly); 28 | data["dateTime"] = _data.dateTime && _data.dateTime.toISOString(); 29 | return data as DummyDto; 30 | } 31 | export interface BodyDto { 32 | tst?: string; 33 | } 34 | export function deserializeBodyDto(json: string): BodyDto { 35 | const data = JSON.parse(json) as BodyDto; 36 | initBodyDto(data); 37 | return data; 38 | } 39 | export function initBodyDto(_data: BodyDto) { 40 | return _data; 41 | } 42 | export function serializeBodyDto(_data: BodyDto | undefined) { 43 | if (_data) { 44 | _data = prepareSerializeBodyDto(_data as BodyDto); 45 | } 46 | return JSON.stringify(_data); 47 | } 48 | export function prepareSerializeBodyDto(_data: BodyDto): BodyDto { 49 | const data: Record = { ..._data }; 50 | return data as BodyDto; 51 | } 52 | export function formatDate(d: Date) { 53 | return d.getFullYear() + '-' + 54 | (d.getMonth() < 9 ? ('0' + (d.getMonth()+1)) : (d.getMonth()+1)) + '-' + 55 | (d.getDate() < 10 ? ('0' + d.getDate()) : d.getDate()); 56 | } 57 | export function parseDateOnly(s: string) { 58 | const date = new Date(s); 59 | return new Date(date.getTime() + 60 | date.getTimezoneOffset() * 60000); 61 | } 62 | import type { AxiosError } from 'axios' 63 | export class ApiException extends Error { 64 | message: string; 65 | status: number; 66 | response: string; 67 | headers: { [key: string]: any; }; 68 | result: any; 69 | constructor(message: string, status: number, response: string, headers: { [key: string]: any; }, result: any) { 70 | super(); 71 | this.message = message; 72 | this.status = status; 73 | this.response = response; 74 | this.headers = headers; 75 | this.result = result; 76 | } 77 | protected isApiException = true; 78 | static isApiException(obj: any): obj is ApiException { 79 | return obj.isApiException === true; 80 | } 81 | } 82 | export function throwException(message: string, status: number, response: string, headers: { [key: string]: any; }, result?: any): any { 83 | if (result !== null && result !== undefined) 84 | throw result; 85 | else 86 | throw new ApiException(message, status, response, headers, null); 87 | } 88 | export function isAxiosError(obj: any | undefined): obj is AxiosError { 89 | return obj && obj.isAxiosError === true; 90 | } 91 | //-----/Types.File----- -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client-minimal-sample/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | import axios from 'axios'; 8 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 9 | 10 | const _resultTypesByQueryKey: Record any> = {}; 11 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 12 | _resultTypesByQueryKey[typeName] = factory; 13 | } 14 | export function getResultTypeFactory(typeName: string) { 15 | return _resultTypesByQueryKey[typeName]; 16 | } 17 | 18 | export function trimArrayEnd(arr: T[]): T[] { 19 | let lastDefinedValueIndex = arr.length - 1; 20 | while (lastDefinedValueIndex >= 0) { 21 | if (arr[lastDefinedValueIndex] === undefined) { 22 | lastDefinedValueIndex--; 23 | } else { 24 | break; 25 | } 26 | } 27 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 28 | } 29 | 30 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 31 | if (metaContext.metaFn) { 32 | options = options ?? { } as any; 33 | options!.meta = { 34 | ...metaContext.metaFn(), 35 | ...options!.meta, 36 | }; 37 | } 38 | return options; 39 | } 40 | /* 41 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 42 | Returns true if parameter is Object 43 | Returns false if parameter is number/string/boolean/Date or Array 44 | */ 45 | export function isParameterObject(param: unknown) { 46 | if (param === null || param === undefined) return false; 47 | if (param instanceof Array) return false; 48 | const isObject = typeof param === 'object'; 49 | if (!isObject) return false; 50 | if (param instanceof Date) return false; 51 | return true; 52 | } 53 | 54 | let _baseUrl = ''; 55 | /* 56 | Returns the base URL for http requests 57 | */ 58 | export function getBaseUrl(): string { 59 | return _baseUrl; 60 | } 61 | 62 | /* 63 | Sets the base URL for http requests 64 | */ 65 | export function setBaseUrl(baseUrl: string) { 66 | _baseUrl = baseUrl; 67 | } 68 | 69 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 70 | /* 71 | Returns an instance of Axios either created by a configured factory or a default one 72 | */ 73 | export function getAxios() { 74 | return _axiosFactory?.() ?? axios; 75 | } 76 | /* 77 | Sets the factory for Axios instances 78 | */ 79 | export function setAxiosFactory(factory: () => AxiosInstance) { 80 | _axiosFactory = factory; 81 | } 82 | 83 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client-minimal/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | import axios from 'axios'; 8 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 9 | 10 | const _resultTypesByQueryKey: Record any> = {}; 11 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 12 | _resultTypesByQueryKey[typeName] = factory; 13 | } 14 | export function getResultTypeFactory(typeName: string) { 15 | return _resultTypesByQueryKey[typeName]; 16 | } 17 | 18 | export function trimArrayEnd(arr: T[]): T[] { 19 | let lastDefinedValueIndex = arr.length - 1; 20 | while (lastDefinedValueIndex >= 0) { 21 | if (arr[lastDefinedValueIndex] === undefined) { 22 | lastDefinedValueIndex--; 23 | } else { 24 | break; 25 | } 26 | } 27 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 28 | } 29 | 30 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 31 | if (metaContext.metaFn) { 32 | options = options ?? { } as any; 33 | options!.meta = { 34 | ...metaContext.metaFn(), 35 | ...options!.meta, 36 | }; 37 | } 38 | return options; 39 | } 40 | /* 41 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 42 | Returns true if parameter is Object 43 | Returns false if parameter is number/string/boolean/Date or Array 44 | */ 45 | export function isParameterObject(param: unknown) { 46 | if (param === null || param === undefined) return false; 47 | if (param instanceof Array) return false; 48 | const isObject = typeof param === 'object'; 49 | if (!isObject) return false; 50 | if (param instanceof Date) return false; 51 | return true; 52 | } 53 | 54 | let _baseUrl = ''; 55 | /* 56 | Returns the base URL for http requests 57 | */ 58 | export function getBaseUrl(): string { 59 | return _baseUrl; 60 | } 61 | 62 | /* 63 | Sets the base URL for http requests 64 | */ 65 | export function setBaseUrl(baseUrl: string) { 66 | _baseUrl = baseUrl; 67 | } 68 | 69 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 70 | /* 71 | Returns an instance of Axios either created by a configured factory or a default one 72 | */ 73 | export function getAxios() { 74 | return _axiosFactory?.() ?? axios; 75 | } 76 | /* 77 | Sets the factory for Axios instances 78 | */ 79 | export function setAxiosFactory(factory: () => AxiosInstance) { 80 | _axiosFactory = factory; 81 | } 82 | 83 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client-no-split/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | import axios from 'axios'; 8 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 9 | 10 | type ClientFactoryFunction = (type: (new (...params: any[]) => T)) => T; 11 | let _clientFactoryFunction: ClientFactoryFunction = (type: (new (...params: any[]) => T)) => { 12 | const params = [_baseUrl, _axiosFactory()]; 13 | return new type(...params); 14 | }; 15 | /* 16 | Overrides default Client factory function 17 | */ 18 | export function setClientFactory(value: ClientFactoryFunction) { 19 | _clientFactoryFunction = value; 20 | } 21 | 22 | /* 23 | Returns current Client factory function 24 | */ 25 | export function getClientFactory() { 26 | return _clientFactoryFunction; 27 | } 28 | 29 | /* 30 | Function that will be called from `useQuery...` methods to get a client of certain type 31 | */ 32 | export function createClient(type: (new () => T)) { 33 | return _clientFactoryFunction(type); 34 | } 35 | const _resultTypesByQueryKey: Record any> = {}; 36 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 37 | _resultTypesByQueryKey[typeName] = factory; 38 | } 39 | export function getResultTypeFactory(typeName: string) { 40 | return _resultTypesByQueryKey[typeName]; 41 | } 42 | 43 | export function trimArrayEnd(arr: T[]): T[] { 44 | let lastDefinedValueIndex = arr.length - 1; 45 | while (lastDefinedValueIndex >= 0) { 46 | if (arr[lastDefinedValueIndex] === undefined) { 47 | lastDefinedValueIndex--; 48 | } else { 49 | break; 50 | } 51 | } 52 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 53 | } 54 | 55 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 56 | if (metaContext.metaFn) { 57 | options = options ?? { } as any; 58 | options!.meta = { 59 | ...metaContext.metaFn(), 60 | ...options!.meta, 61 | }; 62 | } 63 | return options; 64 | } 65 | /* 66 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 67 | Returns true if parameter is Object 68 | Returns false if parameter is number/string/boolean/Date or Array 69 | */ 70 | export function isParameterObject(param: unknown) { 71 | if (param === null || param === undefined) return false; 72 | if (param instanceof Array) return false; 73 | const isObject = typeof param === 'object'; 74 | if (!isObject) return false; 75 | if (param instanceof Date) return false; 76 | return true; 77 | } 78 | 79 | let _baseUrl = ''; 80 | /* 81 | Returns the base URL for http requests 82 | */ 83 | export function getBaseUrl(): string { 84 | return _baseUrl; 85 | } 86 | 87 | /* 88 | Sets the base URL for http requests 89 | */ 90 | export function setBaseUrl(baseUrl: string) { 91 | _baseUrl = baseUrl; 92 | } 93 | 94 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 95 | /* 96 | Returns an instance of Axios either created by a configured factory or a default one 97 | */ 98 | export function getAxios() { 99 | return _axiosFactory?.() ?? axios; 100 | } 101 | /* 102 | Sets the factory for Axios instances 103 | */ 104 | export function setAxiosFactory(factory: () => AxiosInstance) { 105 | _axiosFactory = factory; 106 | } 107 | 108 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/axios-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | import axios from 'axios'; 8 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 9 | 10 | const _resultTypesByQueryKey: Record any> = {}; 11 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 12 | _resultTypesByQueryKey[typeName] = factory; 13 | } 14 | export function getResultTypeFactory(typeName: string) { 15 | return _resultTypesByQueryKey[typeName]; 16 | } 17 | 18 | export function trimArrayEnd(arr: T[]): T[] { 19 | let lastDefinedValueIndex = arr.length - 1; 20 | while (lastDefinedValueIndex >= 0) { 21 | if (arr[lastDefinedValueIndex] === undefined) { 22 | lastDefinedValueIndex--; 23 | } else { 24 | break; 25 | } 26 | } 27 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 28 | } 29 | 30 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 31 | if (metaContext.metaFn) { 32 | options = options ?? { } as any; 33 | options!.meta = { 34 | ...metaContext.metaFn(), 35 | ...options!.meta, 36 | }; 37 | } 38 | return options; 39 | } 40 | /* 41 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 42 | Returns true if parameter is Object 43 | Returns false if parameter is number/string/boolean/Date or Array 44 | */ 45 | export function isParameterObject(param: unknown) { 46 | if (param === null || param === undefined) return false; 47 | if (param instanceof Array) return false; 48 | const isObject = typeof param === 'object'; 49 | if (!isObject) return false; 50 | if (param instanceof Date) return false; 51 | return true; 52 | } 53 | 54 | let _baseUrl = ''; 55 | /* 56 | Returns the base URL for http requests 57 | */ 58 | export function getBaseUrl(): string { 59 | return _baseUrl; 60 | } 61 | 62 | /* 63 | Sets the base URL for http requests 64 | */ 65 | export function setBaseUrl(baseUrl: string) { 66 | _baseUrl = baseUrl; 67 | } 68 | 69 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 70 | /* 71 | Returns an instance of Axios either created by a configured factory or a default one 72 | */ 73 | export function getAxios() { 74 | return _axiosFactory?.() ?? axios; 75 | } 76 | /* 77 | Sets the factory for Axios instances 78 | */ 79 | export function setAxiosFactory(factory: () => AxiosInstance) { 80 | _axiosFactory = factory; 81 | } 82 | 83 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/fetch-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import { useQuery, useMutation } from '@tanstack/react-query'; 3 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/react-query'; 4 | import type { QueryMetaContextValue } from 'react-query-swagger'; 5 | import { QueryMetaContext } from 'react-query-swagger'; 6 | import { useContext } from 'react'; 7 | 8 | type ClientFactoryFunction = (type: (new (...params: any[]) => T)) => T; 9 | let _clientFactoryFunction: ClientFactoryFunction = (type: (new (...params: any[]) => T)) => { 10 | const params = [_baseUrl, _fetchFactory()]; 11 | return new type(...params); 12 | }; 13 | /* 14 | Overrides default Client factory function 15 | */ 16 | export function setClientFactory(value: ClientFactoryFunction) { 17 | _clientFactoryFunction = value; 18 | } 19 | 20 | /* 21 | Returns current Client factory function 22 | */ 23 | export function getClientFactory() { 24 | return _clientFactoryFunction; 25 | } 26 | 27 | /* 28 | Function that will be called from `useQuery...` methods to get a client of certain type 29 | */ 30 | export function createClient(type: (new () => T)) { 31 | return _clientFactoryFunction(type); 32 | }let _jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; 33 | export function getJsonParseReviver() { 34 | return _jsonParseReviver; 35 | } 36 | export function setJsonParseReviver(value: ((key: string, value: any) => any) | undefined) { 37 | _jsonParseReviver = value; 38 | } 39 | const _resultTypesByQueryKey: Record any> = {}; 40 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 41 | _resultTypesByQueryKey[typeName] = factory; 42 | } 43 | export function getResultTypeFactory(typeName: string) { 44 | return _resultTypesByQueryKey[typeName]; 45 | } 46 | 47 | export function trimArrayEnd(arr: T[]): T[] { 48 | let lastDefinedValueIndex = arr.length - 1; 49 | while (lastDefinedValueIndex >= 0) { 50 | if (arr[lastDefinedValueIndex] === undefined) { 51 | lastDefinedValueIndex--; 52 | } else { 53 | break; 54 | } 55 | } 56 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 57 | } 58 | 59 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 60 | if (metaContext.metaFn) { 61 | options = options ?? { } as any; 62 | options!.meta = { 63 | ...metaContext.metaFn(), 64 | ...options!.meta, 65 | }; 66 | } 67 | return options; 68 | } 69 | /* 70 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 71 | Returns true if parameter is Object 72 | Returns false if parameter is number/string/boolean/Date or Array 73 | */ 74 | export function isParameterObject(param: unknown) { 75 | if (param === null || param === undefined) return false; 76 | if (param instanceof Array) return false; 77 | const isObject = typeof param === 'object'; 78 | if (!isObject) return false; 79 | if (param instanceof Date) return false; 80 | return true; 81 | } 82 | 83 | let _baseUrl = ''; 84 | /* 85 | Returns the base URL for http requests 86 | */ 87 | export function getBaseUrl(): string { 88 | return _baseUrl; 89 | } 90 | 91 | /* 92 | Sets the base URL for http requests 93 | */ 94 | export function setBaseUrl(baseUrl: string) { 95 | _baseUrl = baseUrl; 96 | } 97 | 98 | let _fetchFactory = () => window; 99 | /* 100 | Returns an instance of fetch either created by a configured factory or a default one 101 | */ 102 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 103 | return _fetchFactory?.() ?? { fetch }; 104 | } 105 | /* 106 | Sets currently used factory for fetch 107 | */ 108 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 109 | _fetchFactory = factory; 110 | } 111 | 112 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import * as AxiosQuery from './axios-client'; 2 | import * as FetchQuery from './fetch-client'; 3 | import * as NoHooks from './no-hooks-client'; 4 | 5 | export { AxiosQuery, FetchQuery, NoHooks }; 6 | -------------------------------------------------------------------------------- /examples/pet-client/src/api/no-hooks-client-axios/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import axios from 'axios'; 3 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 4 | 5 | /* 6 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 7 | Returns true if parameter is Object 8 | Returns false if parameter is number/string/boolean/Date or Array 9 | */ 10 | function isParameterObject(param: unknown) { 11 | if (param === null || param === undefined) return false; 12 | if (param instanceof Array) return false; 13 | const isObject = typeof param === 'object'; 14 | if (!isObject) return false; 15 | if (param instanceof Date) return false; 16 | return true; 17 | } 18 | 19 | let _baseUrl = ''; 20 | /* 21 | Returns the base URL for http requests 22 | */ 23 | export function getBaseUrl(): string { 24 | return _baseUrl; 25 | } 26 | 27 | /* 28 | Sets the base URL for http requests 29 | */ 30 | export function setBaseUrl(baseUrl: string) { 31 | _baseUrl = baseUrl; 32 | } 33 | 34 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 35 | /* 36 | Returns currently used factory for Axios instances 37 | */ 38 | export function getAxios() { 39 | return _axiosFactory?.() ?? axios; 40 | } 41 | /* 42 | Sets the factory for Axios instances 43 | */ 44 | export function setAxiosFactory(factory: () => AxiosInstance) { 45 | _axiosFactory = factory; 46 | } 47 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/no-hooks-client/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import axios from 'axios'; 3 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 4 | let _jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; 5 | export function getJsonParseReviver() { 6 | return _jsonParseReviver; 7 | } 8 | export function setJsonParseReviver(value: ((key: string, value: any) => any) | undefined) { 9 | _jsonParseReviver = value; 10 | } 11 | /* 12 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 13 | Returns true if parameter is Object 14 | Returns false if parameter is number/string/boolean/Date or Array 15 | */ 16 | function isParameterObject(param: unknown) { 17 | if (param === null || param === undefined) return false; 18 | if (param instanceof Array) return false; 19 | const isObject = typeof param === 'object'; 20 | if (!isObject) return false; 21 | if (param instanceof Date) return false; 22 | return true; 23 | } 24 | 25 | let _baseUrl = ''; 26 | /* 27 | Returns the base URL for http requests 28 | */ 29 | export function getBaseUrl(): string { 30 | return _baseUrl; 31 | } 32 | 33 | /* 34 | Sets the base URL for http requests 35 | */ 36 | export function setBaseUrl(baseUrl: string) { 37 | _baseUrl = baseUrl; 38 | } 39 | 40 | let _fetchFactory = () => window; 41 | /* 42 | Returns currently used factory for fetch 43 | */ 44 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 45 | return _fetchFactory?.() ?? { fetch }; 46 | } 47 | /* 48 | Sets currently used factory for fetch 49 | */ 50 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 51 | _fetchFactory = factory; 52 | } 53 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/api/no-hooks-no-modules/helpers.ts: -------------------------------------------------------------------------------- 1 | //-----ReactQueryFile----- 2 | import axios from 'axios'; 3 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 4 | type ClientFactoryFunction = (type: (new (...params: any[]) => T)) => T; 5 | let _clientFactoryFunction: ClientFactoryFunction = (type: (new (...params: any[]) => T)) => { 6 | const params = [_baseUrl, _fetchFactory()]; 7 | return new type(...params); 8 | }; 9 | /* 10 | Overrides default Client factory function 11 | */ 12 | export function setClientFactory(value: ClientFactoryFunction) { 13 | _clientFactoryFunction = value; 14 | } 15 | 16 | /* 17 | Returns current Client factory function 18 | */ 19 | export function getClientFactory() { 20 | return _clientFactoryFunction; 21 | } 22 | 23 | /* 24 | Function that will be called from `useQuery...` methods to get a client of certain type 25 | */ 26 | export function createClient(type: (new () => T)) { 27 | return _clientFactoryFunction(type); 28 | }let _jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; 29 | export function getJsonParseReviver() { 30 | return _jsonParseReviver; 31 | } 32 | export function setJsonParseReviver(value: ((key: string, value: any) => any) | undefined) { 33 | _jsonParseReviver = value; 34 | } 35 | /* 36 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 37 | Returns true if parameter is Object 38 | Returns false if parameter is number/string/boolean/Date or Array 39 | */ 40 | function isParameterObject(param: unknown) { 41 | if (param === null || param === undefined) return false; 42 | if (param instanceof Array) return false; 43 | const isObject = typeof param === 'object'; 44 | if (!isObject) return false; 45 | if (param instanceof Date) return false; 46 | return true; 47 | } 48 | 49 | let _baseUrl = ''; 50 | /* 51 | Returns the base URL for http requests 52 | */ 53 | export function getBaseUrl(): string { 54 | return _baseUrl; 55 | } 56 | 57 | /* 58 | Sets the base URL for http requests 59 | */ 60 | export function setBaseUrl(baseUrl: string) { 61 | _baseUrl = baseUrl; 62 | } 63 | 64 | let _fetchFactory = () => window; 65 | /* 66 | Returns currently used factory for fetch 67 | */ 68 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 69 | return _fetchFactory?.() ?? { fetch }; 70 | } 71 | /* 72 | Sets currently used factory for fetch 73 | */ 74 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 75 | _fetchFactory = factory; 76 | } 77 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /examples/pet-client/src/components/PetsList.tsx: -------------------------------------------------------------------------------- 1 | import { AxiosQuery } from '../api'; 2 | import { Status } from '../api/axios-client'; 3 | import React from 'react'; 4 | 5 | export const PetsList = () => { 6 | const pets1Query = AxiosQuery.Query.useFindPetsByStatusQuery({ 7 | status: [Status.Pending, Status.Sold], 8 | }); 9 | return ( 10 |
11 |

List:

12 |
    13 | {pets1Query.data?.map((pet, index) => ( 14 |
  1. {pet.name}
  2. 15 | ))} 16 |
17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /examples/pet-client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/pet-client/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; 7 | import { AxiosQuery } from './api'; 8 | import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'; 9 | import { persistQueryClient } from '@tanstack/react-query-persist-client'; 10 | import { initPersister, persisterDeserialize } from './api/axios-client'; 11 | 12 | const queryClient = new QueryClient(); 13 | initPersister(); 14 | const storagePersister = createSyncStoragePersister({ 15 | storage: window.localStorage, 16 | deserialize: persisterDeserialize, 17 | }); 18 | persistQueryClient({ 19 | queryClient, 20 | persister: storagePersister, 21 | }); 22 | AxiosQuery.setBaseUrl('https://petstore.swagger.io/v2'); 23 | AxiosQuery.Query.setFindPetsByStatusDefaultOptions({ 24 | gcTime: 10000, 25 | }); 26 | 27 | const root = ReactDOM.createRoot( 28 | document.getElementById('root') as HTMLElement, 29 | ); 30 | root.render( 31 | 32 | 33 | 34 | 35 | , 36 | ); 37 | 38 | // If you want to start measuring performance in your app, pass a function 39 | // to log results (for example: reportWebVitals(console.log)) 40 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 41 | reportWebVitals(); 42 | -------------------------------------------------------------------------------- /examples/pet-client/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/pet-client/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/pet-client/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/pet-client/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/pet-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/.idea/.idea.DemoSwagger/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /.idea.DemoSwagger.iml 6 | /modules.xml 7 | /contentModel.xml 8 | /projectSettingsUpdater.xml 9 | # Editor-based HTTP Client requests 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/.idea/.idea.DemoSwagger/.idea/CSharpierPlugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/.idea/.idea.DemoSwagger/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/.idea/.idea.DemoSwagger/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/.idea/.idea.DemoSwagger/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/ArrayReturnController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DemoSwagger; 4 | 5 | [Route("array")] 6 | [ApiController] 7 | public class ArrayReturnController 8 | { 9 | [HttpGet("String")] 10 | public string[] String() => new [] {""}; 11 | [HttpGet("Number")] 12 | public int[] Number() => new [] {2}; 13 | [HttpGet("Bool")] 14 | public bool[] Boolean() => new [] {true}; 15 | [HttpGet("DateOnly")] 16 | public DateOnly[] DateOnly() => new [] {System.DateOnly.MaxValue, }; 17 | [HttpGet("DateTime")] 18 | public DateTime[] DateTime() => new [] {System.DateTime.UtcNow, }; 19 | [HttpGet("Dummy")] 20 | public DummyDto[] DummyDto() => new [] {new DummyDto()}; 21 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/DictionaryArrayReturnController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DemoSwagger; 4 | 5 | [Route("dictionary-array")] 6 | [ApiController] 7 | public class DictionaryArrayReturnController 8 | { 9 | [HttpGet("String")] 10 | public Dictionary String() => null!; 11 | [HttpGet("Number")] 12 | public Dictionary Number() => null!; 13 | [HttpGet("Bool")] 14 | public Dictionary Boolean() => null!; 15 | [HttpGet("DateOnly")] 16 | public Dictionary DateOnly() => null!; 17 | [HttpGet("DateTime")] 18 | public Dictionary DateTime() => null!; 19 | [HttpGet("Dummy")] 20 | public Dictionary DummyDto() => null!; 21 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/DictionaryReturnController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DemoSwagger; 4 | 5 | [Route("dictionary")] 6 | [ApiController] 7 | public class DictionaryReturnController 8 | { 9 | [HttpGet("String")] 10 | public Dictionary String() => null!; 11 | [HttpGet("Number")] 12 | public Dictionary Number() => null!; 13 | [HttpGet("Bool")] 14 | public Dictionary Boolean() => null!; 15 | [HttpGet("DateOnly")] 16 | public Dictionary DateOnly() => null!; 17 | [HttpGet("DateTime")] 18 | public Dictionary DateTime() => null!; 19 | [HttpGet("Dummy")] 20 | public Dictionary DummyDto() => null!; 21 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/Dto/DummyDto.cs: -------------------------------------------------------------------------------- 1 | namespace DemoSwagger; 2 | 3 | public class DummyDto 4 | { 5 | public string Test { get; set; } 6 | public DateOnly DateOnly { get; set; } 7 | public DateTime DateTime { get; set; } 8 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/Dto/JsonInNestedDto.cs: -------------------------------------------------------------------------------- 1 | using DemoSwagger.FromQueryJson; 2 | 3 | namespace DemoSwagger; 4 | 5 | public class JsonInNestedDto 6 | { 7 | public string Test { get; set; } 8 | 9 | [FromJsonQuery] 10 | public DummyDto Dummy { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/PostController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DemoSwagger; 4 | 5 | [Route("post")] 6 | [ApiController] 7 | public class PostController 8 | { 9 | [HttpPost("user/{id}")] 10 | public string IdInUrl(int id, DummyDto dto) => ""; 11 | 12 | [HttpPost("no-parameter/no-body")] 13 | public string NoParameterNoBody() => ""; 14 | 15 | [HttpPost("no-parameter/simple-body")] 16 | public string SimpleBody([FromBody] string body) => ""; 17 | 18 | [HttpPost("with-parameter/{id}/no-body")] 19 | public string ParameterInUrlNoBody(string id) => ""; 20 | 21 | [HttpPost("with-parameter/{id}/simple-body")] 22 | public string SimpleBodyWithParameter(int id, [FromBody] string body) => ""; 23 | 24 | [HttpPost("with-parameter/{id}/simple-array-body")] 25 | public string SimpleArrayBodyWithParameter(int id, [FromBody] string[] body) => ""; 26 | 27 | [HttpPost("form-parameter/{id}")] 28 | public string FormParameter(int id, [FromForm] DummyDto dto) => ""; 29 | } 30 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/PrimitiveReturnController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DemoSwagger; 4 | 5 | 6 | [Route("primitive")] 7 | [ApiController] 8 | public class PrimitiveReturnController 9 | { 10 | [HttpGet("String")] 11 | public string String() => ""; 12 | [HttpGet("Number")] 13 | public int Number() => 2; 14 | [HttpGet("Bool")] 15 | public bool Boolean() => true; 16 | [HttpGet("DateOnly")] 17 | public DateOnly DateOnly() => System.DateOnly.MinValue; 18 | [HttpGet("DateTime")] 19 | public DateTime DateTime() => System.DateTime.UtcNow; 20 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Controllers/QueryController.cs: -------------------------------------------------------------------------------- 1 | using DemoSwagger.FromQueryJson; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace DemoSwagger; 5 | 6 | [Route("query")] 7 | [ApiController] 8 | public class QueryController 9 | { 10 | [HttpGet("JsonInQuery")] 11 | public string JsonInQuery([FromJsonQuery] DummyDto? dto) => ""; 12 | 13 | [HttpGet("JsonInNested")] 14 | public string JsonInNestedQuery(JsonInNestedDto? dto) => ""; 15 | 16 | [HttpGet("DateOnlyInQuery")] 17 | public string DateOnlyInQuery(DateOnly date) => ""; 18 | 19 | [HttpGet("DateTimeInQuery")] 20 | public string DateTimeInQuery(DateTime date) => ""; 21 | 22 | [HttpGet("ArrayInQuery")] 23 | public string[] ArrayInQuery([FromQuery] string[]? data) => data ?? []; 24 | 25 | [HttpGet("DictionaryInQuery")] 26 | public Dictionary DictionaryInQuery( 27 | [FromQuery] Dictionary? data 28 | ) => data ?? new Dictionary(); 29 | 30 | [HttpGet("DictionaryInJsonQuery")] 31 | public Dictionary DictionaryInJsonQuery( 32 | [FromJsonQuery] Dictionary? data 33 | ) => data ?? new Dictionary(); 34 | 35 | /// 36 | /// This will have the useQuery generated, since the name starts with Get 37 | /// 38 | [HttpPost("GetViaPost")] 39 | public DummyDto GetViaPost(DummyDto dto) => dto; 40 | 41 | /// 42 | /// However this will not (). 43 | /// 44 | [HttpPost("NonGetViaPost")] 45 | public DummyDto NonGetViaPost(DummyDto dto) => dto; 46 | 47 | /// 48 | /// Do not use in any other API methods except 49 | /// 50 | public class BodyDto 51 | { 52 | public string Tst { get; set; } 53 | } 54 | 55 | [HttpGet("WithBody")] 56 | public string WithBody(BodyDto dto) => ""; 57 | 58 | /// 59 | /// Do not use in any other API methods except 60 | /// 61 | public class ClassInQueryDto 62 | { 63 | public string Tst { get; set; } 64 | } 65 | 66 | /// 67 | /// the name should NOT start with GET 68 | /// 69 | [HttpGet("ClassInQuery")] 70 | public string WithClassInQuery([FromQuery] ClassInQueryDto dto) => ""; 71 | } 72 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/DemoSwagger.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/DemoSwagger.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoSwagger", "DemoSwagger.csproj", "{1EEBD6DF-A53D-4C28-B003-552609559758}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {1EEBD6DF-A53D-4C28-B003-552609559758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {1EEBD6DF-A53D-4C28-B003-552609559758}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {1EEBD6DF-A53D-4C28-B003-552609559758}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {1EEBD6DF-A53D-4C28-B003-552609559758}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | EndGlobal 17 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/FromQueryJson/FromJsonQueryAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DemoSwagger.FromQueryJson; 4 | public class FromJsonQueryAttribute : ModelBinderAttribute 5 | { 6 | public FromJsonQueryAttribute() 7 | { 8 | BinderType = typeof(JsonQueryBinder); 9 | } 10 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/FromQueryJson/JsonQueryBinder.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using Microsoft.AspNetCore.Mvc.ModelBinding; 3 | using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; 4 | 5 | namespace DemoSwagger.FromQueryJson; 6 | 7 | public class JsonQueryBinder : IModelBinder 8 | { 9 | private readonly ILogger _logger; 10 | private readonly IObjectModelValidator _validator; 11 | 12 | public JsonQueryBinder(IObjectModelValidator validator, ILogger logger) 13 | { 14 | _validator = validator; 15 | _logger = logger; 16 | } 17 | public Task BindModelAsync(ModelBindingContext bindingContext) 18 | { 19 | var value = bindingContext.ValueProvider.GetValue(bindingContext.FieldName).FirstValue; 20 | if (value == null) 21 | { 22 | return Task.CompletedTask; 23 | } 24 | 25 | try 26 | { 27 | var parsed = JsonSerializer.Deserialize(value, bindingContext.ModelType, 28 | new JsonSerializerOptions(JsonSerializerDefaults.Web)); 29 | bindingContext.Result = ModelBindingResult.Success(parsed); 30 | 31 | if (parsed != null) 32 | { 33 | _validator.Validate( 34 | bindingContext.ActionContext, 35 | validationState: bindingContext.ValidationState, 36 | prefix: string.Empty, 37 | model: parsed 38 | ); 39 | } 40 | } 41 | catch (JsonException e) 42 | { 43 | _logger.LogError(e, "Failed to bind parameter '{FieldName}'", bindingContext.FieldName); 44 | bindingContext.ActionContext.ModelState.TryAddModelError(key: e.Path, exception: e, 45 | bindingContext.ModelMetadata); 46 | } 47 | catch (Exception e) when (e is FormatException || e is OverflowException) 48 | { 49 | _logger.LogError(e, "Failed to bind parameter '{FieldName}'", bindingContext.FieldName); 50 | bindingContext.ActionContext.ModelState.TryAddModelError(string.Empty, e, bindingContext.ModelMetadata); 51 | } 52 | 53 | return Task.CompletedTask; 54 | } 55 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/FromQueryJson/JsonQueryNSwagOperationProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Mime; 2 | using System.Reflection; 3 | using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; 4 | using NJsonSchema; 5 | using NSwag; 6 | using NSwag.Generation.AspNetCore; 7 | using NSwag.Generation.Processors; 8 | using NSwag.Generation.Processors.Contexts; 9 | 10 | namespace DemoSwagger.FromQueryJson; 11 | 12 | /// 13 | /// Taken from https://abdus.dev/posts/aspnetcore-model-binding-json-query-params/ 14 | /// 15 | public class JsonQueryNSwagOperationProcessor : IOperationProcessor 16 | { 17 | public bool Process(OperationProcessorContext context) 18 | { 19 | if (context is AspNetCoreOperationProcessorContext aspNetOperationContext) 20 | { 21 | var parameterDescriptions = aspNetOperationContext.ApiDescription.ParameterDescriptions; 22 | var parameters = aspNetOperationContext.OperationDescription.Operation.Parameters; 23 | for (int i = 0; i < parameterDescriptions.Count; i++) 24 | { 25 | var parameterDescription = parameterDescriptions[i]; 26 | if (parameterDescription.ModelMetadata is DefaultModelMetadata defaultModelMetadata) 27 | { 28 | if ( 29 | defaultModelMetadata.Attributes.Attributes.Any(attribute => 30 | attribute.GetType() == typeof(FromJsonQueryAttribute) 31 | ) 32 | ) 33 | { 34 | var openApiParameter = parameters[i]; 35 | var content = new Dictionary() 36 | { 37 | [MediaTypeNames.Application.Json] = new OpenApiMediaType() 38 | { 39 | Schema = openApiParameter.Schema, 40 | } 41 | }; 42 | openApiParameter.ExtensionData ??= new Dictionary(); 43 | openApiParameter.ExtensionData.Add("content", content); 44 | // We need to add schema somewhere where it could be parsed by 45 | // JsonSchemaReferenceUtilities.UpdateSchemaReferencePaths. 46 | openApiParameter.AdditionalItemsSchema = openApiParameter.Schema; 47 | openApiParameter.Schema = null; 48 | } 49 | } 50 | } 51 | } 52 | 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/FromQueryJson/JsonQuerySwaggerGenExtensions.cs: -------------------------------------------------------------------------------- 1 | using NJsonSchema.Generation; 2 | using NSwag.Generation.AspNetCore; 3 | 4 | namespace DemoSwagger.FromQueryJson; 5 | 6 | 7 | 8 | public static class JsonQuerySwaggerGenExtensions 9 | { 10 | public static AspNetCoreOpenApiDocumentGeneratorSettings AddJsonQuerySupport( 11 | this AspNetCoreOpenApiDocumentGeneratorSettings options) 12 | { 13 | options.OperationProcessors.Add(new JsonQueryNSwagOperationProcessor()); 14 | return options; 15 | } 16 | } -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Program.cs: -------------------------------------------------------------------------------- 1 | using DemoSwagger.FromQueryJson; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | builder.Services.AddMvc(); 5 | 6 | builder.Services.AddOpenApiDocument(options => options.AddJsonQuerySupport()); 7 | var app = builder.Build(); 8 | 9 | app.MapGet("/", () => "Hello World!"); 10 | 11 | app.UseOpenApi(); // serve OpenAPI/Swagger documents 12 | app.UseSwaggerUi(); // serve Swagger UI 13 | 14 | app.MapControllers(); 15 | app.Run(); 16 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "launchUrl": "/swagger", 7 | "applicationUrl": "http://localhost:22175", 8 | "sslPort": 44379 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "/swagger", 17 | "applicationUrl": "http://localhost:5207", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "/swagger", 27 | "applicationUrl": "https://localhost:7172;http://localhost:5207", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "environmentVariables": { 36 | "ASPNETCORE_ENVIRONMENT": "Development" 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/server/DemoSwagger/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /scripts/patch-vue-templates.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | const args = process.argv.slice(2); 4 | const folder = args[0]; 5 | 6 | await postProcess('AxiosClient.liquid', (content) => { 7 | return content.replace('{%- template PersistorHydrator -%}', ''); 8 | }); 9 | 10 | await postProcess('File.liquid', (content) => { 11 | return content 12 | .replace('//-----PersistorHydrator.File-----', '') 13 | .replace('{% template PersistorHydrator.File %}', '') 14 | .replace('//-----/PersistorHydrator.File----', ''); 15 | }); 16 | 17 | await postProcess('ReactQuery.liquid', (content) => { 18 | content = content 19 | .replace( 20 | `Types.{{ parameter.Type }}{{ parameter.TypePostfix }}`, 21 | `MaybeRef`, 22 | ) 23 | .replace( 24 | /(?<=MutationKey.*)\{\{ ParameterType \}\}\{\{ parameter\.TypePostfix \}\}/, 25 | 'MaybeRef<{{ ParameterType }}{{ parameter.TypePostfix }}>', 26 | ) 27 | .replace( 28 | /(?<=export function.*use.*Mutation.*)\{\{ ParameterType \}\}\{\{ parameter\.TypePostfix \}\}/, 29 | 'MaybeRef<{{ ParameterType }}{{ parameter.TypePostfix }}>', 30 | ) 31 | .replace( 32 | /(?<=export function.*use.*Query.*)\{\{ ParameterType \}\}\{\{ parameter\.TypePostfix \}\}/, 33 | 'MaybeRef<{{ ParameterType }}{{ parameter.TypePostfix }}>', 34 | ) 35 | .replaceAll( 36 | 'mutationFn: (data: {{ TVariableTypeWithParameters }})', 37 | 'mutationFn: (data: NoRefObject<{{ TVariableTypeWithParameters }}>)', 38 | ) 39 | .replace( 40 | 'UseMutationOptions<{{ ResultType }}, unknown, {{ TVariableTypeWithParameters }}, TContext>', 41 | 'UseMutationOptions<{{ ResultType }}, unknown, NoRefObject<{{ TVariableTypeWithParameters }}>, TContext>', 42 | ) 43 | .replace( 44 | 'UseMutationResult<{{ ResultType }}, unknown, {{ TVariableTypeWithParameters }}, TContext>', 45 | 'UseMutationResult<{{ ResultType }}, unknown, NoRefObject<{{ TVariableTypeWithParameters }}>, TContext>', 46 | ) 47 | .replaceAll( 48 | /(?<=mutationFn:.*)\{%- assign ParameterType = parameter.Type -%\}\{\{ parameter.VariableName \}\}\{% unless forloop.last %\}/g, 49 | '{%- assign ParameterType = parameter.Type -%}{{ parameter.VariableName }} as any{% unless forloop.last %}', 50 | ) 51 | .replaceAll( 52 | '{%- if isForm %}{{TVariableName}}.{{parameter.VariableName}}{% else %}{{ parameter.VariableName }}{% endif %}', 53 | '{%- if isForm %}{{TVariableName}}.{{parameter.VariableName}} as any{% else %}{{ parameter.VariableName }} as any{% endif %}', 54 | ) 55 | .replaceAll( 56 | 'options?.parameters?.{{ parameter.VariableName }}!', 57 | 'options?.parameters?.{{ parameter.VariableName }}! as any', 58 | ) 59 | .replace( 60 | " & Partial, 'queryFn'>>", 61 | '', 62 | ); 63 | 64 | return content; 65 | }); 66 | 67 | async function postProcess(file, postProcess) { 68 | let content = fs.readFileSync(`src/${folder}/${file}`, 'utf8').toString(); 69 | content = postProcess(content); 70 | 71 | fs.writeFileSync(`src/${folder}/${file}`, content); 72 | } 73 | -------------------------------------------------------------------------------- /scripts/update-nswag-templates.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import fetch from 'node-fetch'; 3 | 4 | await downloadAndPostProcess( 5 | 'File.liquid', 6 | (content) => 7 | content 8 | .replace( 9 | /\{\{ Types \}\}/, 10 | '//-----Types.File-----\n{{ Types }}\n//-----/CustomTypes.File-----\n', 11 | ) 12 | .replace( 13 | /\{\{ ExtensionCodeBottom \}\}/, 14 | '{{ ExtensionCodeBottom }}\n//-----/Types.File-----', 15 | ), 16 | '_File.liquid', 17 | ); 18 | await downloadAndPostProcess('AxiosClient.liquid', (content) => content); 19 | await downloadAndPostProcess('FetchClient.liquid', (content) => content); 20 | 21 | await downloadAndPostProcess( 22 | 'Client.ProcessResponse.HandleStatusCode.liquid', 23 | (content) => 24 | content.replaceAll( 25 | '{{ operation.ResultType }}', 26 | `{{ operation.ResultType | prepend: 'Types.' }}`, 27 | ), 28 | ); 29 | await downloadAndPostProcess( 30 | 'Client.ProcessResponse.Return.liquid', 31 | (content) => 32 | content.replaceAll( 33 | '{{ operation.ResultType }}', 34 | `{{ operation.ResultType | prepend: 'Types.' }}`, 35 | ), 36 | ); 37 | await downloadAndPostProcess('Client.RequestBody.liquid', (content) => 38 | content 39 | .replace( 40 | '{%- if parameter.IsDateOrDateTimeArray -%}', 41 | `{%- if parameter.IsDateArray -%} 42 | {{ parameter.VariableName }} && {{ parameter.VariableName }}.forEach(item_ => { content_ += encodeURIComponent("{{ parameter.Name }}") + "=" + encodeURIComponent(item_ ? "" + formatDate(item_) : "null") + "&"; }); 43 | {%- elsif parameter.IsDateOrDateTimeArray -%}`, 44 | ) 45 | .replace( 46 | '{%- elsif parameter.IsDateOrDateTime -%}', 47 | `{%- elsif parameter.IsDate -%} 48 | content_ += encodeURIComponent("{{ parameter.Name }}") + "=" + encodeURIComponent({{ parameter.VariableName }} ? "" + formatDate({{ parameter.VariableName }}) : "{{ QueryNullValue }}") + "&"; 49 | {%- elsif parameter.IsDateOrDateTime-%}`, 50 | ) 51 | .replace( 52 | '{%- elsif parameter.IsDateOrDateTime -%}', 53 | `{%- elsif parameter.IsDate -%} 54 | content_.append("{{ parameter.Name }}", formatDate({{ parameter.VariableName }})); 55 | {%- elsif parameter.IsDateOrDateTime-%}`, 56 | ), 57 | ); 58 | 59 | async function downloadAndPostProcess(file, postProcess, newName) { 60 | let content = await fetch( 61 | `https://raw.githubusercontent.com/RicoSuter/NSwag/master/src/NSwag.CodeGeneration.TypeScript/Templates/${file}`, 62 | ).then((x) => x.text()); 63 | 64 | const processedContent = postProcess(content); 65 | if (newName) { 66 | fs.writeFileSync(`src/templates/${newName}`, processedContent); 67 | } else { 68 | const originalFileName = `src/templates/original/${file}`; 69 | const previousOriginalContent = fs.readFileSync(originalFileName); 70 | if (previousOriginalContent != content) { 71 | fs.writeFileSync(originalFileName, content); 72 | fs.writeFileSync(`src/templates/modules/${file}`, processedContent); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-query-swagger", 3 | "version": "15.12.7", 4 | "description": "Generates react-query hooks for your API based on Swagger/OpenAPI definition", 5 | "author": "Artur Drobinskiy", 6 | "license": "MIT", 7 | "homepage": "https://github.com/shaddix/react-query-swagger#readme", 8 | "repository": { 9 | "type": "git", 10 | "url": "git://github.com/shaddix/react-query-swagger.git" 11 | }, 12 | "main": "dist/index.js", 13 | "typings": "dist/index.d.ts", 14 | "types": "dist/index.d.ts", 15 | "keywords": [ 16 | "react-query", 17 | "swagger", 18 | "openapi", 19 | "typescript", 20 | "nswag", 21 | "react" 22 | ], 23 | "scripts": { 24 | "prepublish": "copyfiles -u 1 ../README.md ./ && tsdx build" 25 | }, 26 | "bin": "cli.js", 27 | "devDependencies": { 28 | "child_process": "1.0.2", 29 | "copyfiles": "2.4.1", 30 | "eslint": "8.37.0", 31 | "tsdx": "0.14.1" 32 | }, 33 | "peerDependencies": { 34 | "@tanstack/react-query": "> 4.0", 35 | "@tanstack/react-query-persist-client": ">4.2.0", 36 | "react": "17.x || 18.x || 19.x", 37 | "react-query": ">= 3.33 < 4.0", 38 | "typescript": "> 3.0" 39 | }, 40 | "files": [ 41 | "templates/**/*", 42 | "templates_v3/**/*", 43 | "templates_no_hooks/**/*", 44 | "templates_vue/**/*", 45 | "templates_minimal_vue/**/*", 46 | "templates_minimal/**/*", 47 | "templates_minimal_no_hooks/**/*", 48 | "templates_minimal_angular/**/*", 49 | "dist", 50 | "cli.js" 51 | ], 52 | "dependencies": { 53 | "nswag-portable": "13.20.0-v.17" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/src/QueryMetaProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, { PropsWithChildren, useContext, useMemo } from 'react'; 2 | import { QueryMeta } from 'react-query'; 3 | 4 | type QueryScopeProps = PropsWithChildren<{ 5 | /* 6 | * Every query within a QueryMetaProvider will have `meta` provided by this prop 7 | */ 8 | meta?: QueryMeta; 9 | /* 10 | * metaFn has priority over meta prop (i.e. if both are defined, metaFn is used) 11 | */ 12 | metaFn?: () => QueryMeta; 13 | 14 | /* 15 | * If true Metas from parent's QueryMetaContexts will be erased. 16 | * By default new Metas are appended to the parent's one. 17 | */ 18 | resetParentMeta?: boolean; 19 | }>; 20 | 21 | export type QueryMetaContextValue = { 22 | metaFn?: () => QueryMeta; 23 | }; 24 | 25 | export const QueryMetaContext = React.createContext({}); 26 | 27 | /* 28 | * Provides Meta information for queries (i.e. `useQuery({ meta: META })`). 29 | * All queries within children of this scope will have Meta set to either `meta` prop or the result of `metaFn()`. 30 | */ 31 | export const QueryMetaProvider: React.FC = (props) => { 32 | const parentMeta = useContext(QueryMetaContext); 33 | const value = useMemo(() => { 34 | const metaFn = () => { 35 | const meta = props.metaFn ? props.metaFn() : props.meta; 36 | return { 37 | ...(props.resetParentMeta || !parentMeta.metaFn 38 | ? {} 39 | : parentMeta.metaFn()), 40 | ...meta, 41 | }; 42 | }; 43 | return { 44 | metaFn, 45 | }; 46 | }, [parentMeta.metaFn, props.metaFn, props.meta, props.resetParentMeta]); 47 | 48 | return ( 49 | 50 | {props.children} 51 | 52 | ); 53 | }; 54 | -------------------------------------------------------------------------------- /src/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | QueryMetaProvider, 3 | QueryMetaContext, 4 | QueryMetaContextValue, 5 | } from './QueryMetaProvider'; 6 | 7 | export { QueryMetaProvider, QueryMetaContext }; 8 | export type { QueryMetaContextValue }; 9 | export type Optional = Pick, K> & Omit; 10 | -------------------------------------------------------------------------------- /src/templates/AxiosClient.liquid: -------------------------------------------------------------------------------- 1 | {%- if HasOperations -%} 2 | //-----ClientClass--{{Class}}--- 3 | {% template ClientFileHeader %} 4 | import type { AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 5 | 6 | {% template _AxiosClient %} 7 | {% template AxiosClient_RequestConfig %} 8 | //-----/ClientClass---- 9 | {% endif %} 10 | 11 | {%- if HasOperations -%} 12 | {%- assign QueryClassName = Class | prepend: 'Qqqqqq' | slice: 0, Class.size | append: "Query" | slice: 6, 1000 -%} 13 | //-----ReactQueryClass--{{QueryClassName}}--- 14 | {% template ReactQuery %} 15 | //-----/ReactQueryClass---- 16 | {% endif %} 17 | 18 | {%- template PersistorHydrator -%} -------------------------------------------------------------------------------- /src/templates/Client.RequestBody.Serialize.liquid: -------------------------------------------------------------------------------- 1 | {% unless serializeParameter %} 2 | {% assign serializeParameter = operation.ContentParameter %} 3 | {% endunless %} 4 | const content_ = JSON.stringify({{ serializeParameter.VariableName }}); -------------------------------------------------------------------------------- /src/templates/ClientFileHeader.liquid: -------------------------------------------------------------------------------- 1 | //---------------------- 2 | // 3 | // Generated using the NSwag toolchain v{{ ToolchainVersion }} (http://NSwag.org) 4 | // 5 | //---------------------- 6 | 7 | {% template File.Header %} 8 | -------------------------------------------------------------------------------- /src/templates/FetchClient.liquid: -------------------------------------------------------------------------------- 1 | {%- if HasOperations -%} 2 | //-----ClientClass--{{Class}}--- 3 | {% template _FetchClient %} 4 | //-----/ClientClass---- 5 | {% endif %} 6 | 7 | {%- if HasOperations -%} 8 | {%- assign QueryClassName = Class | prepend: 'Qqqqqq' | slice: 0, Class.size | append: "Query" | slice: 6, 1000 -%} 9 | //-----ReactQueryClass--{{QueryClassName}}--- 10 | {% template ReactQuery %} 11 | //-----/ReactQueryClass---- 12 | {% endif %} 13 | 14 | {% template PersistorHydrator %} 15 | -------------------------------------------------------------------------------- /src/templates/File.liquid: -------------------------------------------------------------------------------- 1 | {% template _File %} 2 | 3 | {% template ReactQueryFile %} 4 | 5 | //-----PersistorHydrator.File----- 6 | {% template PersistorHydrator.File %} 7 | //-----/PersistorHydrator.File---- -------------------------------------------------------------------------------- /src/templates/JsonParseReviver.liquid: -------------------------------------------------------------------------------- 1 | let _jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; 2 | export function getJsonParseReviver() { 3 | return _jsonParseReviver; 4 | } 5 | export function setJsonParseReviver(value: ((key: string, value: any) => any) | undefined) { 6 | _jsonParseReviver = value; 7 | } -------------------------------------------------------------------------------- /src/templates/PersistorHydrator.AddResultTypeFactory.liquid: -------------------------------------------------------------------------------- 1 | addResultTypeFactory('{{ Class }}___{{ operation.ActualOperationName }}', (data: any) => { const result = new {{ typeWithoutBrackets }}(); result.init(data); return result; }); -------------------------------------------------------------------------------- /src/templates/PersistorHydrator.File.liquid: -------------------------------------------------------------------------------- 1 | import type { PersistedClient } from '@tanstack/react-query-persist-client'; 2 | import type { DehydratedState, QueryKey } from '@tanstack/react-query' 3 | import { getResultTypeFactory } from './helpers'; 4 | 5 | /* 6 | * If you have Dates in QueryKeys (i.e. in request parameters), you need to deserialize them to Dates correctly 7 | * (otherwise they are deserialized as strings by default, and your queries are broken). 8 | */ 9 | export function deserializeDate(str: unknown) { 10 | if (!str || typeof str !== 'string') return str; 11 | if (!/^\d\d\d\d\-\d\d\-\d\d/.test(str)) return str; 12 | 13 | const date = new Date(str); 14 | const isDate = date instanceof Date && !isNaN(date as any); 15 | 16 | return isDate ? date : str; 17 | } 18 | 19 | export function deserializeDatesInQueryKeys(queryKey: QueryKey) { 20 | return queryKey 21 | // We need to replace `null` with `undefined` in query key, because 22 | // `undefined` is serialized as `null`. 23 | // And most probably if we have `null` in QueryKey it actually means `undefined`. 24 | // We can't keep nulls, because they have a different meaning, and e.g. boolean parameters are not allowed to be null. 25 | .map(x => (x === null ? undefined : x)) 26 | .map(x => deserializeDate(x)); 27 | } 28 | 29 | 30 | export function deserializeClassesInQueryData(queryKey: QueryKey, data: any) { 31 | if (!data) { 32 | return data; 33 | } else if (typeof data !== 'object') { 34 | return data; 35 | } else if ('pages' in data && 'pageParams' in data && Array.isArray(data.pages) && Array.isArray(data.pageParams)) { 36 | // infinite query 37 | data.pages = data.pages.map((page:any) => deserializeClassesInQueryData(queryKey, page)); 38 | } else if (Array.isArray(data)) { 39 | return data.map(elem => constructDtoClass(queryKey, elem)); 40 | } else { 41 | return constructDtoClass(queryKey, data); 42 | } 43 | } 44 | 45 | /* 46 | * Pass this function as `deserialize` option to createSyncStoragePersister/createAsyncStoragePersister 47 | * to correctly deserialize your DTOs (including Dates) 48 | */ 49 | export function persisterDeserialize(cache: string): PersistedClient { 50 | const client: PersistedClient = JSON.parse(cache); 51 | client.clientState.queries.forEach((query) => { 52 | query.state.data = deserializeClassesInQueryData(query.queryKey, query.state.data); 53 | query.queryKey = deserializeDatesInQueryKeys(query.queryKey); 54 | }); 55 | 56 | 57 | return client; 58 | } 59 | 60 | export function constructDtoClass(queryKey: QueryKey, data: any): unknown { 61 | const resultTypeKey = getResultTypeClassKey(queryKey); 62 | const constructorFunction = getResultTypeFactory(resultTypeKey); 63 | 64 | if (!data || !constructorFunction) 65 | return data; 66 | 67 | return constructorFunction(data); 68 | } 69 | 70 | export function getResultTypeClassKey(queryKey: QueryKey): string { 71 | if (!Array.isArray(queryKey)) { 72 | return queryKey as unknown as string; 73 | } 74 | if (queryKey.length >= 2) { 75 | // We concatenate first and second elements, because they uniquely identify the query. 76 | // All other QueryKey elements are query parameters 77 | return `${queryKey[0]}___${queryKey[1]}`; 78 | } 79 | 80 | // We actually should never reach this point :) 81 | return queryKey.join('___'); 82 | } 83 | 84 | export function initPersister() { 85 | /*--addResultTypeFactory-placeholder--*/ 86 | } -------------------------------------------------------------------------------- /src/templates/PersistorHydrator.liquid: -------------------------------------------------------------------------------- 1 | //-----PersistorHydrator----- 2 | {%- for operation in Operations -%} 3 | {%- if operation.HttpMethodUpper == 'Get' and operation.HasResultType -%} 4 | {%- assign lastSymbol = operation.UnwrappedResultType | slice: -1 -%} 5 | {%- if lastSymbol != '}' -%} 6 | {%- assign typeWithoutBrackets = operation.UnwrappedResultType -%} 7 | {%- if lastSymbol == ']' -%} 8 | {%- assign typeWithoutBrackets = operation.UnwrappedResultType | prepend: ' ' | slice: 0, operation.UnwrappedResultType.size | lstrip -%} 9 | {%- endif -%} 10 | {%- if typeWithoutBrackets != 'string' and typeWithoutBrackets != 'number' and typeWithoutBrackets != 'boolean' and typeWithoutBrackets != 'FileResponse' and typeWithoutBrackets != 'Date' and typeWithoutBrackets != 'any' -%} 11 | {% template PersistorHydrator.AddResultTypeFactory %} 12 | {%- endif -%} 13 | {%- endif -%} 14 | {% endif -%} 15 | {%- endfor -%} 16 | //-----/PersistorHydrator----- -------------------------------------------------------------------------------- /src/templates/ReactQuery.Imports.liquid: -------------------------------------------------------------------------------- 1 | import { useQuery, useMutation } from '@tanstack/react-query'; 2 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/react-query'; 3 | -------------------------------------------------------------------------------- /src/templates/ReactQuery.MetaFile.liquid: -------------------------------------------------------------------------------- 1 | import type { QueryMetaContextValue } from 'react-query-swagger'; 2 | import { QueryMetaContext } from 'react-query-swagger'; 3 | import { useContext } from 'react'; -------------------------------------------------------------------------------- /src/templates/ReactQuery.MetaFileFunctions.liquid: -------------------------------------------------------------------------------- 1 | 2 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 3 | if (metaContext.metaFn) { 4 | options = options ?? { } as any; 5 | options!.meta = { 6 | ...metaContext.metaFn(), 7 | ...options!.meta, 8 | }; 9 | } 10 | return options; 11 | } 12 | -------------------------------------------------------------------------------- /src/templates/ReactQueryFile.liquid: -------------------------------------------------------------------------------- 1 | import { addResultTypeFactory } from './helpers'; 2 | export { setBaseUrl, getBaseUrl } from './helpers'; 3 | {%- if Framework.IsAxios -%} 4 | export { setAxiosFactory, getAxios } from './helpers'; 5 | {%- elsif Framework.IsFetchOrAurelia -%} 6 | export { setFetchFactory, getFetch } from './helpers'; 7 | {%- endif -%} 8 | //-----ReactQueryFile----- 9 | {% template ReactQuery.Imports %} 10 | {% template ReactQuery.MetaFile %} 11 | {% if Framework.IsAxios -%} 12 | import axios from 'axios'; 13 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 14 | {% endif -%} 15 | 16 | {%- template ReactQuery.GetClientFactory -%} 17 | {%- unless Framework.IsAxios -%} 18 | {%- template JsonParseReviver -%} 19 | {%- endunless -%} 20 | 21 | const _resultTypesByQueryKey: Record any> = {}; 22 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 23 | _resultTypesByQueryKey[typeName] = factory; 24 | } 25 | export function getResultTypeFactory(typeName: string) { 26 | return _resultTypesByQueryKey[typeName]; 27 | } 28 | 29 | export function trimArrayEnd(arr: T[]): T[] { 30 | let lastDefinedValueIndex = arr.length - 1; 31 | while (lastDefinedValueIndex >= 0) { 32 | if (arr[lastDefinedValueIndex] === undefined) { 33 | lastDefinedValueIndex--; 34 | } else { 35 | break; 36 | } 37 | } 38 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 39 | } 40 | 41 | {% template ReactQuery.MetaFileFunctions %} 42 | /* 43 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 44 | Returns true if parameter is Object 45 | Returns false if parameter is number/string/boolean/Date or Array 46 | */ 47 | export function isParameterObject(param: unknown) { 48 | if (param === null || param === undefined) return false; 49 | if (param instanceof Array) return false; 50 | const isObject = typeof param === 'object'; 51 | if (!isObject) return false; 52 | if (param instanceof Date) return false; 53 | return true; 54 | } 55 | 56 | let _baseUrl = ''; 57 | /* 58 | Returns the base URL for http requests 59 | */ 60 | export function getBaseUrl(): string { 61 | return _baseUrl; 62 | } 63 | 64 | /* 65 | Sets the base URL for http requests 66 | */ 67 | export function setBaseUrl(baseUrl: string) { 68 | _baseUrl = baseUrl; 69 | } 70 | 71 | {% if Framework.IsAxios -%} 72 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 73 | /* 74 | Returns an instance of Axios either created by a configured factory or a default one 75 | */ 76 | export function getAxios() { 77 | return _axiosFactory?.() ?? axios; 78 | } 79 | /* 80 | Sets the factory for Axios instances 81 | */ 82 | export function setAxiosFactory(factory: () => AxiosInstance) { 83 | _axiosFactory = factory; 84 | } 85 | {% endif -%} 86 | {% if Framework.IsFetchOrAurelia -%} 87 | let _fetchFactory = () => window; 88 | /* 89 | Returns an instance of fetch either created by a configured factory or a default one 90 | */ 91 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 92 | return _fetchFactory?.() ?? { fetch }; 93 | } 94 | /* 95 | Sets currently used factory for fetch 96 | */ 97 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 98 | _fetchFactory = factory; 99 | } 100 | {% endif -%} 101 | 102 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /src/templates/modules/AxiosClient.liquid: -------------------------------------------------------------------------------- 1 | import { throwException, isAxiosError } from '../client'; 2 | import { getAxios, getBaseUrl } from './helpers'; 3 | {%- if GenerateClientInterfaces -%} 4 | {% if ExportTypes %}export {% endif %}interface I{{ Class }} { 5 | {% for operation in Operations -%} 6 | {% template Client.Method.Documentation %} 7 | {{ operation.MethodAccessModifier }}{{ operation.ActualOperationName }}({% for parameter in operation.Parameters %}{{ parameter.VariableName }}{% if GenerateOptionalParameters and parameter.IsOptional %}?{% endif %}: {{ parameter.Type }}{{ parameter.TypePostfix }}{% if parameter.IsLast == false %}, {% endif %}{% endfor %}): Promise<{{ operation.ResultType }}>; 8 | {%- endfor -%}} 9 | {%- endif -%} 10 | {% for operation in Operations %} 11 | 12 | {% template Client.Method.Documentation %} 13 | export function {% template OperationNameSafe %}({% for parameter in operation.Parameters %}{{ parameter.VariableName }}{% if GenerateOptionalParameters and parameter.IsOptional %}?{% endif %}: {{ parameter.Type | prepend: 'Types.' }}{{ parameter.TypePostfix }}{% if parameter.IsLast == false %}, {% endif %}{% endfor %}{% if operation.Parameters.size > 0 %}, {%endif%}config?: AxiosRequestConfig | undefined): Promise<{{ operation.ResultType | prepend: 'Types.' }}> { 14 | {% template Client.RequestUrl %} 15 | 16 | {% if operation.HasBody -%} 17 | {% template Client.RequestBody %} 18 | 19 | {% endif -%} 20 | let options_: AxiosRequestConfig = { 21 | {% if operation.IsFile -%} 22 | responseType: "blob", 23 | {% endif -%} 24 | ..._requestConfig{{ operation.ActualOperationNameUpper }}, 25 | ...config, 26 | {% if operation.HasBody -%} 27 | data: content_, 28 | {% endif -%} 29 | method: "{{ operation.HttpMethodUpper | upcase }}", 30 | url: url_, 31 | headers: { 32 | ..._requestConfig{{ operation.ActualOperationNameUpper }}?.headers, 33 | {% for parameter in operation.HeaderParameters -%} 34 | "{{ parameter.Name }}": {{ parameter.VariableName }} !== undefined && {{ parameter.VariableName }} !== null ? "" + {{ parameter.VariableName }} : "", 35 | {% endfor -%} 36 | {% if operation.HasContent or operation.ConsumesFormUrlEncoded -%} 37 | "Content-Type": "{{ operation.Consumes }}", 38 | {% endif -%} 39 | {% if operation.HasResultType and operation.HasAcceptHeaderParameterParameter == false -%} 40 | "Accept": "{{ operation.Produces }}", 41 | {% endif -%} 42 | ...config?.headers, 43 | } 44 | }; 45 | 46 | {% if UseTransformOptionsMethod -%} 47 | return this.transformOptions(options_).then(transformedOptions_ => { 48 | return this.instance.request(transformedOptions_); 49 | }).catch((_error: any) => { 50 | {% else -%} 51 | return getAxios().request(options_).catch((_error: any) => { 52 | {% endif -%} 53 | if (isAxiosError(_error) && _error.response) { 54 | return _error.response; 55 | } else { 56 | throw _error; 57 | } 58 | }).then((_response: AxiosResponse) => { 59 | {% if UseTransformResultMethod -%} 60 | return this.transformResult(url_, _response, (_response: AxiosResponse) => this.process{{ operation.ActualOperationNameUpper }}(_response)); 61 | {% else -%} 62 | return process{{ operation.ActualOperationNameUpper }}(_response); 63 | {% endif -%} 64 | }); 65 | } 66 | 67 | function process{{ operation.ActualOperationNameUpper }}(response: AxiosResponse): Promise<{{ operation.ResultType | prepend: 'Types.' }}> { 68 | const status = response.status; 69 | {% template Client.ProcessResponse %} 70 | } 71 | {% endfor -%} 72 | -------------------------------------------------------------------------------- /src/templates/modules/AxiosClient_RequestConfig.liquid: -------------------------------------------------------------------------------- 1 | {% for operation in Operations %} 2 | let _requestConfig{{ operation.ActualOperationNameUpper }}: Partial | undefined; 3 | export function get{{ operation.ActualOperationNameUpper }}RequestConfig() { 4 | return _requestConfig{{ operation.ActualOperationNameUpper }}; 5 | } 6 | export function set{{ operation.ActualOperationNameUpper }}RequestConfig(value: Partial) { 7 | _requestConfig{{ operation.ActualOperationNameUpper }} = value; 8 | } 9 | export function patch{{ operation.ActualOperationNameUpper }}RequestConfig(patch: (value: Partial) => Partial) { 10 | _requestConfig{{ operation.ActualOperationNameUpper }} = patch(_requestConfig{{ operation.ActualOperationNameUpper }} ?? {}); 11 | } 12 | {%- endfor -%} 13 | -------------------------------------------------------------------------------- /src/templates/modules/Client.ProcessResponse.Return.liquid: -------------------------------------------------------------------------------- 1 | {% if Framework.IsFetchOrAurelia -%} 2 | {% if operation.WrapResponse -%} 3 | return Promise.resolve<{{ operation.ResultType | prepend: 'Types.' }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 4 | {% else -%} 5 | return Promise.resolve<{{ operation.ResultType | prepend: 'Types.' }}>(null as any); 6 | {% endif -%} 7 | {% elsif Framework.IsAxios -%} 8 | {% if operation.WrapResponse -%} 9 | return Promise.resolve<{{ operation.ResultType | prepend: 'Types.' }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 10 | {% else -%} 11 | return Promise.resolve<{{ operation.ResultType | prepend: 'Types.' }}>(null as any); 12 | {% endif -%} 13 | {% elsif Framework.IsAngular -%} 14 | {% if operation.WrapResponse -%} 15 | return {{ Framework.RxJs.ObservableOfMethod }}<{{ operation.ResultType | prepend: 'Types.' }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 16 | {% else -%} 17 | {% if Framework.UseRxJs7 -%} 18 | return {{ Framework.RxJs.ObservableOfMethod }}(null as any); 19 | {% else -%} 20 | return {{ Framework.RxJs.ObservableOfMethod }}<{{ operation.ResultType | prepend: 'Types.' }}>(null as any); 21 | {% endif -%} 22 | {% endif -%} 23 | {% elsif Framework.IsAngularJS -%} 24 | {% if operation.WrapResponse -%} 25 | return this.q.resolve<{{ operation.ResultType | prepend: 'Types.' }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 26 | {% else -%} 27 | return this.q.resolve<{{ operation.ResultType | prepend: 'Types.' }}>(null as any); 28 | {% endif -%} 29 | {% else -%} 30 | {% if operation.WrapResponse -%} 31 | return new {{ operation.ResponseClass }}(status, _headers, null as any); 32 | {% else -%} 33 | return{% if operation.HasResultType %} null{% endif %}; 34 | {% endif -%} 35 | {%- endif -%} -------------------------------------------------------------------------------- /src/templates/modules/Client.RequestBody.Serialize.liquid: -------------------------------------------------------------------------------- 1 | {% unless serializeParameter %} 2 | {% assign serializeParameter = operation.ContentParameter %} 3 | {% endunless %} 4 | const content_ = JSON.stringify({{ serializeParameter.VariableName }}); -------------------------------------------------------------------------------- /src/templates/modules/FetchClient.liquid: -------------------------------------------------------------------------------- 1 | import { throwException } from '../client'; 2 | import { getFetch, getBaseUrl{% unless Framework.IsAxios -%}, getJsonParseReviver{% endunless %} } from './helpers'; 3 | 4 | {% for operation in Operations %} 5 | 6 | {% template Client.Method.Documentation %} 7 | export function {{ operation.ActualOperationName }}{%if operation.ActualOperationName == 'delete'%}_{%endif%}({% for parameter in operation.Parameters %}{{ parameter.VariableName }}{% if GenerateOptionalParameters and parameter.IsOptional %}?{% endif %}: {{ parameter.Type | prepend: 'Types.' }}{{ parameter.TypePostfix }}{% if parameter.IsLast == false %}, {% endif %}{% endfor %}{% if UseAbortSignal %}{% if operation.Parameters.size > 0 %}, {% endif %}signal?: AbortSignal | undefined{% endif %}): Promise<{{ operation.ResultType | prepend: 'Types.' }}> { 8 | {% template Client.RequestUrl %} 9 | 10 | {%- if operation.HasBody -%} 11 | {% template Client.RequestBody %} 12 | 13 | {%- endif -%} 14 | let options_: RequestInit = { 15 | {%- if operation.HasBody -%} 16 | body: content_, 17 | {%- endif -%} 18 | method: "{{ operation.HttpMethodUpper | upcase }}", 19 | {%- if UseAbortSignal -%} 20 | signal, 21 | {%- endif -%} 22 | headers: { 23 | {%- for parameter in operation.HeaderParameters -%} 24 | "{{ parameter.Name }}": {{ parameter.VariableName }} !== undefined && {{ parameter.VariableName }} !== null ? "" + {{ parameter.VariableName }} : "", 25 | {%- endfor -%} 26 | {%- if operation.HasContent or operation.ConsumesFormUrlEncoded -%} 27 | "Content-Type": "{{ operation.Consumes }}", 28 | {%- endif -%} 29 | {%- if operation.HasResultType and operation.HasAcceptHeaderParameterParameter == false -%} 30 | "Accept": "{{ operation.Produces }}" 31 | {%- endif -%} 32 | } 33 | }; 34 | 35 | {%- if UseTransformOptionsMethod -%} 36 | return transformOptions(options_).then(transformedOptions_ => { 37 | return getFetch().fetch(url_, transformedOptions_); 38 | }).then((_response: Response) => { 39 | {%- else -%} 40 | return getFetch().fetch(url_, options_).then((_response: Response) => { 41 | {%- endif -%} 42 | {%- if UseTransformResultMethod -%} 43 | return transformResult(url_, _response, (_response: Response) => this.process{{ operation.ActualOperationNameUpper }}(_response)); 44 | {%- else -%} 45 | return process{{ operation.ActualOperationNameUpper }}(_response); 46 | {%- endif -%} 47 | }); 48 | } 49 | 50 | function process{{ operation.ActualOperationNameUpper }}(response: Response): Promise<{{ operation.ResultType | prepend: 'Types.' }}> { 51 | const status = response.status; 52 | {% template Client.ProcessResponse %} 53 | } 54 | {% endfor -%} -------------------------------------------------------------------------------- /src/templates/modules/OperationNameSafe.liquid: -------------------------------------------------------------------------------- 1 | {{operation.ActualOperationName}}{%- case operation.ActualOperationName -%} 2 | {%- when "abstract" -%}_ 3 | {%- when "arguments" -%}_ 4 | {%- when "await" -%}_ 5 | {%- when "boolean" -%}_ 6 | {%- when "break" -%}_ 7 | {%- when "byte" -%}_ 8 | {%- when "case" -%}_ 9 | {%- when "catch" -%}_ 10 | {%- when "char" -%}_ 11 | {%- when "class" -%}_ 12 | {%- when "const" -%}_ 13 | {%- when "continue" -%}_ 14 | {%- when "debugger" -%}_ 15 | {%- when "default" -%}_ 16 | {%- when "delete" -%}_ 17 | {%- when "do" -%}_ 18 | {%- when "double" -%}_ 19 | {%- when "else" -%}_ 20 | {%- when "enum" -%}_ 21 | {%- when "eval" -%}_ 22 | {%- when "export" -%}_ 23 | {%- when "extends" -%}_ 24 | {%- when "false" -%}_ 25 | {%- when "final" -%}_ 26 | {%- when "finally" -%}_ 27 | {%- when "float" -%}_ 28 | {%- when "for" -%}_ 29 | {%- when "function" -%}_ 30 | {%- when "goto" -%}_ 31 | {%- when "if" -%}_ 32 | {%- when "implements" -%}_ 33 | {%- when "import" -%}_ 34 | {%- when "in" -%}_ 35 | {%- when "instanceof" -%}_ 36 | {%- when "int" -%}_ 37 | {%- when "interface" -%}_ 38 | {%- when "let" -%}_ 39 | {%- when "long" -%}_ 40 | {%- when "native" -%}_ 41 | {%- when "new" -%}_ 42 | {%- when "null" -%}_ 43 | {%- when "package" -%}_ 44 | {%- when "private" -%}_ 45 | {%- when "protected" -%}_ 46 | {%- when "public" -%}_ 47 | {%- when "return" -%}_ 48 | {%- when "short" -%}_ 49 | {%- when "static" -%}_ 50 | {%- when "super" -%}_ 51 | {%- when "switch" -%}_ 52 | {%- when "synchronized" -%}_ 53 | {%- when "this" -%}_ 54 | {%- when "throw" -%}_ 55 | {%- when "throws" -%}_ 56 | {%- when "transient" -%}_ 57 | {%- when "true" -%}_ 58 | {%- when "try" -%}_ 59 | {%- when "typeof" -%}_ 60 | {%- when "var" -%}_ 61 | {%- when "void" -%}_ 62 | {%- when "volatile" -%}_ 63 | {%- when "while" -%}_ 64 | {%- when "with" -%}_ 65 | {%- when "yield" -%}_ 66 | {%-endcase-%} -------------------------------------------------------------------------------- /src/templates/modules/ReactQuery.GetClientCall.liquid: -------------------------------------------------------------------------------- 1 | Client -------------------------------------------------------------------------------- /src/templates/modules/ReactQuery.GetClientFactory.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates/modules/ReactQuery.GetClientFactory.liquid -------------------------------------------------------------------------------- /src/templates/modules/ReactQuery.GetClientFunction.liquid: -------------------------------------------------------------------------------- 1 | import * as Client from './{{ Class }}' 2 | export { Client }; -------------------------------------------------------------------------------- /src/templates/original/AxiosClient_RequestConfig.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates/original/AxiosClient_RequestConfig.liquid -------------------------------------------------------------------------------- /src/templates/original/Client.ProcessResponse.Return.liquid: -------------------------------------------------------------------------------- 1 | {% if Framework.IsFetchOrAurelia -%} 2 | {% if operation.WrapResponse -%} 3 | return Promise.resolve<{{ operation.ResultType }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 4 | {% else -%} 5 | return Promise.resolve<{{ operation.ResultType }}>(null as any); 6 | {% endif -%} 7 | {% elsif Framework.IsAxios -%} 8 | {% if operation.WrapResponse -%} 9 | return Promise.resolve<{{ operation.ResultType }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 10 | {% else -%} 11 | return Promise.resolve<{{ operation.ResultType }}>(null as any); 12 | {% endif -%} 13 | {% elsif Framework.IsAngular -%} 14 | {% if operation.WrapResponse -%} 15 | return {{ Framework.RxJs.ObservableOfMethod }}<{{ operation.ResultType }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 16 | {% else -%} 17 | {% if Framework.UseRxJs7 -%} 18 | return {{ Framework.RxJs.ObservableOfMethod }}(null as any); 19 | {% else -%} 20 | return {{ Framework.RxJs.ObservableOfMethod }}<{{ operation.ResultType }}>(null as any); 21 | {% endif -%} 22 | {% endif -%} 23 | {% elsif Framework.IsAngularJS -%} 24 | {% if operation.WrapResponse -%} 25 | return this.q.resolve<{{ operation.ResultType }}>(new {{ operation.ResponseClass }}(status, _headers, null as any)); 26 | {% else -%} 27 | return this.q.resolve<{{ operation.ResultType }}>(null as any); 28 | {% endif -%} 29 | {% else -%} 30 | {% if operation.WrapResponse -%} 31 | return new {{ operation.ResponseClass }}(status, _headers, null as any); 32 | {% else -%} 33 | return{% if operation.HasResultType %} null{% endif %}; 34 | {% endif -%} 35 | {%- endif -%} -------------------------------------------------------------------------------- /src/templates/original/OperationNameSafe.liquid: -------------------------------------------------------------------------------- 1 | {{operation.ActualOperationName}} -------------------------------------------------------------------------------- /src/templates/original/ReactQuery.GetClientCall.liquid: -------------------------------------------------------------------------------- 1 | Client() -------------------------------------------------------------------------------- /src/templates/original/ReactQuery.GetClientFactory.liquid: -------------------------------------------------------------------------------- 1 | type ClientFactoryFunction = (type: (new (...params: any[]) => T)) => T; 2 | let _clientFactoryFunction: ClientFactoryFunction = (type: (new (...params: any[]) => T)) => { 3 | {% if Framework.IsAxios -%} 4 | const params = [_baseUrl, _axiosFactory()]; 5 | {% endif -%} 6 | {% if Framework.IsFetchOrAurelia -%} 7 | const params = [_baseUrl, _fetchFactory()]; 8 | {% endif -%} 9 | return new type(...params); 10 | }; 11 | /* 12 | Overrides default Client factory function 13 | */ 14 | export function setClientFactory(value: ClientFactoryFunction) { 15 | _clientFactoryFunction = value; 16 | } 17 | 18 | /* 19 | Returns current Client factory function 20 | */ 21 | export function getClientFactory() { 22 | return _clientFactoryFunction; 23 | } 24 | 25 | /* 26 | Function that will be called from `useQuery...` methods to get a client of certain type 27 | */ 28 | export function createClient(type: (new () => T)) { 29 | return _clientFactoryFunction(type); 30 | } 31 | -------------------------------------------------------------------------------- /src/templates/original/ReactQuery.GetClientFunction.liquid: -------------------------------------------------------------------------------- 1 | import { {{ Class }} as {{ Class }}Class } from '../client'; 2 | import { createClient, getClientFactory } from './helpers'; 3 | 4 | export const Client = () => getClientFactory()({{ Class }}Class); -------------------------------------------------------------------------------- /src/templates_minimal/Class.liquid: -------------------------------------------------------------------------------- 1 | {% template Interface %} 2 | 3 | export function deserialize{{ ClassName }}(json: string): {{ ClassName }} { 4 | const data = JSON.parse(json) as {{ ClassName }}; 5 | {% if HasBaseDiscriminator -%} 6 | {% for derivedClass in DerivedClasses -%} 7 | if (data["{{ BaseDiscriminator }}"] === "{{ derivedClass.Discriminator }}") { 8 | return init{{ derivedClass.ClassName }}(data as {{ derivedClass.ClassName }}); 9 | } 10 | {% endfor -%} 11 | {% endif -%} 12 | init{{ ClassName }}(data); 13 | return data; 14 | } 15 | 16 | export function init{{ ClassName }}(_data: {{ ClassName }}) { 17 | {%- if HasInheritance -%} 18 | init{{ BaseClass }}(_data); 19 | {%- endif -%} 20 | {%- if HasIndexerProperty or HasProperties -%} 21 | if (_data) { 22 | {%- for property in Properties -%} 23 | {%- if property.Type != 'string' and property.Type != 'boolean' and property.Type != 'number' and property.IsDictionary != true -%} 24 | {{ property.ConvertToClassCode | strip}} 25 | {%- endif -%} 26 | {%- endfor -%} 27 | } 28 | {%- endif -%} 29 | return _data; 30 | } 31 | 32 | export function serialize{{ ClassName }}(_data: {{ ClassName }} | undefined) { 33 | if (_data) { 34 | _data = prepareSerialize{{ ClassName }}(_data as {{ ClassName }}); 35 | {% if HasDiscriminator -%} 36 | _data["{{ BaseDiscriminator }}"] = "{{ DiscriminatorName }}"; 37 | {% endif %} 38 | } 39 | return JSON.stringify(_data); 40 | } 41 | 42 | export function prepareSerialize{{ ClassName }}(_data: {{ ClassName }}): {{ ClassName }} { 43 | {%- if HasInheritance -%} 44 | const data = prepareSerialize{{ BaseClass }}(_data as {{ ClassName }}) as Record; 45 | {%- else -%} 46 | const data: Record = { ..._data }; 47 | {%- endif -%} 48 | {%- for property in Properties -%} 49 | {%- if property.Type != 'string' and property.Type != 'boolean' and property.Type != 'number' -%} 50 | {{ property.ConvertToJavaScriptCode | strip}} 51 | {%- endif -%} 52 | {%- endfor -%} 53 | return data as {{ ClassName }}; 54 | } 55 | -------------------------------------------------------------------------------- /src/templates_minimal/ConvertToClass.liquid: -------------------------------------------------------------------------------- 1 | {%- assign StringToDateOnlyCode = StringToDateCode -%} 2 | {%- if UseJsDate -%} 3 | {%- assign StringToDateOnlyCode = 'parseDateOnly' -%} 4 | {%- endif -%} 5 | {% if IsNewableObject -%} 6 | {% if CheckNewableObject -%} 7 | {{ Variable }} = {{ Value }} && Types.init{{ Type }}({{ Value }}); 8 | {% else -%} 9 | {{ Variable }} = Types.init{{ Type }}({{ Value }}); 10 | {% endif -%} 11 | {% elsif IsArray -%} 12 | {% if IsArrayItemNewableObject or IsArrayItemDate or IsArrayItemDateTime -%} 13 | if (Array.isArray({{ Value }})) { 14 | {{ Variable }} = {{ Value }}.map(item => 15 | {% if IsArrayItemNewableObject -%} 16 | Types.init{{ ArrayItemType }}(item) 17 | {% else -%} 18 | {% if IsArrayItemDate -%} 19 | {{ StringToDateOnlyCode }}(item) 20 | {% elsif IsArrayItemDateTime -%} 21 | {{ StringToDateCode }}(item) 22 | {% endif -%} 23 | {% endif -%} 24 | ); 25 | } 26 | {% else %} 27 | {{ Variable }} = {{ Value }}; 28 | {% endif -%} 29 | {% elsif IsDictionary -%} 30 | {% if IsDictionaryValueNewableObject or IsDictionaryValueNewableArray or IsDictionaryValueDate or IsDictionaryValueDateTime -%} 31 | if ({{ Value }}) { 32 | for (let key in {{ Value }}) { 33 | {% if IsDictionaryValueNewableObject -%} 34 | ({{ Variable }}){% if RequiresStrictPropertyInitialization %}!{% endif %}[key] = {{ Value }}[key] ? Types.deserialize{{ DictionaryValueType }}({{ Value }}[key]) : {{ NullValue }}; 35 | {% elsif IsDictionaryValueNewableArray -%} 36 | ({{ Variable }}){% if RequiresStrictPropertyInitialization %}!{% endif %}[key] = {{ Value }}[key] ? {{ Value }}[key].map((i: any) => Types.deserialize{{ DictionaryValueArrayItemType }}(i)) : {{ NullValue }}; 37 | {% elsif IsDictionaryValueDate -%} 38 | ({{ Variable }}){% if RequiresStrictPropertyInitialization %}!{% endif %}[key] = {{ Value }}[key] ? {{ StringToDateOnlyCode }}({{ Value }}[key].toString()) : {% if HasDictionaryValueDefaultValue %}{{ DictionaryValueDefaultValue }}{% else %}{{ NullValue }}{% endif %}; 39 | {% elsif IsDictionaryValueDateTime -%} 40 | ({{ Variable }}){% if RequiresStrictPropertyInitialization %}!{% endif %}[key] = {{ Value }}[key] ? {{ StringToDateCode }}({{ Value }}[key].toString()) : {% if HasDictionaryValueDefaultValue %}{{ DictionaryValueDefaultValue }}{% else %}{{ NullValue }}{% endif %}; 41 | {% endif -%} 42 | } 43 | } 44 | {% else %} 45 | {{ Variable }} = {{ Value }}; 46 | {% endif -%} 47 | {% else -%} 48 | {% if IsDate -%} 49 | {{ Variable }} = {{ Value }} ? {{ StringToDateOnlyCode }}({{ Value }}.toString()) : {% if HasDefaultValue %}{{ StringToDateOnlyCode }}({{ DefaultValue }}){% else %}{{ NullValue }}{% endif %}; 50 | {% elsif IsDateTime -%} 51 | {{ Variable }} = {{ Value }} ? {{ StringToDateCode }}({{ Value }}.toString()) : {% if HasDefaultValue %}{{ StringToDateCode }}({{ DefaultValue }}){% else %}{{ NullValue }}{% endif %}; 52 | {% else %} 53 | {{ Variable }} = {{ Value }}; 54 | {% endif -%} 55 | {% endif -%} 56 | -------------------------------------------------------------------------------- /src/templates_minimal/ConvertToJavaScript.liquid: -------------------------------------------------------------------------------- 1 | {%- if IsNewableObject -%} 2 | {{ Variable }} = {{ Value }} && prepareSerialize{{ Type }}({{ Value }}); 3 | {%- elsif IsArray -%} 4 | {%- if IsArrayItemNewableObject or IsArrayItemDate or IsArrayItemDateTime -%} 5 | if (Array.isArray({{ Value }})) { 6 | {{ Variable }} = {{ Value }}.map(item => 7 | {%- if IsArrayItemNewableObject -%} 8 | prepareSerialize{{ ArrayItemType }}(item) 9 | {%- elsif IsArrayItemDate -%} 10 | {% if UseJsDate %}formatDate(item){% else %}item.{{ DateToStringCode }}{% endif %} 11 | {%- elsif IsArrayItemDateTime -%} 12 | item.{{ DateTimeToStringCode }} 13 | {%- endif -%} 14 | ); 15 | } 16 | {%- endif -%} 17 | {%- elsif IsDictionary -%} 18 | {%- if IsDictionaryValueNewableObject or IsDictionaryValueDate or IsDictionaryValueDateTime -%} 19 | if ({{ Value }}) { 20 | for (let key in {{ Value }}) { 21 | {%- if IsDictionaryValueNewableObject -%} 22 | ({{ Variable }})[key] = {{ Value }}[key] && prepareSerialize{{ DictionaryValueType }}({{ Value }}[key]); 23 | {%- elsif IsDictionaryValueDate -%} 24 | ({{ Variable }})[key] = {{ Value }}[key] && {% if UseJsDate %}formatDate({{ Value }}[key]){% else %}{{ Value }}[key].{{ DateToStringCode }}{% endif %}; 25 | {%- elsif IsDictionaryValueDateTime -%} 26 | ({{ Variable }})[key] = {{ Value }}[key] && {{ Value }}[key].{{ DateTimeToStringCode }}; 27 | {%- endif -%} 28 | } 29 | } 30 | {%- endif -%} 31 | {%- elsif IsDate -%} 32 | {{ Variable }} = {{ Value }} && {% if UseJsDate %}formatDate({{ Value }}){% else %}{{ Value }}.{{ DateToStringCode }}{% endif %}; 33 | {%- elsif IsDateTime -%} 34 | {{ Variable }} = {{ Value }} && {{ Value }}.{{ DateTimeToStringCode }}; 35 | {%- endif %} -------------------------------------------------------------------------------- /src/templates_minimal/File.liquid: -------------------------------------------------------------------------------- 1 | import * as Types from './client.types'; 2 | {%- comment %}this is for backwards compatibility (previously all DTO types were exported from here. Might be removed in next major version.{% endcomment -%} 3 | export * from './client.types'; 4 | 5 | {% template _File %} 6 | 7 | {% template ReactQueryFile %} 8 | 9 | //-----PersistorHydrator.File----- 10 | {% template PersistorHydrator.File %} 11 | //-----/PersistorHydrator.File---- -------------------------------------------------------------------------------- /src/templates_minimal/Interface.liquid: -------------------------------------------------------------------------------- 1 | {%- if HasDescription -%} 2 | /** {{ Description }} */ 3 | {%- endif -%} 4 | {% if ExportTypes %}export {% endif %}interface {{ ClassName }}{{ Inheritance }} { 5 | {%- for property in Properties -%} 6 | {%- if property.HasDescription -%} 7 | /** {{ property.Description }} */ 8 | {%- endif -%} 9 | {% if property.IsReadOnly %}readonly {% endif %}{{ property.InterfaceName }}{% if property.IsOptional %}?{% endif %}: {{ property.Type }}{{ property.TypePostfix }}; 10 | {%- endfor -%} 11 | {%- if HasIndexerProperty -%} 12 | [key: string]: {{ IndexerPropertyValueType }}; 13 | {%- endif -%} 14 | {%- if HasDiscriminator -%} 15 | {{ BaseDiscriminator }}: string; 16 | {%- endif -%} 17 | } -------------------------------------------------------------------------------- /src/templates_minimal/PersistorHydrator.AddResultTypeFactory.liquid: -------------------------------------------------------------------------------- 1 | addResultTypeFactory('{{ Class }}___{{ operation.ActualOperationName }}', (data: any) => Types.init{{ typeWithoutBrackets }}(data)); -------------------------------------------------------------------------------- /src/templates_minimal/modules/Client.RequestBody.Serialize.liquid: -------------------------------------------------------------------------------- 1 | {% unless serializeParameter %} 2 | {% assign serializeParameter = operation.ContentParameter %} 3 | {% endunless %} 4 | {%- if serializeParameter.IsObjectArray -%} 5 | {%- assign typeWithoutBrackets = serializeParameter.Type | prepend: ' ' | slice: 0, serializeParameter.Type.size | lstrip -%} 6 | {{ serializeParameter.VariableName }} = {{ serializeParameter.VariableName }}.map(item => Types.prepareSerialize{{typeWithoutBrackets}}(item)) 7 | const content_ = JSON.stringify({{ serializeParameter.VariableName }}); 8 | {%- elsif serializeParameter.IsArray -%} 9 | const content_ = JSON.stringify({{ serializeParameter.VariableName }}); 10 | {%- elsif serializeParameter.IsObject and serializeParameter.IsDictionary == false -%} 11 | const content_ = Types.serialize{{ serializeParameter.Type }}({{ serializeParameter.VariableName }}); 12 | {%- else -%} 13 | const content_ = JSON.stringify({{ serializeParameter.VariableName }}); 14 | {%- endif -%} -------------------------------------------------------------------------------- /src/templates_minimal_angular/PersistorHydrator.File.liquid: -------------------------------------------------------------------------------- 1 | import type { PersistedClient } from '@tanstack/react-query-persist-client'; 2 | import type { DehydratedState, QueryKey } from '@tanstack/react-query' 3 | import { getResultTypeFactory } from './helpers'; 4 | 5 | /* 6 | * If you have Dates in QueryKeys (i.e. in request parameters), you need to deserialize them to Dates correctly 7 | * (otherwise they are deserialized as strings by default, and your queries are broken). 8 | */ 9 | export function deserializeDate(str: unknown) { 10 | if (!str || typeof str !== 'string') return str; 11 | if (!/^\d\d\d\d\-\d\d\-\d\d/.test(str)) return str; 12 | 13 | const date = new Date(str); 14 | const isDate = date instanceof Date && !isNaN(date as any); 15 | 16 | return isDate ? date : str; 17 | } 18 | 19 | export function deserializeDatesInQueryKeys(queryKey: QueryKey) { 20 | return queryKey 21 | // We need to replace `null` with `undefined` in query key, because 22 | // `undefined` is serialized as `null`. 23 | // And most probably if we have `null` in QueryKey it actually means `undefined`. 24 | // We can't keep nulls, because they have a different meaning, and e.g. boolean parameters are not allowed to be null. 25 | .map(x => (x === null ? undefined : x)) 26 | .map(x => deserializeDate(x)); 27 | } 28 | 29 | 30 | export function deserializeClassesInQueryData(queryKey: QueryKey, data: any) { 31 | if (!data) { 32 | return data; 33 | } else if (typeof data !== 'object') { 34 | return data; 35 | } else if ('pages' in data && 'pageParams' in data && Array.isArray(data.pages) && Array.isArray(data.pageParams)) { 36 | // infinite query 37 | data.pages = data.pages.map((page:any) => deserializeClassesInQueryData(queryKey, page)); 38 | } else if (Array.isArray(data)) { 39 | return data.map(elem => constructDtoClass(queryKey, elem)); 40 | } else { 41 | return constructDtoClass(queryKey, data); 42 | } 43 | } 44 | 45 | /* 46 | * Pass this function as `deserialize` option to createSyncStoragePersister/createAsyncStoragePersister 47 | * to correctly deserialize your DTOs (including Dates) 48 | */ 49 | export function persisterDeserialize(cache: string): PersistedClient { 50 | const client: PersistedClient = JSON.parse(cache); 51 | client.clientState.queries.forEach((query) => { 52 | query.state.data = deserializeClassesInQueryData(query.queryKey, query.state.data); 53 | query.queryKey = deserializeDatesInQueryKeys(query.queryKey); 54 | }); 55 | 56 | 57 | return client; 58 | } 59 | 60 | export function constructDtoClass(queryKey: QueryKey, data: any): unknown { 61 | const resultTypeKey = getResultTypeClassKey(queryKey); 62 | const constructorFunction = getResultTypeFactory(resultTypeKey); 63 | 64 | if (!data || !constructorFunction) 65 | return data; 66 | 67 | return constructorFunction(data); 68 | } 69 | 70 | export function getResultTypeClassKey(queryKey: QueryKey): string { 71 | if (!Array.isArray(queryKey)) { 72 | return queryKey as unknown as string; 73 | } 74 | if (queryKey.length >= 2) { 75 | // We concatenate first and second elements, because they uniquely identify the query. 76 | // All other QueryKey elements are query parameters 77 | return `${queryKey[0]}___${queryKey[1]}`; 78 | } 79 | 80 | // We actually should never reach this point :) 81 | return queryKey.join('___'); 82 | } 83 | 84 | export function initPersister() { 85 | /*--addResultTypeFactory-placeholder--*/ 86 | } -------------------------------------------------------------------------------- /src/templates_minimal_angular/PersistorHydrator.liquid: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/templates_minimal_angular/ReactQuery.Imports.liquid: -------------------------------------------------------------------------------- 1 | import { injectQuery, injectMutation, QueryClient } from '@ngneat/query'; 2 | import { Observable } from 'rxjs'; 3 | import type { UndefinedInitialDataOptions } from '@ngneat/query/lib/query-options'; 4 | import type { Optional } from 'react-query-swagger'; 5 | import type { Result } from '@ngneat/query/lib/types'; 6 | import type { QueryFunctionContext, QueryObserverResult, DefaultError, MutationKey, MutateOptions, MutationObserver, MutationObserverOptions, MutationObserverResult, QueryKey } from '@tanstack/query-core'; 7 | type UseQueryResult = Result>; 8 | export type CreateMutationOptions = Omit, 'mutationFn'> & { 9 | mutationFn?: (variables: TVariables) => Promise | Observable; 10 | }; 11 | type UseMutationResultFn = ReturnType; 12 | type UseMutationResult = ReturnType; 13 | -------------------------------------------------------------------------------- /src/templates_minimal_angular/ReactQuery.MetaFile.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_minimal_angular/ReactQuery.MetaFile.liquid -------------------------------------------------------------------------------- /src/templates_minimal_angular/ReactQuery.MetaFileFunctions.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_minimal_angular/ReactQuery.MetaFileFunctions.liquid -------------------------------------------------------------------------------- /src/templates_minimal_no_hooks/PersistorHydrator.File.liquid: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/templates_minimal_no_hooks/PersistorHydrator.liquid: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/templates_minimal_no_hooks/ReactQuery.Imports.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_minimal_no_hooks/ReactQuery.Imports.liquid -------------------------------------------------------------------------------- /src/templates_minimal_no_hooks/ReactQuery.MetaFile.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_minimal_no_hooks/ReactQuery.MetaFile.liquid -------------------------------------------------------------------------------- /src/templates_minimal_no_hooks/ReactQuery.MetaFileFunctions.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_minimal_no_hooks/ReactQuery.MetaFileFunctions.liquid -------------------------------------------------------------------------------- /src/templates_minimal_no_hooks/ReactQuery.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_minimal_no_hooks/ReactQuery.liquid -------------------------------------------------------------------------------- /src/templates_no_hooks/AxiosClient.liquid: -------------------------------------------------------------------------------- 1 | {%- if HasOperations -%} 2 | //-----ClientClass--{{Class}}--- 3 | {% template ClientFileHeader %} 4 | import type { AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 5 | 6 | {% template _AxiosClient %} 7 | {% template AxiosClient_RequestConfig %} 8 | //-----/ClientClass---- 9 | {% endif %} 10 | 11 | {%- if HasOperations -%} 12 | {%- assign QueryClassName = Class | prepend: 'Qqqqqq' | slice: 0, Class.size | append: "Query" | slice: 6, 1000 -%} 13 | //-----ReactQueryClass--{{QueryClassName}}--- 14 | {% template ReactQuery %} 15 | //-----/ReactQueryClass---- 16 | {% endif %} -------------------------------------------------------------------------------- /src/templates_no_hooks/FetchClient.liquid: -------------------------------------------------------------------------------- 1 | {%- if HasOperations -%} 2 | //-----ClientClass--{{Class}}--- 3 | {% template _FetchClient %} 4 | //-----/ClientClass---- 5 | {% endif %} 6 | 7 | {%- if HasOperations -%} 8 | {%- assign QueryClassName = Class | prepend: 'Qqqqqq' | slice: 0, Class.size | append: "Query" | slice: 6, 1000 -%} 9 | //-----ReactQueryClass--{{QueryClassName}}--- 10 | {% template ReactQuery %} 11 | //-----/ReactQueryClass---- 12 | {% endif %} -------------------------------------------------------------------------------- /src/templates_no_hooks/File.liquid: -------------------------------------------------------------------------------- 1 | {% template _File %} 2 | 3 | {% template ReactQueryFile %} -------------------------------------------------------------------------------- /src/templates_no_hooks/ReactQuery.MetaFile.liquid: -------------------------------------------------------------------------------- 1 | import type { QueryMetaContextValue } from 'react-query-swagger'; 2 | import { QueryMetaContext } from 'react-query-swagger'; 3 | import { useContext } from 'react'; -------------------------------------------------------------------------------- /src/templates_no_hooks/ReactQuery.MetaFileFunctions.liquid: -------------------------------------------------------------------------------- 1 | 2 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 3 | if (metaContext.metaFn) { 4 | options = options ?? { } as any; 5 | options!.meta = { 6 | ...metaContext.metaFn(), 7 | ...options!.meta, 8 | }; 9 | } 10 | return options; 11 | } 12 | -------------------------------------------------------------------------------- /src/templates_no_hooks/ReactQuery.liquid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shaddix/react-query-swagger/c0b3dd73a79ef5352c39ef68709d776e3e983181/src/templates_no_hooks/ReactQuery.liquid -------------------------------------------------------------------------------- /src/templates_no_hooks/ReactQueryFile.liquid: -------------------------------------------------------------------------------- 1 | export { setBaseUrl, getBaseUrl } from './helpers'; 2 | {% if Framework.IsAxios -%} 3 | export { setAxiosFactory, getAxios } from './helpers'; 4 | {% elsif Framework.IsFetchOrAurelia -%} 5 | export { setFetchFactory, getFetch } from './helpers'; 6 | {% endif %} 7 | //-----ReactQueryFile----- 8 | import axios from 'axios'; 9 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 10 | {%- template ReactQuery.GetClientFactory -%} 11 | {%- unless Framework.IsAxios -%} 12 | {%- template JsonParseReviver -%} 13 | {%- endunless -%} 14 | 15 | /* 16 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 17 | Returns true if parameter is Object 18 | Returns false if parameter is number/string/boolean/Date or Array 19 | */ 20 | function isParameterObject(param: unknown) { 21 | if (param === null || param === undefined) return false; 22 | if (param instanceof Array) return false; 23 | const isObject = typeof param === 'object'; 24 | if (!isObject) return false; 25 | if (param instanceof Date) return false; 26 | return true; 27 | } 28 | 29 | let _baseUrl = ''; 30 | /* 31 | Returns the base URL for http requests 32 | */ 33 | export function getBaseUrl(): string { 34 | return _baseUrl; 35 | } 36 | 37 | /* 38 | Sets the base URL for http requests 39 | */ 40 | export function setBaseUrl(baseUrl: string) { 41 | _baseUrl = baseUrl; 42 | } 43 | 44 | {% if Framework.IsAxios -%} 45 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 46 | /* 47 | Returns currently used factory for Axios instances 48 | */ 49 | export function getAxios() { 50 | return _axiosFactory?.() ?? axios; 51 | } 52 | /* 53 | Sets the factory for Axios instances 54 | */ 55 | export function setAxiosFactory(factory: () => AxiosInstance) { 56 | _axiosFactory = factory; 57 | } 58 | {% endif -%} 59 | {% if Framework.IsFetchOrAurelia -%} 60 | let _fetchFactory = () => window; 61 | /* 62 | Returns currently used factory for fetch 63 | */ 64 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 65 | return _fetchFactory?.() ?? { fetch }; 66 | } 67 | /* 68 | Sets currently used factory for fetch 69 | */ 70 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 71 | _fetchFactory = factory; 72 | } 73 | {% endif -%} 74 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /src/templates_v3/File.liquid: -------------------------------------------------------------------------------- 1 | {% template _File %} 2 | 3 | {% template ReactQueryFile %} -------------------------------------------------------------------------------- /src/templates_v3/PersistorHydrator.liquid: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/templates_v3/ReactQuery.Imports.liquid: -------------------------------------------------------------------------------- 1 | import { useQuery, useMutation } from 'react-query'; 2 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from 'react-query'; 3 | -------------------------------------------------------------------------------- /src/templates_v3/ReactQuery.MetaFile.liquid: -------------------------------------------------------------------------------- 1 | import type { QueryMetaContextValue } from 'react-query-swagger'; 2 | import { QueryMetaContext } from 'react-query-swagger'; 3 | import { useContext } from 'react'; -------------------------------------------------------------------------------- /src/templates_v3/ReactQuery.MetaFileFunctions.liquid: -------------------------------------------------------------------------------- 1 | 2 | export function addMetaToOptions(options: T | undefined, metaContext: QueryMetaContextValue): T | undefined { 3 | if (metaContext.metaFn) { 4 | options = options ?? { } as any; 5 | options!.meta = { 6 | ...metaContext.metaFn(), 7 | ...options!.meta, 8 | }; 9 | } 10 | return options; 11 | } 12 | -------------------------------------------------------------------------------- /src/templates_v3/ReactQueryFile.liquid: -------------------------------------------------------------------------------- 1 | import { addResultTypeFactory } from './helpers'; 2 | export { setBaseUrl, getBaseUrl } from './helpers'; 3 | {%- if Framework.IsAxios -%} 4 | export { setAxiosFactory, getAxios } from './helpers'; 5 | {%- elsif Framework.IsFetchOrAurelia -%} 6 | export { setFetchFactory, getFetch } from './helpers'; 7 | {%- endif -%} 8 | //-----ReactQueryFile----- 9 | {% template ReactQuery.Imports %} 10 | {% template ReactQuery.MetaFile %} 11 | {% if Framework.IsAxios -%} 12 | import axios from 'axios'; 13 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 14 | {% endif -%} 15 | 16 | {%- template ReactQuery.GetClientFactory -%} 17 | {%- unless Framework.IsAxios -%} 18 | {%- template JsonParseReviver -%} 19 | {%- endunless -%} 20 | 21 | const _resultTypesByQueryKey: Record any> = {}; 22 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 23 | _resultTypesByQueryKey[typeName] = factory; 24 | } 25 | export function getResultTypeFactory(typeName: string) { 26 | return _resultTypesByQueryKey[typeName]; 27 | } 28 | 29 | export function trimArrayEnd(arr: T[]): T[] { 30 | let lastDefinedValueIndex = arr.length - 1; 31 | while (lastDefinedValueIndex >= 0) { 32 | if (arr[lastDefinedValueIndex] === undefined) { 33 | lastDefinedValueIndex--; 34 | } else { 35 | break; 36 | } 37 | } 38 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 39 | } 40 | 41 | {% template ReactQuery.MetaFileFunctions %} 42 | /* 43 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 44 | Returns true if parameter is Object 45 | Returns false if parameter is number/string/boolean/Date or Array 46 | */ 47 | export function isParameterObject(param: unknown) { 48 | if (param === null || param === undefined) return false; 49 | if (param instanceof Array) return false; 50 | const isObject = typeof param === 'object'; 51 | if (!isObject) return false; 52 | if (param instanceof Date) return false; 53 | return true; 54 | } 55 | 56 | let _baseUrl = ''; 57 | /* 58 | Returns the base URL for http requests 59 | */ 60 | export function getBaseUrl(): string { 61 | return _baseUrl; 62 | } 63 | 64 | /* 65 | Sets the base URL for http requests 66 | */ 67 | export function setBaseUrl(baseUrl: string) { 68 | _baseUrl = baseUrl; 69 | } 70 | 71 | {% if Framework.IsAxios -%} 72 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 73 | /* 74 | Returns an instance of Axios either created by a configured factory or a default one 75 | */ 76 | export function getAxios() { 77 | return _axiosFactory?.() ?? axios; 78 | } 79 | /* 80 | Sets the factory for Axios instances 81 | */ 82 | export function setAxiosFactory(factory: () => AxiosInstance) { 83 | _axiosFactory = factory; 84 | } 85 | {% endif -%} 86 | {% if Framework.IsFetchOrAurelia -%} 87 | let _fetchFactory = () => window; 88 | /* 89 | Returns an instance of fetch either created by a configured factory or a default one 90 | */ 91 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 92 | return _fetchFactory?.() ?? { fetch }; 93 | } 94 | /* 95 | Sets currently used factory for fetch 96 | */ 97 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 98 | _fetchFactory = factory; 99 | } 100 | {% endif -%} 101 | 102 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /src/templates_vue/AxiosClient.liquid: -------------------------------------------------------------------------------- 1 | {%- if HasOperations -%} 2 | //-----ClientClass--{{Class}}--- 3 | {% template ClientFileHeader %} 4 | import type { AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 5 | 6 | {% template _AxiosClient %} 7 | {% template AxiosClient_RequestConfig %} 8 | //-----/ClientClass---- 9 | {% endif %} 10 | 11 | {%- if HasOperations -%} 12 | {%- assign QueryClassName = Class | prepend: 'Qqqqqq' | slice: 0, Class.size | append: "Query" | slice: 6, 1000 -%} 13 | //-----ReactQueryClass--{{QueryClassName}}--- 14 | {% template ReactQuery %} 15 | //-----/ReactQueryClass---- 16 | {% endif %} 17 | 18 | -------------------------------------------------------------------------------- /src/templates_vue/File.liquid: -------------------------------------------------------------------------------- 1 | {% template _File %} 2 | 3 | {% template ReactQueryFile %} 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/templates_vue/ReactQuery.Imports.liquid: -------------------------------------------------------------------------------- 1 | import { useQuery, useMutation } from '@tanstack/vue-query'; 2 | import type { UseQueryResult, QueryFunctionContext, UseQueryOptions, QueryClient, QueryKey, MutationKey, UseMutationOptions, UseMutationResult, QueryMeta, MutationMeta } from '@tanstack/vue-query'; 3 | type MaybeRef = Ref | T; 4 | type NoRef = C extends Ref ? T : C; 5 | type NoRefObject = { 6 | [P in keyof T]: NoRef; 7 | }; 8 | -------------------------------------------------------------------------------- /src/templates_vue/ReactQuery.MetaFile.liquid: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue'; -------------------------------------------------------------------------------- /src/templates_vue/ReactQuery.MetaFileFunctions.liquid: -------------------------------------------------------------------------------- 1 | export function addMetaToOptions() { 2 | } 3 | -------------------------------------------------------------------------------- /src/templates_vue/ReactQueryFile.liquid: -------------------------------------------------------------------------------- 1 | import { addResultTypeFactory } from './helpers'; 2 | export { setBaseUrl, getBaseUrl } from './helpers'; 3 | {%- if Framework.IsAxios -%} 4 | export { setAxiosFactory, getAxios } from './helpers'; 5 | {%- elsif Framework.IsFetchOrAurelia -%} 6 | export { setFetchFactory, getFetch } from './helpers'; 7 | {%- endif -%} 8 | //-----ReactQueryFile----- 9 | {% template ReactQuery.Imports %} 10 | {% template ReactQuery.MetaFile %} 11 | {% if Framework.IsAxios -%} 12 | import axios from 'axios'; 13 | import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelToken } from 'axios'; 14 | {% endif -%} 15 | 16 | {%- template ReactQuery.GetClientFactory -%} 17 | {%- unless Framework.IsAxios -%} 18 | {%- template JsonParseReviver -%} 19 | {%- endunless -%} 20 | 21 | const _resultTypesByQueryKey: Record any> = {}; 22 | export function addResultTypeFactory(typeName: string, factory: (data: any) => any) { 23 | _resultTypesByQueryKey[typeName] = factory; 24 | } 25 | export function getResultTypeFactory(typeName: string) { 26 | return _resultTypesByQueryKey[typeName]; 27 | } 28 | 29 | export function trimArrayEnd(arr: T[]): T[] { 30 | let lastDefinedValueIndex = arr.length - 1; 31 | while (lastDefinedValueIndex >= 0) { 32 | if (arr[lastDefinedValueIndex] === undefined) { 33 | lastDefinedValueIndex--; 34 | } else { 35 | break; 36 | } 37 | } 38 | return lastDefinedValueIndex === arr.length - 1 ? arr : arr.slice(0, lastDefinedValueIndex + 1); 39 | } 40 | 41 | {% template ReactQuery.MetaFileFunctions %} 42 | /* 43 | Determines if first parameter of useSomethingQuery is an object with query parameters, or it's a regular parameter 44 | Returns true if parameter is Object 45 | Returns false if parameter is number/string/boolean/Date or Array 46 | */ 47 | export function isParameterObject(param: unknown) { 48 | if (param === null || param === undefined) return false; 49 | if (param instanceof Array) return false; 50 | const isObject = typeof param === 'object'; 51 | if (!isObject) return false; 52 | if (param instanceof Date) return false; 53 | return true; 54 | } 55 | 56 | let _baseUrl = ''; 57 | /* 58 | Returns the base URL for http requests 59 | */ 60 | export function getBaseUrl(): string { 61 | return _baseUrl; 62 | } 63 | 64 | /* 65 | Sets the base URL for http requests 66 | */ 67 | export function setBaseUrl(baseUrl: string) { 68 | _baseUrl = baseUrl; 69 | } 70 | 71 | {% if Framework.IsAxios -%} 72 | let _axiosFactory: () => AxiosInstance | undefined = () => undefined; 73 | /* 74 | Returns an instance of Axios either created by a configured factory or a default one 75 | */ 76 | export function getAxios() { 77 | return _axiosFactory?.() ?? axios; 78 | } 79 | /* 80 | Sets the factory for Axios instances 81 | */ 82 | export function setAxiosFactory(factory: () => AxiosInstance) { 83 | _axiosFactory = factory; 84 | } 85 | {% endif -%} 86 | {% if Framework.IsFetchOrAurelia -%} 87 | let _fetchFactory = () => window; 88 | /* 89 | Returns an instance of fetch either created by a configured factory or a default one 90 | */ 91 | export function getFetch(): { fetch(url: RequestInfo, init?: RequestInit): Promise } { 92 | return _fetchFactory?.() ?? { fetch }; 93 | } 94 | /* 95 | Sets currently used factory for fetch 96 | */ 97 | export function setFetchFactory(factory: () => { fetch(url: RequestInfo, init?: RequestInit): Promise }) { 98 | _fetchFactory = factory; 99 | } 100 | {% endif -%} 101 | 102 | //-----/ReactQueryFile---- -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "typeRoots": ["types"], 11 | "allowJs": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "allowSyntheticDefaultImports": true, 15 | "strict": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "module": "esnext", 19 | "moduleResolution": "node", 20 | "resolveJsonModule": true, 21 | "isolatedModules": true, 22 | "noEmit": true, 23 | "jsx": "react" 24 | }, 25 | 26 | } 27 | --------------------------------------------------------------------------------