Skip to content

Commit 8d5e458

Browse files
authored
Merge pull request #944 from ferdikoomen/feature/angular
Feature/angular
2 parents be3b248 + ff1cb27 commit 8d5e458

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+5278
-902
lines changed

README.md

Lines changed: 22 additions & 462 deletions
Large diffs are not rendered by default.

bin/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const params = program
1212
.version(pkg.version)
1313
.requiredOption('-i, --input <value>', 'OpenAPI specification, can be a path, url or string content (required)')
1414
.requiredOption('-o, --output <value>', 'Output directory (required)')
15-
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node, axios]', 'fetch')
15+
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node, axios, angular]', 'fetch')
1616
.option('--name <value>', 'Custom client class name')
1717
.option('--useOptions', 'Use options instead of arguments')
1818
.option('--useUnionTypes', 'Use union types instead of enums')

docs/angular-support.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Angular support
2+
3+
This tool allows you to generate a client based on the [`Angular HttpClient`](https://angular.io/guide/http).
4+
The generated services are fully injectable and make use of the [RxJS](https://rxjs.dev/) Observer pattern.
5+
If you want to generate the Angular based client then you can specify `--client angular` in the openapi call:
6+
7+
`openapi --input ./spec.json --output ./generated --client angular`
8+
9+
The Angular client has been tested with the following versions:
10+
11+
```
12+
"@angular/common": "13.1.3",
13+
"@angular/core": "13.1.3",
14+
"rxjs": "7.5.2",
15+
```
16+
17+
## Example
18+
19+
In the AppModule you can import the services and add them to the list of injectable services:
20+
21+
```typescript
22+
import { HttpClientModule } from '@angular/common/http';
23+
import { NgModule } from '@angular/core';
24+
import { BrowserModule } from '@angular/platform-browser';
25+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
26+
27+
import { OrganizationService } from './generated/services/OrganizationService';
28+
29+
@NgModule({
30+
imports: [
31+
BrowserModule,
32+
HttpClientModule,
33+
],
34+
providers: [
35+
OrganizationService,
36+
],
37+
bootstrap: [
38+
AppComponent,
39+
],
40+
})
41+
export class AppModule {}
42+
43+
platformBrowserDynamic()
44+
.bootstrapModule(AppModule)
45+
.catch(err => console.error(err));
46+
```
47+
48+
Inside the component you can inject the service and just use it as you would with any observable:
49+
50+
```typescript
51+
import { Component } from '@angular/core';
52+
53+
import type { OrganizationService } from './generated/services/OrganizationService';
54+
55+
@Component({
56+
selector: 'app-root',
57+
template: `<div>Angular is ready</div>`,
58+
})
59+
export class AppComponent {
60+
constructor(private readonly organizationService: OrganizationService) {
61+
62+
// Make a call
63+
this.organizationService
64+
.createOrganization({
65+
name: 'OrgName',
66+
description: 'OrgDescription',
67+
})
68+
.subscribe(organization => {
69+
console.log(organization);
70+
});
71+
72+
// Or even map result and retry on error
73+
this.organizationService
74+
.getOrganizations()
75+
.pipe(
76+
map(organizations => organizations[0]),
77+
retryWhen(error => error)
78+
)
79+
.subscribe(organization => {
80+
console.log(organization);
81+
});
82+
}
83+
}
84+
```

docs/arguments-vs-object-style.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Arguments vs. Object style
2+
3+
**Flag:** `--useOptions`
4+
5+
There's no [named parameter](https://en.wikipedia.org/wiki/Named_parameter) in JavaScript or TypeScript, because of
6+
that, we offer the flag `--useOptions` to generate code in two different styles.
7+
8+
**Argument style:**
9+
10+
```typescript
11+
const createUser = (name: string, password: string, type?: string, address?: string) => {
12+
// ...
13+
};
14+
15+
// Usage
16+
createUser('Jack', '123456', undefined, 'NY US');
17+
```
18+
19+
**Object style:**
20+
21+
```typescript
22+
const createUser = ({ name, password, type, address }: {
23+
name: string,
24+
password: string,
25+
type?: string
26+
address?: string
27+
}) => {
28+
// ...
29+
};
30+
31+
// Usage
32+
createUser({
33+
name: 'Jack',
34+
password: '123456',
35+
address: 'NY US'
36+
});
37+
```

docs/authorization.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Authorization
2+
3+
The OpenAPI generator supports Bearer Token authorization. In order to enable the sending
4+
of tokens in each request you can set the token using the global OpenAPI configuration:
5+
6+
```typescript
7+
import { OpenAPI } from './generated';
8+
9+
OpenAPI.TOKEN = 'some-bearer-token';
10+
```
11+
12+
Alternatively, we also support an async method that provides the token for each request.
13+
You can simply assign this method to the same `TOKEN `property in the global OpenAPI object.
14+
15+
```typescript
16+
import { OpenAPI } from './generated';
17+
18+
const getToken = async () => {
19+
// Some code that requests a token...
20+
return 'SOME_TOKEN';
21+
};
22+
23+
OpenAPI.TOKEN = getToken;
24+
```

docs/axios-support.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Axios support
2+
3+
This tool allows you to generate a client based on the [`Axios`](https://www.npmjs.com/package/axios) client.
4+
The advantage of the Axios client is that it works in both Node.js and Browser based environments.
5+
If you want to generate the Axios based client then you can specify `--client axios` in the openapi call:
6+
7+
`openapi --input ./spec.json --output ./generated --client axios`
8+
9+
The only downside is that this client needs some additional dependencies to work (due to the missing FormData
10+
classes in Node.js).
11+
12+
```
13+
npm install axios --save-dev
14+
npm install [email protected] --save-dev
15+
```
16+
17+
In order to compile the project and resolve the imports, you will need to enable the `allowSyntheticDefaultImports`
18+
in your `tsconfig.json` file.

docs/babel-support.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Babel support
2+
3+
If you use enums inside your models / definitions then those enums are by default inside a namespace with the same name
4+
as your model. This is called declaration merging. However, the [@babel/plugin-transform-typescript](https://babeljs.io/docs/en/babel-plugin-transform-typescript)
5+
does not support these namespaces, so if you are using babel in your project please use the `--useUnionTypes` flag
6+
to generate union types instead of traditional enums. More info can be found here: [Enums vs. Union Types](#enums-vs-union-types---useuniontypes).
7+
8+
**Note:** If you are using Babel 7 and Typescript 3.8 (or higher) then you should enable the `onlyRemoveTypeImports` to
9+
ignore any 'type only' imports, see https://babeljs.io/docs/en/babel-preset-typescript#onlyremovetypeimports for more info
10+
11+
```javascript
12+
module.exports = {
13+
presets: [
14+
['@babel/preset-typescript', {
15+
onlyRemoveTypeImports: true,
16+
}],
17+
],
18+
};
19+
```

docs/basic-usage.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Basic usage
2+
3+
```
4+
$ openapi --help
5+
6+
Usage: openapi [options]
7+
8+
Options:
9+
-V, --version output the version number
10+
-i, --input <value> OpenAPI specification, can be a path, url or string content (required)
11+
-o, --output <value> Output directory (required)
12+
-c, --client <value> HTTP client to generate [fetch, xhr, node, axios, angular] (default: "fetch")
13+
--name <value> Custom client class name
14+
--useOptions Use options instead of arguments
15+
--useUnionTypes Use union types instead of enums
16+
--exportCore <value> Write core files to disk (default: true)
17+
--exportServices <value> Write services to disk (default: true)
18+
--exportModels <value> Write models to disk (default: true)
19+
--exportSchemas <value> Write schemas to disk (default: false)
20+
--indent <value> Indentation options [4, 2, tab] (default: "5")
21+
--postfix <value> Service name postfix (default: "Service")
22+
--request <value> Path to custom request file
23+
-h, --help display help for command
24+
25+
Examples
26+
$ openapi --input ./spec.json --output ./generated
27+
```
28+
29+
## Example
30+
31+
**package.json**
32+
```json
33+
{
34+
"scripts": {
35+
"generate": "openapi --input ./spec.json --output ./generated"
36+
}
37+
}
38+
```
39+
40+
**NPX**
41+
42+
```
43+
npx openapi-typescript-codegen --input ./spec.json --output ./generated
44+
```
45+
46+
**Node.js**
47+
48+
```javascript
49+
const OpenAPI = require('openapi-typescript-codegen');
50+
51+
OpenAPI.generate({
52+
input: './spec.json',
53+
output: './generated',
54+
});
55+
56+
// Or by providing the content of the spec directly 🚀
57+
OpenAPI.generate({
58+
input: require('./spec.json'),
59+
output: './generated',
60+
});
61+
```

docs/client-instances.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Client instances
2+
3+
**Flag:** `--name`
4+
5+
The OpenAPI generator allows creation of client instances to support the multiple backend services use case.
6+
The generated client uses an instance of the server configuration and not the global `OpenAPI` constant.
7+
To generate a client instance, set a custom name to the client class, use `--name` option.
8+
9+
```
10+
openapi --input ./spec.json --output ./generated ---name AppClient
11+
```
12+
13+
The generated client will be exported from the `index` file and can be used as shown below:
14+
15+
```typescript
16+
// Create the client instance with server and authentication details
17+
const appClient = new AppClient({
18+
BASE: 'http://server-host.com',
19+
TOKEN: '1234',
20+
});
21+
22+
// Use the client instance to make the API call
23+
const response = await appClient.organizations.createOrganization({
24+
name: 'OrgName',
25+
description: 'OrgDescription',
26+
});
27+
```

docs/custom-enums.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Enum with custom names and descriptions
2+
3+
You can use `x-enum-varnames` and `x-enum-descriptions` in your spec to generate enum with custom names and descriptions.
4+
It's not in official [spec](https://github.com/OAI/OpenAPI-Specification/issues/681) yet. But it's a supported extension
5+
that can help developers use more meaningful enumerators.
6+
7+
```json
8+
{
9+
"EnumWithStrings": {
10+
"description": "This is a simple enum with strings",
11+
"enum": [
12+
0,
13+
1,
14+
2
15+
],
16+
"x-enum-varnames": [
17+
"Success",
18+
"Warning",
19+
"Error"
20+
],
21+
"x-enum-descriptions": [
22+
"Used when the status of something is successful",
23+
"Used when the status of something has a warning",
24+
"Used when the status of something has an error"
25+
]
26+
}
27+
}
28+
```
29+
30+
Generated code:
31+
32+
```typescript
33+
enum EnumWithStrings {
34+
/*
35+
* Used when the status of something is successful
36+
*/
37+
Success = 0,
38+
/*
39+
* Used when the status of something has a warning
40+
*/
41+
Waring = 1,
42+
/*
43+
* Used when the status of something has an error
44+
*/
45+
Error = 2,
46+
}
47+
```

docs/enum-vs-union-types.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Enums vs. Union types
2+
3+
**Flag:** `--useUnionTypes`
4+
5+
The OpenAPI spec allows you to define [enums](https://swagger.io/docs/specification/data-models/enums/) inside the
6+
data model. By default, we convert these enums definitions to [TypeScript enums](https://www.typescriptlang.org/docs/handbook/enums.html).
7+
However, these enums are merged inside the namespace of the model, this is unsupported by Babel, [see docs](https://babeljs.io/docs/en/babel-plugin-transform-typescript#impartial-namespace-support).
8+
Because we also want to support projects that use Babel [@babel/plugin-transform-typescript](https://babeljs.io/docs/en/babel-plugin-transform-typescript),
9+
we offer the flag `--useUnionTypes` to generate [union types](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#union-types)
10+
instead of the traditional enums. The difference can be seen below:
11+
12+
**Enums:**
13+
14+
```typescript
15+
// Model
16+
export type Order = {
17+
id?: number;
18+
quantity?: number;
19+
status?: Order.status;
20+
};
21+
22+
export namespace Order {
23+
export enum status {
24+
PLACED = 'placed',
25+
APPROVED = 'approved',
26+
DELIVERED = 'delivered',
27+
}
28+
}
29+
30+
// Usage
31+
const order: Order = {
32+
id: 1,
33+
quantity: 40,
34+
status: Order.status.PLACED,
35+
};
36+
```
37+
38+
**Union Types:**
39+
40+
```typescript
41+
// Model
42+
export type Order = {
43+
id?: number;
44+
quantity?: number;
45+
status?: 'placed' | 'approved' | 'delivered';
46+
};
47+
48+
// Usage
49+
const order: Order = {
50+
id: 1,
51+
quantity: 40,
52+
status: 'placed',
53+
};
54+
```

0 commit comments

Comments
 (0)