utils.mjs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import fs from 'fs';
  2. import { ZipArchive } from 'archiver';
  3. import { exec } from 'child_process';
  4. import { readdir, stat } from 'fs/promises';
  5. import consola from 'consola';
  6. export function readFileRange(file, start, length) {
  7. return new Promise((resolve, reject) => {
  8. fs.open(file, 'r', (err, fd) => {
  9. if (err) {
  10. reject('Error opening file:', er);
  11. return;
  12. }
  13. const buffer = Buffer.alloc(length);
  14. fs.read(fd, buffer, 0, length, start, (err, bytesRead, buffer) => {
  15. if (err) {
  16. reject('Error reading file:', err)
  17. return;
  18. }
  19. fs.close(fd, (err) => {
  20. if (err) {
  21. reject('Error closing file:', err)
  22. return ;
  23. }
  24. resolve(buffer);
  25. });
  26. });
  27. });
  28. })
  29. }
  30. export function pad(num, n) {
  31. var strNum = num.toString();
  32. var len = strNum.length;
  33. while (len < n) {
  34. strNum = "0" + strNum;
  35. len++;
  36. }
  37. return strNum;
  38. }
  39. /**
  40. * 异步执行命令
  41. * @param {string} command 命令
  42. * @returns {Promise<string>} 命令执行结果
  43. */
  44. export function execAsync(command) {
  45. return new Promise((resolve, reject) => {
  46. consola.info('[CMD] ' + command);
  47. exec(command, (error, stdout, stderr) => {
  48. if (error) {
  49. reject(error);
  50. return;
  51. }
  52. resolve(stdout);
  53. });
  54. })
  55. }
  56. /**
  57. * 记录错误信息
  58. * @param {string} message 错误信息
  59. * @param {*} e 错误对象
  60. */
  61. export function logError(message, e) {
  62. consola.error(message, e || '');
  63. }
  64. /**
  65. * 获取错误信息
  66. * @param {*} e 错误对象
  67. * @returns {string} 错误信息
  68. */
  69. export function getErrorMessage(e) {
  70. if (e instanceof Error)
  71. return e.message;
  72. if (typeof e === 'object' && e.message)
  73. return e.message;
  74. return '' + e;
  75. }
  76. /**
  77. * 压缩zip
  78. * @param {string} dir 压缩目录
  79. * @param {string} targetFilePath 压缩文件路径
  80. * @param {string[]} skipFiles 压缩忽略文件 支持按开头匹配,和文件类型通配符匹配,如:'*.js', '*.css', '*.html'
  81. * @returns {Promise<void>}
  82. */
  83. export async function compressZip(dir, targetFilePath, skipFiles) {
  84. const output = fs.createWriteStream(targetFilePath);
  85. const archive = new ZipArchive({
  86. zlib: { level: 9 } // Sets the compression level.
  87. });
  88. archive.pipe(output);
  89. function checkPathSkip(pathString) {
  90. if (!pathString)
  91. return true;
  92. if (pathString.startsWith('.') || pathString.startsWith('/.'))
  93. return true;
  94. if (!skipFiles || skipFiles.length === 0)
  95. return;
  96. return skipFiles.find((item) => (
  97. pathString.startsWith(item) || pathString.startsWith(`/${item}`)
  98. || (item.includes('*.') && pathString.endsWith(item.split('*')[1]))
  99. ));
  100. }
  101. async function loopDir(path, subPrefix) {
  102. const files = await readdir(path);
  103. for (const file of files) {
  104. const subPath = subPrefix + '/' + file;
  105. if (checkPathSkip(subPath))
  106. continue;
  107. consola.info('File: ' + subPath);
  108. const filestat = await stat(dir + subPath);
  109. if (filestat.isDirectory()) {
  110. await loopDir(dir + subPath, subPath);
  111. } else {
  112. archive.file(dir + subPath, { name: subPath });
  113. }
  114. }
  115. }
  116. await loopDir(dir, '')
  117. consola.start('等待压缩zip...');
  118. const waitArchive = new Promise((resolve, reject) => {
  119. output.on('close', function() {
  120. consola.info(archive.pointer() + ' total bytes');
  121. consola.success('archiver has been finalized and the output file descriptor has closed.');
  122. resolve();
  123. });
  124. archive.on('error', function(err) {
  125. reject(err);
  126. });
  127. })
  128. await archive.finalize();
  129. await waitArchive;
  130. }