Эх сурвалжийг харах

解决页面刷新及代码保存未触发 eps 刷新问题

神仙都没用 1 жил өмнө
parent
commit
a4990fc6be

+ 55 - 0
build/cool/base.ts

@@ -0,0 +1,55 @@
+import { Plugin } from "vite";
+import { createSvg } from "./svg";
+import { createTag } from "./tag";
+import { createEps } from "./eps";
+import { createMenu } from "./menu";
+import { parseJson } from "./utils";
+
+export function base(): Plugin {
+	return {
+		name: "vite-cool-base",
+		enforce: "pre",
+		configureServer(server) {
+			server.middlewares.use(async (req, res, next) => {
+				function done(data: any) {
+					res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" });
+					res.end(JSON.stringify(data));
+				}
+
+				if (req.url?.includes("__cool")) {
+					const body = await parseJson(req);
+
+					switch (req.url) {
+						// 快速创建菜单
+						case "/__cool_createMenu":
+							await createMenu(body);
+							break;
+
+						// 创建描述文件
+						case "/__cool_eps":
+							await createEps(body);
+							break;
+
+						default:
+							return done({
+								code: 1001,
+								message: "未知请求"
+							});
+					}
+
+					done({
+						code: 1000
+					});
+				} else {
+					next();
+				}
+			});
+		},
+		transform(code, id) {
+			return createTag(code, id);
+		},
+		transformIndexHtml(html) {
+			return createSvg(html);
+		}
+	};
+}

+ 85 - 130
build/cool/eps/index.ts

@@ -6,51 +6,22 @@ import { isArray, isEmpty, last, merge } from "lodash";
 import { createWriteStream } from "fs";
 import prettier from "prettier";
 import { proxy } from "../../../src/config/proxy";
-
-// 实体类型
-type Entity = {
-	api: {
-		dts: {
-			parameters?: {
-				description: string;
-				name: string;
-				required: boolean;
-				schema: {
-					type: string;
-				};
-			}[];
-		};
-		name: string;
-		method: string;
-		path: string;
-		prefix: string;
-		summary: string;
-		tag: string;
-	}[];
-	columns: {
-		comment: string;
-		length: string;
-		nullable: boolean;
-		propertyName: string;
-		type: string;
-	}[];
-	module: string;
-	name: string;
-	prefix: string;
-};
+import type { Eps } from "../types";
 
 // 获取方法名
 function getNames(v: any) {
 	return Object.keys(v).filter((e) => !["namespace", "permission"].includes(e));
 }
 
-// 获取数据
-async function getData(temps: any[]) {
-	let list: Entity[] = [];
+// 数据
+let service = {};
+let list: Eps.Entity[] = [];
 
+// 获取数据
+async function getData(temps?: Eps.Entity[]) {
 	// 本地文件
 	try {
-		list = JSON.parse(readFile(join(DistPath, "eps.json")));
+		list = JSON.parse(readFile(join(DistPath, "eps.json")) || "[]");
 	} catch (err) {
 		error(`[eps] ${join(DistPath, "eps.json")} 文件异常, ${err.message}`);
 	}
@@ -68,18 +39,17 @@ async function getData(temps: any[]) {
 
 			if (code === 1000) {
 				if (!isEmpty(data) && data) {
-					// @ts-ignore
-					list = Object.values(data).flat();
+					list = Object.values(data).flat() as Eps.Entity[];
 				}
 			} else {
 				error(`[eps] ${message}`);
 			}
 		})
 		.catch(() => {
-			error(`[eps] 获取失败, ${url} 无法访问,请启动服务!`);
+			error(`[eps] ${url} 服务未启动!!!`);
 		});
 
-	// 判断是否重复项
+	// 合并本地 service 数据
 	if (isArray(temps)) {
 		temps.forEach((e) => {
 			const d = list.find((a) => e.prefix === a.prefix);
@@ -91,35 +61,31 @@ async function getData(temps: any[]) {
 			}
 		});
 	}
-
-	return list;
 }
 
