first commit

This commit is contained in:
douboer
2026-03-21 18:57:10 +08:00
commit c49aa1a5e9
570 changed files with 107167 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
import { PERMISSION_WHITELIST, type PluginPackage } from "../types/plugin";
/**
* 插件包静态校验。
*/
export function validatePluginPackage(pluginPackage: PluginPackage): PluginPackage {
const manifest = pluginPackage?.manifest;
if (!manifest) {
throw new Error("缺少 manifest");
}
const required = ["id", "name", "version", "minAppVersion", "description", "entry", "style", "permissions"];
for (const key of required) {
if (!(key in manifest)) {
throw new Error(`manifest 缺少字段: ${key}`);
}
}
if (!/^[a-z0-9][a-z0-9-]{1,62}$/.test(manifest.id)) {
throw new Error("插件 id 不符合规范");
}
if (!/^\d+\.\d+\.\d+$/.test(manifest.version)) {
throw new Error("version 必须是 SemVer例如 0.1.0");
}
if (!/^\d+\.\d+\.\d+$/.test(manifest.minAppVersion)) {
throw new Error("minAppVersion 必须是 SemVer");
}
if (manifest.entry !== "main.js" || manifest.style !== "styles.css") {
throw new Error("entry/style 目前固定为 main.js / styles.css");
}
const allowed = new Set(PERMISSION_WHITELIST);
for (const permission of manifest.permissions || []) {
if (!allowed.has(permission)) {
throw new Error(`未知权限: ${permission}`);
}
}
if (!pluginPackage.mainJs?.trim()) {
throw new Error("mainJs 不能为空");
}
if (pluginPackage.stylesCss == null) {
throw new Error("stylesCss 不能为空");
}
if (/^\s*(\*|body|html)\s*[{,]/m.test(pluginPackage.stylesCss)) {
throw new Error("styles.css 禁止全局选择器(* / body / html");
}
return pluginPackage;
}