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

feat: add Pinia Colada plugin support

Add @pinia/colada plugin to openapi-ts with example implementation.

- Add PiniaColadaPlugin type definitions and configuration
- Register plugin in config system and plugin type map
- Include example Vue application demonstrating Pinia Colada integration
- Update pnpm-lock.yaml with new dependencies
- Fix linting issues in generated code

+4830 -50
-1
.nvmrc
··· 1 - 22.12.0
+15
examples/openapi-ts-pinia-colada/.eslintrc.cjs
··· 1 + /* eslint-env node */ 2 + require('@rushstack/eslint-patch/modern-module-resolution') 3 + 4 + module.exports = { 5 + extends: [ 6 + 'plugin:vue/vue3-essential', 7 + 'eslint:recommended', 8 + '@vue/eslint-config-typescript', 9 + '@vue/eslint-config-prettier/skip-formatting' 10 + ], 11 + parserOptions: { 12 + ecmaVersion: 'latest' 13 + }, 14 + root: true 15 + }
+30
examples/openapi-ts-pinia-colada/.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 + 30 + *.tsbuildinfo
+8
examples/openapi-ts-pinia-colada/.prettierrc.json
··· 1 + { 2 + "$schema": "https://json.schemastore.org/prettierrc", 3 + "semi": false, 4 + "tabWidth": 2, 5 + "singleQuote": true, 6 + "printWidth": 100, 7 + "trailingComma": "none" 8 + }
+3
examples/openapi-ts-pinia-colada/.vscode/extensions.json
··· 1 + { 2 + "recommendations": ["Vue.volar", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] 3 + }
+276
examples/openapi-ts-pinia-colada/CHANGELOG.md
··· 1 + # @example/openapi-ts-tanstack-vue-query 2 + 3 + ## 0.0.39 4 + 5 + ### Patch Changes 6 + 7 + - Updated dependencies [[`f23f3ae`](https://github.com/hey-api/openapi-ts/commit/f23f3ae874385e758eb8d43bb4e274c9858a4e40)]: 8 + - @hey-api/client-fetch@0.13.1 9 + 10 + ## 0.0.38 11 + 12 + ### Patch Changes 13 + 14 + - Updated dependencies [[`10d2e03`](https://github.com/hey-api/openapi-ts/commit/10d2e03b8295e4e887fab8d023aa823699efbae8)]: 15 + - @hey-api/client-fetch@0.13.0 16 + 17 + ## 0.0.37 18 + 19 + ### Patch Changes 20 + 21 + - Updated dependencies [[`4d8c030`](https://github.com/hey-api/openapi-ts/commit/4d8c03038979c9a75315cc158789b3c198c62f90)]: 22 + - @hey-api/client-fetch@0.12.0 23 + 24 + ## 0.0.36 25 + 26 + ### Patch Changes 27 + 28 + - Updated dependencies [[`8152aaf`](https://github.com/hey-api/openapi-ts/commit/8152aaf4892c48b79fd3dc486eb3c0ea333dc3e6)]: 29 + - @hey-api/client-fetch@0.11.0 30 + 31 + ## 0.0.35 32 + 33 + ### Patch Changes 34 + 35 + - Updated dependencies [[`1f99066`](https://github.com/hey-api/openapi-ts/commit/1f99066efbb2d0e6b9e3710c701293c2cc09d65e)]: 36 + - @hey-api/client-fetch@0.10.2 37 + 38 + ## 0.0.34 39 + 40 + ### Patch Changes 41 + 42 + - Updated dependencies [[`565e0b8`](https://github.com/hey-api/openapi-ts/commit/565e0b89fbab4556ecdc63dfe08250942681140e)]: 43 + - @hey-api/client-fetch@0.10.1 44 + 45 + ## 0.0.33 46 + 47 + ### Patch Changes 48 + 49 + - Updated dependencies [[`fed9699`](https://github.com/hey-api/openapi-ts/commit/fed969985275621c7c2b65ffc760c7c66fafaf72)]: 50 + - @hey-api/client-fetch@0.10.0 51 + 52 + ## 0.0.32 53 + 54 + ### Patch Changes 55 + 56 + - Updated dependencies [[`67c385b`](https://github.com/hey-api/openapi-ts/commit/67c385bf6289a79726b0cdd85fd81ca501cf2248)]: 57 + - @hey-api/client-fetch@0.9.0 58 + 59 + ## 0.0.31 60 + 61 + ### Patch Changes 62 + 63 + - Updated dependencies [[`fe43b88`](https://github.com/hey-api/openapi-ts/commit/fe43b889c20a2001f56e259f93f64851a1caa1d1)]: 64 + - @hey-api/client-fetch@0.8.4 65 + 66 + ## 0.0.30 67 + 68 + ### Patch Changes 69 + 70 + - Updated dependencies [[`c0b36b9`](https://github.com/hey-api/openapi-ts/commit/c0b36b95645d484034c3af145c5554867568979b)]: 71 + - @hey-api/client-fetch@0.8.3 72 + 73 + ## 0.0.29 74 + 75 + ### Patch Changes 76 + 77 + - Updated dependencies [[`b8cc9f8`](https://github.com/hey-api/openapi-ts/commit/b8cc9f8a5eaf4f4ff345abc49c14c6b96744c2ea)]: 78 + - @hey-api/client-fetch@0.8.2 79 + 80 + ## 0.0.28 81 + 82 + ### Patch Changes 83 + 84 + - Updated dependencies [[`7f0f4a7`](https://github.com/hey-api/openapi-ts/commit/7f0f4a76b06c8fafb33581b522faf8efc6fd85ac)]: 85 + - @hey-api/client-fetch@0.8.1 86 + 87 + ## 0.0.27 88 + 89 + ### Patch Changes 90 + 91 + - Updated dependencies [[`bb6d46a`](https://github.com/hey-api/openapi-ts/commit/bb6d46ae119ce4e7e3a2ab3fded74ac4fb4cdff2)]: 92 + - @hey-api/client-fetch@0.8.0 93 + 94 + ## 0.0.26 95 + 96 + ### Patch Changes 97 + 98 + - Updated dependencies [[`2dc380e`](https://github.com/hey-api/openapi-ts/commit/2dc380eabc17c723654beb04ecd7bce6d33d3b49), [`603541e`](https://github.com/hey-api/openapi-ts/commit/603541e307dc2953da7dddd300176865629b50bb), [`2cbffeb`](https://github.com/hey-api/openapi-ts/commit/2cbffeb2cdd6c6143cd68cac68369584879dda31), [`2cbffeb`](https://github.com/hey-api/openapi-ts/commit/2cbffeb2cdd6c6143cd68cac68369584879dda31)]: 99 + - @hey-api/client-fetch@0.7.3 100 + 101 + ## 0.0.25 102 + 103 + ### Patch Changes 104 + 105 + - Updated dependencies [[`8eba19d`](https://github.com/hey-api/openapi-ts/commit/8eba19d4092fc0903572ab9fdadf0b4c26928ba2)]: 106 + - @hey-api/client-fetch@0.7.2 107 + 108 + ## 0.0.24 109 + 110 + ### Patch Changes 111 + 112 + - Updated dependencies [[`0432418`](https://github.com/hey-api/openapi-ts/commit/0432418d72c94ef94865f8216ed2f723ad5191f9), [`4784727`](https://github.com/hey-api/openapi-ts/commit/47847276e8bc854045044dd414382080270dd779)]: 113 + - @hey-api/client-fetch@0.7.1 114 + 115 + ## 0.0.23 116 + 117 + ### Patch Changes 118 + 119 + - Updated dependencies [[`465410c`](https://github.com/hey-api/openapi-ts/commit/465410c201eb19e737e3143ad53a146e95f80107)]: 120 + - @hey-api/client-fetch@0.7.0 121 + 122 + ## 0.0.22 123 + 124 + ### Patch Changes 125 + 126 + - Updated dependencies [[`e2e1410`](https://github.com/hey-api/openapi-ts/commit/e2e1410b22c0c84c40d1b1803e9650d546350cb7)]: 127 + - @hey-api/client-fetch@0.6.0 128 + 129 + ## 0.0.21 130 + 131 + ### Patch Changes 132 + 133 + - Updated dependencies [[`20d7497`](https://github.com/hey-api/openapi-ts/commit/20d7497acb6c046f6a4206c2d8137414e17b2263), [`f86d293`](https://github.com/hey-api/openapi-ts/commit/f86d293f18f133ef6dd2f4864d037611b81edd26)]: 134 + - @hey-api/client-fetch@0.5.7 135 + 136 + ## 0.0.20 137 + 138 + ### Patch Changes 139 + 140 + - Updated dependencies [[`ba56424`](https://github.com/hey-api/openapi-ts/commit/ba5642486cdd5461c2372c34b63019c02bc6874e)]: 141 + - @hey-api/client-fetch@0.5.6 142 + 143 + ## 0.0.19 144 + 145 + ### Patch Changes 146 + 147 + - Updated dependencies [[`9cec9e8`](https://github.com/hey-api/openapi-ts/commit/9cec9e8582c12a8c041b922d9587e16f6f19782a)]: 148 + - @hey-api/client-fetch@0.5.5 149 + 150 + ## 0.0.18 151 + 152 + ### Patch Changes 153 + 154 + - Updated dependencies [[`cbf4e84`](https://github.com/hey-api/openapi-ts/commit/cbf4e84db7f3a47f19d8c3eaa87c71b27912c1a2)]: 155 + - @hey-api/client-fetch@0.5.4 156 + 157 + ## 0.0.17 158 + 159 + ### Patch Changes 160 + 161 + - Updated dependencies [[`646064d`](https://github.com/hey-api/openapi-ts/commit/646064d1aecea988d2b4df73bd24b2ee83394ae0)]: 162 + - @hey-api/client-fetch@0.5.3 163 + 164 + ## 0.0.16 165 + 166 + ### Patch Changes 167 + 168 + - Updated dependencies [[`ec48d32`](https://github.com/hey-api/openapi-ts/commit/ec48d323d80de8e6a47ce7ecd732288f0a47e17a)]: 169 + - @hey-api/client-fetch@0.5.2 170 + 171 + ## 0.0.15 172 + 173 + ### Patch Changes 174 + 175 + - Updated dependencies [[`fa8b0f1`](https://github.com/hey-api/openapi-ts/commit/fa8b0f11ed99c63f694a494944ccc2fbfa9706cc)]: 176 + - @hey-api/client-fetch@0.5.1 177 + 178 + ## 0.0.14 179 + 180 + ### Patch Changes 181 + 182 + - Updated dependencies [[`734a62d`](https://github.com/hey-api/openapi-ts/commit/734a62dd8d594b8266964fe16766a481d37eb7df), [`734a62d`](https://github.com/hey-api/openapi-ts/commit/734a62dd8d594b8266964fe16766a481d37eb7df)]: 183 + - @hey-api/client-fetch@0.5.0 184 + 185 + ## 0.0.13 186 + 187 + ### Patch Changes 188 + 189 + - Updated dependencies [[`4c853d0`](https://github.com/hey-api/openapi-ts/commit/4c853d090b79245854d13831f64731db4a92978b)]: 190 + - @hey-api/client-fetch@0.4.4 191 + 192 + ## 0.0.12 193 + 194 + ### Patch Changes 195 + 196 + - Updated dependencies [[`01dee3d`](https://github.com/hey-api/openapi-ts/commit/01dee3df879232939e43355231147b3d910fb482)]: 197 + - @hey-api/client-fetch@0.4.3 198 + 199 + ## 0.0.11 200 + 201 + ### Patch Changes 202 + 203 + - [#1151](https://github.com/hey-api/openapi-ts/pull/1151) [`587791d`](https://github.com/hey-api/openapi-ts/commit/587791dfede0167fbed229281467e4c4875936f5) Thanks [@mrlubos](https://github.com/mrlubos)! - fix: update website domain, add license documentation 204 + 205 + - Updated dependencies [[`587791d`](https://github.com/hey-api/openapi-ts/commit/587791dfede0167fbed229281467e4c4875936f5)]: 206 + - @hey-api/client-fetch@0.4.2 207 + 208 + ## 0.0.10 209 + 210 + ### Patch Changes 211 + 212 + - Updated dependencies [[`a0a5551`](https://github.com/hey-api/openapi-ts/commit/a0a55510d30a1a8dea0ade4908b5b13d51b5f9e6)]: 213 + - @hey-api/client-fetch@0.4.1 214 + 215 + ## 0.0.9 216 + 217 + ### Patch Changes 218 + 219 + - Updated dependencies [[`df5c690`](https://github.com/hey-api/openapi-ts/commit/df5c69048a03a1c7729a5200c586164287a8a6fa), [`df5c690`](https://github.com/hey-api/openapi-ts/commit/df5c69048a03a1c7729a5200c586164287a8a6fa)]: 220 + - @hey-api/client-fetch@0.4.0 221 + 222 + ## 0.0.8 223 + 224 + ### Patch Changes 225 + 226 + - Updated dependencies [[`7f986c2`](https://github.com/hey-api/openapi-ts/commit/7f986c2c7726ed8fbf16f8b235b7769c7d990502)]: 227 + - @hey-api/client-fetch@0.3.4 228 + 229 + ## 0.0.7 230 + 231 + ### Patch Changes 232 + 233 + - Updated dependencies [[`fe743c2`](https://github.com/hey-api/openapi-ts/commit/fe743c2d41c23bf7e1706bceedd6319299131197)]: 234 + - @hey-api/client-fetch@0.3.3 235 + 236 + ## 0.0.6 237 + 238 + ### Patch Changes 239 + 240 + - Updated dependencies [[`11a276a`](https://github.com/hey-api/openapi-ts/commit/11a276a1e35dde0735363e892d8142016fd87eec)]: 241 + - @hey-api/client-fetch@0.3.2 242 + 243 + ## 0.0.5 244 + 245 + ### Patch Changes 246 + 247 + - Updated dependencies [[`7ae2b1d`](https://github.com/hey-api/openapi-ts/commit/7ae2b1db047f3b6efe917a8b43ac7c851fb86c8f), [`2079c6e`](https://github.com/hey-api/openapi-ts/commit/2079c6e83a6b71e157c8e7ea56260b4e9ff8411d)]: 248 + - @hey-api/client-fetch@0.3.1 249 + 250 + ## 0.0.4 251 + 252 + ### Patch Changes 253 + 254 + - Updated dependencies [[`7ebc1d4`](https://github.com/hey-api/openapi-ts/commit/7ebc1d44af74db2522219d71d240325f6bc5689d)]: 255 + - @hey-api/client-fetch@0.3.0 256 + 257 + ## 0.0.3 258 + 259 + ### Patch Changes 260 + 261 + - [#1010](https://github.com/hey-api/openapi-ts/pull/1010) [`b6e58c6`](https://github.com/hey-api/openapi-ts/commit/b6e58c64d1b71897533a85d1738cd7ce7ede178d) Thanks [@mrlubos](https://github.com/mrlubos)! - fix: set query key base url from supplied client if provided 262 + 263 + ## 0.0.2 264 + 265 + ### Patch Changes 266 + 267 + - [#978](https://github.com/hey-api/openapi-ts/pull/978) [`2e051a5`](https://github.com/hey-api/openapi-ts/commit/2e051a596302c2e103dca25951a07b4aae1e9e23) Thanks [@mrlubos](https://github.com/mrlubos)! - docs: add basic TanStack Query plugin description 268 + 269 + ## 0.0.1 270 + 271 + ### Patch Changes 272 + 273 + - [#901](https://github.com/hey-api/openapi-ts/pull/901) [`8ac24a6`](https://github.com/hey-api/openapi-ts/commit/8ac24a63eca2b890899ba9f6fa908b6ed0ae80d3) Thanks [@mrlubos](https://github.com/mrlubos)! - docs: add TanStack Vue Query example 274 + 275 + - Updated dependencies [[`a8c84c0`](https://github.com/hey-api/openapi-ts/commit/a8c84c02dbb5ef1a59f5d414dff425e135c7a446), [`7825a2f`](https://github.com/hey-api/openapi-ts/commit/7825a2fba566a76c63775172ef0569ef375406b6)]: 276 + - @hey-api/client-fetch@0.2.4
+45
examples/openapi-ts-pinia-colada/README.md
··· 1 + # @hey-api/openapi-ts with Pinia Colada Example 2 + 3 + This example demonstrates how to use @hey-api/openapi-ts with Pinia Colada for Vue 3 applications. 4 + 5 + ## Recommended IDE Setup 6 + 7 + [VSCode](https://code.visualstudio.com) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). 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 [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. 12 + 13 + ## Customize configuration 14 + 15 + See [Vite Configuration Reference](https://vitejs.dev/config). 16 + 17 + ## Project Setup 18 + 19 + ```sh 20 + pnpm install 21 + ``` 22 + 23 + ### Compile and Hot-Reload for Development 24 + 25 + ```sh 26 + pnpm dev 27 + ``` 28 + 29 + ### Type-Check, Compile and Minify for Production 30 + 31 + ```sh 32 + pnpm build 33 + ``` 34 + 35 + ### Run Unit Tests with [Vitest](https://vitest.dev) 36 + 37 + ```sh 38 + pnpm test:unit 39 + ``` 40 + 41 + ### Lint with [ESLint](https://eslint.org) 42 + 43 + ```sh 44 + pnpm lint 45 + ```
+1
examples/openapi-ts-pinia-colada/env.d.ts
··· 1 + /// <reference types="vite/client" />
+13
examples/openapi-ts-pinia-colada/index.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <link rel="icon" href="/favicon.ico" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 + <title>Hey API + TanStack Vue Query Demo</title> 8 + </head> 9 + <body> 10 + <div id="app"></div> 11 + <script type="module" src="/src/main.ts"></script> 12 + </body> 13 + </html>
+21
examples/openapi-ts-pinia-colada/openapi-ts.config.ts
··· 1 + import { defineConfig } from '@hey-api/openapi-ts' 2 + 3 + export default defineConfig({ 4 + input: 5 + 'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml', 6 + output: { 7 + format: 'prettier', 8 + lint: 'eslint', 9 + path: './src/client' 10 + }, 11 + plugins: [ 12 + '@hey-api/client-fetch', 13 + '@hey-api/schemas', 14 + '@hey-api/sdk', 15 + { 16 + enums: 'javascript', 17 + name: '@hey-api/typescript' 18 + }, 19 + '@pinia/colada' 20 + ] 21 + })
+50
examples/openapi-ts-pinia-colada/package.json
··· 1 + { 2 + "name": "@example/openapi-ts-pinia-colada", 3 + "private": true, 4 + "version": "0.0.39", 5 + "type": "module", 6 + "scripts": { 7 + "build-only": "vite build", 8 + "build": "run-p typecheck \"build-only {@}\" --", 9 + "dev": "vite", 10 + "format": "prettier --write src/", 11 + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", 12 + "openapi-ts": "openapi-ts", 13 + "preview": "vite preview", 14 + "test:unit": "vitest", 15 + "typecheck": "vue-tsc --build --force" 16 + }, 17 + "dependencies": { 18 + "@pinia/colada": "0.17.0", 19 + "pinia": "2.3.0", 20 + "vue": "3.5.13", 21 + "vue-router": "4.5.0" 22 + }, 23 + "devDependencies": { 24 + "@config/vite-base": "workspace:*", 25 + "@hey-api/openapi-ts": "workspace:*", 26 + "@rushstack/eslint-patch": "1.10.5", 27 + "@tsconfig/node20": "20.1.4", 28 + "@types/jsdom": "21.1.7", 29 + "@types/node": "22.10.5", 30 + "@vitejs/plugin-vue": "5.2.1", 31 + "@vitejs/plugin-vue-jsx": "4.1.1", 32 + "@vue/eslint-config-prettier": "10.1.0", 33 + "@vue/eslint-config-typescript": "14.2.0", 34 + "@vue/test-utils": "2.4.6", 35 + "@vue/tsconfig": "0.7.0", 36 + "autoprefixer": "10.4.20", 37 + "eslint": "9.17.0", 38 + "eslint-plugin-vue": "9.32.0", 39 + "jsdom": "23.0.0", 40 + "npm-run-all2": "6.2.0", 41 + "postcss": "8.4.41", 42 + "prettier": "3.4.2", 43 + "tailwindcss": "3.4.9", 44 + "typescript": "5.8.3", 45 + "vite": "7.1.2", 46 + "vite-plugin-vue-devtools": "7.7.0", 47 + "vitest": "3.1.1", 48 + "vue-tsc": "2.2.0" 49 + } 50 + }
+6
examples/openapi-ts-pinia-colada/postcss.config.js
··· 1 + export default { 2 + plugins: { 3 + autoprefixer: {}, 4 + tailwindcss: {} 5 + } 6 + }
+9
examples/openapi-ts-pinia-colada/src/App.vue
··· 1 + <script setup lang="ts"> 2 + import { RouterView } from 'vue-router' 3 + </script> 4 + 5 + <template> 6 + <div> 7 + <RouterView /> 8 + </div> 9 + </template>
+7
examples/openapi-ts-pinia-colada/src/assets/main.css
··· 1 + @tailwind base; 2 + @tailwind components; 3 + @tailwind utilities; 4 + 5 + body { 6 + @apply bg-[#111113]; 7 + }
+394
examples/openapi-ts-pinia-colada/src/client/@pinia/colada.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + /* eslint-disable @typescript-eslint/no-unused-vars */ 4 + import { client as _heyApiClient } from '../client.gen' 5 + import { 6 + addPet, 7 + createUser, 8 + createUsersWithListInput, 9 + deleteOrder, 10 + deletePet, 11 + deleteUser, 12 + findPetsByStatus, 13 + findPetsByTags, 14 + getInventory, 15 + getOrderById, 16 + getPetById, 17 + getUserByName, 18 + loginUser, 19 + logoutUser, 20 + type Options, 21 + placeOrder, 22 + updatePet, 23 + updatePetWithForm, 24 + updateUser, 25 + uploadFile 26 + } from '../sdk.gen' 27 + import type { 28 + AddPetData, 29 + CreateUserData, 30 + CreateUsersWithListInputData, 31 + DeleteOrderData, 32 + DeletePetData, 33 + DeleteUserData, 34 + FindPetsByStatusData, 35 + FindPetsByTagsData, 36 + GetInventoryData, 37 + GetOrderByIdData, 38 + GetPetByIdData, 39 + GetUserByNameData, 40 + LoginUserData, 41 + LogoutUserData, 42 + PlaceOrderData, 43 + UpdatePetData, 44 + UpdatePetWithFormData, 45 + UpdateUserData, 46 + UploadFileData 47 + } from '../types.gen' 48 + 49 + /** 50 + * Add a new pet to the store. 51 + * Add a new pet to the store. 52 + */ 53 + export const addPetQuery = (options: Options<AddPetData>) => ({ 54 + key: ['addPet', options?.path], 55 + query: async (context: { signal: AbortSignal }) => { 56 + const { data } = await addPet({ 57 + ...options, 58 + signal: context.signal, 59 + throwOnError: true 60 + }) 61 + return data 62 + } 63 + }) 64 + 65 + /** 66 + * Add a new pet to the store. 67 + * Add a new pet to the store. 68 + */ 69 + export const addPetMutation = (options?: Options<AddPetData>) => ({ 70 + mutation: async (options: Options<AddPetData>) => { 71 + const { data } = await addPet(options) 72 + return data 73 + } 74 + }) 75 + 76 + /** 77 + * Update an existing pet. 78 + * Update an existing pet by Id. 79 + */ 80 + export const updatePetMutation = (options?: Options<UpdatePetData>) => ({ 81 + mutation: async (options: Options<UpdatePetData>) => { 82 + const { data } = await updatePet(options) 83 + return data 84 + } 85 + }) 86 + 87 + /** 88 + * Finds Pets by status. 89 + * Multiple status values can be provided with comma separated strings. 90 + */ 91 + export const findPetsByStatusQuery = (options: Options<FindPetsByStatusData>) => ({ 92 + key: ['findPetsByStatus', options?.path], 93 + query: async (context: { signal: AbortSignal }) => { 94 + const { data } = await findPetsByStatus({ 95 + ...options, 96 + signal: context.signal, 97 + throwOnError: true 98 + }) 99 + return data 100 + } 101 + }) 102 + 103 + /** 104 + * Finds Pets by tags. 105 + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. 106 + */ 107 + export const findPetsByTagsQuery = (options: Options<FindPetsByTagsData>) => ({ 108 + key: ['findPetsByTags', options?.path], 109 + query: async (context: { signal: AbortSignal }) => { 110 + const { data } = await findPetsByTags({ 111 + ...options, 112 + signal: context.signal, 113 + throwOnError: true 114 + }) 115 + return data 116 + } 117 + }) 118 + 119 + /** 120 + * Deletes a pet. 121 + * Delete a pet. 122 + */ 123 + export const deletePetMutation = (options?: Options<DeletePetData>) => ({ 124 + mutation: async (options: Options<DeletePetData>) => { 125 + const { data } = await deletePet(options) 126 + return data 127 + } 128 + }) 129 + 130 + /** 131 + * Find pet by ID. 132 + * Returns a single pet. 133 + */ 134 + export const getPetByIdQuery = (options: Options<GetPetByIdData>) => ({ 135 + key: ['getPetById', options?.path], 136 + query: async (context: { signal: AbortSignal }) => { 137 + const { data } = await getPetById({ 138 + ...options, 139 + signal: context.signal, 140 + throwOnError: true 141 + }) 142 + return data 143 + } 144 + }) 145 + 146 + /** 147 + * Updates a pet in the store with form data. 148 + * Updates a pet resource based on the form data. 149 + */ 150 + export const updatePetWithFormQuery = (options: Options<UpdatePetWithFormData>) => ({ 151 + key: ['updatePetWithForm', options?.path], 152 + query: async (context: { signal: AbortSignal }) => { 153 + const { data } = await updatePetWithForm({ 154 + ...options, 155 + signal: context.signal, 156 + throwOnError: true 157 + }) 158 + return data 159 + } 160 + }) 161 + 162 + /** 163 + * Updates a pet in the store with form data. 164 + * Updates a pet resource based on the form data. 165 + */ 166 + export const updatePetWithFormMutation = (options?: Options<UpdatePetWithFormData>) => ({ 167 + mutation: async (options: Options<UpdatePetWithFormData>) => { 168 + const { data } = await updatePetWithForm(options) 169 + return data 170 + } 171 + }) 172 + 173 + /** 174 + * Uploads an image. 175 + * Upload image of the pet. 176 + */ 177 + export const uploadFileQuery = (options: Options<UploadFileData>) => ({ 178 + key: ['uploadFile', options?.path], 179 + query: async (context: { signal: AbortSignal }) => { 180 + const { data } = await uploadFile({ 181 + ...options, 182 + signal: context.signal, 183 + throwOnError: true 184 + }) 185 + return data 186 + } 187 + }) 188 + 189 + /** 190 + * Uploads an image. 191 + * Upload image of the pet. 192 + */ 193 + export const uploadFileMutation = (options?: Options<UploadFileData>) => ({ 194 + mutation: async (options: Options<UploadFileData>) => { 195 + const { data } = await uploadFile(options) 196 + return data 197 + } 198 + }) 199 + 200 + /** 201 + * Returns pet inventories by status. 202 + * Returns a map of status codes to quantities. 203 + */ 204 + export const getInventoryQuery = (options?: Options<GetInventoryData>) => ({ 205 + key: ['getInventory', options?.path], 206 + query: async (context: { signal: AbortSignal }) => { 207 + const { data } = await getInventory({ 208 + ...options, 209 + signal: context.signal, 210 + throwOnError: true 211 + }) 212 + return data 213 + } 214 + }) 215 + 216 + /** 217 + * Place an order for a pet. 218 + * Place a new order in the store. 219 + */ 220 + export const placeOrderQuery = (options?: Options<PlaceOrderData>) => ({ 221 + key: ['placeOrder', options?.path], 222 + query: async (context: { signal: AbortSignal }) => { 223 + const { data } = await placeOrder({ 224 + ...options, 225 + signal: context.signal, 226 + throwOnError: true 227 + }) 228 + return data 229 + } 230 + }) 231 + 232 + /** 233 + * Place an order for a pet. 234 + * Place a new order in the store. 235 + */ 236 + export const placeOrderMutation = (options?: Options<PlaceOrderData>) => ({ 237 + mutation: async (options: Options<PlaceOrderData>) => { 238 + const { data } = await placeOrder(options) 239 + return data 240 + } 241 + }) 242 + 243 + /** 244 + * Delete purchase order by identifier. 245 + * For valid response try integer IDs with value < 1000. Anything above 1000 or non-integers will generate API errors. 246 + */ 247 + export const deleteOrderMutation = (options?: Options<DeleteOrderData>) => ({ 248 + mutation: async (options: Options<DeleteOrderData>) => { 249 + const { data } = await deleteOrder(options) 250 + return data 251 + } 252 + }) 253 + 254 + /** 255 + * Find purchase order by ID. 256 + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions. 257 + */ 258 + export const getOrderByIdQuery = (options: Options<GetOrderByIdData>) => ({ 259 + key: ['getOrderById', options?.path], 260 + query: async (context: { signal: AbortSignal }) => { 261 + const { data } = await getOrderById({ 262 + ...options, 263 + signal: context.signal, 264 + throwOnError: true 265 + }) 266 + return data 267 + } 268 + }) 269 + 270 + /** 271 + * Create user. 272 + * This can only be done by the logged in user. 273 + */ 274 + export const createUserQuery = (options?: Options<CreateUserData>) => ({ 275 + key: ['createUser', options?.path], 276 + query: async (context: { signal: AbortSignal }) => { 277 + const { data } = await createUser({ 278 + ...options, 279 + signal: context.signal, 280 + throwOnError: true 281 + }) 282 + return data 283 + } 284 + }) 285 + 286 + /** 287 + * Create user. 288 + * This can only be done by the logged in user. 289 + */ 290 + export const createUserMutation = (options?: Options<CreateUserData>) => ({ 291 + mutation: async (options: Options<CreateUserData>) => { 292 + const { data } = await createUser(options) 293 + return data 294 + } 295 + }) 296 + 297 + /** 298 + * Creates list of users with given input array. 299 + * Creates list of users with given input array. 300 + */ 301 + export const createUsersWithListInputQuery = (options?: Options<CreateUsersWithListInputData>) => ({ 302 + key: ['createUsersWithListInput', options?.path], 303 + query: async (context: { signal: AbortSignal }) => { 304 + const { data } = await createUsersWithListInput({ 305 + ...options, 306 + signal: context.signal, 307 + throwOnError: true 308 + }) 309 + return data 310 + } 311 + }) 312 + 313 + /** 314 + * Creates list of users with given input array. 315 + * Creates list of users with given input array. 316 + */ 317 + export const createUsersWithListInputMutation = ( 318 + options?: Options<CreateUsersWithListInputData> 319 + ) => ({ 320 + mutation: async (options: Options<CreateUsersWithListInputData>) => { 321 + const { data } = await createUsersWithListInput(options) 322 + return data 323 + } 324 + }) 325 + 326 + /** 327 + * Logs user into the system. 328 + * Log into the system. 329 + */ 330 + export const loginUserQuery = (options?: Options<LoginUserData>) => ({ 331 + key: ['loginUser', options?.path], 332 + query: async (context: { signal: AbortSignal }) => { 333 + const { data } = await loginUser({ 334 + ...options, 335 + signal: context.signal, 336 + throwOnError: true 337 + }) 338 + return data 339 + } 340 + }) 341 + 342 + /** 343 + * Logs out current logged in user session. 344 + * Log user out of the system. 345 + */ 346 + export const logoutUserQuery = (options?: Options<LogoutUserData>) => ({ 347 + key: ['logoutUser', options?.path], 348 + query: async (context: { signal: AbortSignal }) => { 349 + const { data } = await logoutUser({ 350 + ...options, 351 + signal: context.signal, 352 + throwOnError: true 353 + }) 354 + return data 355 + } 356 + }) 357 + 358 + /** 359 + * Delete user resource. 360 + * This can only be done by the logged in user. 361 + */ 362 + export const deleteUserMutation = (options?: Options<DeleteUserData>) => ({ 363 + mutation: async (options: Options<DeleteUserData>) => { 364 + const { data } = await deleteUser(options) 365 + return data 366 + } 367 + }) 368 + 369 + /** 370 + * Get user by user name. 371 + * Get user detail based on username. 372 + */ 373 + export const getUserByNameQuery = (options: Options<GetUserByNameData>) => ({ 374 + key: ['getUserByName', options?.path], 375 + query: async (context: { signal: AbortSignal }) => { 376 + const { data } = await getUserByName({ 377 + ...options, 378 + signal: context.signal, 379 + throwOnError: true 380 + }) 381 + return data 382 + } 383 + }) 384 + 385 + /** 386 + * Update user resource. 387 + * This can only be done by the logged in user. 388 + */ 389 + export const updateUserMutation = (options?: Options<UpdateUserData>) => ({ 390 + mutation: async (options: Options<UpdateUserData>) => { 391 + const { data } = await updateUser(options) 392 + return data 393 + } 394 + })
+27
examples/openapi-ts-pinia-colada/src/client/client.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { 4 + type ClientOptions as DefaultClientOptions, 5 + type Config, 6 + createClient, 7 + createConfig 8 + } from './client' 9 + import type { ClientOptions } from './types.gen' 10 + 11 + /** 12 + * The `createClientConfig()` function will be called on client initialization 13 + * and the returned object will become the client's initial configuration. 14 + * 15 + * You may want to initialize your client this way instead of calling 16 + * `setConfig()`. This is useful for example if you're using Next.js 17 + * to ensure your client always has the correct values. 18 + */ 19 + export type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = ( 20 + override?: Config<DefaultClientOptions & T> 21 + ) => Config<Required<DefaultClientOptions> & T> 22 + 23 + export const client = createClient( 24 + createConfig<ClientOptions>({ 25 + baseUrl: 'https://petstore3.swagger.io/api/v3' 26 + }) 27 + )
+191
examples/openapi-ts-pinia-colada/src/client/client/client.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Client, Config, ResolvedRequestOptions } from './types.gen' 4 + import { 5 + buildUrl, 6 + createConfig, 7 + createInterceptors, 8 + getParseAs, 9 + mergeConfigs, 10 + mergeHeaders, 11 + setAuthParams 12 + } from './utils.gen' 13 + 14 + type ReqInit = Omit<RequestInit, 'body' | 'headers'> & { 15 + body?: any 16 + headers: ReturnType<typeof mergeHeaders> 17 + } 18 + 19 + export const createClient = (config: Config = {}): Client => { 20 + let _config = mergeConfigs(createConfig(), config) 21 + 22 + const getConfig = (): Config => ({ ..._config }) 23 + 24 + const setConfig = (config: Config): Config => { 25 + _config = mergeConfigs(_config, config) 26 + return getConfig() 27 + } 28 + 29 + const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>() 30 + 31 + const request: Client['request'] = async (options) => { 32 + const opts = { 33 + ..._config, 34 + ...options, 35 + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, 36 + headers: mergeHeaders(_config.headers, options.headers), 37 + serializedBody: undefined 38 + } 39 + 40 + if (opts.security) { 41 + await setAuthParams({ 42 + ...opts, 43 + security: opts.security 44 + }) 45 + } 46 + 47 + if (opts.requestValidator) { 48 + await opts.requestValidator(opts) 49 + } 50 + 51 + if (opts.body && opts.bodySerializer) { 52 + opts.serializedBody = opts.bodySerializer(opts.body) 53 + } 54 + 55 + // remove Content-Type header if body is empty to avoid sending invalid requests 56 + if (opts.serializedBody === undefined || opts.serializedBody === '') { 57 + opts.headers.delete('Content-Type') 58 + } 59 + 60 + const url = buildUrl(opts) 61 + const requestInit: ReqInit = { 62 + redirect: 'follow', 63 + ...opts, 64 + body: opts.serializedBody 65 + } 66 + 67 + let request = new Request(url, requestInit) 68 + 69 + for (const fn of interceptors.request._fns) { 70 + if (fn) { 71 + request = await fn(request, opts) 72 + } 73 + } 74 + 75 + // fetch must be assigned here, otherwise it would throw the error: 76 + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation 77 + const _fetch = opts.fetch! 78 + let response = await _fetch(request) 79 + 80 + for (const fn of interceptors.response._fns) { 81 + if (fn) { 82 + response = await fn(response, request, opts) 83 + } 84 + } 85 + 86 + const result = { 87 + request, 88 + response 89 + } 90 + 91 + if (response.ok) { 92 + if (response.status === 204 || response.headers.get('Content-Length') === '0') { 93 + return opts.responseStyle === 'data' 94 + ? {} 95 + : { 96 + data: {}, 97 + ...result 98 + } 99 + } 100 + 101 + const parseAs = 102 + (opts.parseAs === 'auto' 103 + ? getParseAs(response.headers.get('Content-Type')) 104 + : opts.parseAs) ?? 'json' 105 + 106 + let data: any 107 + switch (parseAs) { 108 + case 'arrayBuffer': 109 + case 'blob': 110 + case 'formData': 111 + case 'json': 112 + case 'text': 113 + data = await response[parseAs]() 114 + break 115 + case 'stream': 116 + return opts.responseStyle === 'data' 117 + ? response.body 118 + : { 119 + data: response.body, 120 + ...result 121 + } 122 + } 123 + 124 + if (parseAs === 'json') { 125 + if (opts.responseValidator) { 126 + await opts.responseValidator(data) 127 + } 128 + 129 + if (opts.responseTransformer) { 130 + data = await opts.responseTransformer(data) 131 + } 132 + } 133 + 134 + return opts.responseStyle === 'data' 135 + ? data 136 + : { 137 + data, 138 + ...result 139 + } 140 + } 141 + 142 + const textError = await response.text() 143 + let jsonError: unknown 144 + 145 + try { 146 + jsonError = JSON.parse(textError) 147 + } catch { 148 + // noop 149 + } 150 + 151 + const error = jsonError ?? textError 152 + let finalError = error 153 + 154 + for (const fn of interceptors.error._fns) { 155 + if (fn) { 156 + finalError = (await fn(error, response, request, opts)) as string 157 + } 158 + } 159 + 160 + finalError = finalError || ({} as string) 161 + 162 + if (opts.throwOnError) { 163 + throw finalError 164 + } 165 + 166 + // TODO: we probably want to return error and improve types 167 + return opts.responseStyle === 'data' 168 + ? undefined 169 + : { 170 + error: finalError, 171 + ...result 172 + } 173 + } 174 + 175 + return { 176 + buildUrl, 177 + connect: (options) => request({ ...options, method: 'CONNECT' }), 178 + delete: (options) => request({ ...options, method: 'DELETE' }), 179 + get: (options) => request({ ...options, method: 'GET' }), 180 + getConfig, 181 + head: (options) => request({ ...options, method: 'HEAD' }), 182 + interceptors, 183 + options: (options) => request({ ...options, method: 'OPTIONS' }), 184 + patch: (options) => request({ ...options, method: 'PATCH' }), 185 + post: (options) => request({ ...options, method: 'POST' }), 186 + put: (options) => request({ ...options, method: 'PUT' }), 187 + request, 188 + setConfig, 189 + trace: (options) => request({ ...options, method: 'TRACE' }) 190 + } 191 + }
+25
examples/openapi-ts-pinia-colada/src/client/client/index.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type { Auth } from '../core/auth.gen' 4 + export type { QuerySerializerOptions } from '../core/bodySerializer.gen' 5 + export { 6 + formDataBodySerializer, 7 + jsonBodySerializer, 8 + urlSearchParamsBodySerializer 9 + } from '../core/bodySerializer.gen' 10 + export { buildClientParams } from '../core/params.gen' 11 + export { createClient } from './client.gen' 12 + export type { 13 + Client, 14 + ClientOptions, 15 + Config, 16 + CreateClientConfig, 17 + Options, 18 + OptionsLegacyParser, 19 + RequestOptions, 20 + RequestResult, 21 + ResolvedRequestOptions, 22 + ResponseStyle, 23 + TDataShape 24 + } from './types.gen' 25 + export { createConfig, mergeHeaders } from './utils.gen'
+202
examples/openapi-ts-pinia-colada/src/client/client/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Auth } from '../core/auth.gen' 4 + import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen' 5 + import type { Middleware } from './utils.gen' 6 + 7 + export type ResponseStyle = 'data' | 'fields' 8 + 9 + export interface Config<T extends ClientOptions = ClientOptions> 10 + extends Omit<RequestInit, 'body' | 'headers' | 'method'>, 11 + CoreConfig { 12 + /** 13 + * Base URL for all requests made by this client. 14 + */ 15 + baseUrl?: T['baseUrl'] 16 + /** 17 + * Fetch API implementation. You can use this option to provide a custom 18 + * fetch instance. 19 + * 20 + * @default globalThis.fetch 21 + */ 22 + fetch?: (request: Request) => ReturnType<typeof fetch> 23 + /** 24 + * Please don't use the Fetch client for Next.js applications. The `next` 25 + * options won't have any effect. 26 + * 27 + * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. 28 + */ 29 + next?: never 30 + /** 31 + * Return the response data parsed in a specified format. By default, `auto` 32 + * will infer the appropriate method from the `Content-Type` response header. 33 + * You can override this behavior with any of the {@link Body} methods. 34 + * Select `stream` if you don't want to parse response data at all. 35 + * 36 + * @default 'auto' 37 + */ 38 + parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text' 39 + /** 40 + * Should we return only data or multiple fields (data, error, response, etc.)? 41 + * 42 + * @default 'fields' 43 + */ 44 + responseStyle?: ResponseStyle 45 + /** 46 + * Throw an error instead of returning it in the response? 47 + * 48 + * @default false 49 + */ 50 + throwOnError?: T['throwOnError'] 51 + } 52 + 53 + export interface RequestOptions< 54 + TResponseStyle extends ResponseStyle = 'fields', 55 + ThrowOnError extends boolean = boolean, 56 + Url extends string = string 57 + > extends Config<{ 58 + responseStyle: TResponseStyle 59 + throwOnError: ThrowOnError 60 + }> { 61 + /** 62 + * Any body that you want to add to your request. 63 + * 64 + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} 65 + */ 66 + body?: unknown 67 + path?: Record<string, unknown> 68 + query?: Record<string, unknown> 69 + /** 70 + * Security mechanism(s) to use for the request. 71 + */ 72 + security?: ReadonlyArray<Auth> 73 + url: Url 74 + } 75 + 76 + export interface ResolvedRequestOptions< 77 + TResponseStyle extends ResponseStyle = 'fields', 78 + ThrowOnError extends boolean = boolean, 79 + Url extends string = string 80 + > extends RequestOptions<TResponseStyle, ThrowOnError, Url> { 81 + serializedBody?: string 82 + } 83 + 84 + export type RequestResult< 85 + TData = unknown, 86 + TError = unknown, 87 + ThrowOnError extends boolean = boolean, 88 + TResponseStyle extends ResponseStyle = 'fields' 89 + > = ThrowOnError extends true 90 + ? Promise< 91 + TResponseStyle extends 'data' 92 + ? TData extends Record<string, unknown> 93 + ? TData[keyof TData] 94 + : TData 95 + : { 96 + data: TData extends Record<string, unknown> ? TData[keyof TData] : TData 97 + request: Request 98 + response: Response 99 + } 100 + > 101 + : Promise< 102 + TResponseStyle extends 'data' 103 + ? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined 104 + : ( 105 + | { 106 + data: TData extends Record<string, unknown> ? TData[keyof TData] : TData 107 + error: undefined 108 + } 109 + | { 110 + data: undefined 111 + error: TError extends Record<string, unknown> ? TError[keyof TError] : TError 112 + } 113 + ) & { 114 + request: Request 115 + response: Response 116 + } 117 + > 118 + 119 + export interface ClientOptions { 120 + baseUrl?: string 121 + responseStyle?: ResponseStyle 122 + throwOnError?: boolean 123 + } 124 + 125 + type MethodFn = < 126 + TData = unknown, 127 + TError = unknown, 128 + ThrowOnError extends boolean = false, 129 + TResponseStyle extends ResponseStyle = 'fields' 130 + >( 131 + options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'> 132 + ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle> 133 + 134 + type RequestFn = < 135 + TData = unknown, 136 + TError = unknown, 137 + ThrowOnError extends boolean = false, 138 + TResponseStyle extends ResponseStyle = 'fields' 139 + >( 140 + options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'> & 141 + Pick<Required<RequestOptions<TResponseStyle, ThrowOnError>>, 'method'> 142 + ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle> 143 + 144 + type BuildUrlFn = < 145 + TData extends { 146 + body?: unknown 147 + path?: Record<string, unknown> 148 + query?: Record<string, unknown> 149 + url: string 150 + } 151 + >( 152 + options: Pick<TData, 'url'> & Options<TData> 153 + ) => string 154 + 155 + export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & { 156 + interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions> 157 + } 158 + 159 + /** 160 + * The `createClientConfig()` function will be called on client initialization 161 + * and the returned object will become the client's initial configuration. 162 + * 163 + * You may want to initialize your client this way instead of calling 164 + * `setConfig()`. This is useful for example if you're using Next.js 165 + * to ensure your client always has the correct values. 166 + */ 167 + export type CreateClientConfig<T extends ClientOptions = ClientOptions> = ( 168 + override?: Config<ClientOptions & T> 169 + ) => Config<Required<ClientOptions> & T> 170 + 171 + export interface TDataShape { 172 + body?: unknown 173 + headers?: unknown 174 + path?: unknown 175 + query?: unknown 176 + url: string 177 + } 178 + 179 + type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>> 180 + 181 + export type Options< 182 + TData extends TDataShape = TDataShape, 183 + ThrowOnError extends boolean = boolean, 184 + TResponseStyle extends ResponseStyle = 'fields' 185 + > = OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'path' | 'query' | 'url'> & 186 + Omit<TData, 'url'> 187 + 188 + export type OptionsLegacyParser< 189 + TData = unknown, 190 + ThrowOnError extends boolean = boolean, 191 + TResponseStyle extends ResponseStyle = 'fields' 192 + > = TData extends { body?: any } 193 + ? TData extends { headers?: any } 194 + ? OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'headers' | 'url'> & TData 195 + : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'url'> & 196 + TData & 197 + Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'headers'> 198 + : TData extends { headers?: any } 199 + ? OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'headers' | 'url'> & 200 + TData & 201 + Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'body'> 202 + : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'url'> & TData
+417
examples/openapi-ts-pinia-colada/src/client/client/utils.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import { getAuthToken } from '../core/auth.gen' 4 + import type { QuerySerializer, QuerySerializerOptions } from '../core/bodySerializer.gen' 5 + import { jsonBodySerializer } from '../core/bodySerializer.gen' 6 + import { 7 + serializeArrayParam, 8 + serializeObjectParam, 9 + serializePrimitiveParam 10 + } from '../core/pathSerializer.gen' 11 + import type { Client, ClientOptions, Config, RequestOptions } from './types.gen' 12 + 13 + interface PathSerializer { 14 + path: Record<string, unknown> 15 + url: string 16 + } 17 + 18 + const PATH_PARAM_RE = /\{[^{}]+\}/g 19 + 20 + type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited' 21 + type MatrixStyle = 'label' | 'matrix' | 'simple' 22 + type ArraySeparatorStyle = ArrayStyle | MatrixStyle 23 + 24 + const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { 25 + let url = _url 26 + const matches = _url.match(PATH_PARAM_RE) 27 + if (matches) { 28 + for (const match of matches) { 29 + let explode = false 30 + let name = match.substring(1, match.length - 1) 31 + let style: ArraySeparatorStyle = 'simple' 32 + 33 + if (name.endsWith('*')) { 34 + explode = true 35 + name = name.substring(0, name.length - 1) 36 + } 37 + 38 + if (name.startsWith('.')) { 39 + name = name.substring(1) 40 + style = 'label' 41 + } else if (name.startsWith(';')) { 42 + name = name.substring(1) 43 + style = 'matrix' 44 + } 45 + 46 + const value = path[name] 47 + 48 + if (value === undefined || value === null) { 49 + continue 50 + } 51 + 52 + if (Array.isArray(value)) { 53 + url = url.replace(match, serializeArrayParam({ explode, name, style, value })) 54 + continue 55 + } 56 + 57 + if (typeof value === 'object') { 58 + url = url.replace( 59 + match, 60 + serializeObjectParam({ 61 + explode, 62 + name, 63 + style, 64 + value: value as Record<string, unknown>, 65 + valueOnly: true 66 + }) 67 + ) 68 + continue 69 + } 70 + 71 + if (style === 'matrix') { 72 + url = url.replace( 73 + match, 74 + `;${serializePrimitiveParam({ 75 + name, 76 + value: value as string 77 + })}` 78 + ) 79 + continue 80 + } 81 + 82 + const replaceValue = encodeURIComponent( 83 + style === 'label' ? `.${value as string}` : (value as string) 84 + ) 85 + url = url.replace(match, replaceValue) 86 + } 87 + } 88 + return url 89 + } 90 + 91 + export const createQuerySerializer = <T = unknown>({ 92 + allowReserved, 93 + array, 94 + object 95 + }: QuerySerializerOptions = {}) => { 96 + const querySerializer = (queryParams: T) => { 97 + const search: string[] = [] 98 + if (queryParams && typeof queryParams === 'object') { 99 + for (const name in queryParams) { 100 + const value = queryParams[name] 101 + 102 + if (value === undefined || value === null) { 103 + continue 104 + } 105 + 106 + if (Array.isArray(value)) { 107 + const serializedArray = serializeArrayParam({ 108 + allowReserved, 109 + explode: true, 110 + name, 111 + style: 'form', 112 + value, 113 + ...array 114 + }) 115 + if (serializedArray) search.push(serializedArray) 116 + } else if (typeof value === 'object') { 117 + const serializedObject = serializeObjectParam({ 118 + allowReserved, 119 + explode: true, 120 + name, 121 + style: 'deepObject', 122 + value: value as Record<string, unknown>, 123 + ...object 124 + }) 125 + if (serializedObject) search.push(serializedObject) 126 + } else { 127 + const serializedPrimitive = serializePrimitiveParam({ 128 + allowReserved, 129 + name, 130 + value: value as string 131 + }) 132 + if (serializedPrimitive) search.push(serializedPrimitive) 133 + } 134 + } 135 + } 136 + return search.join('&') 137 + } 138 + return querySerializer 139 + } 140 + 141 + /** 142 + * Infers parseAs value from provided Content-Type header. 143 + */ 144 + export const getParseAs = (contentType: string | null): Exclude<Config['parseAs'], 'auto'> => { 145 + if (!contentType) { 146 + // If no Content-Type header is provided, the best we can do is return the raw response body, 147 + // which is effectively the same as the 'stream' option. 148 + return 'stream' 149 + } 150 + 151 + const cleanContent = contentType.split(';')[0]?.trim() 152 + 153 + if (!cleanContent) { 154 + return 155 + } 156 + 157 + if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) { 158 + return 'json' 159 + } 160 + 161 + if (cleanContent === 'multipart/form-data') { 162 + return 'formData' 163 + } 164 + 165 + if ( 166 + ['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type)) 167 + ) { 168 + return 'blob' 169 + } 170 + 171 + if (cleanContent.startsWith('text/')) { 172 + return 'text' 173 + } 174 + 175 + return 176 + } 177 + 178 + const checkForExistence = ( 179 + options: Pick<RequestOptions, 'auth' | 'query'> & { 180 + headers: Headers 181 + }, 182 + name?: string 183 + ): boolean => { 184 + if (!name) { 185 + return false 186 + } 187 + if ( 188 + options.headers.has(name) || 189 + options.query?.[name] || 190 + options.headers.get('Cookie')?.includes(`${name}=`) 191 + ) { 192 + return true 193 + } 194 + return false 195 + } 196 + 197 + export const setAuthParams = async ({ 198 + security, 199 + ...options 200 + }: Pick<Required<RequestOptions>, 'security'> & 201 + Pick<RequestOptions, 'auth' | 'query'> & { 202 + headers: Headers 203 + }) => { 204 + for (const auth of security) { 205 + if (checkForExistence(options, auth.name)) { 206 + continue 207 + } 208 + 209 + const token = await getAuthToken(auth, options.auth) 210 + 211 + if (!token) { 212 + continue 213 + } 214 + 215 + const name = auth.name ?? 'Authorization' 216 + 217 + switch (auth.in) { 218 + case 'query': 219 + if (!options.query) { 220 + options.query = {} 221 + } 222 + options.query[name] = token 223 + break 224 + case 'cookie': 225 + options.headers.append('Cookie', `${name}=${token}`) 226 + break 227 + case 'header': 228 + default: 229 + options.headers.set(name, token) 230 + break 231 + } 232 + } 233 + } 234 + 235 + export const buildUrl: Client['buildUrl'] = (options) => { 236 + const url = getUrl({ 237 + baseUrl: options.baseUrl as string, 238 + path: options.path, 239 + query: options.query, 240 + querySerializer: 241 + typeof options.querySerializer === 'function' 242 + ? options.querySerializer 243 + : createQuerySerializer(options.querySerializer), 244 + url: options.url 245 + }) 246 + return url 247 + } 248 + 249 + export const getUrl = ({ 250 + baseUrl, 251 + path, 252 + query, 253 + querySerializer, 254 + url: _url 255 + }: { 256 + baseUrl?: string 257 + path?: Record<string, unknown> 258 + query?: Record<string, unknown> 259 + querySerializer: QuerySerializer 260 + url: string 261 + }) => { 262 + const pathUrl = _url.startsWith('/') ? _url : `/${_url}` 263 + let url = (baseUrl ?? '') + pathUrl 264 + if (path) { 265 + url = defaultPathSerializer({ path, url }) 266 + } 267 + let search = query ? querySerializer(query) : '' 268 + if (search.startsWith('?')) { 269 + search = search.substring(1) 270 + } 271 + if (search) { 272 + url += `?${search}` 273 + } 274 + return url 275 + } 276 + 277 + export const mergeConfigs = (a: Config, b: Config): Config => { 278 + const config = { ...a, ...b } 279 + if (config.baseUrl?.endsWith('/')) { 280 + config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1) 281 + } 282 + config.headers = mergeHeaders(a.headers, b.headers) 283 + return config 284 + } 285 + 286 + export const mergeHeaders = ( 287 + ...headers: Array<Required<Config>['headers'] | undefined> 288 + ): Headers => { 289 + const mergedHeaders = new Headers() 290 + for (const header of headers) { 291 + if (!header || typeof header !== 'object') { 292 + continue 293 + } 294 + 295 + const iterator = header instanceof Headers ? header.entries() : Object.entries(header) 296 + 297 + for (const [key, value] of iterator) { 298 + if (value === null) { 299 + mergedHeaders.delete(key) 300 + } else if (Array.isArray(value)) { 301 + for (const v of value) { 302 + mergedHeaders.append(key, v as string) 303 + } 304 + } else if (value !== undefined) { 305 + // assume object headers are meant to be JSON stringified, i.e. their 306 + // content value in OpenAPI specification is 'application/json' 307 + mergedHeaders.set( 308 + key, 309 + typeof value === 'object' ? JSON.stringify(value) : (value as string) 310 + ) 311 + } 312 + } 313 + } 314 + return mergedHeaders 315 + } 316 + 317 + type ErrInterceptor<Err, Res, Req, Options> = ( 318 + error: Err, 319 + response: Res, 320 + request: Req, 321 + options: Options 322 + ) => Err | Promise<Err> 323 + 324 + type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req> 325 + 326 + type ResInterceptor<Res, Req, Options> = ( 327 + response: Res, 328 + request: Req, 329 + options: Options 330 + ) => Res | Promise<Res> 331 + 332 + class Interceptors<Interceptor> { 333 + _fns: (Interceptor | null)[] 334 + 335 + constructor() { 336 + this._fns = [] 337 + } 338 + 339 + clear() { 340 + this._fns = [] 341 + } 342 + 343 + getInterceptorIndex(id: number | Interceptor): number { 344 + if (typeof id === 'number') { 345 + return this._fns[id] ? id : -1 346 + } else { 347 + return this._fns.indexOf(id) 348 + } 349 + } 350 + exists(id: number | Interceptor) { 351 + const index = this.getInterceptorIndex(id) 352 + return !!this._fns[index] 353 + } 354 + 355 + eject(id: number | Interceptor) { 356 + const index = this.getInterceptorIndex(id) 357 + if (this._fns[index]) { 358 + this._fns[index] = null 359 + } 360 + } 361 + 362 + update(id: number | Interceptor, fn: Interceptor) { 363 + const index = this.getInterceptorIndex(id) 364 + if (this._fns[index]) { 365 + this._fns[index] = fn 366 + return id 367 + } else { 368 + return false 369 + } 370 + } 371 + 372 + use(fn: Interceptor) { 373 + this._fns = [...this._fns, fn] 374 + return this._fns.length - 1 375 + } 376 + } 377 + 378 + // `createInterceptors()` response, meant for external use as it does not 379 + // expose internals 380 + export interface Middleware<Req, Res, Err, Options> { 381 + error: Pick<Interceptors<ErrInterceptor<Err, Res, Req, Options>>, 'eject' | 'use'> 382 + request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'> 383 + response: Pick<Interceptors<ResInterceptor<Res, Req, Options>>, 'eject' | 'use'> 384 + } 385 + 386 + // do not add `Middleware` as return type so we can use _fns internally 387 + export const createInterceptors = <Req, Res, Err, Options>() => ({ 388 + error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(), 389 + request: new Interceptors<ReqInterceptor<Req, Options>>(), 390 + response: new Interceptors<ResInterceptor<Res, Req, Options>>() 391 + }) 392 + 393 + const defaultQuerySerializer = createQuerySerializer({ 394 + allowReserved: false, 395 + array: { 396 + explode: true, 397 + style: 'form' 398 + }, 399 + object: { 400 + explode: true, 401 + style: 'deepObject' 402 + } 403 + }) 404 + 405 + const defaultHeaders = { 406 + 'Content-Type': 'application/json' 407 + } 408 + 409 + export const createConfig = <T extends ClientOptions = ClientOptions>( 410 + override: Config<Omit<ClientOptions, keyof T> & T> = {} 411 + ): Config<Omit<ClientOptions, keyof T> & T> => ({ 412 + ...jsonBodySerializer, 413 + headers: defaultHeaders, 414 + parseAs: 'auto', 415 + querySerializer: defaultQuerySerializer, 416 + ...override 417 + })
+41
examples/openapi-ts-pinia-colada/src/client/core/auth.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type AuthToken = string | undefined 4 + 5 + export interface Auth { 6 + /** 7 + * Which part of the request do we use to send the auth? 8 + * 9 + * @default 'header' 10 + */ 11 + in?: 'header' | 'query' | 'cookie' 12 + /** 13 + * Header or query parameter name. 14 + * 15 + * @default 'Authorization' 16 + */ 17 + name?: string 18 + scheme?: 'basic' | 'bearer' 19 + type: 'apiKey' | 'http' 20 + } 21 + 22 + export const getAuthToken = async ( 23 + auth: Auth, 24 + callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken 25 + ): Promise<string | undefined> => { 26 + const token = typeof callback === 'function' ? await callback(auth) : callback 27 + 28 + if (!token) { 29 + return 30 + } 31 + 32 + if (auth.scheme === 'bearer') { 33 + return `Bearer ${token}` 34 + } 35 + 36 + if (auth.scheme === 'basic') { 37 + return `Basic ${btoa(token)}` 38 + } 39 + 40 + return token 41 + }
+76
examples/openapi-ts-pinia-colada/src/client/core/bodySerializer.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen' 4 + 5 + export type QuerySerializer = (query: Record<string, unknown>) => string 6 + 7 + export type BodySerializer = (body: any) => any 8 + 9 + export interface QuerySerializerOptions { 10 + allowReserved?: boolean 11 + array?: SerializerOptions<ArrayStyle> 12 + object?: SerializerOptions<ObjectStyle> 13 + } 14 + 15 + const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => { 16 + if (typeof value === 'string' || value instanceof Blob) { 17 + data.append(key, value) 18 + } else if (value instanceof Date) { 19 + data.append(key, value.toISOString()) 20 + } else { 21 + data.append(key, JSON.stringify(value)) 22 + } 23 + } 24 + 25 + const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => { 26 + if (typeof value === 'string') { 27 + data.append(key, value) 28 + } else { 29 + data.append(key, JSON.stringify(value)) 30 + } 31 + } 32 + 33 + export const formDataBodySerializer = { 34 + bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>( 35 + body: T 36 + ): FormData => { 37 + const data = new FormData() 38 + 39 + Object.entries(body).forEach(([key, value]) => { 40 + if (value === undefined || value === null) { 41 + return 42 + } 43 + if (Array.isArray(value)) { 44 + value.forEach((v) => serializeFormDataPair(data, key, v)) 45 + } else { 46 + serializeFormDataPair(data, key, value) 47 + } 48 + }) 49 + 50 + return data 51 + } 52 + } 53 + 54 + export const jsonBodySerializer = { 55 + bodySerializer: <T>(body: T): string => 56 + JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)) 57 + } 58 + 59 + export const urlSearchParamsBodySerializer = { 60 + bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T): string => { 61 + const data = new URLSearchParams() 62 + 63 + Object.entries(body).forEach(([key, value]) => { 64 + if (value === undefined || value === null) { 65 + return 66 + } 67 + if (Array.isArray(value)) { 68 + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)) 69 + } else { 70 + serializeUrlSearchParamsPair(data, key, value) 71 + } 72 + }) 73 + 74 + return data.toString() 75 + } 76 + }
+144
examples/openapi-ts-pinia-colada/src/client/core/params.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + type Slot = 'body' | 'headers' | 'path' | 'query' 4 + 5 + export type Field = 6 + | { 7 + in: Exclude<Slot, 'body'> 8 + /** 9 + * Field name. This is the name we want the user to see and use. 10 + */ 11 + key: string 12 + /** 13 + * Field mapped name. This is the name we want to use in the request. 14 + * If omitted, we use the same value as `key`. 15 + */ 16 + map?: string 17 + } 18 + | { 19 + in: Extract<Slot, 'body'> 20 + /** 21 + * Key isn't required for bodies. 22 + */ 23 + key?: string 24 + map?: string 25 + } 26 + 27 + export interface Fields { 28 + allowExtra?: Partial<Record<Slot, boolean>> 29 + args?: ReadonlyArray<Field> 30 + } 31 + 32 + export type FieldsConfig = ReadonlyArray<Field | Fields> 33 + 34 + const extraPrefixesMap: Record<string, Slot> = { 35 + $body_: 'body', 36 + $headers_: 'headers', 37 + $path_: 'path', 38 + $query_: 'query' 39 + } 40 + const extraPrefixes = Object.entries(extraPrefixesMap) 41 + 42 + type KeyMap = Map< 43 + string, 44 + { 45 + in: Slot 46 + map?: string 47 + } 48 + > 49 + 50 + const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { 51 + if (!map) { 52 + map = new Map() 53 + } 54 + 55 + for (const config of fields) { 56 + if ('in' in config) { 57 + if (config.key) { 58 + map.set(config.key, { 59 + in: config.in, 60 + map: config.map 61 + }) 62 + } 63 + } else if (config.args) { 64 + buildKeyMap(config.args, map) 65 + } 66 + } 67 + 68 + return map 69 + } 70 + 71 + interface Params { 72 + body: unknown 73 + headers: Record<string, unknown> 74 + path: Record<string, unknown> 75 + query: Record<string, unknown> 76 + } 77 + 78 + const stripEmptySlots = (params: Params) => { 79 + for (const [slot, value] of Object.entries(params)) { 80 + if (value && typeof value === 'object' && !Object.keys(value).length) { 81 + delete params[slot as Slot] 82 + } 83 + } 84 + } 85 + 86 + export const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => { 87 + const params: Params = { 88 + body: {}, 89 + headers: {}, 90 + path: {}, 91 + query: {} 92 + } 93 + 94 + const map = buildKeyMap(fields) 95 + 96 + let config: FieldsConfig[number] | undefined 97 + 98 + for (const [index, arg] of args.entries()) { 99 + if (fields[index]) { 100 + config = fields[index] 101 + } 102 + 103 + if (!config) { 104 + continue 105 + } 106 + 107 + if ('in' in config) { 108 + if (config.key) { 109 + const field = map.get(config.key)! 110 + const name = field.map || config.key 111 + ;(params[field.in] as Record<string, unknown>)[name] = arg 112 + } else { 113 + params.body = arg 114 + } 115 + } else { 116 + for (const [key, value] of Object.entries(arg ?? {})) { 117 + const field = map.get(key) 118 + 119 + if (field) { 120 + const name = field.map || key 121 + ;(params[field.in] as Record<string, unknown>)[name] = value 122 + } else { 123 + const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix)) 124 + 125 + if (extra) { 126 + const [prefix, slot] = extra 127 + ;(params[slot] as Record<string, unknown>)[key.slice(prefix.length)] = value 128 + } else { 129 + for (const [slot, allowed] of Object.entries(config.allowExtra ?? {})) { 130 + if (allowed) { 131 + ;(params[slot as Slot] as Record<string, unknown>)[key] = value 132 + break 133 + } 134 + } 135 + } 136 + } 137 + } 138 + } 139 + } 140 + 141 + stripEmptySlots(params) 142 + 143 + return params 144 + }
+171
examples/openapi-ts-pinia-colada/src/client/core/pathSerializer.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {} 4 + 5 + interface SerializePrimitiveOptions { 6 + allowReserved?: boolean 7 + name: string 8 + } 9 + 10 + export interface SerializerOptions<T> { 11 + /** 12 + * @default true 13 + */ 14 + explode: boolean 15 + style: T 16 + } 17 + 18 + export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited' 19 + export type ArraySeparatorStyle = ArrayStyle | MatrixStyle 20 + type MatrixStyle = 'label' | 'matrix' | 'simple' 21 + export type ObjectStyle = 'form' | 'deepObject' 22 + type ObjectSeparatorStyle = ObjectStyle | MatrixStyle 23 + 24 + interface SerializePrimitiveParam extends SerializePrimitiveOptions { 25 + value: string 26 + } 27 + 28 + export const separatorArrayExplode = (style: ArraySeparatorStyle) => { 29 + switch (style) { 30 + case 'label': 31 + return '.' 32 + case 'matrix': 33 + return ';' 34 + case 'simple': 35 + return ',' 36 + default: 37 + return '&' 38 + } 39 + } 40 + 41 + export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { 42 + switch (style) { 43 + case 'form': 44 + return ',' 45 + case 'pipeDelimited': 46 + return '|' 47 + case 'spaceDelimited': 48 + return '%20' 49 + default: 50 + return ',' 51 + } 52 + } 53 + 54 + export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { 55 + switch (style) { 56 + case 'label': 57 + return '.' 58 + case 'matrix': 59 + return ';' 60 + case 'simple': 61 + return ',' 62 + default: 63 + return '&' 64 + } 65 + } 66 + 67 + export const serializeArrayParam = ({ 68 + allowReserved, 69 + explode, 70 + name, 71 + style, 72 + value 73 + }: SerializeOptions<ArraySeparatorStyle> & { 74 + value: unknown[] 75 + }) => { 76 + if (!explode) { 77 + const joinedValues = ( 78 + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) 79 + ).join(separatorArrayNoExplode(style)) 80 + switch (style) { 81 + case 'label': 82 + return `.${joinedValues}` 83 + case 'matrix': 84 + return `;${name}=${joinedValues}` 85 + case 'simple': 86 + return joinedValues 87 + default: 88 + return `${name}=${joinedValues}` 89 + } 90 + } 91 + 92 + const separator = separatorArrayExplode(style) 93 + const joinedValues = value 94 + .map((v) => { 95 + if (style === 'label' || style === 'simple') { 96 + return allowReserved ? v : encodeURIComponent(v as string) 97 + } 98 + 99 + return serializePrimitiveParam({ 100 + allowReserved, 101 + name, 102 + value: v as string 103 + }) 104 + }) 105 + .join(separator) 106 + return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues 107 + } 108 + 109 + export const serializePrimitiveParam = ({ 110 + allowReserved, 111 + name, 112 + value 113 + }: SerializePrimitiveParam) => { 114 + if (value === undefined || value === null) { 115 + return '' 116 + } 117 + 118 + if (typeof value === 'object') { 119 + throw new Error( 120 + 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.' 121 + ) 122 + } 123 + 124 + return `${name}=${allowReserved ? value : encodeURIComponent(value)}` 125 + } 126 + 127 + export const serializeObjectParam = ({ 128 + allowReserved, 129 + explode, 130 + name, 131 + style, 132 + value, 133 + valueOnly 134 + }: SerializeOptions<ObjectSeparatorStyle> & { 135 + value: Record<string, unknown> | Date 136 + valueOnly?: boolean 137 + }) => { 138 + if (value instanceof Date) { 139 + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}` 140 + } 141 + 142 + if (style !== 'deepObject' && !explode) { 143 + let values: string[] = [] 144 + Object.entries(value).forEach(([key, v]) => { 145 + values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)] 146 + }) 147 + const joinedValues = values.join(',') 148 + switch (style) { 149 + case 'form': 150 + return `${name}=${joinedValues}` 151 + case 'label': 152 + return `.${joinedValues}` 153 + case 'matrix': 154 + return `;${name}=${joinedValues}` 155 + default: 156 + return joinedValues 157 + } 158 + } 159 + 160 + const separator = separatorObjectExplode(style) 161 + const joinedValues = Object.entries(value) 162 + .map(([key, v]) => 163 + serializePrimitiveParam({ 164 + allowReserved, 165 + name: style === 'deepObject' ? `${name}[${key}]` : key, 166 + value: v as string 167 + }) 168 + ) 169 + .join(separator) 170 + return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues 171 + }
+94
examples/openapi-ts-pinia-colada/src/client/core/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Auth, AuthToken } from './auth.gen' 4 + import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen' 5 + 6 + export interface Client<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never> { 7 + /** 8 + * Returns the final request URL. 9 + */ 10 + buildUrl: BuildUrlFn 11 + connect: MethodFn 12 + delete: MethodFn 13 + get: MethodFn 14 + getConfig: () => Config 15 + head: MethodFn 16 + options: MethodFn 17 + patch: MethodFn 18 + post: MethodFn 19 + put: MethodFn 20 + request: RequestFn 21 + setConfig: (config: Config) => Config 22 + trace: MethodFn 23 + } 24 + 25 + export interface Config { 26 + /** 27 + * Auth token or a function returning auth token. The resolved value will be 28 + * added to the request payload as defined by its `security` array. 29 + */ 30 + auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken 31 + /** 32 + * A function for serializing request body parameter. By default, 33 + * {@link JSON.stringify()} will be used. 34 + */ 35 + bodySerializer?: BodySerializer | null 36 + /** 37 + * An object containing any HTTP headers that you want to pre-populate your 38 + * `Headers` object with. 39 + * 40 + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} 41 + */ 42 + headers?: 43 + | RequestInit['headers'] 44 + | Record< 45 + string, 46 + string | number | boolean | (string | number | boolean)[] | null | undefined | unknown 47 + > 48 + /** 49 + * The request method. 50 + * 51 + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} 52 + */ 53 + method?: 'CONNECT' | 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'TRACE' 54 + /** 55 + * A function for serializing request query parameters. By default, arrays 56 + * will be exploded in form style, objects will be exploded in deepObject 57 + * style, and reserved characters are percent-encoded. 58 + * 59 + * This method will have no effect if the native `paramsSerializer()` Axios 60 + * API function is used. 61 + * 62 + * {@link https://swagger.io/docs/specification/serialization/#query View examples} 63 + */ 64 + querySerializer?: QuerySerializer | QuerySerializerOptions 65 + /** 66 + * A function validating request data. This is useful if you want to ensure 67 + * the request conforms to the desired shape, so it can be safely sent to 68 + * the server. 69 + */ 70 + requestValidator?: (data: unknown) => Promise<unknown> 71 + /** 72 + * A function transforming response data before it's returned. This is useful 73 + * for post-processing data, e.g. converting ISO strings into Date objects. 74 + */ 75 + responseTransformer?: (data: unknown) => Promise<unknown> 76 + /** 77 + * A function validating response data. This is useful if you want to ensure 78 + * the response conforms to the desired shape, so it can be safely passed to 79 + * the transformers and returned to the user. 80 + */ 81 + responseValidator?: (data: unknown) => Promise<unknown> 82 + } 83 + 84 + type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never] 85 + ? true 86 + : [T] extends [never | undefined] 87 + ? [undefined] extends [T] 88 + ? false 89 + : true 90 + : false 91 + 92 + export type OmitNever<T extends Record<string, unknown>> = { 93 + [K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true ? never : K]: T[K] 94 + }
+3
examples/openapi-ts-pinia-colada/src/client/index.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + export * from './sdk.gen' 3 + export * from './types.gen'
+188
examples/openapi-ts-pinia-colada/src/client/schemas.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export const OrderSchema = { 4 + properties: { 5 + complete: { 6 + type: 'boolean' 7 + }, 8 + id: { 9 + example: 10, 10 + format: 'int64', 11 + type: 'integer' 12 + }, 13 + petId: { 14 + example: 198772, 15 + format: 'int64', 16 + type: 'integer' 17 + }, 18 + quantity: { 19 + example: 7, 20 + format: 'int32', 21 + type: 'integer' 22 + }, 23 + shipDate: { 24 + format: 'date-time', 25 + type: 'string' 26 + }, 27 + status: { 28 + description: 'Order Status', 29 + enum: ['placed', 'approved', 'delivered'], 30 + example: 'approved', 31 + type: 'string' 32 + } 33 + }, 34 + type: 'object', 35 + 'x-swagger-router-model': 'io.swagger.petstore.model.Order', 36 + xml: { 37 + name: 'order' 38 + } 39 + } as const 40 + 41 + export const CategorySchema = { 42 + properties: { 43 + id: { 44 + example: 1, 45 + format: 'int64', 46 + type: 'integer' 47 + }, 48 + name: { 49 + example: 'Dogs', 50 + type: 'string' 51 + } 52 + }, 53 + type: 'object', 54 + 'x-swagger-router-model': 'io.swagger.petstore.model.Category', 55 + xml: { 56 + name: 'category' 57 + } 58 + } as const 59 + 60 + export const UserSchema = { 61 + properties: { 62 + email: { 63 + example: 'john@email.com', 64 + type: 'string' 65 + }, 66 + firstName: { 67 + example: 'John', 68 + type: 'string' 69 + }, 70 + id: { 71 + example: 10, 72 + format: 'int64', 73 + type: 'integer' 74 + }, 75 + lastName: { 76 + example: 'James', 77 + type: 'string' 78 + }, 79 + password: { 80 + example: '12345', 81 + type: 'string' 82 + }, 83 + phone: { 84 + example: '12345', 85 + type: 'string' 86 + }, 87 + userStatus: { 88 + description: 'User Status', 89 + example: 1, 90 + format: 'int32', 91 + type: 'integer' 92 + }, 93 + username: { 94 + example: 'theUser', 95 + type: 'string' 96 + } 97 + }, 98 + type: 'object', 99 + 'x-swagger-router-model': 'io.swagger.petstore.model.User', 100 + xml: { 101 + name: 'user' 102 + } 103 + } as const 104 + 105 + export const TagSchema = { 106 + properties: { 107 + id: { 108 + format: 'int64', 109 + type: 'integer' 110 + }, 111 + name: { 112 + type: 'string' 113 + } 114 + }, 115 + type: 'object', 116 + 'x-swagger-router-model': 'io.swagger.petstore.model.Tag', 117 + xml: { 118 + name: 'tag' 119 + } 120 + } as const 121 + 122 + export const PetSchema = { 123 + properties: { 124 + category: { 125 + $ref: '#/components/schemas/Category' 126 + }, 127 + id: { 128 + example: 10, 129 + format: 'int64', 130 + type: 'integer' 131 + }, 132 + name: { 133 + example: 'doggie', 134 + type: 'string' 135 + }, 136 + photoUrls: { 137 + items: { 138 + type: 'string', 139 + xml: { 140 + name: 'photoUrl' 141 + } 142 + }, 143 + type: 'array', 144 + xml: { 145 + wrapped: true 146 + } 147 + }, 148 + status: { 149 + description: 'pet status in the store', 150 + enum: ['available', 'pending', 'sold'], 151 + type: 'string' 152 + }, 153 + tags: { 154 + items: { 155 + $ref: '#/components/schemas/Tag' 156 + }, 157 + type: 'array', 158 + xml: { 159 + wrapped: true 160 + } 161 + } 162 + }, 163 + required: ['name', 'photoUrls'], 164 + type: 'object', 165 + 'x-swagger-router-model': 'io.swagger.petstore.model.Pet', 166 + xml: { 167 + name: 'pet' 168 + } 169 + } as const 170 + 171 + export const ApiResponseSchema = { 172 + properties: { 173 + code: { 174 + format: 'int32', 175 + type: 'integer' 176 + }, 177 + message: { 178 + type: 'string' 179 + }, 180 + type: { 181 + type: 'string' 182 + } 183 + }, 184 + type: 'object', 185 + xml: { 186 + name: '##default' 187 + } 188 + } as const
+411
examples/openapi-ts-pinia-colada/src/client/sdk.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + import type { Client, Options as ClientOptions, TDataShape } from './client' 4 + import { client as _heyApiClient } from './client.gen' 5 + import type { 6 + AddPetData, 7 + AddPetErrors, 8 + AddPetResponses, 9 + CreateUserData, 10 + CreateUserErrors, 11 + CreateUserResponses, 12 + CreateUsersWithListInputData, 13 + CreateUsersWithListInputErrors, 14 + CreateUsersWithListInputResponses, 15 + DeleteOrderData, 16 + DeleteOrderErrors, 17 + DeleteOrderResponses, 18 + DeletePetData, 19 + DeletePetErrors, 20 + DeletePetResponses, 21 + DeleteUserData, 22 + DeleteUserErrors, 23 + DeleteUserResponses, 24 + FindPetsByStatusData, 25 + FindPetsByStatusErrors, 26 + FindPetsByStatusResponses, 27 + FindPetsByTagsData, 28 + FindPetsByTagsErrors, 29 + FindPetsByTagsResponses, 30 + GetInventoryData, 31 + GetInventoryErrors, 32 + GetInventoryResponses, 33 + GetOrderByIdData, 34 + GetOrderByIdErrors, 35 + GetOrderByIdResponses, 36 + GetPetByIdData, 37 + GetPetByIdErrors, 38 + GetPetByIdResponses, 39 + GetUserByNameData, 40 + GetUserByNameErrors, 41 + GetUserByNameResponses, 42 + LoginUserData, 43 + LoginUserErrors, 44 + LoginUserResponses, 45 + LogoutUserData, 46 + LogoutUserErrors, 47 + LogoutUserResponses, 48 + PlaceOrderData, 49 + PlaceOrderErrors, 50 + PlaceOrderResponses, 51 + UpdatePetData, 52 + UpdatePetErrors, 53 + UpdatePetResponses, 54 + UpdatePetWithFormData, 55 + UpdatePetWithFormErrors, 56 + UpdatePetWithFormResponses, 57 + UpdateUserData, 58 + UpdateUserErrors, 59 + UpdateUserResponses, 60 + UploadFileData, 61 + UploadFileErrors, 62 + UploadFileResponses 63 + } from './types.gen' 64 + 65 + export type Options< 66 + TData extends TDataShape = TDataShape, 67 + ThrowOnError extends boolean = boolean 68 + > = ClientOptions<TData, ThrowOnError> & { 69 + /** 70 + * You can provide a client instance returned by `createClient()` instead of 71 + * individual options. This might be also useful if you want to implement a 72 + * custom client. 73 + */ 74 + client?: Client 75 + /** 76 + * You can pass arbitrary values through the `meta` object. This can be 77 + * used to access values that aren't defined as part of the SDK function. 78 + */ 79 + meta?: Record<string, unknown> 80 + } 81 + 82 + /** 83 + * Add a new pet to the store. 84 + * Add a new pet to the store. 85 + */ 86 + export const addPet = <ThrowOnError extends boolean = false>( 87 + options: Options<AddPetData, ThrowOnError> 88 + ) => 89 + (options.client ?? _heyApiClient).post<AddPetResponses, AddPetErrors, ThrowOnError>({ 90 + security: [ 91 + { 92 + scheme: 'bearer', 93 + type: 'http' 94 + } 95 + ], 96 + url: '/pet', 97 + ...options, 98 + headers: { 99 + 'Content-Type': 'application/json', 100 + ...options.headers 101 + } 102 + }) 103 + 104 + /** 105 + * Update an existing pet. 106 + * Update an existing pet by Id. 107 + */ 108 + export const updatePet = <ThrowOnError extends boolean = false>( 109 + options: Options<UpdatePetData, ThrowOnError> 110 + ) => 111 + (options.client ?? _heyApiClient).put<UpdatePetResponses, UpdatePetErrors, ThrowOnError>({ 112 + security: [ 113 + { 114 + scheme: 'bearer', 115 + type: 'http' 116 + } 117 + ], 118 + url: '/pet', 119 + ...options, 120 + headers: { 121 + 'Content-Type': 'application/json', 122 + ...options.headers 123 + } 124 + }) 125 + 126 + /** 127 + * Finds Pets by status. 128 + * Multiple status values can be provided with comma separated strings. 129 + */ 130 + export const findPetsByStatus = <ThrowOnError extends boolean = false>( 131 + options: Options<FindPetsByStatusData, ThrowOnError> 132 + ) => 133 + (options.client ?? _heyApiClient).get< 134 + FindPetsByStatusResponses, 135 + FindPetsByStatusErrors, 136 + ThrowOnError 137 + >({ 138 + security: [ 139 + { 140 + scheme: 'bearer', 141 + type: 'http' 142 + } 143 + ], 144 + url: '/pet/findByStatus', 145 + ...options 146 + }) 147 + 148 + /** 149 + * Finds Pets by tags. 150 + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. 151 + */ 152 + export const findPetsByTags = <ThrowOnError extends boolean = false>( 153 + options: Options<FindPetsByTagsData, ThrowOnError> 154 + ) => 155 + (options.client ?? _heyApiClient).get< 156 + FindPetsByTagsResponses, 157 + FindPetsByTagsErrors, 158 + ThrowOnError 159 + >({ 160 + security: [ 161 + { 162 + scheme: 'bearer', 163 + type: 'http' 164 + } 165 + ], 166 + url: '/pet/findByTags', 167 + ...options 168 + }) 169 + 170 + /** 171 + * Deletes a pet. 172 + * Delete a pet. 173 + */ 174 + export const deletePet = <ThrowOnError extends boolean = false>( 175 + options: Options<DeletePetData, ThrowOnError> 176 + ) => 177 + (options.client ?? _heyApiClient).delete<DeletePetResponses, DeletePetErrors, ThrowOnError>({ 178 + security: [ 179 + { 180 + scheme: 'bearer', 181 + type: 'http' 182 + } 183 + ], 184 + url: '/pet/{petId}', 185 + ...options 186 + }) 187 + 188 + /** 189 + * Find pet by ID. 190 + * Returns a single pet. 191 + */ 192 + export const getPetById = <ThrowOnError extends boolean = false>( 193 + options: Options<GetPetByIdData, ThrowOnError> 194 + ) => 195 + (options.client ?? _heyApiClient).get<GetPetByIdResponses, GetPetByIdErrors, ThrowOnError>({ 196 + security: [ 197 + { 198 + name: 'api_key', 199 + type: 'apiKey' 200 + }, 201 + { 202 + scheme: 'bearer', 203 + type: 'http' 204 + } 205 + ], 206 + url: '/pet/{petId}', 207 + ...options 208 + }) 209 + 210 + /** 211 + * Updates a pet in the store with form data. 212 + * Updates a pet resource based on the form data. 213 + */ 214 + export const updatePetWithForm = <ThrowOnError extends boolean = false>( 215 + options: Options<UpdatePetWithFormData, ThrowOnError> 216 + ) => 217 + (options.client ?? _heyApiClient).post< 218 + UpdatePetWithFormResponses, 219 + UpdatePetWithFormErrors, 220 + ThrowOnError 221 + >({ 222 + security: [ 223 + { 224 + scheme: 'bearer', 225 + type: 'http' 226 + } 227 + ], 228 + url: '/pet/{petId}', 229 + ...options 230 + }) 231 + 232 + /** 233 + * Uploads an image. 234 + * Upload image of the pet. 235 + */ 236 + export const uploadFile = <ThrowOnError extends boolean = false>( 237 + options: Options<UploadFileData, ThrowOnError> 238 + ) => 239 + (options.client ?? _heyApiClient).post<UploadFileResponses, UploadFileErrors, ThrowOnError>({ 240 + bodySerializer: null, 241 + security: [ 242 + { 243 + scheme: 'bearer', 244 + type: 'http' 245 + } 246 + ], 247 + url: '/pet/{petId}/uploadImage', 248 + ...options, 249 + headers: { 250 + 'Content-Type': 'application/octet-stream', 251 + ...options.headers 252 + } 253 + }) 254 + 255 + /** 256 + * Returns pet inventories by status. 257 + * Returns a map of status codes to quantities. 258 + */ 259 + export const getInventory = <ThrowOnError extends boolean = false>( 260 + options?: Options<GetInventoryData, ThrowOnError> 261 + ) => 262 + (options?.client ?? _heyApiClient).get<GetInventoryResponses, GetInventoryErrors, ThrowOnError>({ 263 + security: [ 264 + { 265 + name: 'api_key', 266 + type: 'apiKey' 267 + } 268 + ], 269 + url: '/store/inventory', 270 + ...options 271 + }) 272 + 273 + /** 274 + * Place an order for a pet. 275 + * Place a new order in the store. 276 + */ 277 + export const placeOrder = <ThrowOnError extends boolean = false>( 278 + options?: Options<PlaceOrderData, ThrowOnError> 279 + ) => 280 + (options?.client ?? _heyApiClient).post<PlaceOrderResponses, PlaceOrderErrors, ThrowOnError>({ 281 + url: '/store/order', 282 + ...options, 283 + headers: { 284 + 'Content-Type': 'application/json', 285 + ...options?.headers 286 + } 287 + }) 288 + 289 + /** 290 + * Delete purchase order by identifier. 291 + * For valid response try integer IDs with value < 1000. Anything above 1000 or non-integers will generate API errors. 292 + */ 293 + export const deleteOrder = <ThrowOnError extends boolean = false>( 294 + options: Options<DeleteOrderData, ThrowOnError> 295 + ) => 296 + (options.client ?? _heyApiClient).delete<DeleteOrderResponses, DeleteOrderErrors, ThrowOnError>({ 297 + url: '/store/order/{orderId}', 298 + ...options 299 + }) 300 + 301 + /** 302 + * Find purchase order by ID. 303 + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions. 304 + */ 305 + export const getOrderById = <ThrowOnError extends boolean = false>( 306 + options: Options<GetOrderByIdData, ThrowOnError> 307 + ) => 308 + (options.client ?? _heyApiClient).get<GetOrderByIdResponses, GetOrderByIdErrors, ThrowOnError>({ 309 + url: '/store/order/{orderId}', 310 + ...options 311 + }) 312 + 313 + /** 314 + * Create user. 315 + * This can only be done by the logged in user. 316 + */ 317 + export const createUser = <ThrowOnError extends boolean = false>( 318 + options?: Options<CreateUserData, ThrowOnError> 319 + ) => 320 + (options?.client ?? _heyApiClient).post<CreateUserResponses, CreateUserErrors, ThrowOnError>({ 321 + url: '/user', 322 + ...options, 323 + headers: { 324 + 'Content-Type': 'application/json', 325 + ...options?.headers 326 + } 327 + }) 328 + 329 + /** 330 + * Creates list of users with given input array. 331 + * Creates list of users with given input array. 332 + */ 333 + export const createUsersWithListInput = <ThrowOnError extends boolean = false>( 334 + options?: Options<CreateUsersWithListInputData, ThrowOnError> 335 + ) => 336 + (options?.client ?? _heyApiClient).post< 337 + CreateUsersWithListInputResponses, 338 + CreateUsersWithListInputErrors, 339 + ThrowOnError 340 + >({ 341 + url: '/user/createWithList', 342 + ...options, 343 + headers: { 344 + 'Content-Type': 'application/json', 345 + ...options?.headers 346 + } 347 + }) 348 + 349 + /** 350 + * Logs user into the system. 351 + * Log into the system. 352 + */ 353 + export const loginUser = <ThrowOnError extends boolean = false>( 354 + options?: Options<LoginUserData, ThrowOnError> 355 + ) => 356 + (options?.client ?? _heyApiClient).get<LoginUserResponses, LoginUserErrors, ThrowOnError>({ 357 + url: '/user/login', 358 + ...options 359 + }) 360 + 361 + /** 362 + * Logs out current logged in user session. 363 + * Log user out of the system. 364 + */ 365 + export const logoutUser = <ThrowOnError extends boolean = false>( 366 + options?: Options<LogoutUserData, ThrowOnError> 367 + ) => 368 + (options?.client ?? _heyApiClient).get<LogoutUserResponses, LogoutUserErrors, ThrowOnError>({ 369 + url: '/user/logout', 370 + ...options 371 + }) 372 + 373 + /** 374 + * Delete user resource. 375 + * This can only be done by the logged in user. 376 + */ 377 + export const deleteUser = <ThrowOnError extends boolean = false>( 378 + options: Options<DeleteUserData, ThrowOnError> 379 + ) => 380 + (options.client ?? _heyApiClient).delete<DeleteUserResponses, DeleteUserErrors, ThrowOnError>({ 381 + url: '/user/{username}', 382 + ...options 383 + }) 384 + 385 + /** 386 + * Get user by user name. 387 + * Get user detail based on username. 388 + */ 389 + export const getUserByName = <ThrowOnError extends boolean = false>( 390 + options: Options<GetUserByNameData, ThrowOnError> 391 + ) => 392 + (options.client ?? _heyApiClient).get<GetUserByNameResponses, GetUserByNameErrors, ThrowOnError>({ 393 + url: '/user/{username}', 394 + ...options 395 + }) 396 + 397 + /** 398 + * Update user resource. 399 + * This can only be done by the logged in user. 400 + */ 401 + export const updateUser = <ThrowOnError extends boolean = false>( 402 + options: Options<UpdateUserData, ThrowOnError> 403 + ) => 404 + (options.client ?? _heyApiClient).put<UpdateUserResponses, UpdateUserErrors, ThrowOnError>({ 405 + url: '/user/{username}', 406 + ...options, 407 + headers: { 408 + 'Content-Type': 'application/json', 409 + ...options.headers 410 + } 411 + })
+693
examples/openapi-ts-pinia-colada/src/client/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type Order = { 4 + complete?: boolean 5 + id?: number 6 + petId?: number 7 + quantity?: number 8 + shipDate?: string 9 + /** 10 + * Order Status 11 + */ 12 + status?: 'placed' | 'approved' | 'delivered' 13 + } 14 + 15 + export type Category = { 16 + id?: number 17 + name?: string 18 + } 19 + 20 + export type User = { 21 + email?: string 22 + firstName?: string 23 + id?: number 24 + lastName?: string 25 + password?: string 26 + phone?: string 27 + /** 28 + * User Status 29 + */ 30 + userStatus?: number 31 + username?: string 32 + } 33 + 34 + export type Tag = { 35 + id?: number 36 + name?: string 37 + } 38 + 39 + export type Pet = { 40 + category?: Category 41 + id?: number 42 + name: string 43 + photoUrls: Array<string> 44 + /** 45 + * pet status in the store 46 + */ 47 + status?: 'available' | 'pending' | 'sold' 48 + tags?: Array<Tag> 49 + } 50 + 51 + export type ApiResponse = { 52 + code?: number 53 + message?: string 54 + type?: string 55 + } 56 + 57 + export type Pet2 = Pet 58 + 59 + /** 60 + * List of user object 61 + */ 62 + export type UserArray = Array<User> 63 + 64 + export type AddPetData = { 65 + /** 66 + * Create a new pet in the store 67 + */ 68 + body: Pet 69 + path?: never 70 + query?: never 71 + url: '/pet' 72 + } 73 + 74 + export type AddPetErrors = { 75 + /** 76 + * Invalid input 77 + */ 78 + 400: unknown 79 + /** 80 + * Validation exception 81 + */ 82 + 422: unknown 83 + /** 84 + * Unexpected error 85 + */ 86 + default: unknown 87 + } 88 + 89 + export type AddPetResponses = { 90 + /** 91 + * Successful operation 92 + */ 93 + 200: Pet 94 + } 95 + 96 + export type AddPetResponse = AddPetResponses[keyof AddPetResponses] 97 + 98 + export type UpdatePetData = { 99 + /** 100 + * Update an existent pet in the store 101 + */ 102 + body: Pet 103 + path?: never 104 + query?: never 105 + url: '/pet' 106 + } 107 + 108 + export type UpdatePetErrors = { 109 + /** 110 + * Invalid ID supplied 111 + */ 112 + 400: unknown 113 + /** 114 + * Pet not found 115 + */ 116 + 404: unknown 117 + /** 118 + * Validation exception 119 + */ 120 + 422: unknown 121 + /** 122 + * Unexpected error 123 + */ 124 + default: unknown 125 + } 126 + 127 + export type UpdatePetResponses = { 128 + /** 129 + * Successful operation 130 + */ 131 + 200: Pet 132 + } 133 + 134 + export type UpdatePetResponse = UpdatePetResponses[keyof UpdatePetResponses] 135 + 136 + export type FindPetsByStatusData = { 137 + body?: never 138 + path?: never 139 + query: { 140 + /** 141 + * Status values that need to be considered for filter 142 + */ 143 + status: 'available' | 'pending' | 'sold' 144 + } 145 + url: '/pet/findByStatus' 146 + } 147 + 148 + export type FindPetsByStatusErrors = { 149 + /** 150 + * Invalid status value 151 + */ 152 + 400: unknown 153 + /** 154 + * Unexpected error 155 + */ 156 + default: unknown 157 + } 158 + 159 + export type FindPetsByStatusResponses = { 160 + /** 161 + * successful operation 162 + */ 163 + 200: Array<Pet> 164 + } 165 + 166 + export type FindPetsByStatusResponse = FindPetsByStatusResponses[keyof FindPetsByStatusResponses] 167 + 168 + export type FindPetsByTagsData = { 169 + body?: never 170 + path?: never 171 + query: { 172 + /** 173 + * Tags to filter by 174 + */ 175 + tags: Array<string> 176 + } 177 + url: '/pet/findByTags' 178 + } 179 + 180 + export type FindPetsByTagsErrors = { 181 + /** 182 + * Invalid tag value 183 + */ 184 + 400: unknown 185 + /** 186 + * Unexpected error 187 + */ 188 + default: unknown 189 + } 190 + 191 + export type FindPetsByTagsResponses = { 192 + /** 193 + * successful operation 194 + */ 195 + 200: Array<Pet> 196 + } 197 + 198 + export type FindPetsByTagsResponse = FindPetsByTagsResponses[keyof FindPetsByTagsResponses] 199 + 200 + export type DeletePetData = { 201 + body?: never 202 + headers?: { 203 + api_key?: string 204 + } 205 + path: { 206 + /** 207 + * Pet id to delete 208 + */ 209 + petId: number 210 + } 211 + query?: never 212 + url: '/pet/{petId}' 213 + } 214 + 215 + export type DeletePetErrors = { 216 + /** 217 + * Invalid pet value 218 + */ 219 + 400: unknown 220 + /** 221 + * Unexpected error 222 + */ 223 + default: unknown 224 + } 225 + 226 + export type DeletePetResponses = { 227 + /** 228 + * Pet deleted 229 + */ 230 + 200: unknown 231 + } 232 + 233 + export type GetPetByIdData = { 234 + body?: never 235 + path: { 236 + /** 237 + * ID of pet to return 238 + */ 239 + petId: number 240 + } 241 + query?: never 242 + url: '/pet/{petId}' 243 + } 244 + 245 + export type GetPetByIdErrors = { 246 + /** 247 + * Invalid ID supplied 248 + */ 249 + 400: unknown 250 + /** 251 + * Pet not found 252 + */ 253 + 404: unknown 254 + /** 255 + * Unexpected error 256 + */ 257 + default: unknown 258 + } 259 + 260 + export type GetPetByIdResponses = { 261 + /** 262 + * successful operation 263 + */ 264 + 200: Pet 265 + } 266 + 267 + export type GetPetByIdResponse = GetPetByIdResponses[keyof GetPetByIdResponses] 268 + 269 + export type UpdatePetWithFormData = { 270 + body?: never 271 + path: { 272 + /** 273 + * ID of pet that needs to be updated 274 + */ 275 + petId: number 276 + } 277 + query?: { 278 + /** 279 + * Name of pet that needs to be updated 280 + */ 281 + name?: string 282 + /** 283 + * Status of pet that needs to be updated 284 + */ 285 + status?: string 286 + } 287 + url: '/pet/{petId}' 288 + } 289 + 290 + export type UpdatePetWithFormErrors = { 291 + /** 292 + * Invalid input 293 + */ 294 + 400: unknown 295 + /** 296 + * Unexpected error 297 + */ 298 + default: unknown 299 + } 300 + 301 + export type UpdatePetWithFormResponses = { 302 + /** 303 + * successful operation 304 + */ 305 + 200: Pet 306 + } 307 + 308 + export type UpdatePetWithFormResponse = UpdatePetWithFormResponses[keyof UpdatePetWithFormResponses] 309 + 310 + export type UploadFileData = { 311 + body?: Blob | File 312 + path: { 313 + /** 314 + * ID of pet to update 315 + */ 316 + petId: number 317 + } 318 + query?: { 319 + /** 320 + * Additional Metadata 321 + */ 322 + additionalMetadata?: string 323 + } 324 + url: '/pet/{petId}/uploadImage' 325 + } 326 + 327 + export type UploadFileErrors = { 328 + /** 329 + * No file uploaded 330 + */ 331 + 400: unknown 332 + /** 333 + * Pet not found 334 + */ 335 + 404: unknown 336 + /** 337 + * Unexpected error 338 + */ 339 + default: unknown 340 + } 341 + 342 + export type UploadFileResponses = { 343 + /** 344 + * successful operation 345 + */ 346 + 200: ApiResponse 347 + } 348 + 349 + export type UploadFileResponse = UploadFileResponses[keyof UploadFileResponses] 350 + 351 + export type GetInventoryData = { 352 + body?: never 353 + path?: never 354 + query?: never 355 + url: '/store/inventory' 356 + } 357 + 358 + export type GetInventoryErrors = { 359 + /** 360 + * Unexpected error 361 + */ 362 + default: unknown 363 + } 364 + 365 + export type GetInventoryResponses = { 366 + /** 367 + * successful operation 368 + */ 369 + 200: { 370 + [key: string]: number 371 + } 372 + } 373 + 374 + export type GetInventoryResponse = GetInventoryResponses[keyof GetInventoryResponses] 375 + 376 + export type PlaceOrderData = { 377 + body?: Order 378 + path?: never 379 + query?: never 380 + url: '/store/order' 381 + } 382 + 383 + export type PlaceOrderErrors = { 384 + /** 385 + * Invalid input 386 + */ 387 + 400: unknown 388 + /** 389 + * Validation exception 390 + */ 391 + 422: unknown 392 + /** 393 + * Unexpected error 394 + */ 395 + default: unknown 396 + } 397 + 398 + export type PlaceOrderResponses = { 399 + /** 400 + * successful operation 401 + */ 402 + 200: Order 403 + } 404 + 405 + export type PlaceOrderResponse = PlaceOrderResponses[keyof PlaceOrderResponses] 406 + 407 + export type DeleteOrderData = { 408 + body?: never 409 + path: { 410 + /** 411 + * ID of the order that needs to be deleted 412 + */ 413 + orderId: number 414 + } 415 + query?: never 416 + url: '/store/order/{orderId}' 417 + } 418 + 419 + export type DeleteOrderErrors = { 420 + /** 421 + * Invalid ID supplied 422 + */ 423 + 400: unknown 424 + /** 425 + * Order not found 426 + */ 427 + 404: unknown 428 + /** 429 + * Unexpected error 430 + */ 431 + default: unknown 432 + } 433 + 434 + export type DeleteOrderResponses = { 435 + /** 436 + * order deleted 437 + */ 438 + 200: unknown 439 + } 440 + 441 + export type GetOrderByIdData = { 442 + body?: never 443 + path: { 444 + /** 445 + * ID of order that needs to be fetched 446 + */ 447 + orderId: number 448 + } 449 + query?: never 450 + url: '/store/order/{orderId}' 451 + } 452 + 453 + export type GetOrderByIdErrors = { 454 + /** 455 + * Invalid ID supplied 456 + */ 457 + 400: unknown 458 + /** 459 + * Order not found 460 + */ 461 + 404: unknown 462 + /** 463 + * Unexpected error 464 + */ 465 + default: unknown 466 + } 467 + 468 + export type GetOrderByIdResponses = { 469 + /** 470 + * successful operation 471 + */ 472 + 200: Order 473 + } 474 + 475 + export type GetOrderByIdResponse = GetOrderByIdResponses[keyof GetOrderByIdResponses] 476 + 477 + export type CreateUserData = { 478 + /** 479 + * Created user object 480 + */ 481 + body?: User 482 + path?: never 483 + query?: never 484 + url: '/user' 485 + } 486 + 487 + export type CreateUserErrors = { 488 + /** 489 + * Unexpected error 490 + */ 491 + default: unknown 492 + } 493 + 494 + export type CreateUserResponses = { 495 + /** 496 + * successful operation 497 + */ 498 + 200: User 499 + } 500 + 501 + export type CreateUserResponse = CreateUserResponses[keyof CreateUserResponses] 502 + 503 + export type CreateUsersWithListInputData = { 504 + body?: Array<User> 505 + path?: never 506 + query?: never 507 + url: '/user/createWithList' 508 + } 509 + 510 + export type CreateUsersWithListInputErrors = { 511 + /** 512 + * Unexpected error 513 + */ 514 + default: unknown 515 + } 516 + 517 + export type CreateUsersWithListInputResponses = { 518 + /** 519 + * Successful operation 520 + */ 521 + 200: User 522 + } 523 + 524 + export type CreateUsersWithListInputResponse = 525 + CreateUsersWithListInputResponses[keyof CreateUsersWithListInputResponses] 526 + 527 + export type LoginUserData = { 528 + body?: never 529 + path?: never 530 + query?: { 531 + /** 532 + * The password for login in clear text 533 + */ 534 + password?: string 535 + /** 536 + * The user name for login 537 + */ 538 + username?: string 539 + } 540 + url: '/user/login' 541 + } 542 + 543 + export type LoginUserErrors = { 544 + /** 545 + * Invalid username/password supplied 546 + */ 547 + 400: unknown 548 + /** 549 + * Unexpected error 550 + */ 551 + default: unknown 552 + } 553 + 554 + export type LoginUserResponses = { 555 + /** 556 + * successful operation 557 + */ 558 + 200: string 559 + } 560 + 561 + export type LoginUserResponse = LoginUserResponses[keyof LoginUserResponses] 562 + 563 + export type LogoutUserData = { 564 + body?: never 565 + path?: never 566 + query?: never 567 + url: '/user/logout' 568 + } 569 + 570 + export type LogoutUserErrors = { 571 + /** 572 + * Unexpected error 573 + */ 574 + default: unknown 575 + } 576 + 577 + export type LogoutUserResponses = { 578 + /** 579 + * successful operation 580 + */ 581 + 200: unknown 582 + } 583 + 584 + export type DeleteUserData = { 585 + body?: never 586 + path: { 587 + /** 588 + * The name that needs to be deleted 589 + */ 590 + username: string 591 + } 592 + query?: never 593 + url: '/user/{username}' 594 + } 595 + 596 + export type DeleteUserErrors = { 597 + /** 598 + * Invalid username supplied 599 + */ 600 + 400: unknown 601 + /** 602 + * User not found 603 + */ 604 + 404: unknown 605 + /** 606 + * Unexpected error 607 + */ 608 + default: unknown 609 + } 610 + 611 + export type DeleteUserResponses = { 612 + /** 613 + * User deleted 614 + */ 615 + 200: unknown 616 + } 617 + 618 + export type GetUserByNameData = { 619 + body?: never 620 + path: { 621 + /** 622 + * The name that needs to be fetched. Use user1 for testing 623 + */ 624 + username: string 625 + } 626 + query?: never 627 + url: '/user/{username}' 628 + } 629 + 630 + export type GetUserByNameErrors = { 631 + /** 632 + * Invalid username supplied 633 + */ 634 + 400: unknown 635 + /** 636 + * User not found 637 + */ 638 + 404: unknown 639 + /** 640 + * Unexpected error 641 + */ 642 + default: unknown 643 + } 644 + 645 + export type GetUserByNameResponses = { 646 + /** 647 + * successful operation 648 + */ 649 + 200: User 650 + } 651 + 652 + export type GetUserByNameResponse = GetUserByNameResponses[keyof GetUserByNameResponses] 653 + 654 + export type UpdateUserData = { 655 + /** 656 + * Update an existent user in the store 657 + */ 658 + body?: User 659 + path: { 660 + /** 661 + * name that need to be deleted 662 + */ 663 + username: string 664 + } 665 + query?: never 666 + url: '/user/{username}' 667 + } 668 + 669 + export type UpdateUserErrors = { 670 + /** 671 + * bad request 672 + */ 673 + 400: unknown 674 + /** 675 + * user not found 676 + */ 677 + 404: unknown 678 + /** 679 + * Unexpected error 680 + */ 681 + default: unknown 682 + } 683 + 684 + export type UpdateUserResponses = { 685 + /** 686 + * successful operation 687 + */ 688 + 200: unknown 689 + } 690 + 691 + export type ClientOptions = { 692 + baseUrl: 'https://petstore3.swagger.io/api/v3' | (string & {}) 693 + }
+28
examples/openapi-ts-pinia-colada/src/main.ts
··· 1 + import './assets/main.css' 2 + 3 + import { PiniaColada } from '@pinia/colada' 4 + import { createPinia } from 'pinia' 5 + import { createApp } from 'vue' 6 + 7 + import App from './App.vue' 8 + import { client } from './client/client.gen' 9 + import router from './router' 10 + 11 + // configure internal service client 12 + client.setConfig({ 13 + // set default base url for requests 14 + baseUrl: 'https://petstore3.swagger.io/api/v3', 15 + // set default headers for requests 16 + headers: { 17 + Authorization: 'Bearer <token_from_service_client>' 18 + } 19 + }) 20 + 21 + const app = createApp(App) 22 + 23 + const pinia = createPinia() 24 + app.use(pinia) 25 + app.use(PiniaColada) 26 + app.use(router) 27 + 28 + app.mount('#app')
+16
examples/openapi-ts-pinia-colada/src/router/index.ts
··· 1 + import { createRouter, createWebHistory } from 'vue-router' 2 + 3 + import PiniaColadaExample from '@/views/PiniaColadaExample.vue' 4 + 5 + const router = createRouter({ 6 + history: createWebHistory(import.meta.env.BASE_URL), 7 + routes: [ 8 + { 9 + component: PiniaColadaExample, 10 + name: 'home', 11 + path: '/' 12 + } 13 + ] 14 + }) 15 + 16 + export default router
+221
examples/openapi-ts-pinia-colada/src/views/PiniaColadaExample.vue
··· 1 + <script lang="ts" setup> 2 + import type { Pet } from '@/client' 3 + import { createClient } from '@/client/client' 4 + import { PetSchema } from '@/client/schemas.gen' 5 + import { addPetMutation, getPetByIdQuery, updatePetMutation } from '@/client/@pinia/colada.gen' 6 + import { useQuery, useMutation } from '@pinia/colada' 7 + import { ref, watch } from 'vue' 8 + import type { RequestOptions } from '@/client/client' 9 + 10 + const localClient = createClient({ 11 + // set default base url for requests made by this client 12 + baseUrl: 'https://petstore3.swagger.io/api/v3', 13 + /** 14 + * Set default headers only for requests made by this client. This is to 15 + * demonstrate local clients and their configuration taking precedence over 16 + * internal service client. 17 + */ 18 + headers: { 19 + Authorization: 'Bearer <token_from_local_client>' 20 + } 21 + }) 22 + 23 + localClient.interceptors.request.use((request: Request, options: RequestOptions) => { 24 + // Middleware is great for adding authorization tokens to requests made to 25 + // protected paths. Headers are set randomly here to allow surfacing the 26 + // default headers, too. 27 + if (options.url === '/pet/{petId}' && options.method === 'GET' && Math.random() < 0.5) { 28 + request.headers.set('Authorization', 'Bearer <token_from_interceptor>') 29 + } 30 + return request 31 + }) 32 + 33 + const pet = ref<Pet>() 34 + const petId = ref<number>() 35 + 36 + const petInput = ref({ name: '', category: '' }) 37 + 38 + const addPet = useMutation(addPetMutation()) 39 + 40 + const updatePet = useMutation(updatePetMutation()) 41 + 42 + const { data, error } = useQuery(() => { 43 + if (!petId.value) { 44 + return { 45 + key: ['getPetById', 'none'], 46 + query: async () => undefined, 47 + enabled: false 48 + } 49 + } 50 + 51 + return { 52 + ...getPetByIdQuery({ 53 + client: localClient, 54 + path: { 55 + petId: petId.value 56 + } 57 + }), 58 + enabled: true 59 + } 60 + }) 61 + 62 + const handleAddPet = async () => { 63 + if (PetSchema.required.includes('name') && !petInput.value?.name?.length) { 64 + return 65 + } 66 + 67 + const result = await addPet.mutateAsync({ 68 + body: { 69 + category: { 70 + id: 0, 71 + name: petInput.value.category 72 + }, 73 + id: 0, 74 + name: petInput.value?.name, 75 + photoUrls: ['string'], 76 + status: 'available', 77 + tags: [ 78 + { 79 + id: 0, 80 + name: 'string' 81 + } 82 + ] 83 + } 84 + }) 85 + 86 + if (result) { 87 + pet.value = result 88 + petId.value = result.id ?? petId.value 89 + } 90 + } 91 + 92 + function setRandomPetId() { 93 + // random id 1-10 94 + petId.value = Math.floor(Math.random() * (10 - 1 + 1) + 1) 95 + } 96 + 97 + const handleUpdatePet = async () => { 98 + const result = await updatePet.mutateAsync({ 99 + body: { 100 + category: { 101 + id: pet.value?.category?.id ?? 0, 102 + name: petInput.value.category 103 + }, 104 + id: pet.value?.id ?? 0, 105 + name: petInput.value.name, 106 + photoUrls: ['string'], 107 + status: 'available', 108 + tags: [ 109 + { 110 + id: 0, 111 + name: 'string' 112 + } 113 + ] 114 + }, 115 + // setting headers per request 116 + headers: { 117 + Authorization: 'Bearer <token_from_method>' 118 + } 119 + }) 120 + 121 + if (result) { 122 + pet.value = result 123 + petId.value = result.id ?? petId.value 124 + } 125 + } 126 + 127 + watch(data, () => { 128 + pet.value = data.value as Pet | undefined 129 + }) 130 + 131 + watch(error, (error) => { 132 + console.log(error) 133 + }) 134 + </script> 135 + 136 + <template> 137 + <div class="bg-[#18191b] py-12"> 138 + <div class="mx-auto flex max-w-md flex-col gap-12"> 139 + <div class="flex items-center"> 140 + <a class="shrink-0" href="https://heyapi.dev/" target="_blank"> 141 + <img 142 + alt="Hey API logo" 143 + class="size-16 transition duration-300 will-change-auto" 144 + src="https://heyapi.dev/logo.png" 145 + /> 146 + </a> 147 + 148 + <h1 class="text-2xl font-bold text-white">@hey-api/openapi-ts 🤝 Pinia Colada</h1> 149 + </div> 150 + 151 + <div class="flex flex-col gap-2"> 152 + <div 153 + class="flex max-w-60 items-center gap-3 rounded border border-[#575e64] bg-[#1f2123] p-4" 154 + > 155 + <div 156 + class="flex size-10 place-content-center place-items-center rounded-full bg-[#233057] text-lg font-medium text-[#9eb1ff]" 157 + > 158 + <span> 159 + {{ pet?.name?.slice(0, 1) || 'N' }} 160 + </span> 161 + </div> 162 + 163 + <div> 164 + <p class="text-sm font-bold text-white">Name: {{ pet?.name || 'N/A' }}</p> 165 + 166 + <p class="text-sm text-[#f1f7feb5]">Category: {{ pet?.category?.name || 'N/A' }}</p> 167 + </div> 168 + </div> 169 + 170 + <button 171 + class="rounded bg-[#3e63dd] p-1 text-sm font-medium text-white" 172 + type="button" 173 + @click="setRandomPetId" 174 + > 175 + Get Random Pet 176 + </button> 177 + </div> 178 + 179 + <form class="flex flex-col gap-3" @submit.prevent="handleAddPet"> 180 + <div class="flex w-64 flex-col gap-1"> 181 + <label class="font-medium text-white" for="name">Name</label> 182 + 183 + <input 184 + v-model="petInput.name" 185 + class="rounded border border-[#575e64] bg-[#121314] p-1 text-sm text-white placeholder:text-[#575e64]" 186 + name="name" 187 + placeholder="Kitty" 188 + required 189 + /> 190 + </div> 191 + 192 + <div class="flex w-64 flex-col gap-1"> 193 + <label class="font-medium text-white" for="category">Category</label> 194 + 195 + <input 196 + v-model="petInput.category" 197 + class="rounded border border-[#575e64] bg-[#121314] p-1 text-sm text-white placeholder:text-[#575e64]" 198 + name="category" 199 + placeholder="Cats" 200 + required 201 + /> 202 + </div> 203 + 204 + <div class="flex gap-2"> 205 + <button class="rounded bg-[#3e63dd] p-2 text-sm font-medium text-white" type="submit"> 206 + Add Pet 207 + </button> 208 + 209 + <button 210 + class="rounded bg-[#3e63dd] p-2 text-sm font-medium text-white disabled:cursor-not-allowed" 211 + :disabled="!pet" 212 + type="button" 213 + @click="handleUpdatePet" 214 + > 215 + Update Pet 216 + </button> 217 + </div> 218 + </form> 219 + </div> 220 + </div> 221 + </template>
+9
examples/openapi-ts-pinia-colada/tailwind.config.ts
··· 1 + import type { Config } from 'tailwindcss' 2 + 3 + export default { 4 + content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], 5 + plugins: [], 6 + theme: { 7 + extend: {} 8 + } 9 + } satisfies Config
+14
examples/openapi-ts-pinia-colada/tsconfig.app.json
··· 1 + { 2 + "extends": "@vue/tsconfig/tsconfig.dom.json", 3 + "include": ["./env.d.ts", "./src/**/*", "./src/**/*.vue"], 4 + "exclude": ["./src/**/__tests__/*"], 5 + "compilerOptions": { 6 + "composite": true, 7 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 + 9 + "baseUrl": ".", 10 + "paths": { 11 + "@/*": ["./src/*"] 12 + } 13 + } 14 + }
+14
examples/openapi-ts-pinia-colada/tsconfig.json
··· 1 + { 2 + "files": [], 3 + "references": [ 4 + { 5 + "path": "./tsconfig.node.json" 6 + }, 7 + { 8 + "path": "./tsconfig.app.json" 9 + }, 10 + { 11 + "path": "./tsconfig.vitest.json" 12 + } 13 + ] 14 + }
+19
examples/openapi-ts-pinia-colada/tsconfig.node.json
··· 1 + { 2 + "extends": "@tsconfig/node20/tsconfig.json", 3 + "include": [ 4 + "vite.config.*", 5 + "vitest.config.*", 6 + "cypress.config.*", 7 + "nightwatch.conf.*", 8 + "playwright.config.*" 9 + ], 10 + "compilerOptions": { 11 + "composite": true, 12 + "noEmit": true, 13 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 + 15 + "module": "ESNext", 16 + "moduleResolution": "Bundler", 17 + "types": ["node"] 18 + } 19 + }
+11
examples/openapi-ts-pinia-colada/tsconfig.vitest.json
··· 1 + { 2 + "extends": "./tsconfig.app.json", 3 + "exclude": [], 4 + "compilerOptions": { 5 + "composite": true, 6 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", 7 + 8 + "lib": [], 9 + "types": ["node", "jsdom"] 10 + } 11 + }
+16
examples/openapi-ts-pinia-colada/vite.config.ts
··· 1 + import { fileURLToPath, URL } from 'node:url' 2 + 3 + import { createViteConfig } from '@config/vite-base' 4 + import vue from '@vitejs/plugin-vue' 5 + import vueJsx from '@vitejs/plugin-vue-jsx' 6 + import vueDevTools from 'vite-plugin-vue-devtools' 7 + 8 + // https://vitejs.dev/config/ 9 + export default createViteConfig({ 10 + plugins: [vue(), vueJsx(), vueDevTools()], 11 + resolve: { 12 + alias: { 13 + '@': fileURLToPath(new URL('./src', import.meta.url)) 14 + } 15 + } 16 + })
+16
examples/openapi-ts-pinia-colada/vitest.config.ts
··· 1 + import { fileURLToPath } from 'node:url' 2 + 3 + import { createVitestConfig } from '@config/vite-base' 4 + import { configDefaults, mergeConfig } from 'vitest/config' 5 + 6 + import viteConfig from './vite.config' 7 + 8 + export default mergeConfig( 9 + viteConfig, 10 + createVitestConfig(fileURLToPath(new URL('./', import.meta.url)), { 11 + test: { 12 + environment: 'jsdom', 13 + exclude: [...configDefaults.exclude, 'e2e/**'] 14 + } 15 + }) 16 + )
+51
packages/openapi-ts/src/plugins/@pinia/colada/config.ts
··· 1 + import { definePluginConfig } from '../../shared/utils/config'; 2 + import { handler } from './plugin'; 3 + import type { PiniaColadaPlugin } from './types'; 4 + 5 + export const defaultConfig: PiniaColadaPlugin['Config'] = { 6 + config: { 7 + case: 'camelCase', 8 + comments: true, 9 + exportFromIndex: false, 10 + }, 11 + dependencies: ['@hey-api/sdk', '@hey-api/typescript'], 12 + handler: handler as PiniaColadaPlugin['Handler'], 13 + name: '@pinia/colada', 14 + output: '@pinia/colada', 15 + resolveConfig: (plugin, context) => { 16 + plugin.config.mutationOptions = context.valueToObject({ 17 + defaultValue: { 18 + case: plugin.config.case ?? 'camelCase', 19 + enabled: true, 20 + meta: false, 21 + name: '{{name}}Mutation', 22 + }, 23 + mappers: { 24 + boolean: (enabled) => ({ enabled }), 25 + function: (name) => ({ name }), 26 + string: (name) => ({ name }), 27 + }, 28 + value: plugin.config.mutationOptions, 29 + }); 30 + 31 + plugin.config.queryOptions = context.valueToObject({ 32 + defaultValue: { 33 + case: plugin.config.case ?? 'camelCase', 34 + enabled: true, 35 + meta: false, 36 + name: '{{name}}Query', 37 + }, 38 + mappers: { 39 + boolean: (enabled) => ({ enabled }), 40 + function: (name) => ({ name }), 41 + string: (name) => ({ name }), 42 + }, 43 + value: plugin.config.queryOptions, 44 + }); 45 + }, 46 + }; 47 + 48 + /** 49 + * Type helper for `@pinia/colada` plugin, returns {@link Plugin.Config} object 50 + */ 51 + export const defineConfig = definePluginConfig(defaultConfig);
+2
packages/openapi-ts/src/plugins/@pinia/colada/index.ts
··· 1 + export { defaultConfig, defineConfig } from './config'; 2 + export type { PiniaColadaPlugin } from './types';
+430
packages/openapi-ts/src/plugins/@pinia/colada/plugin.ts
··· 1 + import type ts from 'typescript'; 2 + 3 + import { clientApi } from '../../../generate/client'; 4 + import type { IR } from '../../../ir/types'; 5 + import { tsc } from '../../../tsc'; 6 + import { stringCase } from '../../../utils/stringCase'; 7 + import { clientId } from '../../@hey-api/client-core/utils'; 8 + import { sdkId } from '../../@hey-api/sdk/constants'; 9 + import { 10 + operationClasses, 11 + operationOptionsType, 12 + } from '../../@hey-api/sdk/operation'; 13 + import { serviceFunctionIdentifier } from '../../@hey-api/sdk/plugin-legacy'; 14 + import { 15 + createOperationComment, 16 + isOperationOptionsRequired, 17 + } from '../../shared/utils/operation'; 18 + import type { PiniaColadaPlugin } from './types'; 19 + 20 + type PluginHandler = PiniaColadaPlugin['Handler']; 21 + type PluginInstance = PiniaColadaPlugin['Instance']; 22 + 23 + interface PluginState { 24 + hasMutations: boolean; 25 + hasQueries: boolean; 26 + hasUsedQueryFn: boolean; 27 + } 28 + 29 + const handleMeta = ( 30 + plugin: PluginInstance, 31 + operation: IR.OperationObject, 32 + type: 'queryOptions' | 'mutationOptions', 33 + ): ts.Expression | undefined => { 34 + const metaConfig = plugin.config[type].meta; 35 + 36 + if (typeof metaConfig !== 'function') { 37 + return undefined; 38 + } 39 + 40 + const customMeta = metaConfig(operation); 41 + 42 + return tsc.valueToExpression({ value: customMeta }); 43 + }; 44 + 45 + const useTypeData = ({ 46 + operation, 47 + plugin, 48 + }: { 49 + operation: IR.OperationObject; 50 + plugin: PluginInstance; 51 + }) => { 52 + const file = plugin.context.file({ id: plugin.name })!; 53 + const pluginSdk = plugin.getPlugin('@hey-api/sdk')!; 54 + const typeData = operationOptionsType({ file, operation, plugin: pluginSdk }); 55 + return typeData; 56 + }; 57 + 58 + const createQueryOptions = ({ 59 + operation, 60 + plugin, 61 + queryFn, 62 + state, 63 + }: { 64 + operation: IR.OperationObject; 65 + plugin: PluginInstance; 66 + queryFn: string; 67 + state: PluginState; 68 + }) => { 69 + if ( 70 + !plugin.config.queryOptions || 71 + !(['get', 'post'] as ReadonlyArray<typeof operation.method>).includes( 72 + operation.method, 73 + ) 74 + ) { 75 + return state; 76 + } 77 + 78 + const file = plugin.context.file({ id: plugin.name })!; 79 + const isRequiredOptions = isOperationOptionsRequired({ 80 + context: plugin.context, 81 + operation, 82 + }); 83 + 84 + if (!state.hasQueries) { 85 + state.hasQueries = true; 86 + } 87 + 88 + state.hasUsedQueryFn = true; 89 + 90 + const typeData = useTypeData({ operation, plugin }); 91 + 92 + const identifierQueryOptions = file.identifier({ 93 + $ref: `#/pinia-colada-query-options/${operation.id}`, 94 + case: plugin.config.queryOptions.case, 95 + create: true, 96 + nameTransformer: plugin.config.queryOptions.name, 97 + namespace: 'value', 98 + }); 99 + 100 + const awaitSdkExpression = tsc.awaitExpression({ 101 + expression: tsc.callExpression({ 102 + functionName: queryFn, 103 + parameters: [ 104 + tsc.objectExpression({ 105 + multiLine: true, 106 + obj: [ 107 + { 108 + spread: 'options', 109 + }, 110 + { 111 + key: 'signal', 112 + value: tsc.identifier({ 113 + text: 'context.signal', 114 + }), 115 + }, 116 + { 117 + key: 'throwOnError', 118 + value: true, 119 + }, 120 + ], 121 + }), 122 + ], 123 + }), 124 + }); 125 + 126 + const statements: Array<ts.Statement> = []; 127 + 128 + if (plugin.getPlugin('@hey-api/sdk')?.config.responseStyle === 'data') { 129 + statements.push( 130 + tsc.returnVariable({ 131 + expression: awaitSdkExpression, 132 + }), 133 + ); 134 + } else { 135 + statements.push( 136 + tsc.constVariable({ 137 + destructure: true, 138 + expression: awaitSdkExpression, 139 + name: 'data', 140 + }), 141 + tsc.returnVariable({ 142 + expression: 'data', 143 + }), 144 + ); 145 + } 146 + 147 + // Generate query options object for Pinia Colada 148 + const queryOptionsObj: Array<{ key: string; value: ts.Expression }> = [ 149 + { 150 + key: 'key', 151 + value: tsc.arrayLiteralExpression({ 152 + elements: [ 153 + tsc.stringLiteral({ text: operation.id || '' }), 154 + tsc.identifier({ text: 'options?.path' }), 155 + ], 156 + }), 157 + }, 158 + { 159 + key: 'query', 160 + value: tsc.arrowFunction({ 161 + async: true, 162 + multiLine: true, 163 + parameters: [ 164 + { 165 + name: 'context', 166 + type: tsc.typeReferenceNode({ 167 + typeName: '{ signal: AbortSignal }', 168 + }), 169 + }, 170 + ], 171 + statements, 172 + }), 173 + }, 174 + ]; 175 + 176 + const meta = handleMeta(plugin, operation, 'queryOptions'); 177 + 178 + if (meta) { 179 + queryOptionsObj.push({ 180 + key: 'meta', 181 + value: meta, 182 + }); 183 + } 184 + 185 + const statement = tsc.constVariable({ 186 + comment: plugin.config.comments 187 + ? createOperationComment({ operation }) 188 + : undefined, 189 + exportConst: true, 190 + expression: tsc.arrowFunction({ 191 + parameters: [ 192 + { 193 + isRequired: isRequiredOptions, 194 + name: 'options', 195 + type: typeData, 196 + }, 197 + ], 198 + statements: [ 199 + tsc.returnStatement({ 200 + expression: tsc.objectExpression({ 201 + obj: queryOptionsObj, 202 + }), 203 + }), 204 + ], 205 + }), 206 + name: identifierQueryOptions.name || '', 207 + }); 208 + 209 + file.add(statement); 210 + 211 + return state; 212 + }; 213 + 214 + const createMutationOptions = ({ 215 + operation, 216 + plugin, 217 + queryFn, 218 + state, 219 + }: { 220 + operation: IR.OperationObject; 221 + plugin: PluginInstance; 222 + queryFn: string; 223 + state: PluginState; 224 + }) => { 225 + if ( 226 + !plugin.config.mutationOptions || 227 + (['get'] as ReadonlyArray<typeof operation.method>).includes( 228 + operation.method, 229 + ) 230 + ) { 231 + return state; 232 + } 233 + 234 + const file = plugin.context.file({ id: plugin.name })!; 235 + 236 + if (!state.hasMutations) { 237 + state.hasMutations = true; 238 + } 239 + 240 + state.hasUsedQueryFn = true; 241 + 242 + const typeData = useTypeData({ operation, plugin }); 243 + 244 + const identifierMutationOptions = file.identifier({ 245 + $ref: `#/pinia-colada-mutation-options/${operation.id}`, 246 + case: plugin.config.mutationOptions.case, 247 + create: true, 248 + nameTransformer: plugin.config.mutationOptions.name, 249 + namespace: 'value', 250 + }); 251 + 252 + const awaitSdkExpression = tsc.awaitExpression({ 253 + expression: tsc.callExpression({ 254 + functionName: queryFn, 255 + parameters: ['options'], 256 + }), 257 + }); 258 + 259 + const statements: Array<ts.Statement> = []; 260 + 261 + if (plugin.getPlugin('@hey-api/sdk')?.config.responseStyle === 'data') { 262 + statements.push( 263 + tsc.returnVariable({ 264 + expression: awaitSdkExpression, 265 + }), 266 + ); 267 + } else { 268 + statements.push( 269 + tsc.constVariable({ 270 + destructure: true, 271 + expression: awaitSdkExpression, 272 + name: 'data', 273 + }), 274 + tsc.returnVariable({ 275 + expression: 'data', 276 + }), 277 + ); 278 + } 279 + 280 + // Generate mutation options object for Pinia Colada 281 + const mutationOptionsObj: Array<{ key: string; value: ts.Expression }> = [ 282 + { 283 + key: 'mutation', 284 + value: tsc.arrowFunction({ 285 + async: true, 286 + multiLine: true, 287 + parameters: [ 288 + { 289 + name: 'options', 290 + type: typeData, 291 + }, 292 + ], 293 + statements, 294 + }), 295 + }, 296 + ]; 297 + 298 + const meta = handleMeta(plugin, operation, 'mutationOptions'); 299 + 300 + if (meta) { 301 + mutationOptionsObj.push({ 302 + key: 'meta', 303 + value: meta, 304 + }); 305 + } 306 + 307 + const statement = tsc.constVariable({ 308 + comment: plugin.config.comments 309 + ? createOperationComment({ operation }) 310 + : undefined, 311 + exportConst: true, 312 + expression: tsc.arrowFunction({ 313 + parameters: [ 314 + { 315 + isRequired: false, 316 + name: 'options', 317 + type: typeData, 318 + }, 319 + ], 320 + statements: [ 321 + tsc.returnStatement({ 322 + expression: tsc.objectExpression({ 323 + obj: mutationOptionsObj, 324 + }), 325 + }), 326 + ], 327 + }), 328 + name: identifierMutationOptions.name || '', 329 + }); 330 + 331 + file.add(statement); 332 + 333 + return state; 334 + }; 335 + 336 + export const handler: PluginHandler = ({ plugin }) => { 337 + const file = plugin.createFile({ 338 + case: plugin.config.case, 339 + id: plugin.name, 340 + path: plugin.output, 341 + }); 342 + 343 + const state: PluginState = { 344 + hasMutations: false, 345 + hasQueries: false, 346 + hasUsedQueryFn: false, 347 + }; 348 + 349 + // Import Options type from SDK 350 + file.import({ 351 + ...clientApi.Options, 352 + module: file.relativePathToFile({ context: plugin.context, id: sdkId }), 353 + }); 354 + 355 + plugin.forEach( 356 + 'operation', 357 + ({ operation }: { operation: IR.OperationObject }) => { 358 + state.hasUsedQueryFn = false; 359 + 360 + const sdkPlugin = plugin.getPlugin('@hey-api/sdk'); 361 + const classes = sdkPlugin?.config.asClass 362 + ? operationClasses({ 363 + context: plugin.context, 364 + operation, 365 + plugin: sdkPlugin, 366 + }) 367 + : undefined; 368 + const entry = classes ? classes.values().next().value : undefined; 369 + const queryFn = 370 + // TODO: this should use class graph to determine correct path string 371 + // as it's really easy to break once we change the class casing 372 + ( 373 + entry 374 + ? [ 375 + entry.path[0], 376 + ...entry.path.slice(1).map((className: string) => 377 + stringCase({ 378 + case: 'camelCase', 379 + value: className, 380 + }), 381 + ), 382 + entry.methodName, 383 + ].filter(Boolean) 384 + : [ 385 + serviceFunctionIdentifier({ 386 + config: plugin.context.config, 387 + handleIllegal: true, 388 + id: operation.id, 389 + operation, 390 + }), 391 + ] 392 + ).join('.'); 393 + 394 + createQueryOptions({ 395 + operation, 396 + plugin, 397 + queryFn, 398 + state, 399 + }); 400 + 401 + createMutationOptions({ 402 + operation, 403 + plugin, 404 + queryFn, 405 + state, 406 + }); 407 + 408 + if (state.hasUsedQueryFn) { 409 + file.import({ 410 + module: file.relativePathToFile({ 411 + context: plugin.context, 412 + id: sdkId, 413 + }), 414 + name: queryFn.split('.')[0]!, 415 + }); 416 + } 417 + }, 418 + ); 419 + 420 + if (state.hasQueries || state.hasMutations) { 421 + file.import({ 422 + alias: '_heyApiClient', 423 + module: file.relativePathToFile({ 424 + context: plugin.context, 425 + id: clientId, 426 + }), 427 + name: 'client', 428 + }); 429 + } 430 + };
+259
packages/openapi-ts/src/plugins/@pinia/colada/types.d.ts
··· 1 + import type { IR } from '../../../ir/types'; 2 + import type { StringCase, StringName } from '../../../types/case'; 3 + import type { DefinePlugin, Plugin } from '../../types'; 4 + 5 + export type UserConfig = Plugin.Name<'@pinia/colada'> & { 6 + /** 7 + * The casing convention to use for generated names. 8 + * 9 + * @default 'camelCase' 10 + */ 11 + case?: StringCase; 12 + /** 13 + * Add comments from SDK functions to the generated Pinia Colada code? 14 + * 15 + * @default true 16 + */ 17 + comments?: boolean; 18 + /** 19 + * Should the exports from the generated files be re-exported in the index barrel file? 20 + * 21 + * @default false 22 + */ 23 + exportFromIndex?: boolean; 24 + /** 25 + * Configuration for generated mutation options helpers. 26 + * 27 + * Can be: 28 + * - `boolean`: Shorthand for `{ enabled: boolean }` 29 + * - `string` or `function`: Shorthand for `{ name: string | function }` 30 + * - `object`: Full configuration object 31 + * 32 + * @default true 33 + */ 34 + mutationOptions?: 35 + | boolean 36 + | StringName 37 + | { 38 + /** 39 + * The casing convention to use for generated names. 40 + * 41 + * @default 'camelCase' 42 + */ 43 + case?: StringCase; 44 + /** 45 + * Whether to generate mutation options helpers. 46 + * 47 + * @default true 48 + */ 49 + enabled?: boolean; 50 + /** 51 + * Custom function to generate metadata for the operation. 52 + * Can return any valid meta object that will be included in the generated mutation options. 53 + * 54 + * @param operation - The operation object containing all available metadata 55 + * @returns A meta object with any properties you want to include 56 + * 57 + * @example 58 + * ```typescript 59 + * meta: (operation) => ({ 60 + * customField: operation.id, 61 + * isDeprecated: operation.deprecated, 62 + * tags: operation.tags, 63 + * customObject: { 64 + * method: operation.method, 65 + * path: operation.path 66 + * } 67 + * }) 68 + * ``` 69 + */ 70 + meta?: false | ((operation: IR.OperationObject) => Record<string, any>); 71 + /** 72 + * Custom naming pattern for generated mutation options names. The name variable is 73 + * obtained from the SDK function name. 74 + * 75 + * @default '{{name}}Mutation' 76 + */ 77 + name?: StringName; 78 + }; 79 + /** 80 + * Name of the generated file. 81 + * 82 + * @default '@pinia/colada' 83 + */ 84 + output?: string; 85 + /** 86 + * Configuration for generated query options helpers. 87 + * 88 + * Can be: 89 + * - `boolean`: Shorthand for `{ enabled: boolean }` 90 + * - `string` or `function`: Shorthand for `{ name: string | function }` 91 + * - `object`: Full configuration object 92 + * 93 + * @default true 94 + */ 95 + queryOptions?: 96 + | boolean 97 + | StringName 98 + | { 99 + /** 100 + * The casing convention to use for generated names. 101 + * 102 + * @default 'camelCase' 103 + */ 104 + case?: StringCase; 105 + /** 106 + * Whether to generate query options helpers. 107 + * 108 + * @default true 109 + */ 110 + enabled?: boolean; 111 + /** 112 + * Custom function to generate metadata for the operation. 113 + * Can return any valid meta object that will be included in the generated query options. 114 + * 115 + * @param operation - The operation object containing all available metadata 116 + * @returns A meta object with any properties you want to include 117 + * 118 + * @example 119 + * ```typescript 120 + * meta: (operation) => ({ 121 + * customField: operation.id, 122 + * isDeprecated: operation.deprecated, 123 + * tags: operation.tags, 124 + * customObject: { 125 + * method: operation.method, 126 + * path: operation.path 127 + * } 128 + * }) 129 + * ``` 130 + */ 131 + meta?: false | ((operation: IR.OperationObject) => Record<string, any>); 132 + /** 133 + * Custom naming pattern for generated query options names. The name variable is 134 + * obtained from the SDK function name. 135 + * 136 + * @default '{{name}}Query' 137 + */ 138 + name?: StringName; 139 + }; 140 + }; 141 + 142 + export type Config = Plugin.Name<'@pinia/colada'> & { 143 + /** 144 + * The casing convention to use for generated names. 145 + * 146 + * @default 'camelCase' 147 + */ 148 + case: StringCase; 149 + /** 150 + * Add comments from SDK functions to the generated Pinia Colada code? 151 + * 152 + * @default true 153 + */ 154 + comments: boolean; 155 + /** 156 + * Should the exports from the generated files be re-exported in the index barrel file? 157 + * 158 + * @default false 159 + */ 160 + exportFromIndex: boolean; 161 + /** 162 + * Resolved configuration for generated mutation options helpers. 163 + */ 164 + mutationOptions: { 165 + /** 166 + * The casing convention to use for generated names. 167 + * 168 + * @default 'camelCase' 169 + */ 170 + case: StringCase; 171 + /** 172 + * Whether to generate mutation options helpers. 173 + * 174 + * @default true 175 + */ 176 + enabled: boolean; 177 + /** 178 + * Custom function to generate metadata for the operation. 179 + * Can return any valid meta object that will be included in the generated mutation options. 180 + * 181 + * @param operation - The operation object containing all available metadata 182 + * @returns A meta object with any properties you want to include 183 + * 184 + * @example 185 + * ```typescript 186 + * meta: (operation) => ({ 187 + * customField: operation.id, 188 + * isDeprecated: operation.deprecated, 189 + * tags: operation.tags, 190 + * customObject: { 191 + * method: operation.method, 192 + * path: operation.path 193 + * } 194 + * }) 195 + * ``` 196 + */ 197 + meta?: false | ((operation: IR.OperationObject) => Record<string, any>); 198 + /** 199 + * Custom naming pattern for generated mutation options names. The name variable is 200 + * obtained from the SDK function name. 201 + * 202 + * @default '{{name}}Mutation' 203 + */ 204 + name: StringName; 205 + }; 206 + /** 207 + * Name of the generated file. 208 + * 209 + * @default '@pinia/colada' 210 + */ 211 + output: string; 212 + /** 213 + * Resolved configuration for generated query options helpers. 214 + */ 215 + queryOptions: { 216 + /** 217 + * The casing convention to use for generated names. 218 + * 219 + * @default 'camelCase' 220 + */ 221 + case: StringCase; 222 + /** 223 + * Whether to generate query options helpers. 224 + * 225 + * @default true 226 + */ 227 + enabled: boolean; 228 + /** 229 + * Custom function to generate metadata for the operation. 230 + * Can return any valid meta object that will be included in the generated query options. 231 + * 232 + * @param operation - The operation object containing all available metadata 233 + * @returns A meta object with any properties you want to include 234 + * 235 + * @example 236 + * ```typescript 237 + * meta: (operation) => ({ 238 + * customField: operation.id, 239 + * isDeprecated: operation.deprecated, 240 + * tags: operation.tags, 241 + * customObject: { 242 + * method: operation.method, 243 + * path: operation.path 244 + * } 245 + * }) 246 + * ``` 247 + */ 248 + meta?: false | ((operation: IR.OperationObject) => Record<string, any>); 249 + /** 250 + * Custom naming pattern for generated query options names. The name variable is 251 + * obtained from the SDK function name. 252 + * 253 + * @default '{{name}}Query' 254 + */ 255 + name: StringName; 256 + }; 257 + }; 258 + 259 + export type PiniaColadaPlugin = DefinePlugin<UserConfig, Config>;
+4
packages/openapi-ts/src/plugins/config.ts
··· 28 28 import { defaultConfig as heyApiTransformers } from './@hey-api/transformers'; 29 29 import type { HeyApiTypeScriptPlugin } from './@hey-api/typescript'; 30 30 import { defaultConfig as heyApiTypeScript } from './@hey-api/typescript'; 31 + import type { PiniaColadaPlugin } from './@pinia/colada'; 32 + import { defaultConfig as piniaColada } from './@pinia/colada'; 31 33 import type { TanStackAngularQueryPlugin } from './@tanstack/angular-query-experimental'; 32 34 import { defaultConfig as tanStackAngularQuery } from './@tanstack/angular-query-experimental'; 33 35 import type { TanStackReactQueryPlugin } from './@tanstack/react-query'; ··· 57 59 '@hey-api/sdk': HeyApiSdkPlugin['Types']; 58 60 '@hey-api/transformers': HeyApiTransformersPlugin['Types']; 59 61 '@hey-api/typescript': HeyApiTypeScriptPlugin['Types']; 62 + '@pinia/colada': PiniaColadaPlugin['Types']; 60 63 '@tanstack/angular-query-experimental': TanStackAngularQueryPlugin['Types']; 61 64 '@tanstack/react-query': TanStackReactQueryPlugin['Types']; 62 65 '@tanstack/solid-query': TanStackSolidQueryPlugin['Types']; ··· 85 88 '@hey-api/sdk': heyApiSdk, 86 89 '@hey-api/transformers': heyApiTransformers, 87 90 '@hey-api/typescript': heyApiTypeScript, 91 + '@pinia/colada': piniaColada, 88 92 '@tanstack/angular-query-experimental': tanStackAngularQuery, 89 93 '@tanstack/react-query': tanStackReactQuery, 90 94 '@tanstack/solid-query': tanStackSolidQuery,
+1
packages/openapi-ts/src/plugins/types.d.ts
··· 26 26 | '@hey-api/sdk' 27 27 | '@hey-api/transformers' 28 28 | '@hey-api/typescript' 29 + | '@pinia/colada' 29 30 | '@tanstack/angular-query-experimental' 30 31 | '@tanstack/react-query' 31 32 | '@tanstack/solid-query'
+158 -49
pnpm-lock.yaml
··· 605 605 specifier: 7.1.2 606 606 version: 7.1.2(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0) 607 607 608 + examples/openapi-ts-pinia-colada: 609 + dependencies: 610 + '@pinia/colada': 611 + specifier: 0.17.0 612 + version: 0.17.0(pinia@2.3.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))) 613 + pinia: 614 + specifier: 2.3.0 615 + version: 2.3.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)) 616 + vue: 617 + specifier: 3.5.13 618 + version: 3.5.13(typescript@5.8.3) 619 + vue-router: 620 + specifier: 4.5.0 621 + version: 4.5.0(vue@3.5.13(typescript@5.8.3)) 622 + devDependencies: 623 + '@config/vite-base': 624 + specifier: workspace:* 625 + version: link:../../packages/config-vite-base 626 + '@hey-api/openapi-ts': 627 + specifier: workspace:* 628 + version: link:../../packages/openapi-ts 629 + '@rushstack/eslint-patch': 630 + specifier: 1.10.5 631 + version: 1.10.5 632 + '@tsconfig/node20': 633 + specifier: 20.1.4 634 + version: 20.1.4 635 + '@types/jsdom': 636 + specifier: 21.1.7 637 + version: 21.1.7 638 + '@types/node': 639 + specifier: 22.10.5 640 + version: 22.10.5 641 + '@vitejs/plugin-vue': 642 + specifier: 5.2.1 643 + version: 5.2.1(vite@7.1.2(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.8.3)) 644 + '@vitejs/plugin-vue-jsx': 645 + specifier: 4.1.1 646 + version: 4.1.1(vite@7.1.2(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.8.3)) 647 + '@vue/eslint-config-prettier': 648 + specifier: 10.1.0 649 + version: 10.1.0(@types/eslint@9.6.0)(eslint@9.17.0(jiti@2.4.2))(prettier@3.4.2) 650 + '@vue/eslint-config-typescript': 651 + specifier: 14.2.0 652 + version: 14.2.0(eslint-plugin-vue@9.32.0(eslint@9.17.0(jiti@2.4.2)))(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.3) 653 + '@vue/test-utils': 654 + specifier: 2.4.6 655 + version: 2.4.6 656 + '@vue/tsconfig': 657 + specifier: 0.7.0 658 + version: 0.7.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)) 659 + autoprefixer: 660 + specifier: 10.4.20 661 + version: 10.4.20(postcss@8.4.41) 662 + eslint: 663 + specifier: 9.17.0 664 + version: 9.17.0(jiti@2.4.2) 665 + eslint-plugin-vue: 666 + specifier: 9.32.0 667 + version: 9.32.0(eslint@9.17.0(jiti@2.4.2)) 668 + jsdom: 669 + specifier: 23.0.0 670 + version: 23.0.0 671 + npm-run-all2: 672 + specifier: 6.2.0 673 + version: 6.2.0 674 + postcss: 675 + specifier: 8.4.41 676 + version: 8.4.41 677 + prettier: 678 + specifier: 3.4.2 679 + version: 3.4.2 680 + tailwindcss: 681 + specifier: 3.4.9 682 + version: 3.4.9(ts-node@10.9.2(@types/node@22.10.5)(typescript@5.8.3)) 683 + typescript: 684 + specifier: 5.8.3 685 + version: 5.8.3 686 + vite: 687 + specifier: 7.1.2 688 + version: 7.1.2(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0) 689 + vite-plugin-vue-devtools: 690 + specifier: 7.7.0 691 + version: 7.7.0(rollup@4.46.2)(vite@7.1.2(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0))(vue@3.5.13(typescript@5.8.3)) 692 + vitest: 693 + specifier: 3.1.1 694 + version: 3.1.1(@types/debug@4.1.12)(@types/node@22.10.5)(jiti@2.4.2)(jsdom@23.0.0)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0) 695 + vue-tsc: 696 + specifier: 2.2.0 697 + version: 2.2.0(typescript@5.8.3) 698 + 608 699 examples/openapi-ts-sample: 609 700 dependencies: 610 701 '@radix-ui/react-form': ··· 4028 4119 resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} 4029 4120 engines: {node: '>= 10.0.0'} 4030 4121 4122 + '@pinia/colada@0.17.0': 4123 + resolution: {integrity: sha512-u4lTNCbiUeachdRxIZ3CHKVKPJ56NP139+S4gs3AvwIZjn1l+us0QiYXppDXGKPv9yyH4msj+qFSy9CFhrfVKw==} 4124 + peerDependencies: 4125 + pinia: ^2.2.6 || ^3.0.0 4126 + 4031 4127 '@pkgjs/parseargs@0.11.0': 4032 4128 resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 4033 4129 engines: {node: '>=14'} ··· 5885 5981 '@vue/devtools-api@6.6.4': 5886 5982 resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} 5887 5983 5984 + '@vue/devtools-api@7.7.7': 5985 + resolution: {integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==} 5986 + 5888 5987 '@vue/devtools-api@8.0.0': 5889 5988 resolution: {integrity: sha512-I2jF/knesMU36zTw1hnExjoixDZvDoantiWKVrHpLd2J160zqqe8vp3vrGfjWdfuHmPJwSXe/YNG3rYOYiwy1Q==} 5890 5989 ··· 5904 6003 '@vue/devtools-kit@7.7.2': 5905 6004 resolution: {integrity: sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==} 5906 6005 6006 + '@vue/devtools-kit@7.7.7': 6007 + resolution: {integrity: sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==} 6008 + 5907 6009 '@vue/devtools-kit@8.0.0': 5908 6010 resolution: {integrity: sha512-b11OeQODkE0bctdT0RhL684pEV2DPXJ80bjpywVCbFn1PxuL3bmMPDoJKjbMnnoWbrnUYXYzFfmMWBZAMhORkQ==} 5909 6011 5910 6012 '@vue/devtools-shared@7.7.2': 5911 6013 resolution: {integrity: sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==} 5912 6014 6015 + '@vue/devtools-shared@7.7.7': 6016 + resolution: {integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==} 6017 + 5913 6018 '@vue/devtools-shared@8.0.0': 5914 6019 resolution: {integrity: sha512-jrKnbjshQCiOAJanoeJjTU7WaCg0Dz2BUal6SaR6VM/P3hiFdX5Q6Pxl73ZMnrhCxNK9nAg5hvvRGqs+6dtU1g==} 5915 6020 ··· 6588 6693 6589 6694 caniuse-api@3.0.0: 6590 6695 resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} 6591 - 6592 - caniuse-lite@1.0.30001703: 6593 - resolution: {integrity: sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==} 6594 6696 6595 6697 caniuse-lite@1.0.30001709: 6596 6698 resolution: {integrity: sha512-NgL3vUTnDrPCZ3zTahp4fsugQ4dc7EKTSzwQDPEel6DMoMnfH2jhry9n2Zm8onbSR+f/QtKHFOA+iAQu4kbtWA==} ··· 9453 9555 nanoid@3.3.11: 9454 9556 resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 9455 9557 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 9456 - hasBin: true 9457 - 9458 - nanoid@3.3.9: 9459 - resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} 9460 - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 9461 - hasBin: true 9462 - 9463 - nanoid@5.1.3: 9464 - resolution: {integrity: sha512-zAbEOEr7u2CbxwoMRlz/pNSpRP0FdAU4pRaYunCdEezWohXFs+a0Xw7RfkKaezMsmSM1vttcLthJtwRnVtOfHQ==} 9465 - engines: {node: ^18 || >=20} 9466 9558 hasBin: true 9467 9559 9468 9560 nanoid@5.1.5: ··· 13365 13457 '@babel/helper-compilation-targets': 7.26.5 13366 13458 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) 13367 13459 '@babel/helpers': 7.26.10 13368 - '@babel/parser': 7.26.10 13460 + '@babel/parser': 7.28.3 13369 13461 '@babel/template': 7.26.9 13370 13462 '@babel/traverse': 7.26.10 13371 - '@babel/types': 7.26.10 13463 + '@babel/types': 7.28.2 13372 13464 convert-source-map: 2.0.0 13373 13465 debug: 4.4.0(supports-color@9.4.0) 13374 13466 gensync: 1.0.0-beta.2 ··· 13387 13479 13388 13480 '@babel/generator@7.26.9': 13389 13481 dependencies: 13390 - '@babel/parser': 7.26.10 13391 - '@babel/types': 7.26.10 13482 + '@babel/parser': 7.28.3 13483 + '@babel/types': 7.28.2 13392 13484 '@jridgewell/gen-mapping': 0.3.8 13393 13485 '@jridgewell/trace-mapping': 0.3.25 13394 13486 jsesc: 3.1.0 13395 13487 13396 13488 '@babel/helper-annotate-as-pure@7.25.9': 13397 13489 dependencies: 13398 - '@babel/types': 7.26.10 13490 + '@babel/types': 7.28.2 13399 13491 13400 13492 '@babel/helper-compilation-targets@7.26.5': 13401 13493 dependencies: ··· 13452 13544 '@babel/helper-member-expression-to-functions@7.25.9': 13453 13545 dependencies: 13454 13546 '@babel/traverse': 7.26.10 13455 - '@babel/types': 7.26.10 13547 + '@babel/types': 7.28.2 13456 13548 transitivePeerDependencies: 13457 13549 - supports-color 13458 13550 ··· 13483 13575 13484 13576 '@babel/helper-optimise-call-expression@7.25.9': 13485 13577 dependencies: 13486 - '@babel/types': 7.26.10 13578 + '@babel/types': 7.28.2 13487 13579 13488 13580 '@babel/helper-plugin-utils@7.26.5': {} 13489 13581 ··· 13517 13609 '@babel/helper-skip-transparent-expression-wrappers@7.25.9': 13518 13610 dependencies: 13519 13611 '@babel/traverse': 7.26.10 13520 - '@babel/types': 7.26.10 13612 + '@babel/types': 7.28.2 13521 13613 transitivePeerDependencies: 13522 13614 - supports-color 13523 13615 13524 13616 '@babel/helper-split-export-declaration@7.24.7': 13525 13617 dependencies: 13526 - '@babel/types': 7.26.10 13618 + '@babel/types': 7.28.2 13527 13619 13528 13620 '@babel/helper-string-parser@7.25.9': {} 13529 13621 ··· 13539 13631 dependencies: 13540 13632 '@babel/template': 7.26.9 13541 13633 '@babel/traverse': 7.26.10 13542 - '@babel/types': 7.26.10 13634 + '@babel/types': 7.28.2 13543 13635 transitivePeerDependencies: 13544 13636 - supports-color 13545 13637 ··· 14076 14168 dependencies: 14077 14169 '@babel/core': 7.26.9 14078 14170 '@babel/helper-plugin-utils': 7.26.5 14079 - '@babel/types': 7.26.10 14171 + '@babel/types': 7.28.2 14080 14172 esutils: 2.0.3 14081 14173 14082 14174 '@babel/runtime@7.26.10': ··· 15943 16035 '@parcel/watcher-win32-ia32': 2.5.1 15944 16036 '@parcel/watcher-win32-x64': 2.5.1 15945 16037 16038 + '@pinia/colada@0.17.0(pinia@2.3.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)))': 16039 + dependencies: 16040 + '@vue/devtools-api': 7.7.7 16041 + pinia: 2.3.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)) 16042 + 15946 16043 '@pkgjs/parseargs@0.11.0': 15947 16044 optional: true 15948 16045 ··· 17841 17938 '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) 17842 17939 '@babel/template': 7.26.9 17843 17940 '@babel/traverse': 7.26.10 17844 - '@babel/types': 7.26.10 17941 + '@babel/types': 7.28.2 17845 17942 '@vue/babel-helper-vue-transform-on': 1.4.0 17846 17943 '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.26.10) 17847 17944 '@vue/shared': 3.5.18 ··· 17856 17953 '@babel/core': 7.26.10 17857 17954 '@babel/helper-module-imports': 7.25.9 17858 17955 '@babel/helper-plugin-utils': 7.26.5 17859 - '@babel/parser': 7.26.10 17956 + '@babel/parser': 7.28.3 17860 17957 '@vue/compiler-sfc': 3.5.18 17861 17958 transitivePeerDependencies: 17862 17959 - supports-color ··· 17928 18025 17929 18026 '@vue/devtools-api@6.6.4': {} 17930 18027 18028 + '@vue/devtools-api@7.7.7': 18029 + dependencies: 18030 + '@vue/devtools-kit': 7.7.7 18031 + 17931 18032 '@vue/devtools-api@8.0.0': 17932 18033 dependencies: 17933 18034 '@vue/devtools-kit': 8.0.0 ··· 17949 18050 '@vue/devtools-kit': 7.7.2 17950 18051 '@vue/devtools-shared': 7.7.2 17951 18052 mitt: 3.0.1 17952 - nanoid: 5.1.3 18053 + nanoid: 5.1.5 17953 18054 pathe: 2.0.3 17954 18055 vite-hot-client: 0.2.4(vite@7.1.2(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.8.0)) 17955 18056 vue: 3.5.13(typescript@5.8.3) ··· 17976 18077 speakingurl: 14.0.1 17977 18078 superjson: 2.2.2 17978 18079 18080 + '@vue/devtools-kit@7.7.7': 18081 + dependencies: 18082 + '@vue/devtools-shared': 7.7.7 18083 + birpc: 2.5.0 18084 + hookable: 5.5.3 18085 + mitt: 3.0.1 18086 + perfect-debounce: 1.0.0 18087 + speakingurl: 14.0.1 18088 + superjson: 2.2.2 18089 + 17979 18090 '@vue/devtools-kit@8.0.0': 17980 18091 dependencies: 17981 18092 '@vue/devtools-shared': 8.0.0 ··· 17987 18098 superjson: 2.2.2 17988 18099 17989 18100 '@vue/devtools-shared@7.7.2': 18101 + dependencies: 18102 + rfdc: 1.4.1 18103 + 18104 + '@vue/devtools-shared@7.7.7': 17990 18105 dependencies: 17991 18106 rfdc: 1.4.1 17992 18107 ··· 18420 18535 18421 18536 ast-walker-scope@0.6.2: 18422 18537 dependencies: 18423 - '@babel/parser': 7.26.10 18538 + '@babel/parser': 7.28.3 18424 18539 ast-kit: 1.4.2 18425 18540 18426 18541 async-function@1.0.0: {} ··· 18446 18561 autoprefixer@10.4.20(postcss@8.4.41): 18447 18562 dependencies: 18448 18563 browserslist: 4.24.4 18449 - caniuse-lite: 1.0.30001703 18564 + caniuse-lite: 1.0.30001709 18450 18565 fraction.js: 4.3.7 18451 18566 normalize-range: 0.1.2 18452 18567 picocolors: 1.1.1 ··· 18456 18571 autoprefixer@10.4.20(postcss@8.5.2): 18457 18572 dependencies: 18458 18573 browserslist: 4.24.4 18459 - caniuse-lite: 1.0.30001703 18574 + caniuse-lite: 1.0.30001709 18460 18575 fraction.js: 4.3.7 18461 18576 normalize-range: 0.1.2 18462 18577 picocolors: 1.1.1 ··· 18466 18581 autoprefixer@10.4.20(postcss@8.5.6): 18467 18582 dependencies: 18468 18583 browserslist: 4.24.4 18469 - caniuse-lite: 1.0.30001703 18584 + caniuse-lite: 1.0.30001709 18470 18585 fraction.js: 4.3.7 18471 18586 normalize-range: 0.1.2 18472 18587 picocolors: 1.1.1 ··· 18646 18761 18647 18762 browserslist@4.24.4: 18648 18763 dependencies: 18649 - caniuse-lite: 1.0.30001703 18764 + caniuse-lite: 1.0.30001709 18650 18765 electron-to-chromium: 1.5.114 18651 18766 node-releases: 2.0.19 18652 18767 update-browserslist-db: 1.1.3(browserslist@4.24.4) ··· 18767 18882 caniuse-lite: 1.0.30001709 18768 18883 lodash.memoize: 4.1.2 18769 18884 lodash.uniq: 4.5.0 18770 - 18771 - caniuse-lite@1.0.30001703: {} 18772 18885 18773 18886 caniuse-lite@1.0.30001709: {} 18774 18887 ··· 19984 20097 natural-compare: 1.4.0 19985 20098 nth-check: 2.1.1 19986 20099 postcss-selector-parser: 6.1.2 19987 - semver: 7.7.1 20100 + semver: 7.7.2 19988 20101 vue-eslint-parser: 9.4.3(eslint@9.17.0(jiti@2.4.2)) 19989 20102 xml-name-validator: 4.0.0 19990 20103 transitivePeerDependencies: ··· 21234 21347 istanbul-lib-instrument@6.0.3: 21235 21348 dependencies: 21236 21349 '@babel/core': 7.26.10 21237 - '@babel/parser': 7.26.10 21350 + '@babel/parser': 7.28.3 21238 21351 '@istanbuljs/schema': 0.1.3 21239 21352 istanbul-lib-coverage: 3.2.2 21240 21353 semver: 7.7.2 ··· 21739 21852 21740 21853 magicast@0.3.5: 21741 21854 dependencies: 21742 - '@babel/parser': 7.26.10 21743 - '@babel/types': 7.26.10 21855 + '@babel/parser': 7.28.3 21856 + '@babel/types': 7.28.2 21744 21857 source-map-js: 1.2.1 21745 21858 21746 21859 make-dir@2.1.0: ··· 22214 22327 22215 22328 nanoid@3.3.11: {} 22216 22329 22217 - nanoid@3.3.9: {} 22218 - 22219 - nanoid@5.1.3: {} 22220 - 22221 22330 nanoid@5.1.5: {} 22222 22331 22223 22332 nanotar@0.1.1: {} ··· 23468 23577 23469 23578 postcss@8.5.2: 23470 23579 dependencies: 23471 - nanoid: 3.3.9 23580 + nanoid: 3.3.11 23472 23581 picocolors: 1.1.1 23473 23582 source-map-js: 1.2.1 23474 23583 ··· 25377 25486 25378 25487 unplugin-vue-router@0.10.9(rollup@3.29.5)(vue-router@4.5.0(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3)): 25379 25488 dependencies: 25380 - '@babel/types': 7.26.10 25489 + '@babel/types': 7.28.2 25381 25490 '@rollup/pluginutils': 5.1.4(rollup@3.29.5) 25382 25491 '@vue-macros/common': 1.16.1(vue@3.5.13(typescript@5.8.3)) 25383 25492 ast-walker-scope: 0.6.2 ··· 25399 25508 25400 25509 unplugin-vue-router@0.10.9(rollup@4.46.2)(vue-router@4.5.0(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3)): 25401 25510 dependencies: 25402 - '@babel/types': 7.26.10 25511 + '@babel/types': 7.28.2 25403 25512 '@rollup/pluginutils': 5.1.4(rollup@4.46.2) 25404 25513 '@vue-macros/common': 1.16.1(vue@3.5.13(typescript@5.8.3)) 25405 25514 ast-walker-scope: 0.6.2 ··· 25464 25573 dependencies: 25465 25574 '@babel/core': 7.26.10 25466 25575 '@babel/standalone': 7.26.10 25467 - '@babel/types': 7.26.10 25576 + '@babel/types': 7.28.2 25468 25577 citty: 0.1.6 25469 25578 defu: 6.1.4 25470 25579 jiti: 2.4.2 ··· 25633 25742 debug: 4.4.0(supports-color@9.4.0) 25634 25743 error-stack-parser-es: 0.1.5 25635 25744 fs-extra: 11.3.0 25636 - open: 10.1.0 25745 + open: 10.1.2 25637 25746 perfect-debounce: 1.0.0 25638 25747 picocolors: 1.1.1 25639 25748 sirv: 3.0.1 ··· 25651 25760 debug: 4.4.0(supports-color@9.4.0) 25652 25761 error-stack-parser-es: 0.1.5 25653 25762 fs-extra: 11.3.0 25654 - open: 10.1.0 25763 + open: 10.1.2 25655 25764 perfect-debounce: 1.0.0 25656 25765 picocolors: 1.1.1 25657 25766 sirv: 3.0.1 ··· 26034 26143 http-proxy-middleware: 2.0.7(@types/express@4.17.21) 26035 26144 ipaddr.js: 2.2.0 26036 26145 launch-editor: 2.10.0 26037 - open: 10.1.0 26146 + open: 10.1.2 26038 26147 p-retry: 6.2.1 26039 26148 schema-utils: 4.3.0 26040 26149 selfsigned: 2.4.1