From 776f52435e1e69c93dd43065b4cf65671585b099 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 24 Apr 2024 09:37:06 +0000 Subject: [PATCH] chore: add working local example with axios client --- package.json | 1 + pnpm-lock.yaml | 474 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- pnpm-workspace.yaml | 1 + examples/openapi-ts-axios/.gitignore | 24 ++++++++++++++++++++++++ examples/openapi-ts-axios/index.html | 13 +++++++++++++ examples/openapi-ts-axios/openapi-ts.config.ts | 10 ++++++++++ examples/openapi-ts-axios/package.json | 33 +++++++++++++++++++++++++++++++++ examples/openapi-ts-axios/tsconfig.json | 25 +++++++++++++++++++++++++ examples/openapi-ts-axios/tsconfig.node.json | 11 +++++++++++ examples/openapi-ts-axios/vite.config.ts | 7 +++++++ packages/client-axios/package.json | 9 ++++++--- packages/client-axios/rollup.config.ts | 58 +++++++++++++++++++++++++++++++++++++++------------------- packages/client-axios/rollup.dts.config.ts | 4 ++-- packages/client-core/package.json | 9 ++++++--- packages/client-core/rollup.config.ts | 58 +++++++++++++++++++++++++++++++++++++++------------------- packages/client-core/rollup.dts.config.ts | 4 ++-- examples/openapi-ts-axios/src/App.css | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/openapi-ts-axios/src/App.tsx | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/openapi-ts-axios/src/index.css | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/openapi-ts-axios/src/main.tsx | 12 ++++++++++++ examples/openapi-ts-axios/src/vite-env.d.ts | 1 + packages/client-axios/src/index.ts | 34 ++++++++++++++++++++++++++++++++++ packages/client-axios/src/tsconfig.json | 9 --------- packages/client-core/src/index.ts | 7 +++---- packages/client-core/src/tsconfig.json | 9 --------- packages/openapi-ts/src/index.ts | 16 ++++++++-------- examples/openapi-ts-axios/src/client/index.ts | 4 ++++ examples/openapi-ts-axios/src/client/schemas.gen.ts | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/openapi-ts-axios/src/client/services.gen.ts | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/openapi-ts-axios/src/client/types.gen.ts | 433 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ packages/client-axios/src/node/index.ts | 2 ++ packages/client-axios/src/node/tsconfig.json | 9 +++++++++ packages/client-core/src/node/index.ts | 21 +++++++++++++++++++++ packages/client-core/src/node/tsconfig.json | 9 +++++++++ packages/openapi-ts/src/types/config.ts | 9 ++++++++- packages/openapi-ts/src/utils/getHttpRequestName.ts | 4 ++-- packages/openapi-ts/src/utils/write/services.ts | 39 +++++++++++++++++++++++++++++---------- 37 file(s) changed, 2172 insertion(s)(+), 101 deletion(s)(-) diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "client-fetch": "pnpm --filter @hey-api/client-fetch --", "client-nextjs": "pnpm --filter @hey-api/client-nextjs --", "docs": "pnpm --filter @hey-api/docs --", + "example": "pnpm --filter @examples/openapi-ts-axios --", "format": "prettier --write .", "lint:fix": "prettier --check . && eslint . --fix", "lint": "prettier --check . && eslint .", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,6 +82,58 @@ specifier: 1.1.3 version: 1.1.3(@algolia/client-search@4.23.3)(@types/node@20.12.7)(search-insights@2.13.0)(typescript@5.4.5) + examples/openapi-ts-axios: + dependencies: + '@hey-api/client-axios': + specifier: workspace:* + version: link:../../packages/client-axios + axios: + specifier: 1.6.8 + version: 1.6.8 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + devDependencies: + '@hey-api/openapi-ts': + specifier: workspace:* + version: link:../../packages/openapi-ts + '@types/react': + specifier: 18.2.79 + version: 18.2.79 + '@types/react-dom': + specifier: 18.2.25 + version: 18.2.25 + '@typescript-eslint/eslint-plugin': + specifier: 7.7.1 + version: 7.7.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': + specifier: 7.7.1 + version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) + '@vitejs/plugin-react': + specifier: 4.2.1 + version: 4.2.1(vite@5.2.10) + eslint: + specifier: 8.57.0 + version: 8.57.0 + eslint-plugin-react-hooks: + specifier: 4.6.0 + version: 4.6.0(eslint@8.57.0) + eslint-plugin-react-refresh: + specifier: 0.4.6 + version: 0.4.6(eslint@8.57.0) + prettier: + specifier: 3.2.5 + version: 3.2.5 + typescript: + specifier: 5.4.5 + version: 5.4.5 + vite: + specifier: 5.2.10 + version: 5.2.10(@types/node@20.12.7) + packages/client-axios: dependencies: '@hey-api/client-core': @@ -1683,6 +1735,26 @@ '@babel/helper-plugin-utils': 7.24.0 dev: true + /@babel/plugin-transform-react-jsx-self@7.24.1(@babel/core@7.24.0): + resolution: {integrity: sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.0 + '@babel/helper-plugin-utils': 7.24.0 + dev: true + + /@babel/plugin-transform-react-jsx-source@7.24.1(@babel/core@7.24.0): + resolution: {integrity: sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.0 + '@babel/helper-plugin-utils': 7.24.0 + dev: true + /@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.0): resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} engines: {node: '>=6.9.0'} @@ -2843,6 +2915,16 @@ dev: true optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + dev: true + /@eslint-community/eslint-utils@4.4.0(eslint@9.1.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2856,6 +2938,23 @@ /@eslint-community/regexpp@4.10.0: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color dev: true /@eslint/eslintrc@3.0.2: @@ -2875,9 +2974,25 @@ - supports-color dev: true + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@eslint/js@9.1.1: resolution: {integrity: sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color dev: true /@humanwhocodes/config-array@0.13.0: @@ -3514,6 +3629,35 @@ minimatch: 9.0.4 dev: true + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: true + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + dev: true + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.24.0 + dev: true + /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: @@ -3638,12 +3782,29 @@ resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} dev: true + /@types/prop-types@15.7.12: + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + dev: true + /@types/qs@6.9.15: resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} dev: true /@types/range-parser@1.2.7: resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: true + + /@types/react-dom@18.2.25: + resolution: {integrity: sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==} + dependencies: + '@types/react': 18.2.79 + dev: true + + /@types/react@18.2.79: + resolution: {integrity: sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==} + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 dev: true /@types/resolve@1.20.2: @@ -3732,6 +3893,35 @@ - supports-color dev: true + /@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.7.1 + '@typescript-eslint/type-utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.7.1 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/parser@7.7.0(eslint@9.1.0)(typescript@5.4.5): resolution: {integrity: sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3753,12 +3943,41 @@ - supports-color dev: true + /@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 7.7.1 + '@typescript-eslint/types': 7.7.1 + '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.7.1 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/scope-manager@7.7.0: resolution: {integrity: sha512-/8INDn0YLInbe9Wt7dK4cXLDYp0fNHP5xKLHvZl3mOT5X17rK/YShXaiNmorl+/U4VKCVIjJnx4Ri5b0y+HClw==} engines: {node: ^18.18.0 || >=20.0.0} dependencies: '@typescript-eslint/types': 7.7.0 '@typescript-eslint/visitor-keys': 7.7.0 + dev: true + + /@typescript-eslint/scope-manager@7.7.1: + resolution: {integrity: sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.7.1 + '@typescript-eslint/visitor-keys': 7.7.1 dev: true /@typescript-eslint/type-utils@7.7.0(eslint@9.1.0)(typescript@5.4.5): @@ -3781,8 +4000,33 @@ - supports-color dev: true + /@typescript-eslint/type-utils@7.7.1(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) + '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/types@7.7.0: resolution: {integrity: sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w==} + engines: {node: ^18.18.0 || >=20.0.0} + dev: true + + /@typescript-eslint/types@7.7.1: + resolution: {integrity: sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==} engines: {node: ^18.18.0 || >=20.0.0} dev: true @@ -3797,6 +4041,28 @@ dependencies: '@typescript-eslint/types': 7.7.0 '@typescript-eslint/visitor-keys': 7.7.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@7.7.1(typescript@5.4.5): + resolution: {integrity: sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.7.1 + '@typescript-eslint/visitor-keys': 7.7.1 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -3827,12 +4093,43 @@ - typescript dev: true + /@typescript-eslint/utils@7.7.1(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 7.7.1 + '@typescript-eslint/types': 7.7.1 + '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/visitor-keys@7.7.0: resolution: {integrity: sha512-h0WHOj8MhdhY8YWkzIF30R379y0NqyOHExI9N9KCzvmu05EgG4FumeYa3ccfKUSphyWkWQE1ybVrgz/Pbam6YA==} engines: {node: ^18.18.0 || >=20.0.0} dependencies: '@typescript-eslint/types': 7.7.0 eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@7.7.1: + resolution: {integrity: sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.7.1 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true /@vitejs/plugin-basic-ssl@1.1.0(vite@5.1.7): @@ -3842,6 +4139,22 @@ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 dependencies: vite: 5.1.7(@types/node@20.12.7)(less@4.2.0)(sass@1.71.1)(terser@5.29.1) + dev: true + + /@vitejs/plugin-react@4.2.1(vite@5.2.10): + resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 + dependencies: + '@babel/core': 7.24.0 + '@babel/plugin-transform-react-jsx-self': 7.24.1(@babel/core@7.24.0) + '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.0) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.0 + vite: 5.2.10(@types/node@20.12.7) + transitivePeerDependencies: + - supports-color dev: true /@vitejs/plugin-vue@5.0.4(vite@5.2.10)(vue@3.4.23): @@ -4490,7 +4803,6 @@ /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true /autoprefixer@10.4.18(postcss@8.4.35): resolution: {integrity: sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==} @@ -4523,7 +4835,6 @@ proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - dev: true /b4a@1.6.6: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} @@ -5031,7 +5342,6 @@ engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: true /commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} @@ -5417,7 +5727,6 @@ /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: true /depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} @@ -5473,6 +5782,13 @@ engines: {node: '>=6'} dependencies: '@leichtgewicht/ip-codec': 2.0.5 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 dev: true /dom-serializer@2.0.0: @@ -5837,6 +6153,23 @@ eslint: 9.1.0 dev: true + /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-plugin-react-refresh@0.4.6(eslint@8.57.0): + resolution: {integrity: sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA==} + peerDependencies: + eslint: '>=7' + dependencies: + eslint: 8.57.0 + dev: true + /eslint-plugin-simple-import-sort@12.1.0(eslint@9.1.0): resolution: {integrity: sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==} peerDependencies: @@ -5863,6 +6196,14 @@ estraverse: 4.3.0 dev: true + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + /eslint-scope@8.0.1: resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5884,6 +6225,53 @@ /eslint-visitor-keys@4.0.0: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color dev: true /eslint@9.1.0: @@ -5945,6 +6333,15 @@ acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) eslint-visitor-keys: 1.3.0 + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 dev: true /esprima@4.0.1: @@ -6170,6 +6567,13 @@ escape-string-regexp: 1.0.5 dev: true + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + /file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -6237,6 +6641,15 @@ pkg-dir: 4.2.0 dev: true + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + /flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -6268,7 +6681,6 @@ peerDependenciesMeta: debug: optional: true - dev: true /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -6291,7 +6703,6 @@ asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true /formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} @@ -6527,6 +6938,13 @@ /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 dev: true /globals@14.0.0: @@ -7257,7 +7675,6 @@ /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true /js-tokens@9.0.0: resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} @@ -7563,6 +7980,13 @@ wrap-ansi: 9.0.0 dev: true + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: @@ -7731,14 +8155,12 @@ /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: true /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 - dev: true /mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} @@ -8772,7 +9194,6 @@ /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} @@ -8877,9 +9298,31 @@ destr: 2.0.3 dev: false + /react-dom@18.2.0(react@18.2.0): + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true + + /react-refresh@0.14.0: + resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} + engines: {node: '>=0.10.0'} + dev: true + + /react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false /read-package-json-fast@3.0.2: resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} @@ -9253,6 +9696,12 @@ requiresBuild: true dev: true optional: true + + /scheduler@0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false /schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} @@ -10078,6 +10527,11 @@ /type-fest@0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} dev: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - docs + - examples/* - packages/* diff --git a/examples/openapi-ts-axios/.gitignore b/examples/openapi-ts-axios/.gitignore new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/openapi-ts-axios/index.html b/examples/openapi-ts-axios/index.html new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/index.html @@ -0,0 +1,13 @@ + + + + + + + Hey API + Axios Demo + + +
+ + + diff --git a/examples/openapi-ts-axios/openapi-ts.config.ts b/examples/openapi-ts-axios/openapi-ts.config.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/openapi-ts.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from '@hey-api/openapi-ts'; + +export default defineConfig({ + base: 'https://petstore3.swagger.io/api/v3', + format: 'prettier', + input: + 'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml', + lint: 'eslint', + output: './src/client', +}); diff --git a/examples/openapi-ts-axios/package.json b/examples/openapi-ts-axios/package.json new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/package.json @@ -0,0 +1,33 @@ +{ + "name": "@examples/openapi-ts-axios", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "build": "tsc && vite build", + "dev": "vite", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "openapi-ts": "openapi-ts", + "preview": "vite preview" + }, + "dependencies": { + "@hey-api/client-axios": "workspace:*", + "axios": "1.6.8", + "react": "18.2.0", + "react-dom": "18.2.0" + }, + "devDependencies": { + "@hey-api/openapi-ts": "workspace:*", + "@types/react": "18.2.79", + "@types/react-dom": "18.2.25", + "@typescript-eslint/eslint-plugin": "7.7.1", + "@typescript-eslint/parser": "7.7.1", + "@vitejs/plugin-react": "4.2.1", + "eslint": "8.57.0", + "eslint-plugin-react-hooks": "4.6.0", + "eslint-plugin-react-refresh": "0.4.6", + "prettier": "3.2.5", + "typescript": "5.4.5", + "vite": "5.2.10" + } +} diff --git a/examples/openapi-ts-axios/tsconfig.json b/examples/openapi-ts-axios/tsconfig.json new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/examples/openapi-ts-axios/tsconfig.node.json b/examples/openapi-ts-axios/tsconfig.node.json new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/examples/openapi-ts-axios/vite.config.ts b/examples/openapi-ts-axios/vite.config.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/vite.config.ts @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/packages/client-axios/package.json b/packages/client-axios/package.json --- a/packages/client-axios/package.json +++ b/packages/client-axios/package.json @@ -26,13 +26,16 @@ "typescript", "vue" ], - "main": "./dist/index.cjs", - "types": "./dist/index.d.ts", + "exports": { + "import": "./dist/node/index.mjs", + "require": "./dist/node/index.cjs", + "types": "./dist/node/index.d.ts" + }, "scripts": { "build-bundle": "rollup --config rollup.config.ts --configPlugin typescript", "build-types-check": "tsc --project tsconfig.check.json", "build-types-roll": "rollup --config rollup.dts.config.ts --configPlugin typescript && rimraf temp", - "build-types-temp": "tsc --emitDeclarationOnly --outDir temp -p src", + "build-types-temp": "tsc --emitDeclarationOnly --outDir temp -p src/node", "build-types": "pnpm build-types-temp && pnpm build-types-roll && pnpm build-types-check", "build": "pnpm clean && pnpm build-bundle && pnpm build-types", "clean": "rimraf dist coverage node_modules/.cache", diff --git a/packages/client-axios/rollup.config.ts b/packages/client-axios/rollup.config.ts --- a/packages/client-axios/rollup.config.ts +++ b/packages/client-axios/rollup.config.ts @@ -20,28 +20,48 @@ ]; function createConfig(isProduction: boolean) { - return defineConfig({ - external: externalDependencies, - input: path.resolve(__dirname, 'src/index.ts'), - output: { - file: path.resolve(__dirname, 'dist/index.cjs'), - format: 'cjs', - }, - plugins: [ - typescript({ - declaration: false, - tsconfig: path.resolve(__dirname, 'src/tsconfig.json'), - }), - commonjs({ - sourceMap: false, - }), - isProduction && terser(), - ], - }); + return [ + defineConfig({ + external: externalDependencies, + input: path.resolve(__dirname, 'src/node/index.ts'), + output: { + file: path.resolve(__dirname, 'dist/node/index.cjs'), + format: 'cjs', + }, + plugins: [ + typescript({ + declaration: false, + tsconfig: path.resolve(__dirname, 'src/node/tsconfig.json'), + }), + commonjs({ + sourceMap: false, + }), + isProduction && terser(), + ], + }), + defineConfig({ + external: externalDependencies, + input: path.resolve(__dirname, 'src/node/index.ts'), + output: { + file: path.resolve(__dirname, 'dist/node/index.mjs'), + format: 'esm', + }, + plugins: [ + typescript({ + declaration: false, + tsconfig: path.resolve(__dirname, 'src/node/tsconfig.json'), + }), + commonjs({ + sourceMap: false, + }), + isProduction && terser(), + ], + }), + ]; } export default (commandLineArgs: any): RollupOptions[] => { const isDev = commandLineArgs.watch; const isProduction = !isDev; - return defineConfig([createConfig(isProduction)]); + return defineConfig(createConfig(isProduction)); }; diff --git a/packages/client-axios/rollup.dts.config.ts b/packages/client-axios/rollup.dts.config.ts --- a/packages/client-axios/rollup.dts.config.ts +++ b/packages/client-axios/rollup.dts.config.ts @@ -6,10 +6,10 @@ export default defineConfig({ external: externalDependencies, input: { - index: './temp/index.d.ts', + index: './temp/node/index.d.ts', }, output: { - dir: './dist', + dir: './dist/node', format: 'cjs', }, plugins: [dts({ respectExternal: true })], diff --git a/packages/client-core/package.json b/packages/client-core/package.json --- a/packages/client-core/package.json +++ b/packages/client-core/package.json @@ -13,13 +13,16 @@ "url": "https://github.com/hey-api/openapi-ts/issues" }, "license": "MIT", - "main": "./dist/index.cjs", - "types": "./dist/index.d.ts", + "exports": { + "import": "./dist/node/index.mjs", + "require": "./dist/node/index.cjs", + "types": "./dist/node/index.d.ts" + }, "scripts": { "build-bundle": "rollup --config rollup.config.ts --configPlugin typescript", "build-types-check": "tsc --project tsconfig.check.json", "build-types-roll": "rollup --config rollup.dts.config.ts --configPlugin typescript && rimraf temp", - "build-types-temp": "tsc --emitDeclarationOnly --outDir temp -p src", + "build-types-temp": "tsc --emitDeclarationOnly --outDir temp -p src/node", "build-types": "pnpm build-types-temp && pnpm build-types-roll && pnpm build-types-check", "build": "pnpm clean && pnpm build-bundle && pnpm build-types", "clean": "rimraf dist coverage node_modules/.cache", diff --git a/packages/client-core/rollup.config.ts b/packages/client-core/rollup.config.ts --- a/packages/client-core/rollup.config.ts +++ b/packages/client-core/rollup.config.ts @@ -20,28 +20,48 @@ ]; function createConfig(isProduction: boolean) { - return defineConfig({ - external: externalDependencies, - input: path.resolve(__dirname, 'src/index.ts'), - output: { - file: path.resolve(__dirname, 'dist/index.cjs'), - format: 'cjs', - }, - plugins: [ - typescript({ - declaration: false, - tsconfig: path.resolve(__dirname, 'src/tsconfig.json'), - }), - commonjs({ - sourceMap: false, - }), - isProduction && terser(), - ], - }); + return [ + defineConfig({ + external: externalDependencies, + input: path.resolve(__dirname, 'src/node/index.ts'), + output: { + file: path.resolve(__dirname, 'dist/node/index.cjs'), + format: 'cjs', + }, + plugins: [ + typescript({ + declaration: false, + tsconfig: path.resolve(__dirname, 'src/node/tsconfig.json'), + }), + commonjs({ + sourceMap: false, + }), + isProduction && terser(), + ], + }), + defineConfig({ + external: externalDependencies, + input: path.resolve(__dirname, 'src/node/index.ts'), + output: { + file: path.resolve(__dirname, 'dist/node/index.mjs'), + format: 'esm', + }, + plugins: [ + typescript({ + declaration: false, + tsconfig: path.resolve(__dirname, 'src/node/tsconfig.json'), + }), + commonjs({ + sourceMap: false, + }), + isProduction && terser(), + ], + }), + ]; } export default (commandLineArgs: any): RollupOptions[] => { const isDev = commandLineArgs.watch; const isProduction = !isDev; - return defineConfig([createConfig(isProduction)]); + return defineConfig(createConfig(isProduction)); }; diff --git a/packages/client-core/rollup.dts.config.ts b/packages/client-core/rollup.dts.config.ts --- a/packages/client-core/rollup.dts.config.ts +++ b/packages/client-core/rollup.dts.config.ts @@ -6,10 +6,10 @@ export default defineConfig({ external: externalDependencies, input: { - index: './temp/index.d.ts', + index: './temp/node/index.d.ts', }, output: { - dir: './dist', + dir: './dist/node', format: 'cjs', }, plugins: [dts({ respectExternal: true })], diff --git a/examples/openapi-ts-axios/src/App.css b/examples/openapi-ts-axios/src/App.css new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/App.css @@ -0,0 +1,102 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.flex { + align-items: center; + display: flex; + padding: 1em 0; +} + +.pet-name { + padding: 0 1em; +} + +.button { + border: 1px solid #444; +} + +#root { + max-width: 1280px; + margin: 0 auto; + padding: 0.5rem 2rem; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +.h1 { + font-size: 1.2em; + line-height: 1.1; +} + +.logo { + height: 4em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.container { + align-items: center; + display: flex; + grid-gap: 1em; + text-align: center; +} + +.openapi-ts { + color: #444; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/examples/openapi-ts-axios/src/App.tsx b/examples/openapi-ts-axios/src/App.tsx new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/App.tsx @@ -0,0 +1,56 @@ +import './App.css'; + +import { OpenAPI } from '@hey-api/client-axios'; +import { useState } from 'react'; + +import { $Pet } from './client/schemas.gen'; +import { PetService } from './client/services.gen'; + +OpenAPI.BASE = 'https://petstore3.swagger.io/api/v3'; + +// OpenAPI.interceptors.response.use((response) => { +// if (response.status === 200) { +// console.log(`request to ${response.url} was successful`); +// } +// return response; +// }); + +function App() { + const [pet, setPet] = + useState>>(); + + const onFetchPet = async () => { + const pet = await PetService.getPetById({ + // random id 1-10 + petId: Math.floor(Math.random() * (10 - 1 + 1) + 1), + }); + setPet(pet); + }; + + return ( + <> +
+ + Hey API logo + +

@hey-api/openapi-ts example

+
+
+ + Fetched pet's name: {pet?.name} +
+
+ {"import { $Pet } from './client/schemas.gen'"} +
{JSON.stringify($Pet, null, 2)}
+
+ + ); +} + +export default App; diff --git a/examples/openapi-ts-axios/src/index.css b/examples/openapi-ts-axios/src/index.css new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/index.css @@ -0,0 +1,68 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/examples/openapi-ts-axios/src/main.tsx b/examples/openapi-ts-axios/src/main.tsx new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/main.tsx @@ -0,0 +1,12 @@ +import './index.css'; + +import React from 'react'; +import ReactDOM from 'react-dom/client'; + +import App from './App.tsx'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/examples/openapi-ts-axios/src/vite-env.d.ts b/examples/openapi-ts-axios/src/vite-env.d.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/vite-env.d.ts @@ -0,0 +1,1 @@ +/// diff --git a/packages/client-axios/src/index.ts b/packages/client-axios/src/index.ts --- a/packages/client-axios/src/index.ts +++ b/packages/client-axios/src/index.ts @@ -25,6 +25,40 @@ } from 'axios'; import axios from 'axios'; +type Middleware = (value: T) => T | Promise; + +class Interceptors { + _fns: Middleware[]; + + constructor() { + this._fns = []; + } + + eject(fn: Middleware) { + const index = this._fns.indexOf(fn); + if (index !== -1) { + this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)]; + } + } + + use(fn: Middleware) { + this._fns = [...this._fns, fn]; + } +} + +export const OpenAPI: OpenAPIConfig = { + BASE: '', + CREDENTIALS: 'include', + ENCODE_PATH: undefined, + HEADERS: undefined, + PASSWORD: undefined, + TOKEN: undefined, + USERNAME: undefined, + VERSION: '1.26.0', + WITH_CREDENTIALS: false, + interceptors: { request: new Interceptors(), response: new Interceptors() }, +}; + export const getHeaders = async ( config: OpenAPIConfig, options: ApiRequestOptions, diff --git a/packages/client-axios/src/tsconfig.json b/packages/client-axios/src/tsconfig.json deleted file mode 100644 --- a/packages/client-axios/src/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "lib": ["ESNext"], - "stripInternal": true - }, - "exclude": ["./**/__tests__"], - "extends": "../tsconfig.base.json", - "include": ["./"] -} diff --git a/packages/client-core/src/index.ts b/packages/client-core/src/index.ts --- a/packages/client-core/src/index.ts +++ b/packages/client-core/src/index.ts @@ -7,7 +7,6 @@ } from './types'; export { CancelablePromise, CancelError, OnCancel } from './cancelablePromise'; -export type { ApiRequestOptions, ApiResult } from './types'; export class ApiError extends Error { public readonly url: string; @@ -51,7 +50,7 @@ } } -export type OpenAPIConfig = { +export type OpenAPIConfig = { BASE: string; CREDENTIALS: 'include' | 'omit' | 'same-origin'; ENCODE_PATH?: ((path: string) => string) | undefined; @@ -62,8 +61,8 @@ VERSION: string; WITH_CREDENTIALS: boolean; interceptors: { - request: Interceptors; - response: Interceptors; + request: Interceptors; + response: Interceptors; }; }; diff --git a/packages/client-core/src/tsconfig.json b/packages/client-core/src/tsconfig.json deleted file mode 100644 --- a/packages/client-core/src/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "lib": ["ESNext"], - "stripInternal": true - }, - "exclude": ["./**/__tests__"], - "extends": "../tsconfig.base.json", - "include": ["./"] -} diff --git a/packages/openapi-ts/src/index.ts b/packages/openapi-ts/src/index.ts --- a/packages/openapi-ts/src/index.ts +++ b/packages/openapi-ts/src/index.ts @@ -21,7 +21,8 @@ // Dependencies used in each client. User must have installed these to use the generated client const clientDependencies: Record = { - '@hey-api': [], + '@hey-api/client-axios': ['axios'], + '@hey-api/client-fetch': [], angular: ['@angular/common', '@angular/core', 'rxjs'], axios: ['axios'], fetch: [], @@ -93,12 +94,11 @@ }; const inferClient = (dependencies: Dependencies): Config['client'] => { - if ( - dependencies['@hey-api/client-axios'] || - dependencies['@hey-api/client-fetch'] || - dependencies['@hey-api/client-nextjs'] - ) { - return '@hey-api'; + if (dependencies['@hey-api/client-axios']) { + return '@hey-api/client-axios'; + } + if (dependencies['@hey-api/client-fetch']) { + return '@hey-api/client-fetch'; } if (dependencies.axios) { return 'axios'; @@ -297,7 +297,7 @@ debug, dryRun, enums, - exportCore: client === '@hey-api' ? false : exportCore, + exportCore: client.startsWith('@hey-api') ? false : exportCore, format, input, lint, diff --git a/examples/openapi-ts-axios/src/client/index.ts b/examples/openapi-ts-axios/src/client/index.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/client/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts +export * from './schemas.gen'; +export * from './services.gen'; +export * from './types.gen'; diff --git a/examples/openapi-ts-axios/src/client/schemas.gen.ts b/examples/openapi-ts-axios/src/client/schemas.gen.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/client/schemas.gen.ts @@ -0,0 +1,244 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export const $Order = { + properties: { + complete: { + type: 'boolean', + }, + id: { + example: 10, + format: 'int64', + type: 'integer', + }, + petId: { + example: 198772, + format: 'int64', + type: 'integer', + }, + quantity: { + example: 7, + format: 'int32', + type: 'integer', + }, + shipDate: { + format: 'date-time', + type: 'string', + }, + status: { + description: 'Order Status', + enum: ['placed', 'approved', 'delivered'], + example: 'approved', + type: 'string', + }, + }, + type: 'object', + 'x-swagger-router-model': 'io.swagger.petstore.model.Order', + xml: { + name: 'order', + }, +} as const; + +export const $Customer = { + properties: { + address: { + items: { + $ref: '#/components/schemas/Address', + }, + type: 'array', + xml: { + name: 'addresses', + wrapped: true, + }, + }, + id: { + example: 100000, + format: 'int64', + type: 'integer', + }, + username: { + example: 'fehguy', + type: 'string', + }, + }, + type: 'object', + xml: { + name: 'customer', + }, +} as const; + +export const $Address = { + properties: { + city: { + example: 'Palo Alto', + type: 'string', + }, + state: { + example: 'CA', + type: 'string', + }, + street: { + example: '437 Lytton', + type: 'string', + }, + zip: { + example: 94301, + type: 'string', + }, + }, + type: 'object', + xml: { + name: 'address', + }, +} as const; + +export const $Category = { + properties: { + id: { + example: 1, + format: 'int64', + type: 'integer', + }, + name: { + example: 'Dogs', + type: 'string', + }, + }, + type: 'object', + 'x-swagger-router-model': 'io.swagger.petstore.model.Category', + xml: { + name: 'category', + }, +} as const; + +export const $User = { + properties: { + email: { + example: 'john@email.com', + type: 'string', + }, + firstName: { + example: 'John', + type: 'string', + }, + id: { + example: 10, + format: 'int64', + type: 'integer', + }, + lastName: { + example: 'James', + type: 'string', + }, + password: { + example: 12345, + type: 'string', + }, + phone: { + example: 12345, + type: 'string', + }, + userStatus: { + description: 'User Status', + example: 1, + format: 'int32', + type: 'integer', + }, + username: { + example: 'theUser', + type: 'string', + }, + }, + type: 'object', + 'x-swagger-router-model': 'io.swagger.petstore.model.User', + xml: { + name: 'user', + }, +} as const; + +export const $Tag = { + properties: { + id: { + format: 'int64', + type: 'integer', + }, + name: { + type: 'string', + }, + }, + type: 'object', + 'x-swagger-router-model': 'io.swagger.petstore.model.Tag', + xml: { + name: 'tag', + }, +} as const; + +export const $Pet = { + properties: { + category: { + $ref: '#/components/schemas/Category', + }, + id: { + example: 10, + format: 'int64', + type: 'integer', + }, + name: { + example: 'doggie', + type: 'string', + }, + photoUrls: { + items: { + type: 'string', + xml: { + name: 'photoUrl', + }, + }, + type: 'array', + xml: { + wrapped: true, + }, + }, + status: { + description: 'pet status in the store', + enum: ['available', 'pending', 'sold'], + type: 'string', + }, + tags: { + items: { + $ref: '#/components/schemas/Tag', + xml: { + name: 'tag', + }, + }, + type: 'array', + xml: { + wrapped: true, + }, + }, + }, + required: ['name', 'photoUrls'], + type: 'object', + 'x-swagger-router-model': 'io.swagger.petstore.model.Pet', + xml: { + name: 'pet', + }, +} as const; + +export const $ApiResponse = { + properties: { + code: { + format: 'int32', + type: 'integer', + }, + message: { + type: 'string', + }, + type: { + type: 'string', + }, + }, + type: 'object', + xml: { + name: '##default', + }, +} as const; diff --git a/examples/openapi-ts-axios/src/client/services.gen.ts b/examples/openapi-ts-axios/src/client/services.gen.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/client/services.gen.ts @@ -0,0 +1,444 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { CancelablePromise } from '@hey-api/client-axios'; +import { OpenAPI } from '@hey-api/client-axios'; +import { request as __request } from '@hey-api/client-axios'; + +import type { $OpenApiTs } from './types.gen'; + +export class PetService { + /** + * Add a new pet to the store + * Add a new pet to the store + * @param data The data for the request. + * @param data.requestBody Create a new pet in the store + * @returns Pet Successful operation + * @throws ApiError + */ + public static addPet( + data: $OpenApiTs['/pet']['post']['req'], + ): CancelablePromise<$OpenApiTs['/pet']['post']['res'][200]> { + return __request(OpenAPI, { + body: data.requestBody, + errors: { + 405: 'Invalid input', + }, + mediaType: 'application/json', + method: 'POST', + url: '/pet', + }); + } + + /** + * Update an existing pet + * Update an existing pet by Id + * @param data The data for the request. + * @param data.requestBody Update an existent pet in the store + * @returns Pet Successful operation + * @throws ApiError + */ + public static updatePet( + data: $OpenApiTs['/pet']['put']['req'], + ): CancelablePromise<$OpenApiTs['/pet']['put']['res'][200]> { + return __request(OpenAPI, { + body: data.requestBody, + errors: { + 400: 'Invalid ID supplied', + 404: 'Pet not found', + 405: 'Validation exception', + }, + mediaType: 'application/json', + method: 'PUT', + url: '/pet', + }); + } + + /** + * Finds Pets by status + * Multiple status values can be provided with comma separated strings + * @param data The data for the request. + * @param data.status Status values that need to be considered for filter + * @returns Pet successful operation + * @throws ApiError + */ + public static findPetsByStatus( + data: $OpenApiTs['/pet/findByStatus']['get']['req'] = {}, + ): CancelablePromise<$OpenApiTs['/pet/findByStatus']['get']['res'][200]> { + return __request(OpenAPI, { + errors: { + 400: 'Invalid status value', + }, + method: 'GET', + query: { + status: data.status, + }, + url: '/pet/findByStatus', + }); + } + + /** + * Finds Pets by tags + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * @param data The data for the request. + * @param data.tags Tags to filter by + * @returns Pet successful operation + * @throws ApiError + */ + public static findPetsByTags( + data: $OpenApiTs['/pet/findByTags']['get']['req'] = {}, + ): CancelablePromise<$OpenApiTs['/pet/findByTags']['get']['res'][200]> { + return __request(OpenAPI, { + errors: { + 400: 'Invalid tag value', + }, + method: 'GET', + query: { + tags: data.tags, + }, + url: '/pet/findByTags', + }); + } + + /** + * Find pet by ID + * Returns a single pet + * @param data The data for the request. + * @param data.petId ID of pet to return + * @returns Pet successful operation + * @throws ApiError + */ + public static getPetById( + data: $OpenApiTs['/pet/{petId}']['get']['req'], + ): CancelablePromise<$OpenApiTs['/pet/{petId}']['get']['res'][200]> { + return __request(OpenAPI, { + errors: { + 400: 'Invalid ID supplied', + 404: 'Pet not found', + }, + method: 'GET', + path: { + petId: data.petId, + }, + url: '/pet/{petId}', + }); + } + + /** + * Updates a pet in the store with form data + * @param data The data for the request. + * @param data.petId ID of pet that needs to be updated + * @param data.name Name of pet that needs to be updated + * @param data.status Status of pet that needs to be updated + * @throws ApiError + */ + public static updatePetWithForm( + data: $OpenApiTs['/pet/{petId}']['post']['req'], + ): CancelablePromise { + return __request(OpenAPI, { + errors: { + 405: 'Invalid input', + }, + method: 'POST', + path: { + petId: data.petId, + }, + query: { + name: data.name, + status: data.status, + }, + url: '/pet/{petId}', + }); + } + + /** + * Deletes a pet + * @param data The data for the request. + * @param data.petId Pet id to delete + * @param data.apiKey + * @throws ApiError + */ + public static deletePet( + data: $OpenApiTs['/pet/{petId}']['delete']['req'], + ): CancelablePromise { + return __request(OpenAPI, { + errors: { + 400: 'Invalid pet value', + }, + headers: { + api_key: data.apiKey, + }, + method: 'DELETE', + path: { + petId: data.petId, + }, + url: '/pet/{petId}', + }); + } + + /** + * uploads an image + * @param data The data for the request. + * @param data.petId ID of pet to update + * @param data.additionalMetadata Additional Metadata + * @param data.requestBody + * @returns ApiResponse successful operation + * @throws ApiError + */ + public static uploadFile( + data: $OpenApiTs['/pet/{petId}/uploadImage']['post']['req'], + ): CancelablePromise< + $OpenApiTs['/pet/{petId}/uploadImage']['post']['res'][200] + > { + return __request(OpenAPI, { + body: data.requestBody, + mediaType: 'application/octet-stream', + method: 'POST', + path: { + petId: data.petId, + }, + query: { + additionalMetadata: data.additionalMetadata, + }, + url: '/pet/{petId}/uploadImage', + }); + } +} + +export class StoreService { + /** + * Returns pet inventories by status + * Returns a map of status codes to quantities + * @returns number successful operation + * @throws ApiError + */ + public static getInventory(): CancelablePromise< + $OpenApiTs['/store/inventory']['get']['res'][200] + > { + return __request(OpenAPI, { + method: 'GET', + url: '/store/inventory', + }); + } + + /** + * Place an order for a pet + * Place a new order in the store + * @param data The data for the request. + * @param data.requestBody + * @returns Order successful operation + * @throws ApiError + */ + public static placeOrder( + data: $OpenApiTs['/store/order']['post']['req'] = {}, + ): CancelablePromise<$OpenApiTs['/store/order']['post']['res'][200]> { + return __request(OpenAPI, { + body: data.requestBody, + errors: { + 405: 'Invalid input', + }, + mediaType: 'application/json', + method: 'POST', + url: '/store/order', + }); + } + + /** + * Find purchase order by ID + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions. + * @param data The data for the request. + * @param data.orderId ID of order that needs to be fetched + * @returns Order successful operation + * @throws ApiError + */ + public static getOrderById( + data: $OpenApiTs['/store/order/{orderId}']['get']['req'], + ): CancelablePromise< + $OpenApiTs['/store/order/{orderId}']['get']['res'][200] + > { + return __request(OpenAPI, { + errors: { + 400: 'Invalid ID supplied', + 404: 'Order not found', + }, + method: 'GET', + path: { + orderId: data.orderId, + }, + url: '/store/order/{orderId}', + }); + } + + /** + * Delete purchase order by ID + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * @param data The data for the request. + * @param data.orderId ID of the order that needs to be deleted + * @throws ApiError + */ + public static deleteOrder( + data: $OpenApiTs['/store/order/{orderId}']['delete']['req'], + ): CancelablePromise { + return __request(OpenAPI, { + errors: { + 400: 'Invalid ID supplied', + 404: 'Order not found', + }, + method: 'DELETE', + path: { + orderId: data.orderId, + }, + url: '/store/order/{orderId}', + }); + } +} + +export class UserService { + /** + * Create user + * This can only be done by the logged in user. + * @param data The data for the request. + * @param data.requestBody Created user object + * @returns User successful operation + * @throws ApiError + */ + public static createUser( + data: $OpenApiTs['/user']['post']['req'] = {}, + ): CancelablePromise<$OpenApiTs['/user']['post']['res'][200]> { + return __request(OpenAPI, { + body: data.requestBody, + mediaType: 'application/json', + method: 'POST', + url: '/user', + }); + } + + /** + * Creates list of users with given input array + * Creates list of users with given input array + * @param data The data for the request. + * @param data.requestBody + * @returns User Successful operation + * @returns unknown successful operation + * @throws ApiError + */ + public static createUsersWithListInput( + data: $OpenApiTs['/user/createWithList']['post']['req'] = {}, + ): CancelablePromise< + | $OpenApiTs['/user/createWithList']['post']['res'][200] + | $OpenApiTs['/user/createWithList']['post']['res'][200] + > { + return __request(OpenAPI, { + body: data.requestBody, + mediaType: 'application/json', + method: 'POST', + url: '/user/createWithList', + }); + } + + /** + * Logs user into the system + * @param data The data for the request. + * @param data.username The user name for login + * @param data.password The password for login in clear text + * @returns string successful operation + * @throws ApiError + */ + public static loginUser( + data: $OpenApiTs['/user/login']['get']['req'] = {}, + ): CancelablePromise<$OpenApiTs['/user/login']['get']['res'][200]> { + return __request(OpenAPI, { + errors: { + 400: 'Invalid username/password supplied', + }, + method: 'GET', + query: { + password: data.password, + username: data.username, + }, + url: '/user/login', + }); + } + + /** + * Logs out current logged in user session + * @returns unknown successful operation + * @throws ApiError + */ + public static logoutUser(): CancelablePromise< + $OpenApiTs['/user/logout']['get']['res'][200] + > { + return __request(OpenAPI, { + method: 'GET', + url: '/user/logout', + }); + } + + /** + * Get user by user name + * @param data The data for the request. + * @param data.username The name that needs to be fetched. Use user1 for testing. + * @returns User successful operation + * @throws ApiError + */ + public static getUserByName( + data: $OpenApiTs['/user/{username}']['get']['req'], + ): CancelablePromise<$OpenApiTs['/user/{username}']['get']['res'][200]> { + return __request(OpenAPI, { + errors: { + 400: 'Invalid username supplied', + 404: 'User not found', + }, + method: 'GET', + path: { + username: data.username, + }, + url: '/user/{username}', + }); + } + + /** + * Update user + * This can only be done by the logged in user. + * @param data The data for the request. + * @param data.username name that needs to be updated + * @param data.requestBody Update an existent user in the store + * @returns unknown successful operation + * @throws ApiError + */ + public static updateUser( + data: $OpenApiTs['/user/{username}']['put']['req'], + ): CancelablePromise<$OpenApiTs['/user/{username}']['put']['res'][200]> { + return __request(OpenAPI, { + body: data.requestBody, + mediaType: 'application/json', + method: 'PUT', + path: { + username: data.username, + }, + url: '/user/{username}', + }); + } + + /** + * Delete user + * This can only be done by the logged in user. + * @param data The data for the request. + * @param data.username The name that needs to be deleted + * @throws ApiError + */ + public static deleteUser( + data: $OpenApiTs['/user/{username}']['delete']['req'], + ): CancelablePromise { + return __request(OpenAPI, { + errors: { + 400: 'Invalid username supplied', + 404: 'User not found', + }, + method: 'DELETE', + path: { + username: data.username, + }, + url: '/user/{username}', + }); + } +} diff --git a/examples/openapi-ts-axios/src/client/types.gen.ts b/examples/openapi-ts-axios/src/client/types.gen.ts new file mode 100644 --- /dev/null +++ b/examples/openapi-ts-axios/src/client/types.gen.ts @@ -0,0 +1,433 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type Order = { + id?: number; + petId?: number; + quantity?: number; + shipDate?: string; + /** + * Order Status + */ + status?: 'placed' | 'approved' | 'delivered'; + complete?: boolean; +}; + +export type Customer = { + id?: number; + username?: string; + address?: Array
; +}; + +export type Address = { + street?: string; + city?: string; + state?: string; + zip?: string; +}; + +export type Category = { + id?: number; + name?: string; +}; + +export type User = { + id?: number; + username?: string; + firstName?: string; + lastName?: string; + email?: string; + password?: string; + phone?: string; + /** + * User Status + */ + userStatus?: number; +}; + +export type Tag = { + id?: number; + name?: string; +}; + +export type Pet = { + id?: number; + name: string; + category?: Category; + photoUrls: Array; + tags?: Array; + /** + * pet status in the store + */ + status?: 'available' | 'pending' | 'sold'; +}; + +export type ApiResponse = { + code?: number; + type?: string; + message?: string; +}; + +export type $OpenApiTs = { + '/pet': { + post: { + req: { + /** + * Create a new pet in the store + */ + requestBody: Pet; + }; + res: { + /** + * Successful operation + */ + 200: Pet; + /** + * Invalid input + */ + 405: unknown; + }; + }; + put: { + req: { + /** + * Update an existent pet in the store + */ + requestBody: Pet; + }; + res: { + /** + * Successful operation + */ + 200: Pet; + /** + * Invalid ID supplied + */ + 400: unknown; + /** + * Pet not found + */ + 404: unknown; + /** + * Validation exception + */ + 405: unknown; + }; + }; + }; + '/pet/findByStatus': { + get: { + req: { + /** + * Status values that need to be considered for filter + */ + status?: 'available' | 'pending' | 'sold'; + }; + res: { + /** + * successful operation + */ + 200: Array; + /** + * Invalid status value + */ + 400: unknown; + }; + }; + }; + '/pet/findByTags': { + get: { + req: { + /** + * Tags to filter by + */ + tags?: Array; + }; + res: { + /** + * successful operation + */ + 200: Array; + /** + * Invalid tag value + */ + 400: unknown; + }; + }; + }; + '/pet/{petId}': { + get: { + req: { + /** + * ID of pet to return + */ + petId: number; + }; + res: { + /** + * successful operation + */ + 200: Pet; + /** + * Invalid ID supplied + */ + 400: unknown; + /** + * Pet not found + */ + 404: unknown; + }; + }; + post: { + req: { + /** + * Name of pet that needs to be updated + */ + name?: string; + /** + * ID of pet that needs to be updated + */ + petId: number; + /** + * Status of pet that needs to be updated + */ + status?: string; + }; + res: { + /** + * Invalid input + */ + 405: unknown; + }; + }; + delete: { + req: { + apiKey?: string; + /** + * Pet id to delete + */ + petId: number; + }; + res: { + /** + * Invalid pet value + */ + 400: unknown; + }; + }; + }; + '/pet/{petId}/uploadImage': { + post: { + req: { + /** + * Additional Metadata + */ + additionalMetadata?: string; + /** + * ID of pet to update + */ + petId: number; + requestBody?: Blob | File; + }; + res: { + /** + * successful operation + */ + 200: ApiResponse; + }; + }; + }; + '/store/inventory': { + get: { + res: { + /** + * successful operation + */ + 200: { + [key: string]: number; + }; + }; + }; + }; + '/store/order': { + post: { + req: { + requestBody?: Order; + }; + res: { + /** + * successful operation + */ + 200: Order; + /** + * Invalid input + */ + 405: unknown; + }; + }; + }; + '/store/order/{orderId}': { + get: { + req: { + /** + * ID of order that needs to be fetched + */ + orderId: number; + }; + res: { + /** + * successful operation + */ + 200: Order; + /** + * Invalid ID supplied + */ + 400: unknown; + /** + * Order not found + */ + 404: unknown; + }; + }; + delete: { + req: { + /** + * ID of the order that needs to be deleted + */ + orderId: number; + }; + res: { + /** + * Invalid ID supplied + */ + 400: unknown; + /** + * Order not found + */ + 404: unknown; + }; + }; + }; + '/user': { + post: { + req: { + /** + * Created user object + */ + requestBody?: User; + }; + res: { + /** + * successful operation + */ + 200: User; + }; + }; + }; + '/user/createWithList': { + post: { + req: { + requestBody?: Array; + }; + res: { + /** + * successful operation + */ + 200: unknown; + }; + }; + }; + '/user/login': { + get: { + req: { + /** + * The password for login in clear text + */ + password?: string; + /** + * The user name for login + */ + username?: string; + }; + res: { + /** + * successful operation + */ + 200: string; + /** + * Invalid username/password supplied + */ + 400: unknown; + }; + }; + }; + '/user/logout': { + get: { + res: { + /** + * successful operation + */ + 200: unknown; + }; + }; + }; + '/user/{username}': { + get: { + req: { + /** + * The name that needs to be fetched. Use user1 for testing. + */ + username: string; + }; + res: { + /** + * successful operation + */ + 200: User; + /** + * Invalid username supplied + */ + 400: unknown; + /** + * User not found + */ + 404: unknown; + }; + }; + put: { + req: { + /** + * Update an existent user in the store + */ + requestBody?: User; + /** + * name that needs to be updated + */ + username: string; + }; + res: { + /** + * successful operation + */ + 200: unknown; + }; + }; + delete: { + req: { + /** + * The name that needs to be deleted + */ + username: string; + }; + res: { + /** + * Invalid username supplied + */ + 400: unknown; + /** + * User not found + */ + 404: unknown; + }; + }; + }; +}; diff --git a/packages/client-axios/src/node/index.ts b/packages/client-axios/src/node/index.ts new file mode 100644 --- /dev/null +++ b/packages/client-axios/src/node/index.ts @@ -0,0 +1,2 @@ +export { OpenAPI, request } from '../'; +export type { CancelablePromise } from '@hey-api/client-core'; diff --git a/packages/client-axios/src/node/tsconfig.json b/packages/client-axios/src/node/tsconfig.json new file mode 100644 --- /dev/null +++ b/packages/client-axios/src/node/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "lib": ["ES2020", "DOM"], + "stripInternal": true + }, + "exclude": ["../**/__tests__"], + "extends": "../../tsconfig.base.json", + "include": ["../"] +} diff --git a/packages/client-core/src/node/index.ts b/packages/client-core/src/node/index.ts new file mode 100644 --- /dev/null +++ b/packages/client-core/src/node/index.ts @@ -0,0 +1,21 @@ +export { + ApiError, + base64, + CancelablePromise, + CancelError, + catchErrorCodes, + getFormData, + getQueryString, + getUrl, + Interceptors, + isBlob, + isFormData, + isString, + isStringWithValue, + isSuccess, + OnCancel, + OpenAPI, + type OpenAPIConfig, + resolve, +} from '../'; +export type { ApiRequestOptions, ApiResult } from '../types'; diff --git a/packages/client-core/src/node/tsconfig.json b/packages/client-core/src/node/tsconfig.json new file mode 100644 --- /dev/null +++ b/packages/client-core/src/node/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "lib": ["ES2020", "DOM"], + "stripInternal": true + }, + "exclude": ["../**/__tests__"], + "extends": "../../tsconfig.base.json", + "include": ["../"] +} diff --git a/packages/openapi-ts/src/types/config.ts b/packages/openapi-ts/src/types/config.ts --- a/packages/openapi-ts/src/types/config.ts +++ b/packages/openapi-ts/src/types/config.ts @@ -7,7 +7,14 @@ * The selected HTTP client (fetch, xhr, node or axios) * @default 'fetch' */ - client?: '@hey-api' | 'angular' | 'axios' | 'fetch' | 'node' | 'xhr'; + client?: + | '@hey-api/client-axios' + | '@hey-api/client-fetch' + | 'angular' + | 'axios' + | 'fetch' + | 'node' + | 'xhr'; /** * Run in debug mode? * @default false diff --git a/packages/openapi-ts/src/utils/getHttpRequestName.ts b/packages/openapi-ts/src/utils/getHttpRequestName.ts --- a/packages/openapi-ts/src/utils/getHttpRequestName.ts +++ b/packages/openapi-ts/src/utils/getHttpRequestName.ts @@ -6,8 +6,6 @@ */ export const getHttpRequestName = (client: Config['client']): string => { switch (client) { - case '@hey-api': - return ''; case 'angular': return 'AngularHttpRequest'; case 'axios': @@ -18,5 +16,7 @@ return 'NodeHttpRequest'; case 'xhr': return 'XHRHttpRequest'; + default: + return ''; } }; diff --git a/packages/openapi-ts/src/utils/write/services.ts b/packages/openapi-ts/src/utils/write/services.ts --- a/packages/openapi-ts/src/utils/write/services.ts +++ b/packages/openapi-ts/src/utils/write/services.ts @@ -288,33 +288,52 @@ // Import required packages and core files. if (config.client === 'angular') { file.addNamedImport('Injectable', '@angular/core'); - if (config.name === undefined) { + + if (!config.name) { file.addNamedImport('HttpClient', '@angular/common/http'); } + file.addNamedImport({ isTypeOnly: true, name: 'Observable' }, 'rxjs'); } else { - file.addNamedImport( - { isTypeOnly: true, name: 'CancelablePromise' }, - './core/CancelablePromise', - ); + if (config.client.startsWith('@hey-api')) { + file.addNamedImport( + { isTypeOnly: true, name: 'CancelablePromise' }, + config.client, + ); + } else { + file.addNamedImport( + { isTypeOnly: true, name: 'CancelablePromise' }, + './core/CancelablePromise', + ); + } } + if (config.services.response === 'response') { file.addNamedImport( { isTypeOnly: true, name: 'ApiResult' }, './core/ApiResult', ); } + if (config.name) { file.addNamedImport( { isTypeOnly: config.client !== 'angular', name: 'BaseHttpRequest' }, './core/BaseHttpRequest', ); } else { - file.addNamedImport('OpenAPI', './core/OpenAPI'); - file.addNamedImport( - { alias: '__request', name: 'request' }, - './core/request', - ); + if (config.client.startsWith('@hey-api')) { + file.addNamedImport('OpenAPI', config.client); + file.addNamedImport( + { alias: '__request', name: 'request' }, + config.client, + ); + } else { + file.addNamedImport('OpenAPI', './core/OpenAPI'); + file.addNamedImport( + { alias: '__request', name: 'request' }, + './core/request', + ); + } } // Import all models required by the services. -- tangled.sh