Skip to content

Commit c0df340

Browse files
committed
Merge remote-tracking branch 'origin/master' into bugfix/dependabot-alerts
2 parents 9d27320 + 9e2b661 commit c0df340

21 files changed

+884
-13
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/.idea
2-
/node_modules
2+
node_modules
33
/.vscode
44
/test/out
55
/specs

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# [2.0.0-alpha.24](https://github.com/devexperts/swagger-codegen-ts/compare/v2.0.0-alpha.23...v2.0.0-alpha.24) (2020-12-24)
1+
# [2.0.0-alpha.25](https://github.com/devexperts/swagger-codegen-ts/compare/v2.0.0-alpha.24...v2.0.0-alpha.25) (2021-05-25)
22

33

44
### Bug Fixes
@@ -8,6 +8,8 @@
88

99
### Features
1010

11+
* **asyncapi:** channel parameters ([33ea85d](https://github.com/devexperts/swagger-codegen-ts/commit/33ea85d))
12+
* support binary and text responses for 2.0 spec ([da355db](https://github.com/devexperts/swagger-codegen-ts/commit/da355db))
1113
* Support headers ([#133](https://github.com/devexperts/swagger-codegen-ts/issues/133)) ([24b70fa](https://github.com/devexperts/swagger-codegen-ts/commit/24b70fa)), closes [#57](https://github.com/devexperts/swagger-codegen-ts/issues/57)
1214

1315

README.md

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,66 @@
11
[![Build Status](https://travis-ci.org/devexperts/swagger-codegen-ts.svg?branch=master)](https://travis-ci.org/devexperts/swagger-codegen-ts)
2-
3-
### FAQ
4-
1. **Why don't spec codecs reuse common parts?**
5-
6-
That's because different versions of specs refer to different versions of [JSON Schema](http://json-schema.org) and they are generally not the same. We would like to avoid maintaining JSON Schema composition in this project. (for now)
72

8-
### Contributions
9-
- use https://www.conventionalcommits.org/en/v1.0.0-beta.2/
3+
# Typesafe OpenAPI generator for TypeScript
104

11-
### Publish
12-
`npm version major|minor|patch`
5+
## Features
6+
* Generates client code from **OpenAPI 3.0, 2.0** (aka Swagger) and **AsyncAPI** specs
7+
* **Pluggable HTTP clients:** can use `fetch`, `Axios` or any other library
8+
* **Flexible response types:** works with Promises and reactive streams like RxJS
9+
* **Runtime type checks:** validates server responses against the spec
10+
* Written in **pure TypeScript** using [`fp-ts`](https://github.com/gcanti/fp-ts) and [`io-ts`](https://github.com/gcanti/io-ts) libraries
11+
12+
## Demo code
13+
14+
> The examples below refer to the [Pet Store OpenAPI 3.0 schema](https://petstore3.swagger.io/).
15+
16+
After running the codegen, interacting with a REST API may be as simple as this:
17+
18+
```typescript
19+
import { petController as createPetController } from "./src/generated/petstore.json/paths/PetController";
20+
import { Pet } from "./src/generated/petstore.json/components/schemas/Pet";
21+
22+
// Creating a controller, see the "HTTP Clients" wiki page for more details
23+
const petController = createPetController({ httpClient: fetchHttpClient });
24+
25+
// The returned object is guaranteed to be a valid `Pet`
26+
const createdPet: Promise<Pet> = petController.addPet({
27+
body: {
28+
// The parameters are statically typed, IntelliSense works, too
29+
name: "Spotty",
30+
photoUrls: [],
31+
},
32+
});
33+
```
34+
35+
More usage scenarios are supported - check the [usage page](./docs/usage/generated-code.md) for more detail.
36+
37+
## Installation
38+
39+
1. Make sure the peer dependencies are installed, then install the codegen itself:
40+
```
41+
yarn add typescript fp-ts io-ts io-ts-types
42+
yarn add -D @devexperts/swagger-codegen-ts
43+
```
44+
45+
2. Create a console script that would invoke the `generate` function, passing the options such as path to the schema file and the output directory.
46+
See the [Generators](docs/usage/api.md) page for the API reference, and [examples/generate](examples/generate) for sample scripts.
47+
48+
3. In most cases, you might want to include the code generation step into the build and local launch scripts. Example:
49+
```diff
50+
/* package.json */
51+
52+
"scripts": {
53+
+ "generate:api": "ts-node scripts/generate-api.ts",
54+
- "start": "react-scripts start",
55+
+ "start": "yarn generate:api && react-scripts start",
56+
- "build": "react-scripts build"
57+
+ "build": "yarn generate:api && react-scripts build"
58+
}
59+
```
60+
61+
## Contributing
62+
63+
* Feel free to file bugs and feature requests in [GitHub issues](https://github.com/devexperts/swagger-codegen-ts/issues/new).
64+
* Pull requests are welcome - please use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.2/).
65+
66+
Please read the [Contributors Guide](./docs/development/contributors-guide.md) for more information.

docs/development/clients.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Creating HTTP Clients
2+
3+
The code generated by OpenAPI and AsyncAPI generators requires the user to provide an `HTTPClient` or `WebSocketClient` instance respectively.
4+
5+
The original intent is to create such instances in the consumer's application; however, some predefined clients may be added in the future. This guide describes basic steps to create one.
6+
7+
### Defining a return type
8+
9+
In order to support the desired return type, the generated code must know how to perform some basic operations over that type, such as creating a "successful" or "failed" response object, or applying a given transform function to the response. These operations are abstracted via the [`MonadThrow`](https://gcanti.github.io/fp-ts/modules/MonadThrow.ts.html) interface from the `fp-ts` library.
10+
11+
Some common types already have corresponding `Monad` implementations, while for others you might have to implement one from scratch. For an example of how this can be done and what functions are required, check how the `Monad` is implemented for RxJS's `Observable` in the [`fp-ts-rxjs`](https://github.com/gcanti/fp-ts-rxjs/blob/master/src/Observable.ts) package.
12+
13+
### Implementing the actual HTTP requests logic
14+
15+
Once the `Monad` implementation is available, just two methods need to be added to form a working `HTTPClient`: `throwError` and `request`. As can be seen from their signatures, they create a "failed" response and make actual HTTP calls, respectively.
16+
17+
Considering the above, an `HTTPClient` for RxJS could be defined as follows:
18+
19+
```typescript
20+
import { Monad } from "fp-ts-rxjs/lib/Observable";
21+
import { throwError } from "rxjs";
22+
23+
const rxjsHttpClient: HTTPClient1<"Observable"> = {
24+
...Monad,
25+
request: (req) => {
26+
return ajax({
27+
url: req.url,
28+
method: req.method,
29+
// add the logic to handle `req.body` and other parameters
30+
}).pipe();
31+
},
32+
throwError,
33+
};
34+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Contributors Guide
2+
3+
Thanks for your attention and efforts to improve the codegen!
4+
5+
Here are some resources to help you getting familiar with the code base.
6+
7+
* [Development: Overview](./overview.md)
8+
9+
# Testing
10+
11+
# Submitting changes
12+
13+
# Code style and conventions

docs/development/overview.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Development: Overview
2+
3+
TODO: describe the architecture and data flows
4+
5+
### FAQ
6+
1. **Why don't spec codecs reuse common parts?**
7+
8+
That's because different versions of specs refer to different versions of [JSON Schema](http://json-schema.org) and they are generally not the same. We would like to avoid maintaining JSON Schema composition in this project. (for now)
9+
10+
### Publish
11+
`npm version major|minor|patch`

docs/usage/api.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# API
2+
3+
The single entry point to the generator is the `generate` function:
4+
5+
```typescript
6+
import { generate } from "@devexperts/swagger-codegen-ts";
7+
import { OpenapiObjectCodec } from "@devexperts/swagger-codegen-ts/dist/schema/3.0/openapi-object";
8+
import { serialize } from "@devexperts/swagger-codegen-ts/dist/language/typescript/3.0";
9+
10+
generate({
11+
spec: path.resolve(__dirname, "petstore.json"),
12+
out: path.resolve(__dirname, "src/generated"),
13+
language: serialize,
14+
decoder: OpenapiObjectCodec,
15+
});
16+
```
17+
18+
See the typedocs for more info about the options.
19+
20+
# CLI
21+
22+
Not implemented yet - PRs are highly welcome!

docs/usage/clients.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Clients Reference
2+
3+
Different projects have slightly different requirements regarding the error handling, request and response processing and other logic.
4+
These requirements should be implemented as an `HTTPClient` instance, which in turn is provided to the generated controllers.
5+
6+
Resources:
7+
- For developing a custom `HTTPClient`, please refer to [Developers Guide - HTTP clients](../development/clients.md);
8+
- The repository contains a few [examples](../../examples/clients) of HTTPClient implementation for common libraries;

docs/usage/generated-code.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Using the generated code
2+
3+
> The examples below refer to the [Pet Store OpenAPI 3.0 schema](https://petstore3.swagger.io/).
4+
5+
## Basic example: using a single controller
6+
7+
In the most basic scenario, you may need just a single **controller** from the generated code. In this case, the code is as simple as this:
8+
9+
```typescript
10+
import { petController as createPetController } from "./src/generated/petstore.json/paths/PetController";
11+
import { Pet } from "./src/generated/petstore.json/components/schemas/Pet";
12+
13+
// Creating a controller, see the "HTTP Clients" wiki page for more details
14+
const petController = createPetController({ httpClient: fetchHttpClient });
15+
16+
// The returned object is guaranteed to be a valid `Pet`
17+
const createdPet: Promise<Pet> = petController.addPet({
18+
body: {
19+
// The parameters are statically typed, IntelliSense works, too
20+
name: "Spotty",
21+
photoUrls: [],
22+
},
23+
});
24+
```
25+
26+
## The `controllers` object
27+
28+
In most projects, the generated code includes more than one controller. Sometimes it's handy to have a single entry points to all of them - for this purpose, the `controllers` object is created by the generator:
29+
30+
```typescript
31+
import { controllers } from "./src/generated/petstore.json/paths/paths";
32+
33+
const api = controllers({ httpClient: fetchHttpClient });
34+
const pets = api.petController.findPetsByStatus({
35+
query: { status: some("available") },
36+
});
37+
// api.userController and api.storeController are also available
38+
```
39+
40+
## Plugging different HTTP clients
41+
42+
Generated functions may be instructed to return any generic type with one or two type arguments, for example `Promise<Response>` or `Observable<Either<Error, Response>>`. The return type is specified by providing a corresponding **client**. In the example below, providing an `rxjsHttpClient` makes the `petController` return RxJS's `Observable`:
43+
44+
```typescript
45+
import { Observable } from "rxjs";
46+
47+
// Now create another controller returning an RxJS stream
48+
const petRxjsController = createPetController({ httpClient: rxjsHttpClient });
49+
const createdPet$: Observable<Pet> = petRxjsController.addPet({
50+
body: {
51+
name: "Spotty",
52+
photoUrls: [],
53+
},
54+
});
55+
```
56+
57+
The list of bundled clients and more information can be found in the [Clients](./clients.md) page.
58+
59+
## Using [`RemoteData`](https://github.com/devexperts/remote-data-ts)
60+
61+
The codegen provides first class support for the `RemoteData<Error, Response>` type, making it easier to build complex logic on top of the generated controllers.
62+
63+
```typescript
64+
const petRDController = createPetController({ httpClient: liveDataHttpClient });
65+
/**
66+
* `LiveData<E, A> = Observable<RemoteData<E, A>>`
67+
*
68+
* Emits `pending` when the request is started,
69+
* then `success(Pet)` or `failure(Error)` upon completion.
70+
*/
71+
const createdPet$: LiveData<Error, Pet> = petRDController.addPet({
72+
body: {
73+
name: "Spotty",
74+
photoUrls: [],
75+
},
76+
});
77+
```
78+
79+
## Validation utils
80+
81+
Each schema defined in the spec produces a TS type and an `io-ts` codec, which can be used for runtime type checking in the application code:
82+
83+
```typescript
84+
import { either } from "fp-ts";
85+
import { pipe } from "fp-ts/function";
86+
import { User, UserIO } from "./src/generated/petstore.json/components/schemas/User";
87+
88+
pipe(
89+
UserIO.decode(JSON.parse(localStorage.getItem('PetStore.user'))),
90+
either.fold(
91+
error => {
92+
console.log('The user record is not valid');
93+
},
94+
(user: User) => {
95+
console.log(`Was previously logged in as: ${user.email}`);
96+
}
97+
)
98+
);
99+
```
100+
101+
Learn more on the `Either` type: [Getting started with fp-ts: Either vs Validation](https://dev.to/gcanti/getting-started-with-fp-ts-either-vs-validation-5eja)
102+

examples/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/out/

0 commit comments

Comments
 (0)