Skip to content

Commit

Permalink
Merge pull request #158 from FrontEndDev-org/feat/v0.x
Browse files Browse the repository at this point in the history
Feat/v0.x
  • Loading branch information
cloudcome authored Apr 16, 2023
2 parents 9dce9fd + 561ad57 commit 0496e5c
Show file tree
Hide file tree
Showing 67 changed files with 11,596 additions and 2,400 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: node env
name: setup nvm
description: 依照 nvmrc 创建 node 环境

runs:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/code-review.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 代码格式检查
# 代码格式、基本质量检查

name: code review

Expand All @@ -16,18 +16,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- uses: ./.github/actions/setup-nvm
- run: npm ci
- run: npm run lint

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- uses: ./.github/actions/setup-nvm
- run: npm ci
- run: npm run test:coverage
- uses: codacy/codacy-coverage-reporter-action@v1
if: github.actor != 'dependabot[bot]'
with:
api-token: ${{ secrets.CODACY_API_TOKEN }}
coverage-reports: coverage/lcov.info
10 changes: 5 additions & 5 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 如果是开发合并请求到主干,则会根据约定式提交创建一个 releasePR,是一个新版本合并请求
# 如果是新版本合并请求合并到主干,则会触发版本发布到 npm/github 等仓库
# 如果 devPR 到主干,则会根据约定式提交创建一个 releasePR,是一个新版本合并请求
# 如果 releasePR 到主干,则会触发新版本发布到 npm/github 等仓库

name: release please

