diff --git a/README.md b/README.md index d26c0f2..d458984 100644 --- a/README.md +++ b/README.md @@ -40,13 +40,14 @@ | description | string | 插件描述(限制50字符) | "karin plugin basic" | | time | string | 发布时间 (YYYY-MM-DD HH:mm:ss) | "2025-01-19 10:00:00" | | license | object | 开源协议信息 | 见下方示例 | +| home | string | 插件主页 | https://github.com/sj817 | #### 许可证信息 (license) | 字段名 | 类型 | 描述 | 示例 | | ------ | ------ | ---------- | ----------------------------------------------------------------- | | name | string | 许可证名称 | "MIT" | -| url | string | 许可证地址 | "https://github.com/karinjs/karin-plugin-basic/blob/main/LICENSE" | +| url | string | 许可证地址 | https://github.com/karinjs/karin-plugin-basic/blob/main/LICENSE | #### 作者信息 (author) @@ -54,8 +55,8 @@ | 字段名 | 类型 | 描述 | 示例 | | ------ | ------ | -------- | -------------------------- | -| name | string | 作者名称 | "shijin" | -| home | string | 作者主页 | "https://github.com/sj817" | +| name | string | 作者名称 | shijin | +| home | string | 作者主页 | https://github.com/sj817 | #### 仓库信息 (repo) @@ -64,7 +65,34 @@ | 字段名 | 类型 | 描述 | 示例 | | ------ | ------ | ---------------------------------------------------------------- | ----------------------------------------------- | | type | string | 仓库类型 ("github" \| "gitee" \| "gitcode" \| "gitlab" \| "npm") | "github" | -| url | string | 仓库地址 | "https://github.com/karinjs/karin-plugin-basic" | +| url | string | 仓库地址 | https://github.com/karinjs/karin-plugin-basic | +| branch | string | 默认分支(npm类型为空字符串) | "main" | + +#### 主页信息 (home) + +| 字段名 | 类型 | 描述 | 示例 | +| ------ | ------ | -------- | -------------------------- | +| home | string | 主页地址 | https://github.com/sj817 | + +### 插件类型说明 + +1. **NPM 插件** (`type: "npm"`) + - 通过 npm 包方式发布的插件 + +2. **Git 插件** (`type: "git"`) + - 通过 git 仓库方式发布的插件 + +3. **App 插件** (`type: "app"`) + - 单应用插件,需要提供文件直链地址 + - 需要在配置中添加 `files` 字段,包含应用文件的直链地址 + +## 注意事项 + +- 请确保将新插件添加到 `plugins` 数组中 +- name 必须是唯一的 +- description 长度限制为 50 字符 +- 对于 App 类型插件,建议提供多个下载源以提高可用性 +- 所有仓库源都必须提供`package.json` 并且包含`name` 和 `version` 字段 ### 示例 @@ -91,7 +119,13 @@ "repo": [ { "type": "github", - "url": "https://github.com/karinjs/karin-plugin-basic" + "url": "https://github.com/karinjs/karin-plugin-basic", + "branch": "main" + }, + { + "type": "npm", + "url": "https://www.npmjs.com/package/karin-plugin-basic", + "branch": "" } ] }, @@ -113,11 +147,13 @@ "repo": [ { "type": "github", - "url": "https://github.com/username/karin-plugin-git-example" + "url": "https://github.com/username/karin-plugin-git-example", + "branch": "main" }, { "type": "gitee", - "url": "https://gitee.com/username/karin-plugin-git-example" + "url": "https://gitee.com/username/karin-plugin-git-example", + "branch": "master" } ] }, @@ -139,7 +175,8 @@ "repo": [ { "type": "github", - "url": "https://github.com/username/karin-plugin-app-example" + "url": "https://github.com/username/karin-plugin-app-example", + "branch": "main" } ], "files": [ @@ -151,25 +188,6 @@ } ``` -### 插件类型说明 - -1. **NPM 插件** (`type: "npm"`) - - 通过 npm 包方式发布的插件 - -2. **Git 插件** (`type: "git"`) - - 通过 git 仓库方式发布的插件 - -3. **App 插件** (`type: "app"`) - - 单应用插件,需要提供文件直链地址 - - 需要在配置中添加 `files` 字段,包含应用文件的直链地址 - -## 注意事项 - -- 请确保将新插件添加到 `plugins` 数组中 -- name 必须是唯一的 -- description 长度限制为 50 字符 -- 对于 App 类型插件,建议提供多个下载源以提高可用性 - ## 许可证 本仓库采用 MIT 许可证 diff --git a/plugins.json b/plugins.json index d55c9b7..3ab6081 100644 --- a/plugins.json +++ b/plugins.json @@ -4,6 +4,7 @@ "name": "karin-plugin-basic", "type": "npm", "description": "karin plugin basic", + "home": "https://github.com/karinjs/karin-plugin-basic", "license": { "name": "MIT", "url": "https://github.com/karinjs/karin-plugin-basic/blob/main/LICENSE" @@ -18,7 +19,8 @@ "repo": [ { "type": "github", - "url": "https://github.com/karinjs/karin-plugin-basic" + "url": "https://github.com/karinjs/karin-plugin-basic", + "branch": "main" } ] }, @@ -26,6 +28,7 @@ "name": "karin-plugin-kkk", "type": "npm", "description": "咕咕咕 ~", + "home": "https://github.com/ikenxuan/karin-plugin-kkk", "license": { "name": "GPL-3.0", "url": "https://github.com/ikenxuan/karin-plugin-kkk/blob/main/LICENSE" @@ -40,7 +43,8 @@ "repo": [ { "type": "github", - "url": "https://github.com/ikenxuan/karin-plugin-kkk" + "url": "https://github.com/ikenxuan/karin-plugin-kkk", + "branch": "main" } ] } diff --git a/scripts/validate.js b/scripts/validate.js index a23b684..f55a623 100644 --- a/scripts/validate.js +++ b/scripts/validate.js @@ -35,7 +35,7 @@ const isValidUrl = (url) => { * @param {object} plugin */ const validateBaseFields = (plugin) => { - const requiredFields = ['name', 'type', 'description', 'license', 'time', 'author', 'repo'] + const requiredFields = ['name', 'type', 'description', 'license', 'time', 'author', 'repo', 'home'] for (const field of requiredFields) { if (!plugin[field]) { @@ -68,6 +68,10 @@ const validateBaseFields = (plugin) => { if (!type.includes(plugin.type)) { throw new Error(`插件 ${plugin.name} 的类型 ${plugin.type} 无效`) } + + if (!isValidUrl(plugin.home)) { + throw new Error(`插件 ${plugin.name} 的主页 URL 无效`) + } } /** @@ -85,6 +89,71 @@ const validateAuthor = (plugin) => { } } +/** + * 获取仓库原始文件的URL + * @param {object} repo - 仓库信息 + * @param {string} filePath - 文件路径 + * @returns {string} 原始文件URL + */ +const getRawFileUrl = (repo) => { + const { type, url, branch } = repo + const filePath = 'package.json' + + switch (type) { + case 'github': + return url.replace('github.com', 'raw.githubusercontent.com') + `/${branch}/${filePath}` + case 'gitee': + return `${url}/raw/${branch}/${filePath}` + case 'gitlab': + return `${url}/-/raw/${branch}/${filePath}` + case 'gitcode': + return `${url}/-/raw/${branch}/${filePath}` + case 'npm': + return `https://registry.npmjs.org/${url}/latest` + default: + throw new Error(`不支持的仓库类型: ${type}`) + } +} + +/** + * 验证仓库的 package.json + * @param {object} plugin - 插件信息 + * @param {object} repo - 仓库信息 + */ +const validatePackageJson = async (plugin, repo) => { + try { + if (repo.type === 'npm') { + if (repo.branch !== '') { + throw new Error(`插件 ${plugin.name} 的 npm 仓库不应该设置 branch 字段`) + } + return // npm 类型不需要验证 package.json + } + + if (!repo.branch) { + throw new Error(`插件 ${plugin.name} 的 ${repo.type} 仓库缺少 branch 字段`) + } + + const rawUrl = getRawFileUrl(repo) + const response = await fetch(rawUrl) + + if (!response.ok) { + throw new Error(`无法访问 package.json: ${response.statusText}`) + } + + const packageJson = await response.json() + + if (!packageJson.name) { + throw new Error('package.json 缺少 name 字段') + } + + if (!packageJson.version) { + throw new Error('package.json 缺少 version 字段') + } + } catch (error) { + throw new Error(`插件 ${plugin.name} 的仓库 ${repo.url} 验证失败: ${error.message}`) + } +} + /** * 验证仓库信息 * @param {object} plugin @@ -144,6 +213,11 @@ const main = async () => { validateAuthor(plugin) validateRepo(plugin) + // 验证每个仓库的 package.json + for (const repo of plugin.repo) { + await validatePackageJson(plugin, repo) + } + if (plugin.type === 'app') { validateAppPlugin(plugin) } else if (plugin.type === 'git' || plugin.type === 'npm') { diff --git a/types.ts b/types.ts index fbc4a40..9f28b04 100644 --- a/types.ts +++ b/types.ts @@ -15,6 +15,8 @@ export interface Base { description: string /** 插件提交到仓库时间 */ time: string + /** 插件主页 */ + home: string /** 插件许可证 */ license: { /** 许可证名称 */ @@ -35,6 +37,8 @@ export interface Base { type: 'github' | 'gitee' | 'gitcode' | 'gitlab' | 'npm' /** 仓库地址 */ url: string + /** 默认分支 npm类型为空字符串 */ + branch: string }[] }