Skip to content

Commit

Permalink
Merge pull request #97 from long-woo/dev
Browse files Browse the repository at this point in the history
release: 2.8.0
  • Loading branch information
long-woo authored Jan 6, 2025
2 parents 57f705a + 1fadbae commit 12f218e
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 95 deletions.
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ STC (Swagger Transform Code) is a tool for converting OpenApi/Swagger/Apifox int
![Publish to release](https://github.com/long-woo/stc/actions/workflows/deno-build.yml/badge.svg)
[![Publish Package to npmjs](https://github.com/long-woo/stc/actions/workflows/npm.yml/badge.svg)](https://github.com/long-woo/stc/actions/workflows/npm.yml)

[![JSR](https://jsr.io/badges/@loongwoo/stc)](https://jsr.io/@loongwoo/stc)
![NPM Version](https://img.shields.io/npm/v/%40loongwoo%2Fstc)

> New scope enabled since 2.8.0 **@lonu**
[![JSR](https://jsr.io/badges/@lonu/stc)](https://jsr.io/@lonu/stc)
![NPM Version](https://img.shields.io/npm/v/%40lonu%2Fstc)

<div align="center">
<img src="resources/20240422-151653.gif" alt="stc" />
Expand Down Expand Up @@ -45,7 +43,7 @@ STC (Swagger Transform Code) is a tool for converting OpenApi/Swagger/Apifox int
1.Install the `@loogwoo/stc` npm package.

```sh
pnpm add @loongwoo/stc -D
pnpm add @lonu/stc -D
```

2.Open the project's `package.json` file and add the following command to `scripts`:
Expand Down Expand Up @@ -143,7 +141,7 @@ App<IAppOption>({

## Plug-in development

For convenience, STC can not only develop plugins in Deno, but also provides `@loongwoo/stc` npm library, which can develop plugins in Node environment.
For convenience, STC can not only develop plugins in Deno, but also provides `@lonu/stc` npm library, which can develop plugins in Node environment.

[examples](https://github.com/long-woo/stc/tree/master/examples)

Expand All @@ -156,7 +154,7 @@ Create a `myPlugin.ts` file:
```ts
// 引用模块
// import { start } from 'https://deno.land/x/stc@2.7.3/mod.ts'
import { start } from 'jsr:@loongwoo/stc@^2.7.3'
import { start } from 'jsr:@lonu/stc@^2.8.0'

// Defining plugins
const myPlugin: IPlugin = {
Expand Down Expand Up @@ -199,10 +197,10 @@ start({

1. Create a `myPlugin.ts` file.

2. Add the `@loongwoo/stc` reference and use the `start` method:
2. Add the `@lonu/stc` reference and use the `start` method:

```ts
import { start } from '@loongwoo/stc'
import { start } from '@lonu/stc'
```

3. Implement the code that converts `definition` and `action` into the target language in the plugin's `onTransform` hook function.
Expand Down
8 changes: 4 additions & 4 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@loongwoo/stc",
"version": "2.7.3",
"name": "@lonu/stc",
"version": "2.8.0",
"exports": "./mod.ts",
"tasks": {
"pack": "deno run -A src/pack.ts",
"dev": "deno task pack && deno run -A --watch=src src/main.ts --url='https://petstore3.swagger.io/api/v3/openapi.json'",
"dev": "deno run -A --watch=src src/main.ts --url='https://petstore3.swagger.io/api/v3/openapi.json'",
"serve": "deno run -A --watch=src src/service.ts",
"version": "echo '2.7.3' > release/version",
"version": "echo '2.8.0' > release/version",
"build:npm": "deno run -A src/npm/build.ts",
"build:mac": "deno compile -A --target x86_64-apple-darwin --output release/stc src/main.ts",
"build:mac-m": "deno compile -A --target aarch64-apple-darwin --output release/stc-m src/main.ts",
Expand Down
4 changes: 2 additions & 2 deletions src/npm/pkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@loongwoo/stc",
"version": "2.7.3",
"name": "@lonu/stc",
"version": "2.8.0",
"description": "A tool for converting OpenApi/Swagger/Apifox into code.",
"type": "module",
"module": "esm/mod.js",
Expand Down
23 changes: 11 additions & 12 deletions src/plugins/typescript/shared/apiClientBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,23 @@ export interface ApiClientParams {
}

export interface ApiClientConfig {
baseURL?: string;
url?: string;
method?: ApiClientMethod;
params?: ApiClientParams;
timeout?: number;
signal?: AbortSignal;
withCredentials?: boolean;
baseURL?: string
url?: string
method?: ApiClientMethod
params?: ApiClientParams
timeout?: number
signal?: AbortSignal
withCredentials?: boolean
/**
* 忽略错误发生的 url 或 baseURL,不触发 error 回调函数。示例:/api/test
*/
errorIgnore?: string[];
abortUrls?: string[];
config?: Pick<ApiClientConfig, "timeout" | "signal">;
errorIgnore?: string[]
config?: Pick<ApiClientConfig, 'baseURL' | 'timeout' | 'signal'>
/**
* 错误回调函数
*/
onError?: (message: string) => void;
onLogin?: () => void;
onError?: (message: string) => void
onLogin?: () => void
}

/**
Expand Down
47 changes: 6 additions & 41 deletions src/plugins/typescript/shared/axios/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
AxiosHeaders,
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
Expand All @@ -8,53 +9,18 @@ import axios from "axios";

import type { ApiClientConfig, IDefaultObject } from "../apiClientBase";

type RequestConfig = AxiosRequestConfig<Record<string, unknown>>;

let axiosInstance: AxiosInstance;
let abortUrls: string[] = [];
let errorIgnore: string[] = [];
let onError: ((message: string) => void) | undefined;
let onLogin: (() => void) | undefined;
const pendingMap = new Map<string, AbortController>();

const addPending = (config: RequestConfig) => {
const url = config.url ?? "";
const data = config.data ?? {};
const controller = new AbortController();

if (
!url.includes("add_pending=true") &&
!data.addPending &&
!abortUrls.includes(url)
) {
return;
}

if (!pendingMap.has(url)) {
config.signal = controller.signal;
pendingMap.set(url, controller);
}
};

const removePending = (config: RequestConfig) => {
const url = config.url ?? "";

if (url && pendingMap.has(url)) {
pendingMap.get(url)?.abort();
pendingMap.delete(url);
}
};

const requestInterceptor = () => {
axiosInstance.interceptors.request.use(
(config: InternalAxiosRequestConfig<any>) => {
removePending(config);
addPending(config);

return config;
},
(error: any) => {
return Promise.reject(error);
return Promise.resolve(error);
},
);
};
Expand All @@ -69,14 +35,13 @@ const responseInterceptor = () => {

// 全局提示。忽略排除的 url 或 baseURL
if (!_errorIgnore) {
// onError?.(_data.message);
onError?.(_data);
}

if (response.status === 401) {
onLogin?.();
}

removePending(_config);
return _data;
},
(error: any) => {
Expand All @@ -85,7 +50,7 @@ const responseInterceptor = () => {
onError?.("network error.");
}

return Promise.reject(error);
return Promise.resolve(error);
},
);
};
Expand All @@ -105,7 +70,6 @@ export const createAxios = (
});

errorIgnore = config.errorIgnore ?? [];
abortUrls = config.abortUrls ?? [];
onError = config.onError;
onLogin = config.onLogin;

Expand Down Expand Up @@ -142,8 +106,9 @@ export const request = <T>(
method: config.method,
data: _data,
params: config.params?.query,
headers: config.params?.header,
headers: config.params?.header as AxiosHeaders,
timeout: config.config?.timeout,
signal: config.config?.signal,
baseURL: config.config?.baseURL,
});
};
24 changes: 1 addition & 23 deletions src/plugins/typescript/shared/fetchRuntime.eta
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const fetchRuntime = <T>(
url: string,
method: ApiClientMethod,
req?: ApiClientParams,
config?: ApiClientConfig,
config?: ApiClientConfig['config'],
): Promise<T> => {
const _url = generateURL(url, req?.path as unknown as IDefaultObject);

Expand All @@ -33,25 +33,3 @@ export const fetchRuntime = <T>(

return request<T>(apiClientConfig);
};

/**
* 1.`webClient.create` is modified to `createApiClient`
*
* 2.`webClient.request` modified to `fetchRuntime`
*/
export class ApiClient {
static create (config: Omit<ApiClientConfig, "url" | "signal" | "config">): void {
createApiClient(config);
}

static request<T>(
url: string,
method: ApiClientMethod,
req?: ApiClientParams,
config?: ApiClientConfig,
): Promise<T> {
return fetchRuntime<T>(url, method, req, config);
}
}

export default ApiClient;
2 changes: 1 addition & 1 deletion src/plugins/typescript/shared/index.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/plugins/typescript/template/actionImport.eta
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ApiClientConfig } from '<%= it.importPath %>shared/apiClientBase'
import { fetchRuntime } from '<%= it.importPath %>shared/fetchRuntime'
<% if (it.imports.length) { %>
import type { <%= it.imports.join(', ') %> } from '<%= it.importPath %><%= it.typeFileName %>'
Expand Down
5 changes: 3 additions & 2 deletions src/plugins/typescript/template/actionMethod.eta
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@

<% }) %>
<% } %>
* @param {ApiClientConfig['config']} [config] - ApiClientConfig['config']
* @returns {Promise<<%~ it.responseType %>>} Promise<<%~ it.responseType %>>
*/
<% /* API 方法 */ %>
export const <%= it.methodName %> = (<% it.params.forEach((param, index) => { %>
<%= param.name %><% if (!param.required) { %>?<% } %>: <%~ param.type %><% if (index < it.params.length - 1) { %>, <% } %>
<% }) %>): Promise<<%~ it.responseType %>> => fetchRuntime<<%~ it.responseType %>>('<%= it.url %>', '<%= it.method.toUpperCase() %>'<% if (it.params.length) { %>, {
<% }) %><% if (it.params.length) { %>, <% } %>config?: ApiClientConfig['config']): Promise<<%~ it.responseType %>> => fetchRuntime<<%~ it.responseType %>>('<%= it.url %>', '<%= it.method.toUpperCase() %>'<% if (it.params.length) { %>, {
<% it.params.forEach((param, index) => { %>
<%= param.category %><% if (param.category === param.name) { %>
<% } else { %>: <% if (param.category === 'body') { %><%= param.name %><% } else { %>{
Expand All @@ -35,4 +36,4 @@ export const <%= it.methodName %> = (<% it.params.forEach((param, index) => { %>
<% } %><% if (index < it.params.length - 1) { %>, <% } %>

<% }) %>
}<% } %>)
}<% } %>, config)
2 changes: 1 addition & 1 deletion src/plugins/typescript/template/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// this file is auto generated.
export default {"actionImport":"import { fetchRuntime } from '<%= it.importPath %>shared/fetchRuntime'\n<% if (it.imports.length) { %>\nimport type { <%= it.imports.join(', ') %> } from '<%= it.importPath %><%= it.typeFileName %>'\n<% } %>","actionMethod":"<% /* API 方法注释 */ %>\n/**\n<% if (it.summary) { %>\n * <%~ it.summary %>\n<% } %>\n<% if (it.summary !== it.description) { %>\n<% if (it.summary && it.description) { %>\n\n *\n<% } %>\n<% if (it.description) { %>\n * @description <%~ it.description %>\n<% } %>\n<% } %>\n<% if (it.params.length) { %>\n\n *\n<% it.params.forEach(param => { %>\n * @param {<%~ param.type %>} <% if (!param.required) { %>[<% } %><%= param.name %><% if (!param.required) { %>]<% } %> - <%~ param.description || param.type %>\n\n<% }) %>\n<% } %>\n * @returns {Promise<<%~ it.responseType %>>} Promise<<%~ it.responseType %>>\n */\n<% /* API 方法 */ %>\nexport const <%= it.methodName %> = (<% it.params.forEach((param, index) => { %>\n<%= param.name %><% if (!param.required) { %>?<% } %>: <%~ param.type %><% if (index < it.params.length - 1) { %>, <% } %>\n<% }) %>): Promise<<%~ it.responseType %>> => fetchRuntime<<%~ it.responseType %>>('<%= it.url %>', '<%= it.method.toUpperCase() %>'<% if (it.params.length) { %>, {\n<% it.params.forEach((param, index) => { %>\n <%= param.category %><% if (param.category === param.name) { %>\n<% } else { %>: <% if (param.category === 'body') { %><%= param.name %><% } else { %>{\n\t\t<%= param.name %>\n\n\t}<% } %>\n<% } %><% if (index < it.params.length - 1) { %>, <% } %>\n\n<% }) %>\n}<% } %>)\n","definitionBody":"<% if (it.propCommit) { %>\n /**\n * <%~ it.propCommit %>\n\n */\n<% } %>\n <%= it.prop.name %><% if (!it.prop.required) { %>?<% } %>: <%~ it.propType %>;","definitionFooter":"}\n// #endregion\n","definitionHeader":"// #region <%= it.defName %>\n\nexport interface <%= it.defName %> {","enum":"<% \n const option = it.data.map(item => { \n const val = it.convertValue(item)\n\n return typeof val === 'number' ? val : `'${val}'`\n })\n%>\n// #region <%= it.name %>\n\nexport type <%= it.name %> = <%~ option.join(\" | \") %>;\n// #endregion\n"}
export default {"actionImport":"import type { ApiClientConfig } from '<%= it.importPath %>shared/apiClientBase'\nimport { fetchRuntime } from '<%= it.importPath %>shared/fetchRuntime'\n<% if (it.imports.length) { %>\nimport type { <%= it.imports.join(', ') %> } from '<%= it.importPath %><%= it.typeFileName %>'\n<% } %>","actionMethod":"<% /* API 方法注释 */ %>\n/**\n<% if (it.summary) { %>\n * <%~ it.summary %>\n<% } %>\n<% if (it.summary !== it.description) { %>\n<% if (it.summary && it.description) { %>\n\n *\n<% } %>\n<% if (it.description) { %>\n * @description <%~ it.description %>\n<% } %>\n<% } %>\n<% if (it.params.length) { %>\n\n *\n<% it.params.forEach(param => { %>\n * @param {<%~ param.type %>} <% if (!param.required) { %>[<% } %><%= param.name %><% if (!param.required) { %>]<% } %> - <%~ param.description || param.type %>\n\n<% }) %>\n<% } %>\n * @param {ApiClientConfig['config']} [config] - ApiClientConfig['config']\n * @returns {Promise<<%~ it.responseType %>>} Promise<<%~ it.responseType %>>\n */\n<% /* API 方法 */ %>\nexport const <%= it.methodName %> = (<% it.params.forEach((param, index) => { %>\n<%= param.name %><% if (!param.required) { %>?<% } %>: <%~ param.type %><% if (index < it.params.length - 1) { %>, <% } %>\n<% }) %><% if (it.params.length) { %>, <% } %>config?: ApiClientConfig['config']): Promise<<%~ it.responseType %>> => fetchRuntime<<%~ it.responseType %>>('<%= it.url %>', '<%= it.method.toUpperCase() %>'<% if (it.params.length) { %>, {\n<% it.params.forEach((param, index) => { %>\n <%= param.category %><% if (param.category === param.name) { %>\n<% } else { %>: <% if (param.category === 'body') { %><%= param.name %><% } else { %>{\n\t\t<%= param.name %>\n\n\t}<% } %>\n<% } %><% if (index < it.params.length - 1) { %>, <% } %>\n\n<% }) %>\n}<% } %>, config)\n","definitionBody":"<% if (it.propCommit) { %>\n /**\n * <%~ it.propCommit %>\n\n */\n<% } %>\n <%= it.prop.name %><% if (!it.prop.required) { %>?<% } %>: <%~ it.propType %>;","definitionFooter":"}\n// #endregion\n","definitionHeader":"// #region <%= it.defName %>\n\nexport interface <%= it.defName %> {","enum":"<% \n const option = it.data.map(item => { \n const val = it.convertValue(item)\n\n return typeof val === 'number' ? val : `'${val}'`\n })\n%>\n// #region <%= it.name %>\n\nexport type <%= it.name %> = <%~ option.join(\" | \") %>;\n// #endregion\n"}

0 comments on commit 12f218e

Please sign in to comment.