@tianyio/quality-helper
Version:
统一项目规范的工具包
212 lines (211 loc) • 6.45 kB
JavaScript
import { join as c, dirname as $ } from "path";
import o, { readFile as y, writeFile as j } from "fs/promises";
import { execFile as b, execSync as D } from "child_process";
import { fileURLToPath as x } from "url";
function k(e, r) {
const t = JSON.parse(e), i = JSON.parse(r), s = { ...i };
for (const n in t)
n in i ? typeof t[n] == "object" && !Array.isArray(t[n]) ? s[n] = k(t[n], i[n]) : t[n] !== i[n] && (s[n] = t[n], s[`${n}_bak`] = i[n]) : s[n] = t[n];
return s;
}
function v(e) {
return e.split(`
`).reduce((r, t) => {
if (t.trim().startsWith("#"))
return r[t] = "", r;
const [i, s] = t.split("=").map((n) => n.trim());
return i && s && (r[i] = s), r;
}, {});
}
function P(e, r) {
const t = v(e), i = v(r), s = { ...i };
for (const n in t)
s[n] = t[n], n in i && t[n] !== i[n] && (s[`#${n}_bak`] = i[n]);
return Object.entries(s).map(([n, a]) => n.startsWith("#") && !n.endsWith("_bak") ? n : `${n}=${a}`).join(`
`);
}
async function h(e, r, t) {
const i = c(e, t), s = c(r, t);
if (!await o.stat(s).catch(() => !1)) {
await o.copyFile(i, s), console.log(`✅ 创建新文件: ${s}`);
return;
}
try {
const [n, a] = await Promise.all([
o.readFile(i, "utf8"),
o.readFile(s, "utf8")
]);
let l = "";
t.endsWith(".json") ? (await k(n, a), l = JSON.stringify(l, null, 2)) : t.match(/\.(ts|js)$/) ? await o.copyFile(i, s) : l = P(n, a), await o.writeFile(s, l, "utf8"), console.log(`🔄 配置已更新: ${s}`);
} catch (n) {
await o.copyFile(i, s), console.warn(`⚠️ ${s} 合并失败,已覆盖`), console.warn(`⚠️ 失败原因:${n.message}`);
}
}
async function N(e, r) {
const t = c(e, "env"), i = c(r, "env");
try {
await o.mkdir(i, { recursive: !0 });
} catch (a) {
console.warn(`⚠️ 创建 env 文件夹失败: ${a.message}`);
}
const s = await o.readdir(t), n = [];
for (const a of s) {
h(t, i, a);
const l = a.replace(/^\.env./, "");
n.push(l);
}
return n;
}
const O = {
eslint: "9.29.0",
"eslint-config-prettier": "10.1.5",
"eslint-plugin-prettier": "5.5.0",
"eslint-plugin-promise": "7.2.1",
"eslint-plugin-vue": "10.2.0",
prettier: "3.5.3",
husky: "9.1.7",
"lint-staged": "16.1.2",
"@commitlint/cli": "19.8.1",
"@commitlint/config-conventional": "19.8.1",
"@typescript-eslint/eslint-plugin": "8.34.1",
"@typescript-eslint/parser": "8.34.1"
};
function E(e) {
const r = {};
return e?.forEach((t) => {
r[`build:${t}`] = `vite build --mode ${t}`;
}), r;
}
async function J(e, r) {
const t = c(e, "package.json");
let i = {};
try {
await o.stat(t).catch(() => !1) && (i = JSON.parse(await o.readFile(t, "utf8")));
} catch (s) {
console.warn(`⚠️ 读取 package.json 失败: ${s.message}`);
}
i.devDependencies = {
...i.devDependencies,
...O
}, i.scripts = {
...i.scripts,
...E(r)
};
try {
await o.writeFile(t, JSON.stringify(i, null, 2), "utf8"), console.log("✅ package.json 已更新,请手动安装依赖");
} catch (s) {
console.error(`❌ package.json 写入失败: ${s.message}`), process.exit(1);
}
}
async function T(e, r) {
const t = c(e, "config"), i = await o.readdir(t);
for (const s of i)
await h(t, r, s);
}
function S(e, r) {
return new Promise((t, i) => {
b(e, r, (s, n, a) => {
if (s)
return i(s);
a && console.warn(a), t(n);
});
});
}
async function A(e) {
try {
await o.stat(c(e, ".git")).catch(() => (console.log("📦 初始化 Git 仓库..."), S("git", ["init", "--initial-branch=master"])));
} catch (r) {
console.warn(`⚠️ Git 初始化失败: ${r.message}`);
}
}
async function C(e, r) {
await A(r);
try {
console.log("🔧 初始化 Git Hooks...");
const t = c(r, ".husky");
if (!await o.stat(t).catch(() => !1))
try {
await S("npx", ["husky"]);
} catch {
await o.mkdir(t, { recursive: !0 });
}
const i = c(e, ".husky"), s = await o.readdir(i);
for (const n of s)
h(i, t, n);
} catch (t) {
console.error("❌ Git Hooks 初始化失败:", t.message), process.exit(1);
}
}
const g = c($(x(import.meta.url)), "..", "templates"), G = async (e = process.cwd()) => {
let r = e;
for (; ; )
try {
return await o.access(c(r, "package.json")), r;
} catch {
const t = $(r);
if (t === r)
break;
r = t;
}
return e;
};
async function R() {
const e = await G();
try {
console.log("🚀 开始安装代码规范工具..."), process.version < "v22.0.0" && console.warn("⚠️ 推荐使用 Node.js v22+ 版本");
const r = await N(g, e);
await J(e, r), await T(g, e), await C(g, e), console.log("🎉 完整开发规范已就绪!");
} catch (r) {
console.error("❌ 安装失败:", r), process.exit(1);
}
}
const H = (e) => `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")} ${String(e.getHours()).padStart(2, "0")}:${String(e.getMinutes()).padStart(2, "0")}:${String(e.getSeconds()).padStart(2, "0")}.${String(e.getMilliseconds()).padStart(3, "0")}`;
function m(e) {
try {
return D(e, { stdio: "pipe" }).toString();
} catch {
return "";
}
}
function W() {
const e = H(/* @__PURE__ */ new Date()), r = m("git describe --tags --exact-match").trim(), t = m("git rev-parse --short HEAD").trim(), i = m("git rev-parse --abbrev-ref HEAD").trim();
return {
time: e,
tag: r,
hash: t,
branch: i
};
}
function U() {
return {
name: "@tianyio/version-info",
async config({ envDir: e, envPrefix: r }, { mode: t }) {
let i = {};
try {
i = W();
} catch (f) {
return console.warn("⚠️ 版本信息生成失败:", f.message), {};
}
e || (e = process.cwd()), r || (r = "VITE");
const s = `${r}_APP_VERSION`, n = `${s}='${JSON.stringify(i)}'`, a = c(e, `.env.${t}`), l = c(e, ".env");
let w = a, u = "";
try {
u = await y(a, "utf-8");
} catch {
try {
u = await y(l, "utf-8"), w = l;
} catch {
}
}
const F = u.split(/\r?\n/);
let d = !1;
const p = F.filter((f) => f.trim() !== "").map((f) => f.startsWith(s) ? (d = !0, n) : f);
return d || p.push(n), p.push(""), j(w, p.join(`
`), "utf-8");
}
};
}
export {
R as install,
U as versionInfoPlugin
};