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

This commit is contained in:
神仙都没用 2023-10-13 17:24:28 +08:00
parent 55ad9b30a6
commit a4990fc6be
6 changed files with 239 additions and 205 deletions

55
build/cool/base.ts Normal file
View File

@ -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);
}
};
}

View File

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

View File

@ -1,73 +1,6 @@
import { Plugin } from "vite"; import { base } from "./base";
import { createSvg } from "./svg"; import { virtual } from "./virtual";
import { createTag } from "./tag";
import { createEps } from "./eps";
import { createModule } from "./module";
import { createMenu } from "./menu";
import { parseJson } from "./utils";
export function cool(): Plugin { export function cool() {
// 虚拟模块 return [base(), virtual()];
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();
}
}
};
} }

View File

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

32
build/cool/types/index.d.ts vendored Normal file
View File

@ -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
build/cool/virtual.ts Normal file
View File

@ -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)}
`;
}
}
};
}