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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'main' of https://github.com/nicolas-chaulet/openapi-typescript-codegen into feat/clients

Lubos db92b225 805e7688

+1569 -1033
-5
.changeset/smart-buttons-mate.md
··· 1 - --- 2 - "@hey-api/openapi-ts": patch 3 - --- 4 - 5 - fix: comment position in JavaScript enums
+2 -2
.github/workflows/ci.yml
··· 22 22 steps: 23 23 - uses: actions/checkout@v4 24 24 25 - - uses: pnpm/action-setup@v3 25 + - uses: pnpm/action-setup@v4 26 26 with: 27 - version: 8 27 + version: 8.15.7 28 28 29 29 - uses: actions/setup-node@v4 30 30 with:
+2 -2
.github/workflows/coverage.yml
··· 21 21 steps: 22 22 - uses: actions/checkout@v4 23 23 24 - - uses: pnpm/action-setup@v3 24 + - uses: pnpm/action-setup@v4 25 25 with: 26 - version: 8 26 + version: 8.15.7 27 27 28 28 - uses: actions/setup-node@v4 29 29 with:
+2 -2
.github/workflows/release.yml
··· 14 14 steps: 15 15 - uses: actions/checkout@v4 16 16 17 - - uses: pnpm/action-setup@v3 17 + - uses: pnpm/action-setup@v4 18 18 with: 19 - version: 8 19 + version: 8.15.7 20 20 21 21 - uses: actions/setup-node@v4 22 22 with:
-2
README.md
··· 13 13 - works with CLI, Node.js, or npx 14 14 - supports OpenAPI 2.0, 3.0, and 3.1 specifications 15 15 - supports both JSON and YAML input files 16 - - supports external references using [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser/) 17 16 - generates TypeScript interfaces, REST clients, and JSON Schemas 18 17 - Fetch API, Axios, Angular, Node.js, and XHR clients available 19 - - abortable requests through cancellable promise pattern 20 18 21 19 ## Documentation 22 20
+12
docs/CHANGELOG.md
··· 1 1 # @hey-api/docs 2 2 3 + ## 0.5.5 4 + 5 + ### Patch Changes 6 + 7 + - docs: add migration for v0.45.0 ([#569](https://github.com/hey-api/openapi-ts/pull/569)) 8 + 9 + ## 0.5.4 10 + 11 + ### Patch Changes 12 + 13 + - docs: add format and lint migration for 0.44.0 ([#546](https://github.com/hey-api/openapi-ts/pull/546)) 14 + 3 15 ## 0.5.3 4 16 5 17 ### Patch Changes
+1 -1
docs/openapi-ts/clients.md
··· 11 11 12 12 ## Legacy Clients 13 13 14 - Before standalone client packages, clients were generated using `openapi-ts`. If you want to use a client that isn't published as a standalone package, you can explicitly set the `client` config option to generate it. 14 + Before standalone client packages, clients were generated using `openapi-ts`. If you want to generate a legacy client that isn't published as a standalone package, you can use the `client` config option. 15 15 16 16 ::: code-group 17 17
+58 -21
docs/openapi-ts/configuration.md
··· 40 40 41 41 ## Clients 42 42 43 - By default, `openapi-ts` will try to guess your client based on your project dependencies. If we don't get it right, you can specify the desired client 43 + By default, `openapi-ts` will generate a Fetch API client. If you want a different client, you can specify it using the `client` option. 44 44 45 45 ::: code-group 46 46 ··· 101 101 You might not need a `node` client. Fetch API is [experimental](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch) in Node.js v18 and [stable](https://nodejs.org/docs/latest-v21.x/api/globals.html#fetch) in Node.js v21. We recommend upgrading to the latest Node.js version. 102 102 ::: 103 103 104 + <!-- 105 + TODO: uncomment after c12 supports multiple configs 106 + see https://github.com/unjs/c12/issues/92 107 + --> 108 + <!-- ### Multiple Clients 109 + 110 + If you want to generate multiple clients with a single `openapi-ts` command, you can provide an array of configuration objects. 111 + 112 + ```js 113 + import { defineConfig } from '@hey-api/openapi-ts'; 114 + 115 + export default defineConfig([ 116 + { 117 + client: 'fetch', 118 + input: 'path/to/openapi_one.json', 119 + output: 'src/client_one', 120 + }, 121 + { 122 + client: 'axios', 123 + input: 'path/to/openapi_two.json', 124 + output: 'src/client_two', 125 + }, 126 + ]) 127 + ``` --> 128 + 104 129 ## Formatting 105 130 106 - By default, `openapi-ts` will not automatically format your client. To enable this feature, set `format` to a valid formatter. 131 + By default, `openapi-ts` will not automatically format your client. To enable this feature, set `output.format` to a valid formatter. 107 132 108 133 ::: code-group 109 134 110 - ```js{2} [disabled] 135 + ```js{4} [disabled] 111 136 export default { 112 - format: false, 113 137 input: 'path/to/openapi.json', 114 - output: 'src/client', 138 + output: { 139 + format: false, 140 + path: 'src/client', 141 + }, 115 142 } 116 143 ``` 117 144 118 - ```js{2} [prettier] 145 + ```js{4} [prettier] 119 146 export default { 120 - format: 'prettier', 121 147 input: 'path/to/openapi.json', 122 - output: 'src/client', 148 + output: { 149 + format: 'prettier', 150 + path: 'src/client', 151 + }, 123 152 } 124 153 ``` 125 154 126 - ```js{2} [biome] 155 + ```js{4} [biome] 127 156 export default { 128 - format: 'biome', 129 157 input: 'path/to/openapi.json', 130 - output: 'src/client', 158 + output: { 159 + format: 'biome', 160 + path: 'src/client', 161 + }, 131 162 } 132 163 ``` 133 164 ··· 137 168 138 169 ## Linting 139 170 140 - For performance reasons, `openapi-ts` does not automatically lint your client. To enable this feature, set `lint` to a valid linter. 171 + For performance reasons, `openapi-ts` does not automatically lint your client. To enable this feature, set `output.lint` to a valid linter. 141 172 142 173 ::: code-group 143 174 144 - ```js{3} [disabled] 175 + ```js{4} [disabled] 145 176 export default { 146 177 input: 'path/to/openapi.json', 147 - lint: false, 148 - output: 'src/client', 178 + output: { 179 + lint: false, 180 + path: 'src/client', 181 + }, 149 182 } 150 183 ``` 151 184 152 - ```js{3} [eslint] 185 + ```js{4} [eslint] 153 186 export default { 154 187 input: 'path/to/openapi.json', 155 - lint: 'eslint', 156 - output: 'src/client', 188 + output: { 189 + lint: 'eslint', 190 + path: 'src/client', 191 + }, 157 192 } 158 193 ``` 159 194 160 - ```js{3} [biome] 195 + ```js{4} [biome] 161 196 export default { 162 197 input: 'path/to/openapi.json', 163 - lint: 'biome', 164 - output: 'src/client', 198 + output: { 199 + lint: 'biome', 200 + path: 'src/client', 201 + }, 165 202 } 166 203 ``` 167 204
-2
docs/openapi-ts/get-started.md
··· 20 20 - works with CLI, Node.js, or npx 21 21 - supports OpenAPI 2.0, 3.0, and 3.1 specifications 22 22 - supports both JSON and YAML input files 23 - - supports external references using [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser/) 24 23 - generates TypeScript interfaces, REST clients, and JSON Schemas 25 24 - Fetch API, Axios, Angular, Node.js, and XHR clients available 26 - - abortable requests through cancellable promise pattern 27 25 28 26 ## Quick Start 29 27
+45 -1
docs/openapi-ts/migrating.md
··· 50 50 51 51 This config option is deprecated and will be removed in favor of [clients](./clients). 52 52 53 + ## v0.45.0 54 + 55 + ### Removed `client` inference 56 + 57 + `openapi-ts` will no longer infer which client you want to generate. By default, we will create a `fetch` client. If you want a different client, you can specify it using the `client` option. 58 + 59 + ```js{2} 60 + export default { 61 + client: 'axios', 62 + input: 'path/to/openapi.json', 63 + output: 'src/client', 64 + } 65 + ``` 66 + 67 + ## v0.44.0 68 + 69 + ### Moved `format` 70 + 71 + This config option has been moved. You can now configure formatter using the `output.format` option. 72 + 73 + ```js{4} 74 + export default { 75 + input: 'path/to/openapi.json', 76 + output: { 77 + format: 'prettier', 78 + path: 'src/client', 79 + }, 80 + } 81 + ``` 82 + 83 + ### Moved `lint` 84 + 85 + This config option has been moved. You can now configure linter using the `output.lint` option. 86 + 87 + ```js{4} 88 + export default { 89 + input: 'path/to/openapi.json', 90 + output: { 91 + lint: 'eslint', 92 + path: 'src/client', 93 + }, 94 + } 95 + ``` 96 + 53 97 ## v0.43.0 54 98 55 99 ### Removed `enums.gen.ts` ··· 360 404 361 405 ## OpenAPI TypeScript Codegen 362 406 363 - `openapi-ts` was originally forked from Ferdi Koomen's [openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen). Therefore, we want you to be able to migrate your projects. Migration should be relatively straightforward if you follow the release notes on this page. Start here and scroll up to the release you're migrating to. 407 + `openapi-ts` was originally forked from Ferdi Koomen's [openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen). Therefore, we want you to be able to migrate your projects. Migration should be relatively straightforward if you follow the release notes on this page. Start on [v0.27.24](#v0-27-24) and scroll to the release you're migrating to.
+2 -2
docs/package.json
··· 1 1 { 2 2 "name": "@hey-api/docs", 3 - "version": "0.5.3", 3 + "version": "0.5.5", 4 4 "description": "Documentation for OpenaAPI TypeScript.", 5 5 "private": true, 6 6 "type": "module", ··· 10 10 "preview": "vitepress preview" 11 11 }, 12 12 "dependencies": { 13 - "@stackblitz/sdk": "1.9.0" 13 + "@stackblitz/sdk": "1.10.0" 14 14 }, 15 15 "devDependencies": { 16 16 "vitepress": "1.1.4"
+2 -2
examples/openapi-ts-axios/package.json
··· 19 19 }, 20 20 "devDependencies": { 21 21 "@hey-api/openapi-ts": "workspace:*", 22 - "@types/react": "18.3.1", 22 + "@types/react": "18.3.2", 23 23 "@types/react-dom": "18.3.0", 24 24 "@typescript-eslint/eslint-plugin": "7.8.0", 25 25 "@typescript-eslint/parser": "7.8.0", 26 26 "@vitejs/plugin-react": "4.2.1", 27 27 "eslint": "9.2.0", 28 28 "eslint-plugin-react-hooks": "4.6.2", 29 - "eslint-plugin-react-refresh": "0.4.6", 29 + "eslint-plugin-react-refresh": "0.4.7", 30 30 "prettier": "3.2.5", 31 31 "typescript": "5.4.5", 32 32 "vite": "5.2.11"
+6 -3
examples/openapi-ts-fetch/openapi-ts.config.ts
··· 2 2 3 3 export default defineConfig({ 4 4 base: 'https://petstore3.swagger.io/api/v3', 5 - format: 'prettier', 5 + client: '@hey-api/client-fetch', 6 6 input: 7 7 // 'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml', 8 8 'https://raw.githubusercontent.com/Redocly/museum-openapi-example/main/openapi.yaml', 9 - lint: 'eslint', 10 - output: './src/client', 9 + output: { 10 + format: 'prettier', 11 + lint: 'eslint', 12 + path: './src/client', 13 + }, 11 14 });
+2 -2
examples/openapi-ts-fetch/package.json
··· 18 18 }, 19 19 "devDependencies": { 20 20 "@hey-api/openapi-ts": "workspace:*", 21 - "@types/react": "18.3.1", 21 + "@types/react": "18.3.2", 22 22 "@types/react-dom": "18.3.0", 23 23 "@typescript-eslint/eslint-plugin": "7.8.0", 24 24 "@typescript-eslint/parser": "7.8.0", 25 25 "@vitejs/plugin-react": "4.2.1", 26 26 "eslint": "9.2.0", 27 27 "eslint-plugin-react-hooks": "4.6.2", 28 - "eslint-plugin-react-refresh": "0.4.6", 28 + "eslint-plugin-react-refresh": "0.4.7", 29 29 "prettier": "3.2.5", 30 30 "typescript": "5.4.5", 31 31 "vite": "5.2.11"
+5 -5
package.json
··· 20 20 "docs": "pnpm --filter @hey-api/docs --", 21 21 "example": "sh ./scripts/example.sh", 22 22 "format": "prettier --write .", 23 - "lint:fix": "prettier --check . && eslint . --fix", 23 + "lint:fix": "prettier --check --write . && eslint . --fix", 24 24 "lint": "prettier --check . && eslint .", 25 25 "openapi-ts": "pnpm --filter @hey-api/openapi-ts --", 26 26 "prepare": "husky", ··· 39 39 "@rollup/plugin-terser": "0.4.4", 40 40 "@rollup/plugin-typescript": "11.1.6", 41 41 "@svitejs/changesets-changelog-github-compact": "1.1.0", 42 - "@types/node": "20.12.8", 42 + "@types/node": "20.12.11", 43 43 "@vitest/coverage-v8": "1.6.0", 44 44 "eslint": "9.2.0", 45 45 "eslint-config-prettier": "9.1.0", 46 46 "eslint-plugin-simple-import-sort": "12.1.0", 47 47 "eslint-plugin-sort-keys-fix": "1.1.2", 48 - "globals": "15.1.0", 48 + "globals": "15.2.0", 49 49 "husky": "9.0.11", 50 50 "lint-staged": "15.2.2", 51 51 "prettier": "3.2.5", 52 - "rimraf": "5.0.5", 52 + "rimraf": "5.0.7", 53 53 "rollup": "4.17.2", 54 54 "rollup-plugin-dts": "6.1.0", 55 55 "typescript": "5.4.5", 56 56 "typescript-eslint": "7.8.0", 57 57 "vitest": "1.6.0" 58 58 }, 59 - "packageManager": "pnpm@8.15.7+sha256.50783dd0fa303852de2dd1557cd4b9f07cb5b018154a6e76d0f40635d6cee019" 59 + "packageManager": "pnpm@8.15.7" 60 60 }
+28
packages/openapi-ts/CHANGELOG.md
··· 1 1 # @hey-api/openapi-ts 2 2 3 + ## 0.45.0 4 + 5 + ### Minor Changes 6 + 7 + - feat: remove client inference ([#569](https://github.com/hey-api/openapi-ts/pull/569)) 8 + 9 + ### Patch Changes 10 + 11 + - fix: deduplicate inlined enums ([#573](https://github.com/hey-api/openapi-ts/pull/573)) 12 + 13 + - fix: generate correct optional key in types when using positional arguments (useOptions: false) ([#572](https://github.com/hey-api/openapi-ts/pull/572)) 14 + 15 + ## 0.44.0 16 + 17 + ### Minor Changes 18 + 19 + - feat: move format and lint config options to output object ([#546](https://github.com/hey-api/openapi-ts/pull/546)) 20 + 21 + ### Patch Changes 22 + 23 + - fix: comment position in JavaScript enums ([#544](https://github.com/hey-api/openapi-ts/pull/544)) 24 + 25 + - fix: export inlined enums from components ([#563](https://github.com/hey-api/openapi-ts/pull/563)) 26 + 27 + - fix: remove unused enums option from CLI ([#565](https://github.com/hey-api/openapi-ts/pull/565)) 28 + 29 + - fix: Support typescript in peerDependencies ([#551](https://github.com/hey-api/openapi-ts/pull/551)) 30 + 3 31 ## 0.43.2 4 32 5 33 ### Patch Changes
-2
packages/openapi-ts/README.md
··· 13 13 - works with CLI, Node.js, or npx 14 14 - supports OpenAPI 2.0, 3.0, and 3.1 specifications 15 15 - supports both JSON and YAML input files 16 - - supports external references using [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser/) 17 16 - generates TypeScript interfaces, REST clients, and JSON Schemas 18 17 - Fetch API, Axios, Angular, Node.js, and XHR clients available 19 - - abortable requests through cancellable promise pattern 20 18 21 19 ## Documentation 22 20
+7 -12
packages/openapi-ts/bin/index.cjs
··· 13 13 .usage('[options]') 14 14 .version(pkg.version) 15 15 .option( 16 - '-i, --input <value>', 17 - 'OpenAPI specification (path, url, or string content)', 16 + '--base [value]', 17 + 'Manually set base in OpenAPI config instead of inferring from server value', 18 18 ) 19 - .option('-o, --output <value>', 'Output directory') 20 19 .option( 21 20 '-c, --client <value>', 22 21 'HTTP client to generate [angular, axios, fetch, node, xhr]', 23 22 ) 24 23 .option('-d, --debug', 'Run in debug mode?') 24 + .option('--dry-run [value]', 'Skip writing files to disk?') 25 + .option('--exportCore [value]', 'Write core files to disk') 25 26 .option( 26 - '--base [value]', 27 - 'Manually set base in OpenAPI config instead of inferring from server value', 27 + '-i, --input <value>', 28 + 'OpenAPI specification (path, url, or string content)', 28 29 ) 29 - .option('--dry-run [value]', 'Skip writing files to disk?') 30 - .option('--enums <value>', 'Export enum definitions (javascript, typescript)') 31 - .option('--exportCore [value]', 'Write core files to disk') 32 - .option('--format [value]', 'Process output folder with formatter?') 33 - .option('--lint [value]', 'Process output folder with linter?') 34 30 .option('--name <value>', 'Custom client class name') 31 + .option('-o, --output <value>', 'Output directory') 35 32 .option('--request <value>', 'Path to custom request file') 36 33 .option('--schemas [value]', 'Write schemas to disk') 37 34 .option('--services [value]', 'Write services to disk') ··· 71 68 userConfig = processParams(params, [ 72 69 'dryRun', 73 70 'exportCore', 74 - 'format', 75 - 'lint', 76 71 'schemas', 77 72 'services', 78 73 'types',
+14 -14
packages/openapi-ts/package.json
··· 1 1 { 2 2 "name": "@hey-api/openapi-ts", 3 - "version": "0.43.2", 3 + "version": "0.45.0", 4 4 "type": "module", 5 5 "description": "Turn your OpenAPI specification into a beautiful TypeScript client", 6 6 "homepage": "https://heyapi.vercel.app/", ··· 68 68 "typescript": "^5.x" 69 69 }, 70 70 "devDependencies": { 71 - "@angular-devkit/build-angular": "17.3.6", 72 - "@angular/animations": "17.3.7", 73 - "@angular/cli": "17.3.6", 74 - "@angular/common": "17.3.7", 75 - "@angular/compiler": "17.3.7", 76 - "@angular/compiler-cli": "17.3.7", 77 - "@angular/core": "17.3.7", 78 - "@angular/forms": "17.3.7", 79 - "@angular/platform-browser": "17.3.7", 80 - "@angular/platform-browser-dynamic": "17.3.7", 81 - "@angular/router": "17.3.7", 71 + "@angular-devkit/build-angular": "17.3.7", 72 + "@angular/animations": "17.3.8", 73 + "@angular/cli": "17.3.7", 74 + "@angular/common": "17.3.8", 75 + "@angular/compiler": "17.3.8", 76 + "@angular/compiler-cli": "17.3.8", 77 + "@angular/core": "17.3.8", 78 + "@angular/forms": "17.3.8", 79 + "@angular/platform-browser": "17.3.8", 80 + "@angular/platform-browser-dynamic": "17.3.8", 81 + "@angular/router": "17.3.8", 82 82 "@rollup/plugin-json": "6.1.0", 83 83 "@rollup/plugin-node-resolve": "15.2.3", 84 84 "@types/cross-spawn": "6.0.6", ··· 87 87 "cross-spawn": "7.0.3", 88 88 "eslint": "9.2.0", 89 89 "express": "4.19.2", 90 - "glob": "10.3.12", 90 + "glob": "10.3.15", 91 91 "node-fetch": "3.3.2", 92 92 "prettier": "3.2.5", 93 - "puppeteer": "22.7.1", 93 + "puppeteer": "22.8.0", 94 94 "rxjs": "7.8.1", 95 95 "ts-node": "10.9.2", 96 96 "tslib": "2.6.2",
+138 -196
packages/openapi-ts/src/index.ts
··· 1 - import { existsSync, readFileSync } from 'node:fs'; 2 1 import path from 'node:path'; 3 2 4 3 import { loadConfig } from 'c12'; ··· 6 5 7 6 import { parse } from './openApi'; 8 7 import type { Client } from './types/client'; 9 - import type { Config, UserConfig } from './types/config'; 8 + import type { ClientConfig, Config, UserConfig } from './types/config'; 10 9 import { getConfig, setConfig } from './utils/config'; 11 10 import { getOpenApiSpec } from './utils/getOpenApiSpec'; 12 11 import { registerHandlebarTemplates } from './utils/handlebars'; 13 12 import { postProcessClient } from './utils/postprocess'; 14 13 import { writeClient } from './utils/write/client'; 15 14 16 - type Dependencies = Record<string, unknown>; 17 - type PackageDependencies = { 18 - dependencies?: Dependencies; 19 - devDependencies?: Dependencies; 20 - }; 21 - 22 - // Dependencies used in each client. User must have installed these to use the generated client 23 - const clientDependencies: Record<Config['client'], string[]> = { 24 - '@hey-api/client-axios': ['axios'], 25 - '@hey-api/client-fetch': [], 26 - angular: ['@angular/common', '@angular/core', 'rxjs'], 27 - axios: ['axios'], 28 - fetch: [], 29 - node: ['node-fetch'], 30 - xhr: [], 31 - }; 32 - 33 15 type OutputProcesser = { 34 - args: (output: string) => string[]; 16 + args: (path: string) => ReadonlyArray<string>; 35 17 command: string; 36 - condition: (dependencies: Dependencies) => boolean; 37 18 name: string; 38 19 }; 39 20 40 - // Map of supported formatters 41 - const formatters: Record<Extract<Config['format'], string>, OutputProcesser> = { 21 + /** 22 + * Map of supported formatters 23 + */ 24 + const formatters: Record< 25 + Extract<Config['output']['format'], string>, 26 + OutputProcesser 27 + > = { 42 28 biome: { 43 - args: (output) => ['format', '--write', output], 29 + args: (path) => ['format', '--write', path], 44 30 command: 'biome', 45 - condition: (dependencies) => Boolean(dependencies['@biomejs/biome']), 46 31 name: 'Biome (Format)', 47 32 }, 48 33 prettier: { 49 - args: (output) => [ 34 + args: (path) => [ 50 35 '--ignore-unknown', 51 - output, 36 + path, 52 37 '--write', 53 38 '--ignore-path', 54 39 './.prettierignore', 55 40 ], 56 41 command: 'prettier', 57 - condition: (dependencies) => Boolean(dependencies.prettier), 58 42 name: 'Prettier', 59 43 }, 60 44 }; 61 45 62 - // Map of supported linters 63 - const linters: Record<Extract<Config['lint'], string>, OutputProcesser> = { 46 + /** 47 + * Map of supported linters 48 + */ 49 + const linters: Record< 50 + Extract<Config['output']['lint'], string>, 51 + OutputProcesser 52 + > = { 64 53 biome: { 65 - args: (output) => ['lint', '--apply', output], 54 + args: (path) => ['lint', '--apply', path], 66 55 command: 'biome', 67 - condition: (dependencies) => Boolean(dependencies['@biomejs/biome']), 68 56 name: 'Biome (Lint)', 69 57 }, 70 58 eslint: { 71 - args: (output) => [output, '--fix'], 59 + args: (path) => [path, '--fix'], 72 60 command: 'eslint', 73 - condition: (dependencies) => Boolean(dependencies.eslint), 74 61 name: 'ESLint', 75 62 }, 76 63 }; 77 64 78 - const processOutput = (dependencies: Dependencies) => { 65 + const processOutput = () => { 79 66 const config = getConfig(); 80 - if (config.format) { 81 - const formatter = formatters[config.format]; 82 - if (formatter.condition(dependencies)) { 83 - console.log(`✨ Running ${formatter.name}`); 84 - sync(formatter.command, formatter.args(config.output)); 85 - } 67 + 68 + if (config.output.format) { 69 + const module = formatters[config.output.format]; 70 + console.log(`✨ Running ${module.name}`); 71 + sync(module.command, module.args(config.output.path)); 86 72 } 87 - if (config.lint) { 88 - const linter = linters[config.lint]; 89 - if (linter.condition(dependencies)) { 90 - console.log(`✨ Running ${linter.name}`); 91 - sync(linter.command, linter.args(config.output)); 92 - } 93 - } 94 - }; 95 73 96 - const inferClient = (dependencies: Dependencies): Config['client'] => { 97 - if (dependencies['@hey-api/client-axios']) { 98 - return '@hey-api/client-axios'; 74 + if (config.output.lint) { 75 + const module = linters[config.output.lint]; 76 + console.log(`✨ Running ${module.name}`); 77 + sync(module.command, module.args(config.output.path)); 99 78 } 100 - if (dependencies['@hey-api/client-fetch']) { 101 - return '@hey-api/client-fetch'; 102 - } 103 - if (dependencies.axios) { 104 - return 'axios'; 105 - } 106 - if (dependencies['node-fetch']) { 107 - return 'node'; 108 - } 109 - if (Object.keys(dependencies).some((d) => d.startsWith('@angular'))) { 110 - return 'angular'; 111 - } 112 - return 'fetch'; 113 79 }; 114 80 115 81 const logClientMessage = () => { ··· 117 83 switch (client) { 118 84 case 'angular': 119 85 return console.log('✨ Creating Angular client'); 86 + case '@hey-api/client-axios': 120 87 case 'axios': 121 88 return console.log('✨ Creating Axios client'); 89 + case '@hey-api/client-fetch': 122 90 case 'fetch': 123 91 return console.log('✨ Creating Fetch client'); 124 92 case 'node': ··· 128 96 } 129 97 }; 130 98 131 - const logMissingDependenciesWarning = (dependencies: Dependencies) => { 132 - const { client } = getConfig(); 133 - const missing = clientDependencies[client].filter( 134 - (d) => dependencies[d] === undefined, 135 - ); 136 - if (missing.length > 0) { 137 - console.log( 138 - '⚠️ Dependencies used in generated client are missing: ' + 139 - missing.join(' '), 140 - ); 99 + const getOutput = (userConfig: ClientConfig): Config['output'] => { 100 + let output: Config['output'] = { 101 + format: false, 102 + lint: false, 103 + path: '', 104 + }; 105 + if (typeof userConfig.output === 'string') { 106 + output.path = userConfig.output; 107 + } else { 108 + output = { 109 + ...output, 110 + ...userConfig.output, 111 + }; 141 112 } 113 + return output; 142 114 }; 143 115 144 - const getSchemas = (userConfig: UserConfig): Config['schemas'] => { 116 + const getSchemas = (userConfig: ClientConfig): Config['schemas'] => { 145 117 let schemas: Config['schemas'] = { 146 118 export: true, 147 119 type: 'json', ··· 157 129 return schemas; 158 130 }; 159 131 160 - const getServices = (userConfig: UserConfig): Config['services'] => { 132 + const getServices = (userConfig: ClientConfig): Config['services'] => { 161 133 let services: Config['services'] = { 162 134 export: true, 163 135 name: '{{name}}Service', ··· 177 149 return services; 178 150 }; 179 151 180 - const getTypes = (userConfig: UserConfig): Config['types'] => { 152 + const getTypes = (userConfig: ClientConfig): Config['types'] => { 181 153 let types: Config['types'] = { 182 154 dates: false, 183 155 enums: false, ··· 197 169 return types; 198 170 }; 199 171 200 - const getInstalledDependencies = (): Dependencies => { 201 - const toReducedDependencies = (p: PackageDependencies): Dependencies => 202 - [p.dependencies ?? {}, p.devDependencies ?? {}].reduce( 203 - (deps, devDeps) => ({ 204 - ...deps, 205 - ...devDeps, 206 - }), 207 - {}, 208 - ); 209 - 210 - let dependencies: Dependencies = {}; 211 - 212 - // Attempt to get all globally installed pacakges. 213 - const result = sync('npm', ['list', '-g', '--json', '--depth=0']); 214 - if (!result.error) { 215 - const globally: PackageDependencies = JSON.parse(result.stdout.toString()); 216 - dependencies = { 217 - ...dependencies, 218 - ...toReducedDependencies(globally), 219 - }; 220 - } 221 - 222 - // Attempt to read any dependencies installed in a local projects package.json. 223 - const pkgPath = path.resolve(process.cwd(), 'package.json'); 224 - if (existsSync(pkgPath)) { 225 - const locally: PackageDependencies = JSON.parse( 226 - readFileSync(pkgPath).toString(), 227 - ); 228 - dependencies = { 229 - ...dependencies, 230 - ...toReducedDependencies(locally), 231 - }; 232 - } 233 - 234 - return dependencies; 235 - }; 236 - 237 - const initConfig = async ( 238 - userConfig: UserConfig, 239 - dependencies: Dependencies, 240 - ) => { 241 - const { config: userConfigFromFile } = await loadConfig<UserConfig>({ 172 + const initConfigs = async (userConfig: UserConfig): Promise<Config[]> => { 173 + const { config: configFromFile } = await loadConfig<UserConfig>({ 242 174 jitiOptions: { 243 175 esmResolve: true, 244 176 }, 245 177 name: 'openapi-ts', 246 - overrides: userConfig, 247 178 }); 248 179 249 - if (userConfigFromFile) { 250 - userConfig = { ...userConfigFromFile, ...userConfig }; 251 - } 180 + const userConfigs: ClientConfig[] = Array.isArray(userConfig) 181 + ? userConfig 182 + : Array.isArray(configFromFile) 183 + ? configFromFile.map((config) => ({ 184 + ...config, 185 + ...userConfig, 186 + })) 187 + : [{ ...(configFromFile ?? {}), ...userConfig }]; 252 188 253 - const { 254 - base, 255 - debug = false, 256 - dryRun = false, 257 - exportCore = true, 258 - format = false, 259 - input, 260 - lint = false, 261 - name, 262 - request, 263 - useOptions = true, 264 - } = userConfig; 189 + return userConfigs.map((userConfig) => { 190 + const { 191 + base, 192 + client = 'fetch', 193 + debug = false, 194 + dryRun = false, 195 + exportCore = true, 196 + input, 197 + name, 198 + request, 199 + useOptions = true, 200 + } = userConfig; 265 201 266 - if (debug) { 267 - console.warn('userConfig:', userConfig); 268 - } 202 + if (debug) { 203 + console.warn('userConfig:', userConfig); 204 + } 269 205 270 - if (!input) { 271 - throw new Error( 272 - '🚫 input not provided - provide path to OpenAPI specification', 273 - ); 274 - } 206 + const output = getOutput(userConfig); 275 207 276 - if (!userConfig.output) { 277 - throw new Error( 278 - '🚫 output not provided - provide path where we should generate your client', 279 - ); 280 - } 208 + if (!input) { 209 + throw new Error( 210 + '🚫 input not provided - provide path to OpenAPI specification', 211 + ); 212 + } 281 213 282 - if (!useOptions) { 283 - console.warn( 284 - '⚠️ Deprecation warning: useOptions set to false. This setting will be removed in future versions. Please migrate useOptions to true https://heyapi.vercel.app/openapi-ts/migrating.html#v0-27-38', 285 - ); 286 - } 214 + if (!output.path) { 215 + throw new Error( 216 + '🚫 output not provided - provide path where we should generate your client', 217 + ); 218 + } 219 + 220 + if (!useOptions) { 221 + console.warn( 222 + '⚠️ Deprecation warning: useOptions set to false. This setting will be removed in future versions. Please migrate useOptions to true https://heyapi.vercel.app/openapi-ts/migrating.html#v0-27-38', 223 + ); 224 + } 287 225 288 - const client = userConfig.client || inferClient(dependencies); 289 - const output = path.resolve(process.cwd(), userConfig.output); 290 - const schemas = getSchemas(userConfig); 291 - const services = getServices(userConfig); 292 - const types = getTypes(userConfig); 226 + const schemas = getSchemas(userConfig); 227 + const services = getServices(userConfig); 228 + const types = getTypes(userConfig); 229 + 230 + output.path = path.resolve(process.cwd(), output.path); 293 231 294 - return setConfig({ 295 - base, 296 - client, 297 - debug, 298 - dryRun, 299 - exportCore: client.startsWith('@hey-api') ? false : exportCore, 300 - format, 301 - input, 302 - lint, 303 - name, 304 - output, 305 - request, 306 - schemas, 307 - services, 308 - types, 309 - useOptions, 232 + return setConfig({ 233 + base, 234 + client, 235 + debug, 236 + dryRun, 237 + exportCore: client.startsWith('@hey-api') ? false : exportCore, 238 + input, 239 + name, 240 + output, 241 + request, 242 + schemas, 243 + services, 244 + types, 245 + useOptions, 246 + }); 310 247 }); 311 248 }; 312 249 ··· 316 253 * service layer, etc. 317 254 * @param userConfig {@link UserConfig} passed to the `createClient()` method 318 255 */ 319 - export async function createClient(userConfig: UserConfig): Promise<Client> { 320 - const dependencies = getInstalledDependencies(); 256 + export async function createClient(userConfig: UserConfig): Promise<Client[]> { 257 + const configs = await initConfigs(userConfig); 258 + 259 + const createClientPromise = (config: Config) => async () => { 260 + const openApi = 261 + typeof config.input === 'string' 262 + ? await getOpenApiSpec(config.input) 263 + : (config.input as unknown as Awaited< 264 + ReturnType<typeof getOpenApiSpec> 265 + >); 321 266 322 - if (!dependencies.typescript) { 323 - throw new Error('🚫 dependency missing - TypeScript must be installed'); 324 - } 267 + const client = postProcessClient(parse(openApi)); 268 + const templates = registerHandlebarTemplates(); 325 269 326 - const config = await initConfig(userConfig, dependencies); 270 + if (!config.dryRun) { 271 + logClientMessage(); 272 + await writeClient(openApi, client, templates); 273 + processOutput(); 274 + } 327 275 328 - const openApi = 329 - typeof config.input === 'string' 330 - ? await getOpenApiSpec(config.input) 331 - : (config.input as unknown as Awaited<ReturnType<typeof getOpenApiSpec>>); 276 + console.log('✨ Done! Your client is located in:', config.output.path); 332 277 333 - const client = postProcessClient(parse(openApi)); 334 - const templates = registerHandlebarTemplates(); 278 + return client; 279 + }; 335 280 336 - if (!config.dryRun) { 337 - logClientMessage(); 338 - logMissingDependenciesWarning(dependencies); 339 - await writeClient(openApi, client, templates); 340 - processOutput(dependencies); 281 + let clients: Client[] = []; 282 + const clientPromises = configs.map((config) => createClientPromise(config)); 283 + for (const clientPromise of clientPromises) { 284 + const client = await clientPromise(); 285 + clients = [...clients, client]; 341 286 } 342 - 343 - console.log('✨ Done! Your client is located in:', config.output); 344 - 345 - return client; 287 + return clients; 346 288 } 347 289 348 290 /**
+6 -6
packages/openapi-ts/src/openApi/common/parser/__tests__/operation.spec.ts
··· 13 13 debug: false, 14 14 dryRun: true, 15 15 exportCore: false, 16 - format: false, 17 16 input: '', 18 - lint: false, 19 - output: '', 17 + output: { 18 + path: '', 19 + }, 20 20 schemas: { 21 21 export: false, 22 22 }, ··· 36 36 debug: false, 37 37 dryRun: true, 38 38 exportCore: false, 39 - format: false, 40 39 input: '', 41 - lint: false, 42 - output: '', 40 + output: { 41 + path: '', 42 + }, 43 43 schemas: { 44 44 export: false, 45 45 },
+3 -3
packages/openapi-ts/src/openApi/common/parser/getDefault.ts
··· 30 30 return value; 31 31 } 32 32 return definition.default; 33 - case 'string': 34 - return definition.default; 35 33 case 'array': 36 34 case 'boolean': 37 35 case 'object': 36 + case 'string': 38 37 return definition.default; 38 + default: 39 + return undefined; 39 40 } 40 - return undefined; 41 41 };
+1 -4
packages/openapi-ts/src/openApi/common/parser/getRef.ts
··· 12 12 if (item.$ref) { 13 13 // Fetch the paths to the definitions, this converts: 14 14 // "#/components/schemas/Form" to ["components", "schemas", "Form"] 15 - const paths = item.$ref 16 - .replace(/^#/g, '') 17 - .split('/') 18 - .filter((item) => item); 15 + const paths = item.$ref.replace(/^#/g, '').split('/').filter(Boolean); 19 16 20 17 // Try to find the reference by walking down the path, 21 18 // if we cannot find it, then we throw an error.
+3 -3
packages/openapi-ts/src/openApi/v2/index.ts
··· 13 13 export const parse = (openApi: OpenApi): Client => { 14 14 const version = getServiceVersion(openApi.info.version); 15 15 const server = getServer(openApi); 16 - const models = getModels(openApi); 17 - const services = getServices(openApi); 16 + const { models, types } = getModels(openApi); 17 + const services = getServices({ openApi, types }); 18 18 19 19 return { 20 20 models, 21 21 server, 22 22 services, 23 - types: {}, 23 + types, 24 24 version, 25 25 }; 26 26 };
+13
packages/openapi-ts/src/openApi/v2/interfaces/Model.ts
··· 1 + import type { Client } from '../../../types/client'; 2 + import type { Model, ModelMeta } from '../../common/interfaces/client'; 3 + import type { OpenApi } from './OpenApi'; 4 + import type { OpenApiSchema } from './OpenApiSchema'; 5 + 6 + export type GetModelFn = ( 7 + args: Pick<Client, 'types'> & { 8 + definition: OpenApiSchema; 9 + isDefinition?: boolean; 10 + meta?: ModelMeta; 11 + openApi: OpenApi; 12 + }, 13 + ) => Model;
+21 -18
packages/openapi-ts/src/openApi/v2/parser/__tests__/getServices.spec.ts
··· 10 10 debug: false, 11 11 dryRun: true, 12 12 exportCore: true, 13 - format: false, 14 13 input: '', 15 - lint: false, 16 - output: '', 14 + output: { 15 + path: '', 16 + }, 17 17 schemas: {}, 18 18 services: { 19 19 operationId: false, ··· 23 23 }); 24 24 25 25 const services = getServices({ 26 - info: { 27 - title: 'x', 28 - version: '1', 29 - }, 30 - paths: { 31 - '/api/trips': { 32 - get: { 33 - responses: { 34 - 200: { 35 - description: 'x', 26 + openApi: { 27 + info: { 28 + title: 'x', 29 + version: '1', 30 + }, 31 + paths: { 32 + '/api/trips': { 33 + get: { 34 + responses: { 35 + 200: { 36 + description: 'x', 37 + }, 38 + default: { 39 + description: 'default', 40 + }, 36 41 }, 37 - default: { 38 - description: 'default', 39 - }, 42 + tags: [], 40 43 }, 41 - tags: [], 42 44 }, 43 45 }, 46 + swagger: '2.0', 44 47 }, 45 - swagger: '2.0', 48 + types: {}, 46 49 }); 47 50 48 51 expect(services).toHaveLength(1);
+21 -8
packages/openapi-ts/src/openApi/v2/parser/getModel.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { Model, ModelMeta } from '../../common/interfaces/client'; 2 3 import { getEnums } from '../../common/parser/getEnums'; 3 4 import { getPattern } from '../../common/parser/getPattern'; ··· 12 13 isDefinition = false, 13 14 meta, 14 15 openApi, 15 - }: { 16 + types, 17 + }: Pick<Client, 'types'> & { 16 18 definition: OpenApiSchema; 17 19 isDefinition?: boolean; 18 20 meta?: ModelMeta; ··· 83 85 model.imports.push(...arrayItems.imports); 84 86 return model; 85 87 } else { 86 - const arrayItems = getModel({ definition: definition.items, openApi }); 88 + const arrayItems = getModel({ 89 + definition: definition.items, 90 + openApi, 91 + types, 92 + }); 87 93 model.export = 'array'; 88 94 model.type = arrayItems.type; 89 95 model.base = arrayItems.base; ··· 112 118 const additionalProperties = getModel({ 113 119 definition: definition.additionalProperties, 114 120 openApi, 121 + types, 115 122 }); 116 123 model.export = 'dictionary'; 117 124 model.type = additionalProperties.type; ··· 124 131 } 125 132 126 133 if (definition.allOf?.length) { 127 - const composition = getModelComposition( 128 - openApi, 134 + const composition = getModelComposition({ 129 135 definition, 130 - definition.allOf, 131 - 'all-of', 136 + definitions: definition.allOf, 132 137 getModel, 133 - ); 138 + openApi, 139 + type: 'all-of', 140 + types, 141 + }); 134 142 model.export = composition.export; 135 143 model.imports.push(...composition.imports); 136 144 model.properties.push(...composition.properties); ··· 144 152 model.base = 'unknown'; 145 153 146 154 if (definition.properties) { 147 - const modelProperties = getModelProperties(openApi, definition, getModel); 155 + const modelProperties = getModelProperties({ 156 + definition, 157 + getModel, 158 + openApi, 159 + types, 160 + }); 148 161 modelProperties.forEach((modelProperty) => { 149 162 model.imports.push(...modelProperty.imports); 150 163 model.enums = [...model.enums, ...modelProperty.enums];
+29 -17
packages/openapi-ts/src/openApi/v2/parser/getModelComposition.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { Model, ModelComposition } from '../../common/interfaces/client'; 3 + import type { GetModelFn } from '../interfaces/Model'; 2 4 import type { OpenApi } from '../interfaces/OpenApi'; 3 5 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 4 - import type { getModel } from './getModel'; 5 6 import { getModelProperties } from './getModelProperties'; 6 7 import { getRequiredPropertiesFromComposition } from './getRequiredPropertiesFromComposition'; 7 8 8 - // Fix for circular dependency 9 - export type GetModelFn = typeof getModel; 10 - 11 - export const getModelComposition = ( 12 - openApi: OpenApi, 13 - definition: OpenApiSchema, 14 - definitions: OpenApiSchema[], 15 - type: 'one-of' | 'any-of' | 'all-of', 16 - getModel: GetModelFn, 17 - ): ModelComposition => { 9 + export const getModelComposition = ({ 10 + definition, 11 + definitions, 12 + getModel, 13 + openApi, 14 + type, 15 + types, 16 + }: { 17 + openApi: OpenApi; 18 + definition: OpenApiSchema; 19 + definitions: OpenApiSchema[]; 20 + type: 'one-of' | 'any-of' | 'all-of'; 21 + getModel: GetModelFn; 22 + types: Client['types']; 23 + }): ModelComposition => { 18 24 const composition: ModelComposition = { 19 25 $refs: [], 20 26 enums: [], ··· 26 32 const properties: Model[] = []; 27 33 28 34 definitions 29 - .map((definition) => getModel({ definition, openApi })) 35 + .map((definition) => getModel({ definition, openApi, types })) 30 36 .filter((model) => { 31 37 const hasProperties = model.properties.length; 32 38 const hasEnums = model.enums.length; ··· 41 47 }); 42 48 43 49 if (definition.required) { 44 - const requiredProperties = getRequiredPropertiesFromComposition( 45 - openApi, 46 - definition.required, 50 + const requiredProperties = getRequiredPropertiesFromComposition({ 47 51 definitions, 48 52 getModel, 49 - ); 53 + openApi, 54 + required: definition.required, 55 + types, 56 + }); 50 57 requiredProperties.forEach((requiredProperty) => { 51 58 composition.imports.push(...requiredProperty.imports); 52 59 composition.enums.push(...requiredProperty.enums); ··· 55 62 } 56 63 57 64 if (definition.properties) { 58 - const modelProperties = getModelProperties(openApi, definition, getModel); 65 + const modelProperties = getModelProperties({ 66 + definition, 67 + getModel, 68 + openApi, 69 + types, 70 + }); 59 71 modelProperties.forEach((modelProperty) => { 60 72 composition.imports.push(...modelProperty.imports); 61 73 composition.enums.push(...modelProperty.enums);
+17 -11
packages/openapi-ts/src/openApi/v2/parser/getModelProperties.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import { escapeName } from '../../../utils/escape'; 2 3 import type { Model } from '../../common/interfaces/client'; 3 4 import { getPattern } from '../../common/parser/getPattern'; 4 5 import { getType } from '../../common/parser/type'; 6 + import type { GetModelFn } from '../interfaces/Model'; 5 7 import type { OpenApi } from '../interfaces/OpenApi'; 6 8 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 7 - import type { getModel } from './getModel'; 8 9 9 - // Fix for circular dependency 10 - export type GetModelFn = typeof getModel; 11 - 12 - export const getModelProperties = ( 13 - openApi: OpenApi, 14 - definition: OpenApiSchema, 15 - getModel: GetModelFn, 16 - ): Model[] => { 10 + export const getModelProperties = ({ 11 + definition, 12 + getModel, 13 + openApi, 14 + types, 15 + }: { 16 + definition: OpenApiSchema; 17 + getModel: GetModelFn; 18 + openApi: OpenApi; 19 + types: Client['types']; 20 + }): Model[] => { 17 21 const models: Model[] = []; 18 22 19 23 Object.entries(definition.properties ?? {}).forEach( 20 24 ([propertyName, property]) => { 21 - const propertyRequired = !!definition.required?.includes(propertyName); 25 + const propertyRequired = Boolean( 26 + definition.required?.includes(propertyName), 27 + ); 22 28 if (property.$ref) { 23 29 const model = getType({ type: property.$ref }); 24 30 models.push({ ··· 54 60 uniqueItems: property.uniqueItems, 55 61 }); 56 62 } else { 57 - const model = getModel({ definition: property, openApi }); 63 + const model = getModel({ definition: property, openApi, types }); 58 64 models.push({ 59 65 $refs: [], 60 66 base: model.base,
+18 -8
packages/openapi-ts/src/openApi/v2/parser/getModels.ts
··· 1 - import type { Model } from '../../common/interfaces/client'; 1 + import type { Client } from '../../../types/client'; 2 2 import { reservedWords } from '../../common/parser/reservedWords'; 3 3 import { getType } from '../../common/parser/type'; 4 4 import type { OpenApi } from '../interfaces/OpenApi'; 5 5 import { getModel } from './getModel'; 6 6 7 - export const getModels = (openApi: OpenApi): Model[] => { 8 - let models: Model[] = []; 7 + export const getModels = ( 8 + openApi: OpenApi, 9 + ): Pick<Client, 'models' | 'types'> => { 10 + const types: Client['types'] = {}; 11 + let models: Client['models'] = []; 9 12 10 13 Object.entries(openApi.definitions ?? {}).forEach( 11 14 ([definitionName, definition]) => { 12 15 const definitionType = getType({ type: definitionName }); 16 + const name = definitionType.base.replace(reservedWords, '_$1'); 17 + const meta = { 18 + $ref: `#/definitions/${definitionName}`, 19 + name, 20 + }; 21 + types[name] = meta; 13 22 const model = getModel({ 14 23 definition, 15 24 isDefinition: true, 16 - meta: { 17 - $ref: `#/definitions/${definitionName}`, 18 - name: definitionType.base.replace(reservedWords, '_$1'), 19 - }, 25 + meta, 20 26 openApi, 27 + types, 21 28 }); 22 29 models = [...models, model]; 23 30 }, 24 31 ); 25 32 26 - return models; 33 + return { 34 + models, 35 + types, 36 + }; 27 37 };
+28 -10
packages/openapi-ts/src/openApi/v2/parser/getOperation.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import { getOperationResults } from '../../../utils/operation'; 2 3 import type { 3 4 Operation, ··· 15 16 import { getOperationParameters } from './getOperationParameters'; 16 17 import { getOperationResponses } from './getOperationResponses'; 17 18 18 - export const getOperation = ( 19 - openApi: OpenApi, 20 - url: string, 21 - method: Lowercase<Operation['method']>, 22 - tag: string, 23 - op: OpenApiOperation, 24 - pathParams: OperationParameters, 25 - ): Operation => { 19 + export const getOperation = ({ 20 + method, 21 + op, 22 + openApi, 23 + pathParams, 24 + tag, 25 + types, 26 + url, 27 + }: { 28 + openApi: OpenApi; 29 + url: string; 30 + method: Lowercase<Operation['method']>; 31 + tag: string; 32 + op: OpenApiOperation; 33 + pathParams: OperationParameters; 34 + types: Client['types']; 35 + }): Operation => { 26 36 const serviceName = getServiceName(tag); 27 37 const name = getOperationName(url, method, op.operationId); 28 38 ··· 51 61 52 62 // Parse the operation parameters (path, query, body, etc). 53 63 if (op.parameters) { 54 - const parameters = getOperationParameters(openApi, op.parameters); 64 + const parameters = getOperationParameters({ 65 + openApi, 66 + parameters: op.parameters, 67 + types, 68 + }); 55 69 operation.imports.push(...parameters.imports); 56 70 operation.parameters.push(...parameters.parameters); 57 71 operation.parametersPath.push(...parameters.parametersPath); ··· 64 78 65 79 // Parse the operation responses. 66 80 if (op.responses) { 67 - const operationResponses = getOperationResponses(openApi, op.responses); 81 + const operationResponses = getOperationResponses({ 82 + openApi, 83 + responses: op.responses, 84 + types, 85 + }); 68 86 const operationResults = getOperationResults(operationResponses); 69 87 operation.errors = getOperationErrors(operationResponses); 70 88 operation.responseHeader = getOperationResponseHeader(operationResults);
+11 -5
packages/openapi-ts/src/openApi/v2/parser/getOperationParameter.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationParameter } from '../../common/interfaces/client'; 2 3 import { getDefault } from '../../common/parser/getDefault'; 3 4 import { getEnums } from '../../common/parser/getEnums'; ··· 10 11 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 11 12 import { getModel } from './getModel'; 12 13 13 - export const getOperationParameter = ( 14 - openApi: OpenApi, 15 - parameter: OpenApiParameter, 16 - ): OperationParameter => { 14 + export const getOperationParameter = ({ 15 + openApi, 16 + parameter, 17 + types, 18 + }: { 19 + openApi: OpenApi; 20 + parameter: OpenApiParameter; 21 + types: Client['types']; 22 + }): OperationParameter => { 17 23 const operationParameter: OperationParameter = { 18 24 $refs: [], 19 25 base: 'unknown', ··· 114 120 operationParameter.default = getDefault(parameter, operationParameter); 115 121 return operationParameter; 116 122 } else { 117 - const model = getModel({ definition: schema, openApi }); 123 + const model = getModel({ definition: schema, openApi, types }); 118 124 operationParameter.export = model.export; 119 125 operationParameter.type = model.type; 120 126 operationParameter.base = model.base;
+15 -5
packages/openapi-ts/src/openApi/v2/parser/getOperationParameters.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationParameters } from '../../common/interfaces/client'; 2 3 import { getRef } from '../../common/parser/getRef'; 3 4 import type { OpenApi } from '../interfaces/OpenApi'; 4 5 import type { OpenApiParameter } from '../interfaces/OpenApiParameter'; 5 6 import { getOperationParameter } from './getOperationParameter'; 6 7 7 - export const getOperationParameters = ( 8 - openApi: OpenApi, 9 - parameters: OpenApiParameter[], 10 - ): OperationParameters => { 8 + export const getOperationParameters = ({ 9 + openApi, 10 + parameters, 11 + types, 12 + }: { 13 + openApi: OpenApi; 14 + parameters: OpenApiParameter[]; 15 + types: Client['types']; 16 + }): OperationParameters => { 11 17 const operationParameters: OperationParameters = { 12 18 $refs: [], 13 19 imports: [], ··· 26 32 openApi, 27 33 parameterOrReference, 28 34 ); 29 - const parameter = getOperationParameter(openApi, parameterDef); 35 + const parameter = getOperationParameter({ 36 + openApi, 37 + parameter: parameterDef, 38 + types, 39 + }); 30 40 31 41 // We ignore the "api-version" param, since we do not want to add this 32 42 // as the first / default parameter for each of the service calls.
+13 -6
packages/openapi-ts/src/openApi/v2/parser/getOperationResponse.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationResponse } from '../../common/interfaces/client'; 2 3 import { getPattern } from '../../common/parser/getPattern'; 3 4 import { getRef } from '../../common/parser/getRef'; ··· 7 8 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 8 9 import { getModel } from './getModel'; 9 10 10 - export const getOperationResponse = ( 11 - openApi: OpenApi, 12 - response: OpenApiResponse, 13 - code: number | 'default', 14 - ): OperationResponse => { 11 + export const getOperationResponse = ({ 12 + code, 13 + openApi, 14 + response, 15 + types, 16 + }: { 17 + openApi: OpenApi; 18 + response: OpenApiResponse; 19 + code: number | 'default'; 20 + types: Client['types']; 21 + }): OperationResponse => { 15 22 const operationResponse: OperationResponse = { 16 23 $refs: [], 17 24 base: code !== 204 ? 'unknown' : 'void', ··· 51 58 operationResponse.imports.push(...model.imports); 52 59 return operationResponse; 53 60 } else { 54 - const model = getModel({ definition: schema, openApi }); 61 + const model = getModel({ definition: schema, openApi, types }); 55 62 operationResponse.export = model.export; 56 63 operationResponse.type = model.type; 57 64 operationResponse.base = model.base;
+14 -7
packages/openapi-ts/src/openApi/v2/parser/getOperationResponses.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationResponse } from '../../common/interfaces/client'; 2 3 import { getRef } from '../../common/parser/getRef'; 3 4 import { getOperationResponseCode } from '../../common/parser/operation'; ··· 6 7 import type { OpenApiResponses } from '../interfaces/OpenApiResponses'; 7 8 import { getOperationResponse } from './getOperationResponse'; 8 9 9 - export const getOperationResponses = ( 10 - openApi: OpenApi, 11 - responses: OpenApiResponses, 12 - ): OperationResponse[] => { 10 + export const getOperationResponses = ({ 11 + openApi, 12 + responses, 13 + types, 14 + }: { 15 + openApi: OpenApi; 16 + responses: OpenApiResponses; 17 + types: Client['types']; 18 + }): OperationResponse[] => { 13 19 const operationResponses: OperationResponse[] = []; 14 20 15 21 // Iterate over each response code and get the ··· 19 25 const responseCode = getOperationResponseCode(code); 20 26 21 27 if (responseCode) { 22 - const operationResponse = getOperationResponse( 28 + const operationResponse = getOperationResponse({ 29 + code: responseCode, 23 30 openApi, 24 31 response, 25 - responseCode, 26 - ); 32 + types, 33 + }); 27 34 operationResponses.push(operationResponse); 28 35 } 29 36 });
+20 -12
packages/openapi-ts/src/openApi/v2/parser/getRequiredPropertiesFromComposition.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { Model } from '../../common/interfaces/client'; 2 3 import { getRef } from '../../common/parser/getRef'; 4 + import type { GetModelFn } from '../interfaces/Model'; 3 5 import type { OpenApi } from '../interfaces/OpenApi'; 4 6 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 5 - import type { getModel } from './getModel'; 6 7 7 - // Fix for circular dependency 8 - export type GetModelFn = typeof getModel; 9 - 10 - export const getRequiredPropertiesFromComposition = ( 11 - openApi: OpenApi, 12 - required: string[], 13 - definitions: OpenApiSchema[], 14 - getModel: GetModelFn, 15 - ): Model[] => 8 + export const getRequiredPropertiesFromComposition = ({ 9 + definitions, 10 + getModel, 11 + openApi, 12 + required, 13 + types, 14 + }: { 15 + openApi: OpenApi; 16 + required: string[]; 17 + definitions: OpenApiSchema[]; 18 + getModel: GetModelFn; 19 + types: Client['types']; 20 + }): Model[] => 16 21 definitions 17 22 .reduce((properties, definition) => { 18 23 if (definition.$ref) { 19 24 const schema = getRef<OpenApiSchema>(openApi, definition); 20 25 return [ 21 26 ...properties, 22 - ...getModel({ definition: schema, openApi }).properties, 27 + ...getModel({ definition: schema, openApi, types }).properties, 23 28 ]; 24 29 } 25 - return [...properties, ...getModel({ definition, openApi }).properties]; 30 + return [ 31 + ...properties, 32 + ...getModel({ definition, openApi, types }).properties, 33 + ]; 26 34 }, [] as Model[]) 27 35 .filter( 28 36 (property) => !property.isRequired && required.includes(property.name),
+19 -7
packages/openapi-ts/src/openApi/v2/parser/getServices.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import { unique } from '../../../utils/unique'; 2 3 import type { Service } from '../../common/interfaces/client'; 3 4 import type { OpenApi } from '../interfaces/OpenApi'; ··· 7 8 /** 8 9 * Get the OpenAPI services 9 10 */ 10 - export const getServices = (openApi: OpenApi): Service[] => { 11 + export const getServices = ({ 12 + openApi, 13 + types, 14 + }: { 15 + openApi: OpenApi; 16 + types: Client['types']; 17 + }): Service[] => { 11 18 const services = new Map<string, Service>(); 12 19 13 20 Object.entries(openApi.paths).forEach(([url, path]) => { 14 21 // Grab path and parse any global path parameters 15 - const pathParams = getOperationParameters(openApi, path.parameters || []); 22 + const pathParams = getOperationParameters({ 23 + openApi, 24 + parameters: path.parameters || [], 25 + types, 26 + }); 16 27 17 28 Object.keys(path).forEach((method) => { 18 29 // Parse all the methods for this path ··· 28 39 const op = path[method]!; 29 40 const tags = op.tags?.length ? op.tags.filter(unique) : ['Default']; 30 41 tags.forEach((tag) => { 31 - const operation = getOperation( 32 - openApi, 33 - url, 42 + const operation = getOperation({ 34 43 method, 35 - tag, 36 44 op, 45 + openApi, 37 46 pathParams, 38 - ); 47 + tag, 48 + types, 49 + url, 50 + }); 39 51 40 52 // If we have already declared a service, then we should fetch that and 41 53 // append the new method to it. Otherwise we should create a new service object.
+3 -3
packages/openapi-ts/src/openApi/v3/index.ts
··· 13 13 export const parse = (openApi: OpenApi): Client => { 14 14 const version = getServiceVersion(openApi.info.version); 15 15 const server = getServer(openApi); 16 - const models = getModels(openApi); 17 - const services = getServices(openApi); 16 + const { models, types } = getModels(openApi); 17 + const services = getServices({ openApi, types }); 18 18 19 19 return { 20 20 models, 21 21 server, 22 22 services, 23 - types: {}, 23 + types, 24 24 version, 25 25 }; 26 26 };
+18
packages/openapi-ts/src/openApi/v3/interfaces/Model.ts
··· 1 + import type { Client } from '../../../types/client'; 2 + import type { Model, ModelMeta } from '../../common/interfaces/client'; 3 + import type { OpenApi } from './OpenApi'; 4 + import type { OpenApiSchema } from './OpenApiSchema'; 5 + 6 + export type GetModelFn = ( 7 + args: Pick<Client, 'types'> & { 8 + definition: OpenApiSchema; 9 + /** 10 + * Pass through initial model values 11 + */ 12 + initialValues?: Partial<Model>; 13 + isDefinition?: boolean; 14 + meta?: ModelMeta; 15 + openApi: OpenApi; 16 + parentDefinition?: OpenApiSchema | null; 17 + }, 18 + ) => Model;
+2
packages/openapi-ts/src/openApi/v3/parser/__tests__/getModel.spec.ts
··· 99 99 name: definitionType.base.replace(reservedWords, '_$1'), 100 100 }, 101 101 openApi, 102 + types: {}, 102 103 }); 103 104 expect(model.properties[0].properties.length).toBe(2); 104 105 }); ··· 114 115 name: definitionType.base.replace(reservedWords, '_$1'), 115 116 }, 116 117 openApi, 118 + types: {}, 117 119 }); 118 120 expect(model.properties[0].properties.length).toBe(3); 119 121 });
+21 -18
packages/openapi-ts/src/openApi/v3/parser/__tests__/getServices.spec.ts
··· 10 10 debug: false, 11 11 dryRun: true, 12 12 exportCore: true, 13 - format: false, 14 13 input: '', 15 - lint: false, 16 - output: '', 14 + output: { 15 + path: '', 16 + }, 17 17 schemas: {}, 18 18 services: { 19 19 operationId: true, ··· 23 23 }); 24 24 25 25 const services = getServices({ 26 - info: { 27 - title: 'x', 28 - version: '1', 29 - }, 30 - openapi: '3.0.0', 31 - paths: { 32 - '/api/trips': { 33 - get: { 34 - responses: { 35 - 200: { 36 - description: 'x', 26 + openApi: { 27 + info: { 28 + title: 'x', 29 + version: '1', 30 + }, 31 + openapi: '3.0.0', 32 + paths: { 33 + '/api/trips': { 34 + get: { 35 + responses: { 36 + 200: { 37 + description: 'x', 38 + }, 39 + default: { 40 + description: 'default', 41 + }, 37 42 }, 38 - default: { 39 - description: 'default', 40 - }, 43 + tags: [], 41 44 }, 42 - tags: [], 43 45 }, 44 46 }, 45 47 }, 48 + types: {}, 46 49 }); 47 50 48 51 expect(services).toHaveLength(1);
+43 -12
packages/openapi-ts/src/openApi/v3/parser/getModel.ts
··· 1 + import type { Client } from '../../../types/client'; 2 + import { enumMeta } from '../../../utils/enum'; 1 3 import type { Model, ModelMeta } from '../../common/interfaces/client'; 2 4 import { getDefault } from '../../common/parser/getDefault'; 3 5 import { getEnums } from '../../common/parser/getEnums'; ··· 21 23 22 24 export const getModel = ({ 23 25 definition, 26 + initialValues = {}, 24 27 isDefinition = false, 25 28 meta, 26 29 openApi, 27 30 parentDefinition = null, 28 - }: { 31 + types, 32 + }: Pick<Client, 'types'> & { 29 33 definition: OpenApiSchema; 34 + /** 35 + * Pass through initial model values 36 + */ 37 + initialValues?: Partial<Model>; 30 38 isDefinition?: boolean; 31 39 meta?: ModelMeta; 32 40 openApi: OpenApi; ··· 68 76 template: null, 69 77 type: 'unknown', 70 78 uniqueItems: definition.uniqueItems, 79 + ...initialValues, 71 80 }; 72 81 73 82 if (definition.$ref) { ··· 90 99 model.export = 'enum'; 91 100 model.type = 'string'; 92 101 model.default = getDefault(definition, model); 102 + if (!model.meta) { 103 + model.meta = enumMeta(model); 104 + } 93 105 return model; 94 106 } 95 107 } ··· 115 127 (definition) => !getDefinitionTypes(definition).includes('array'), 116 128 ) 117 129 ) { 118 - return getModel({ definition: definition.items, openApi }); 130 + return getModel({ 131 + definition: definition.items, 132 + openApi, 133 + parentDefinition: definition, 134 + types, 135 + }); 119 136 } 120 137 } 121 138 ··· 128 145 anyOf: definition.items, 129 146 } 130 147 : definition.items; 131 - const arrayItems = getModel({ definition: arrayItemsDefinition, openApi }); 148 + const arrayItems = getModel({ 149 + definition: arrayItemsDefinition, 150 + openApi, 151 + parentDefinition: definition, 152 + types, 153 + }); 132 154 model.base = arrayItems.base; 133 155 model.export = 'array'; 134 156 model.$refs = [...model.$refs, ...arrayItems.$refs]; ··· 148 170 getModel, 149 171 model, 150 172 openApi, 173 + types, 151 174 }); 152 175 return { ...model, ...composition }; 153 176 } ··· 159 182 model.type = 'unknown'; 160 183 model.default = getDefault(definition, model); 161 184 162 - const modelProperties = getModelProperties( 163 - openApi, 185 + const modelProperties = getModelProperties({ 164 186 definition, 165 187 getModel, 166 - model, 167 - ); 188 + openApi, 189 + parent: model, 190 + types, 191 + }); 168 192 modelProperties.forEach((modelProperty) => { 169 193 model.$refs = [...model.$refs, ...modelProperty.$refs]; 170 194 model.enums = [...model.enums, ...modelProperty.enums]; 171 195 model.imports = [...model.imports, ...modelProperty.imports]; 172 - model.properties.push(modelProperty); 196 + model.properties = [...model.properties, modelProperty]; 173 197 if (modelProperty.export === 'enum') { 174 198 model.enums = [...model.enums, modelProperty]; 175 199 } 176 200 }); 177 201 178 202 if (definition.additionalProperties) { 179 - const modelProperty = getAdditionalPropertiesModel( 180 - openApi, 203 + const modelProperty = getAdditionalPropertiesModel({ 181 204 definition, 182 205 getModel, 183 206 model, 184 - ); 207 + openApi, 208 + types, 209 + }); 185 210 model.properties.push(modelProperty); 186 211 } 187 212 188 213 return model; 189 214 } 190 215 191 - return getAdditionalPropertiesModel(openApi, definition, getModel, model); 216 + return getAdditionalPropertiesModel({ 217 + definition, 218 + getModel, 219 + model, 220 + openApi, 221 + types, 222 + }); 192 223 } 193 224 194 225 if (definition.const !== undefined) {
+57 -43
packages/openapi-ts/src/openApi/v3/parser/getModelComposition.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { Model, ModelComposition } from '../../common/interfaces/client'; 3 + import type { GetModelFn } from '../interfaces/Model'; 2 4 import type { OpenApi } from '../interfaces/OpenApi'; 3 5 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 4 - import type { getModel } from './getModel'; 5 6 import { getModelProperties } from './getModelProperties'; 6 7 import { getRequiredPropertiesFromComposition } from './getRequiredPropertiesFromComposition'; 7 - 8 - // Fix for circular dependency 9 - export type GetModelFn = typeof getModel; 10 8 11 9 type Composition = { 12 10 definitions: OpenApiSchema[]; ··· 45 43 model, 46 44 openApi, 47 45 type, 48 - }: Composition & { 49 - definition: OpenApiSchema; 50 - getModel: GetModelFn; 51 - model: Model; 52 - openApi: OpenApi; 53 - }): ModelComposition => { 46 + types, 47 + }: Composition & 48 + Pick<Client, 'types'> & { 49 + definition: OpenApiSchema; 50 + getModel: GetModelFn; 51 + model: Model; 52 + openApi: OpenApi; 53 + }): ModelComposition => { 54 54 const composition: ModelComposition = { 55 55 $refs: model.$refs, 56 56 enums: model.enums, ··· 59 59 properties: model.properties, 60 60 }; 61 61 62 - const properties: Model[] = []; 62 + let properties: Model[] = []; 63 63 64 64 definitions 65 65 .map((def) => 66 - getModel({ definition: def, openApi, parentDefinition: definition }), 66 + getModel({ 67 + definition: def, 68 + openApi, 69 + parentDefinition: definition, 70 + types, 71 + }), 67 72 ) 68 73 .forEach((model) => { 69 74 composition.$refs = [...composition.$refs, ...model.$refs]; 70 75 composition.imports = [...composition.imports, ...model.imports]; 71 - composition.enums.push(...model.enums); 72 - composition.properties.push(model); 76 + composition.enums = [...composition.enums, ...model.enums]; 77 + composition.properties = [...composition.properties, model]; 73 78 }); 74 79 75 80 if (definition.required) { 76 - const requiredProperties = getRequiredPropertiesFromComposition( 77 - openApi, 78 - definition.required, 81 + const requiredProperties = getRequiredPropertiesFromComposition({ 79 82 definitions, 80 83 getModel, 81 - ); 84 + openApi, 85 + required: definition.required, 86 + types, 87 + }); 82 88 requiredProperties.forEach((requiredProperty) => { 83 89 composition.$refs = [...composition.$refs, ...requiredProperty.$refs]; 84 90 composition.imports = [ 85 91 ...composition.imports, 86 92 ...requiredProperty.imports, 87 93 ]; 88 - composition.enums.push(...requiredProperty.enums); 94 + composition.enums = [...composition.enums, ...requiredProperty.enums]; 89 95 }); 90 - properties.push(...requiredProperties); 96 + properties = [...properties, ...requiredProperties]; 91 97 } 92 98 93 99 if (definition.properties) { 94 - const modelProperties = getModelProperties(openApi, definition, getModel); 100 + const modelProperties = getModelProperties({ 101 + definition, 102 + getModel, 103 + openApi, 104 + types, 105 + }); 95 106 modelProperties.forEach((modelProperty) => { 96 107 composition.$refs = [...composition.$refs, ...modelProperty.$refs]; 97 108 composition.imports = [...composition.imports, ...modelProperty.imports]; 98 - composition.enums.push(...modelProperty.enums); 109 + composition.enums = [...composition.enums, ...modelProperty.enums]; 99 110 if (modelProperty.export === 'enum') { 100 - composition.enums.push(modelProperty); 111 + composition.enums = [...composition.enums, modelProperty]; 101 112 } 102 113 }); 103 - properties.push(...modelProperties); 114 + properties = [...properties, ...modelProperties]; 104 115 } 105 116 106 117 if (properties.length) { 107 118 const foundComposition = findModelComposition(definition); 108 119 if (foundComposition?.type === 'one-of') { 109 120 composition.properties.forEach((property) => { 110 - property.properties.push(...properties); 121 + property.properties = [...property.properties, ...properties]; 111 122 }); 112 123 } else { 113 - composition.properties.push({ 114 - $refs: [], 115 - base: 'unknown', 116 - description: '', 117 - enum: [], 118 - enums: [], 119 - export: 'interface', 120 - imports: [], 121 - isDefinition: false, 122 - isNullable: false, 123 - isReadOnly: false, 124 - isRequired: false, 125 - link: null, 126 - name: 'properties', 127 - properties, 128 - template: null, 129 - type: 'unknown', 130 - }); 124 + composition.properties = [ 125 + ...composition.properties, 126 + { 127 + $refs: [], 128 + base: 'unknown', 129 + description: '', 130 + enum: [], 131 + enums: [], 132 + export: 'interface', 133 + imports: [], 134 + isDefinition: false, 135 + isNullable: false, 136 + isReadOnly: false, 137 + isRequired: false, 138 + link: null, 139 + name: 'properties', 140 + properties, 141 + template: null, 142 + type: 'unknown', 143 + }, 144 + ]; 131 145 } 132 146 } 133 147
+80 -62
packages/openapi-ts/src/openApi/v3/parser/getModelProperties.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import { escapeName } from '../../../utils/escape'; 2 3 import { unique } from '../../../utils/unique'; 3 4 import type { Model } from '../../common/interfaces/client'; 4 5 import { getDefault } from '../../common/parser/getDefault'; 5 6 import { getPattern } from '../../common/parser/getPattern'; 6 7 import { getType } from '../../common/parser/type'; 8 + import type { GetModelFn } from '../interfaces/Model'; 7 9 import type { OpenApi } from '../interfaces/OpenApi'; 8 10 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 9 11 import { 10 12 findOneOfParentDiscriminator, 11 13 mapPropertyValue, 12 14 } from './discriminator'; 13 - import type { getModel } from './getModel'; 14 15 import { isDefinitionNullable } from './inferType'; 15 16 16 - // Fix for circular dependency 17 - export type GetModelFn = typeof getModel; 18 - 19 - export const getAdditionalPropertiesModel = ( 20 - openApi: OpenApi, 21 - definition: OpenApiSchema, 22 - getModel: GetModelFn, 23 - model: Model, 24 - ): Model => { 17 + export const getAdditionalPropertiesModel = ({ 18 + definition, 19 + getModel, 20 + model, 21 + openApi, 22 + types, 23 + }: { 24 + openApi: OpenApi; 25 + definition: OpenApiSchema; 26 + getModel: GetModelFn; 27 + model: Model; 28 + types: Client['types']; 29 + }): Model => { 25 30 const ap = 26 31 typeof definition.additionalProperties === 'object' 27 32 ? definition.additionalProperties 28 33 : {}; 29 - const apModel = getModel({ definition: ap, openApi }); 34 + const apModel = getModel({ 35 + definition: ap, 36 + openApi, 37 + parentDefinition: definition, 38 + types, 39 + }); 30 40 31 41 if (ap.$ref) { 32 42 const apType = getType({ type: ap.$ref }); ··· 68 78 return model; 69 79 }; 70 80 71 - export const getModelProperties = ( 72 - openApi: OpenApi, 73 - definition: OpenApiSchema, 74 - getModel: GetModelFn, 75 - parent?: Model, 76 - ): Model[] => { 77 - const models: Model[] = []; 81 + export const getModelProperties = ({ 82 + definition, 83 + getModel, 84 + openApi, 85 + parent, 86 + types, 87 + }: { 88 + definition: OpenApiSchema; 89 + getModel: GetModelFn; 90 + openApi: OpenApi; 91 + parent?: Model; 92 + types: Client['types']; 93 + }): Model[] => { 94 + let models: Model[] = []; 78 95 const discriminator = findOneOfParentDiscriminator(openApi, parent); 79 96 80 97 Object.entries(definition.properties ?? {}).forEach( 81 98 ([propertyName, property]) => { 82 - const propertyRequired = !!definition.required?.includes(propertyName); 99 + const propertyRequired = Boolean( 100 + definition.required?.includes(propertyName), 101 + ); 83 102 const propertyValues: Omit< 84 103 Model, 85 104 | '$refs' ··· 118 137 }; 119 138 120 139 if (parent && discriminator?.propertyName == propertyName) { 121 - models.push({ 122 - ...propertyValues, 123 - $refs: [], 124 - base: `'${mapPropertyValue(discriminator, parent)}'`, 125 - enum: [], 126 - enums: [], 127 - export: 'reference', 128 - imports: [], 129 - isNullable: isDefinitionNullable(property), 130 - link: null, 131 - properties: [], 132 - template: null, 133 - type: 'string', 134 - }); 140 + models = [ 141 + ...models, 142 + { 143 + ...propertyValues, 144 + $refs: [], 145 + base: `'${mapPropertyValue(discriminator, parent)}'`, 146 + enum: [], 147 + enums: [], 148 + export: 'reference', 149 + imports: [], 150 + isNullable: isDefinitionNullable(property), 151 + link: null, 152 + properties: [], 153 + template: null, 154 + type: 'string', 155 + }, 156 + ]; 135 157 } else if (property.$ref) { 136 158 const model = getType({ type: property.$ref }); 137 - models.push({ 138 - ...propertyValues, 139 - $refs: model.$refs, 140 - base: model.base, 141 - enum: [], 142 - enums: [], 143 - export: 'reference', 144 - imports: model.imports, 145 - isNullable: model.isNullable || isDefinitionNullable(property), 146 - link: null, 147 - properties: [], 148 - template: model.template, 149 - type: model.type, 150 - }); 159 + models = [ 160 + ...models, 161 + { 162 + ...propertyValues, 163 + $refs: model.$refs, 164 + base: model.base, 165 + enum: [], 166 + enums: [], 167 + export: 'reference', 168 + imports: model.imports, 169 + isNullable: model.isNullable || isDefinitionNullable(property), 170 + link: null, 171 + properties: [], 172 + template: model.template, 173 + type: model.type, 174 + }, 175 + ]; 151 176 } else { 152 - const model = getModel({ definition: property, openApi }); 153 - models.push({ 154 - ...propertyValues, 155 - $refs: model.$refs, 156 - base: model.base, 157 - default: model.default, 158 - enum: model.enum, 159 - enums: model.enums, 160 - export: model.export, 161 - imports: model.imports, 162 - isNullable: model.isNullable || isDefinitionNullable(property), 163 - link: model.link, 164 - properties: model.properties, 165 - template: model.template, 166 - type: model.type, 177 + const model = getModel({ 178 + definition: property, 179 + initialValues: propertyValues, 180 + openApi, 181 + parentDefinition: definition, 182 + types, 167 183 }); 184 + model.isNullable = model.isNullable || isDefinitionNullable(property); 185 + models = [...models, model]; 168 186 } 169 187 }, 170 188 );
+45 -28
packages/openapi-ts/src/openApi/v3/parser/getModels.ts
··· 1 - import type { Model } from '../../common/interfaces/client'; 1 + import type { Client } from '../../../types/client'; 2 2 import { reservedWords } from '../../common/parser/reservedWords'; 3 3 import { getType } from '../../common/parser/type'; 4 4 import type { OpenApi } from '../interfaces/OpenApi'; 5 5 import { getModel } from './getModel'; 6 6 7 - export const getModels = (openApi: OpenApi): Model[] => { 7 + export const getModels = ( 8 + openApi: OpenApi, 9 + ): Pick<Client, 'models' | 'types'> => { 10 + const types: Client['types'] = {}; 11 + let models: Client['models'] = []; 12 + 8 13 if (!openApi.components) { 9 - return []; 14 + return { 15 + models, 16 + types, 17 + }; 10 18 } 11 19 12 - let models: Model[] = []; 13 - 14 20 Object.entries(openApi.components.schemas ?? {}).forEach( 15 21 ([definitionName, definition]) => { 16 22 const definitionType = getType({ type: definitionName }); 23 + const name = definitionType.base.replace(reservedWords, '_$1'); 24 + const meta = { 25 + $ref: `#/components/schemas/${definitionName}`, 26 + name, 27 + }; 28 + types[name] = meta; 17 29 const model = getModel({ 18 30 definition, 19 31 isDefinition: true, 20 - meta: { 21 - $ref: `#/components/schemas/${definitionName}`, 22 - name: definitionType.base.replace(reservedWords, '_$1'), 23 - }, 32 + meta, 24 33 openApi, 34 + types, 25 35 }); 26 36 models = [...models, model]; 27 37 }, ··· 35 45 } 36 46 37 47 const definitionType = getType({ type: definitionName }); 48 + /** 49 + * Prefix parameter names to avoid name conflicts with schemas. 50 + * Assuming people are mostly interested in importing schema types 51 + * and don't care about this name as much. It should be resolved in 52 + * a cleaner way, there just isn't a good deduplication strategy 53 + * today. This is a workaround in the meantime, hopefully reducing 54 + * the chance of conflicts. 55 + * 56 + * Example where this would break: schema named `ParameterFoo` and 57 + * parameter named `Foo` (this would transform to `ParameterFoo`) 58 + * 59 + * Note: there's a related code to this workaround in `getType()` 60 + * method that needs to be cleaned up when this is addressed. 61 + */ 62 + const name = `Parameter${definitionType.base.replace(reservedWords, '_$1')}`; 63 + const meta = { 64 + $ref: `#/components/parameters/${definitionName}`, 65 + name, 66 + }; 67 + types[name] = meta; 38 68 const model = getModel({ 39 69 definition: schema, 40 70 isDefinition: true, 41 - meta: { 42 - $ref: `#/components/parameters/${definitionName}`, 43 - /** 44 - * Prefix parameter names to avoid name conflicts with schemas. 45 - * Assuming people are mostly interested in importing schema types 46 - * and don't care about this name as much. It should be resolved in 47 - * a cleaner way, there just isn't a good deduplication strategy 48 - * today. This is a workaround in the meantime, hopefully reducing 49 - * the chance of conflicts. 50 - * 51 - * Example where this would break: schema named `ParameterFoo` and 52 - * parameter named `Foo` (this would transform to `ParameterFoo`) 53 - * 54 - * Note: there's a related code to this workaround in `getType()` 55 - * method that needs to be cleaned up when this is addressed. 56 - */ 57 - name: `Parameter${definitionType.base.replace(reservedWords, '_$1')}`, 58 - }, 71 + meta, 59 72 openApi, 73 + types, 60 74 }); 61 75 model.deprecated = definition.deprecated; 62 76 model.description = definition.description || null; ··· 64 78 }, 65 79 ); 66 80 67 - return models; 81 + return { 82 + models, 83 + types, 84 + }; 68 85 };
+49 -38
packages/openapi-ts/src/openApi/v3/parser/getOperationParameter.ts
··· 1 + import type { Client } from '../../../types/client'; 2 + import { enumMeta } from '../../../utils/enum'; 1 3 import type { OperationParameter } from '../../common/interfaces/client'; 2 4 import { getDefault } from '../../common/parser/getDefault'; 3 5 import { getPattern } from '../../common/parser/getPattern'; ··· 10 12 import { getModel } from './getModel'; 11 13 import { isDefinitionNullable } from './inferType'; 12 14 13 - export const getOperationParameter = ( 14 - openApi: OpenApi, 15 - parameter: OpenApiParameter, 16 - ): OperationParameter => { 17 - const operationParameter: OperationParameter = { 15 + export const getOperationParameter = ({ 16 + openApi, 17 + parameter, 18 + types, 19 + }: { 20 + openApi: OpenApi; 21 + parameter: OpenApiParameter; 22 + types: Client['types']; 23 + }): OperationParameter => { 24 + let operationParameter: OperationParameter = { 18 25 $refs: [], 19 26 base: 'unknown', 20 27 deprecated: parameter.deprecated === true, ··· 73 80 operationParameter.default = getDefault(schema); 74 81 return operationParameter; 75 82 } else { 76 - const model = getModel({ definition: schema, openApi }); 77 - operationParameter.export = model.export; 78 - operationParameter.type = model.type; 79 - operationParameter.base = model.base; 80 - operationParameter.template = model.template; 81 - operationParameter.link = model.link; 82 - operationParameter.isReadOnly = model.isReadOnly; 83 - operationParameter.isRequired = 84 - operationParameter.isRequired || model.isRequired; 85 - operationParameter.isNullable = 86 - operationParameter.isNullable || model.isNullable; 87 - operationParameter.format = model.format; 88 - operationParameter.maximum = model.maximum; 89 - operationParameter.exclusiveMaximum = model.exclusiveMaximum; 90 - operationParameter.minimum = model.minimum; 91 - operationParameter.exclusiveMinimum = model.exclusiveMinimum; 92 - operationParameter.multipleOf = model.multipleOf; 93 - operationParameter.maxLength = model.maxLength; 94 - operationParameter.minLength = model.minLength; 95 - operationParameter.maxItems = model.maxItems; 96 - operationParameter.minItems = model.minItems; 97 - operationParameter.uniqueItems = model.uniqueItems; 98 - operationParameter.maxProperties = model.maxProperties; 99 - operationParameter.minProperties = model.minProperties; 100 - operationParameter.pattern = getPattern(model.pattern); 83 + const model = getModel({ definition: schema, openApi, types }); 84 + operationParameter = { 85 + ...operationParameter, 86 + $refs: [...operationParameter.$refs, ...model.$refs], 87 + base: model.base, 88 + enum: [...operationParameter.enum, ...model.enum], 89 + enums: [...operationParameter.enums, ...model.enums], 90 + exclusiveMaximum: model.exclusiveMaximum, 91 + exclusiveMinimum: model.exclusiveMinimum, 92 + export: model.export, 93 + format: model.format, 94 + imports: [...operationParameter.imports, ...model.imports], 95 + isNullable: operationParameter.isNullable || model.isNullable, 96 + isReadOnly: model.isReadOnly, 97 + isRequired: operationParameter.isRequired || model.isRequired, 98 + link: model.link, 99 + maxItems: model.maxItems, 100 + maxLength: model.maxLength, 101 + maxProperties: model.maxProperties, 102 + maximum: model.maximum, 103 + minItems: model.minItems, 104 + minLength: model.minLength, 105 + minProperties: model.minProperties, 106 + minimum: model.minimum, 107 + multipleOf: model.multipleOf, 108 + pattern: getPattern(model.pattern), 109 + properties: [...operationParameter.properties, ...model.properties], 110 + template: model.template, 111 + type: model.type, 112 + uniqueItems: model.uniqueItems, 113 + }; 114 + if ( 115 + (operationParameter.enum.length || operationParameter.enums.length) && 116 + !operationParameter.meta 117 + ) { 118 + operationParameter.meta = enumMeta(operationParameter); 119 + } 101 120 operationParameter.default = model.default; 102 - operationParameter.$refs = [...operationParameter.$refs, ...model.$refs]; 103 - operationParameter.imports = [ 104 - ...operationParameter.imports, 105 - ...model.imports, 106 - ]; 107 - operationParameter.enum.push(...model.enum); 108 - operationParameter.enums.push(...model.enums); 109 - operationParameter.properties.push(...model.properties); 110 121 return operationParameter; 111 122 } 112 123 }
+15 -5
packages/openapi-ts/src/openApi/v3/parser/getOperationParameters.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationParameters } from '../../common/interfaces/client'; 2 3 import { getRef } from '../../common/parser/getRef'; 3 4 import type { OpenApi } from '../interfaces/OpenApi'; ··· 6 7 7 8 const allowedIn = ['cookie', 'formData', 'header', 'path', 'query'] as const; 8 9 9 - export const getOperationParameters = ( 10 - openApi: OpenApi, 11 - parameters: OpenApiParameter[], 12 - ): OperationParameters => { 10 + export const getOperationParameters = ({ 11 + openApi, 12 + parameters, 13 + types, 14 + }: { 15 + openApi: OpenApi; 16 + parameters: OpenApiParameter[]; 17 + types: Client['types']; 18 + }): OperationParameters => { 13 19 const operationParameters: OperationParameters = { 14 20 $refs: [], 15 21 imports: [], ··· 27 33 openApi, 28 34 parameterOrReference, 29 35 ); 30 - const parameter = getOperationParameter(openApi, parameterDef); 36 + const parameter = getOperationParameter({ 37 + openApi, 38 + parameter: parameterDef, 39 + types, 40 + }); 31 41 32 42 const defIn = parameterDef.in as (typeof allowedIn)[number]; 33 43
+11 -5
packages/openapi-ts/src/openApi/v3/parser/getOperationRequestBody.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationParameter } from '../../common/interfaces/client'; 2 3 import { getPattern } from '../../common/parser/getPattern'; 3 4 import { getType } from '../../common/parser/type'; ··· 6 7 import { getContent } from './getContent'; 7 8 import { getModel } from './getModel'; 8 9 9 - export const getOperationRequestBody = ( 10 - openApi: OpenApi, 11 - body: OpenApiRequestBody, 12 - ): OperationParameter => { 10 + export const getOperationRequestBody = ({ 11 + body, 12 + openApi, 13 + types, 14 + }: { 15 + body: OpenApiRequestBody; 16 + openApi: OpenApi; 17 + types: Client['types']; 18 + }): OperationParameter => { 13 19 const name = body['x-body-name'] ?? 'requestBody'; 14 20 15 21 const requestBody: OperationParameter = { ··· 57 63 requestBody.imports = [...requestBody.imports, ...model.imports]; 58 64 return requestBody; 59 65 } else { 60 - const model = getModel({ definition: content.schema, openApi }); 66 + const model = getModel({ definition: content.schema, openApi, types }); 61 67 requestBody.export = model.export; 62 68 requestBody.type = model.type; 63 69 requestBody.base = model.base;
+13 -6
packages/openapi-ts/src/openApi/v3/parser/getOperationResponse.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationResponse } from '../../common/interfaces/client'; 2 3 import { getPattern } from '../../common/parser/getPattern'; 3 4 import { getRef } from '../../common/parser/getRef'; ··· 8 9 import { getContent } from './getContent'; 9 10 import { getModel } from './getModel'; 10 11 11 - export const getOperationResponse = ( 12 - openApi: OpenApi, 13 - response: OpenApiResponse, 14 - code: number | 'default', 15 - ): OperationResponse => { 12 + export const getOperationResponse = ({ 13 + code, 14 + openApi, 15 + response, 16 + types, 17 + }: { 18 + openApi: OpenApi; 19 + response: OpenApiResponse; 20 + code: number | 'default'; 21 + types: Client['types']; 22 + }): OperationResponse => { 16 23 const operationResponse: OperationResponse = { 17 24 $refs: [], 18 25 base: code !== 204 ? 'unknown' : 'void', ··· 53 60 operationResponse.type = model.type; 54 61 return operationResponse; 55 62 } else { 56 - const model = getModel({ definition: content.schema, openApi }); 63 + const model = getModel({ definition: content.schema, openApi, types }); 57 64 operationResponse.export = model.export; 58 65 operationResponse.type = model.type; 59 66 operationResponse.base = model.base;
+14 -7
packages/openapi-ts/src/openApi/v3/parser/getOperationResponses.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { OperationResponse } from '../../common/interfaces/client'; 2 3 import { getRef } from '../../common/parser/getRef'; 3 4 import { getOperationResponseCode } from '../../common/parser/operation'; ··· 6 7 import type { OpenApiResponses } from '../interfaces/OpenApiResponses'; 7 8 import { getOperationResponse } from './getOperationResponse'; 8 9 9 - export const getOperationResponses = ( 10 - openApi: OpenApi, 11 - responses: OpenApiResponses, 12 - ): OperationResponse[] => { 10 + export const getOperationResponses = ({ 11 + openApi, 12 + responses, 13 + types, 14 + }: { 15 + openApi: OpenApi; 16 + responses: OpenApiResponses; 17 + types: Client['types']; 18 + }): OperationResponse[] => { 13 19 const operationResponses: OperationResponse[] = []; 14 20 15 21 // Iterate over each response code and get the ··· 19 25 const responseCode = getOperationResponseCode(code); 20 26 21 27 if (responseCode) { 22 - const operationResponse = getOperationResponse( 28 + const operationResponse = getOperationResponse({ 29 + code: responseCode, 23 30 openApi, 24 31 response, 25 - responseCode, 26 - ); 32 + types, 33 + }); 27 34 operationResponses.push(operationResponse); 28 35 } 29 36 });
+47 -13
packages/openapi-ts/src/openApi/v3/parser/getRequiredPropertiesFromComposition.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import type { Model } from '../../common/interfaces/client'; 2 3 import { getRef } from '../../common/parser/getRef'; 4 + import { getType } from '../../common/parser/type'; 5 + import type { GetModelFn } from '../interfaces/Model'; 3 6 import type { OpenApi } from '../interfaces/OpenApi'; 4 7 import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; 5 - import type { getModel } from './getModel'; 6 8 7 - // Fix for circular dependency 8 - export type GetModelFn = typeof getModel; 9 - 10 - export const getRequiredPropertiesFromComposition = ( 11 - openApi: OpenApi, 12 - required: string[], 13 - definitions: OpenApiSchema[], 14 - getModel: GetModelFn, 15 - ): Model[] => 16 - definitions 9 + export const getRequiredPropertiesFromComposition = ({ 10 + definitions, 11 + getModel, 12 + openApi, 13 + required, 14 + types, 15 + }: { 16 + openApi: OpenApi; 17 + required: string[]; 18 + definitions: OpenApiSchema[]; 19 + getModel: GetModelFn; 20 + types: Client['types']; 21 + }): Model[] => { 22 + const requiredProperties = definitions 17 23 .reduce((properties, definition) => { 18 24 if (definition.$ref) { 25 + const type = getType({ type: definition.$ref }); 26 + // avoid circular references if two refs reference each other 27 + // if (types[type.base] && types[type.base].$ref === definition.$ref) { 28 + // const schema = getRef<OpenApiSchema>(openApi, definition); 29 + // return [...properties] 30 + // } 31 + 32 + const meta = { 33 + $ref: definition.$ref, 34 + name: type.base, 35 + }; 36 + types[type.base] = meta; 19 37 const schema = getRef<OpenApiSchema>(openApi, definition); 20 38 return [ 21 39 ...properties, 22 - ...getModel({ definition: schema, openApi }).properties, 40 + ...getModel({ 41 + definition: schema, 42 + meta, 43 + openApi, 44 + types, 45 + }).properties, 23 46 ]; 24 47 } 25 - return [...properties, ...getModel({ definition, openApi }).properties]; 48 + 49 + return [ 50 + ...properties, 51 + ...getModel({ 52 + definition, 53 + openApi, 54 + parentDefinition: definition, 55 + types, 56 + }).properties, 57 + ]; 26 58 }, [] as Model[]) 27 59 .filter( 28 60 (property) => !property.isRequired && required.includes(property.name), ··· 31 63 ...property, 32 64 isRequired: true, 33 65 })); 66 + return requiredProperties; 67 + };
+16 -3
packages/openapi-ts/src/openApi/v3/parser/getServices.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import { unique } from '../../../utils/unique'; 2 3 import type { Operation, Service } from '../../common/interfaces/client'; 3 4 import type { OpenApi } from '../interfaces/OpenApi'; ··· 23 24 operations: [], 24 25 }); 25 26 26 - export const getServices = (openApi: OpenApi): Service[] => { 27 + export const getServices = ({ 28 + openApi, 29 + types, 30 + }: { 31 + openApi: OpenApi; 32 + types: Client['types']; 33 + }): Service[] => { 27 34 const services = new Map<string, Service>(); 28 35 29 36 for (const url in openApi.paths) { 30 37 const path = openApi.paths[url]; 31 - const pathParams = getOperationParameters(openApi, path.parameters ?? []); 38 + const pathParams = getOperationParameters({ 39 + openApi, 40 + parameters: path.parameters ?? [], 41 + types, 42 + }); 32 43 33 44 for (const key in path) { 34 45 const method = key as Lowercase<Operation['method']>; ··· 36 47 const op = path[method]!; 37 48 const tags = op.tags?.length ? op.tags.filter(unique) : ['Default']; 38 49 tags.forEach((tag) => { 39 - const operation = getOperation(openApi, { 50 + const operation = getOperation({ 40 51 method, 41 52 op, 53 + openApi, 42 54 pathParams, 43 55 tag, 56 + types, 44 57 url, 45 58 }); 46 59 const service =
+33 -14
packages/openapi-ts/src/openApi/v3/parser/operation.ts
··· 1 + import type { Client } from '../../../types/client'; 1 2 import { getOperationResults } from '../../../utils/operation'; 2 3 import type { 3 4 Operation, ··· 40 41 return mergedParameters; 41 42 }; 42 43 43 - export const getOperation = ( 44 - openApi: OpenApi, 45 - data: { 46 - method: Lowercase<Operation['method']>; 47 - op: OpenApiOperation; 48 - pathParams: OperationParameters; 49 - tag: string; 50 - url: string; 51 - }, 52 - ): Operation => { 53 - const { method, op, pathParams, tag, url } = data; 44 + export const getOperation = ({ 45 + method, 46 + op, 47 + openApi, 48 + pathParams, 49 + tag, 50 + types, 51 + url, 52 + }: { 53 + method: Lowercase<Operation['method']>; 54 + op: OpenApiOperation; 55 + openApi: OpenApi; 56 + pathParams: OperationParameters; 57 + tag: string; 58 + types: Client['types']; 59 + url: string; 60 + }): Operation => { 54 61 const service = getServiceName(tag); 55 62 const name = getOperationName(url, method, op.operationId); 56 63 ··· 77 84 }; 78 85 79 86 if (op.parameters) { 80 - const parameters = getOperationParameters(openApi, op.parameters); 87 + const parameters = getOperationParameters({ 88 + openApi, 89 + parameters: op.parameters, 90 + types, 91 + }); 81 92 operation.$refs = [...operation.$refs, ...parameters.$refs]; 82 93 operation.imports = [...operation.imports, ...parameters.imports]; 83 94 operation.parameters = [...operation.parameters, ...parameters.parameters]; ··· 106 117 107 118 if (op.requestBody) { 108 119 const requestBodyDef = getRef<OpenApiRequestBody>(openApi, op.requestBody); 109 - const requestBody = getOperationRequestBody(openApi, requestBodyDef); 120 + const requestBody = getOperationRequestBody({ 121 + body: requestBodyDef, 122 + openApi, 123 + types, 124 + }); 110 125 operation.$refs = [...operation.$refs, ...requestBody.$refs]; 111 126 operation.imports = [...operation.imports, ...requestBody.imports]; 112 127 operation.parameters = [...operation.parameters, requestBody]; ··· 114 129 } 115 130 116 131 if (op.responses) { 117 - const operationResponses = getOperationResponses(openApi, op.responses); 132 + const operationResponses = getOperationResponses({ 133 + openApi, 134 + responses: op.responses, 135 + types, 136 + }); 118 137 const operationResults = getOperationResults(operationResponses); 119 138 operation.errors = getOperationErrors(operationResponses); 120 139 operation.responseHeader = getOperationResponseHeader(operationResults);
+34 -19
packages/openapi-ts/src/types/config.ts
··· 1 - export interface UserConfig { 1 + export interface ClientConfig { 2 2 /** 3 3 * Manually set base in OpenAPI config instead of inferring from server value 4 + * @deprecated 4 5 */ 5 6 base?: string; 6 7 /** 7 - * The selected HTTP client (fetch, xhr, node or axios) 8 + * HTTP client to generate 8 9 * @default 'fetch' 9 10 */ 10 11 client?: ··· 31 32 */ 32 33 exportCore?: boolean; 33 34 /** 34 - * Process output folder with formatter? 35 - * @default false 36 - */ 37 - format?: 'biome' | 'prettier' | false; 38 - /** 39 35 * The relative location of the OpenAPI spec 40 36 */ 41 37 input: string | Record<string, unknown>; 42 38 /** 43 - * Process output folder with linter? 44 - * @default false 45 - */ 46 - lint?: 'biome' | 'eslint' | false; 47 - /** 48 39 * Custom client class name 40 + * @deprecated 49 41 */ 50 42 name?: string; 51 43 /** 52 44 * The relative location of the output directory 53 45 */ 54 - output: string; 46 + output: 47 + | string 48 + | { 49 + /** 50 + * Process output folder with formatter? 51 + * @default false 52 + */ 53 + format?: 'biome' | 'prettier' | false; 54 + /** 55 + * Process output folder with linter? 56 + * @default false 57 + */ 58 + lint?: 'biome' | 'eslint' | false; 59 + /** 60 + * The relative location of the output directory 61 + */ 62 + path: string; 63 + }; 55 64 /** 56 65 * Path to custom request file 66 + * @deprecated 57 67 */ 58 68 request?: string; 59 69 /** ··· 144 154 }; 145 155 /** 146 156 * Use options or arguments functions 157 + * @deprecated 147 158 * @default true 148 159 */ 149 160 useOptions?: boolean; 150 161 } 151 162 163 + // export type UserConfig = ClientConfig | Array<ClientConfig> 164 + export type UserConfig = ClientConfig; 165 + 152 166 export type Config = Omit< 153 - Required<UserConfig>, 154 - 'base' | 'name' | 'request' | 'schemas' | 'services' | 'types' 167 + Required<ClientConfig>, 168 + 'base' | 'name' | 'output' | 'request' | 'schemas' | 'services' | 'types' 155 169 > & 156 - Pick<UserConfig, 'base' | 'name' | 'request'> & { 157 - schemas: Extract<Required<UserConfig>['schemas'], object>; 158 - services: Extract<Required<UserConfig>['services'], object>; 159 - types: Extract<Required<UserConfig>['types'], object>; 170 + Pick<ClientConfig, 'base' | 'name' | 'request'> & { 171 + output: Extract<Required<ClientConfig>['output'], object>; 172 + schemas: Extract<Required<ClientConfig>['schemas'], object>; 173 + services: Extract<Required<ClientConfig>['services'], object>; 174 + types: Extract<Required<ClientConfig>['types'], object>; 160 175 };
+8 -6
packages/openapi-ts/src/utils/__tests__/handlebars.spec.ts
··· 14 14 debug: false, 15 15 dryRun: false, 16 16 exportCore: true, 17 - format: 'prettier', 18 17 input: '', 19 - lint: false, 20 - output: '', 18 + output: { 19 + format: 'prettier', 20 + path: '', 21 + }, 21 22 schemas: {}, 22 23 services: {}, 23 24 types: { ··· 42 43 debug: false, 43 44 dryRun: false, 44 45 exportCore: true, 45 - format: 'prettier', 46 46 input: '', 47 - lint: false, 48 - output: '', 47 + output: { 48 + format: 'prettier', 49 + path: '', 50 + }, 49 51 schemas: {}, 50 52 services: {}, 51 53 types: {
+26 -1
packages/openapi-ts/src/utils/enum.ts
··· 1 - import type { Enum } from '../openApi'; 1 + import type { Enum, Model } from '../openApi'; 2 + import { ensureValidTypeScriptJavaScriptIdentifier } from '../openApi/common/parser/sanitize'; 3 + import { unescapeName } from './escape'; 4 + import { sort } from './sort'; 2 5 import { unique } from './unique'; 3 6 4 7 /** ··· 49 52 } 50 53 return value; 51 54 }; 55 + 56 + export const enumEntry = (enumerator: Enum) => { 57 + const key = enumKey(enumerator.value, enumerator.customName); 58 + const value = enumValue(enumerator.value); 59 + return { key, value }; 60 + }; 61 + 62 + /** 63 + * Represent enum in `meta` object for deduplication 64 + */ 65 + export const enumMeta = (model: Model): Required<Model>['meta'] => { 66 + // serialize enum values in namespace for quick lookup 67 + const serialized = model.enum 68 + .map((enumerator) => enumEntry(enumerator)) 69 + .sort((a, b) => sort(a.key, b.key)) 70 + .map((enumerator) => `${enumerator.key}=${enumerator.value}`) 71 + .join('&'); 72 + return { 73 + $ref: `enum/${model.name}/${serialized}`, 74 + name: ensureValidTypeScriptJavaScriptIdentifier(unescapeName(model.name)), 75 + }; 76 + };
+1 -1
packages/openapi-ts/src/utils/getHttpRequestName.ts
··· 2 2 3 3 /** 4 4 * Generate the HttpRequest filename based on the selected client 5 - * @param client The selected HTTP client (fetch, xhr, node or axios) 5 + * @param client HTTP client to generate 6 6 */ 7 7 export const getHttpRequestName = (client: Config['client']): string => { 8 8 switch (client) {
-19
packages/openapi-ts/src/utils/required.ts
··· 1 - import { Model, OperationParameter } from '../openApi'; 2 - import { getConfig } from './config'; 3 - 4 - export const getDefaultPrintable = ( 5 - p: OperationParameter | Model, 6 - ): string | undefined => { 7 - if (p.default === undefined) { 8 - return undefined; 9 - } 10 - return JSON.stringify(p.default, null, 4); 11 - }; 12 - 13 - export const modelIsRequired = (model: Model) => { 14 - const config = getConfig(); 15 - if (config?.useOptions) { 16 - return model.isRequired ? '' : '?'; 17 - } 18 - return !model.isRequired && !getDefaultPrintable(model) ? '?' : ''; 19 - };
+3 -3
packages/openapi-ts/src/utils/write/__tests__/class.spec.ts
··· 16 16 debug: false, 17 17 dryRun: false, 18 18 exportCore: true, 19 - format: false, 20 19 input: '', 21 - lint: false, 22 20 name: 'AppClient', 23 - output: '', 21 + output: { 22 + path: '', 23 + }, 24 24 schemas: {}, 25 25 services: {}, 26 26 types: {
+4 -3
packages/openapi-ts/src/utils/write/__tests__/client.spec.ts
··· 16 16 debug: false, 17 17 dryRun: false, 18 18 exportCore: true, 19 - format: 'prettier', 20 19 input: '', 21 - lint: false, 22 - output: './dist', 20 + output: { 21 + format: 'prettier', 22 + path: './dist', 23 + }, 23 24 schemas: {}, 24 25 services: {}, 25 26 types: {
+9 -9
packages/openapi-ts/src/utils/write/__tests__/core.spec.ts
··· 29 29 debug: false, 30 30 dryRun: false, 31 31 exportCore: true, 32 - format: false, 33 32 input: '', 34 - lint: false, 35 33 name: 'AppClient', 36 - output: '', 34 + output: { 35 + path: '', 36 + }, 37 37 schemas: {}, 38 38 services: {}, 39 39 types: { ··· 84 84 debug: false, 85 85 dryRun: false, 86 86 exportCore: true, 87 - format: false, 88 87 input: '', 89 - lint: false, 90 88 name: 'AppClient', 91 - output: '', 89 + output: { 90 + path: '', 91 + }, 92 92 schemas: {}, 93 93 services: {}, 94 94 types: { ··· 122 122 debug: false, 123 123 dryRun: false, 124 124 exportCore: true, 125 - format: false, 126 125 input: '', 127 - lint: false, 128 126 name: 'AppClient', 129 - output: '', 127 + output: { 128 + path: '', 129 + }, 130 130 schemas: {}, 131 131 services: {}, 132 132 types: {
+3 -3
packages/openapi-ts/src/utils/write/__tests__/index.spec.ts
··· 16 16 debug: false, 17 17 dryRun: false, 18 18 exportCore: true, 19 - format: false, 20 19 input: '', 21 - lint: false, 22 - output: '', 20 + output: { 21 + path: '', 22 + }, 23 23 schemas: {}, 24 24 services: {}, 25 25 types: {
+3 -3
packages/openapi-ts/src/utils/write/__tests__/models.spec.ts
··· 16 16 debug: false, 17 17 dryRun: false, 18 18 exportCore: true, 19 - format: false, 20 19 input: '', 21 - lint: false, 22 20 name: 'AppClient', 23 - output: '', 21 + output: { 22 + path: '', 23 + }, 24 24 schemas: {}, 25 25 services: {}, 26 26 types: {
+3 -3
packages/openapi-ts/src/utils/write/__tests__/schemas.spec.ts
··· 17 17 debug: false, 18 18 dryRun: false, 19 19 exportCore: true, 20 - format: false, 21 20 input: '', 22 - lint: false, 23 21 name: 'AppClient', 24 - output: '', 22 + output: { 23 + path: '', 24 + }, 25 25 schemas: {}, 26 26 services: {}, 27 27 types: {
+3 -3
packages/openapi-ts/src/utils/write/__tests__/services.spec.ts
··· 16 16 debug: false, 17 17 dryRun: false, 18 18 exportCore: true, 19 - format: false, 20 19 input: '', 21 - lint: false, 22 - output: '', 20 + output: { 21 + path: '', 22 + }, 23 23 schemas: {}, 24 24 services: {}, 25 25 types: {},
+6 -6
packages/openapi-ts/src/utils/write/client.ts
··· 38 38 client.models = client.models.filter((model) => regexp.test(model.name)); 39 39 } 40 40 41 - const outputPath = path.resolve(config.output); 41 + const outputPath = path.resolve(config.output.path); 42 42 43 43 if (!existsSync(outputPath)) { 44 44 mkdirSync(outputPath, { recursive: true }); ··· 46 46 47 47 const files: Record<string, TypeScriptFile> = { 48 48 index: new TypeScriptFile({ 49 - dir: config.output, 49 + dir: config.output.path, 50 50 name: 'index.ts', 51 51 }), 52 52 }; 53 53 if (config.schemas.export) { 54 54 files.schemas = new TypeScriptFile({ 55 - dir: config.output, 55 + dir: config.output.path, 56 56 name: 'schemas.ts', 57 57 }); 58 58 } 59 59 if (config.services.export) { 60 60 files.services = new TypeScriptFile({ 61 - dir: config.output, 61 + dir: config.output.path, 62 62 name: 'services.ts', 63 63 }); 64 64 } 65 65 if (config.types.export) { 66 66 files.types = new TypeScriptFile({ 67 - dir: config.output, 67 + dir: config.output.path, 68 68 name: 'types.ts', 69 69 }); 70 70 } ··· 75 75 76 76 // deprecated files 77 77 await writeClientClass(openApi, outputPath, client, templates); 78 - await writeCore(path.resolve(config.output, 'core'), client, templates); 78 + await writeCore(path.resolve(config.output.path, 'core'), client, templates); 79 79 80 80 await processIndex({ files }); 81 81
+11 -2
packages/openapi-ts/src/utils/write/services.ts
··· 18 18 import type { Client } from '../../types/client'; 19 19 import { getConfig } from '../config'; 20 20 import { escapeComment, escapeName } from '../escape'; 21 - import { modelIsRequired } from '../required'; 22 21 import { transformServiceName } from '../transform'; 23 22 import { unique } from '../unique'; 24 23 import { uniqueTypeName } from './type'; ··· 89 88 return []; 90 89 } 91 90 91 + const getDefaultPrintable = ( 92 + p: OperationParameter | Model, 93 + ): string | undefined => { 94 + if (p.default === undefined) { 95 + return undefined; 96 + } 97 + return JSON.stringify(p.default, null, 4); 98 + }; 99 + 92 100 // legacy configuration 93 101 if (!config.useOptions) { 94 102 return operation.parameters.map((p) => { 95 103 const typePath = `${importedType}['${p.name}']`; 96 104 return { 97 105 default: p?.default, 98 - isRequired: modelIsRequired(p) === '', 106 + isRequired: 107 + (!p.isRequired && !getDefaultPrintable(p) ? '?' : '') === '', 99 108 name: p.name, 100 109 type: typePath, 101 110 };
+1 -2
packages/openapi-ts/src/utils/write/type.ts
··· 4 4 import { getConfig } from '../config'; 5 5 import { enumValue } from '../enum'; 6 6 import { escapeComment } from '../escape'; 7 - import { modelIsRequired } from '../required'; 8 7 import { unique } from '../unique'; 9 8 10 9 const base = (model: Model) => { ··· 86 85 } 87 86 88 87 const properties: Property[] = model.properties.map((property) => { 89 - let maybeRequired = modelIsRequired(property); 88 + let maybeRequired = property.isRequired ? '' : '?'; 90 89 let value = toType(property); 91 90 // special case for additional properties type 92 91 if (property.name === '[key: string]' && maybeRequired) {
+4 -14
packages/openapi-ts/src/utils/write/types.ts
··· 8 8 import type { Method } from '../../openApi/common/interfaces/client'; 9 9 import type { Client } from '../../types/client'; 10 10 import { getConfig } from '../config'; 11 - import { enumKey, enumUnionType, enumValue } from '../enum'; 11 + import { enumEntry, enumUnionType } from '../enum'; 12 12 import { escapeComment } from '../escape'; 13 13 import { sortByName, sorterByName } from '../sort'; 14 14 import { ··· 110 110 model.enums.forEach((enumerator) => processEnum(client, enumerator, onNode)); 111 111 }; 112 112 113 - const processEnum = ( 114 - client: Client, 115 - model: Model, 116 - onNode: OnNode, 117 - isExported: boolean = false, 118 - ) => { 119 - if (!isExported) { 120 - return; 121 - } 122 - 113 + const processEnum = (client: Client, model: Model, onNode: OnNode) => { 123 114 const config = getConfig(); 124 115 125 116 const properties: Record<string | number, unknown> = {}; 126 117 const comments: Record<string | number, Comments> = {}; 127 118 model.enum.forEach((enumerator) => { 128 - const key = enumKey(enumerator.value, enumerator.customName); 129 - const value = enumValue(enumerator.value); 119 + const { key, value } = enumEntry(enumerator); 130 120 properties[key] = value; 131 121 const comment = enumerator.customDescription || enumerator.description; 132 122 if (comment) { ··· 199 189 case 'interface': 200 190 return processComposition(client, model, onNode); 201 191 case 'enum': 202 - return processEnum(client, model, onNode, true); 192 + return processEnum(client, model, onNode); 203 193 default: 204 194 return processType(client, model, onNode); 205 195 }
+63 -1
packages/openapi-ts/test/__snapshots__/test/generated/v3/types.gen.ts.snap
··· 345 345 }; 346 346 347 347 /** 348 + * This is a simple enum with strings 349 + */ 350 + export type foo_bar_enum = 'Success' | 'Warning' | 'Error' | 'ØÆÅ字符串'; 351 + 352 + /** 353 + * This is a simple enum with strings 354 + */ 355 + export const foo_bar_enum = { 356 + SUCCESS: 'Success', 357 + WARNING: 'Warning', 358 + ERROR: 'Error', 359 + 'ØÆÅ字符串': 'ØÆÅ字符串' 360 + } as const; 361 + 362 + /** 348 363 * This is a model with one enum 349 364 */ 350 365 export type ModelWithEnum = { ··· 363 378 }; 364 379 365 380 /** 381 + * These are the HTTP error code enums 382 + */ 383 + export type statusCode = '100' | '200 FOO' | '300 FOO_BAR' | '400 foo-bar' | '500 foo.bar' | '600 foo&bar'; 384 + 385 + /** 386 + * These are the HTTP error code enums 387 + */ 388 + export const statusCode = { 389 + _100: '100', 390 + _200_FOO: '200 FOO', 391 + _300_FOO_BAR: '300 FOO_BAR', 392 + _400_FOO_BAR: '400 foo-bar', 393 + _500_FOO_BAR: '500 foo.bar', 394 + _600_FOO_BAR: '600 foo&bar' 395 + } as const; 396 + 397 + /** 366 398 * This is a model with one enum with escaped name 367 399 */ 368 400 export type ModelWithEnumWithHyphen = { 369 401 'foo-bar-baz-qux'?: '3.0'; 370 402 }; 403 + 404 + export type foo_bar_baz_qux = '3.0'; 405 + 406 + export const foo_bar_baz_qux = { 407 + _3_0: '3.0' 408 + } as const; 371 409 372 410 /** 373 411 * This is a model with one enum ··· 786 824 foo: 'Corge'; 787 825 }; 788 826 827 + export type foo = 'Bar'; 828 + 829 + export const foo = { 830 + BAR: 'Bar' 831 + } as const; 832 + 789 833 export type ModelWithNestedArrayEnumsDataFoo = 'foo' | 'bar'; 790 834 791 835 export const ModelWithNestedArrayEnumsDataFoo = { ··· 853 897 */ 854 898 value?: -10 | -1 | 0 | 1 | 3 | 6 | 12; 855 899 }; 900 + 901 + /** 902 + * Период 903 + */ 904 + export type value = -10 | -1 | 0 | 1 | 3 | 6 | 12; 905 + 906 + /** 907 + * Период 908 + */ 909 + export const value = { 910 + '_-10': -10, 911 + '_-1': -1, 912 + '_0': 0, 913 + '_1': 1, 914 + '_3': 3, 915 + '_6': 6, 916 + '_12': 12 917 + } as const; 856 918 857 919 /** 858 920 * Some description with `back ticks` ··· 1689 1751 }; 1690 1752 }; 1691 1753 }; 1692 - }; 1754 + };
+19
packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/types.gen.ts.snap
··· 280 280 }; 281 281 282 282 /** 283 + * This is a simple enum with strings 284 + */ 285 + export type foo_bar_enum = 'Success' | 'Warning' | 'Error' | 'ØÆÅ字符串'; 286 + 287 + /** 283 288 * This is a model with one enum 284 289 */ 285 290 export type ModelWithEnum = { ··· 298 303 }; 299 304 300 305 /** 306 + * These are the HTTP error code enums 307 + */ 308 + export type statusCode = '100' | '200 FOO' | '300 FOO_BAR' | '400 foo-bar' | '500 foo.bar' | '600 foo&bar'; 309 + 310 + /** 301 311 * This is a model with one enum with escaped name 302 312 */ 303 313 export type ModelWithEnumWithHyphen = { 304 314 'foo-bar-baz-qux'?: '3.0'; 305 315 }; 316 + 317 + export type foo_bar_baz_qux = '3.0'; 306 318 307 319 /** 308 320 * This is a model with one enum ··· 716 728 foo: 'Corge'; 717 729 }; 718 730 731 + export type foo = 'Bar'; 732 + 719 733 export type ModelWithNestedArrayEnumsDataFoo = 'foo' | 'bar'; 720 734 721 735 export type ModelWithNestedArrayEnumsDataBar = 'baz' | 'qux'; ··· 773 787 */ 774 788 value?: -10 | -1 | 0 | 1 | 3 | 6 | 12; 775 789 }; 790 + 791 + /** 792 + * Период 793 + */ 794 + export type value = -10 | -1 | 0 | 1 | 3 | 6 | 12; 776 795 777 796 /** 778 797 * Some description with `back ticks`
+19
packages/openapi-ts/test/__snapshots__/test/generated/v3_client/types.gen.ts.snap
··· 280 280 }; 281 281 282 282 /** 283 + * This is a simple enum with strings 284 + */ 285 + export type foo_bar_enum = 'Success' | 'Warning' | 'Error' | 'ØÆÅ字符串'; 286 + 287 + /** 283 288 * This is a model with one enum 284 289 */ 285 290 export type ModelWithEnum = { ··· 298 303 }; 299 304 300 305 /** 306 + * These are the HTTP error code enums 307 + */ 308 + export type statusCode = '100' | '200 FOO' | '300 FOO_BAR' | '400 foo-bar' | '500 foo.bar' | '600 foo&bar'; 309 + 310 + /** 301 311 * This is a model with one enum with escaped name 302 312 */ 303 313 export type ModelWithEnumWithHyphen = { 304 314 'foo-bar-baz-qux'?: '3.0'; 305 315 }; 316 + 317 + export type foo_bar_baz_qux = '3.0'; 306 318 307 319 /** 308 320 * This is a model with one enum ··· 716 728 foo: 'Corge'; 717 729 }; 718 730 731 + export type foo = 'Bar'; 732 + 719 733 export type ModelWithNestedArrayEnumsDataFoo = 'foo' | 'bar'; 720 734 721 735 export type ModelWithNestedArrayEnumsDataBar = 'baz' | 'qux'; ··· 773 787 */ 774 788 value?: -10 | -1 | 0 | 1 | 3 | 6 | 12; 775 789 }; 790 + 791 + /** 792 + * Период 793 + */ 794 + export type value = -10 | -1 | 0 | 1 | 3 | 6 | 12; 776 795 777 796 /** 778 797 * Some description with `back ticks`
+43
packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/types.gen.ts.snap
··· 326 326 }; 327 327 328 328 /** 329 + * This is a simple enum with strings 330 + */ 331 + export enum foo_bar_enum { 332 + SUCCESS = 'Success', 333 + WARNING = 'Warning', 334 + ERROR = 'Error', 335 + ØÆÅ字符串 = 'ØÆÅ字符串' 336 + } 337 + 338 + /** 329 339 * This is a model with one enum 330 340 */ 331 341 export type ModelWithEnum = { ··· 344 354 }; 345 355 346 356 /** 357 + * These are the HTTP error code enums 358 + */ 359 + export enum statusCode { 360 + _100 = '100', 361 + _200_FOO = '200 FOO', 362 + _300_FOO_BAR = '300 FOO_BAR', 363 + _400_FOO_BAR = '400 foo-bar', 364 + _500_FOO_BAR = '500 foo.bar', 365 + _600_FOO_BAR = '600 foo&bar' 366 + } 367 + 368 + /** 347 369 * This is a model with one enum with escaped name 348 370 */ 349 371 export type ModelWithEnumWithHyphen = { 350 372 'foo-bar-baz-qux'?: '3.0'; 351 373 }; 374 + 375 + export enum foo_bar_baz_qux { 376 + _3_0 = '3.0' 377 + } 352 378 353 379 /** 354 380 * This is a model with one enum ··· 765 791 foo: 'Corge'; 766 792 }; 767 793 794 + export enum foo { 795 + BAR = 'Bar' 796 + } 797 + 768 798 export enum ModelWithNestedArrayEnumsDataFoo { 769 799 FOO = 'foo', 770 800 BAR = 'bar' ··· 828 858 */ 829 859 value?: -10 | -1 | 0 | 1 | 3 | 6 | 12; 830 860 }; 861 + 862 + /** 863 + * Период 864 + */ 865 + export enum value { 866 + '_-10' = -10, 867 + '_-1' = -1, 868 + '_0' = 0, 869 + '_1' = 1, 870 + '_3' = 3, 871 + '_6' = 6, 872 + '_12' = 12 873 + } 831 874 832 875 /** 833 876 * Some description with `back ticks`
+14 -14
packages/openapi-ts/test/__snapshots__/test/generated/v3_legacy_positional_args/types.gen.ts.snap
··· 24 24 /** 25 25 * This is a simple boolean with default value 26 26 */ 27 - parameterBoolean: boolean | null; 27 + parameterBoolean?: boolean | null; 28 28 /** 29 29 * This is a simple enum with default value 30 30 */ 31 - parameterEnum: 'Success' | 'Warning' | 'Error'; 31 + parameterEnum?: 'Success' | 'Warning' | 'Error'; 32 32 /** 33 33 * This is a simple model with default value 34 34 */ 35 - parameterModel: ModelWithString | null; 35 + parameterModel?: ModelWithString | null; 36 36 /** 37 37 * This is a simple number with default value 38 38 */ 39 - parameterNumber: number | null; 39 + parameterNumber?: number | null; 40 40 /** 41 41 * This is a simple string with default value 42 42 */ 43 - parameterString: string | null; 43 + parameterString?: string | null; 44 44 }; 45 45 46 46 export type CallWithDefaultOptionalParametersData = { 47 47 /** 48 48 * This is a simple boolean that is optional with default value 49 49 */ 50 - parameterBoolean: boolean; 50 + parameterBoolean?: boolean; 51 51 /** 52 52 * This is a simple enum that is optional with default value 53 53 */ 54 - parameterEnum: 'Success' | 'Warning' | 'Error'; 54 + parameterEnum?: 'Success' | 'Warning' | 'Error'; 55 55 /** 56 56 * This is a simple model that is optional with default value 57 57 */ 58 - parameterModel: ModelWithString; 58 + parameterModel?: ModelWithString; 59 59 /** 60 60 * This is a simple number that is optional with default value 61 61 */ 62 - parameterNumber: number; 62 + parameterNumber?: number; 63 63 /** 64 64 * This is a simple string that is optional with default value 65 65 */ 66 - parameterString: string; 66 + parameterString?: string; 67 67 }; 68 68 69 69 export type CallToTestOrderOfParamsData = { 70 70 /** 71 71 * This is a optional string with default 72 72 */ 73 - parameterOptionalStringWithDefault: string; 73 + parameterOptionalStringWithDefault?: string; 74 74 /** 75 75 * This is a optional string with empty default 76 76 */ 77 - parameterOptionalStringWithEmptyDefault: string; 77 + parameterOptionalStringWithEmptyDefault?: string; 78 78 /** 79 79 * This is a optional string with no default 80 80 */ ··· 82 82 /** 83 83 * This is a string that can be null with default 84 84 */ 85 - parameterStringNullableWithDefault: string | null; 85 + parameterStringNullableWithDefault?: string | null; 86 86 /** 87 87 * This is a string that can be null with no default 88 88 */ ··· 113 113 req: CallToTestOrderOfParamsData; 114 114 }; 115 115 }; 116 - }; 116 + };
+19
packages/openapi-ts/test/__snapshots__/test/generated/v3_models/types.gen.ts.snap
··· 280 280 }; 281 281 282 282 /** 283 + * This is a simple enum with strings 284 + */ 285 + export type foo_bar_enum = 'Success' | 'Warning' | 'Error' | 'ØÆÅ字符串'; 286 + 287 + /** 283 288 * This is a model with one enum 284 289 */ 285 290 export type ModelWithEnum = { ··· 298 303 }; 299 304 300 305 /** 306 + * These are the HTTP error code enums 307 + */ 308 + export type statusCode = '100' | '200 FOO' | '300 FOO_BAR' | '400 foo-bar' | '500 foo.bar' | '600 foo&bar'; 309 + 310 + /** 301 311 * This is a model with one enum with escaped name 302 312 */ 303 313 export type ModelWithEnumWithHyphen = { 304 314 'foo-bar-baz-qux'?: '3.0'; 305 315 }; 316 + 317 + export type foo_bar_baz_qux = '3.0'; 306 318 307 319 /** 308 320 * This is a model with one enum ··· 716 728 foo: 'Corge'; 717 729 }; 718 730 731 + export type foo = 'Bar'; 732 + 719 733 export type ModelWithNestedArrayEnumsDataFoo = 'foo' | 'bar'; 720 734 721 735 export type ModelWithNestedArrayEnumsDataBar = 'baz' | 'qux'; ··· 773 787 */ 774 788 value?: -10 | -1 | 0 | 1 | 3 | 6 | 12; 775 789 }; 790 + 791 + /** 792 + * Период 793 + */ 794 + export type value = -10 | -1 | 0 | 1 | 3 | 6 | 12; 776 795 777 796 /** 778 797 * Some description with `back ticks`
-34
packages/openapi-ts/test/bin.spec.ts
··· 139 139 expect(result.stderr.toString()).toBe(''); 140 140 }); 141 141 142 - it('formats output with Prettier', () => { 143 - const result = sync('node', [ 144 - './bin/index.cjs', 145 - '--input', 146 - './test/spec/v3.json', 147 - '--output', 148 - './test/generated/bin', 149 - '--format', 150 - 'prettier', 151 - ]); 152 - expect(result.stdout.toString()).toContain('Prettier'); 153 - expect(result.stderr.toString()).toBe(''); 154 - }); 155 - 156 - it('lints output with ESLint', () => { 157 - const result = sync('node', [ 158 - './bin/index.cjs', 159 - '--input', 160 - './test/spec/v3.json', 161 - '--output', 162 - './test/generated/bin', 163 - '--lint', 164 - 'eslint', 165 - ]); 166 - expect(result.stdout.toString()).toContain('ESLint'); 167 - expect(result.stderr.toString()).toBe(''); 168 - }); 169 - 170 142 it('throws error without parameters', () => { 171 143 const result = sync('node', ['./bin/index.cjs', '--dry-run', 'true']); 172 144 expect(result.stdout.toString()).toBe(''); ··· 221 193 'false', 222 194 '--services', 223 195 'false', 224 - '--format', 225 - 'false', 226 - '--lint', 227 - 'false', 228 196 '--useOptions', 229 197 'false', 230 198 '--dry-run', ··· 235 203 expect(result.stderr.toString()).toContain('exportCore: false'); 236 204 expect(result.stderr.toString()).toContain('types: false'); 237 205 expect(result.stderr.toString()).toContain('services: false'); 238 - expect(result.stderr.toString()).toContain('format: false'); 239 - expect(result.stderr.toString()).toContain('lint: false'); 240 206 expect(result.stderr.toString()).toContain('schemas: false'); 241 207 expect(result.stderr.toString()).toContain('useOptions: false'); 242 208 });
+9 -5
packages/openapi-ts/test/sample.cjs
··· 5 5 const config = { 6 6 client: 'fetch', 7 7 input: './test/spec/v3.json', 8 - output: './test/generated/v3/', 8 + // input: 'https://mongodb-mms-prod-build-server.s3.amazonaws.com/openapi/2caffd88277a4e27c95dcefc7e3b6a63a3b03297-v2-2023-11-15.json', 9 + output: { 10 + path: './test/generated/v3/', 11 + }, 9 12 schemas: { 10 - // export: false, 13 + export: false, 11 14 }, 12 15 services: { 13 - // export: false, 16 + export: false, 14 17 }, 15 18 types: { 16 - // enums: 'javascript', 17 - // include: '^NestedAnyOfArraysNullable', 19 + enums: 'typescript', 20 + // include: '^CloudProvider', 18 21 // name: 'PascalCase', 19 22 }, 23 + // useOptions: false, 20 24 }; 21 25 22 26 const { createClient } = await import(
+219 -219
pnpm-lock.yaml
··· 24 24 specifier: 1.1.0 25 25 version: 1.1.0 26 26 '@types/node': 27 - specifier: 20.12.8 28 - version: 20.12.8 27 + specifier: 20.12.11 28 + version: 20.12.11 29 29 '@vitest/coverage-v8': 30 30 specifier: 1.6.0 31 31 version: 1.6.0(vitest@1.6.0) ··· 42 42 specifier: 1.1.2 43 43 version: 1.1.2 44 44 globals: 45 - specifier: 15.1.0 46 - version: 15.1.0 45 + specifier: 15.2.0 46 + version: 15.2.0 47 47 husky: 48 48 specifier: 9.0.11 49 49 version: 9.0.11 ··· 54 54 specifier: 3.2.5 55 55 version: 3.2.5 56 56 rimraf: 57 - specifier: 5.0.5 58 - version: 5.0.5 57 + specifier: 5.0.7 58 + version: 5.0.7 59 59 rollup: 60 60 specifier: 4.17.2 61 61 version: 4.17.2 ··· 70 70 version: 7.8.0(eslint@9.2.0)(typescript@5.4.5) 71 71 vitest: 72 72 specifier: 1.6.0 73 - version: 1.6.0(@types/node@20.12.8) 73 + version: 1.6.0(@types/node@20.12.11) 74 74 75 75 docs: 76 76 dependencies: 77 77 '@stackblitz/sdk': 78 - specifier: 1.9.0 79 - version: 1.9.0 78 + specifier: 1.10.0 79 + version: 1.10.0 80 80 devDependencies: 81 81 vitepress: 82 82 specifier: 1.1.4 83 - version: 1.1.4(@algolia/client-search@4.23.3)(@types/node@20.12.8)(search-insights@2.13.0)(typescript@5.4.5) 83 + version: 1.1.4(@algolia/client-search@4.23.3)(@types/node@20.12.11)(search-insights@2.13.0)(typescript@5.4.5) 84 84 85 85 examples/openapi-ts-axios: 86 86 dependencies: ··· 101 101 specifier: workspace:* 102 102 version: link:../../packages/openapi-ts 103 103 '@types/react': 104 - specifier: 18.3.1 105 - version: 18.3.1 104 + specifier: 18.3.2 105 + version: 18.3.2 106 106 '@types/react-dom': 107 107 specifier: 18.3.0 108 108 version: 18.3.0 ··· 122 122 specifier: 4.6.2 123 123 version: 4.6.2(eslint@9.2.0) 124 124 eslint-plugin-react-refresh: 125 - specifier: 0.4.6 126 - version: 0.4.6(eslint@9.2.0) 125 + specifier: 0.4.7 126 + version: 0.4.7(eslint@9.2.0) 127 127 prettier: 128 128 specifier: 3.2.5 129 129 version: 3.2.5 ··· 132 132 version: 5.4.5 133 133 vite: 134 134 specifier: 5.2.11 135 - version: 5.2.11(@types/node@20.12.8) 135 + version: 5.2.11(@types/node@20.12.11) 136 136 137 137 examples/openapi-ts-fetch: 138 138 dependencies: ··· 150 150 specifier: workspace:* 151 151 version: link:../../packages/openapi-ts 152 152 '@types/react': 153 - specifier: 18.3.1 154 - version: 18.3.1 153 + specifier: 18.3.2 154 + version: 18.3.2 155 155 '@types/react-dom': 156 156 specifier: 18.3.0 157 157 version: 18.3.0 ··· 171 171 specifier: 4.6.2 172 172 version: 4.6.2(eslint@9.2.0) 173 173 eslint-plugin-react-refresh: 174 - specifier: 0.4.6 175 - version: 0.4.6(eslint@9.2.0) 174 + specifier: 0.4.7 175 + version: 0.4.7(eslint@9.2.0) 176 176 prettier: 177 177 specifier: 3.2.5 178 178 version: 3.2.5 ··· 181 181 version: 5.4.5 182 182 vite: 183 183 specifier: 5.2.11 184 - version: 5.2.11(@types/node@20.12.8) 184 + version: 5.2.11(@types/node@20.12.11) 185 185 186 186 packages/client-axios: 187 187 dependencies: ··· 216 216 version: 4.7.8 217 217 devDependencies: 218 218 '@angular-devkit/build-angular': 219 - specifier: 17.3.6 220 - version: 17.3.6(@angular/compiler-cli@17.3.7)(@types/express@4.17.21)(@types/node@20.12.8)(typescript@5.4.5) 219 + specifier: 17.3.7 220 + version: 17.3.7(@angular/compiler-cli@17.3.8)(@types/express@4.17.21)(@types/node@20.12.11)(typescript@5.4.5) 221 221 '@angular/animations': 222 + specifier: 17.3.8 223 + version: 17.3.8(@angular/core@17.3.8) 224 + '@angular/cli': 222 225 specifier: 17.3.7 223 - version: 17.3.7(@angular/core@17.3.7) 224 - '@angular/cli': 225 - specifier: 17.3.6 226 - version: 17.3.6 226 + version: 17.3.7 227 227 '@angular/common': 228 - specifier: 17.3.7 229 - version: 17.3.7(@angular/core@17.3.7)(rxjs@7.8.1) 228 + specifier: 17.3.8 229 + version: 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) 230 230 '@angular/compiler': 231 - specifier: 17.3.7 232 - version: 17.3.7(@angular/core@17.3.7) 231 + specifier: 17.3.8 232 + version: 17.3.8(@angular/core@17.3.8) 233 233 '@angular/compiler-cli': 234 - specifier: 17.3.7 235 - version: 17.3.7(@angular/compiler@17.3.7)(typescript@5.4.5) 234 + specifier: 17.3.8 235 + version: 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) 236 236 '@angular/core': 237 - specifier: 17.3.7 238 - version: 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 237 + specifier: 17.3.8 238 + version: 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 239 239 '@angular/forms': 240 - specifier: 17.3.7 241 - version: 17.3.7(@angular/common@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7)(rxjs@7.8.1) 240 + specifier: 17.3.8 241 + version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) 242 242 '@angular/platform-browser': 243 - specifier: 17.3.7 244 - version: 17.3.7(@angular/animations@17.3.7)(@angular/common@17.3.7)(@angular/core@17.3.7) 243 + specifier: 17.3.8 244 + version: 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) 245 245 '@angular/platform-browser-dynamic': 246 - specifier: 17.3.7 247 - version: 17.3.7(@angular/common@17.3.7)(@angular/compiler@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7) 246 + specifier: 17.3.8 247 + version: 17.3.8(@angular/common@17.3.8)(@angular/compiler@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8) 248 248 '@angular/router': 249 - specifier: 17.3.7 250 - version: 17.3.7(@angular/common@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7)(rxjs@7.8.1) 249 + specifier: 17.3.8 250 + version: 17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1) 251 251 '@rollup/plugin-json': 252 252 specifier: 6.1.0 253 253 version: 6.1.0(rollup@4.17.2) ··· 273 273 specifier: 4.19.2 274 274 version: 4.19.2 275 275 glob: 276 - specifier: 10.3.12 277 - version: 10.3.12 276 + specifier: 10.3.15 277 + version: 10.3.15 278 278 node-fetch: 279 279 specifier: 3.3.2 280 280 version: 3.3.2 ··· 282 282 specifier: 3.2.5 283 283 version: 3.2.5 284 284 puppeteer: 285 - specifier: 22.7.1 286 - version: 22.7.1(typescript@5.4.5) 285 + specifier: 22.8.0 286 + version: 22.8.0(typescript@5.4.5) 287 287 rxjs: 288 288 specifier: 7.8.1 289 289 version: 7.8.1 290 290 ts-node: 291 291 specifier: 10.9.2 292 - version: 10.9.2(@types/node@20.12.8)(typescript@5.4.5) 292 + version: 10.9.2(@types/node@20.12.11)(typescript@5.4.5) 293 293 tslib: 294 294 specifier: 2.6.2 295 295 version: 2.6.2 ··· 457 457 '@jridgewell/trace-mapping': 0.3.25 458 458 dev: true 459 459 460 - /@angular-devkit/architect@0.1703.6: 461 - resolution: {integrity: sha512-Ck501FD/QuOjeKVFs7hU92w8+Ffetv0d5Sq09XY2/uygo5c/thMzp9nkevaIWBxUSeU5RqYZizDrhFVgYzbbOw==} 460 + /@angular-devkit/architect@0.1703.7: 461 + resolution: {integrity: sha512-SwXbdsZqEE3JtvujCLChAii+FA20d1931VDjDYffrGWdQEViTBAr4NKtDr/kOv8KkgiL3fhGibPnRNUHTeAMtg==} 462 462 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 463 463 dependencies: 464 - '@angular-devkit/core': 17.3.6 464 + '@angular-devkit/core': 17.3.7 465 465 rxjs: 7.8.1 466 466 transitivePeerDependencies: 467 467 - chokidar 468 468 dev: true 469 469 470 - /@angular-devkit/build-angular@17.3.6(@angular/compiler-cli@17.3.7)(@types/express@4.17.21)(@types/node@20.12.8)(typescript@5.4.5): 471 - resolution: {integrity: sha512-K4CEZvhQZUUOpmXPVoI1YBM8BARbIlqE6FZRxakmnr+YOtVTYE5s+Dr1wgja8hZIohNz6L7j167G9Aut7oPU/w==} 470 + /@angular-devkit/build-angular@17.3.7(@angular/compiler-cli@17.3.8)(@types/express@4.17.21)(@types/node@20.12.11)(typescript@5.4.5): 471 + resolution: {integrity: sha512-AsV80kiFMIPIhm3uzJgOHDj4u6JteUkZedPTKAFFFJC7CTat1luW5qx306vfF7wj62aMvUl5g9HFWaeLghTQGA==} 472 472 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 473 473 peerDependencies: 474 474 '@angular/compiler-cli': ^17.0.0 ··· 509 509 optional: true 510 510 dependencies: 511 511 '@ampproject/remapping': 2.3.0 512 - '@angular-devkit/architect': 0.1703.6 513 - '@angular-devkit/build-webpack': 0.1703.6(webpack-dev-server@4.15.1)(webpack@5.90.3) 514 - '@angular-devkit/core': 17.3.6 515 - '@angular/compiler-cli': 17.3.7(@angular/compiler@17.3.7)(typescript@5.4.5) 512 + '@angular-devkit/architect': 0.1703.7 513 + '@angular-devkit/build-webpack': 0.1703.7(webpack-dev-server@4.15.1)(webpack@5.90.3) 514 + '@angular-devkit/core': 17.3.7 515 + '@angular/compiler-cli': 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) 516 516 '@babel/core': 7.24.0 517 517 '@babel/generator': 7.23.6 518 518 '@babel/helper-annotate-as-pure': 7.22.5 ··· 523 523 '@babel/preset-env': 7.24.0(@babel/core@7.24.0) 524 524 '@babel/runtime': 7.24.0 525 525 '@discoveryjs/json-ext': 0.5.7 526 - '@ngtools/webpack': 17.3.6(@angular/compiler-cli@17.3.7)(typescript@5.4.5)(webpack@5.90.3) 526 + '@ngtools/webpack': 17.3.7(@angular/compiler-cli@17.3.8)(typescript@5.4.5)(webpack@5.90.3) 527 527 '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.1.7) 528 528 ansi-colors: 4.1.3 529 529 autoprefixer: 10.4.18(postcss@8.4.35) ··· 566 566 tslib: 2.6.2 567 567 typescript: 5.4.5 568 568 undici: 6.11.1 569 - vite: 5.1.7(@types/node@20.12.8)(less@4.2.0)(sass@1.71.1)(terser@5.29.1) 569 + vite: 5.1.7(@types/node@20.12.11)(less@4.2.0)(sass@1.71.1)(terser@5.29.1) 570 570 watchpack: 2.4.0 571 571 webpack: 5.90.3(esbuild@0.20.1) 572 572 webpack-dev-middleware: 6.1.2(webpack@5.90.3) ··· 595 595 - webpack-cli 596 596 dev: true 597 597 598 - /@angular-devkit/build-webpack@0.1703.6(webpack-dev-server@4.15.1)(webpack@5.90.3): 599 - resolution: {integrity: sha512-pJu0et2SiF0kfXenHSTtAART0omzbWpLgBfeUo4hBh4uwX5IaT+mRpYpr8gCXMq+qsjoQp3HobSU3lPDeBn+bg==} 598 + /@angular-devkit/build-webpack@0.1703.7(webpack-dev-server@4.15.1)(webpack@5.90.3): 599 + resolution: {integrity: sha512-gpt2Ia5I1gmdp3hdbtB7tkZTba5qWmKeVhlCYswa/LvbceKmkjedoeNRAoyr1UKM9GeGqt6Xl1B2eHzCH+ykrg==} 600 600 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 601 601 peerDependencies: 602 602 webpack: ^5.30.0 603 603 webpack-dev-server: ^4.0.0 604 604 dependencies: 605 - '@angular-devkit/architect': 0.1703.6 605 + '@angular-devkit/architect': 0.1703.7 606 606 rxjs: 7.8.1 607 607 webpack: 5.90.3(esbuild@0.20.1) 608 608 webpack-dev-server: 4.15.1(webpack@5.90.3) ··· 610 610 - chokidar 611 611 dev: true 612 612 613 - /@angular-devkit/core@17.3.6: 614 - resolution: {integrity: sha512-FVbkT9dEwHEvjnxr4mvMNSMg2bCFoGoP4X68xXU9dhLEUpC05opLvfbaR3Qh543eCJ5AstosBFVzB/krfIkOvA==} 613 + /@angular-devkit/core@17.3.7: 614 + resolution: {integrity: sha512-qpZ7BShyqS/Jqld36E7kL02cyb2pjn1Az1p9439SbP8nsvJgYlsyjwYK2Kmcn/Wi+TZGIKxkqxgBBw9vqGgeJw==} 615 615 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 616 616 peerDependencies: 617 617 chokidar: ^3.5.2 ··· 627 627 source-map: 0.7.4 628 628 dev: true 629 629 630 - /@angular-devkit/schematics@17.3.6: 631 - resolution: {integrity: sha512-2G1YuPInd8znG7uUgKOS7z72Aku50lTzB/2csWkWPJLAFkh7vKC8QZ40x8S1nC9npVYPhI5CRLX/HVpBh9CyxA==} 630 + /@angular-devkit/schematics@17.3.7: 631 + resolution: {integrity: sha512-d7NKSwstdxYLYmPsbcYO3GOFNfXxXwOyHxSqDa1JNKoSzMdbLj4tvlCpfXw0ThNM7gioMx8aLBaaH1ac+yk06Q==} 632 632 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 633 633 dependencies: 634 - '@angular-devkit/core': 17.3.6 634 + '@angular-devkit/core': 17.3.7 635 635 jsonc-parser: 3.2.1 636 636 magic-string: 0.30.8 637 637 ora: 5.4.1 ··· 640 640 - chokidar 641 641 dev: true 642 642 643 - /@angular/animations@17.3.7(@angular/core@17.3.7): 644 - resolution: {integrity: sha512-ahenGALPPweeHgqtl9BMkGIAV4fUNI5kOWUrLNbKBfwIJN+aOBOYV1Jz6NKUQq6eYn/1ZYtm0f3lIkHIdtLKEw==} 643 + /@angular/animations@17.3.8(@angular/core@17.3.8): 644 + resolution: {integrity: sha512-ywT3dH0yZeAlo+Vu/6RpRozxzTbu4Bwqky6RgNfk/UMoyXZ5UiFStszDqO/HAyBGGCDHagm1XJkgsNZcStWq8A==} 645 645 engines: {node: ^18.13.0 || >=20.9.0} 646 646 peerDependencies: 647 - '@angular/core': 17.3.7 647 + '@angular/core': 17.3.8 648 648 dependencies: 649 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 649 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 650 650 tslib: 2.6.2 651 651 dev: true 652 652 653 - /@angular/cli@17.3.6: 654 - resolution: {integrity: sha512-poKaRPeI+hFqX+AxIaEriaIggFVcC3XqlT9E1/uBC2rfHirE1n5F9Z7xqEDtMHduKwLbNXhQIPoKIKya8+Hnew==} 653 + /@angular/cli@17.3.7: 654 + resolution: {integrity: sha512-JgCav3sdRCoJHwLXxmF/EMzArYjwbqB+AGUW/xIR98oZET8QxCB985bOFUAm02SkAEUVcMJvjxec+WCaa60m/A==} 655 655 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 656 656 hasBin: true 657 657 dependencies: 658 - '@angular-devkit/architect': 0.1703.6 659 - '@angular-devkit/core': 17.3.6 660 - '@angular-devkit/schematics': 17.3.6 661 - '@schematics/angular': 17.3.6 658 + '@angular-devkit/architect': 0.1703.7 659 + '@angular-devkit/core': 17.3.7 660 + '@angular-devkit/schematics': 17.3.7 661 + '@schematics/angular': 17.3.7 662 662 '@yarnpkg/lockfile': 1.1.0 663 663 ansi-colors: 4.1.3 664 664 ini: 4.1.2 ··· 679 679 - supports-color 680 680 dev: true 681 681 682 - /@angular/common@17.3.7(@angular/core@17.3.7)(rxjs@7.8.1): 683 - resolution: {integrity: sha512-A7LRJu1vVCGGgrfZXjU+njz50SiU4weheKCar5PIUprcdIofS1IrHAJDqYh+kwXxkjXbZMOr/ijQY0+AESLEsw==} 682 + /@angular/common@17.3.8(@angular/core@17.3.8)(rxjs@7.8.1): 683 + resolution: {integrity: sha512-HEhTibrsWmoKilyhvAFmqg4SH1hWBP3eV9Y689lmsxBQCTRAmRI2pMAoRKQ+dBcoYLE/FZhcmdHJUSl5jR7Isg==} 684 684 engines: {node: ^18.13.0 || >=20.9.0} 685 685 peerDependencies: 686 - '@angular/core': 17.3.7 686 + '@angular/core': 17.3.8 687 687 rxjs: ^6.5.3 || ^7.4.0 688 688 dependencies: 689 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 689 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 690 690 rxjs: 7.8.1 691 691 tslib: 2.6.2 692 692 dev: true 693 693 694 - /@angular/compiler-cli@17.3.7(@angular/compiler@17.3.7)(typescript@5.4.5): 695 - resolution: {integrity: sha512-vSg5IQZ9jGmvYjpbfH8KbH4Sl1IVeE+Mr1ogcxkGEsURSRvKo7EWc0K7LSEI9+gg0VLamMiP9EyCJdPxiJeLJQ==} 694 + /@angular/compiler-cli@17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5): 695 + resolution: {integrity: sha512-/TsbCmk7QJUEEZnRdNzi6znsPfoDJuy6vHDqcwWVEcw7y6W7DjirSFmtT9u1QwrV67KM6kOh22+RvPdGM8sPmg==} 696 696 engines: {node: ^18.13.0 || >=20.9.0} 697 697 hasBin: true 698 698 peerDependencies: 699 - '@angular/compiler': 17.3.7 699 + '@angular/compiler': 17.3.8 700 700 typescript: '>=5.2 <5.5' 701 701 dependencies: 702 - '@angular/compiler': 17.3.7(@angular/core@17.3.7) 702 + '@angular/compiler': 17.3.8(@angular/core@17.3.8) 703 703 '@babel/core': 7.23.9 704 704 '@jridgewell/sourcemap-codec': 1.4.15 705 705 chokidar: 3.6.0 ··· 713 713 - supports-color 714 714 dev: true 715 715 716 - /@angular/compiler@17.3.7(@angular/core@17.3.7): 717 - resolution: {integrity: sha512-AlKiqPoxnrpQ0hn13fIaQPSVodaVAIjBW4vpFyuKFqs2LBKg6iolwZ21s8rEI0KR2gXl+8ugj0/UZ6YADiVM5w==} 716 + /@angular/compiler@17.3.8(@angular/core@17.3.8): 717 + resolution: {integrity: sha512-7vZSh2Oa95lZdRR4MhE0icvZ7JUuYY+NSo3eTSOMZSlH5I9rtwQoSFqfoGW+35rXCzGFLOhQmZBbXkxDPDs97Q==} 718 718 engines: {node: ^18.13.0 || >=20.9.0} 719 719 peerDependencies: 720 - '@angular/core': 17.3.7 720 + '@angular/core': 17.3.8 721 721 peerDependenciesMeta: 722 722 '@angular/core': 723 723 optional: true 724 724 dependencies: 725 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 725 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 726 726 tslib: 2.6.2 727 727 dev: true 728 728 729 - /@angular/core@17.3.7(rxjs@7.8.1)(zone.js@0.14.5): 730 - resolution: {integrity: sha512-HWcrbxqnvIMSxFuQdN0KPt08bc87hqr0LKm89yuRTUwx/2sNJlNQUobk6aJj4trswGBttcRDT+GOS4DQP2Nr4g==} 729 + /@angular/core@17.3.8(rxjs@7.8.1)(zone.js@0.14.5): 730 + resolution: {integrity: sha512-+tUQ+B1yVvNbczzaWBCgJWWIgZ2z+GVJWu+UNOHHWzdqD8qpXjuIkDfnhyLNeGvvXgsqey4u6ApFf2SoFYLjuA==} 731 731 engines: {node: ^18.13.0 || >=20.9.0} 732 732 peerDependencies: 733 733 rxjs: ^6.5.3 || ^7.4.0 ··· 738 738 zone.js: 0.14.5 739 739 dev: true 740 740 741 - /@angular/forms@17.3.7(@angular/common@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7)(rxjs@7.8.1): 742 - resolution: {integrity: sha512-FEhXh/VmT++XCoO8i7bBtzxG7Am/cE1zrr9aF+fWW+4jpWvJvVN1IaSiJxgBB+iPsOJ9lTBRwfRW3onlcDkhrw==} 741 + /@angular/forms@17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1): 742 + resolution: {integrity: sha512-ZoPJMx3O1eKliK6oEUqtKJNqrLwwOLBC5x+zbCHrwJeBB3lbgWXrrnTrFvCXpp3QVERAboZTzZ3XBmHX1o6gmw==} 743 743 engines: {node: ^18.13.0 || >=20.9.0} 744 744 peerDependencies: 745 - '@angular/common': 17.3.7 746 - '@angular/core': 17.3.7 747 - '@angular/platform-browser': 17.3.7 745 + '@angular/common': 17.3.8 746 + '@angular/core': 17.3.8 747 + '@angular/platform-browser': 17.3.8 748 748 rxjs: ^6.5.3 || ^7.4.0 749 749 dependencies: 750 - '@angular/common': 17.3.7(@angular/core@17.3.7)(rxjs@7.8.1) 751 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 752 - '@angular/platform-browser': 17.3.7(@angular/animations@17.3.7)(@angular/common@17.3.7)(@angular/core@17.3.7) 750 + '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) 751 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 752 + '@angular/platform-browser': 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) 753 753 rxjs: 7.8.1 754 754 tslib: 2.6.2 755 755 dev: true 756 756 757 - /@angular/platform-browser-dynamic@17.3.7(@angular/common@17.3.7)(@angular/compiler@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7): 758 - resolution: {integrity: sha512-9c2I4u0L1p2v1/lW8qy+WaNHisUWbyy6wqsv2v9FfCaSM49Lxymgo9LPFPC4qEG5ei5nE+eIQ2ocRiXXsf5QkQ==} 757 + /@angular/platform-browser-dynamic@17.3.8(@angular/common@17.3.8)(@angular/compiler@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8): 758 + resolution: {integrity: sha512-uL6FPh+Pr9xzIjyiv3p66jteq/CytHP1+m5jOsIKa1LUwTXx0a2pmOYcZxXpNkQGR9Ir/dlbrYmKlSP3QZf7uw==} 759 759 engines: {node: ^18.13.0 || >=20.9.0} 760 760 peerDependencies: 761 - '@angular/common': 17.3.7 762 - '@angular/compiler': 17.3.7 763 - '@angular/core': 17.3.7 764 - '@angular/platform-browser': 17.3.7 761 + '@angular/common': 17.3.8 762 + '@angular/compiler': 17.3.8 763 + '@angular/core': 17.3.8 764 + '@angular/platform-browser': 17.3.8 765 765 dependencies: 766 - '@angular/common': 17.3.7(@angular/core@17.3.7)(rxjs@7.8.1) 767 - '@angular/compiler': 17.3.7(@angular/core@17.3.7) 768 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 769 - '@angular/platform-browser': 17.3.7(@angular/animations@17.3.7)(@angular/common@17.3.7)(@angular/core@17.3.7) 766 + '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) 767 + '@angular/compiler': 17.3.8(@angular/core@17.3.8) 768 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 769 + '@angular/platform-browser': 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) 770 770 tslib: 2.6.2 771 771 dev: true 772 772 773 - /@angular/platform-browser@17.3.7(@angular/animations@17.3.7)(@angular/common@17.3.7)(@angular/core@17.3.7): 774 - resolution: {integrity: sha512-Nn8ZMaftAvO9dEwribWdNv+QBHhYIBrRkv85G6et80AXfXoYAr/xcfnQECRFtZgPmANqHC5auv/xrmExQG+Yeg==} 773 + /@angular/platform-browser@17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8): 774 + resolution: {integrity: sha512-UMGSV3TdJqMtf2xvhbW6fx8TKJLOoHQgFxohhy3y8GvxHBu+PUyrwhovb7r03bs+muY6u4ygGCMm7Mt1TFVwfQ==} 775 775 engines: {node: ^18.13.0 || >=20.9.0} 776 776 peerDependencies: 777 - '@angular/animations': 17.3.7 778 - '@angular/common': 17.3.7 779 - '@angular/core': 17.3.7 777 + '@angular/animations': 17.3.8 778 + '@angular/common': 17.3.8 779 + '@angular/core': 17.3.8 780 780 peerDependenciesMeta: 781 781 '@angular/animations': 782 782 optional: true 783 783 dependencies: 784 - '@angular/animations': 17.3.7(@angular/core@17.3.7) 785 - '@angular/common': 17.3.7(@angular/core@17.3.7)(rxjs@7.8.1) 786 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 784 + '@angular/animations': 17.3.8(@angular/core@17.3.8) 785 + '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) 786 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 787 787 tslib: 2.6.2 788 788 dev: true 789 789 790 - /@angular/router@17.3.7(@angular/common@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7)(rxjs@7.8.1): 791 - resolution: {integrity: sha512-lMkuRrc1ZjP5JPDxNHqoAhB0uAnfPQ/q6mJrw1s8IZoVV6VyM+FxR5r13ajNcXWC38xy/YhBjpXPF1vBdxuLXg==} 790 + /@angular/router@17.3.8(@angular/common@17.3.8)(@angular/core@17.3.8)(@angular/platform-browser@17.3.8)(rxjs@7.8.1): 791 + resolution: {integrity: sha512-2JKTW1u1H+iNDfAmIjEiMJjQHfzb97TBk23/euIR0JuyGHjyywkrQ97HHiOEAJyy/Zpr0Vbem3HRqDqSfjTWvg==} 792 792 engines: {node: ^18.13.0 || >=20.9.0} 793 793 peerDependencies: 794 - '@angular/common': 17.3.7 795 - '@angular/core': 17.3.7 796 - '@angular/platform-browser': 17.3.7 794 + '@angular/common': 17.3.8 795 + '@angular/core': 17.3.8 796 + '@angular/platform-browser': 17.3.8 797 797 rxjs: ^6.5.3 || ^7.4.0 798 798 dependencies: 799 - '@angular/common': 17.3.7(@angular/core@17.3.7)(rxjs@7.8.1) 800 - '@angular/core': 17.3.7(rxjs@7.8.1)(zone.js@0.14.5) 801 - '@angular/platform-browser': 17.3.7(@angular/animations@17.3.7)(@angular/common@17.3.7)(@angular/core@17.3.7) 799 + '@angular/common': 17.3.8(@angular/core@17.3.8)(rxjs@7.8.1) 800 + '@angular/core': 17.3.8(rxjs@7.8.1)(zone.js@0.14.5) 801 + '@angular/platform-browser': 17.3.8(@angular/animations@17.3.8)(@angular/common@17.3.8)(@angular/core@17.3.8) 802 802 rxjs: 7.8.1 803 803 tslib: 2.6.2 804 804 dev: true ··· 3132 3132 read-yaml-file: 1.1.0 3133 3133 dev: true 3134 3134 3135 - /@ngtools/webpack@17.3.6(@angular/compiler-cli@17.3.7)(typescript@5.4.5)(webpack@5.90.3): 3136 - resolution: {integrity: sha512-equxbgh2DKzZtiFMoVf1KD4yJcH1q8lpqQ/GSPPQUvONcmHrr+yqdRUdaJ7oZCyCYmXF/nByBxtMKtJr6nKZVg==} 3135 + /@ngtools/webpack@17.3.7(@angular/compiler-cli@17.3.8)(typescript@5.4.5)(webpack@5.90.3): 3136 + resolution: {integrity: sha512-kQNS68jsPQlaWAnKcVeFKNHp6K90uQANvq+9oXb/i+JnYWzuBsHzn2r8bVdMmvjd1HdBRiGtg767XRk3u+jgRw==} 3137 3137 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 3138 3138 peerDependencies: 3139 3139 '@angular/compiler-cli': ^17.0.0 3140 3140 typescript: '>=5.2 <5.5' 3141 3141 webpack: ^5.54.0 3142 3142 dependencies: 3143 - '@angular/compiler-cli': 17.3.7(@angular/compiler@17.3.7)(typescript@5.4.5) 3143 + '@angular/compiler-cli': 17.3.8(@angular/compiler@17.3.8)(typescript@5.4.5) 3144 3144 typescript: 5.4.5 3145 3145 webpack: 5.90.3(esbuild@0.20.1) 3146 3146 dev: true ··· 3173 3173 agent-base: 7.1.1 3174 3174 http-proxy-agent: 7.0.2 3175 3175 https-proxy-agent: 7.0.4 3176 - lru-cache: 10.2.0 3176 + lru-cache: 10.2.2 3177 3177 socks-proxy-agent: 8.0.3 3178 3178 transitivePeerDependencies: 3179 3179 - supports-color ··· 3191 3191 engines: {node: ^16.14.0 || >=18.0.0} 3192 3192 dependencies: 3193 3193 '@npmcli/promise-spawn': 7.0.1 3194 - lru-cache: 10.2.0 3194 + lru-cache: 10.2.2 3195 3195 npm-pick-manifest: 9.0.0 3196 3196 proc-log: 4.2.0 3197 3197 promise-inflight: 1.0.1 ··· 3221 3221 engines: {node: ^16.14.0 || >=18.0.0} 3222 3222 dependencies: 3223 3223 '@npmcli/git': 5.0.6 3224 - glob: 10.3.12 3224 + glob: 10.3.15 3225 3225 hosted-git-info: 7.0.1 3226 3226 json-parse-even-better-errors: 3.0.1 3227 3227 normalize-package-data: 6.0.0 ··· 3507 3507 dev: true 3508 3508 optional: true 3509 3509 3510 - /@schematics/angular@17.3.6: 3511 - resolution: {integrity: sha512-jCNZdjHSVrI8TrrCnCoXC8GYvQRj7zh+SDdmm91Ve8dbikYNmBOKYLuPaCTsmojWx7ytv962yLlgKzpaa2bbfw==} 3510 + /@schematics/angular@17.3.7: 3511 + resolution: {integrity: sha512-HaJroKaberriP4wFefTTSVFrtU9GMvnG3I6ELbOteOyKMH7o2V91FXGJDJ5KnIiLRlBmC30G3r+9Ybc/rtAYkw==} 3512 3512 engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} 3513 3513 dependencies: 3514 - '@angular-devkit/core': 17.3.6 3515 - '@angular-devkit/schematics': 17.3.6 3514 + '@angular-devkit/core': 17.3.7 3515 + '@angular-devkit/schematics': 17.3.7 3516 3516 jsonc-parser: 3.2.1 3517 3517 transitivePeerDependencies: 3518 3518 - chokidar ··· 3580 3580 resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} 3581 3581 dev: true 3582 3582 3583 - /@stackblitz/sdk@1.9.0: 3584 - resolution: {integrity: sha512-3m6C7f8pnR5KXys/Hqx2x6ylnpqOak6HtnZI6T5keEO0yT+E4Spkw37VEbdwuC+2oxmjdgq6YZEgiKX7hM1GmQ==} 3583 + /@stackblitz/sdk@1.10.0: 3584 + resolution: {integrity: sha512-IcvE9Xifo2c4/f+yNqjFM/OW5VTBPLed3TxsQ+n8n81Py358IqD5w0IYfFgV5gbDjp2g5H5YK2/Shls/kQNTWQ==} 3585 3585 dev: false 3586 3586 3587 3587 /@svitejs/changesets-changelog-github-compact@1.1.0: ··· 3660 3660 resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} 3661 3661 dependencies: 3662 3662 '@types/connect': 3.4.38 3663 - '@types/node': 20.12.8 3663 + '@types/node': 20.12.11 3664 3664 dev: true 3665 3665 3666 3666 /@types/bonjour@3.5.13: 3667 3667 resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} 3668 3668 dependencies: 3669 - '@types/node': 20.12.8 3669 + '@types/node': 20.12.11 3670 3670 dev: true 3671 3671 3672 3672 /@types/connect-history-api-fallback@1.5.4: 3673 3673 resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} 3674 3674 dependencies: 3675 3675 '@types/express-serve-static-core': 4.19.0 3676 - '@types/node': 20.12.8 3676 + '@types/node': 20.12.11 3677 3677 dev: true 3678 3678 3679 3679 /@types/connect@3.4.38: 3680 3680 resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} 3681 3681 dependencies: 3682 - '@types/node': 20.12.8 3682 + '@types/node': 20.12.11 3683 3683 dev: true 3684 3684 3685 3685 /@types/cross-spawn@6.0.6: 3686 3686 resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} 3687 3687 dependencies: 3688 - '@types/node': 20.12.8 3688 + '@types/node': 20.12.11 3689 3689 dev: true 3690 3690 3691 3691 /@types/eslint-scope@3.7.7: ··· 3709 3709 /@types/express-serve-static-core@4.19.0: 3710 3710 resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} 3711 3711 dependencies: 3712 - '@types/node': 20.12.8 3712 + '@types/node': 20.12.11 3713 3713 '@types/qs': 6.9.15 3714 3714 '@types/range-parser': 1.2.7 3715 3715 '@types/send': 0.17.4 ··· 3731 3731 /@types/http-proxy@1.17.14: 3732 3732 resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} 3733 3733 dependencies: 3734 - '@types/node': 20.12.8 3734 + '@types/node': 20.12.11 3735 3735 dev: true 3736 3736 3737 3737 /@types/json-schema@7.0.15: ··· 3763 3763 /@types/node-forge@1.3.11: 3764 3764 resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} 3765 3765 dependencies: 3766 - '@types/node': 20.12.8 3766 + '@types/node': 20.12.11 3767 3767 dev: true 3768 3768 3769 3769 /@types/node@12.20.55: 3770 3770 resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} 3771 3771 dev: true 3772 3772 3773 - /@types/node@20.12.8: 3774 - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} 3773 + /@types/node@20.12.11: 3774 + resolution: {integrity: sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==} 3775 3775 dependencies: 3776 3776 undici-types: 5.26.5 3777 3777 dev: true ··· 3795 3795 /@types/react-dom@18.3.0: 3796 3796 resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} 3797 3797 dependencies: 3798 - '@types/react': 18.3.1 3798 + '@types/react': 18.3.2 3799 3799 dev: true 3800 3800 3801 - /@types/react@18.3.1: 3802 - resolution: {integrity: sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==} 3801 + /@types/react@18.3.2: 3802 + resolution: {integrity: sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==} 3803 3803 dependencies: 3804 3804 '@types/prop-types': 15.7.12 3805 3805 csstype: 3.1.3 ··· 3821 3821 resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} 3822 3822 dependencies: 3823 3823 '@types/mime': 1.3.5 3824 - '@types/node': 20.12.8 3824 + '@types/node': 20.12.11 3825 3825 dev: true 3826 3826 3827 3827 /@types/serve-index@1.9.4: ··· 3834 3834 resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} 3835 3835 dependencies: 3836 3836 '@types/http-errors': 2.0.4 3837 - '@types/node': 20.12.8 3837 + '@types/node': 20.12.11 3838 3838 '@types/send': 0.17.4 3839 3839 dev: true 3840 3840 3841 3841 /@types/sockjs@0.3.36: 3842 3842 resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} 3843 3843 dependencies: 3844 - '@types/node': 20.12.8 3844 + '@types/node': 20.12.11 3845 3845 dev: true 3846 3846 3847 3847 /@types/web-bluetooth@0.0.20: ··· 3851 3851 /@types/ws@8.5.10: 3852 3852 resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} 3853 3853 dependencies: 3854 - '@types/node': 20.12.8 3854 + '@types/node': 20.12.11 3855 3855 dev: true 3856 3856 3857 3857 /@types/yauzl@2.10.3: 3858 3858 resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} 3859 3859 requiresBuild: true 3860 3860 dependencies: 3861 - '@types/node': 20.12.8 3861 + '@types/node': 20.12.11 3862 3862 dev: true 3863 3863 optional: true 3864 3864 ··· 4000 4000 peerDependencies: 4001 4001 vite: ^3.0.0 || ^4.0.0 || ^5.0.0 4002 4002 dependencies: 4003 - vite: 5.1.7(@types/node@20.12.8)(less@4.2.0)(sass@1.71.1)(terser@5.29.1) 4003 + vite: 5.1.7(@types/node@20.12.11)(less@4.2.0)(sass@1.71.1)(terser@5.29.1) 4004 4004 dev: true 4005 4005 4006 4006 /@vitejs/plugin-react@4.2.1(vite@5.2.11): ··· 4014 4014 '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.0) 4015 4015 '@types/babel__core': 7.20.5 4016 4016 react-refresh: 0.14.0 4017 - vite: 5.2.11(@types/node@20.12.8) 4017 + vite: 5.2.11(@types/node@20.12.11) 4018 4018 transitivePeerDependencies: 4019 4019 - supports-color 4020 4020 dev: true ··· 4026 4026 vite: ^5.0.0 4027 4027 vue: ^3.2.25 4028 4028 dependencies: 4029 - vite: 5.2.10(@types/node@20.12.8) 4029 + vite: 5.2.10(@types/node@20.12.11) 4030 4030 vue: 3.4.25(typescript@5.4.5) 4031 4031 dev: true 4032 4032 ··· 4048 4048 std-env: 3.7.0 4049 4049 strip-literal: 2.1.0 4050 4050 test-exclude: 6.0.0 4051 - vitest: 1.6.0(@types/node@20.12.8) 4051 + vitest: 1.6.0(@types/node@20.12.11) 4052 4052 transitivePeerDependencies: 4053 4053 - supports-color 4054 4054 dev: true ··· 4993 4993 dependencies: 4994 4994 '@npmcli/fs': 3.1.0 4995 4995 fs-minipass: 3.0.3 4996 - glob: 10.3.12 4997 - lru-cache: 10.2.0 4998 - minipass: 7.0.4 4996 + glob: 10.3.15 4997 + lru-cache: 10.2.2 4998 + minipass: 7.1.1 4999 4999 minipass-collect: 2.0.1 5000 5000 minipass-flush: 1.0.5 5001 5001 minipass-pipeline: 1.2.4 ··· 6045 6045 eslint: 9.2.0 6046 6046 dev: true 6047 6047 6048 - /eslint-plugin-react-refresh@0.4.6(eslint@9.2.0): 6049 - resolution: {integrity: sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA==} 6048 + /eslint-plugin-react-refresh@0.4.7(eslint@9.2.0): 6049 + resolution: {integrity: sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==} 6050 6050 peerDependencies: 6051 6051 eslint: '>=7' 6052 6052 dependencies: ··· 6565 6565 resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} 6566 6566 engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} 6567 6567 dependencies: 6568 - minipass: 7.0.4 6568 + minipass: 7.1.1 6569 6569 dev: true 6570 6570 6571 6571 /fs-monkey@1.0.5: ··· 6704 6704 resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 6705 6705 dev: true 6706 6706 6707 - /glob@10.3.12: 6708 - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} 6709 - engines: {node: '>=16 || 14 >=14.17'} 6707 + /glob@10.3.15: 6708 + resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==} 6709 + engines: {node: '>=16 || 14 >=14.18'} 6710 6710 hasBin: true 6711 6711 dependencies: 6712 6712 foreground-child: 3.1.1 6713 6713 jackspeak: 2.3.6 6714 6714 minimatch: 9.0.4 6715 - minipass: 7.0.4 6716 - path-scurry: 1.10.2 6715 + minipass: 7.1.1 6716 + path-scurry: 1.11.1 6717 6717 dev: true 6718 6718 6719 6719 /glob@7.2.3: ··· 6748 6748 engines: {node: '>=18'} 6749 6749 dev: true 6750 6750 6751 - /globals@15.1.0: 6752 - resolution: {integrity: sha512-926gJqg+4mkxwYKiFvoomM4J0kWESfk3qfTvRL2/oc/tK/eTDBbrfcKnSa2KtfdxB5onoL7D3A3qIHQFpd4+UA==} 6751 + /globals@15.2.0: 6752 + resolution: {integrity: sha512-FQ5YwCHZM3nCmtb5FzEWwdUc9K5d3V/w9mzcz8iGD1gC/aOTHc6PouYu0kkKipNJqHAT7m51sqzQjEjIP+cK0A==} 6753 6753 engines: {node: '>=18'} 6754 6754 dev: true 6755 6755 ··· 6879 6879 resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} 6880 6880 engines: {node: ^16.14.0 || >=18.0.0} 6881 6881 dependencies: 6882 - lru-cache: 10.2.0 6882 + lru-cache: 10.2.2 6883 6883 dev: true 6884 6884 6885 6885 /hpack.js@2.1.6: ··· 7460 7460 resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} 7461 7461 engines: {node: '>= 10.13.0'} 7462 7462 dependencies: 7463 - '@types/node': 20.12.8 7463 + '@types/node': 20.12.11 7464 7464 merge-stream: 2.0.0 7465 7465 supports-color: 8.1.1 7466 7466 dev: true ··· 7789 7789 get-func-name: 2.0.2 7790 7790 dev: true 7791 7791 7792 - /lru-cache@10.2.0: 7793 - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} 7792 + /lru-cache@10.2.2: 7793 + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} 7794 7794 engines: {node: 14 || >=16.14} 7795 7795 dev: true 7796 7796 ··· 7869 7869 cacache: 18.0.2 7870 7870 http-cache-semantics: 4.1.1 7871 7871 is-lambda: 1.0.1 7872 - minipass: 7.0.4 7872 + minipass: 7.1.1 7873 7873 minipass-fetch: 3.0.4 7874 7874 minipass-flush: 1.0.5 7875 7875 minipass-pipeline: 1.2.4 ··· 8030 8030 resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} 8031 8031 engines: {node: '>=16 || 14 >=14.17'} 8032 8032 dependencies: 8033 - minipass: 7.0.4 8033 + minipass: 7.1.1 8034 8034 dev: true 8035 8035 8036 8036 /minipass-fetch@3.0.4: 8037 8037 resolution: {integrity: sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==} 8038 8038 engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} 8039 8039 dependencies: 8040 - minipass: 7.0.4 8040 + minipass: 7.1.1 8041 8041 minipass-sized: 1.0.3 8042 8042 minizlib: 2.1.2 8043 8043 optionalDependencies: ··· 8082 8082 resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 8083 8083 engines: {node: '>=8'} 8084 8084 8085 - /minipass@7.0.4: 8086 - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} 8085 + /minipass@7.1.1: 8086 + resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} 8087 8087 engines: {node: '>=16 || 14 >=14.17'} 8088 8088 dev: true 8089 8089 ··· 8258 8258 dependencies: 8259 8259 env-paths: 2.2.1 8260 8260 exponential-backoff: 3.1.1 8261 - glob: 10.3.12 8261 + glob: 10.3.15 8262 8262 graceful-fs: 4.2.11 8263 8263 make-fetch-happen: 13.0.0 8264 8264 nopt: 7.2.0 ··· 8362 8362 dependencies: 8363 8363 '@npmcli/redact': 1.1.0 8364 8364 make-fetch-happen: 13.0.0 8365 - minipass: 7.0.4 8365 + minipass: 7.1.1 8366 8366 minipass-fetch: 3.0.4 8367 8367 minipass-json-stream: 1.0.1 8368 8368 minizlib: 2.1.2 ··· 8622 8622 '@npmcli/run-script': 7.0.4 8623 8623 cacache: 18.0.2 8624 8624 fs-minipass: 3.0.3 8625 - minipass: 7.0.4 8625 + minipass: 7.1.1 8626 8626 npm-package-arg: 11.0.1 8627 8627 npm-packlist: 8.0.2 8628 8628 npm-pick-manifest: 9.0.0 ··· 8713 8713 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 8714 8714 dev: true 8715 8715 8716 - /path-scurry@1.10.2: 8717 - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} 8718 - engines: {node: '>=16 || 14 >=14.17'} 8716 + /path-scurry@1.11.1: 8717 + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 8718 + engines: {node: '>=16 || 14 >=14.18'} 8719 8719 dependencies: 8720 - lru-cache: 10.2.0 8721 - minipass: 7.0.4 8720 + lru-cache: 10.2.2 8721 + minipass: 7.1.1 8722 8722 dev: true 8723 8723 8724 8724 /path-to-regexp@0.1.7: ··· 9022 9022 engines: {node: '>=6'} 9023 9023 dev: true 9024 9024 9025 - /puppeteer-core@22.7.1: 9026 - resolution: {integrity: sha512-jD7T7yN7PWGuJmNT0TAEboA26s0VVnvbgCxqgQIF+eNQW2u71ENaV2JwzSJiCHO+e72H4Ue6AgKD9USQ8xAcOQ==} 9025 + /puppeteer-core@22.8.0: 9026 + resolution: {integrity: sha512-S5bWx3g/fNuyFxjZX9TkZMN07CEH47+9Zm6IiTl1QfqI9pnVaShbwrD9kRe5vmz/XPp/jLGhhxRUj1sY4wObnA==} 9027 9027 engines: {node: '>=18'} 9028 9028 dependencies: 9029 9029 '@puppeteer/browsers': 2.2.3 9030 9030 chromium-bidi: 0.5.19(devtools-protocol@0.0.1273771) 9031 9031 debug: 4.3.4 9032 9032 devtools-protocol: 0.0.1273771 9033 - ws: 8.16.0 9033 + ws: 8.17.0 9034 9034 transitivePeerDependencies: 9035 9035 - bufferutil 9036 9036 - supports-color 9037 9037 - utf-8-validate 9038 9038 dev: true 9039 9039 9040 - /puppeteer@22.7.1(typescript@5.4.5): 9041 - resolution: {integrity: sha512-JBCBCwQ9+dyPp5haqeecgv0N0vgWFx44woUeKJaPeJT8CU3RXrd8F/tqJQbuAmcWlbMhYJSlTJkIFrwVAs6BNA==} 9040 + /puppeteer@22.8.0(typescript@5.4.5): 9041 + resolution: {integrity: sha512-Z616wyTr0d7KpxmfcBG22rAkzuo/xzHJ3ycpu4KiJ3dZNHn/C1CpqcCwPlpiIIsmPojTAfWjo6EMR7M+AaC0Ww==} 9042 9042 engines: {node: '>=18'} 9043 9043 hasBin: true 9044 9044 requiresBuild: true ··· 9046 9046 '@puppeteer/browsers': 2.2.3 9047 9047 cosmiconfig: 9.0.0(typescript@5.4.5) 9048 9048 devtools-protocol: 0.0.1273771 9049 - puppeteer-core: 22.7.1 9049 + puppeteer-core: 22.8.0 9050 9050 transitivePeerDependencies: 9051 9051 - bufferutil 9052 9052 - supports-color ··· 9141 9141 resolution: {integrity: sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==} 9142 9142 engines: {node: ^16.14.0 || >=18.0.0} 9143 9143 dependencies: 9144 - glob: 10.3.12 9144 + glob: 10.3.15 9145 9145 json-parse-even-better-errors: 3.0.1 9146 9146 normalize-package-data: 6.0.0 9147 9147 npm-normalize-package-bin: 3.0.1 ··· 9364 9364 glob: 7.2.3 9365 9365 dev: true 9366 9366 9367 - /rimraf@5.0.5: 9368 - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} 9369 - engines: {node: '>=14'} 9367 + /rimraf@5.0.7: 9368 + resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==} 9369 + engines: {node: '>=14.18'} 9370 9370 hasBin: true 9371 9371 dependencies: 9372 - glob: 10.3.12 9372 + glob: 10.3.15 9373 9373 dev: true 9374 9374 9375 9375 /rollup-plugin-dts@6.1.0(rollup@4.17.2)(typescript@5.4.5): ··· 9903 9903 resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==} 9904 9904 engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} 9905 9905 dependencies: 9906 - minipass: 7.0.4 9906 + minipass: 7.1.1 9907 9907 dev: true 9908 9908 9909 9909 /stackback@0.0.2: ··· 10258 10258 typescript: 5.4.5 10259 10259 dev: true 10260 10260 10261 - /ts-node@10.9.2(@types/node@20.12.8)(typescript@5.4.5): 10261 + /ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5): 10262 10262 resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} 10263 10263 hasBin: true 10264 10264 peerDependencies: ··· 10277 10277 '@tsconfig/node12': 1.0.11 10278 10278 '@tsconfig/node14': 1.0.3 10279 10279 '@tsconfig/node16': 1.0.4 10280 - '@types/node': 20.12.8 10280 + '@types/node': 20.12.11 10281 10281 acorn: 8.11.3 10282 10282 acorn-walk: 8.3.2 10283 10283 arg: 4.1.3 ··· 10577 10577 engines: {node: '>= 0.8'} 10578 10578 dev: true 10579 10579 10580 - /vite-node@1.6.0(@types/node@20.12.8): 10580 + /vite-node@1.6.0(@types/node@20.12.11): 10581 10581 resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} 10582 10582 engines: {node: ^18.0.0 || >=20.0.0} 10583 10583 hasBin: true ··· 10586 10586 debug: 4.3.4 10587 10587 pathe: 1.1.2 10588 10588 picocolors: 1.0.0 10589 - vite: 5.2.11(@types/node@20.12.8) 10589 + vite: 5.2.11(@types/node@20.12.11) 10590 10590 transitivePeerDependencies: 10591 10591 - '@types/node' 10592 10592 - less ··· 10598 10598 - terser 10599 10599 dev: true 10600 10600 10601 - /vite@5.1.7(@types/node@20.12.8)(less@4.2.0)(sass@1.71.1)(terser@5.29.1): 10601 + /vite@5.1.7(@types/node@20.12.11)(less@4.2.0)(sass@1.71.1)(terser@5.29.1): 10602 10602 resolution: {integrity: sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA==} 10603 10603 engines: {node: ^18.0.0 || >=20.0.0} 10604 10604 hasBin: true ··· 10626 10626 terser: 10627 10627 optional: true 10628 10628 dependencies: 10629 - '@types/node': 20.12.8 10629 + '@types/node': 20.12.11 10630 10630 esbuild: 0.19.12 10631 10631 less: 4.2.0 10632 10632 postcss: 8.4.38 ··· 10637 10637 fsevents: 2.3.3 10638 10638 dev: true 10639 10639 10640 - /vite@5.2.10(@types/node@20.12.8): 10640 + /vite@5.2.10(@types/node@20.12.11): 10641 10641 resolution: {integrity: sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==} 10642 10642 engines: {node: ^18.0.0 || >=20.0.0} 10643 10643 hasBin: true ··· 10665 10665 terser: 10666 10666 optional: true 10667 10667 dependencies: 10668 - '@types/node': 20.12.8 10668 + '@types/node': 20.12.11 10669 10669 esbuild: 0.20.2 10670 10670 postcss: 8.4.38 10671 10671 rollup: 4.17.2 ··· 10673 10673 fsevents: 2.3.3 10674 10674 dev: true 10675 10675 10676 - /vite@5.2.11(@types/node@20.12.8): 10676 + /vite@5.2.11(@types/node@20.12.11): 10677 10677 resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==} 10678 10678 engines: {node: ^18.0.0 || >=20.0.0} 10679 10679 hasBin: true ··· 10701 10701 terser: 10702 10702 optional: true 10703 10703 dependencies: 10704 - '@types/node': 20.12.8 10704 + '@types/node': 20.12.11 10705 10705 esbuild: 0.20.2 10706 10706 postcss: 8.4.38 10707 10707 rollup: 4.17.2 ··· 10709 10709 fsevents: 2.3.3 10710 10710 dev: true 10711 10711 10712 - /vitepress@1.1.4(@algolia/client-search@4.23.3)(@types/node@20.12.8)(search-insights@2.13.0)(typescript@5.4.5): 10712 + /vitepress@1.1.4(@algolia/client-search@4.23.3)(@types/node@20.12.11)(search-insights@2.13.0)(typescript@5.4.5): 10713 10713 resolution: {integrity: sha512-bWIzFZXpPB6NIDBuWnS20aMADH+FcFKDfQNYFvbOWij03PR29eImTceQHIzCKordjXYBhM/TjE5VKFTUJ3EheA==} 10714 10714 hasBin: true 10715 10715 peerDependencies: ··· 10734 10734 mark.js: 8.11.1 10735 10735 minisearch: 6.3.0 10736 10736 shiki: 1.3.0 10737 - vite: 5.2.10(@types/node@20.12.8) 10737 + vite: 5.2.10(@types/node@20.12.11) 10738 10738 vue: 3.4.25(typescript@5.4.5) 10739 10739 transitivePeerDependencies: 10740 10740 - '@algolia/client-search' ··· 10764 10764 - universal-cookie 10765 10765 dev: true 10766 10766 10767 - /vitest@1.6.0(@types/node@20.12.8): 10767 + /vitest@1.6.0(@types/node@20.12.11): 10768 10768 resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} 10769 10769 engines: {node: ^18.0.0 || >=20.0.0} 10770 10770 hasBin: true ··· 10789 10789 jsdom: 10790 10790 optional: true 10791 10791 dependencies: 10792 - '@types/node': 20.12.8 10792 + '@types/node': 20.12.11 10793 10793 '@vitest/expect': 1.6.0 10794 10794 '@vitest/runner': 1.6.0 10795 10795 '@vitest/snapshot': 1.6.0 ··· 10807 10807 strip-literal: 2.1.0 10808 10808 tinybench: 2.8.0 10809 10809 tinypool: 0.8.4 10810 - vite: 5.2.11(@types/node@20.12.8) 10811 - vite-node: 1.6.0(@types/node@20.12.8) 10810 + vite: 5.2.11(@types/node@20.12.11) 10811 + vite-node: 1.6.0(@types/node@20.12.11) 10812 10812 why-is-node-running: 2.2.2 10813 10813 transitivePeerDependencies: 10814 10814 - less ··· 10954 10954 spdy: 4.0.2 10955 10955 webpack: 5.90.3(esbuild@0.20.1) 10956 10956 webpack-dev-middleware: 5.3.4(webpack@5.90.3) 10957 - ws: 8.16.0 10957 + ws: 8.17.0 10958 10958 transitivePeerDependencies: 10959 10959 - bufferutil 10960 10960 - debug ··· 11168 11168 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 11169 11169 dev: true 11170 11170 11171 - /ws@8.16.0: 11172 - resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} 11171 + /ws@8.17.0: 11172 + resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} 11173 11173 engines: {node: '>=10.0.0'} 11174 11174 peerDependencies: 11175 11175 bufferutil: ^4.0.1