output-paths.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. const fs = require('fs');
  2. const path = require('path');
  3. const PACKAGE_ROOT = path.resolve(__dirname, '..', '..', '..');
  4. const OUTPUT_CATEGORIES = Object.freeze([
  5. 'login',
  6. 'api-calls',
  7. 'subscription',
  8. 'meetings',
  9. 'docs',
  10. 'messages',
  11. 'smoke',
  12. 'tmp'
  13. ]);
  14. function outputsRoot() {
  15. const override = process.env.QIWEI_OUTPUTS_DIR;
  16. if (override && String(override).trim()) return path.resolve(String(override).trim());
  17. return path.join(PACKAGE_ROOT, 'outputs');
  18. }
  19. function ensureDir(dirPath) {
  20. fs.mkdirSync(dirPath, { recursive: true });
  21. return dirPath;
  22. }
  23. function assertCategory(category) {
  24. if (!OUTPUT_CATEGORIES.includes(category)) {
  25. throw new Error(`未知输出类别 "${category}",允许的类别:${OUTPUT_CATEGORIES.join(', ')}`);
  26. }
  27. return category;
  28. }
  29. function slugify(value, fallback = 'run') {
  30. const slug = String(value || '')
  31. .trim()
  32. .toLowerCase()
  33. .replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
  34. .replace(/^-+|-+$/g, '')
  35. .slice(0, 60);
  36. return slug || fallback;
  37. }
  38. function dateStamp(date = new Date()) {
  39. return date.toISOString().slice(0, 10);
  40. }
  41. function timeStamp(date = new Date()) {
  42. return date.toISOString().slice(11, 19).replace(/:/g, '');
  43. }
  44. function categoryDir(category) {
  45. return ensureDir(path.join(outputsRoot(), assertCategory(category)));
  46. }
  47. function latestPath(category, filename) {
  48. return path.join(categoryDir(category), filename);
  49. }
  50. function createRunDir(category, slug, date = new Date()) {
  51. const dir = path.join(
  52. categoryDir(category),
  53. dateStamp(date),
  54. `${timeStamp(date)}-${slugify(slug)}`
  55. );
  56. return ensureDir(dir);
  57. }
  58. function writeRunManifest(runDir, manifest = {}) {
  59. const filePath = path.join(runDir, 'manifest.json');
  60. const body = {
  61. createdAt: new Date().toISOString(),
  62. ...manifest,
  63. files: (manifest.files || []).map(file => path.relative(runDir, path.resolve(runDir, file)))
  64. };
  65. fs.writeFileSync(filePath, JSON.stringify(body, null, 2), 'utf8');
  66. return filePath;
  67. }
  68. module.exports = {
  69. PACKAGE_ROOT,
  70. OUTPUT_CATEGORIES,
  71. outputsRoot,
  72. ensureDir,
  73. slugify,
  74. dateStamp,
  75. timeStamp,
  76. categoryDir,
  77. latestPath,
  78. createRunDir,
  79. writeRunManifest
  80. };