frontend-guardian-core 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/bin/fg-core.js +1238 -0
  3. package/bin/watch-mode.js +123 -0
  4. package/dist/engine/cache.d.ts +68 -0
  5. package/dist/engine/cache.d.ts.map +1 -0
  6. package/dist/engine/cache.js +164 -0
  7. package/dist/engine/cache.js.map +1 -0
  8. package/dist/engine/rule-engine.d.ts +135 -0
  9. package/dist/engine/rule-engine.d.ts.map +1 -0
  10. package/dist/engine/rule-engine.js +716 -0
  11. package/dist/engine/rule-engine.js.map +1 -0
  12. package/dist/formatters/github-annotation.d.ts +36 -0
  13. package/dist/formatters/github-annotation.d.ts.map +1 -0
  14. package/dist/formatters/github-annotation.js +122 -0
  15. package/dist/formatters/github-annotation.js.map +1 -0
  16. package/dist/formatters/pr-comment.d.ts +43 -0
  17. package/dist/formatters/pr-comment.d.ts.map +1 -0
  18. package/dist/formatters/pr-comment.js +171 -0
  19. package/dist/formatters/pr-comment.js.map +1 -0
  20. package/dist/formatters/sarif.d.ts +104 -0
  21. package/dist/formatters/sarif.d.ts.map +1 -0
  22. package/dist/formatters/sarif.js +130 -0
  23. package/dist/formatters/sarif.js.map +1 -0
  24. package/dist/index.d.ts +46 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +108 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/integrations/base.d.ts +44 -0
  29. package/dist/integrations/base.d.ts.map +1 -0
  30. package/dist/integrations/base.js +104 -0
  31. package/dist/integrations/base.js.map +1 -0
  32. package/dist/integrations/eslint.d.ts +8 -0
  33. package/dist/integrations/eslint.d.ts.map +1 -0
  34. package/dist/integrations/eslint.js +67 -0
  35. package/dist/integrations/eslint.js.map +1 -0
  36. package/dist/integrations/formatter.d.ts +35 -0
  37. package/dist/integrations/formatter.d.ts.map +1 -0
  38. package/dist/integrations/formatter.js +182 -0
  39. package/dist/integrations/formatter.js.map +1 -0
  40. package/dist/integrations/index.d.ts +17 -0
  41. package/dist/integrations/index.d.ts.map +1 -0
  42. package/dist/integrations/index.js +25 -0
  43. package/dist/integrations/index.js.map +1 -0
  44. package/dist/integrations/stylelint.d.ts +8 -0
  45. package/dist/integrations/stylelint.d.ts.map +1 -0
  46. package/dist/integrations/stylelint.js +59 -0
  47. package/dist/integrations/stylelint.js.map +1 -0
  48. package/dist/integrations/typescript.d.ts +8 -0
  49. package/dist/integrations/typescript.d.ts.map +1 -0
  50. package/dist/integrations/typescript.js +92 -0
  51. package/dist/integrations/typescript.js.map +1 -0
  52. package/dist/rules/registry.d.ts +83 -0
  53. package/dist/rules/registry.d.ts.map +1 -0
  54. package/dist/rules/registry.js +205 -0
  55. package/dist/rules/registry.js.map +1 -0
  56. package/dist/scanners/a11y-scanner.d.ts +14 -0
  57. package/dist/scanners/a11y-scanner.d.ts.map +1 -0
  58. package/dist/scanners/a11y-scanner.js +781 -0
  59. package/dist/scanners/a11y-scanner.js.map +1 -0
  60. package/dist/scanners/component-scanner.d.ts +12 -0
  61. package/dist/scanners/component-scanner.d.ts.map +1 -0
  62. package/dist/scanners/component-scanner.js +304 -0
  63. package/dist/scanners/component-scanner.js.map +1 -0
  64. package/dist/scanners/cross-file-scanner.d.ts +18 -0
  65. package/dist/scanners/cross-file-scanner.d.ts.map +1 -0
  66. package/dist/scanners/cross-file-scanner.js +684 -0
  67. package/dist/scanners/cross-file-scanner.js.map +1 -0
  68. package/dist/scanners/hooks-scanner.d.ts +15 -0
  69. package/dist/scanners/hooks-scanner.d.ts.map +1 -0
  70. package/dist/scanners/hooks-scanner.js +670 -0
  71. package/dist/scanners/hooks-scanner.js.map +1 -0
  72. package/dist/scanners/i18n-scanner.d.ts +13 -0
  73. package/dist/scanners/i18n-scanner.d.ts.map +1 -0
  74. package/dist/scanners/i18n-scanner.js +535 -0
  75. package/dist/scanners/i18n-scanner.js.map +1 -0
  76. package/dist/scanners/naming-scanner.d.ts +19 -0
  77. package/dist/scanners/naming-scanner.d.ts.map +1 -0
  78. package/dist/scanners/naming-scanner.js +746 -0
  79. package/dist/scanners/naming-scanner.js.map +1 -0
  80. package/dist/scanners/performance-scanner.d.ts +7 -0
  81. package/dist/scanners/performance-scanner.d.ts.map +1 -0
  82. package/dist/scanners/performance-scanner.js +402 -0
  83. package/dist/scanners/performance-scanner.js.map +1 -0
  84. package/dist/scanners/platform-scanner.d.ts +15 -0
  85. package/dist/scanners/platform-scanner.d.ts.map +1 -0
  86. package/dist/scanners/platform-scanner.js +320 -0
  87. package/dist/scanners/platform-scanner.js.map +1 -0
  88. package/dist/scanners/security-scanner.d.ts +7 -0
  89. package/dist/scanners/security-scanner.d.ts.map +1 -0
  90. package/dist/scanners/security-scanner.js +349 -0
  91. package/dist/scanners/security-scanner.js.map +1 -0
  92. package/dist/scanners/svelte-scanner.d.ts +14 -0
  93. package/dist/scanners/svelte-scanner.d.ts.map +1 -0
  94. package/dist/scanners/svelte-scanner.js +228 -0
  95. package/dist/scanners/svelte-scanner.js.map +1 -0
  96. package/dist/types.d.ts +343 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +6 -0
  99. package/dist/types.js.map +1 -0
  100. package/dist/utils/ast-parser.d.ts +21 -0
  101. package/dist/utils/ast-parser.d.ts.map +1 -0
  102. package/dist/utils/ast-parser.js +119 -0
  103. package/dist/utils/ast-parser.js.map +1 -0
  104. package/dist/utils/baseline.d.ts +89 -0
  105. package/dist/utils/baseline.d.ts.map +1 -0
  106. package/dist/utils/baseline.js +156 -0
  107. package/dist/utils/baseline.js.map +1 -0
  108. package/dist/utils/ci-generator.d.ts +34 -0
  109. package/dist/utils/ci-generator.d.ts.map +1 -0
  110. package/dist/utils/ci-generator.js +194 -0
  111. package/dist/utils/ci-generator.js.map +1 -0
  112. package/dist/utils/common.d.ts +8 -0
  113. package/dist/utils/common.d.ts.map +1 -0
  114. package/dist/utils/common.js +38 -0
  115. package/dist/utils/common.js.map +1 -0
  116. package/dist/utils/concurrent.d.ts +16 -0
  117. package/dist/utils/concurrent.d.ts.map +1 -0
  118. package/dist/utils/concurrent.js +49 -0
  119. package/dist/utils/concurrent.js.map +1 -0
  120. package/dist/utils/config-loader.d.ts +8 -0
  121. package/dist/utils/config-loader.d.ts.map +1 -0
  122. package/dist/utils/config-loader.js +154 -0
  123. package/dist/utils/config-loader.js.map +1 -0
  124. package/dist/utils/fix-bot.d.ts +36 -0
  125. package/dist/utils/fix-bot.d.ts.map +1 -0
  126. package/dist/utils/fix-bot.js +274 -0
  127. package/dist/utils/fix-bot.js.map +1 -0
  128. package/dist/utils/git-hooks.d.ts +55 -0
  129. package/dist/utils/git-hooks.d.ts.map +1 -0
  130. package/dist/utils/git-hooks.js +318 -0
  131. package/dist/utils/git-hooks.js.map +1 -0
  132. package/dist/utils/history-report.d.ts +72 -0
  133. package/dist/utils/history-report.d.ts.map +1 -0
  134. package/dist/utils/history-report.js +144 -0
  135. package/dist/utils/history-report.js.map +1 -0
  136. package/dist/utils/init-config.d.ts +23 -0
  137. package/dist/utils/init-config.d.ts.map +1 -0
  138. package/dist/utils/init-config.js +146 -0
  139. package/dist/utils/init-config.js.map +1 -0
  140. package/dist/utils/pr-publisher.d.ts +64 -0
  141. package/dist/utils/pr-publisher.d.ts.map +1 -0
  142. package/dist/utils/pr-publisher.js +265 -0
  143. package/dist/utils/pr-publisher.js.map +1 -0
  144. package/dist/utils/project-detector.d.ts +20 -0
  145. package/dist/utils/project-detector.d.ts.map +1 -0
  146. package/dist/utils/project-detector.js +342 -0
  147. package/dist/utils/project-detector.js.map +1 -0
  148. package/dist/utils/report-uploader.d.ts +35 -0
  149. package/dist/utils/report-uploader.d.ts.map +1 -0
  150. package/dist/utils/report-uploader.js +106 -0
  151. package/dist/utils/report-uploader.js.map +1 -0
  152. package/package.json +78 -0
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ /**
3
+ * Baseline 管理器
4
+ *
5
+ * 支持已有问题不阻塞,仅关注新增问题的渐进式治理模式。
6
+ * 适用于遗留项目首次接入 frontend-guardian。
7
+ *
8
+ * 使用方式:
9
+ * 1. 首次运行:fg-core --baseline .fg-baseline.json --module all
10
+ * → 扫描全部问题并保存为 baseline 文件
11
+ * 2. 后续运行:fg-core --baseline .fg-baseline.json --module all
12
+ * → 仅报告新增问题(与 baseline 对比)
13
+ * 3. 定期刷新:删除 baseline 重新生成(清理已修复的遗留问题)
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.BaselineManager = void 0;
17
+ exports.toBaselineIssue = toBaselineIssue;
18
+ exports.loadBaseline = loadBaseline;
19
+ exports.saveBaseline = saveBaseline;
20
+ exports.compareWithBaseline = compareWithBaseline;
21
+ exports.generateBaseline = generateBaseline;
22
+ const node_fs_1 = require("node:fs");
23
+ const node_path_1 = require("node:path");
24
+ /** 问题匹配键 */
25
+ function issueKey(issue) {
26
+ // 列号可选,允许小范围偏移(±5列)视为同一问题
27
+ const col = issue.column != null ? Math.round(issue.column / 5) * 5 : 0;
28
+ return `${issue.file}|${issue.ruleId}|${issue.line}|${col}`;
29
+ }
30
+ /** 将 Issue 精简为 BaselineIssue */
31
+ function toBaselineIssue(issue) {
32
+ return {
33
+ file: issue.file,
34
+ ruleId: issue.ruleId,
35
+ line: issue.line,
36
+ column: issue.column,
37
+ severity: issue.severity,
38
+ title: issue.title,
39
+ };
40
+ }
41
+ /** 加载 baseline 文件 */
42
+ function loadBaseline(filePath) {
43
+ try {
44
+ if (!(0, node_fs_1.existsSync)(filePath)) {
45
+ return null;
46
+ }
47
+ const raw = (0, node_fs_1.readFileSync)(filePath, "utf-8");
48
+ const data = JSON.parse(raw);
49
+ // 版本校验
50
+ if (!data.version || !Array.isArray(data.issues)) {
51
+ return null;
52
+ }
53
+ return data;
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ /** 保存 baseline 文件 */
60
+ function saveBaseline(filePath, issues, meta) {
61
+ const baseline = {
62
+ version: "1.0",
63
+ generatedAt: Date.now(),
64
+ issues: issues.map(toBaselineIssue),
65
+ meta: {
66
+ toolVersion: "2.3.0",
67
+ ...meta,
68
+ },
69
+ };
70
+ (0, node_fs_1.writeFileSync)(filePath, JSON.stringify(baseline, null, 2), "utf-8");
71
+ }
72
+ /**
73
+ * 将当前扫描结果与 baseline 对比
74
+ * @param issues 当前扫描出的所有问题
75
+ * @param baselinePath baseline 文件路径(绝对或相对)
76
+ * @param projectDir 项目根目录(用于解析相对路径)
77
+ * @returns BaselineResult 对比结果
78
+ */
79
+ function compareWithBaseline(issues, baselinePath, projectDir) {
80
+ const resolvedPath = (0, node_path_1.resolve)(projectDir, baselinePath);
81
+ const baseline = loadBaseline(resolvedPath);
82
+ if (!baseline) {
83
+ // baseline 文件不存在,返回全部问题作为 newIssues
84
+ return {
85
+ newIssues: issues,
86
+ knownIssues: [],
87
+ fixedIssues: [],
88
+ totalIssues: issues.length,
89
+ baselineLoaded: false,
90
+ };
91
+ }
92
+ const baselineKeys = new Set(baseline.issues.map((i) => issueKey(i)));
93
+ const currentKeys = new Set(issues.map((i) => issueKey(i)));
94
+ const newIssues = [];
95
+ const knownIssues = [];
96
+ for (const issue of issues) {
97
+ if (baselineKeys.has(issueKey(issue))) {
98
+ knownIssues.push(issue);
99
+ }
100
+ else {
101
+ newIssues.push(issue);
102
+ }
103
+ }
104
+ const fixedIssues = baseline.issues.filter((i) => !currentKeys.has(issueKey(i)));
105
+ return {
106
+ newIssues,
107
+ knownIssues,
108
+ fixedIssues,
109
+ totalIssues: issues.length,
110
+ baselineLoaded: true,
111
+ };
112
+ }
113
+ /**
114
+ * 生成或更新 baseline 文件
115
+ * 如果文件已存在则覆盖
116
+ */
117
+ function generateBaseline(issues, baselinePath, projectDir, meta) {
118
+ const resolvedPath = (0, node_path_1.resolve)(projectDir, baselinePath);
119
+ saveBaseline(resolvedPath, issues, meta);
120
+ }
121
+ /**
122
+ * BaselineManager — 面向对象的封装
123
+ */
124
+ class BaselineManager {
125
+ baselinePath;
126
+ projectDir;
127
+ baseline = null;
128
+ constructor(baselinePath, projectDir) {
129
+ this.baselinePath = (0, node_path_1.resolve)(projectDir, baselinePath);
130
+ this.projectDir = projectDir;
131
+ this.baseline = loadBaseline(this.baselinePath);
132
+ }
133
+ /** 是否已加载有效的 baseline */
134
+ isLoaded() {
135
+ return this.baseline !== null;
136
+ }
137
+ /** 获取已加载的 baseline 内容 */
138
+ getBaseline() {
139
+ return this.baseline;
140
+ }
141
+ /** 对比当前 issues,返回仅含新增问题的过滤结果 */
142
+ filterNewIssues(issues) {
143
+ return compareWithBaseline(issues, this.baselinePath, this.projectDir);
144
+ }
145
+ /** 将当前 issues 保存为 baseline(覆盖) */
146
+ save(issues, meta) {
147
+ saveBaseline(this.baselinePath, issues, meta);
148
+ this.baseline = loadBaseline(this.baselinePath);
149
+ }
150
+ /** 获取 baseline 文件路径 */
151
+ getPath() {
152
+ return this.baselinePath;
153
+ }
154
+ }
155
+ exports.BaselineManager = BaselineManager;
156
+ //# sourceMappingURL=baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/utils/baseline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * CI 配置自动生成工具
3
+ * 一键生成 GitHub Actions / GitLab CI 配置文件
4
+ */
5
+ export type CIProvider = "github" | "gitlab" | "both";
6
+ export interface CIGeneratorOptions {
7
+ provider: CIProvider;
8
+ /** Node.js 版本 */
9
+ nodeVersion?: string;
10
+ /** 包管理器 */
11
+ packageManager?: "npm" | "yarn" | "pnpm";
12
+ /** 是否运行测试 */
13
+ runTests?: boolean;
14
+ /** 是否上传报告为 artifact */
15
+ uploadArtifact?: boolean;
16
+ /** 扫描参数 */
17
+ scanArgs?: string;
18
+ /** 门禁配置 */
19
+ gate?: boolean;
20
+ /** 是否在 MR/PR 中自动发布评论 */
21
+ postComment?: boolean;
22
+ }
23
+ /**
24
+ * 自动检测项目使用的 CI 平台
25
+ * 基于目录结构和 git remote URL 推断
26
+ */
27
+ export declare function detectCIProvider(projectDir: string): "github" | "gitlab";
28
+ /**
29
+ * 生成 CI 配置文件
30
+ */
31
+ export declare function generateCIConfig(projectDir: string, options: CIGeneratorOptions): {
32
+ created: string[];
33
+ };
34
+ //# sourceMappingURL=ci-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-generator.d.ts","sourceRoot":"","sources":["../../src/utils/ci-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,UAAU,CAAC;IACrB,iBAAiB;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,cAAc,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACzC,aAAa;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wBAAwB;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAuHD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CA+BxE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAyCvG"}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ /**
3
+ * CI 配置自动生成工具
4
+ * 一键生成 GitHub Actions / GitLab CI 配置文件
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.detectCIProvider = detectCIProvider;
8
+ exports.generateCIConfig = generateCIConfig;
9
+ const node_fs_1 = require("node:fs");
10
+ const node_path_1 = require("node:path");
11
+ const GITHUB_ACTIONS_TEMPLATE = `name: Frontend Guardian
12
+
13
+ on:
14
+ push:
15
+ branches: [main, master]
16
+ pull_request:
17
+ branches: [main, master]
18
+
19
+ jobs:
20
+ scan:
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: write
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ {{NODE_SETUP}}
28
+ {{INSTALL}}
29
+ {{TEST}}
30
+ - name: 🛡️ Frontend Guardian Scan
31
+ run: npx fg-core . --scan --gate --output fg-report.md{{ARGS}}
32
+ continue-on-error: true
33
+
34
+ - name: 💬 Post PR Comment
35
+ if: github.event_name == 'pull_request'
36
+ run: npx fg-core . --scan --post-comment{{ARGS}}
37
+ env:
38
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
39
+ continue-on-error: true
40
+
41
+ - name: 📊 Upload Report
42
+ if: always()
43
+ uses: actions/upload-artifact@v4
44
+ with:
45
+ name: frontend-guardian-report
46
+ path: fg-report.md
47
+
48
+ - name: 🚪 Gate Check
49
+ run: |
50
+ if [ -f fg-report.md ]; then
51
+ echo "报告已生成"
52
+ fi
53
+ # 如果扫描返回非 0 则失败
54
+ npx fg-core . --scan --gate{{ARGS}}
55
+ `;
56
+ const GITLAB_CI_TEMPLATE = `stages:
57
+ - test
58
+
59
+ variables:
60
+ NPM_CONFIG_CACHE: .npm
61
+
62
+ frontend-guardian-scan:
63
+ stage: test
64
+ image: node:{{NODE_VERSION}}-alpine
65
+ rules:
66
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
67
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
68
+ cache:
69
+ key:
70
+ files:
71
+ - {{LOCK_FILE}}
72
+ paths:
73
+ - .npm/
74
+ before_script:
75
+ {{INSTALL}}
76
+ script:
77
+ - npx fg-core . --scan --gate --output fg-report.md --post-comment{{ARGS}}
78
+ artifacts:
79
+ when: always
80
+ paths:
81
+ - fg-report.md
82
+ expire_in: 1 week
83
+ allow_failure: false
84
+ `;
85
+ function renderNodeSetup(pm) {
86
+ if (pm === "pnpm") {
87
+ return ` - uses: pnpm/action-setup@v2\n - uses: actions/setup-node@v4\n with:\n node-version: '{{NODE_VERSION}}'\n cache: 'pnpm'`;
88
+ }
89
+ return ` - uses: actions/setup-node@v4\n with:\n node-version: '{{NODE_VERSION}}'\n cache: '${pm}'`;
90
+ }
91
+ function renderInstall(pm) {
92
+ const cmds = {
93
+ npm: "npm ci",
94
+ yarn: "yarn install --frozen-lockfile",
95
+ pnpm: "pnpm install --frozen-lockfile",
96
+ };
97
+ const cmd = cmds[pm] || cmds.npm;
98
+ return ` - name: 📦 Install Dependencies\n run: ${cmd}`;
99
+ }
100
+ function renderTest(runTests) {
101
+ if (!runTests)
102
+ return "";
103
+ return ` - name: 🧪 Run Tests\n run: npm test\n`;
104
+ }
105
+ function renderGitlabInstall(pm) {
106
+ const cmds = {
107
+ npm: " - npm ci --cache .npm --prefer-offline",
108
+ yarn: " - yarn install --frozen-lockfile",
109
+ pnpm: " - npm install -g pnpm\n - pnpm install --frozen-lockfile",
110
+ };
111
+ return cmds[pm] || cmds.npm;
112
+ }
113
+ function renderLockFile(pm) {
114
+ const files = {
115
+ npm: "package-lock.json",
116
+ yarn: "yarn.lock",
117
+ pnpm: "pnpm-lock.yaml",
118
+ };
119
+ return files[pm] || files.npm;
120
+ }
121
+ /**
122
+ * 自动检测项目使用的 CI 平台
123
+ * 基于目录结构和 git remote URL 推断
124
+ */
125
+ function detectCIProvider(projectDir) {
126
+ // 1. 检查现有 CI 配置文件
127
+ if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(projectDir, ".gitlab-ci.yml"))) {
128
+ return "gitlab";
129
+ }
130
+ if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(projectDir, ".github", "workflows"))) {
131
+ return "github";
132
+ }
133
+ // 2. 检查 git remote URL
134
+ try {
135
+ const configPath = (0, node_path_1.resolve)(projectDir, ".git", "config");
136
+ if ((0, node_fs_1.existsSync)(configPath)) {
137
+ const config = (0, node_fs_1.readFileSync)(configPath, "utf-8");
138
+ const urlMatch = config.match(/\[remote "origin"\]\s*\n\s*url\s*=\s*(.+)/);
139
+ if (urlMatch) {
140
+ const remoteUrl = urlMatch[1].trim();
141
+ if (remoteUrl.includes("gitlab.com") || remoteUrl.includes("gitlab")) {
142
+ return "gitlab";
143
+ }
144
+ if (remoteUrl.includes("github.com") || remoteUrl.includes("github")) {
145
+ return "github";
146
+ }
147
+ }
148
+ }
149
+ }
150
+ catch {
151
+ // 读取失败,忽略
152
+ }
153
+ // 3. 默认 GitHub
154
+ return "github";
155
+ }
156
+ /**
157
+ * 生成 CI 配置文件
158
+ */
159
+ function generateCIConfig(projectDir, options) {
160
+ const created = [];
161
+ const nodeVersion = options.nodeVersion || "20";
162
+ const pm = options.packageManager || "npm";
163
+ const args = options.scanArgs ? ` ${options.scanArgs}` : "";
164
+ const providers = options.provider === "both" ? ["github", "gitlab"] : [options.provider];
165
+ for (const provider of providers) {
166
+ if (provider === "github") {
167
+ const workflowDir = (0, node_path_1.resolve)(projectDir, ".github", "workflows");
168
+ if (!(0, node_fs_1.existsSync)(workflowDir)) {
169
+ (0, node_fs_1.mkdirSync)(workflowDir, { recursive: true });
170
+ }
171
+ let content = GITHUB_ACTIONS_TEMPLATE;
172
+ content = content.replace("{{NODE_SETUP}}", renderNodeSetup(pm));
173
+ content = content.replace("{{INSTALL}}", renderInstall(pm));
174
+ content = content.replace("{{TEST}}", renderTest(options.runTests ?? false));
175
+ content = content.replace(/{{NODE_VERSION}}/g, nodeVersion);
176
+ content = content.replace(/{{ARGS}}/g, args);
177
+ const path = (0, node_path_1.resolve)(workflowDir, "frontend-guardian.yml");
178
+ (0, node_fs_1.writeFileSync)(path, content, "utf-8");
179
+ created.push(path);
180
+ }
181
+ if (provider === "gitlab") {
182
+ let content = GITLAB_CI_TEMPLATE;
183
+ content = content.replace(/{{NODE_VERSION}}/g, nodeVersion);
184
+ content = content.replace("{{INSTALL}}", renderGitlabInstall(pm));
185
+ content = content.replace(/{{LOCK_FILE}}/g, renderLockFile(pm));
186
+ content = content.replace(/{{ARGS}}/g, args);
187
+ const path = (0, node_path_1.resolve)(projectDir, ".gitlab-ci.yml");
188
+ (0, node_fs_1.writeFileSync)(path, content, "utf-8");
189
+ created.push(path);
190
+ }
191
+ }
192
+ return { created };
193
+ }
194
+ //# sourceMappingURL=ci-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-generator.js","sourceRoot":"","sources":["../../src/utils/ci-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * v2.1.0: 公共工具函数 — 从各 scanner 提取,消除代码重复
3
+ */
4
+ /** 从文件路径提取扩展名 */
5
+ export declare function getFileExt(filePath: string): string;
6
+ /** 从 JSX AST 节点提取标签名(支持 <Component.Sub />) */
7
+ export declare function getJSXTagName(name: any): string | null;
8
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,iBAAiB;AACjB,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAqBtD"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /**
3
+ * v2.1.0: 公共工具函数 — 从各 scanner 提取,消除代码重复
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getFileExt = getFileExt;
7
+ exports.getJSXTagName = getJSXTagName;
8
+ /** 从文件路径提取扩展名 */
9
+ function getFileExt(filePath) {
10
+ const match = filePath.match(/\.[^.]+$/);
11
+ return match ? match[0] : ".js";
12
+ }
13
+ /** 从 JSX AST 节点提取标签名(支持 <Component.Sub />) */
14
+ function getJSXTagName(name) {
15
+ if (name.type === "JSXIdentifier") {
16
+ return name.name;
17
+ }
18
+ if (name.type === "JSXMemberExpression") {
19
+ const parts = [];
20
+ let current = name;
21
+ while (current) {
22
+ if (current.type === "JSXIdentifier") {
23
+ parts.unshift(current.name);
24
+ break;
25
+ }
26
+ else if (current.type === "JSXMemberExpression") {
27
+ parts.unshift(current.property.name);
28
+ current = current.object;
29
+ }
30
+ else {
31
+ break;
32
+ }
33
+ }
34
+ return parts.join(".");
35
+ }
36
+ return null;
37
+ }
38
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAGH,gCAGC;AAGD,sCAqBC;AA5BD,iBAAiB;AACjB,SAAgB,UAAU,CAAC,QAAgB;IACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACpC,CAAC;AAED,8CAA8C;AAC9C,SAAgB,aAAa,CAAC,IAAS;IACnC,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;QACtC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,OAAO,OAAO,EAAE,CAAC;YACb,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACnC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM;YACV,CAAC;iBAAM,IAAI,OAAO,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;gBAChD,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACrC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACJ,MAAM;YACV,CAAC;QACL,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Concurrent execution utilities — 并发控制工具
3
+ *
4
+ * v2.1.0: 提供受控并发的 Promise.all 替代方案,避免大项目 OOM。
5
+ */
6
+ /** 获取合理的默认并发数(CPU 核心数) */
7
+ export declare function getDefaultConcurrency(): number;
8
+ /**
9
+ * 受控并发的 map 操作
10
+ * @param items 待处理数组
11
+ * @param concurrency 最大并发数
12
+ * @param fn 处理函数
13
+ * @returns 按原顺序的结果数组
14
+ */
15
+ export declare function concurrentMap<T, R>(items: T[], concurrency: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
16
+ //# sourceMappingURL=concurrent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrent.d.ts","sourceRoot":"","sources":["../../src/utils/concurrent.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,0BAA0B;AAC1B,wBAAgB,qBAAqB,IAAI,MAAM,CAM9C;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,EACpC,KAAK,EAAE,CAAC,EAAE,EACV,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3C,OAAO,CAAC,CAAC,EAAE,CAAC,CAuBd"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * Concurrent execution utilities — 并发控制工具
4
+ *
5
+ * v2.1.0: 提供受控并发的 Promise.all 替代方案,避免大项目 OOM。
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.getDefaultConcurrency = getDefaultConcurrency;
9
+ exports.concurrentMap = concurrentMap;
10
+ const node_os_1 = require("node:os");
11
+ /** 获取合理的默认并发数(CPU 核心数) */
12
+ function getDefaultConcurrency() {
13
+ try {
14
+ return (0, node_os_1.availableParallelism)();
15
+ }
16
+ catch {
17
+ return 4;
18
+ }
19
+ }
20
+ /**
21
+ * 受控并发的 map 操作
22
+ * @param items 待处理数组
23
+ * @param concurrency 最大并发数
24
+ * @param fn 处理函数
25
+ * @returns 按原顺序的结果数组
26
+ */
27
+ async function concurrentMap(items, concurrency, fn) {
28
+ if (items.length === 0)
29
+ return [];
30
+ const results = new Array(items.length);
31
+ let index = 0;
32
+ let error = null;
33
+ async function worker() {
34
+ while (index < items.length && !error) {
35
+ const currentIndex = index++;
36
+ try {
37
+ results[currentIndex] = await fn(items[currentIndex], currentIndex);
38
+ }
39
+ catch (err) {
40
+ error = err;
41
+ throw err;
42
+ }
43
+ }
44
+ }
45
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
46
+ await Promise.all(workers);
47
+ return results;
48
+ }
49
+ //# sourceMappingURL=concurrent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrent.js","sourceRoot":"","sources":["../../src/utils/concurrent.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAKH,sDAMC;AASD,sCA2BC;AA7CD,qCAA+C;AAE/C,0BAA0B;AAC1B,SAAgB,qBAAqB;IACjC,IAAI,CAAC;QACD,OAAO,IAAA,8BAAoB,GAAE,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,CAAC;IACb,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,aAAa,CAC/B,KAAU,EACV,WAAmB,EACnB,EAA0C;IAE1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,OAAO,GAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAY,IAAI,CAAC;IAE1B,KAAK,UAAU,MAAM;QACjB,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACpC,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACD,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC;YACxE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,KAAK,GAAG,GAAG,CAAC;gBACZ,MAAM,GAAG,CAAC;YACd,CAAC;QACL,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5F,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAE3B,OAAO,OAAO,CAAC;AACnB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 配置文件加载工具
3
+ * 支持 .frontend-guardian.yml 和 .frontend-guardian.json
4
+ * 支持 extends 继承组织级基线配置
5
+ */
6
+ import type { ProjectConfig } from "../types.js";
7
+ export declare function loadConfig(projectDir: string, configFile?: string): ProjectConfig;
8
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,YAAY,CAAC;AAE5D,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,aAAa,CAkCjF"}