146 lines
3.7 KiB
JavaScript
146 lines
3.7 KiB
JavaScript
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();
|
||
|