Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ jobs:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- run: npm ci
- run: npm run test
- run: npm run test:coverage
- uses: codacy/codacy-coverage-reporter-action@v1
with:
api-token: ${{ secrets.CODACY_API_TOKEN }}
coverage-reports: coverage/lcov.info
2 changes: 1 addition & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v3
- uses: ./.github/actions/node-env
- run: npm ci
- run: npm run test-coverage
- run: npm run test:coverage
- uses: codacy/codacy-coverage-reporter-action@v1
with:
api-token: ${{ secrets.CODACY_API_TOKEN }}
Expand Down
34 changes: 16 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,24 +132,22 @@ generate({

# 配置

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

`OpenApiSpec` 签名:

| 名称 | 类型 | 可选项 | 描述 | 默认值 |
| ------------- | -------- | ------- | -------------------------------------- | --------------- |
| `name` | `string` | `true` | 文件名,可以包含路径,相当于 dest 配置 | `process.cwd()` |
| `axiosImport` | `string` | `false` | axios 导入内容,优先级更高 | 无 |
| `url` | `string` | `false` | 远程 openApi 描述地址 | `undefined` |
| `spec` | `Spec` | `false` | 本地 OpenApi 描述文件 | `undefined` |

备注:`url` 属性和 `spec` 属性,至少有一个必须。
| 参数名 | 类型 | 可选性 | 描述 | 默认值 |
| -------------------- | ----------------- | ------- | --------------------------------------------------------------------------------- | ----------------------------------------------- |
| `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 列表 <br/> <br/> | `[]` |

`OpenapiConfig` 签名:

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

# 鸣谢

Expand Down
75 changes: 1 addition & 74 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"prepare": "husky install",
"lint": "eslint src/**/*.ts && tsc --project tsconfig.json --noEmit",
"test": "vitest run",
"test-coverage": "vitest run --coverage",
"test:coverage": "vitest run --coverage",
"build:types": "rm -rf dist-dts && tsc --project tsconfig.types.json",
"build:files": "rm -rf dist-cjs dist-mjs && rollup --config",
"build": "npm run build:types && npm run build:files"
Expand Down
6 changes: 3 additions & 3 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function start(startConfig?: StartConfig) {

try {
await generate(strictConfig, (generated, info) => {
const { oasItem } = generated;
const { openapi } = generated;
const { index, length, done, start, end } = info;
const width = Math.min(String(length).length, 2);
const stepText = String(index + 1).padStart(width, '0');
Expand All @@ -61,14 +61,14 @@ export async function start(startConfig?: StartConfig) {
console.log(
chalk.cyanBright(`[${stepText}/${length}]`),
'generated ',
chalk.yellowBright(oasItem.name),
chalk.yellowBright(openapi.name),
chalk.gray(`${past}ms`)
);
} else {
console.log(
chalk.cyanBright(`[${stepText}/${length}]`),
'generating',
chalk.yellowBright(oasItem.name),
chalk.yellowBright(openapi.name),
chalk.gray('...')
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const defaults: StrictConfig = {
dest: 'src/apis',
axiosImport: axiosImportDefault,
unwrapResponseData: false,
list: [],
apis: [],
onGenerated: () => 0,
};

Expand Down
62 changes: 40 additions & 22 deletions src/generator.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,52 @@
import fs from 'fs/promises';
import { isBoolean, isString } from 'lodash-es';
import path from 'path';
import { generateApi } from 'swagger-typescript-api';
import { generateApi, GenerateApiParams } from 'swagger-typescript-api';
import { axiosImportDefault, helpersImport, templatesDir } from './const';
import {
Generated,
GeneratedCallback,
OpenApiSpec,
OpenApiSpecAsLocal,
OpenApiSpecAsRemote,
StrictConfig,
} from './types';
import { Generated, GeneratedCallback, OpenapiConfig, StrictConfig } from './types';

export async function generateItem(oasItem: OpenApiSpec, config: StrictConfig): Promise<Generated> {
const { name, axiosImport: axiosImportScope } = oasItem;
const { cwd, dest, axiosImport: axiosImportGlobal, unwrapResponseData } = config;
const axiosImport = axiosImportScope || axiosImportGlobal || axiosImportDefault;
const { files } = await generateApi({
export function generateParams(openapiConfig: OpenapiConfig, config: StrictConfig): GenerateApiParams {
const { name, schema, unwrapResponseData: unwrapResponseDataScope } = openapiConfig;
const { unwrapResponseData: unwrapResponseDataGlobal } = config;
const unwrapResponseData = isBoolean(unwrapResponseDataScope) ? unwrapResponseDataScope : unwrapResponseDataGlobal;
const common: Omit<GenerateApiParams, 'url' | 'input' | 'spec'> = {
name,
url: (oasItem as OpenApiSpecAsRemote).url,
spec: (oasItem as OpenApiSpecAsLocal).spec,
output: false,
httpClientType: 'axios',
templates: templatesDir,
silent: true,
unwrapResponseData,
});
};

if (isString(schema)) {
if (/^https:\/\//i.test(schema)) {
return {
...common,
url: schema,
};
} else {
return {
...common,
input: schema,
};
}
} else {
return {
...common,
spec: schema,
};
}
}

export async function generateItem(openapiConfig: OpenapiConfig, config: StrictConfig): Promise<Generated> {
const { axiosImport: axiosImportScope, schema } = openapiConfig;
const { cwd, dest, axiosImport: axiosImportGlobal, unwrapResponseData } = config;
const axiosImport = axiosImportScope || axiosImportGlobal || axiosImportDefault;
const params = generateParams(openapiConfig, config);
const { files } = await generateApi(params);
const generated: Generated = {
files: [],
oasItem,
openapi: openapiConfig,
config,
};

Expand All @@ -47,17 +65,17 @@ export async function generateItem(oasItem: OpenApiSpec, config: StrictConfig):
}

export async function generate(config: StrictConfig, callback?: GeneratedCallback): Promise<Generated[]> {
const { list, onGenerated } = config;
const { apis, onGenerated } = config;
let index = 0;
const length = list.length;
const length = apis.length;
const generatedList: Generated[] = [];

for (const oasItem of list) {
for (const oasItem of apis) {
const start = Date.now();
callback?.(
{
files: [],
oasItem,
openapi: oasItem,
config,
},
{ index, length, done: false, start, end: start }
Expand Down
39 changes: 22 additions & 17 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
interface OpenApiSpecBase {
export type OpenapiSpec = import('swagger-schema-official').Spec;

export type OpenapiConfig = {
/**
* openapi 的名称,将会生成 ${name}.ts 文件
*/
name: string;

/**
* 全局导入 axios 客户端,优先级低于每个 oas 配置,默认从 axios 官方导入,导入名称必须为 axios,例如
* 导入 axios 客户端,默认从 axios 官方导入,导入名称必须为 axios,优先级高于全局配置,例如
* ```
* import { axios } from '@/utils/axios';
* ```
*/
axiosImport?: string;
}

export interface OpenApiSpecAsRemote extends OpenApiSpecBase {
url: string;
}

export type Spec = import('swagger-schema-official').Spec;

export interface OpenApiSpecAsLocal extends OpenApiSpecBase {
spec: Spec;
}
/**
* 是否取消包装 data,默认 undefined,优先级高于全局配置
* false = 返回值就是响应(response),response.data 才是实际值
* true = 返回值就是数据
*/
unwrapResponseData?: boolean;

export type OpenApiSpec = OpenApiSpecAsRemote | OpenApiSpecAsLocal;
/**
* openapi 的 schema,可以是一个链接地址,也可以是本地路径,也可以是一个对象
*/
schema: string | OpenapiSpec;
};

export interface UserConfig {
/**
Expand All @@ -34,7 +39,7 @@ export interface UserConfig {
dest?: string;

/**
* 导入 axios 客户端,优先级高于全局配置,默认从 axios 官方导入,导入名称必须为 axios,例如
* 默认从 axios 官方导入,导入名称必须为 axios,例如
* ```
* import { axios } from '@/utils/axios';
* ```
Expand All @@ -56,9 +61,9 @@ export interface UserConfig {
onGenerated?: (generated: Generated) => any;

/**
* OpenApiSpec 列表
* OpenapiConfig 列表
*/
list: OpenApiSpec[];
apis: OpenapiConfig[];
}

export type StrictConfig = Required<UserConfig>;
Expand All @@ -73,7 +78,7 @@ export enum ContentKind {

export interface Generated {
files: string[];
oasItem: OpenApiSpec;
openapi: OpenapiConfig;
config: StrictConfig;
}

Expand Down
4 changes: 2 additions & 2 deletions test/configure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ test('defaults', () => {
const axios = new Axios();`);
expect(defaults.dest).toBe('src/apis');
expect(defaults.cwd).toBe(process.cwd());
expect(defaults.list).toHaveLength(0);
expect(defaults.apis).toHaveLength(0);
expect(defaults.unwrapResponseData).toBe(false);
expect(defaults.onGenerated).toBeTypeOf('function');
});

test('defineConfig', () => {
const userConfig: UserConfig = {
list: [],
apis: [],
};
const strictConfig = defineConfig(userConfig);

Expand Down
Loading