Pont - 搭建前后端之桥,生成前端接口层代码
一、创建项目
bash
1yarn create vite my-react-app --template react
二、安装依赖
bash
1yarn add axios qs swr pont-engine
三、创建文件
3.1 创建src/utils/service.ts
文件,内容如下
typescript
1import axios, { 2 AxiosInstance, 3 AxiosRequestConfig, 4 AxiosResponse, 5 AxiosError, 6 InternalAxiosRequestConfig, 7} from "axios"; 8import qs from "qs"; 9import useSwr, { SWRConfiguration ,SWRResponse} from "swr"; 10 11/** 后端返回的数据类型 */ 12type ResponseData<T> = T; 13// type ResponseData<T> = { 14// code: number; 15// data: T; 16// message: string; 17// }; 18 19/** 创建axios实例 */ 20const axiosInstance: AxiosInstance = axios.create({ 21 timeout: 60000, 22 baseURL:'http://localhost:3000' 23}); 24 25/** 异常拦截处理器 */ 26const errorHandler = (error: AxiosError) => { 27 if (error.response) { 28 switch (error.response.status) { 29 case 401: 30 // 登录过期错误处理 31 break; 32 case 500: 33 // 服务器错误处理 34 break; 35 default: 36 } 37 } 38 return Promise.reject(error); 39}; 40/** 请求拦截处理器 */ 41axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { 42 // qs是axios自带的序列化参数方式 43 if ( 44 config.headers && 45 config.headers["Content-Type"] && 46 (config.headers["Content-Type"] as string).includes( 47 "application/x-www-form-urlencoded" 48 ) 49 ) { 50 config.params = qs.stringify(config.params); 51 } 52 return config; 53}, errorHandler); 54 55/** 响应拦截处理器 */ 56axiosInstance.interceptors.response.use((response: AxiosResponse) => { 57 return response; 58}, errorHandler); 59 60/*** 61 * @name axios 请求封装 62 * @config AxiosRequestConfig 63 * */ 64export function service<T>(config: AxiosRequestConfig): Promise<T> { 65 return new Promise((resolve, reject) => { 66 axiosInstance 67 .request<T, AxiosResponse<ResponseData<T>>>(config) 68 .then((result: AxiosResponse<ResponseData<T>>) => { 69 const { data } = result; 70 resolve(data); 71 // if (data.code === 0) { 72 // resolve(data.data); 73 // } else { 74 // reject(data); 75 // } 76 }) 77 .catch((err: AxiosError) => { 78 reject(err); 79 }); 80 }); 81} 82 83/*** 84 * @name useService 请求封装 85 * @config AxiosRequestConfig 86 * @options SWRConfiguration 87 * SWRResponse 88 * */ 89export function useService<T>( 90 config: AxiosRequestConfig, 91 options?: SWRConfiguration | null 92):SWRResponse<T> { 93 const { isLoading, error, ...other } = useSwr( 94 options 95 ? `${config.url}${qs.stringify(config.params || {})}${qs.stringify( 96 config.data || {} 97 )}` 98 : null, 99 () => service<T>(config), 100 options || {} 101 ); 102 return { ...other, isLoading: error ? false : isLoading, error }; 103} 104 105
3.2 创建config/pont-config.json
文件,内容如下:
json
1{ 2 "outDir": "../src/services", 3 "templatePath": "./pontTemplate", 4 "originType": "SwaggerV2", 5 "originUrl": "https://petstore.swagger.io/v2/swagger.json", 6 "prettierConfig": { 7 "useTabs": false, 8 "tabWidth": 2, 9 "printWidth": 100, 10 "singleQuote": true, 11 "trailingComma": "none", 12 "bracketSpacing": true, 13 "semi": false 14 } 15} 16
3.2 创建config/pontTemplate.ts
文件,内容如下:
typescript
1import { CodeGenerator, Interface } from "pont-engine"; 2 3export default class MyGenerator extends CodeGenerator { 4 getInterfaceContent(inter: Interface) { 5 const url = inter.path; 6 const method = inter.method.toUpperCase(); 7 const paramsCode = inter.getParamsCode(); 8 const description = inter.description.replace(/(\n|\s)/g, ""); 9 return ` 10 /*** 11 * @description ${description} 12 * @name ${inter.name} 13 */ 14 import { useService, service } from "@/utils/service"; 15 import type { SWRConfiguration, SWRResponse } from "swr"; 16 17 export ${paramsCode}; 18 19 export type Response = ${inter.responseType}; 20 ${ 21 inter.getBodyParamsCode() 22 ? `export type Body = ${inter.getBodyParamsCode()};` 23 : "" 24 } 25 26 27 export function request(params:Params${ 28 inter.getBodyParamsCode() ? `,data:Body` : "" 29 },): Promise<Response> { 30 return service<Response>({ 31 url:\`${url.replace(/{/g, "${params.")}\`, 32 method:"${method}", 33 params, 34 ${inter.getBodyParamsCode() ? `data` : ""} 35 }) 36 } 37 export function useRequest(params:Params${ 38 inter.getBodyParamsCode() ? `,data:Body` : "" 39 }, options?: SWRConfiguration | null):SWRResponse<Response> { 40 return useService<Response>({ 41 url:\`${url.replace(/{/g, "${params.")}\`, 42 method:"${method}", 43 params, 44 ${inter.getBodyParamsCode() ? `data` : ""} 45 },options) 46 } 47 `; 48 } 49 /** 获取总的类型定义代码 */ 50 getDeclaration() { 51 return ` 52 type ObjectMap<Key extends string | number | symbol = any, Value = any> = { 53 [key in Key]: Value; 54 } 55 56 declare type SWRConfiguration = import('swr').SWRConfiguration 57 declare type SWRResponse<T> = import('swr').SWRResponse<T> 58 59 ${this.getCommonDeclaration()} 60 61 ${this.getBaseClassesInDeclaration()} 62 63 ${this.getModsDeclaration()} 64 `; 65 } 66 getInterfaceContentInDeclaration(inter: Interface) { 67 const paramsCode = inter.getParamsCode(); 68 const description = inter.description.replace(/(\n|\s)/g, ""); 69 return ` 70 /*** 71 * @description ${description} 72 * @name ${inter.name} 73 */ 74 75 export ${paramsCode}; 76 77 78 export type Response = ${inter.responseType}; 79 ${ 80 inter.getBodyParamsCode() 81 ? `export type Body = ${inter.getBodyParamsCode()};` 82 : "" 83 } 84 85 86 export function request(params:Params${ 87 inter.getBodyParamsCode() ? `,data:Body` : "" 88 },): Promise<Response>; 89 export function useRequest(params:Params${ 90 inter.getBodyParamsCode() ? `,data:Body` : "" 91 }, options?: SWRConfiguration | null): SWRResponse<Response>; 92 `; 93 } 94 /** 获取所有模块的 index 入口文件 */ 95 getModsIndex() { 96 let conclusion = ` 97 export { 98 ${this.dataSource.mods.map((mod) => mod.name).join(", \n")} 99 }; 100 `; 101 102 // dataSource name means multiple dataSource 103 if (this.dataSource.name) { 104 conclusion = ` 105 export const ${this.dataSource.name} = { 106 ${this.dataSource.mods.map((mod) => mod.name).join(", \n")} 107 }; 108 `; 109 } 110 111 return ` 112 ${this.dataSource.mods 113 .map((mod) => { 114 return `import * as ${mod.name} from './${mod.name}';`; 115 }) 116 .join("\n")} 117 118 ${conclusion} 119 `; 120 } 121 122 /** 获取接口类和基类的总的 index 入口文件代码 */ 123 getIndex() { 124 let conclusion = ` 125 import * as API from './mods'; 126 window.API = API 127 `; 128 if (this.dataSource.name) { 129 conclusion = ` 130 import { ${this.dataSource.name} } from './mods/'; 131 window.API = ${this.dataSource.name} 132 `; 133 } 134 return conclusion; 135 } 136} 137 138
四、拉取接口生成文件
4.1 命令拉取
在
package.json
中scripts
新增"pont": "pont generate",
4.2 vs code 安装插件 pont
阅读量:1157发布日期:2023-08-29 11:00:30
博客描述
Pont - 搭建前后端之桥,生成前端接口层代码,解放生产力