diff --git a/build/cool/base.ts b/build/cool/base.ts new file mode 100644 index 0000000..ce3ea23 --- /dev/null +++ b/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); + } + }; +} diff --git a/build/cool/eps/index.ts b/build/cool/eps/index.ts index b9d45f1..dbfbd28 100644 --- a/build/cool/eps/index.ts +++ b/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 }; +// 创建 service +function createService() { + list.forEach((e) => { + // 分隔路径 + const arr = e.prefix + .replace(/\//, "") + .replace("admin", "") + .split("/") + .filter(Boolean) + .map(toCamel); - 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]; - // 遍历 - 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("/", ""); - - 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); - } + 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("/", ""); + + 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 + }; } diff --git a/build/cool/index.ts b/build/cool/index.ts index 0e8d96d..6013f1a 100644 --- a/build/cool/index.ts +++ b/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()]; } diff --git a/build/cool/module/index.ts b/build/cool/module/index.ts index 3677569..d3956d6 100644 --- a/build/cool/module/index.ts +++ b/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 }; } diff --git a/build/cool/types/index.d.ts b/build/cool/types/index.d.ts new file mode 100644 index 0000000..2b6f3bd --- /dev/null +++ b/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; + } +} diff --git a/build/cool/virtual.ts b/build/cool/virtual.ts new file mode 100644 index 0000000..7d059b1 --- /dev/null +++ b/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)} + `; + } + } + }; +}