File size: 2,929 Bytes
e1ae2c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const fs = require('fs');
const path = require('path');
const { execFileSync } = require('child_process');

/**
 * 解析页面配置文件路径(优先 user,回退 _default)
 * 注意:仅用于构建期读取文件元信息,不会把路径注入到页面/扩展配置中。
 * @param {string} pageId 页面ID(与 pages/<id>.yml 文件名对应)
 * @returns {string|null} 文件路径或 null
 */
function resolvePageConfigFilePath(pageId) {
  if (!pageId) return null;

  const candidates = [
    path.join(process.cwd(), 'config', 'user', 'pages', `${pageId}.yml`),
    path.join(process.cwd(), 'config', 'user', 'pages', `${pageId}.yaml`),
    path.join(process.cwd(), 'config', '_default', 'pages', `${pageId}.yml`),
    path.join(process.cwd(), 'config', '_default', 'pages', `${pageId}.yaml`),
  ];

  for (const filePath of candidates) {
    try {
      if (fs.existsSync(filePath)) return filePath;
    } catch (e) {
      // 忽略 IO 异常,继续尝试下一个候选
    }
  }

  return null;
}

/**
 * 尝试获取文件最后一次 git 提交时间(ISO 字符串)
 * @param {string} filePath 文件路径
 * @returns {string|null} ISO 字符串(UTC),失败返回 null
 */
function tryGetGitLastCommitIso(filePath) {
  if (!filePath) return null;

  try {
    const relativePath = path.relative(process.cwd(), filePath).replace(/\\/g, '/');
    const output = execFileSync('git', ['log', '-1', '--format=%cI', '--', relativePath], {
      encoding: 'utf8',
      stdio: ['ignore', 'pipe', 'ignore'],
    });
    const raw = String(output || '').trim();
    if (!raw) return null;

    const date = new Date(raw);
    if (Number.isNaN(date.getTime())) return null;

    return date.toISOString();
  } catch (e) {
    return null;
  }
}

/**
 * 获取文件 mtime(ISO 字符串)
 * @param {string} filePath 文件路径
 * @returns {string|null} ISO 字符串(UTC),失败返回 null
 */
function tryGetFileMtimeIso(filePath) {
  if (!filePath) return null;

  try {
    const stats = fs.statSync(filePath);
    const mtime = stats && stats.mtime ? stats.mtime : null;
    if (!(mtime instanceof Date) || Number.isNaN(mtime.getTime())) return null;
    return mtime.toISOString();
  } catch (e) {
    return null;
  }
}

/**
 * 计算页面配置文件“内容更新时间”(优先 git,回退 mtime)
 * @param {string} pageId 页面ID
 * @returns {{updatedAt: string, updatedAtSource: 'git'|'mtime'}|null}
 */
function getPageConfigUpdatedAtMeta(pageId) {
  const filePath = resolvePageConfigFilePath(pageId);
  if (!filePath) return null;

  const gitIso = tryGetGitLastCommitIso(filePath);
  if (gitIso) {
    return { updatedAt: gitIso, updatedAtSource: 'git' };
  }

  const mtimeIso = tryGetFileMtimeIso(filePath);
  if (mtimeIso) {
    return { updatedAt: mtimeIso, updatedAtSource: 'mtime' };
  }

  return null;
}

module.exports = {
  getPageConfigUpdatedAtMeta,
};