Expand Down Expand Up @@ -29,7 +29,7 @@ jobs:
if: needs.release.outputs.release_created
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- uses: ./.github/actions/setup-nvm
- run: npm ci
- run: npm run test:coverage
- uses: codacy/codacy-coverage-reporter-action@v1
Expand All @@ -42,7 +42,7 @@ jobs:
needs: test-coverage
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- uses: ./.github/actions/setup-nvm
- run: npm ci
- run: npm run build
- uses: FrontEndDev-org/publish-node-package-action@v1
Expand All @@ -58,7 +58,7 @@ jobs:
needs: test-coverage
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- uses: ./.github/actions/setup-nvm
- run: npm ci
- run: npm run build
- uses: FrontEndDev-org/publish-node-package-action@v1
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged --allow-empty
npx tsc --noEmit
2 changes: 1 addition & 1 deletion .lintstagedrc.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
'(src|test)/*.{cjs,mjs,ts,tsx}': 'eslint --fix',
'*.{cjs,mjs,ts,tsx}': 'eslint --fix',
'*.{cjs,mjs,ts,tsx,html,css,scss}': 'prettier --write',
'(package|tsconfig*).json': 'prettier --write',
};
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
16
181 changes: 103 additions & 78 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,40 @@ OpenAPI ➡️ Axios
[![dependency-review](https://github.com/FrontEndDev-org/openapi-axios/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/FrontEndDev-org/openapi-axios/actions/workflows/dependency-review.yml)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4fa1acaeb717469caddfe21a84c50bb2)](https://app.codacy.com/gh/FrontEndDev-org/openapi-axios/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[![Codacy Badge](https://app.codacy.com/project/badge/Coverage/4fa1acaeb717469caddfe21a84c50bb2)](https://app.codacy.com/gh/FrontEndDev-org/openapi-axios/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
[![npm](https://img.shields.io/npm/v/openapi-axios)](https://npmjs.com/package/openapi-axios)
[![release](https://img.shields.io/github/v/release/FrontEndDev-org/openapi-axios)](https://github.com/FrontEndDev-org/openapi-axios/releases)
[![npm version](https://badge.fury.io/js/openapi-axios.svg)](https://npmjs.com/package/openapi-axios)

将 OpenAPI 规范声明文件转换为类型声明和可执行函数(基于 Axios)。与其他同类工具相比,具有以下特点:

- 每个 API 都是一个函数,用于在构建时轻松进行 tree shaking
- 轻松与本地请求客户端集成,例如在本地项目中创建的 Axios 实例
- 易于使用,易于学习,类型安全
- 😆 支持 [openAPI](https://www.openapis.org/) v3(当前仅)
- 😉 每个 API 都是一个函数,用于在构建时轻松进行 tree shaking
- 😎 与最流行的 HTTP 客户端 [axios](https://axios-http.com/) 进行适配
- 🤗 轻松与本地请求客户端集成,例如在本地项目中创建的 Axios 实例(通常我们在本地都是需要自定义一些拦截器什么的)
- 😁 易于使用,易于学习,类型安全

# 安装

```shell
npm i -D openapi-axios
```

or

```shell
yarn add --dev openapi-axios
```

# 使用

## 命令行

在项目根目录下创建配置文件,配置文件的搜索顺序是 `openapi.config.cjs``openapi.config.js``openapi.json`
在项目根目录下创建配置文件,配置文件的搜索顺序是 `openapi.config.cjs``openapi.config.js`

```js
// openapi.config.cjs
const { defineConfig } = require('openapi-axios');

module.exports = defineConfig({
list: [
openAPIs: [
{
name: 'swagger/pet',
url: 'https://petstore3.swagger.io/api/v3/openapi.json',
// 将会生成 src/apis/swagger/petStore3.ts 文件
name: 'swagger/petStore3',
// 可以是一个 URL 链接或者本地路径,或者一个 OPENAPI3 文档对象
document: 'https://petstore3.swagger.io/api/v3/openapi.json',
},
],
});
Expand All @@ -51,103 +49,130 @@ module.exports = defineConfig({
# 根据配置文件生成typescript文件
npx openapi-axios

# 将生成 `src/apis/swagger/pet.ts` 文件
# 将会生成 src/apis/swagger/petStore3.ts 文件
```

生成的文件将导出为一个函数和一个操作,如下所示:
<details>
<summary>生成的文件将导出为一个函数和一个操作,如下所示</summary>

```ts
// src/apis/swagger/pet.ts
// src/apis/swagger/petStore3.ts

import type { OneOf } from 'openapi-axios/helpers';
import type { AxiosPromise, AxiosRequestConfig } from 'axios';
import {
DELETE,
GET,
HEAD,
OPTIONS,
PATCH,
POST,
PUT,
resolveURL,
} from 'openapi-axios/helpers';
import { Axios } from 'axios';
const axios = new Axios();

const request = axios.request;
const BASE_URL = '/api/v3';

// ...

export interface Pet {
export type Pet = {
category?: Category;
/**
* @format int64
* @example 10
*/
id?: number;
/** @example "doggie" */
/**
* @example doggie
*/
name: string;
category?: Category;
photoUrls: string[];
tags?: Tag[];
/** pet status in the store */
photoUrls: Array<string>;
/**
* @description pet status in the store
*/
status?: 'available' | 'pending' | 'sold';
}
tags?: Array<Tag>;
};

// ...

export type AddPetReqData = Pet;
export type AddPetResData = Pet;
/**
* @summary Finds Pets by status
* @description Multiple status values can be provided with comma separated strings
* @tags pet
* @request GET:/pet/findByStatus
* @secure
* @title Add a new pet to the store
* @description Add a new pet to the store
*/
export async function findPetsByStatus(
query?: {
/**
* Status values that need to be considered for filter
* @default "available"
*/
status?: 'available' | 'pending' | 'sold';
},
axiosRequestConfig?: AxiosRequestConfig
): AxiosReturn<Pet[]> {
return axios.request({
url: `${BASE_URL}/pet/findByStatus`,
method: MethodType.GET,
params: query,
headers: formatHeaders(ContentKind.OTHER),
responseType: ResponseType.Json,
...axiosRequestConfig,
export async function addPet(
data: AddPetReqData,
config?: AxiosRequestConfig
): AxiosPromise<AddPetResData> {
return request({
url: resolveURL(BASE_URL, `/pet`),
method: POST,
data,
...config,
});
}

// ...
```
</details>

然后你可以直接导入一个函数并使用它。 调用接口就像调用本地函数一样简单,是不是类似于 RPC(remote procedure call)。

```ts
import { findPetsByStatus } from '@/apis/swagger/pet';
import { addPet } from '@/apis/swagger/petStore3';

// 在调用函数和编写参数时,有类型提示,这要感谢 TypeScript
const pets = await findPetsByStatus({
status: ['avaliable'],
// 类型安全
const { data: pet } = await addPet({
name: 'MyCat',
photoUrls: ['photo1', 'photo2']
});
```

## API

```ts
import { generate } from 'openapi-axios';

generate({
// ...config
});
// 类型安全
console.log(pet);
```

# 配置

| 参数名 | 类型 | 可选性 | 描述 | 默认值 |
|----------------------|-------------------|---------|----------------------------------------------------------------|-----------------------------|
| `cwd` | `string` | `false` | 当前工作路径 | `process.cwd()` |
| `dest` | `string` | `false` | 目标目录 | `src/apis` |
| `axiosImport` | `string` | `false` | axios 导入内容 | 默认从官方 Axios 导入,可以使用自己实现的客户端 |
| `unwrapResponseData` | `boolean` | `false` | 是否取消对 axios response 的包裹(即直接返回 ResponseData,而不是 AxiosResponse) | `false` |
| `apis` | `OpenapiConfig[]` | `false` | OpenAPI 列表 | `[]` |

`OpenapiConfig` 签名:

| 名称 | 类型 | 可选 | 描述 | 默认值 |
|----------------------|-----------|--------------|----------------------------------------------------------------------|----------------------------------------------|
| `name` | `string` | 必须 | openapi 的名称,将会生成 ${name}.ts 文件 | `undefined` |
| `axiosImport` | `string` | 可选 | axios 导入内容,优先级更高 ||
| `unwrapResponseData` | `boolean` | 可选 | 是否取消对 axios response 的包裹,优先级更高(即直接返回 ResponseData,而不是 AxiosResponse) | `false` |
| `schema` | `string | OpenApiSpec` | 必须 | openapi 的 schema,可以是一个链接地址,也可以是本地路径,也可以是一个对象 | `undefined` |
# openapi.config

| 参数名 | 类型 | 可选性 | 描述 | 默认值 |
|---------------|--------------------|---------|----------------------------|-----------------------------|
| `cwd` | `string` | `false` | 当前工作路径 | `process.cwd()` |
| `dest` | `string` | `false` | 目标目录 | `src/apis` |
| `parser` | `ParserOptions` | `false` | 解析配置 | `undefined` |
| `printer` | `PrinterOptions` | `false` | 输出配置 | `undefined` |
| `openAPIs` | `OpenAPIOptions[]` | `true` | OpenAPIOptions 列表,至少需要配置一个 ||

## `ParserOptions` 签名:
| 参数名 | 类型 | 可选性 | 描述 | 默认值 |
|------------------------|----------|---------|------------|--------------------|
| `cwd` | `string` | `false` | 当前工作路径 | `process.cwd()` |
| `okCode` | `number` | `false` | ok 的响应码 | `200` |
| `okMediaType` | `number` | `false` | ok 的响应类型 | `application/json` |
| `requestPathTypeName` | `string` | `false` | 请求路径参数类型名称 | `ReqPath` |
| `requestQueryTypeName` | `string` | `false` | 请求查询参数类型名称 | `ReqParams` |
| `requestBodyTypeName` | `string` | `false` | 请求体参数类型名称 | `ReqData` |
| `responseBodyTypeName` | `string` | `false` | 响应体参数类型名称 | `ResData` |

## `PrinterOptions` 签名:
| 参数名 | 类型 | 可选性 | 描述 | 默认值 |
|-----------------------|----------|---------|-------------------------------------|-----------------------------|
| `axiosImport` | `string` | `false` | axios 导入内容 | 默认从官方 Axios 导入,可以使用自己实现的客户端 |
| `prettier` | `object` | `false` | [prettier](https://prettier.io/) 配置 | `{ singleQuote: true }` |
| `requestPathArgName` | `string` | `false` | 请求路径参数入参名称 | `path` |
| `requestQueryArgName` | `string` | `false` | 请求查询参数入参名称 | `params` |
| `requestBodyArgName` | `string` | `false` | 请求体参数入参名称 | `data` |
| `responseTypeName` | `string` | `false` | 响应类型名称 | `AxiosPromise` |

## `OpenAPIOptions` 签名:

| 名称 | 类型 | 可选 | 描述 | 默认值 |
|------------|---------------------------|----|--------------------------------------------------|-------------|
| `name` | `string` | 必须 | openapi 的名称,将会生成 ${name}.ts 文件 | `undefined` |
| `document` | `string,OpenAPI3Document` | 必须 | openapi 文档,可以是一个 URL 链接或者本地路径,或者一个 OPENAPI3 文档对象 | `undefined` |

# 鸣谢

- [swagger-typescript-api](https://www.npmjs.com/package/swagger-typescript-api)
5 changes: 5 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- [ ] 支持 OneOf AllOf
- [ ] 支持长度为一的必填参数展开
- [ ] openapi document validate
- [ ] 接口 mock
- [ ] 接口运行期类型检查
Loading

0 comments on commit 0496e5c

Please sign in to comment.