-// 创建数据文件
-function createJson(eps: Entity[]) {
-	createWriteStream(join(DistPath, "eps.json"), {
-		flags: "w"
-	}).write(
-		JSON.stringify(
-			eps.map((e) => {
+// 创建 json 文件
+function createJson() {
+	const d = list.map((e) => {
+		return {
+			prefix: e.prefix,
+			name: e.name || "",
+			api: e.api.map((e) => {
 				return {
-					prefix: e.prefix,
-					name: e.name || "",
-					api: e.api.map((e) => {
-						return {
-							name: e.name,
-							method: e.method,
-							path: e.path
-						};
-					})
+					name: e.name,
+					method: e.method,
+					path: e.path
 				};
 			})
-		)
-	);
+		};
+	});
+
+	createWriteStream(join(DistPath, "eps.json"), {
+		flags: "w"
+	}).write(JSON.stringify(d));
 }
 
 // 创建描述文件
-async function createDescribe({ list, service }: { list: Entity[]; service: any }) {
+async function createDescribe({ list, service }: { list: Eps.Entity[]; service: any }) {
 	// 获取类型
 	function getType({ propertyName, type }) {
 		for (const map of Entity.mapping) {
@@ -355,7 +321,7 @@ async function createDescribe({ list, service }: { list: Entity[]; service: any
 	`;
 
 	// 文本内容
-	const content = await prettier.format(text, {
+	const content = prettier.format(text, {
 		parser: "typescript",
 		useTabs: true,
 		tabWidth: 4,
@@ -372,93 +338,82 @@ async function createDescribe({ list, service }: { list: Entity[]; service: any
 	}).write(content);
 }
 
-// 创建服务
-function createService(data: Entity[]) {
-	const list: Entity[] = [];
-	const service = {};
-	const d = { data };
-
-	for (const i in d) {
-		if (isArray(d[i])) {
-			d[i].forEach((e: Entity) => {
-				// 分隔路径
-				const arr = e.prefix
-					.replace(/\//, "")
-					.replace("admin", "")
-					.split("/")
-					.filter(Boolean)
-					.map(toCamel);
-
-				// 遍历
-				function deep(d: any, i: number) {
-					const k = arr[i];
-
-					if (k) {
-						// 是否最后一个
-						if (arr[i + 1]) {
-							if (!d[k]) {
-								d[k] = {};
-							}
-
-							deep(d[k], i + 1);
-						} else {
-							// 本地不存在则创建实例
-							if (!d[k]) {
-								d[k] = {
-									namespace: e.prefix.substring(1, e.prefix.length),
-									permission: {}
-								};
-							}
-
-							// 创建方法
-							e.api.forEach((a) => {
-								// 方法名
-								const n = a.path.replace("/", "");
+// 创建 service
+function createService() {
+	list.forEach((e) => {
+		// 分隔路径
+		const arr = e.prefix
+			.replace(/\//, "")
+			.replace("admin", "")
+			.split("/")
+			.filter(Boolean)
+			.map(toCamel);
+
+		// 遍历
+		function deep(d: any, i: number) {
+			const k = arr[i];
+
+			if (k) {
+				// 是否最后一个
+				if (arr[i + 1]) {
+					if (!d[k]) {
+						d[k] = {};
+					}
 
-								if (n && !/[-:]/g.test(n)) {
-									d[k][n] = a;
-								}
-							});
+					deep(d[k], i + 1);
+				} else {
+					// 不存在则创建
+					if (!d[k]) {
+						d[k] = {
+							namespace: e.prefix.substring(1, e.prefix.length),
+							permission: {}
+						};
+					}
 
-							// 创建权限
-							getNames(d[k]).forEach((e) => {
-								d[k].permission[e] = `${d[k].namespace.replace(
-									"admin/",
-									""
-								)}/${e}`.replace(/\//g, ":");
-							});
+					// 创建方法
+					e.api.forEach((a) => {
+						// 方法名
+						const n = a.path.replace("/", "");
 
-							list.push(e);
+						if (n && !/[-:]/g.test(n)) {
+							d[k][n] = a;
 						}
-					}
+					});
+
+					// 创建权限
+					getNames(d[k]).forEach((e) => {
+						d[k].permission[e] = `${d[k].namespace.replace("admin/", "")}/${e}`.replace(
+							/\//g,
+							":"
+						);
+					});
 				}
-
-				deep(service, 0);
-			});
+			}
 		}
-	}
 
-	return { service, list };
+		deep(service, 0);
+	});
 }
 
 // 创建 eps
 export async function createEps(query?: { list: any[] }) {
 	// 获取数据
-	const data = await getData(query?.list || []);
+	await getData(query?.list || []);
 
-	// 生成数据
-	const { service, list } = createService(data);
+	// 创建 service
+	createService();
 
 	// 创建临时目录
 	createDir(DistPath);
 
-	// 创建数据文件
-	createJson(data);
+	// 创建 json 文件
+	createJson();
 
 	// 创建描述文件
 	createDescribe({ service, list });
 
-	return `
-	export const eps = ${JSON.stringify({ service, list })}
-	`;
+	return {
+		service,
+		list
+	};
 }

+ 4 - 71
build/cool/index.ts

@@ -1,73 +1,6 @@
-import { Plugin } from "vite";
-import { createSvg } from "./svg";
-import { createTag } from "./tag";
-import { createEps } from "./eps";
-import { createModule } from "./module";
-import { createMenu } from "./menu";
-import { parseJson } from "./utils";
+import { base } from "./base";
+import { virtual } from "./virtual";
 
-export function cool(): Plugin {
-	// 虚拟模块
-	const virtualModuleIds = ["virtual:eps", "virtual:module"];
-
-	return {
-		name: "vite-cool",
-		enforce: "pre",
-		configureServer(server) {
-			server.middlewares.use(async (req, res, next) => {
-				function done(data: any) {
-					res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" });
-					res.end(JSON.stringify(data));
-				}
-
-				if (req.url?.includes("__cool")) {
-					const body = await parseJson(req);
-
-					switch (req.url) {
-						// 快速创建菜单
-						case "/__cool_createMenu":
-							await createMenu(body);
-							break;
-
-						// 创建描述文件
-						case "/__cool_eps":
-							await createEps(body);
-							break;
-
-						default:
-							return done({
-								code: 1001,
-								message: "未知请求"
-							});
-					}
-
-					done({
-						code: 1000
-					});
-				} else {
-					next();
-				}
-			});
-		},
-		transform(code, id) {
-			return createTag(code, id);
-		},
-		transformIndexHtml(html) {
-			return createSvg(html);
-		},
-		resolveId(id) {
-			if (virtualModuleIds.includes(id)) {
-				return "\0" + id;
-			}
-		},
-		async load(id) {
-			if (id === "\0virtual:eps") {
-				return createEps();
-			}
-
-			if (id === "\0virtual:module") {
-				return createModule();
-			}
-		}
-	};
+export function cool() {
+	return [base(), virtual()];
 }

+ 1 - 3
build/cool/module/index.ts

@@ -8,7 +8,5 @@ export function createModule() {
 		dirs = dirs.filter((e) => !e.includes("."));
 	} catch (err) {}
 
-	return `
-		export const dirs = ${JSON.stringify(dirs)}
-	`;
+	return { dirs };
 }

+ 32 - 0
build/cool/types/index.d.ts

@@ -0,0 +1,32 @@
+export namespace Eps {
+	interface Entity {
+		api: {
+			dts: {
+				parameters?: {
+					description: string;
+					name: string;
+					required: boolean;
+					schema: {
+						type: string;
+					};
+				}[];
+			};
+			name: string;
+			method: string;
+			path: string;
+			prefix: string;
+			summary: string;
+			tag: string;
+		}[];
+		columns: {
+			comment: string;
+			length: string;
+			nullable: boolean;
+			propertyName: string;
+			type: string;
+		}[];
+		module: string;
+		name: string;
+		prefix: string;
+	}
+}

+ 61 - 0
build/cool/virtual.ts

@@ -0,0 +1,61 @@
+import type { Plugin, ViteDevServer } from "vite";
+import { createEps } from "./eps";
+import { createModule } from "./module";
+
+export function virtual(): Plugin {
+	const virtualModuleIds = ["virtual:eps", "virtual:module"];
+
+	// 使虚拟模块失效,重新加载
+	function buildEps(server: ViteDevServer) {
+		virtualModuleIds.forEach((vm) => {
+			const mod = server.moduleGraph.getModuleById(`\0${vm}`);
+
+			if (mod) {
+				server.moduleGraph.invalidateModule(mod);
+			}
+		});
+	}
+
+	return {
+		name: "vite-cool-virtual",
+		enforce: "pre",
+		configureServer(server) {
+			server.middlewares.use(async (req, res, next) => {
+				// 页面刷新时触发 eps 刷新
+				if (req.url == "/@vite/client") {
+					buildEps(server);
+				}
+
+				next();
+			});
+		},
+		handleHotUpdate({ file, server }) {
+			// 代码保存时触发 eps 刷新
+			if (!file.includes("build/cool/dist")) {
+				buildEps(server);
+			}
+		},
+		resolveId(id) {
+			if (virtualModuleIds.includes(id)) {
+				return "\0" + id;
+			}
+		},
+		async load(id) {
+			if (id === "\0virtual:eps") {
+				const { service, list } = await createEps();
+
+				return `
+					export const eps = ${JSON.stringify({ service, list })}
+				`;
+			}
+
+			if (id === "\0virtual:module") {
+				const { dirs } = createModule();
+
+				return `
+					export const dirs = ${JSON.stringify(dirs)}
+				`;
+			}
+		}
+	};
+}