mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- Added axios client
- Added function to escape path and stopped replacement of ":" character in path
This commit is contained in:
parent
de3a44ae1b
commit
5b3348d6f9
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@ -6,3 +6,6 @@ updates:
|
||||
interval: weekly
|
||||
time: "04:00"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: "@types/node-fetch"
|
||||
- dependency-name: "node-fetch"
|
||||
|
||||
30
README.md
30
README.md
@ -15,7 +15,7 @@
|
||||
- Frontend ❤️ OpenAPI, but we do not want to use JAVA codegen in our builds
|
||||
- Quick, lightweight, robust and framework agnostic 🚀
|
||||
- Supports generation of TypeScript clients
|
||||
- Supports generations of fetch and XHR http clients
|
||||
- Supports generations of fetch, XHR and Axios http clients
|
||||
- Supports OpenAPI specification v2.0 and v3.0
|
||||
- Supports JSON and YAML files for input
|
||||
- Supports generation through CLI, Node.js and NPX
|
||||
@ -40,7 +40,7 @@ $ openapi --help
|
||||
-V, --version output the version number
|
||||
-i, --input <value> OpenAPI specification, can be a path, url or string content (required)
|
||||
-o, --output <value> Output directory (required)
|
||||
-c, --client <value> HTTP client to generate [fetch, xhr, node] (default: "fetch")
|
||||
-c, --client <value> HTTP client to generate [fetch, xhr, axios, node] (default: "fetch")
|
||||
--useOptions Use options instead of arguments
|
||||
--useUnionTypes Use union types instead of enums
|
||||
--exportCore <value> Write core files to disk (default: true)
|
||||
@ -403,12 +403,12 @@ as part of your types to ensure everything is able to be TypeScript generated.
|
||||
|
||||
External references may be:
|
||||
* *relative references* - references to other files at the same location e.g.
|
||||
`{ $ref: 'schemas/customer.yml' }`
|
||||
`{ $ref: 'schemas/customer.yml' }`
|
||||
* *remote references* - fully qualified references to another remote location
|
||||
e.g. `{ $ref: 'https://myexampledomain.com/schemas/customer_schema.yml' }`
|
||||
e.g. `{ $ref: 'https://myexampledomain.com/schemas/customer_schema.yml' }`
|
||||
|
||||
For remote references, both files (when the file is on the current filesystem)
|
||||
and http(s) URLs are supported.
|
||||
For remote references, both files (when the file is on the current filesystem)
|
||||
and http(s) URLs are supported.
|
||||
|
||||
External references may also contain internal paths in the external schema (e.g.
|
||||
`schemas/collection.yml#/definitions/schemas/Customer`) and back-references to
|
||||
@ -419,14 +419,6 @@ At start-up, an OpenAPI or Swagger file with external references will be "bundle
|
||||
so that all external references and back-references will be resolved (but local
|
||||
references preserved).
|
||||
|
||||
### Compare to other generators
|
||||
Depending on which swagger generator you use, you will see different output.
|
||||
For instance: Different ways of generating models, services, level of quality,
|
||||
HTTP client, etc. I've compiled a list with the results per area and how they
|
||||
compare against the openapi-typescript-codegen.
|
||||
|
||||
[Click here to see the comparison](https://htmlpreview.github.io/?https://github.com/ferdikoomen/openapi-typescript-codegen/blob/master/samples/index.html)
|
||||
|
||||
|
||||
FAQ
|
||||
===
|
||||
@ -452,6 +444,9 @@ module.exports = {
|
||||
|
||||
|
||||
### Node.js support
|
||||
> Since version 3.x [`node-fetch`](https://www.npmjs.com/package/node-fetch) switched to ESM only, breaking many
|
||||
> CommonJS based toolchains (like Jest). Right now we do not support this new version!
|
||||
|
||||
By default, this library will generate a client that is compatible with the (browser based) [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),
|
||||
however this client will not work inside the Node.js environment. If you want to generate a Node.js compatible client then
|
||||
you can specify `--client node` in the openapi call:
|
||||
@ -459,11 +454,12 @@ you can specify `--client node` in the openapi call:
|
||||
`openapi --input ./spec.json --output ./dist --client node`
|
||||
|
||||
This will generate a client that uses [`node-fetch`](https://www.npmjs.com/package/node-fetch) internally. However,
|
||||
in order to compile and run this client, you will need to install the `node-fetch@2.x` dependencies:
|
||||
in order to compile and run this client, you might need to install the `node-fetch@2.x` dependencies:
|
||||
|
||||
```
|
||||
npm install node-fetch --save-dev
|
||||
npm install form-data --save-dev
|
||||
npm install @types/node-fetch@2.x --save-dev
|
||||
npm install node-fetch@2.x --save-dev
|
||||
npm install form-data@4.x --save-dev
|
||||
```
|
||||
|
||||
In order to compile the project and resolve the imports, you will need to enable the `allowSyntheticDefaultImports`
|
||||
|
||||
@ -12,7 +12,7 @@ const params = program
|
||||
.version(pkg.version)
|
||||
.requiredOption('-i, --input <value>', 'OpenAPI specification, can be a path, url or string content (required)')
|
||||
.requiredOption('-o, --output <value>', 'Output directory (required)')
|
||||
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node]', 'fetch')
|
||||
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node, axios]', 'fetch')
|
||||
.option('--useOptions', 'Use options instead of arguments')
|
||||
.option('--useUnionTypes', 'Use union types instead of enums')
|
||||
.option('--exportCore <value>', 'Write core files to disk', true)
|
||||
|
||||
@ -20,10 +20,12 @@ module.exports = {
|
||||
testMatch: [
|
||||
'<rootDir>/test/e2e/v2.fetch.spec.js',
|
||||
'<rootDir>/test/e2e/v2.xhr.spec.js',
|
||||
'<rootDir>/test/e2e/v2.axios.spec.js',
|
||||
'<rootDir>/test/e2e/v2.node.spec.js',
|
||||
'<rootDir>/test/e2e/v2.babel.spec.js',
|
||||
'<rootDir>/test/e2e/v3.fetch.spec.js',
|
||||
'<rootDir>/test/e2e/v3.xhr.spec.js',
|
||||
'<rootDir>/test/e2e/v3.axios.spec.js',
|
||||
'<rootDir>/test/e2e/v3.node.spec.js',
|
||||
'<rootDir>/test/e2e/v3.babel.spec.js',
|
||||
],
|
||||
|
||||
13
package.json
13
package.json
@ -32,7 +32,6 @@
|
||||
}
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"bin": {
|
||||
"openapi": "bin/index.js"
|
||||
@ -61,7 +60,8 @@
|
||||
"codecov": "codecov --token=66c30c23-8954-4892-bef9-fbaed0a2e42b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node-fetch": "^3.0.3",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"axios": "^0.22.0",
|
||||
"camelcase": "^6.2.0",
|
||||
"commander": "^8.0.0",
|
||||
"form-data": "^4.0.0",
|
||||
@ -69,23 +69,24 @@
|
||||
"js-yaml": "^4.0.0",
|
||||
"json-schema-ref-parser": "^9.0.7",
|
||||
"mkdirp": "^1.0.4",
|
||||
"node-fetch": "^3.0.0",
|
||||
"node-fetch": "^2.6.5",
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.15.7",
|
||||
"@babel/core": "7.15.5",
|
||||
"@babel/preset-env": "7.15.6",
|
||||
"@babel/core": "7.15.8",
|
||||
"@babel/preset-env": "7.15.8",
|
||||
"@babel/preset-typescript": "7.15.0",
|
||||
"@rollup/plugin-commonjs": "21.0.0",
|
||||
"@rollup/plugin-node-resolve": "13.0.5",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/glob": "7.1.4",
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/js-yaml": "4.0.3",
|
||||
"@types/node": "16.10.3",
|
||||
"@types/qs": "6.9.7",
|
||||
"@typescript-eslint/eslint-plugin": "4.33.0",
|
||||
"@typescript-eslint/parser": "4.32.0",
|
||||
"@typescript-eslint/parser": "4.33.0",
|
||||
"codecov": "3.8.3",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
|
||||
@ -1,274 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="google" value="notranslate">
|
||||
<meta http-equiv="Content-Language" content="en_EN">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" crossorigin="anonymous">
|
||||
<title>Compared to other generators</title>
|
||||
<style>
|
||||
details summary {
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<section class="page-header">
|
||||
<h1>Compared to other generators</h1>
|
||||
<p class="lead">
|
||||
Depending on which swagger generator you use, you will see different output. For instance:
|
||||
Different ways of generating models, services, level of quality, HTTP client, etc.
|
||||
I've compiled a list below with the results per area and how they compare
|
||||
against the <strong>openapi-typescript-codegen.</strong>
|
||||
</p>
|
||||
</section>
|
||||
<h5>I've used the standard petshop examples from OpenAPI:</h5>
|
||||
<ul>
|
||||
<li><a href="https://petstore3.swagger.io/api/v3/openapi.json" target="_blank">https://petstore3.swagger.io/api/v3/openapi.json</a></li>
|
||||
<li><a href="https://petstore.swagger.io/v2/swagger.json" target="_blank">https://petstore.swagger.io/v2/swagger.json</a></li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<h5>And used the following generators with their default options:</h5>
|
||||
<ul>
|
||||
<li>typescript-aurelia</li>
|
||||
<li>typescript-angular</li>
|
||||
<li>typescript-inversify</li>
|
||||
<li>typescript-angular</li>
|
||||
<li>typescript-fetch</li>
|
||||
<li>typescript-jquery</li>
|
||||
<li>typescript-node</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="30%"></th>
|
||||
<th width="10%">openapi-typescript-codegen</th>
|
||||
<th width="10%">aurelia</th>
|
||||
<th width="10%">inversify</th>
|
||||
<th width="10%">angular</th>
|
||||
<th width="10%">fetch</th>
|
||||
<th width="10%">jquery</th>
|
||||
<th width="10%">node</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Supports OpenApi v2 specification</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Supports OpenApi v3 specification</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="danger" data-type="aurelia">❌</td>
|
||||
<td class="danger" data-type="inversify">❌</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="danger" data-type="jquery">❌</td>
|
||||
<td class="danger" data-type="node">❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Supports authentication</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="danger" data-type="aurelia">❌</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Strongly typed models</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Strongly typed enums</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Models and services exported as individual files</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="danger" data-type="aurelia">❌</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="danger" data-type="fetch">❌</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="danger" data-type="node">❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Index file that exports all services and models</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="danger" data-type="inversify">❌</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="danger" data-type="node">❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Service returns typed result</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="danger" data-type="fetch">❌</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Service supports sending and receiving binary content</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="warning" data-type="angular">
|
||||
<span>⚠️</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>V3 version sends data as <code>application/octet-stream</code> instead of <code>application/x-www-form-urlencoded</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="warning" data-type="fetch">
|
||||
<span>⚠️</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>V3 version sends data as <code>application/octet-stream</code> instead of <code>application/x-www-form-urlencoded</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Models and services contain inline documentation</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="success" data-type="aurelia">✅</td>
|
||||
<td class="success" data-type="inversify">✅</td>
|
||||
<td class="success" data-type="angular">✅</td>
|
||||
<td class="success" data-type="fetch">✅</td>
|
||||
<td class="success" data-type="jquery">✅</td>
|
||||
<td class="success" data-type="node">✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Framework agnostic</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="danger" data-type="aurelia">❌</td>
|
||||
<td class="danger" data-type="inversify">❌</td>
|
||||
<td class="danger" data-type="angular">❌</td>
|
||||
<td class="warning" data-type="node">
|
||||
<span>⚠️</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Requires portable-fetch</p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="danger" data-type="jquery">❌</td>
|
||||
<td class="warning" data-type="node">
|
||||
<span>⚠️</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Requires bluebird</p>
|
||||
</details>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Compiles in strict mode without issues</th>
|
||||
<td class="success" data-type="openapi-typescript-codegen">✅</td>
|
||||
<td class="danger" data-type="aurelia">
|
||||
<span>❌</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Errors when compiling: <code>PetApi.ts:147:30 - error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="danger" data-type="inversify">
|
||||
<span>❌</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Errors when compiling: <code>pet.service.ts:312:159 - error TS2304: Cannot find name 'body'</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="danger" data-type="angular">
|
||||
<span>❌</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Errors when compiling: <code>pet.service.ts:528:26 - error TS1345: An expression of type 'void' cannot be tested for truthiness</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="danger" data-type="fetch">
|
||||
<span>❌</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Errors when compiling: <code>api.ts:2276:67 - error TS2300: Duplicate identifier 'username'</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="danger" data-type="jquery">
|
||||
<span>❌</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Errors when compiling: <code>PetApi.ts:25:12 - error TS2322: Type 'null' is not assignable to type 'JQueryAjaxSettings | undefined'</code></p>
|
||||
</details>
|
||||
</td>
|
||||
<td class="danger" data-type="node">
|
||||
<span>❌</span>
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
<p>Errors when compiling: <code>api.ts:1631:45 - error TS2694: Namespace '"http"' has no exported member 'ClientResponse'</code></p>
|
||||
</details>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Generated size (typescript)</th>
|
||||
<td data-type="openapi-typescript-codegen"><span class="badge">30KB</span></td>
|
||||
<td data-type="aurelia"><span class="badge">29KB</span></td>
|
||||
<td data-type="inversify"><span class="badge">37KB</span></td>
|
||||
<td data-type="angular"><span class="badge">63KB</span></td>
|
||||
<td data-type="fetch"><span class="badge">85KB</span></td>
|
||||
<td data-type="jquery"><span class="badge">57KB</span></td>
|
||||
<td data-type="node"><span class="badge">65KB</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Build size (javascript, not minimized)</th>
|
||||
<td data-type="openapi-typescript-codegen"><span class="badge">17KB</span></td>
|
||||
<td data-type="aurelia"><span class="badge">16KB</span></td>
|
||||
<td data-type="inversify"><span class="badge">22KB</span></td>
|
||||
<td data-type="angular"><span class="badge">36KB</span></td>
|
||||
<td data-type="fetch"><span class="badge">48KB</span></td>
|
||||
<td data-type="jquery"><span class="badge">37KB</span></td>
|
||||
<td data-type="node"><span class="badge">53KB</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Generation time</th>
|
||||
<td data-type="openapi-typescript-codegen"><span class="badge">0.2s</span></td>
|
||||
<td data-type="aurelia"><span class="badge">0.7s</span></td>
|
||||
<td data-type="inversify"><span class="badge">0.7s</span></td>
|
||||
<td data-type="angular"><span class="badge">1.4s</span></td>
|
||||
<td data-type="fetch"><span class="badge">1.1s</span></td>
|
||||
<td data-type="jquery"><span class="badge">0.7s</span></td>
|
||||
<td data-type="node"><span class="badge">0.7s</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -2,4 +2,5 @@ export enum HttpClient {
|
||||
FETCH = 'fetch',
|
||||
XHR = 'xhr',
|
||||
NODE = 'node',
|
||||
AXIOS = 'axios',
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ export type Options = {
|
||||
* service layer, etc.
|
||||
* @param input The relative location of the OpenAPI spec
|
||||
* @param output The relative location of the output directory
|
||||
* @param httpClient The selected httpClient (fetch or XHR)
|
||||
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
|
||||
* @param useOptions Use options or arguments functions
|
||||
* @param useUnionTypes Use union types instead of enums
|
||||
* @param exportCore: Generate core client classes
|
||||
|
||||
@ -7,6 +7,7 @@ describe('getModelTemplate', () => {
|
||||
base: 'Link',
|
||||
template: 'Model',
|
||||
imports: ['Model'],
|
||||
isNullable: false,
|
||||
});
|
||||
expect(template).toEqual('<T>');
|
||||
});
|
||||
@ -17,6 +18,7 @@ describe('getModelTemplate', () => {
|
||||
base: 'string',
|
||||
template: null,
|
||||
imports: [],
|
||||
isNullable: false,
|
||||
});
|
||||
expect(template).toEqual('');
|
||||
});
|
||||
|
||||
@ -7,6 +7,7 @@ describe('getModelTemplate', () => {
|
||||
base: 'Link',
|
||||
template: 'Model',
|
||||
imports: ['Model'],
|
||||
isNullable: false,
|
||||
});
|
||||
expect(template).toEqual('<T>');
|
||||
});
|
||||
@ -17,6 +18,7 @@ describe('getModelTemplate', () => {
|
||||
base: 'string',
|
||||
template: null,
|
||||
imports: [],
|
||||
isNullable: false,
|
||||
});
|
||||
expect(template).toEqual('');
|
||||
});
|
||||
|
||||
@ -13,6 +13,7 @@ type Config = {
|
||||
USERNAME?: string | Resolver<string>;
|
||||
PASSWORD?: string | Resolver<string>;
|
||||
HEADERS?: Headers | Resolver<Headers>;
|
||||
ENCODE_PATH?: (path: string) => string;
|
||||
}
|
||||
|
||||
export const OpenAPI: Config = {
|
||||
@ -23,4 +24,5 @@ export const OpenAPI: Config = {
|
||||
USERNAME: undefined,
|
||||
PASSWORD: undefined,
|
||||
HEADERS: undefined,
|
||||
ENCODE_PATH: undefined,
|
||||
};
|
||||
|
||||
29
src/templates/core/axios/getHeaders.hbs
Normal file
29
src/templates/core/axios/getHeaders.hbs
Normal file
@ -0,0 +1,29 @@
|
||||
async function getHeaders(options: ApiRequestOptions, formData?: FormData): Promise<Record<string, string>> {
|
||||
const token = await resolve(options, OpenAPI.TOKEN);
|
||||
const username = await resolve(options, OpenAPI.USERNAME);
|
||||
const password = await resolve(options, OpenAPI.PASSWORD);
|
||||
const additionalHeaders = await resolve(options, OpenAPI.HEADERS);
|
||||
|
||||
const headers = Object.entries({
|
||||
Accept: 'application/json',
|
||||
...additionalHeaders,
|
||||
...options.headers,
|
||||
...formData?.getHeaders()
|
||||
})
|
||||
.filter(([key, value]) => isDefined(value))
|
||||
.reduce((headers, [key, value]) => ({
|
||||
...headers,
|
||||
[key]: value,
|
||||
}), {} as Record<string, string>);
|
||||
|
||||
if (isStringWithValue(token)) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = base64(`${username}:${password}`);
|
||||
headers['Authorization'] = `Basic ${credentials}`;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
6
src/templates/core/axios/getResponseBody.hbs
Normal file
6
src/templates/core/axios/getResponseBody.hbs
Normal file
@ -0,0 +1,6 @@
|
||||
function getResponseBody(response: AxiosResponse<any>): any {
|
||||
if (response.status !== 204) {
|
||||
return response.data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
9
src/templates/core/axios/getResponseHeader.hbs
Normal file
9
src/templates/core/axios/getResponseHeader.hbs
Normal file
@ -0,0 +1,9 @@
|
||||
function getResponseHeader(response: AxiosResponse<any>, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = response.headers[responseHeader];
|
||||
if (isString(content)) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
75
src/templates/core/axios/request.hbs
Normal file
75
src/templates/core/axios/request.hbs
Normal file
@ -0,0 +1,75 @@
|
||||
{{>header}}
|
||||
|
||||
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import FormData from 'form-data';
|
||||
|
||||
import { ApiError } from './ApiError';
|
||||
import type { ApiRequestOptions } from './ApiRequestOptions';
|
||||
import type { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
{{>functions/isDefined}}
|
||||
|
||||
|
||||
{{>functions/isString}}
|
||||
|
||||
|
||||
{{>functions/isStringWithValue}}
|
||||
|
||||
|
||||
{{>functions/isSuccess}}
|
||||
|
||||
|
||||
{{>functions/base64}}
|
||||
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
|
||||
{{>functions/getUrl}}
|
||||
|
||||
|
||||
{{>functions/getFormData}}
|
||||
|
||||
|
||||
{{>functions/resolve}}
|
||||
|
||||
|
||||
{{>axios/getHeaders}}
|
||||
|
||||
|
||||
{{>axios/sendRequest}}
|
||||
|
||||
|
||||
{{>axios/getResponseHeader}}
|
||||
|
||||
|
||||
{{>axios/getResponseBody}}
|
||||
|
||||
|
||||
{{>functions/catchErrors}}
|
||||
|
||||
|
||||
/**
|
||||
* Request using axios client
|
||||
* @param options The request options from the the service
|
||||
* @returns ApiResult
|
||||
* @throws ApiError
|
||||
*/
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
const url = getUrl(options);
|
||||
const response = await sendRequest(options, url);
|
||||
const responseBody = getResponseBody(response);
|
||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||
|
||||
const result: ApiResult = {
|
||||
url,
|
||||
ok: isSuccess(response.status),
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: responseHeader || responseBody,
|
||||
};
|
||||
|
||||
catchErrors(options, result);
|
||||
return result;
|
||||
}
|
||||
11
src/templates/core/axios/sendRequest.hbs
Normal file
11
src/templates/core/axios/sendRequest.hbs
Normal file
@ -0,0 +1,11 @@
|
||||
async function sendRequest(options: ApiRequestOptions, url: string): Promise<AxiosResponse<any>> {
|
||||
const formData = options.formData && getFormData(options.formData);
|
||||
const data = formData || options.body;
|
||||
const config: AxiosRequestConfig = {
|
||||
url,
|
||||
data,
|
||||
method: options.method,
|
||||
headers: await getHeaders(options, formData),
|
||||
};
|
||||
return await axios.request(config);
|
||||
}
|
||||
@ -22,7 +22,7 @@ async function getHeaders(options: ApiRequestOptions): Promise<Headers> {
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = btoa(`${username}:${password}`);
|
||||
const credentials = base64(`${username}:${password}`);
|
||||
headers.append('Authorization', `Basic ${credentials}`);
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,9 @@ import { OpenAPI } from './OpenAPI';
|
||||
{{>functions/isBlob}}
|
||||
|
||||
|
||||
{{>functions/base64}}
|
||||
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
|
||||
|
||||
7
src/templates/core/functions/base64.hbs
Normal file
7
src/templates/core/functions/base64.hbs
Normal file
@ -0,0 +1,7 @@
|
||||
function base64(str: string): string {
|
||||
try {
|
||||
return btoa(str);
|
||||
} catch (err) {
|
||||
return Buffer.from(str).toString('base64');
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
function getUrl(options: ApiRequestOptions): string {
|
||||
const path = options.path.replace(/[:]/g, '_');
|
||||
const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path;
|
||||
const url = `${OpenAPI.BASE}${path}`;
|
||||
|
||||
if (options.query) {
|
||||
return `${url}${getQueryString(options.query)}`;
|
||||
}
|
||||
|
||||
@ -22,14 +22,14 @@ async function getHeaders(options: ApiRequestOptions): Promise<Headers> {
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
||||
const credentials = base64(`${username}:${password}`);
|
||||
headers.append('Authorization', `Basic ${credentials}`);
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
if (options.mediaType) {
|
||||
headers.append('Content-Type', options.mediaType);
|
||||
} else if (isBlob(options.body) || isBinary(options.body)) {
|
||||
} else if (isBinary(options.body)) {
|
||||
headers.append('Content-Type', 'application/octet-stream');
|
||||
} else if (isString(options.body)) {
|
||||
headers.append('Content-Type', 'text/plain');
|
||||
|
||||
@ -24,6 +24,9 @@ import { OpenAPI } from './OpenAPI';
|
||||
{{>functions/isBinary}}
|
||||
|
||||
|
||||
{{>functions/base64}}
|
||||
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
{{~#equals @root.httpClient 'fetch'}}{{>fetch/request}}{{/equals~}}
|
||||
{{~#equals @root.httpClient 'xhr'}}{{>xhr/request}}{{/equals~}}
|
||||
{{~#equals @root.httpClient 'axios'}}{{>axios/request}}{{/equals~}}
|
||||
{{~#equals @root.httpClient 'node'}}{{>node/request}}{{/equals~}}
|
||||
|
||||
@ -22,7 +22,7 @@ async function getHeaders(options: ApiRequestOptions): Promise<Headers> {
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = btoa(`${username}:${password}`);
|
||||
const credentials = base64(`${username}:${password}`);
|
||||
headers.append('Authorization', `Basic ${credentials}`);
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,9 @@ import { OpenAPI } from './OpenAPI';
|
||||
{{>functions/isSuccess}}
|
||||
|
||||
|
||||
{{>functions/base64}}
|
||||
|
||||
|
||||
{{>functions/getQueryString}}
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
{{~#equals base 'File'~}}
|
||||
{{~#equals @root.httpClient 'fetch'}}Blob{{/equals~}}
|
||||
{{~#equals @root.httpClient 'xhr'}}Blob{{/equals~}}
|
||||
{{~#equals @root.httpClient 'node'}}Blob | Buffer | ArrayBuffer | ArrayBufferView{{/equals~}}
|
||||
{{~#equals @root.httpClient 'axios'}}Blob{{/equals~}}
|
||||
{{~#equals @root.httpClient 'node'}}Buffer | ArrayBuffer | ArrayBufferView{{/equals~}}
|
||||
{{~else~}}
|
||||
{{{base}}}
|
||||
{{~/equals~}}
|
||||
|
||||
@ -4,12 +4,18 @@ import { HttpClient } from '../HttpClient';
|
||||
import templateCoreApiError from '../templates/core/ApiError.hbs';
|
||||
import templateCoreApiRequestOptions from '../templates/core/ApiRequestOptions.hbs';
|
||||
import templateCoreApiResult from '../templates/core/ApiResult.hbs';
|
||||
import axiosGetHeaders from '../templates/core/axios/getHeaders.hbs';
|
||||
import axiosGetResponseBody from '../templates/core/axios/getResponseBody.hbs';
|
||||
import axiosGetResponseHeader from '../templates/core/axios/getResponseHeader.hbs';
|
||||
import axiosRequest from '../templates/core/axios/request.hbs';
|
||||
import axiosSendRequest from '../templates/core/axios/sendRequest.hbs';
|
||||
import fetchGetHeaders from '../templates/core/fetch/getHeaders.hbs';
|
||||
import fetchGetRequestBody from '../templates/core/fetch/getRequestBody.hbs';
|
||||
import fetchGetResponseBody from '../templates/core/fetch/getResponseBody.hbs';
|
||||
import fetchGetResponseHeader from '../templates/core/fetch/getResponseHeader.hbs';
|
||||
import fetchRequest from '../templates/core/fetch/request.hbs';
|
||||
import fetchSendRequest from '../templates/core/fetch/sendRequest.hbs';
|
||||
import functionBase64 from '../templates/core/functions/base64.hbs';
|
||||
import functionCatchErrors from '../templates/core/functions/catchErrors.hbs';
|
||||
import functionGetFormData from '../templates/core/functions/getFormData.hbs';
|
||||
import functionGetQueryString from '../templates/core/functions/getQueryString.hbs';
|
||||
@ -148,6 +154,7 @@ export function registerHandlebarTemplates(root: { httpClient: HttpClient; useOp
|
||||
Handlebars.registerPartial('functions/isString', Handlebars.template(functionIsString));
|
||||
Handlebars.registerPartial('functions/isStringWithValue', Handlebars.template(functionIsStringWithValue));
|
||||
Handlebars.registerPartial('functions/isSuccess', Handlebars.template(functionIsSuccess));
|
||||
Handlebars.registerPartial('functions/base64', Handlebars.template(functionBase64));
|
||||
Handlebars.registerPartial('functions/resolve', Handlebars.template(functionResolve));
|
||||
|
||||
// Specific files for the fetch client implementation
|
||||
@ -174,5 +181,12 @@ export function registerHandlebarTemplates(root: { httpClient: HttpClient; useOp
|
||||
Handlebars.registerPartial('node/sendRequest', Handlebars.template(nodeSendRequest));
|
||||
Handlebars.registerPartial('node/request', Handlebars.template(nodeRequest));
|
||||
|
||||
// Specific files for the axios client implementation
|
||||
Handlebars.registerPartial('axios/getHeaders', Handlebars.template(axiosGetHeaders));
|
||||
Handlebars.registerPartial('axios/getResponseBody', Handlebars.template(axiosGetResponseBody));
|
||||
Handlebars.registerPartial('axios/getResponseHeader', Handlebars.template(axiosGetResponseHeader));
|
||||
Handlebars.registerPartial('axios/sendRequest', Handlebars.template(axiosSendRequest));
|
||||
Handlebars.registerPartial('axios/request', Handlebars.template(axiosRequest));
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import { writeClientServices } from './writeClientServices';
|
||||
* @param client Client object with all the models, services, etc.
|
||||
* @param templates Templates wrapper with all loaded Handlebars templates
|
||||
* @param output The relative location of the output directory
|
||||
* @param httpClient The selected httpClient (fetch, xhr or node)
|
||||
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
|
||||
* @param useOptions Use options or arguments functions
|
||||
* @param useUnionTypes Use union types instead of enums
|
||||
* @param exportCore: Generate core client classes
|
||||
|
||||
@ -10,7 +10,7 @@ import { Templates } from './registerHandlebarTemplates';
|
||||
* @param client Client object, containing, models, schemas and services
|
||||
* @param templates The loaded handlebar templates
|
||||
* @param outputPath Directory to write the generated files to
|
||||
* @param httpClient The selected httpClient (fetch, xhr or node)
|
||||
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
|
||||
* @param request: Path to custom request file
|
||||
*/
|
||||
export async function writeClientCore(client: Client, templates: Templates, outputPath: string, httpClient: HttpClient, request?: string): Promise<void> {
|
||||
|
||||
@ -11,7 +11,7 @@ import { Templates } from './registerHandlebarTemplates';
|
||||
* @param models Array of Models to write
|
||||
* @param templates The loaded handlebar templates
|
||||
* @param outputPath Directory to write the generated files to
|
||||
* @param httpClient The selected httpClient (fetch, xhr or node)
|
||||
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
|
||||
* @param useUnionTypes Use union types instead of enums
|
||||
*/
|
||||
export async function writeClientModels(models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean): Promise<void> {
|
||||
|
||||
@ -11,7 +11,7 @@ import { Templates } from './registerHandlebarTemplates';
|
||||
* @param models Array of Models to write
|
||||
* @param templates The loaded handlebar templates
|
||||
* @param outputPath Directory to write the generated files to
|
||||
* @param httpClient The selected httpClient (fetch, xhr or node)
|
||||
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
|
||||
* @param useUnionTypes Use union types instead of enums
|
||||
*/
|
||||
export async function writeClientSchemas(models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean): Promise<void> {
|
||||
|
||||
@ -13,7 +13,7 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION';
|
||||
* @param services Array of Services to write
|
||||
* @param templates The loaded handlebar templates
|
||||
* @param outputPath Directory to write the generated files to
|
||||
* @param httpClient The selected httpClient (fetch, xhr or node)
|
||||
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
|
||||
* @param useUnionTypes Use union types instead of enums
|
||||
* @param useOptions Use options or arguments functions
|
||||
*/
|
||||
|
||||
@ -71,6 +71,7 @@ type Config = {
|
||||
USERNAME?: string | Resolver<string>;
|
||||
PASSWORD?: string | Resolver<string>;
|
||||
HEADERS?: Headers | Resolver<Headers>;
|
||||
ENCODE_PATH?: (path: string) => string;
|
||||
}
|
||||
|
||||
export const OpenAPI: Config = {
|
||||
@ -81,6 +82,7 @@ export const OpenAPI: Config = {
|
||||
USERNAME: undefined,
|
||||
PASSWORD: undefined,
|
||||
HEADERS: undefined,
|
||||
ENCODE_PATH: undefined,
|
||||
};"
|
||||
`;
|
||||
|
||||
@ -109,6 +111,14 @@ function isBlob(value: any): value is Blob {
|
||||
return value instanceof Blob;
|
||||
}
|
||||
|
||||
function base64(str: string): string {
|
||||
try {
|
||||
return btoa(str);
|
||||
} catch (err) {
|
||||
return Buffer.from(str).toString('base64');
|
||||
}
|
||||
}
|
||||
|
||||
function getQueryString(params: Record<string, any>): string {
|
||||
const qs: string[] = [];
|
||||
Object.keys(params).forEach(key => {
|
||||
@ -130,9 +140,8 @@ function getQueryString(params: Record<string, any>): string {
|
||||
}
|
||||
|
||||
function getUrl(options: ApiRequestOptions): string {
|
||||
const path = options.path.replace(/[:]/g, '_');
|
||||
const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path;
|
||||
const url = \`\${OpenAPI.BASE}\${path}\`;
|
||||
|
||||
if (options.query) {
|
||||
return \`\${url}\${getQueryString(options.query)}\`;
|
||||
}
|
||||
@ -183,7 +192,7 @@ async function getHeaders(options: ApiRequestOptions): Promise<Headers> {
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = btoa(\`\${username}:\${password}\`);
|
||||
const credentials = base64(\`\${username}:\${password}\`);
|
||||
headers.append('Authorization', \`Basic \${credentials}\`);
|
||||
}
|
||||
|
||||
@ -2433,6 +2442,7 @@ type Config = {
|
||||
USERNAME?: string | Resolver<string>;
|
||||
PASSWORD?: string | Resolver<string>;
|
||||
HEADERS?: Headers | Resolver<Headers>;
|
||||
ENCODE_PATH?: (path: string) => string;
|
||||
}
|
||||
|
||||
export const OpenAPI: Config = {
|
||||
@ -2443,6 +2453,7 @@ export const OpenAPI: Config = {
|
||||
USERNAME: undefined,
|
||||
PASSWORD: undefined,
|
||||
HEADERS: undefined,
|
||||
ENCODE_PATH: undefined,
|
||||
};"
|
||||
`;
|
||||
|
||||
@ -2471,6 +2482,14 @@ function isBlob(value: any): value is Blob {
|
||||
return value instanceof Blob;
|
||||
}
|
||||
|
||||
function base64(str: string): string {
|
||||
try {
|
||||
return btoa(str);
|
||||
} catch (err) {
|
||||
return Buffer.from(str).toString('base64');
|
||||
}
|
||||
}
|
||||
|
||||
function getQueryString(params: Record<string, any>): string {
|
||||
const qs: string[] = [];
|
||||
Object.keys(params).forEach(key => {
|
||||
@ -2492,9 +2511,8 @@ function getQueryString(params: Record<string, any>): string {
|
||||
}
|
||||
|
||||
function getUrl(options: ApiRequestOptions): string {
|
||||
const path = options.path.replace(/[:]/g, '_');
|
||||
const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path;
|
||||
const url = \`\${OpenAPI.BASE}\${path}\`;
|
||||
|
||||
if (options.query) {
|
||||
return \`\${url}\${getQueryString(options.query)}\`;
|
||||
}
|
||||
@ -2545,7 +2563,7 @@ async function getHeaders(options: ApiRequestOptions): Promise<Headers> {
|
||||
}
|
||||
|
||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||
const credentials = btoa(\`\${username}:\${password}\`);
|
||||
const credentials = base64(\`\${username}:\${password}\`);
|
||||
headers.append('Authorization', \`Basic \${credentials}\`);
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ import type { ApiResult } from './ApiResult';
|
||||
import { OpenAPI } from './OpenAPI';
|
||||
|
||||
export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
|
||||
const url = `${OpenAPI.BASE}${options.path}`;
|
||||
|
||||
// Do your request...
|
||||
@ -17,7 +16,7 @@ export async function request(options: ApiRequestOptions): Promise<ApiResult> {
|
||||
status: 200,
|
||||
statusText: 'dummy',
|
||||
body: {
|
||||
...options
|
||||
...options,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
let browser;
|
||||
let page
|
||||
let page;
|
||||
|
||||
async function start() {
|
||||
// This starts the a new puppeteer browser (Chrome)
|
||||
|
||||
@ -22,7 +22,7 @@ function compileWithTypescript(dir) {
|
||||
strictNullChecks: true,
|
||||
strictFunctionTypes: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
skipLibCheck: true
|
||||
skipLibCheck: true,
|
||||
},
|
||||
include: ['./index.ts'],
|
||||
};
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
const express = require('express');
|
||||
|
||||
let app;
|
||||
let server
|
||||
let server;
|
||||
|
||||
async function start(dir) {
|
||||
return new Promise(resolve => {
|
||||
|
||||
38
test/e2e/v2.axios.spec.js
Normal file
38
test/e2e/v2.axios.spec.js
Normal file
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
const generate = require('./scripts/generate');
|
||||
const compileWithTypescript = require('./scripts/compileWithTypescript');
|
||||
const server = require('./scripts/server');
|
||||
|
||||
describe('v2.node', () => {
|
||||
beforeAll(async () => {
|
||||
await generate('v2/axios', 'v2', 'axios');
|
||||
compileWithTypescript('v2/axios');
|
||||
await server.start('v2/axios');
|
||||
}, 30000);
|
||||
|
||||
afterAll(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('requests token', async () => {
|
||||
const { OpenAPI, SimpleService } = require('./generated/v2/axios/index.js');
|
||||
const tokenRequest = jest.fn().mockResolvedValue('MY_TOKEN');
|
||||
OpenAPI.TOKEN = tokenRequest;
|
||||
const result = await SimpleService.getCallWithoutParametersAndResponse();
|
||||
expect(tokenRequest.mock.calls.length).toBe(1);
|
||||
expect(result.headers.authorization).toBe('Bearer MY_TOKEN');
|
||||
});
|
||||
|
||||
it('complexService', async () => {
|
||||
const { ComplexService } = require('./generated/v2/axios/index.js');
|
||||
const result = await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -7,7 +7,6 @@ const server = require('./scripts/server');
|
||||
const browser = require('./scripts/browser');
|
||||
|
||||
describe('v2.fetch', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await generate('v2/babel', 'v2', 'fetch', true, true);
|
||||
await copy('v2/babel');
|
||||
@ -37,9 +36,9 @@ describe('v2.fetch', () => {
|
||||
return await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
|
||||
@ -7,7 +7,6 @@ const server = require('./scripts/server');
|
||||
const browser = require('./scripts/browser');
|
||||
|
||||
describe('v2.fetch', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await generate('v2/fetch', 'v2', 'fetch');
|
||||
await copy('v2/fetch');
|
||||
@ -37,9 +36,9 @@ describe('v2.fetch', () => {
|
||||
return await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
|
||||
@ -30,9 +30,9 @@ describe('v2.node', () => {
|
||||
const result = await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
@ -7,7 +7,6 @@ const server = require('./scripts/server');
|
||||
const browser = require('./scripts/browser');
|
||||
|
||||
describe('v2.xhr', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await generate('v2/xhr', 'v2', 'xhr');
|
||||
await copy('v2/xhr');
|
||||
@ -37,9 +36,9 @@ describe('v2.xhr', () => {
|
||||
return await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
|
||||
64
test/e2e/v3.axios.spec.js
Normal file
64
test/e2e/v3.axios.spec.js
Normal file
@ -0,0 +1,64 @@
|
||||
'use strict';
|
||||
|
||||
const generate = require('./scripts/generate');
|
||||
const compileWithTypescript = require('./scripts/compileWithTypescript');
|
||||
const server = require('./scripts/server');
|
||||
|
||||
describe('v3.node', () => {
|
||||
beforeAll(async () => {
|
||||
await generate('v3/axios', 'v3', 'axios');
|
||||
compileWithTypescript('v3/axios');
|
||||
await server.start('v3/axios');
|
||||
}, 30000);
|
||||
|
||||
afterAll(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
it('requests token', async () => {
|
||||
const { OpenAPI, SimpleService } = require('./generated/v3/axios/index.js');
|
||||
const tokenRequest = jest.fn().mockResolvedValue('MY_TOKEN');
|
||||
OpenAPI.TOKEN = tokenRequest;
|
||||
OpenAPI.USERNAME = undefined;
|
||||
OpenAPI.PASSWORD = undefined;
|
||||
const result = await SimpleService.getCallWithoutParametersAndResponse();
|
||||
expect(tokenRequest.mock.calls.length).toBe(1);
|
||||
expect(result.headers.authorization).toBe('Bearer MY_TOKEN');
|
||||
});
|
||||
|
||||
it('uses credentials', async () => {
|
||||
const { OpenAPI, SimpleService } = require('./generated/v3/axios/index.js');
|
||||
OpenAPI.TOKEN = undefined;
|
||||
OpenAPI.USERNAME = 'username';
|
||||
OpenAPI.PASSWORD = 'password';
|
||||
const result = await SimpleService.getCallWithoutParametersAndResponse();
|
||||
expect(result.headers.authorization).toBe('Basic dXNlcm5hbWU6cGFzc3dvcmQ=');
|
||||
});
|
||||
|
||||
it('complexService', async () => {
|
||||
const { ComplexService } = require('./generated/v3/axios/index.js');
|
||||
const result = await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
it('formData', async () => {
|
||||
const { ParametersService } = require('./generated/v3/axios/index.js');
|
||||
const result = await ParametersService.callWithParameters(
|
||||
'valueHeader',
|
||||
'valueQuery',
|
||||
'valueForm',
|
||||
'valueCookie',
|
||||
'valuePath',
|
||||
{
|
||||
prop: 'valueBody',
|
||||
},
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -7,7 +7,6 @@ const server = require('./scripts/server');
|
||||
const browser = require('./scripts/browser');
|
||||
|
||||
describe('v3.fetch', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await generate('v3/babel', 'v3', 'fetch', true, true);
|
||||
await copy('v3/babel');
|
||||
@ -50,9 +49,9 @@ describe('v3.fetch', () => {
|
||||
return await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
|
||||
@ -7,7 +7,6 @@ const server = require('./scripts/server');
|
||||
const browser = require('./scripts/browser');
|
||||
|
||||
describe('v3.fetch', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await generate('v3/fetch', 'v3', 'fetch');
|
||||
await copy('v3/fetch');
|
||||
@ -50,9 +49,9 @@ describe('v3.fetch', () => {
|
||||
return await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
@ -61,18 +60,10 @@ describe('v3.fetch', () => {
|
||||
it('formData', async () => {
|
||||
const result = await browser.evaluate(async () => {
|
||||
const { ParametersService } = window.api;
|
||||
return await ParametersService.callWithParameters(
|
||||
'valueHeader',
|
||||
'valueQuery',
|
||||
'valueForm',
|
||||
'valueCookie',
|
||||
'valuePath',
|
||||
{
|
||||
prop: 'valueBody'
|
||||
}
|
||||
);
|
||||
return await ParametersService.callWithParameters('valueHeader', 'valueQuery', 'valueForm', 'valueCookie', 'valuePath', {
|
||||
prop: 'valueBody',
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -41,9 +41,9 @@ describe('v3.node', () => {
|
||||
const result = await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
@ -57,8 +57,8 @@ describe('v3.node', () => {
|
||||
'valueCookie',
|
||||
'valuePath',
|
||||
{
|
||||
prop: 'valueBody'
|
||||
}
|
||||
prop: 'valueBody',
|
||||
},
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
@ -7,7 +7,6 @@ const server = require('./scripts/server');
|
||||
const browser = require('./scripts/browser');
|
||||
|
||||
describe('v3.xhr', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await generate('v3/xhr', 'v3', 'xhr');
|
||||
await copy('v3/xhr');
|
||||
@ -50,9 +49,9 @@ describe('v3.xhr', () => {
|
||||
return await ComplexService.complexTypes({
|
||||
first: {
|
||||
second: {
|
||||
third: 'Hello World!'
|
||||
}
|
||||
}
|
||||
third: 'Hello World!',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
|
||||
1
types/index.d.ts
vendored
1
types/index.d.ts
vendored
@ -2,6 +2,7 @@ export declare enum HttpClient {
|
||||
FETCH = 'fetch',
|
||||
XHR = 'xhr',
|
||||
NODE = 'node',
|
||||
AXIOS = 'axios',
|
||||
}
|
||||
|
||||
export type Options = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user