mirror of
https://github.com/timeshiftsauce/CeruMusic.git
synced 2025-11-25 03:15:07 +08:00
fix:优化主进程代码优化
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '1.0'
|
||||
name: pr-pipeline
|
||||
displayName: PRPipeline
|
||||
stages:
|
||||
- stage:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
@@ -16,7 +16,7 @@ stages:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
|
||||
@@ -23,7 +23,7 @@ npm install node-fetch
|
||||
### 基本使用
|
||||
|
||||
```javascript
|
||||
const CeruMusicPluginHost = require('./CeruMusicPluginHost');
|
||||
const CeruMusicPluginHost = require('./CeruMusicPluginHost')
|
||||
|
||||
// 方式1: 从代码字符串创建
|
||||
const pluginCode = `
|
||||
@@ -48,26 +48,26 @@ async function musicUrl(source, musicInfo, quality) {
|
||||
}
|
||||
|
||||
module.exports = { pluginInfo, sources, musicUrl };
|
||||
`;
|
||||
`
|
||||
|
||||
const host = new CeruMusicPluginHost(pluginCode);
|
||||
const host = new CeruMusicPluginHost(pluginCode)
|
||||
|
||||
// 方式2: 从文件加载
|
||||
const host2 = new CeruMusicPluginHost();
|
||||
await host2.loadPlugin('./my-plugin.js');
|
||||
const host2 = new CeruMusicPluginHost()
|
||||
await host2.loadPlugin('./my-plugin.js')
|
||||
```
|
||||
|
||||
### 获取插件信息
|
||||
|
||||
```javascript
|
||||
// 获取插件基本信息
|
||||
const info = host.getPluginInfo();
|
||||
console.log(info);
|
||||
const info = host.getPluginInfo()
|
||||
console.log(info)
|
||||
// 输出: { name: "示例插件", version: "1.0.0", ... }
|
||||
|
||||
// 获取支持的音源
|
||||
const sources = host.getSupportedSources();
|
||||
console.log(sources);
|
||||
const sources = host.getSupportedSources()
|
||||
console.log(sources)
|
||||
// 输出: { demo: { name: "示例音源", type: "music", ... } }
|
||||
```
|
||||
|
||||
@@ -77,31 +77,31 @@ console.log(sources);
|
||||
// 获取音乐URL
|
||||
try {
|
||||
const musicInfo = {
|
||||
songmid: "123456",
|
||||
hash: "abcdef",
|
||||
title: "歌曲名"
|
||||
};
|
||||
|
||||
const url = await host.getMusicUrl("demo", musicInfo, "320k");
|
||||
console.log("音乐URL:", url);
|
||||
songmid: '123456',
|
||||
hash: 'abcdef',
|
||||
title: '歌曲名'
|
||||
}
|
||||
|
||||
const url = await host.getMusicUrl('demo', musicInfo, '320k')
|
||||
console.log('音乐URL:', url)
|
||||
} catch (error) {
|
||||
console.error("获取失败:", error.message);
|
||||
console.error('获取失败:', error.message)
|
||||
}
|
||||
|
||||
// 获取歌曲封面(如果插件支持)
|
||||
try {
|
||||
const picUrl = await host.getPic("demo", musicInfo);
|
||||
console.log("封面URL:", picUrl);
|
||||
const picUrl = await host.getPic('demo', musicInfo)
|
||||
console.log('封面URL:', picUrl)
|
||||
} catch (error) {
|
||||
console.error("获取封面失败:", error.message);
|
||||
console.error('获取封面失败:', error.message)
|
||||
}
|
||||
|
||||
// 获取歌词(如果插件支持)
|
||||
try {
|
||||
const lyric = await host.getLyric("demo", musicInfo);
|
||||
console.log("歌词:", lyric);
|
||||
const lyric = await host.getLyric('demo', musicInfo)
|
||||
console.log('歌词:', lyric)
|
||||
} catch (error) {
|
||||
console.error("获取歌词失败:", error.message);
|
||||
console.error('获取歌词失败:', error.message)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -114,6 +114,7 @@ new CeruMusicPluginHost(pluginCode?)
|
||||
```
|
||||
|
||||
**参数:**
|
||||
|
||||
- `pluginCode` (string, 可选): 插件的 JavaScript 代码字符串
|
||||
|
||||
### 方法
|
||||
@@ -123,6 +124,7 @@ new CeruMusicPluginHost(pluginCode?)
|
||||
从文件加载插件。
|
||||
|
||||
**参数:**
|
||||
|
||||
- `pluginPath` (string): 插件文件路径
|
||||
|
||||
**返回:** Promise<Object> - 插件导出的对象
|
||||
@@ -144,6 +146,7 @@ new CeruMusicPluginHost(pluginCode?)
|
||||
获取音乐播放链接。
|
||||
|
||||
**参数:**
|
||||
|
||||
- `source` (string): 音源标识
|
||||
- `musicInfo` (Object): 歌曲信息对象
|
||||
- `quality` (string): 音质标识
|
||||
@@ -155,6 +158,7 @@ new CeruMusicPluginHost(pluginCode?)
|
||||
获取歌曲封面链接。
|
||||
|
||||
**参数:**
|
||||
|
||||
- `source` (string): 音源标识
|
||||
- `musicInfo` (Object): 歌曲信息对象
|
||||
|
||||
@@ -165,6 +169,7 @@ new CeruMusicPluginHost(pluginCode?)
|
||||
获取歌曲歌词。
|
||||
|
||||
**参数:**
|
||||
|
||||
- `source` (string): 音源标识
|
||||
- `musicInfo` (Object): 歌曲信息对象
|
||||
|
||||
@@ -178,19 +183,19 @@ new CeruMusicPluginHost(pluginCode?)
|
||||
|
||||
```javascript
|
||||
// CeruMusic API
|
||||
cerumusic.env // 运行环境标识
|
||||
cerumusic.version // 版本号
|
||||
cerumusic.request // HTTP 请求函数
|
||||
cerumusic.utils // 工具函数集合
|
||||
cerumusic.env // 运行环境标识
|
||||
cerumusic.version // 版本号
|
||||
cerumusic.request // HTTP 请求函数
|
||||
cerumusic.utils // 工具函数集合
|
||||
|
||||
// 标准 JavaScript 对象
|
||||
console // 控制台输出
|
||||
setTimeout // 定时器
|
||||
console // 控制台输出
|
||||
setTimeout // 定时器
|
||||
clearTimeout
|
||||
setInterval
|
||||
clearInterval
|
||||
Buffer // Node.js Buffer
|
||||
JSON // JSON 处理
|
||||
Buffer // Node.js Buffer
|
||||
JSON // JSON 处理
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
@@ -201,16 +206,16 @@ JSON // JSON 处理
|
||||
// 支持 callback 模式
|
||||
cerumusic.request(url, options, (error, response) => {
|
||||
if (error) {
|
||||
console.error('请求失败:', error);
|
||||
return;
|
||||
console.error('请求失败:', error)
|
||||
return
|
||||
}
|
||||
|
||||
console.log('响应状态:', response.statusCode);
|
||||
console.log('响应内容:', response.body);
|
||||
});
|
||||
|
||||
console.log('响应状态:', response.statusCode)
|
||||
console.log('响应内容:', response.body)
|
||||
})
|
||||
|
||||
// 也支持 Promise 模式
|
||||
const response = await cerumusic.request(url, options);
|
||||
const response = await cerumusic.request(url, options)
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
@@ -218,20 +223,22 @@ const response = await cerumusic.request(url, options);
|
||||
### 常见错误类型
|
||||
|
||||
1. **插件加载错误**
|
||||
|
||||
```javascript
|
||||
try {
|
||||
const host = new CeruMusicPluginHost(invalidCode);
|
||||
const host = new CeruMusicPluginHost(invalidCode)
|
||||
} catch (error) {
|
||||
console.error('插件加载失败:', error.message);
|
||||
console.error('插件加载失败:', error.message)
|
||||
}
|
||||
```
|
||||
|
||||
2. **方法调用错误**
|
||||
|
||||
```javascript
|
||||
try {
|
||||
const url = await host.getMusicUrl("invalid_source", {}, "320k");
|
||||
const url = await host.getMusicUrl('invalid_source', {}, '320k')
|
||||
} catch (error) {
|
||||
console.error('方法调用失败:', error.message);
|
||||
console.error('方法调用失败:', error.message)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -249,6 +256,7 @@ const response = await cerumusic.request(url, options);
|
||||
## 示例项目
|
||||
|
||||
查看项目中的示例文件:
|
||||
|
||||
- `example-plugin.js` - 标准插件示例
|
||||
- `test-converted-plugin.js` - 插件测试示例
|
||||
|
||||
@@ -270,4 +278,4 @@ A: 检查插件内部是否有死循环或长时间阻塞的操作
|
||||
|
||||
## 版本历史
|
||||
|
||||
- v1.0.0: 初始版本,支持基本的插件加载和执行功能
|
||||
- v1.0.0: 初始版本,支持基本的插件加载和执行功能
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
pluginInfo, // 插件信息
|
||||
sources, // 支持的音源
|
||||
musicUrl // 获取音乐链接的函数
|
||||
};
|
||||
pluginInfo, // 插件信息
|
||||
sources, // 支持的音源
|
||||
musicUrl // 获取音乐链接的函数
|
||||
}
|
||||
```
|
||||
|
||||
# 完整示例
|
||||
@@ -32,70 +32,70 @@ const pluginInfo = {
|
||||
name: '示例音源插件',
|
||||
version: '1.0.0',
|
||||
author: '开发者名称',
|
||||
description: '这是一个示例音乐源插件',
|
||||
};
|
||||
description: '这是一个示例音乐源插件'
|
||||
}
|
||||
|
||||
// 2. 支持的音源配置
|
||||
const sources = {
|
||||
demo: {
|
||||
name: '示例音源',
|
||||
type: 'music',
|
||||
qualitys: ['128k', '320k', 'flac'],
|
||||
qualitys: ['128k', '320k', 'flac']
|
||||
},
|
||||
demo2: {
|
||||
name: '示例音源2',
|
||||
type: 'music',
|
||||
qualitys: ['128k', '320k'],
|
||||
type: 'music',
|
||||
qualitys: ['128k', '320k']
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 3. 获取音乐URL的核心函数
|
||||
async function musicUrl(source, musicInfo, quality) {
|
||||
// 从 cerumusic 对象获取 API
|
||||
const { request, env, version } = cerumusic;
|
||||
|
||||
const { request, env, version } = cerumusic
|
||||
|
||||
// 构建请求参数
|
||||
const songId = musicInfo.hash ?? musicInfo.songmid;
|
||||
const apiUrl = `https://api.example.com/music/${source}/${songId}/${quality}`;
|
||||
|
||||
console.log(`[${pluginInfo.name}] 请求音乐链接: ${apiUrl}`);
|
||||
|
||||
const songId = musicInfo.hash ?? musicInfo.songmid
|
||||
const apiUrl = `https://api.example.com/music/${source}/${songId}/${quality}`
|
||||
|
||||
console.log(`[${pluginInfo.name}] 请求音乐链接: ${apiUrl}`)
|
||||
|
||||
// 发起网络请求
|
||||
const { body, statusCode } = await request(apiUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': `cerumusic-${env}/${version}`,
|
||||
},
|
||||
});
|
||||
|
||||
'User-Agent': `cerumusic-${env}/${version}`
|
||||
}
|
||||
})
|
||||
|
||||
// 处理响应
|
||||
if (statusCode !== 200 || body.code !== 200) {
|
||||
const errorMessage = body.msg || `接口错误 (HTTP: ${statusCode})`;
|
||||
console.error(`[${pluginInfo.name}] Error: ${errorMessage}`);
|
||||
throw new Error(errorMessage);
|
||||
const errorMessage = body.msg || `接口错误 (HTTP: ${statusCode})`
|
||||
console.error(`[${pluginInfo.name}] Error: ${errorMessage}`)
|
||||
throw new Error(errorMessage)
|
||||
}
|
||||
|
||||
console.log(`[${pluginInfo.name}] 获取成功: ${body.url}`);
|
||||
return body.url;
|
||||
|
||||
console.log(`[${pluginInfo.name}] 获取成功: ${body.url}`)
|
||||
return body.url
|
||||
}
|
||||
|
||||
// 4. 可选:获取封面图片
|
||||
async function getPic(source, musicInfo) {
|
||||
const { request } = cerumusic;
|
||||
const songId = musicInfo.hash ?? musicInfo.songmid;
|
||||
|
||||
const { body } = await request(`https://api.example.com/pic/${source}/${songId}`);
|
||||
return body.picUrl;
|
||||
const { request } = cerumusic
|
||||
const songId = musicInfo.hash ?? musicInfo.songmid
|
||||
|
||||
const { body } = await request(`https://api.example.com/pic/${source}/${songId}`)
|
||||
return body.picUrl
|
||||
}
|
||||
|
||||
// 5. 可选:获取歌词
|
||||
async function getLyric(source, musicInfo) {
|
||||
const { request } = cerumusic;
|
||||
const songId = musicInfo.hash ?? musicInfo.songmid;
|
||||
|
||||
const { body } = await request(`https://api.example.com/lyric/${source}/${songId}`);
|
||||
return body.lyric;
|
||||
const { request } = cerumusic
|
||||
const songId = musicInfo.hash ?? musicInfo.songmid
|
||||
|
||||
const { body } = await request(`https://api.example.com/lyric/${source}/${songId}`)
|
||||
return body.lyric
|
||||
}
|
||||
|
||||
// 导出插件
|
||||
@@ -103,9 +103,9 @@ module.exports = {
|
||||
pluginInfo,
|
||||
sources,
|
||||
musicUrl,
|
||||
getPic, // 可选
|
||||
getLyric, // 可选
|
||||
};
|
||||
getPic, // 可选
|
||||
getLyric // 可选
|
||||
}
|
||||
```
|
||||
|
||||
## 详细说明
|
||||
@@ -116,11 +116,11 @@ module.exports = {
|
||||
|
||||
```javascript
|
||||
const pluginInfo = {
|
||||
name: '插件名称', // 必需:插件显示名称
|
||||
version: '1.0.0', // 必需:版本号
|
||||
author: '作者名', // 必需:作者信息
|
||||
description: '插件描述', // 必需:功能描述
|
||||
};
|
||||
name: '插件名称', // 必需:插件显示名称
|
||||
version: '1.0.0', // 必需:版本号
|
||||
author: '作者名', // 必需:作者信息
|
||||
description: '插件描述' // 必需:功能描述
|
||||
}
|
||||
```
|
||||
|
||||
### 2. sources 对象
|
||||
@@ -130,18 +130,19 @@ const pluginInfo = {
|
||||
```javascript
|
||||
const sources = {
|
||||
// 音源标识(用于API调用)
|
||||
'source_id': {
|
||||
name: '音源显示名称', // 必需:用户看到的名称
|
||||
type: 'music', // 必需:固定为 'music'
|
||||
qualitys: [ // 必需:支持的音质列表
|
||||
'128k', // 标准音质
|
||||
'320k', // 高音质
|
||||
'flac', // 无损音质
|
||||
'flac24bit', // 24位无损
|
||||
'hires' // 高解析度
|
||||
],
|
||||
source_id: {
|
||||
name: '音源显示名称', // 必需:用户看到的名称
|
||||
type: 'music', // 必需:固定为 'music'
|
||||
qualitys: [
|
||||
// 必需:支持的音质列表
|
||||
'128k', // 标准音质
|
||||
'320k', // 高音质
|
||||
'flac', // 无损音质
|
||||
'flac24bit', // 24位无损
|
||||
'hires' // 高解析度
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 3. musicUrl 函数
|
||||
@@ -153,7 +154,6 @@ async function musicUrl(source, musicInfo, quality) {
|
||||
// source: 音源标识(sources 对象的键)
|
||||
// musicInfo: 歌曲信息对象
|
||||
// quality: 请求的音质
|
||||
|
||||
// 返回: Promise<string> - 音乐播放链接
|
||||
}
|
||||
```
|
||||
@@ -162,13 +162,13 @@ async function musicUrl(source, musicInfo, quality) {
|
||||
|
||||
```javascript
|
||||
const musicInfo = {
|
||||
songmid: '歌曲ID', // 歌曲标识符
|
||||
hash: '歌曲哈希', // 备用标识符
|
||||
title: '歌曲标题', // 歌曲名称
|
||||
artist: '艺术家', // 演唱者
|
||||
album: '专辑名', // 专辑信息
|
||||
songmid: '歌曲ID', // 歌曲标识符
|
||||
hash: '歌曲哈希', // 备用标识符
|
||||
title: '歌曲标题', // 歌曲名称
|
||||
artist: '艺术家', // 演唱者
|
||||
album: '专辑名' // 专辑信息
|
||||
// ... 其他可能的字段
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 可用 API
|
||||
@@ -178,7 +178,7 @@ const musicInfo = {
|
||||
插件运行时可以访问 `cerumusic` 全局对象:
|
||||
|
||||
```javascript
|
||||
const { request, env, version, utils } = cerumusic;
|
||||
const { request, env, version, utils } = cerumusic
|
||||
```
|
||||
|
||||
#### request 函数
|
||||
@@ -187,19 +187,20 @@ const { request, env, version, utils } = cerumusic;
|
||||
|
||||
```javascript
|
||||
// Promise 模式
|
||||
const response = await request(url, options);
|
||||
const response = await request(url, options)
|
||||
|
||||
// Callback 模式
|
||||
// Callback 模式
|
||||
request(url, options, (error, response) => {
|
||||
if (error) {
|
||||
console.error('请求失败:', error);
|
||||
return;
|
||||
console.error('请求失败:', error)
|
||||
return
|
||||
}
|
||||
console.log('响应:', response);
|
||||
});
|
||||
console.log('响应:', response)
|
||||
})
|
||||
```
|
||||
|
||||
**参数说明:**
|
||||
|
||||
- `url` (string): 请求地址
|
||||
- `options` (Object): 请求选项
|
||||
- `method`: HTTP 方法 ('GET', 'POST', 等)
|
||||
@@ -207,6 +208,7 @@ request(url, options, (error, response) => {
|
||||
- `body`: 请求体(POST 请求时)
|
||||
|
||||
**响应格式:**
|
||||
|
||||
```javascript
|
||||
{
|
||||
body: {}, // 解析后的响应体
|
||||
@@ -220,11 +222,11 @@ request(url, options, (error, response) => {
|
||||
提供实用工具函数:
|
||||
|
||||
```javascript
|
||||
const { utils } = cerumusic;
|
||||
const { utils } = cerumusic
|
||||
|
||||
// Buffer 操作
|
||||
const buffer = utils.buffer.from('hello', 'utf8');
|
||||
const string = utils.buffer.bufToString(buffer, 'utf8');
|
||||
const buffer = utils.buffer.from('hello', 'utf8')
|
||||
const string = utils.buffer.bufToString(buffer, 'utf8')
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
@@ -232,26 +234,28 @@ const string = utils.buffer.bufToString(buffer, 'utf8');
|
||||
### 最佳实践
|
||||
|
||||
1. **总是检查 API 响应状态**
|
||||
|
||||
```javascript
|
||||
if (statusCode !== 200 || body.code !== 200) {
|
||||
throw new Error(`请求失败: ${body.msg || '未知错误'}`);
|
||||
throw new Error(`请求失败: ${body.msg || '未知错误'}`)
|
||||
}
|
||||
```
|
||||
|
||||
2. **提供有意义的错误信息**
|
||||
|
||||
```javascript
|
||||
console.error(`[${pluginInfo.name}] Error: ${errorMessage}`);
|
||||
throw new Error(errorMessage);
|
||||
console.error(`[${pluginInfo.name}] Error: ${errorMessage}`)
|
||||
throw new Error(errorMessage)
|
||||
```
|
||||
|
||||
3. **处理网络异常**
|
||||
```javascript
|
||||
try {
|
||||
const response = await request(url, options);
|
||||
const response = await request(url, options)
|
||||
// 处理响应
|
||||
} catch (error) {
|
||||
console.error(`[${pluginInfo.name}] 网络请求失败:`, error.message);
|
||||
throw new Error(`网络错误: ${error.message}`);
|
||||
console.error(`[${pluginInfo.name}] 网络请求失败:`, error.message)
|
||||
throw new Error(`网络错误: ${error.message}`)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -279,17 +283,17 @@ node converter-event-driven.js input-plugin.js output-plugin.js
|
||||
### 1. 使用 console.log
|
||||
|
||||
```javascript
|
||||
console.log(`[${pluginInfo.name}] 调试信息:`, data);
|
||||
console.error(`[${pluginInfo.name}] 错误:`, error);
|
||||
console.log(`[${pluginInfo.name}] 调试信息:`, data)
|
||||
console.error(`[${pluginInfo.name}] 错误:`, error)
|
||||
```
|
||||
|
||||
### 2. 检查请求和响应
|
||||
|
||||
```javascript
|
||||
console.log('请求URL:', url);
|
||||
console.log('请求选项:', options);
|
||||
console.log('响应状态:', statusCode);
|
||||
console.log('响应内容:', body);
|
||||
console.log('请求URL:', url)
|
||||
console.log('请求选项:', options)
|
||||
console.log('响应状态:', statusCode)
|
||||
console.log('响应内容:', body)
|
||||
```
|
||||
|
||||
### 3. 测试插件
|
||||
@@ -297,26 +301,26 @@ console.log('响应内容:', body);
|
||||
创建测试文件:
|
||||
|
||||
```javascript
|
||||
const CeruMusicPluginHost = require('./CeruMusicPluginHost');
|
||||
const CeruMusicPluginHost = require('./CeruMusicPluginHost')
|
||||
|
||||
async function testPlugin() {
|
||||
const host = new CeruMusicPluginHost();
|
||||
await host.loadPlugin('./my-plugin.js');
|
||||
|
||||
const host = new CeruMusicPluginHost()
|
||||
await host.loadPlugin('./my-plugin.js')
|
||||
|
||||
const musicInfo = {
|
||||
songmid: 'test123',
|
||||
title: '测试歌曲'
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
const url = await host.getMusicUrl('demo', musicInfo, '320k');
|
||||
console.log('成功获取URL:', url);
|
||||
const url = await host.getMusicUrl('demo', musicInfo, '320k')
|
||||
console.log('成功获取URL:', url)
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error.message);
|
||||
console.error('测试失败:', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
testPlugin();
|
||||
testPlugin()
|
||||
```
|
||||
|
||||
## 发布和分发
|
||||
@@ -334,6 +338,7 @@ my-plugin/
|
||||
### 版本管理
|
||||
|
||||
遵循语义化版本规范:
|
||||
|
||||
- `1.0.0` - 主版本.次版本.修订版本
|
||||
- 主版本:不兼容的 API 修改
|
||||
- 次版本:向下兼容的功能性新增
|
||||
@@ -342,6 +347,7 @@ my-plugin/
|
||||
## 示例插件
|
||||
|
||||
查看项目中的示例:
|
||||
|
||||
- `example-plugin.js` - 基础插件示例
|
||||
- `plugin.js` - 事件驱动插件示例
|
||||
- `fm.js` - 复杂插件示例
|
||||
@@ -372,4 +378,4 @@ A: 减少不必要的网络请求,使用适当的缓存策略,避免阻塞
|
||||
4. 提交 Pull Request
|
||||
5. 等待代码审查
|
||||
|
||||
欢迎贡献新的音源插件!
|
||||
欢迎贡献新的音源插件!
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -50,7 +50,7 @@
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/node": "^22.16.5",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"electron": "^37.2.3",
|
||||
"electron": "^37.3.1",
|
||||
"electron-builder": "^25.1.8",
|
||||
"electron-icon-builder": "^2.0.1",
|
||||
"electron-vite": "^4.0.0",
|
||||
@@ -7497,9 +7497,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "37.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/electron/-/electron-37.3.0.tgz",
|
||||
"integrity": "sha512-cPOPUD26DwCh+PZ9q+gMyVBvdBN75SnekI6u5zcOeoLVIXQpzrCm1ewz9BcrkWkVW7oOtfQAEo1G1SffvXrSSw==",
|
||||
"version": "37.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/electron/-/electron-37.3.1.tgz",
|
||||
"integrity": "sha512-7DhktRLqhe6OJh/Bo75bTI0puUYEmIwSzMinocgO63mx3MVjtIn2tYMzLmAleNIlud2htkjpsMG2zT4PiTCloA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/node": "^22.16.5",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"electron": "^37.2.3",
|
||||
"electron": "^37.3.1",
|
||||
"electron-builder": "^25.1.8",
|
||||
"electron-icon-builder": "^2.0.1",
|
||||
"electron-vite": "^4.0.0",
|
||||
|
||||
1641
pnpm-lock.yaml
generated
1641
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
71
src/main/events/ai.ts
Normal file
71
src/main/events/ai.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { AIService } from '../services/ai-service'
|
||||
import { ipcMain } from 'electron'
|
||||
// 创建AI服务实例
|
||||
export default function aiEvents(mainWindow) {
|
||||
const aiService = new AIService()
|
||||
|
||||
// 注册AI服务的IPC处理器
|
||||
ipcMain.handle('ai-ask', async (_, prompt) => {
|
||||
try {
|
||||
return await aiService.askChat(prompt)
|
||||
} catch (error: any) {
|
||||
console.error('AI对话失败:', error)
|
||||
// 返回错误信息给渲染进程
|
||||
throw {
|
||||
message: (error as Error).message || 'AI服务暂时不可用',
|
||||
code: 'AI_SERVICE_ERROR'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 注册AI流式服务的IPC处理器
|
||||
ipcMain.handle('ai-ask-stream', async (event, prompt, streamId) => {
|
||||
try {
|
||||
const stream = aiService.askChatStream(prompt)
|
||||
|
||||
for await (const chunk of stream) {
|
||||
// 发送流式数据块到渲染进程
|
||||
event.sender.send('ai-stream-chunk', { streamId, chunk })
|
||||
}
|
||||
|
||||
// 发送流结束信号
|
||||
event.sender.send('ai-stream-end', { streamId })
|
||||
return { success: true }
|
||||
} catch (error: any) {
|
||||
console.error('AI流式对话失败:', error)
|
||||
// 发送错误信号,包含更详细的错误信息
|
||||
const errorMessage = (error as Error).message || 'AI服务暂时不可用'
|
||||
event.sender.send('ai-stream-error', {
|
||||
streamId,
|
||||
error: errorMessage,
|
||||
code: 'AI_SERVICE_ERROR'
|
||||
})
|
||||
throw {
|
||||
message: errorMessage,
|
||||
code: 'AI_SERVICE_ERROR'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 注册获取用户配置的IPC处理器
|
||||
ipcMain.handle('get-user-config', async () => {
|
||||
try {
|
||||
// 从渲染进程的localStorage获取用户配置
|
||||
const result = await mainWindow?.webContents.executeJavaScript(`
|
||||
(() => {
|
||||
try {
|
||||
const userInfo = localStorage.getItem('userInfo');
|
||||
return userInfo ? JSON.parse(userInfo) : null;
|
||||
} catch (error) {
|
||||
console.error('获取用户配置失败:', error);
|
||||
return null;
|
||||
}
|
||||
})()
|
||||
`)
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('获取用户配置失败:', error)
|
||||
return null
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,64 +1,19 @@
|
||||
import { app, shell, BrowserWindow, ipcMain, Tray, Menu } from 'electron'
|
||||
import { app, shell, BrowserWindow, ipcMain, Tray } from 'electron'
|
||||
import { is } from '@electron-toolkit/utils'
|
||||
import { join } from 'path'
|
||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||
|
||||
import icon from '../../resources/logo.png?asset'
|
||||
import path from 'node:path'
|
||||
import musicService from './services/music'
|
||||
import pluginService from './services/plugin'
|
||||
import { AIService } from './services/ai-service'
|
||||
import useWindow from './window/index'
|
||||
|
||||
import aiEvents from './events/ai'
|
||||
|
||||
let tray: Tray | null = null
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
let isQuitting = false
|
||||
|
||||
function createTray(): void {
|
||||
// 创建系统托盘
|
||||
const trayIconPath = path.join(__dirname, '../../resources/logo.png')
|
||||
tray = new Tray(trayIconPath)
|
||||
|
||||
// 创建托盘菜单
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: '显示窗口',
|
||||
click: () => {
|
||||
if (mainWindow) {
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '播放/暂停',
|
||||
click: () => {
|
||||
// 这里可以添加播放控制逻辑
|
||||
mainWindow?.webContents.send('music-control')
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '退出',
|
||||
click: () => {
|
||||
isQuitting = true
|
||||
app.quit()
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
tray.setContextMenu(contextMenu)
|
||||
tray.setToolTip('Ceru Music')
|
||||
|
||||
// 双击托盘图标显示窗口
|
||||
tray.on('click', () => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isVisible()) {
|
||||
mainWindow.hide()
|
||||
} else {
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 使用对象包装布尔值,以便通过引用传递
|
||||
const isQuittingState = { value: false }
|
||||
const tray: { value: Tray | null } = { value: null }
|
||||
|
||||
function createWindow(): void {
|
||||
// Create the browser window.
|
||||
@@ -92,13 +47,13 @@ function createWindow(): void {
|
||||
|
||||
// 阻止窗口关闭,改为隐藏到系统托盘
|
||||
mainWindow.on('close', (event) => {
|
||||
if (!isQuitting) {
|
||||
if (!isQuittingState.value) {
|
||||
event.preventDefault()
|
||||
mainWindow?.hide()
|
||||
|
||||
// 显示托盘通知
|
||||
if (tray) {
|
||||
tray.displayBalloon({
|
||||
if (tray.value) {
|
||||
tray.value.displayBalloon({
|
||||
iconType: 'info',
|
||||
title: 'Ceru Music',
|
||||
content: '已最小化到系统托盘啦,点击托盘图标可重新打开~'
|
||||
@@ -138,166 +93,17 @@ ipcMain.handle('service-music-request', async (_, api, args) => {
|
||||
return await musicService.request(api, args)
|
||||
})
|
||||
|
||||
// 创建AI服务实例
|
||||
const aiService = new AIService()
|
||||
|
||||
// 注册AI服务的IPC处理器
|
||||
ipcMain.handle('ai-ask', async (_, prompt) => {
|
||||
try {
|
||||
return await aiService.askChat(prompt)
|
||||
} catch (error: any) {
|
||||
console.error('AI对话失败:', error)
|
||||
// 返回错误信息给渲染进程
|
||||
throw {
|
||||
message: (error as Error).message || 'AI服务暂时不可用',
|
||||
code: 'AI_SERVICE_ERROR'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 注册AI流式服务的IPC处理器
|
||||
ipcMain.handle('ai-ask-stream', async (event, prompt, streamId) => {
|
||||
try {
|
||||
const stream = aiService.askChatStream(prompt)
|
||||
|
||||
for await (const chunk of stream) {
|
||||
// 发送流式数据块到渲染进程
|
||||
event.sender.send('ai-stream-chunk', { streamId, chunk })
|
||||
}
|
||||
|
||||
// 发送流结束信号
|
||||
event.sender.send('ai-stream-end', { streamId })
|
||||
return { success: true }
|
||||
} catch (error: any) {
|
||||
console.error('AI流式对话失败:', error)
|
||||
// 发送错误信号,包含更详细的错误信息
|
||||
const errorMessage = (error as Error).message || 'AI服务暂时不可用'
|
||||
event.sender.send('ai-stream-error', {
|
||||
streamId,
|
||||
error: errorMessage,
|
||||
code: 'AI_SERVICE_ERROR'
|
||||
})
|
||||
throw {
|
||||
message: errorMessage,
|
||||
code: 'AI_SERVICE_ERROR'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 注册获取用户配置的IPC处理器
|
||||
ipcMain.handle('get-user-config', async () => {
|
||||
try {
|
||||
// 从渲染进程的localStorage获取用户配置
|
||||
const result = await mainWindow?.webContents.executeJavaScript(`
|
||||
(() => {
|
||||
try {
|
||||
const userInfo = localStorage.getItem('userInfo');
|
||||
return userInfo ? JSON.parse(userInfo) : null;
|
||||
} catch (error) {
|
||||
console.error('获取用户配置失败:', error);
|
||||
return null;
|
||||
}
|
||||
})()
|
||||
`)
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('获取用户配置失败:', error)
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId('com.cerulean.music')
|
||||
|
||||
// Default open or close DevTools by F12 in development
|
||||
// and ignore CommandOrControl + R in production.
|
||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
app.on('browser-window-created', (_, window) => {
|
||||
optimizer.watchWindowShortcuts(window)
|
||||
})
|
||||
|
||||
// IPC test
|
||||
ipcMain.on('ping', () => console.log('pong'))
|
||||
|
||||
// 窗口控制 IPC 处理
|
||||
ipcMain.on('window-minimize', () => {
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
if (window) {
|
||||
window.minimize()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('window-maximize', () => {
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
if (window) {
|
||||
if (window.isMaximized()) {
|
||||
window.unmaximize()
|
||||
} else {
|
||||
window.maximize()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('window-close', () => {
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
if (window) {
|
||||
window.close()
|
||||
}
|
||||
})
|
||||
|
||||
// Mini 模式 IPC 处理 - 最小化到系统托盘
|
||||
ipcMain.on('window-mini-mode', (_, isMini) => {
|
||||
if (mainWindow) {
|
||||
if (isMini) {
|
||||
// 进入 Mini 模式:隐藏窗口到系统托盘
|
||||
mainWindow.hide()
|
||||
// 显示托盘通知(可选)
|
||||
if (tray) {
|
||||
tray.displayBalloon({
|
||||
title: '澜音 Music',
|
||||
content: '已最小化到系统托盘啦,点击托盘图标可重新打开~'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 退出 Mini 模式:显示窗口
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 全屏模式 IPC 处理
|
||||
ipcMain.on('window-toggle-fullscreen', () => {
|
||||
if (mainWindow) {
|
||||
const isFullScreen = mainWindow.isFullScreen()
|
||||
mainWindow.setFullScreen(!isFullScreen)
|
||||
}
|
||||
})
|
||||
|
||||
createWindow()
|
||||
createTray()
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// 当所有窗口关闭时不退出应用,因为我们有系统托盘
|
||||
app.on('window-all-closed', () => {
|
||||
// 在 macOS 上,应用通常会保持活跃状态
|
||||
// 在其他平台上,我们也保持应用运行,因为有系统托盘
|
||||
})
|
||||
aiEvents(mainWindow)
|
||||
|
||||
// 应用退出前的清理
|
||||
app.on('before-quit', () => {
|
||||
isQuitting = true
|
||||
isQuittingState.value = true
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
// 创建窗口并注册window服务
|
||||
app.whenReady().then(() => {
|
||||
// 先创建窗口
|
||||
createWindow()
|
||||
// 然后注册window服务,确保mainWindow已经创建
|
||||
useWindow(() => {}, ipcMain, app, mainWindow, isQuittingState, tray)
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable */
|
||||
const vm = require('vm');
|
||||
const fetch = require('node-fetch');
|
||||
const vm = require('vm')
|
||||
const fetch = require('node-fetch')
|
||||
|
||||
/**
|
||||
* CeruMusic 插件引擎
|
||||
@@ -11,11 +11,11 @@ class CeruMusicPluginHost {
|
||||
* @param {string | null} pluginCode 插件的 JavaScript 代码字符串(可选)
|
||||
* @param {any} logger
|
||||
*/
|
||||
constructor(pluginCode = null, logger=console) {
|
||||
this.pluginCode = pluginCode;
|
||||
this.plugin = null; // 存储插件导出的对象
|
||||
constructor(pluginCode = null, logger = console) {
|
||||
this.pluginCode = pluginCode
|
||||
this.plugin = null // 存储插件导出的对象
|
||||
if (pluginCode) {
|
||||
this._initialize(logger);
|
||||
this._initialize(logger)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ class CeruMusicPluginHost {
|
||||
* @param {string} pluginPath 插件文件路径
|
||||
* @param {any} logger
|
||||
*/
|
||||
async loadPlugin(pluginPath, logger=console) {
|
||||
const fs = require('fs');
|
||||
this.pluginCode = fs.readFileSync(pluginPath, 'utf-8');
|
||||
this._initialize(logger);
|
||||
return this.plugin;
|
||||
async loadPlugin(pluginPath, logger = console) {
|
||||
const fs = require('fs')
|
||||
this.pluginCode = fs.readFileSync(pluginPath, 'utf-8')
|
||||
this._initialize(logger)
|
||||
return this.plugin
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,93 +43,92 @@ class CeruMusicPluginHost {
|
||||
utils: {
|
||||
buffer: {
|
||||
from: (data, encoding) => Buffer.from(data, encoding),
|
||||
bufToString: (buffer, encoding) => buffer.toString(encoding),
|
||||
},
|
||||
bufToString: (buffer, encoding) => buffer.toString(encoding)
|
||||
}
|
||||
},
|
||||
request: (url, options, callback) => {
|
||||
// 支持 Promise 和 callback 两种调用方式
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = { method: 'GET' };
|
||||
callback = options
|
||||
options = { method: 'GET' }
|
||||
}
|
||||
|
||||
const makeRequest = async () => {
|
||||
try {
|
||||
console.log(`[CeruMusic] 发起请求: ${url}`);
|
||||
console.log(`[CeruMusic] 发起请求: ${url}`)
|
||||
|
||||
// 添加超时设置
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), 10000) // 10秒超时
|
||||
|
||||
const requestOptions = {
|
||||
method: 'GET',
|
||||
...options,
|
||||
signal: controller.signal
|
||||
};
|
||||
}
|
||||
|
||||
const response = await fetch(url, requestOptions);
|
||||
clearTimeout(timeoutId);
|
||||
const response = await fetch(url, requestOptions)
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
console.log(`[CeruMusic] 请求响应状态: ${response.status}`);
|
||||
console.log(`[CeruMusic] 请求响应状态: ${response.status}`)
|
||||
|
||||
// 尝试解析JSON,如果失败则返回文本
|
||||
let body;
|
||||
const contentType = response.headers.get('content-type');
|
||||
let body
|
||||
const contentType = response.headers.get('content-type')
|
||||
|
||||
try {
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
body = await response.json();
|
||||
body = await response.json()
|
||||
} else {
|
||||
const text = await response.text();
|
||||
console.log(`[CeruMusic] 响应不是JSON格式,内容: ${text.substring(0, 200)}...`);
|
||||
const text = await response.text()
|
||||
console.log(`[CeruMusic] 响应不是JSON格式,内容: ${text.substring(0, 200)}...`)
|
||||
// 对于非JSON响应,创建一个错误状态的body
|
||||
body = {
|
||||
code: response.status,
|
||||
msg: `Expected JSON response but got: ${contentType || 'unknown content type'}`,
|
||||
data: text
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error(`[CeruMusic] 解析响应失败: ${parseError.message}`);
|
||||
console.error(`[CeruMusic] 解析响应失败: ${parseError.message}`)
|
||||
// 解析失败时创建错误body
|
||||
body = {
|
||||
code: response.status,
|
||||
msg: `Failed to parse response: ${parseError.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[CeruMusic] 请求响应内容:`, body);
|
||||
console.log(`[CeruMusic] 请求响应内容:`, body)
|
||||
|
||||
const result = {
|
||||
body,
|
||||
statusCode: response.status,
|
||||
headers: response.headers.raw(),
|
||||
};
|
||||
headers: response.headers.raw()
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(null, result);
|
||||
callback(null, result)
|
||||
}
|
||||
return result;
|
||||
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error(`[CeruMusic] Request failed: ${error.message}`);
|
||||
console.error(`[CeruMusic] Request failed: ${error.message}`)
|
||||
|
||||
if (callback) {
|
||||
// 网络错误时,调用 callback(error, null)
|
||||
callback(error, null);
|
||||
callback(error, null)
|
||||
} else {
|
||||
throw error;
|
||||
throw error
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
makeRequest().catch(() => {}); // 错误已在makeRequest中处理
|
||||
makeRequest().catch(() => {}) // 错误已在makeRequest中处理
|
||||
} else {
|
||||
return makeRequest();
|
||||
return makeRequest()
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const sandbox = {
|
||||
module: { exports: {} },
|
||||
@@ -144,21 +143,21 @@ class CeruMusicPluginHost {
|
||||
require: () => ({}),
|
||||
global: {},
|
||||
process: { env: {} }
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
// 在沙箱中执行插件代码
|
||||
vm.runInNewContext(this.pluginCode, sandbox);
|
||||
this.plugin = sandbox.module.exports;
|
||||
console.log(`[CeruMusic] Plugin "${this.plugin.pluginInfo.name}" loaded successfully.`);
|
||||
vm.runInNewContext(this.pluginCode, sandbox)
|
||||
this.plugin = sandbox.module.exports
|
||||
console.log(`[CeruMusic] Plugin "${this.plugin.pluginInfo.name}" loaded successfully.`)
|
||||
} catch (e) {
|
||||
console.error('[CeruMusic] Error executing plugin code:', e);
|
||||
throw new Error('Failed to initialize plugin.');
|
||||
console.error('[CeruMusic] Error executing plugin code:', e)
|
||||
throw new Error('Failed to initialize plugin.')
|
||||
}
|
||||
|
||||
// 验证插件结构
|
||||
if (!this.plugin.pluginInfo || !this.plugin.sources || !this.plugin.musicUrl) {
|
||||
throw new Error('Invalid plugin structure. Required fields: pluginInfo, sources, musicUrl.');
|
||||
throw new Error('Invalid plugin structure. Required fields: pluginInfo, sources, musicUrl.')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,14 +165,14 @@ class CeruMusicPluginHost {
|
||||
* 获取插件信息
|
||||
*/
|
||||
getPluginInfo() {
|
||||
return this.plugin.pluginInfo;
|
||||
return this.plugin.pluginInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支持的音源和音质信息
|
||||
*/
|
||||
getSupportedSources() {
|
||||
return this.plugin.sources;
|
||||
return this.plugin.sources
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,10 +184,10 @@ class CeruMusicPluginHost {
|
||||
async getMusicUrl(source, musicInfo, quality) {
|
||||
try {
|
||||
if (typeof this.plugin.musicUrl !== 'function') {
|
||||
throw new Error(`Action "musicUrl" is not implemented in plugin.`);
|
||||
throw new Error(`Action "musicUrl" is not implemented in plugin.`)
|
||||
}
|
||||
|
||||
console.log(`[CeruMusic] 开始调用插件的 musicUrl 方法...`);
|
||||
console.log(`[CeruMusic] 开始调用插件的 musicUrl 方法...`)
|
||||
|
||||
// 将 cerumusic API 绑定到函数调用的 this 上下文
|
||||
const result = await this.plugin.musicUrl.call(
|
||||
@@ -196,17 +195,16 @@ class CeruMusicPluginHost {
|
||||
source,
|
||||
musicInfo,
|
||||
quality
|
||||
);
|
||||
|
||||
console.log(`[CeruMusic] 插件 musicUrl 方法调用成功`);
|
||||
return result;
|
||||
)
|
||||
|
||||
console.log(`[CeruMusic] 插件 musicUrl 方法调用成功`)
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error(`[CeruMusic] getMusicUrl 方法执行失败:`, error.message);
|
||||
console.error(`[CeruMusic] 错误堆栈:`, error.stack);
|
||||
console.error(`[CeruMusic] getMusicUrl 方法执行失败:`, error.message)
|
||||
console.error(`[CeruMusic] 错误堆栈:`, error.stack)
|
||||
|
||||
// 重新抛出错误,确保外部可以捕获
|
||||
throw new Error(`Plugin getMusicUrl failed: ${error.message}`);
|
||||
throw new Error(`Plugin getMusicUrl failed: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,93 +219,92 @@ class CeruMusicPluginHost {
|
||||
utils: {
|
||||
buffer: {
|
||||
from: (data, encoding) => Buffer.from(data, encoding),
|
||||
bufToString: (buffer, encoding) => buffer.toString(encoding),
|
||||
},
|
||||
bufToString: (buffer, encoding) => buffer.toString(encoding)
|
||||
}
|
||||
},
|
||||
request: (url, options, callback) => {
|
||||
// 支持 Promise 和 callback 两种调用方式
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = { method: 'GET' };
|
||||
callback = options
|
||||
options = { method: 'GET' }
|
||||
}
|
||||
|
||||
const makeRequest = async () => {
|
||||
try {
|
||||
console.log(`[CeruMusic] 发起请求: ${url}`);
|
||||
console.log(`[CeruMusic] 发起请求: ${url}`)
|
||||
|
||||
// 添加超时设置
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), 10000) // 10秒超时
|
||||
|
||||
const requestOptions = {
|
||||
method: 'GET',
|
||||
...options,
|
||||
signal: controller.signal
|
||||
};
|
||||
}
|
||||
|
||||
const response = await fetch(url, requestOptions);
|
||||
clearTimeout(timeoutId);
|
||||
const response = await fetch(url, requestOptions)
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
console.log(`[CeruMusic] 请求响应状态: ${response.status}`);
|
||||
console.log(`[CeruMusic] 请求响应状态: ${response.status}`)
|
||||
|
||||
// 尝试解析JSON,如果失败则返回文本
|
||||
let body;
|
||||
const contentType = response.headers.get('content-type');
|
||||
let body
|
||||
const contentType = response.headers.get('content-type')
|
||||
|
||||
try {
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
body = await response.json();
|
||||
body = await response.json()
|
||||
} else {
|
||||
const text = await response.text();
|
||||
console.log(`[CeruMusic] 响应不是JSON格式,内容: ${text.substring(0, 200)}...`);
|
||||
const text = await response.text()
|
||||
console.log(`[CeruMusic] 响应不是JSON格式,内容: ${text.substring(0, 200)}...`)
|
||||
// 对于非JSON响应,创建一个错误状态的body
|
||||
body = {
|
||||
code: response.status,
|
||||
msg: `Expected JSON response but got: ${contentType || 'unknown content type'}`,
|
||||
data: text
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error(`[CeruMusic] 解析响应失败: ${parseError.message}`);
|
||||
console.error(`[CeruMusic] 解析响应失败: ${parseError.message}`)
|
||||
// 解析失败时创建错误body
|
||||
body = {
|
||||
code: response.status,
|
||||
msg: `Failed to parse response: ${parseError.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[CeruMusic] 请求响应内容:`, body);
|
||||
console.log(`[CeruMusic] 请求响应内容:`, body)
|
||||
|
||||
const result = {
|
||||
body,
|
||||
statusCode: response.status,
|
||||
headers: response.headers.raw(),
|
||||
};
|
||||
headers: response.headers.raw()
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(null, result);
|
||||
callback(null, result)
|
||||
}
|
||||
return result;
|
||||
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error(`[CeruMusic] Request failed: ${error.message}`);
|
||||
console.error(`[CeruMusic] Request failed: ${error.message}`)
|
||||
|
||||
if (callback) {
|
||||
// 网络错误时,调用 callback(error, null)
|
||||
callback(error, null);
|
||||
callback(error, null)
|
||||
} else {
|
||||
throw error;
|
||||
throw error
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
makeRequest().catch(() => {}); // 错误已在makeRequest中处理
|
||||
makeRequest().catch(() => {}) // 错误已在makeRequest中处理
|
||||
} else {
|
||||
return makeRequest();
|
||||
return makeRequest()
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,23 +315,22 @@ class CeruMusicPluginHost {
|
||||
async getPic(source, musicInfo) {
|
||||
try {
|
||||
if (typeof this.plugin.getPic !== 'function') {
|
||||
throw new Error(`Action "getPic" is not implemented in plugin.`);
|
||||
throw new Error(`Action "getPic" is not implemented in plugin.`)
|
||||
}
|
||||
|
||||
console.log(`[CeruMusic] 开始调用插件的 getPic 方法...`);
|
||||
console.log(`[CeruMusic] 开始调用插件的 getPic 方法...`)
|
||||
|
||||
const result = await this.plugin.getPic.call(
|
||||
{ cerumusic: this._getCerumusicApi() },
|
||||
source,
|
||||
musicInfo
|
||||
);
|
||||
|
||||
console.log(`[CeruMusic] 插件 getPic 方法调用成功`);
|
||||
return result;
|
||||
)
|
||||
|
||||
console.log(`[CeruMusic] 插件 getPic 方法调用成功`)
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error(`[CeruMusic] getPic 方法执行失败:`, error.message);
|
||||
throw new Error(`Plugin getPic failed: ${error.message}`);
|
||||
console.error(`[CeruMusic] getPic 方法执行失败:`, error.message)
|
||||
throw new Error(`Plugin getPic failed: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,23 +342,22 @@ class CeruMusicPluginHost {
|
||||
async getLyric(source, musicInfo) {
|
||||
try {
|
||||
if (typeof this.plugin.getLyric !== 'function') {
|
||||
throw new Error(`Action "getLyric" is not implemented in plugin.`);
|
||||
throw new Error(`Action "getLyric" is not implemented in plugin.`)
|
||||
}
|
||||
|
||||
console.log(`[CeruMusic] 开始调用插件的 getLyric 方法...`);
|
||||
console.log(`[CeruMusic] 开始调用插件的 getLyric 方法...`)
|
||||
|
||||
const result = await this.plugin.getLyric.call(
|
||||
{ cerumusic: this._getCerumusicApi() },
|
||||
source,
|
||||
musicInfo
|
||||
);
|
||||
|
||||
console.log(`[CeruMusic] 插件 getLyric 方法调用成功`);
|
||||
return result;
|
||||
)
|
||||
|
||||
console.log(`[CeruMusic] 插件 getLyric 方法调用成功`)
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error(`[CeruMusic] getLyric 方法执行失败:`, error.message);
|
||||
throw new Error(`Plugin getLyric failed: ${error.message}`);
|
||||
console.error(`[CeruMusic] getLyric 方法执行失败:`, error.message)
|
||||
throw new Error(`Plugin getLyric failed: ${error.message}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
const fs = require('fs');
|
||||
const fs = require('fs')
|
||||
|
||||
function convertEventDrivenPlugin(inputFile) {
|
||||
console.log('检测到事件驱动插件,使用事件包装器转换...');
|
||||
|
||||
const originalCode = fs.readFileSync(inputFile, 'utf-8');
|
||||
|
||||
// 提取插件信息
|
||||
const nameMatch = originalCode.match(/@name\s+(.+)/);
|
||||
const versionMatch = originalCode.match(/@version\s+(.+)/);
|
||||
const descMatch = originalCode.match(/@description\s+(.+)/);
|
||||
|
||||
const pluginName = nameMatch ? nameMatch[1].trim() : "未知插件";
|
||||
const pluginVersion = versionMatch ? versionMatch[1].trim() : "1.0.0";
|
||||
const pluginDesc = descMatch ? descMatch[1].trim() : "从事件驱动插件转换而来";
|
||||
|
||||
return `/**
|
||||
console.log('检测到事件驱动插件,使用事件包装器转换...')
|
||||
|
||||
const originalCode = fs.readFileSync(inputFile, 'utf-8')
|
||||
|
||||
// 提取插件信息
|
||||
const nameMatch = originalCode.match(/@name\s+(.+)/)
|
||||
const versionMatch = originalCode.match(/@version\s+(.+)/)
|
||||
const descMatch = originalCode.match(/@description\s+(.+)/)
|
||||
|
||||
const pluginName = nameMatch ? nameMatch[1].trim() : '未知插件'
|
||||
const pluginVersion = versionMatch ? versionMatch[1].trim() : '1.0.0'
|
||||
const pluginDesc = descMatch ? descMatch[1].trim() : '从事件驱动插件转换而来'
|
||||
|
||||
return `/**
|
||||
* 由 CeruMusic 插件转换器转换 - @author sqj
|
||||
* @name ${pluginName}
|
||||
* @version ${pluginVersion}
|
||||
@@ -49,16 +49,16 @@ function initializePlugin() {
|
||||
updateAlert: 'updateAlert'
|
||||
},
|
||||
on: (event, handler) => {
|
||||
console.log(\`[${ pluginName + ' by Ceru插件' || 'ceru插件' }] 注册事件监听器: \${event}\`);
|
||||
console.log(\`[${pluginName + ' by Ceru插件' || 'ceru插件'}] 注册事件监听器: \${event}\`);
|
||||
if (event === 'request') {
|
||||
requestHandler = handler;
|
||||
}
|
||||
},
|
||||
send: (event, data) => {
|
||||
console.log(\`[${ pluginName + ' by Ceru插件' || 'ceru插件' }] 发送事件: \${event}\`, data);
|
||||
console.log(\`[${pluginName + ' by Ceru插件' || 'ceru插件'}] 发送事件: \${event}\`, data);
|
||||
if (event === 'inited' && data.sources) {
|
||||
pluginSources = data.sources;
|
||||
console.log('[${ pluginName + ' by Ceru插件' || 'ceru插件' }] 音源注册完成:', Object.keys(pluginSources));
|
||||
console.log('[${pluginName + ' by Ceru插件' || 'ceru插件'}] 音源注册完成:', Object.keys(pluginSources));
|
||||
}
|
||||
},
|
||||
request: request,
|
||||
@@ -233,31 +233,31 @@ module.exports = {
|
||||
pluginInfo,
|
||||
sources,
|
||||
musicUrl
|
||||
};`;
|
||||
};`
|
||||
}
|
||||
|
||||
// 主函数
|
||||
function main() {
|
||||
const inputFile = process.argv[2];
|
||||
const outputFile = process.argv[3] || 'event-driven-plugin.js';
|
||||
const inputFile = process.argv[2]
|
||||
const outputFile = process.argv[3] || 'event-driven-plugin.js'
|
||||
|
||||
if (!inputFile) {
|
||||
console.error('使用方法: node converter-event-driven.js <输入文件> [输出文件]');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!inputFile) {
|
||||
console.error('使用方法: node converter-event-driven.js <输入文件> [输出文件]')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
try {
|
||||
const result = convertEventDrivenPlugin(inputFile);
|
||||
fs.writeFileSync(outputFile, result);
|
||||
|
||||
console.log('\\n🎉 事件驱动插件转换成功!');
|
||||
console.log(` 新插件已保存至: ${outputFile}`);
|
||||
} catch (error) {
|
||||
console.error('❌ 转换失败:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
try {
|
||||
const result = convertEventDrivenPlugin(inputFile)
|
||||
fs.writeFileSync(outputFile, result)
|
||||
|
||||
console.log('\\n🎉 事件驱动插件转换成功!')
|
||||
console.log(` 新插件已保存至: ${outputFile}`)
|
||||
} catch (error) {
|
||||
console.error('❌ 转换失败:', error.message)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
main()
|
||||
}
|
||||
|
||||
@@ -9,6 +9,4 @@ function getAppDirPath() {
|
||||
return dirPath
|
||||
}
|
||||
|
||||
export {
|
||||
getAppDirPath
|
||||
}
|
||||
export { getAppDirPath }
|
||||
|
||||
178
src/main/window/index.ts
Normal file
178
src/main/window/index.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import { Tray, Menu, BrowserWindow } from 'electron'
|
||||
import { electronApp, optimizer } from '@electron-toolkit/utils'
|
||||
import path from 'node:path'
|
||||
// 使用传入的 tray 对象
|
||||
export default function useWindow(
|
||||
createWindow,
|
||||
ipcMain,
|
||||
app,
|
||||
mainWindow: BrowserWindow | null,
|
||||
isQuitting: { value: boolean },
|
||||
trayObj: { value: Tray | null }
|
||||
) {
|
||||
function createTray(): void {
|
||||
// 创建系统托盘
|
||||
const trayIconPath = path.join(__dirname, '../../resources/logo.png')
|
||||
trayObj.value = new Tray(trayIconPath)
|
||||
|
||||
// 创建托盘菜单
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: '显示窗口',
|
||||
click: () => {
|
||||
if (mainWindow) {
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '播放/暂停',
|
||||
click: () => {
|
||||
// 这里可以添加播放控制逻辑
|
||||
mainWindow?.webContents.send('music-control')
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '退出',
|
||||
click: () => {
|
||||
isQuitting.value = true
|
||||
app.quit()
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
trayObj.value.setContextMenu(contextMenu)
|
||||
trayObj.value.setToolTip('Ceru Music')
|
||||
|
||||
// 双击托盘图标显示窗口
|
||||
trayObj.value.on('click', () => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isVisible()) {
|
||||
mainWindow.hide()
|
||||
} else {
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId('com.cerulean.music')
|
||||
|
||||
// Default open or close DevTools by F12 in development
|
||||
// and ignore CommandOrControl + R in production.
|
||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
app.on('browser-window-created', (_, window) => {
|
||||
optimizer.watchWindowShortcuts(window)
|
||||
})
|
||||
|
||||
// 窗口控制 IPC 处理
|
||||
ipcMain.on('window-minimize', () => {
|
||||
console.log('收到 window-minimize 事件')
|
||||
if (mainWindow) {
|
||||
console.log('正在最小化窗口...')
|
||||
mainWindow.minimize()
|
||||
} else {
|
||||
console.log('mainWindow 不存在')
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
if (window) {
|
||||
console.log('使用 getFocusedWindow 最小化窗口...')
|
||||
window.minimize()
|
||||
} else {
|
||||
console.log('没有找到可用的窗口')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('window-maximize', () => {
|
||||
console.log('收到 window-maximize 事件')
|
||||
if (mainWindow) {
|
||||
console.log('正在最大化/还原窗口...')
|
||||
if (mainWindow.isMaximized()) {
|
||||
mainWindow.unmaximize()
|
||||
} else {
|
||||
mainWindow.maximize()
|
||||
}
|
||||
} else {
|
||||
console.log('mainWindow 不存在')
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
if (window) {
|
||||
console.log('使用 getFocusedWindow 最大化/还原窗口...')
|
||||
if (window.isMaximized()) {
|
||||
window.unmaximize()
|
||||
} else {
|
||||
window.maximize()
|
||||
}
|
||||
} else {
|
||||
console.log('没有找到可用的窗口')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('window-close', () => {
|
||||
console.log('收到 window-close 事件')
|
||||
if (mainWindow) {
|
||||
console.log('正在关闭窗口...')
|
||||
mainWindow.close()
|
||||
} else {
|
||||
console.log('mainWindow 不存在')
|
||||
const window = BrowserWindow.getFocusedWindow()
|
||||
if (window) {
|
||||
console.log('使用 getFocusedWindow 关闭窗口...')
|
||||
window.close()
|
||||
} else {
|
||||
console.log('没有找到可用的窗口')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Mini 模式 IPC 处理 - 最小化到系统托盘
|
||||
ipcMain.on('window-mini-mode', (_, isMini) => {
|
||||
console.log('收到 window-mini-mode 事件,isMini:', isMini)
|
||||
if (mainWindow) {
|
||||
if (isMini) {
|
||||
// 进入 Mini 模式:隐藏窗口到系统托盘
|
||||
console.log('正在隐藏窗口...')
|
||||
mainWindow.hide()
|
||||
// 显示托盘通知(可选)
|
||||
if (trayObj.value) {
|
||||
console.log('显示托盘通知...')
|
||||
trayObj.value.displayBalloon({
|
||||
title: '澜音 Music',
|
||||
content: '已最小化到系统托盘啦,点击托盘图标可重新打开~'
|
||||
})
|
||||
} else {
|
||||
console.log('托盘对象不存在!trayObj.value:', trayObj.value)
|
||||
}
|
||||
} else {
|
||||
// 退出 Mini 模式:显示窗口
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 全屏模式 IPC 处理
|
||||
ipcMain.on('window-toggle-fullscreen', () => {
|
||||
if (mainWindow) {
|
||||
const isFullScreen = mainWindow.isFullScreen()
|
||||
mainWindow.setFullScreen(!isFullScreen)
|
||||
}
|
||||
})
|
||||
|
||||
createWindow()
|
||||
createTray()
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
// 不需要返回 tray,因为我们已经通过引用修改了外部传入的 trayObj
|
||||
return {}
|
||||
}
|
||||
@@ -4,10 +4,22 @@ import { electronAPI } from '@electron-toolkit/preload'
|
||||
// Custom APIs for renderer
|
||||
const api = {
|
||||
// 窗口控制方法
|
||||
minimize: () => ipcRenderer.send('window-minimize'),
|
||||
maximize: () => ipcRenderer.send('window-maximize'),
|
||||
close: () => ipcRenderer.send('window-close'),
|
||||
setMiniMode: (isMini: boolean) => ipcRenderer.send('window-mini-mode', isMini),
|
||||
minimize: () => {
|
||||
console.log('preload: 发送 window-minimize 事件')
|
||||
ipcRenderer.send('window-minimize')
|
||||
},
|
||||
maximize: () => {
|
||||
console.log('preload: 发送 window-maximize 事件')
|
||||
ipcRenderer.send('window-maximize')
|
||||
},
|
||||
close: () => {
|
||||
console.log('preload: 发送 window-close 事件')
|
||||
ipcRenderer.send('window-close')
|
||||
},
|
||||
setMiniMode: (isMini: boolean) => {
|
||||
console.log('preload: 发送 window-mini-mode 事件,isMini:', isMini)
|
||||
ipcRenderer.send('window-mini-mode', isMini)
|
||||
},
|
||||
toggleFullscreen: () => ipcRenderer.send('window-toggle-fullscreen'),
|
||||
onMusicCtrl: (callback) => ipcRenderer.on('music-control', callback),
|
||||
|
||||
|
||||
4
src/renderer/auto-imports.d.ts
vendored
4
src/renderer/auto-imports.d.ts
vendored
@@ -5,6 +5,4 @@
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
||||
declare global {}
|
||||
|
||||
@@ -20,7 +20,6 @@ import { parseYrc, parseLrc, parseTTML } from '@applemusic-like-lyrics/lyric/pkg
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
|
||||
interface Props {
|
||||
show?: boolean
|
||||
coverImage?: string
|
||||
@@ -120,7 +119,7 @@ watch(
|
||||
const translatedline = parseLrc(lyricData.tlyric.lyric)
|
||||
console.log(translatedline)
|
||||
for (let i = 0; i < parsedLyrics.length; i++) {
|
||||
parsedLyrics[i].translatedLyric = translatedline[i].words[0].word
|
||||
parsedLyrics[i].translatedLyric = translatedline[i].words[0].word
|
||||
}
|
||||
console.log('使用翻译歌词', translatedline)
|
||||
}
|
||||
@@ -274,7 +273,7 @@ watch(
|
||||
<div v-show="state.lyricLines.length > 0" class="right">
|
||||
<LyricPlayer
|
||||
ref="lyricPlayerRef"
|
||||
:lyric-lines="props.show? state.lyricLines : []"
|
||||
:lyric-lines="props.show ? state.lyricLines : []"
|
||||
:current-time="state.currentTime"
|
||||
:align-position="0.38"
|
||||
style="mix-blend-mode: plus-lighter"
|
||||
|
||||
@@ -52,7 +52,13 @@ const handleClose = (): void => {
|
||||
|
||||
const handleMiniMode = (): void => {
|
||||
// 直接最小化到系统托盘
|
||||
window.api?.setMiniMode(true)
|
||||
console.log('TitleBarControls: 点击了最小化到系统托盘按钮')
|
||||
if (window.api) {
|
||||
console.log('TitleBarControls: window.api 存在,调用 setMiniMode(true)')
|
||||
window.api.setMiniMode(true)
|
||||
} else {
|
||||
console.error('TitleBarControls: window.api 不存在!')
|
||||
}
|
||||
console.log('最小化到系统托盘')
|
||||
}
|
||||
|
||||
|
||||
641
yarn.lock
641
yarn.lock
@@ -432,6 +432,138 @@
|
||||
minimatch "^9.0.3"
|
||||
plist "^3.1.0"
|
||||
|
||||
"@emnapi/runtime@^1.2.0":
|
||||
version "1.4.5"
|
||||
resolved "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.4.5.tgz"
|
||||
integrity sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@esbuild/aix-ppc64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz"
|
||||
integrity sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==
|
||||
|
||||
"@esbuild/android-arm@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.9.tgz"
|
||||
integrity sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==
|
||||
|
||||
"@esbuild/android-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz"
|
||||
integrity sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==
|
||||
|
||||
"@esbuild/android-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.9.tgz"
|
||||
integrity sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==
|
||||
|
||||
"@esbuild/darwin-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz"
|
||||
integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==
|
||||
|
||||
"@esbuild/darwin-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz"
|
||||
integrity sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz"
|
||||
integrity sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==
|
||||
|
||||
"@esbuild/freebsd-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz"
|
||||
integrity sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==
|
||||
|
||||
"@esbuild/linux-arm@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz"
|
||||
integrity sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==
|
||||
|
||||
"@esbuild/linux-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz"
|
||||
integrity sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==
|
||||
|
||||
"@esbuild/linux-ia32@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz"
|
||||
integrity sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==
|
||||
|
||||
"@esbuild/linux-loong64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz"
|
||||
integrity sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==
|
||||
|
||||
"@esbuild/linux-mips64el@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz"
|
||||
integrity sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==
|
||||
|
||||
"@esbuild/linux-ppc64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz"
|
||||
integrity sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==
|
||||
|
||||
"@esbuild/linux-riscv64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz"
|
||||
integrity sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==
|
||||
|
||||
"@esbuild/linux-s390x@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz"
|
||||
integrity sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==
|
||||
|
||||
"@esbuild/linux-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz"
|
||||
integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==
|
||||
|
||||
"@esbuild/netbsd-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz"
|
||||
integrity sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==
|
||||
|
||||
"@esbuild/netbsd-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz"
|
||||
integrity sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz"
|
||||
integrity sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==
|
||||
|
||||
"@esbuild/openbsd-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz"
|
||||
integrity sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==
|
||||
|
||||
"@esbuild/openharmony-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz"
|
||||
integrity sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==
|
||||
|
||||
"@esbuild/sunos-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz"
|
||||
integrity sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==
|
||||
|
||||
"@esbuild/win32-arm64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz"
|
||||
integrity sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz"
|
||||
integrity sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==
|
||||
|
||||
"@esbuild/win32-x64@0.25.9":
|
||||
version "0.25.9"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz"
|
||||
@@ -536,6 +668,114 @@
|
||||
resolved "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz"
|
||||
integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==
|
||||
|
||||
"@img/sharp-darwin-arm64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz"
|
||||
integrity sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-arm64" "1.0.4"
|
||||
|
||||
"@img/sharp-darwin-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz"
|
||||
integrity sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-x64" "1.0.4"
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz"
|
||||
integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==
|
||||
|
||||
"@img/sharp-libvips-darwin-x64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz"
|
||||
integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==
|
||||
|
||||
"@img/sharp-libvips-linux-arm@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz"
|
||||
integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==
|
||||
|
||||
"@img/sharp-libvips-linux-arm64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz"
|
||||
integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==
|
||||
|
||||
"@img/sharp-libvips-linux-s390x@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz"
|
||||
integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==
|
||||
|
||||
"@img/sharp-libvips-linux-x64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz"
|
||||
integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz"
|
||||
integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz"
|
||||
integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==
|
||||
|
||||
"@img/sharp-linux-arm@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz"
|
||||
integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm" "1.0.5"
|
||||
|
||||
"@img/sharp-linux-arm64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz"
|
||||
integrity sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm64" "1.0.4"
|
||||
|
||||
"@img/sharp-linux-s390x@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz"
|
||||
integrity sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-s390x" "1.0.4"
|
||||
|
||||
"@img/sharp-linux-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz"
|
||||
integrity sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-x64" "1.0.4"
|
||||
|
||||
"@img/sharp-linuxmusl-arm64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz"
|
||||
integrity sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-arm64" "1.0.4"
|
||||
|
||||
"@img/sharp-linuxmusl-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz"
|
||||
integrity sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-x64" "1.0.4"
|
||||
|
||||
"@img/sharp-wasm32@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz"
|
||||
integrity sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==
|
||||
dependencies:
|
||||
"@emnapi/runtime" "^1.2.0"
|
||||
|
||||
"@img/sharp-win32-ia32@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz"
|
||||
integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==
|
||||
|
||||
"@img/sharp-win32-x64@0.33.5":
|
||||
version "0.33.5"
|
||||
resolved "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz"
|
||||
@@ -992,6 +1232,66 @@
|
||||
mkdirp "^1.0.4"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
"@parcel/watcher-android-arm64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz"
|
||||
integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
|
||||
|
||||
"@parcel/watcher-darwin-arm64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz"
|
||||
integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
|
||||
|
||||
"@parcel/watcher-darwin-x64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz"
|
||||
integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
|
||||
|
||||
"@parcel/watcher-freebsd-x64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz"
|
||||
integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz"
|
||||
integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
|
||||
|
||||
"@parcel/watcher-linux-arm-musl@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz"
|
||||
integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz"
|
||||
integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz"
|
||||
integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz"
|
||||
integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
|
||||
|
||||
"@parcel/watcher-linux-x64-musl@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz"
|
||||
integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
|
||||
|
||||
"@parcel/watcher-win32-arm64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz"
|
||||
integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
|
||||
|
||||
"@parcel/watcher-win32-ia32@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz"
|
||||
integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
|
||||
|
||||
"@parcel/watcher-win32-x64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz"
|
||||
@@ -1158,6 +1458,101 @@
|
||||
resolved "https://registry.npmmirror.com/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz"
|
||||
integrity sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz"
|
||||
integrity sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz"
|
||||
integrity sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz"
|
||||
integrity sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz"
|
||||
integrity sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==
|
||||
|
||||
"@rollup/rollup-freebsd-arm64@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz"
|
||||
integrity sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==
|
||||
|
||||
"@rollup/rollup-freebsd-x64@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz"
|
||||
integrity sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz"
|
||||
integrity sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz"
|
||||
integrity sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz"
|
||||
integrity sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz"
|
||||
integrity sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz"
|
||||
integrity sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==
|
||||
|
||||
"@rollup/rollup-linux-ppc64-gnu@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz"
|
||||
integrity sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz"
|
||||
integrity sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-musl@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz"
|
||||
integrity sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz"
|
||||
integrity sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz"
|
||||
integrity sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz"
|
||||
integrity sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz"
|
||||
integrity sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz"
|
||||
integrity sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.46.2":
|
||||
version "4.46.2"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz"
|
||||
@@ -1178,6 +1573,51 @@
|
||||
resolved "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz"
|
||||
integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==
|
||||
|
||||
"@swc/core-darwin-arm64@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.3.tgz"
|
||||
integrity sha512-ux0Ws4pSpBTqbDS9GlVP354MekB1DwYlbxXU3VhnDr4GBcCOimpocx62x7cFJkSpEBF8bmX8+/TTCGKh4PbyXw==
|
||||
|
||||
"@swc/core-darwin-x64@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-darwin-x64/-/core-darwin-x64-1.13.3.tgz"
|
||||
integrity sha512-p0X6yhxmNUOMZrbeZ3ZNsPige8lSlSe1llllXvpCLkKKxN/k5vZt1sULoq6Nj4eQ7KeHQVm81/+AwKZyf/e0TA==
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.3.tgz"
|
||||
integrity sha512-OmDoiexL2fVWvQTCtoh0xHMyEkZweQAlh4dRyvl8ugqIPEVARSYtaj55TBMUJIP44mSUOJ5tytjzhn2KFxFcBA==
|
||||
|
||||
"@swc/core-linux-arm64-gnu@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.3.tgz"
|
||||
integrity sha512-STfKku3QfnuUj6k3g9ld4vwhtgCGYIFQmsGPPgT9MK/dI3Lwnpe5Gs5t1inoUIoGNP8sIOLlBB4HV4MmBjQuhw==
|
||||
|
||||
"@swc/core-linux-arm64-musl@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.3.tgz"
|
||||
integrity sha512-bc+CXYlFc1t8pv9yZJGus372ldzOVscBl7encUBlU1m/Sig0+NDJLz6cXXRcFyl6ABNOApWeR4Yl7iUWx6C8og==
|
||||
|
||||
"@swc/core-linux-x64-gnu@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.3.tgz"
|
||||
integrity sha512-dFXoa0TEhohrKcxn/54YKs1iwNeW6tUkHJgXW33H381SvjKFUV53WR231jh1sWVJETjA3vsAwxKwR23s7UCmUA==
|
||||
|
||||
"@swc/core-linux-x64-musl@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.3.tgz"
|
||||
integrity sha512-ieyjisLB+ldexiE/yD8uomaZuZIbTc8tjquYln9Quh5ykOBY7LpJJYBWvWtm1g3pHv6AXlBI8Jay7Fffb6aLfA==
|
||||
|
||||
"@swc/core-win32-arm64-msvc@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.3.tgz"
|
||||
integrity sha512-elTQpnaX5vESSbhCEgcwXjpMsnUbqqHfEpB7ewpkAsLzKEXZaK67ihSRYAuAx6ewRQTo7DS5iTT6X5aQD3MzMw==
|
||||
|
||||
"@swc/core-win32-ia32-msvc@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.3.tgz"
|
||||
integrity sha512-nvehQVEOdI1BleJpuUgPLrclJ0TzbEMc+MarXDmmiRFwEUGqj+pnfkTSb7RZyS1puU74IXdK/YhTirHurtbI9w==
|
||||
|
||||
"@swc/core-win32-x64-msvc@1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.npmmirror.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.3.tgz"
|
||||
@@ -1344,6 +1784,14 @@
|
||||
resolved "https://registry.npmmirror.com/@types/node/-/node-16.9.1.tgz"
|
||||
integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
|
||||
|
||||
"@types/plist@^3.0.1":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.npmmirror.com/@types/plist/-/plist-3.0.5.tgz"
|
||||
integrity sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
xmlbuilder ">=11.0.1"
|
||||
|
||||
"@types/responselike@^1.0.0":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmmirror.com/@types/responselike/-/responselike-1.0.3.tgz"
|
||||
@@ -1381,6 +1829,11 @@
|
||||
resolved "https://registry.npmmirror.com/@types/validator/-/validator-13.15.2.tgz"
|
||||
integrity sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==
|
||||
|
||||
"@types/verror@^1.10.3":
|
||||
version "1.10.11"
|
||||
resolved "https://registry.npmmirror.com/@types/verror/-/verror-1.10.11.tgz"
|
||||
integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==
|
||||
|
||||
"@types/yauzl@^2.9.1":
|
||||
version "2.10.3"
|
||||
resolved "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz"
|
||||
@@ -1790,7 +2243,7 @@ ajv-keywords@^3.4.1:
|
||||
resolved "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz"
|
||||
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
|
||||
|
||||
ajv@^6.12.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.9.1:
|
||||
ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.9.1:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz"
|
||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||
@@ -2007,6 +2460,11 @@ ast-types@^0.13.4:
|
||||
dependencies:
|
||||
tslib "^2.0.1"
|
||||
|
||||
astral-regex@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz"
|
||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
||||
|
||||
async-exit-hook@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz"
|
||||
@@ -2189,7 +2647,7 @@ buffer-from@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer@^5.2.0, buffer@^5.5.0:
|
||||
buffer@^5.1.0, buffer@^5.2.0, buffer@^5.5.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz"
|
||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||
@@ -2443,6 +2901,14 @@ cli-spinners@^2.5.0:
|
||||
resolved "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz"
|
||||
integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
|
||||
|
||||
cli-truncate@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz"
|
||||
integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
|
||||
dependencies:
|
||||
slice-ansi "^3.0.0"
|
||||
string-width "^4.2.0"
|
||||
|
||||
cliui@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmmirror.com/cliui/-/cliui-3.2.0.tgz"
|
||||
@@ -2677,6 +3143,13 @@ crc-32@^1.2.0:
|
||||
resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz"
|
||||
integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
|
||||
|
||||
crc@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.npmmirror.com/crc/-/crc-3.8.0.tgz"
|
||||
integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
|
||||
dependencies:
|
||||
buffer "^5.1.0"
|
||||
|
||||
crc32-stream@^4.0.2:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmmirror.com/crc32-stream/-/crc32-stream-4.0.3.tgz"
|
||||
@@ -2934,6 +3407,20 @@ dmg-builder@25.1.8:
|
||||
optionalDependencies:
|
||||
dmg-license "^1.0.11"
|
||||
|
||||
dmg-license@^1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.npmmirror.com/dmg-license/-/dmg-license-1.0.11.tgz"
|
||||
integrity sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==
|
||||
dependencies:
|
||||
"@types/plist" "^3.0.1"
|
||||
"@types/verror" "^1.10.3"
|
||||
ajv "^6.10.0"
|
||||
crc "^3.8.0"
|
||||
iconv-corefoundation "^1.1.7"
|
||||
plist "^3.0.4"
|
||||
smart-buffer "^4.0.2"
|
||||
verror "^1.10.0"
|
||||
|
||||
dom-walk@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.npmmirror.com/dom-walk/-/dom-walk-0.1.2.tgz"
|
||||
@@ -3076,10 +3563,10 @@ electron-vite@^4.0.0:
|
||||
magic-string "^0.30.17"
|
||||
picocolors "^1.1.1"
|
||||
|
||||
electron@^37.2.3, electron@>=13.0.0:
|
||||
version "37.3.0"
|
||||
resolved "https://registry.npmmirror.com/electron/-/electron-37.3.0.tgz"
|
||||
integrity sha512-cPOPUD26DwCh+PZ9q+gMyVBvdBN75SnekI6u5zcOeoLVIXQpzrCm1ewz9BcrkWkVW7oOtfQAEo1G1SffvXrSSw==
|
||||
electron@^37.3.1, electron@>=13.0.0:
|
||||
version "37.3.1"
|
||||
resolved "https://registry.npmmirror.com/electron/-/electron-37.3.1.tgz"
|
||||
integrity sha512-7DhktRLqhe6OJh/Bo75bTI0puUYEmIwSzMinocgO63mx3MVjtIn2tYMzLmAleNIlud2htkjpsMG2zT4PiTCloA==
|
||||
dependencies:
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^22.7.7"
|
||||
@@ -3508,7 +3995,12 @@ extract-zip@^2.0.1:
|
||||
optionalDependencies:
|
||||
"@types/yauzl" "^2.9.1"
|
||||
|
||||
extsprintf@^1.2.0, extsprintf@1.3.0:
|
||||
extsprintf@^1.2.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmmirror.com/extsprintf/-/extsprintf-1.4.1.tgz"
|
||||
integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
|
||||
|
||||
extsprintf@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmmirror.com/extsprintf/-/extsprintf-1.3.0.tgz"
|
||||
integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==
|
||||
@@ -3805,6 +4297,11 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz"
|
||||
@@ -4219,6 +4716,14 @@ icon-gen@^2.0.0:
|
||||
svg2png "4.1.1"
|
||||
uuid "^8.3.1"
|
||||
|
||||
iconv-corefoundation@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.npmmirror.com/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz"
|
||||
integrity sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==
|
||||
dependencies:
|
||||
cli-truncate "^2.1.0"
|
||||
node-addon-api "^1.6.3"
|
||||
|
||||
iconv-lite@^0.6.2:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz"
|
||||
@@ -5401,6 +5906,11 @@ node-abi@^3.45.0:
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
node-addon-api@^1.6.3:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-1.7.2.tgz"
|
||||
integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
|
||||
|
||||
node-addon-api@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz"
|
||||
@@ -5948,7 +6458,7 @@ pkg-types@^2.0.1, pkg-types@^2.2.0:
|
||||
exsolve "^1.0.7"
|
||||
pathe "^2.0.3"
|
||||
|
||||
plist@^3.0.5, plist@^3.1.0:
|
||||
plist@^3.0.4, plist@^3.0.5, plist@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmmirror.com/plist/-/plist-3.1.0.tgz"
|
||||
integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==
|
||||
@@ -6462,6 +6972,95 @@ sanitize-filename@^1.6.3:
|
||||
dependencies:
|
||||
truncate-utf8-bytes "^1.0.0"
|
||||
|
||||
sass-embedded-all-unknown@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.90.0.tgz"
|
||||
integrity sha512-/n7jTQvI+hftDDrHzK19G4pxfDzOhtjuQO1K54ui1pT2S0sWfWDjCYUbQgtWQ6FO7g5qWS0hgmrWdc7fmS3rgA==
|
||||
dependencies:
|
||||
sass "1.90.0"
|
||||
|
||||
sass-embedded-android-arm@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-android-arm/-/sass-embedded-android-arm-1.90.0.tgz"
|
||||
integrity sha512-usF6kVJQWa1CMgPH1nCT1y8KEmAT2fzB00dDIPBYHq8U5VZLCihi2bJRP5U9NlcwP1TlKGKCjwsbIdSjDKfecg==
|
||||
|
||||
sass-embedded-android-arm64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.90.0.tgz"
|
||||
integrity sha512-bkTlewzWksa6Sj4Zs1CWiutnvUbsO3xuYh2QBRknXsOtuMlfTPoXnwhCnyE4lSvUxw2qxSbv+NdQev9qMfsBgA==
|
||||
|
||||
sass-embedded-android-riscv64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.90.0.tgz"
|
||||
integrity sha512-bpqCIOaX+0Lou/BNJ4iJIKbWbVaYXFdg26C3gG6gxxKZRzp/6OYCxHrIQDwhKz6YC8Q5rwNPMpfDVYbWPcgroA==
|
||||
|
||||
sass-embedded-android-x64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-android-x64/-/sass-embedded-android-x64-1.90.0.tgz"
|
||||
integrity sha512-GNxVKnCMd/p2icZ+Q4mhvNk19NrLXq1C4guiqjrycHYQLEnxRkjbW1QXYiL+XyDn4e+Bcq0knzG0I9pMuNZxkg==
|
||||
|
||||
sass-embedded-darwin-arm64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.90.0.tgz"
|
||||
integrity sha512-qr4KBMJfBA+lzXiWnP00qzpLzHQzGd1OSK3VHcUFjZ8l7VOYf2R7Tc3fcTLhpaNPMJtTK0jrk8rFqBvsiZExnA==
|
||||
|
||||
sass-embedded-darwin-x64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.90.0.tgz"
|
||||
integrity sha512-z2nr1nNqtWDLVRwTbHtL7zriK90U7O/Gb15UaCSMYeAz9Y+wog5s/sDEKm0+GsVdzzkaCaMZRWGN4jTilnUwmQ==
|
||||
|
||||
sass-embedded-linux-arm@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.90.0.tgz"
|
||||
integrity sha512-FeBxI5Q2HvM3CCadcEcQgvWbDPVs2YEF0PZ87fbAVTCG8dV+iNnQreSz7GRJroknpvbRhm5t2gedvcgmTnPb2Q==
|
||||
|
||||
sass-embedded-linux-arm64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.90.0.tgz"
|
||||
integrity sha512-SPMcGZuP71Fj8btCGtlBnv8h8DAbJn8EQfLzXs9oo6NGFFLVjNGiFpqGfgtUV6DLWCuaRyEFeViO7wZow/vKGQ==
|
||||
|
||||
sass-embedded-linux-musl-arm@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.90.0.tgz"
|
||||
integrity sha512-EB2z0fUXdUdvSoddf4DzdZQkD/xyreD72gwAi8YScgUvR4HMXI7bLcK/n78Rft6OnqvV8090hjC8FsLDo3x5xQ==
|
||||
|
||||
sass-embedded-linux-musl-arm64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.90.0.tgz"
|
||||
integrity sha512-xLH7+PFq763MoEm3vI7hQk5E+nStiLWbijHEYW/tEtCbcQIphgzSkDItEezxXew3dU4EJ1jqrBUySPdoXFLqWA==
|
||||
|
||||
sass-embedded-linux-musl-riscv64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.90.0.tgz"
|
||||
integrity sha512-L21UkOgnSrD+ERF+jo1IWneGv40t0ap9+3cI+wZWYhQS5MkxponhT9QaNU57JEDJwB9mOl01LVw14opz4SN+VQ==
|
||||
|
||||
sass-embedded-linux-musl-x64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.90.0.tgz"
|
||||
integrity sha512-NeAycQlsdhFdnIeSmRmScYUyCd+uE+x15NLFunbF8M0PgCKurrUhaxgGKSuBbaK56FpxarKOHCqcOrWbemIGzQ==
|
||||
|
||||
sass-embedded-linux-riscv64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.90.0.tgz"
|
||||
integrity sha512-lJopaQhW8S+kaQ61vMqq3c+bOurcf9RdZf2EmzQYpc2y1vT5cWfRNrRkbAgO/23IQxsk/fq3UIUnsjnyQmi6MA==
|
||||
|
||||
sass-embedded-linux-x64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.90.0.tgz"
|
||||
integrity sha512-Cc061gBfMPwH9rN7neQaH36cvOQC+dFMSGIeX5qUOhrEL4Ng51iqBV6aI4RIB1jCFGth6eDydVRN1VdV9qom8A==
|
||||
|
||||
sass-embedded-unknown-all@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.90.0.tgz"
|
||||
integrity sha512-DBGzHVCJDqtjTHZFohush9YTxd4ZxhIygIRTNRXnA0359woF9Z8AS7/YxfzwkqrTX5durSJa6ZamGFYVLoRphQ==
|
||||
dependencies:
|
||||
sass "1.90.0"
|
||||
|
||||
sass-embedded-win32-arm64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.90.0.tgz"
|
||||
integrity sha512-c3/vL/CATnaW3x/6kcNbCROEOUU7zvJpIURp7M9664GJj08/gLPRWKNruw0OkAPQ3C5TTQz7+/fQWEpRA6qmvA==
|
||||
|
||||
sass-embedded-win32-x64@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.90.0.tgz"
|
||||
@@ -6500,7 +7099,7 @@ sass-embedded@^1.70.0, sass-embedded@^1.90.0:
|
||||
sass-embedded-win32-arm64 "1.90.0"
|
||||
sass-embedded-win32-x64 "1.90.0"
|
||||
|
||||
sass@^1.70.0:
|
||||
sass@^1.70.0, sass@1.90.0:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmmirror.com/sass/-/sass-1.90.0.tgz"
|
||||
integrity sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==
|
||||
@@ -6748,7 +7347,16 @@ slash@^3.0.0:
|
||||
resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
smart-buffer@^4.2.0:
|
||||
slice-ansi@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz"
|
||||
integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
smart-buffer@^4.0.2, smart-buffer@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz"
|
||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||
@@ -7206,7 +7814,7 @@ ts-api-utils@^2.1.0:
|
||||
resolved "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz"
|
||||
integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
|
||||
|
||||
tslib@^2.0.1, tslib@^2.1.0:
|
||||
tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
@@ -7478,6 +8086,15 @@ vary@~1.1.2:
|
||||
resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
||||
verror@^1.10.0:
|
||||
version "1.10.1"
|
||||
resolved "https://registry.npmmirror.com/verror/-/verror-1.10.1.tgz"
|
||||
integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
core-util-is "1.0.2"
|
||||
extsprintf "^1.2.0"
|
||||
|
||||
verror@1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.npmmirror.com/verror/-/verror-1.10.0.tgz"
|
||||
@@ -7765,7 +8382,7 @@ xml2js@^0.6.2:
|
||||
sax ">=0.6.0"
|
||||
xmlbuilder "~11.0.0"
|
||||
|
||||
xmlbuilder@^15.1.1:
|
||||
xmlbuilder@^15.1.1, xmlbuilder@>=11.0.1:
|
||||
version "15.1.1"
|
||||
resolved "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz"
|
||||
integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
|
||||
|
||||
Reference in New Issue
Block a user