Pont - 搭建前后端之桥,生成前端接口层代码
# 一、创建项目 ```bash yarn create vite my-react-app --template react ``` # 二、安装依赖 ```bash yarn add axios qs swr pont-engine ``` # 三、创建文件 ## 3.1 创建`src/utils/service.ts`文件,内容如下 ```typescript import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError, InternalAxiosRequestConfig, } from "axios"; import qs from "qs"; import useSwr, { SWRConfiguration ,SWRResponse} from "swr"; /** 后端返回的数据类型 */ type ResponseData<T> = T; // type ResponseData<T> = { // code: number; // data: T; // message: string; // }; /** 创建axios实例 */ const axiosInstance: AxiosInstance = axios.create({ timeout: 60000, baseURL:'http://localhost:3000' }); /** 异常拦截处理器 */ const errorHandler = (error: AxiosError) => { if (error.response) { switch (error.response.status) { case 401: // 登录过期错误处理 break; case 500: // 服务器错误处理 break; default: } } return Promise.reject(error); }; /** 请求拦截处理器 */ axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { // qs是axios自带的序列化参数方式 if ( config.headers && config.headers["Content-Type"] && (config.headers["Content-Type"] as string).includes( "application/x-www-form-urlencoded" ) ) { config.params = qs.stringify(config.params); } return config; }, errorHandler); /** 响应拦截处理器 */ axiosInstance.interceptors.response.use((response: AxiosResponse) => { return response; }, errorHandler); /*** * @name axios 请求封装 * @config AxiosRequestConfig * */ export function service<T>(config: AxiosRequestConfig): Promise<T> { return new Promise((resolve, reject) => { axiosInstance .request<T, AxiosResponse<ResponseData<T>>>(config) .then((result: AxiosResponse<ResponseData<T>>) => { const { data } = result; resolve(data); // if (data.code === 0) { // resolve(data.data); // } else { // reject(data); // } }) .catch((err: AxiosError) => { reject(err); }); }); } /*** * @name useService 请求封装 * @config AxiosRequestConfig * @options SWRConfiguration * SWRResponse * */ export function useService<T>( config: AxiosRequestConfig, options?: SWRConfiguration | null ):SWRResponse<T> { const { isLoading, error, ...other } = useSwr( options ? `${config.url}${qs.stringify(config.params || {})}${qs.stringify( config.data || {} )}` : null, () => service<T>(config), options || {} ); return { ...other, isLoading: error ? false : isLoading, error }; } ``` ## 3.2 创建`config/pont-config.json`文件,内容如下: ```json { "outDir": "../src/services", "templatePath": "./pontTemplate", "originType": "SwaggerV2", "originUrl": "https://petstore.swagger.io/v2/swagger.json", "prettierConfig": { "useTabs": false, "tabWidth": 2, "printWidth": 100, "singleQuote": true, "trailingComma": "none", "bracketSpacing": true, "semi": false } } ``` ## 3.2 创建`config/pontTemplate.ts`文件,内容如下: ```typescript import { CodeGenerator, Interface } from "pont-engine"; export default class MyGenerator extends CodeGenerator { getInterfaceContent(inter: Interface) { const url = inter.path; const method = inter.method.toUpperCase(); const paramsCode = inter.getParamsCode(); const description = inter.description.replace(/(\n|\s)/g, ""); return ` /*** * @description ${description} * @name ${inter.name} */ import { useService, service } from "@/utils/service"; import type { SWRConfiguration, SWRResponse } from "swr"; export ${paramsCode}; export type Response = ${inter.responseType}; ${ inter.getBodyParamsCode() ? `export type Body = ${inter.getBodyParamsCode()};` : "" } export function request(params:Params${ inter.getBodyParamsCode() ? `,data:Body` : "" },): Promise<Response> { return service<Response>({ url:\`${url.replace(/{/g, "${params.")}\`, method:"${method}", params, ${inter.getBodyParamsCode() ? `data` : ""} }) } export function useRequest(params:Params${ inter.getBodyParamsCode() ? `,data:Body` : "" }, options?: SWRConfiguration | null):SWRResponse<Response> { return useService<Response>({ url:\`${url.replace(/{/g, "${params.")}\`, method:"${method}", params, ${inter.getBodyParamsCode() ? `data` : ""} },options) } `; } /** 获取总的类型定义代码 */ getDeclaration() { return ` type ObjectMap<Key extends string | number | symbol = any, Value = any> = { [key in Key]: Value; } declare type SWRConfiguration = import('swr').SWRConfiguration declare type SWRResponse<T> = import('swr').SWRResponse<T> ${this.getCommonDeclaration()} ${this.getBaseClassesInDeclaration()} ${this.getModsDeclaration()} `; } getInterfaceContentInDeclaration(inter: Interface) { const paramsCode = inter.getParamsCode(); const description = inter.description.replace(/(\n|\s)/g, ""); return ` /*** * @description ${description} * @name ${inter.name} */ export ${paramsCode}; export type Response = ${inter.responseType}; ${ inter.getBodyParamsCode() ? `export type Body = ${inter.getBodyParamsCode()};` : "" } export function request(params:Params${ inter.getBodyParamsCode() ? `,data:Body` : "" },): Promise<Response>; export function useRequest(params:Params${ inter.getBodyParamsCode() ? `,data:Body` : "" }, options?: SWRConfiguration | null): SWRResponse<Response>; `; } /** 获取所有模块的 index 入口文件 */ getModsIndex() { let conclusion = ` export { ${this.dataSource.mods.map((mod) => mod.name).join(", \n")} }; `; // dataSource name means multiple dataSource if (this.dataSource.name) { conclusion = ` export const ${this.dataSource.name} = { ${this.dataSource.mods.map((mod) => mod.name).join(", \n")} }; `; } return ` ${this.dataSource.mods .map((mod) => { return `import * as ${mod.name} from './${mod.name}';`; }) .join("\n")} ${conclusion} `; } /** 获取接口类和基类的总的 index 入口文件代码 */ getIndex() { let conclusion = ` import * as API from './mods'; window.API = API `; if (this.dataSource.name) { conclusion = ` import { ${this.dataSource.name} } from './mods/'; window.API = ${this.dataSource.name} `; } return conclusion; } } ``` # 四、拉取接口生成文件 ## 4.1 命令拉取 > 在`package.json`中`scripts`新增` "pont": "pont generate",` ## 4.2 vs code 安装插件 `pont`
博客描述
Pont - 搭建前后端之桥,生成前端接口层代码,解放生产力