1
This commit is contained in:
145
api/services/version_service.js
Normal file
145
api/services/version_service.js
Normal file
@@ -0,0 +1,145 @@
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* 版本服务
|
||||
* 提供版本比较、文件哈希计算等功能
|
||||
*/
|
||||
class VersionService {
|
||||
/**
|
||||
* 比较两个版本号
|
||||
* @param {string} version1 - 版本号1(x.y.z 格式)
|
||||
* @param {string} version2 - 版本号2(x.y.z 格式)
|
||||
* @returns {number} 返回 1 表示 version1 > version2,-1 表示 version1 < version2,0 表示相等
|
||||
*/
|
||||
compare_version(version1, version2) {
|
||||
if (!version1 || !version2) {
|
||||
throw new Error('版本号不能为空');
|
||||
}
|
||||
|
||||
// 验证版本号格式
|
||||
const version_pattern = /^\d+\.\d+\.\d+$/;
|
||||
if (!version_pattern.test(version1) || !version_pattern.test(version2)) {
|
||||
throw new Error('版本号格式错误,应为 x.y.z 格式');
|
||||
}
|
||||
|
||||
// 将版本号按 "." 分割成数组
|
||||
const v1_parts = version1.split('.').map(Number);
|
||||
const v2_parts = version2.split('.').map(Number);
|
||||
|
||||
// 逐位比较
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (v1_parts[i] > v2_parts[i]) {
|
||||
return 1;
|
||||
} else if (v1_parts[i] < v2_parts[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有新版本
|
||||
* @param {string} current_version - 当前版本号
|
||||
* @param {string} latest_version - 最新版本号
|
||||
* @returns {boolean} 是否有新版本
|
||||
*/
|
||||
has_new_version(current_version, latest_version) {
|
||||
try {
|
||||
const result = this.compare_version(latest_version, current_version);
|
||||
return result > 0;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算文件的 SHA256 哈希值
|
||||
* @param {string} file_path - 文件路径
|
||||
* @returns {Promise<string>} SHA256 哈希值(小写十六进制字符串)
|
||||
*/
|
||||
async calculate_file_hash(file_path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 检查文件是否存在
|
||||
if (!fs.existsSync(file_path)) {
|
||||
return reject(new Error(`文件不存在: ${file_path}`));
|
||||
}
|
||||
|
||||
// 创建哈希对象
|
||||
const hash = crypto.createHash('sha256');
|
||||
const stream = fs.createReadStream(file_path);
|
||||
|
||||
stream.on('data', (data) => {
|
||||
hash.update(data);
|
||||
});
|
||||
|
||||
stream.on('end', () => {
|
||||
const hash_value = hash.digest('hex');
|
||||
resolve(hash_value);
|
||||
});
|
||||
|
||||
stream.on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件大小
|
||||
* @param {string} file_path - 文件路径
|
||||
* @returns {Promise<number>} 文件大小(字节)
|
||||
*/
|
||||
async get_file_size(file_path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!fs.existsSync(file_path)) {
|
||||
return reject(new Error(`文件不存在: ${file_path}`));
|
||||
}
|
||||
|
||||
fs.stat(file_path, (error, stats) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
resolve(stats.size);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证版本号格式
|
||||
* @param {string} version - 版本号
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
is_valid_version(version) {
|
||||
if (!version || typeof version !== 'string') {
|
||||
return false;
|
||||
}
|
||||
const version_pattern = /^\d+\.\d+\.\d+$/;
|
||||
return version_pattern.test(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证平台类型
|
||||
* @param {string} platform - 平台类型
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
is_valid_platform(platform) {
|
||||
const valid_platforms = ['win32', 'darwin', 'linux'];
|
||||
return valid_platforms.includes(platform);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证架构类型
|
||||
* @param {string} arch - 架构类型
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
is_valid_arch(arch) {
|
||||
const valid_archs = ['x64', 'ia32', 'arm64'];
|
||||
return valid_archs.includes(arch);
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例
|
||||
module.exports = new VersionService();
|
||||
|
||||
Reference in New Issue
Block a user