@playcraft/devkit 1.0.31-beta.11 → 1.0.31-beta.14

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 (101) hide show
  1. package/cli/bin/playable-scripts.js +6 -53
  2. package/cli/commands/build.js +32 -241
  3. package/cli/commands/builds.js +2 -13
  4. package/cli/commands/dev.js +1 -22
  5. package/cli/commands/pack.js +40 -320
  6. package/cli/commands/vite-dev.js +1 -7
  7. package/core/artifacts/emit-fonts.test.js +1 -0
  8. package/core/artifacts/emit.js +4 -98
  9. package/core/artifacts/fflate.js +1 -31
  10. package/core/artifacts/zip.js +1 -39
  11. package/core/batch-build.js +147 -1261
  12. package/core/constants.js +2 -20
  13. package/core/cos-uploader.js +23 -289
  14. package/core/engines/cocos/adapter-vfs-path.test.js +1 -0
  15. package/core/engines/cocos/clean-cache.js +5 -179
  16. package/core/engines/cocos/clean-cache.test.js +1 -75
  17. package/core/engines/cocos/cli-build.js +2 -116
  18. package/core/engines/cocos/cli.js +11 -38
  19. package/core/engines/cocos/constants.js +1 -21
  20. package/core/engines/cocos/creator-cli.js +1 -108
  21. package/core/engines/cocos/dev-server.js +4 -412
  22. package/core/engines/cocos/fs.js +1 -105
  23. package/core/engines/cocos/injects/3x/init.js +19 -438
  24. package/core/engines/cocos/injects/3x/main.js +2 -52
  25. package/core/engines/cocos/injects/libs/pako.js +1 -2
  26. package/core/engines/cocos/mcp-refresh.js +2 -76
  27. package/core/engines/cocos/merge-inline.test.js +1 -0
  28. package/core/engines/cocos/merge.js +9 -148
  29. package/core/engines/cocos/omit-playable-weight.js +10 -0
  30. package/core/engines/cocos/omit-playable-weight.test.js +2 -0
  31. package/core/engines/cocos/pack.js +1 -187
  32. package/core/engines/cocos/preview-cache.js +2 -48
  33. package/core/engines/cocos/preview-cache.test.js +1 -32
  34. package/core/engines/cocos/preview-concat.js +6 -189
  35. package/core/engines/cocos/preview-concat.test.js +1 -73
  36. package/core/engines/cocos/preview-json-hook.js +1 -200
  37. package/core/engines/cocos/preview-json-pack.js +3 -376
  38. package/core/engines/cocos/preview-json-pack.test.js +2 -226
  39. package/core/engines/cocos/preview-proxy.js +1 -132
  40. package/core/engines/cocos/rebundle-preview.js +2 -54
  41. package/core/engines/cocos/strip-social-share.js +3 -115
  42. package/core/engines/cocos/theme-assets.js +2 -161
  43. package/core/engines/cocos/theme-levels.js +1 -0
  44. package/core/engines/cocos/writable-cli.js +2 -248
  45. package/core/engines/cocos/writable-cli.test.js +1 -112
  46. package/core/engines/web/index.js +1 -20
  47. package/core/engines/web/vite.dev.js +17 -322
  48. package/core/engines/web/webpack.build.js +37 -522
  49. package/core/engines/web/webpack.common.js +11 -177
  50. package/core/engines/web/webpack.dev.js +6 -88
  51. package/core/index.js +7 -101
  52. package/core/injectors/apply.js +1 -94
  53. package/core/injectors/check-channel-matrix.js +2 -130
  54. package/core/injectors/spec.js +10 -217
  55. package/core/loaders/gltf-loader.js +28 -74
  56. package/core/options.js +16 -353
  57. package/core/plugins/AdikteevInjectorPlugin.js +4 -26
  58. package/core/plugins/BigoAdsInjectorPlugin.js +4 -21
  59. package/core/plugins/DAPIInjectorPlugin.js +2 -25
  60. package/core/plugins/DebuggerInjectionPlugin.js +3 -31
  61. package/core/plugins/ExitAPIInjectorPlugin.js +3 -56
  62. package/core/plugins/FflateCompressionPlugin.js +160 -307
  63. package/core/plugins/FflateCompressionPlugin.test.js +13 -0
  64. package/core/plugins/FontInjectionWebpackPlugin.js +4 -46
  65. package/core/plugins/LiftoffInjectorPlugin.js +4 -26
  66. package/core/plugins/MRAIDInjectorPlugin.js +2 -24
  67. package/core/plugins/MintegralInjectorPlugin.js +2 -25
  68. package/core/plugins/PangleInjectorPlugin.js +2 -24
  69. package/core/plugins/PlaycraftOrientationInjectorPlugin.js +3 -29
  70. package/core/plugins/SnapchatInjectorPlugin.js +4 -26
  71. package/core/plugins/SocialMediaInjectorPlugin.js +7 -119
  72. package/core/plugins/TikTokInjectorPlugin.js +2 -24
  73. package/core/plugins/UnityInjectorPlugin.js +8 -37
  74. package/core/plugins/ZipPlugin.js +20 -154
  75. package/core/plugins/socialMediaVitePlugin.js +2 -108
  76. package/core/utils/buildDefines.js +2 -30
  77. package/core/utils/buildTemplateString.js +5 -39
  78. package/core/utils/date.js +1 -16
  79. package/core/utils/fontRegistry.js +13 -81
  80. package/core/utils/fontResolver.js +37 -335
  81. package/core/utils/generateAdikteevHtmlWebpackPluginConfig.js +8 -42
  82. package/core/utils/generateBigabidHtmlWebpackPluginConfig.js +3 -30
  83. package/core/utils/generateInMobiHtmlWebpackPluginConfig.js +7 -43
  84. package/core/utils/getPlaycraftOrientationSuffix.js +2 -9
  85. package/core/utils/injectSDKPlugins.js +13 -68
  86. package/core/utils/logOptions.js +5 -46
  87. package/core/utils/mergeOptions.js +2 -21
  88. package/core/utils/obfuscateLevels.js +14 -0
  89. package/core/utils/obfuscateLevels.test.js +10 -0
  90. package/core/utils/parseArgvOptions.js +5 -125
  91. package/core/utils/resolveChannelFold2Zip.js +3 -15
  92. package/core/utils/validateThemeData.js +26 -227
  93. package/core/validators/pre-build-checker.js +25 -287
  94. package/core/validators/tracking-validator.js +40 -441
  95. package/core/validators/tracking-validator.test.js +2 -84
  96. package/core/vite.dev.js +1 -1
  97. package/core/webpack.build.js +1 -1
  98. package/core/webpack.common.js +1 -1
  99. package/core/webpack.dev.js +1 -1
  100. package/package.json +2 -3
  101. package/README.md +0 -262
@@ -1,9 +1,6 @@
1
- const { validateTracking, printValidationResult } = require('./tracking-validator.js');
2
-
3
- // ============================================================
1
+ "use strict";const{validateTracking,printValidationResult}=require("./tracking-validator.js");// ============================================================
4
2
  // 检查器注册表
5
3
  // ============================================================
6
-
7
4
  /**
8
5
  * 检查器定义
9
6
  * @typedef {Object} Checker
@@ -11,53 +8,21 @@ const { validateTracking, printValidationResult } = require('./tracking-validato
11
8
  * @property {string} description - 检查器描述
12
9
  * @property {boolean} enabled - 是否启用
13
10
  * @property {(projectRoot: string, options: any) => Promise<CheckResult>|CheckResult} validator - 验证函数
14
- */
15
-
16
- /**
11
+ *//**
17
12
  * 检查结果
18
13
  * @typedef {Object} CheckResult
19
14
  * @property {boolean} success - 是否通过
20
15
  * @property {string} message - 结果消息
21
16
  * @property {any} [data] - 额外数据
22
- */
23
-
24
- /**
17
+ *//**
25
18
  * 所有注册的检查器
26
19
  * @type {Map<string, Checker>}
27
- */
28
- const checkers = new Map();
29
-
30
- // ============================================================
20
+ */const checkers=new Map;// ============================================================
31
21
  // 内置检查器
32
22
  // ============================================================
33
-
34
23
  /**
35
24
  * 埋点验证检查器
36
- */
37
- checkers.set('tracking', {
38
- name: '埋点验证',
39
- description: '验证项目中是否正确调用了所有必须的埋点方法',
40
- enabled: true,
41
- validator: (projectRoot, options = {}) => {
42
- const result = validateTracking(projectRoot, {
43
- verbose: options.verbose || false,
44
- extensions: options.extensions,
45
- excludeDirs: options.excludeDirs,
46
- engine: options.engine,
47
- scanDirs: options.scanDirs,
48
- });
49
-
50
- return {
51
- success: result.success,
52
- message: result.success
53
- ? '✅ 埋点验证通过'
54
- : `❌ 埋点验证失败:缺少 ${result.errors.length} 个必须的埋点方法`,
55
- data: result
56
- };
57
- }
58
- });
59
-
60
- /**
25
+ */checkers.set("tracking",{name:"\u57CB\u70B9\u9A8C\u8BC1",description:"\u9A8C\u8BC1\u9879\u76EE\u4E2D\u662F\u5426\u6B63\u786E\u8C03\u7528\u4E86\u6240\u6709\u5FC5\u987B\u7684\u57CB\u70B9\u65B9\u6CD5",enabled:true,validator:(projectRoot,options={})=>{const result=validateTracking(projectRoot,{verbose:options.verbose||false,extensions:options.extensions,excludeDirs:options.excludeDirs,engine:options.engine,scanDirs:options.scanDirs});return{success:result.success,message:result.success?"\u2705 \u57CB\u70B9\u9A8C\u8BC1\u901A\u8FC7":`❌ 埋点验证失败:缺少 ${result.errors.length} 个必须的埋点方法`,data:result}}});/**
61
26
  * 主题名称检查器
62
27
  * 校验本次构建涉及的主题名称长度是否超过限制(不超过 50 个字符)。
63
28
  * 主题名称过长可能导致下游文件名 / 目录名 / COS Key 超出系统或第三方平台限制。
@@ -68,90 +33,10 @@ checkers.set('tracking', {
68
33
  * 渠道名可能带有锁定 UI 等后缀变体(如 google_L / google_P),
69
34
  * 因此必须以传入的 options.channels 实际渠道列表为准逐一比对,
70
35
  * 而不能只校验主题名称本身。
71
- */
72
- checkers.set('themeName', {
73
- name: '主题名称检查',
74
- description: '验证主题名称、以及「主题名_渠道名」组合后的长度是否超过限制(不超过 50 个字符)',
75
- enabled: true,
76
- validator: (projectRoot, options = {}) => {
77
- const MAX_LENGTH = 50;
78
- const themeNames = Array.isArray(options.themes)
79
- ? options.themes.filter(name => typeof name === 'string' && name.length > 0)
80
- : [];
81
- const channelNames = Array.isArray(options.channels)
82
- ? options.channels.filter(name => typeof name === 'string' && name.length > 0)
83
- : [];
84
-
85
- if (themeNames.length === 0) {
86
- return {
87
- success: true,
88
- message: 'ℹ️ 未提供主题名称,跳过主题名称检查'
89
- };
90
- }
91
-
92
- // 情况一:主题名称自身已超过限制(拼不拼渠道名都会超)
93
- const bareInvalidThemes = themeNames.filter(name => name.length > MAX_LENGTH);
94
- const bareInvalidThemeSet = new Set(bareInvalidThemes);
95
-
96
- // 情况二:主题名称自身未超限,但拼接渠道名(含锁定 UI 后缀,如 google_L / google_P)后超限
97
- const combinedViolations = [];
98
- if (channelNames.length > 0) {
99
- themeNames.forEach(theme => {
100
- if (bareInvalidThemeSet.has(theme)) return; // 已在情况一中报告,避免重复
101
-
102
- channelNames.forEach(channel => {
103
- const combined = `${theme}_${channel}`;
104
- if (combined.length > MAX_LENGTH) {
105
- combinedViolations.push({
106
- theme,
107
- channel,
108
- combined,
109
- length: combined.length,
110
- exceededBy: combined.length - MAX_LENGTH
111
- });
112
- }
113
- });
114
- });
115
- }
116
-
117
- if (bareInvalidThemes.length === 0 && combinedViolations.length === 0) {
118
- return {
119
- success: true,
120
- message: channelNames.length > 0
121
- ? `✅ 主题名称检查通过(共 ${themeNames.length} 个主题 × ${channelNames.length} 个渠道,「主题名_渠道名」组合均未超过 ${MAX_LENGTH} 个字符)`
122
- : `✅ 主题名称检查通过(共 ${themeNames.length} 个主题,均未超过 ${MAX_LENGTH} 个字符)`
123
- };
124
- }
125
-
126
- const lines = [];
127
-
128
- if (bareInvalidThemes.length > 0) {
129
- lines.push('主题名称自身已超过长度限制:');
130
- bareInvalidThemes.forEach(name => {
131
- lines.push(` - "${name}" (${name.length} 个字符,超出 ${name.length - MAX_LENGTH} 个字符)`);
132
- });
133
- }
134
-
135
- if (combinedViolations.length > 0) {
136
- lines.push('主题名称本身未超限,但与渠道名拼接后(zip 文件名)超过长度限制:');
137
- combinedViolations.forEach(v => {
138
- lines.push(
139
- ` - 主题 "${v.theme}" + 渠道 "${v.channel}" → "${v.combined}" ` +
140
- `(${v.length} 个字符,超出 ${v.exceededBy} 个字符)`
141
- );
142
- });
143
- lines.push(' 提示:部分渠道可能带有锁定 UI 后缀(如 google_L / google_P),拼接后长度会更长,请一并纳入考量。');
144
- }
145
-
146
- return {
147
- success: false,
148
- message: `❌ 主题名称检查失败:\n${lines.join('\n')}`,
149
- data: { bareInvalidThemes, combinedViolations, maxLength: MAX_LENGTH }
150
- };
151
- }
152
- });
153
-
154
- // 预留:未来可添加更多检查器
36
+ */checkers.set("themeName",{name:"\u4E3B\u9898\u540D\u79F0\u68C0\u67E5",description:"\u9A8C\u8BC1\u4E3B\u9898\u540D\u79F0\u3001\u4EE5\u53CA\u300C\u4E3B\u9898\u540D_\u6E20\u9053\u540D\u300D\u7EC4\u5408\u540E\u7684\u957F\u5EA6\u662F\u5426\u8D85\u8FC7\u9650\u5236\uFF08\u4E0D\u8D85\u8FC7 50 \u4E2A\u5B57\u7B26\uFF09",enabled:true,validator:(projectRoot,options={})=>{const MAX_LENGTH=50;const themeNames=Array.isArray(options.themes)?options.themes.filter(name=>typeof name==="string"&&name.length>0):[];const channelNames=Array.isArray(options.channels)?options.channels.filter(name=>typeof name==="string"&&name.length>0):[];if(themeNames.length===0){return{success:true,message:"\u2139\uFE0F \u672A\u63D0\u4F9B\u4E3B\u9898\u540D\u79F0\uFF0C\u8DF3\u8FC7\u4E3B\u9898\u540D\u79F0\u68C0\u67E5"}}// 情况一:主题名称自身已超过限制(拼不拼渠道名都会超)
37
+ const bareInvalidThemes=themeNames.filter(name=>name.length>MAX_LENGTH);const bareInvalidThemeSet=new Set(bareInvalidThemes);// 情况二:主题名称自身未超限,但拼接渠道名(含锁定 UI 后缀,如 google_L / google_P)后超限
38
+ const combinedViolations=[];if(channelNames.length>0){themeNames.forEach(theme=>{if(bareInvalidThemeSet.has(theme))return;// 已在情况一中报告,避免重复
39
+ channelNames.forEach(channel=>{const combined=`${theme}_${channel}`;if(combined.length>MAX_LENGTH){combinedViolations.push({theme,channel,combined,length:combined.length,exceededBy:combined.length-MAX_LENGTH})}})})}if(bareInvalidThemes.length===0&&combinedViolations.length===0){return{success:true,message:channelNames.length>0?`✅ 主题名称检查通过(共 ${themeNames.length} 个主题 × ${channelNames.length} 个渠道,「主题名_渠道名」组合均未超过 ${MAX_LENGTH} 个字符)`:`✅ 主题名称检查通过(共 ${themeNames.length} 个主题,均未超过 ${MAX_LENGTH} 个字符)`}}const lines=[];if(bareInvalidThemes.length>0){lines.push("\u4E3B\u9898\u540D\u79F0\u81EA\u8EAB\u5DF2\u8D85\u8FC7\u957F\u5EA6\u9650\u5236\uFF1A");bareInvalidThemes.forEach(name=>{lines.push(` - "${name}" (${name.length} 个字符,超出 ${name.length-MAX_LENGTH} 个字符)`)})}if(combinedViolations.length>0){lines.push("\u4E3B\u9898\u540D\u79F0\u672C\u8EAB\u672A\u8D85\u9650\uFF0C\u4F46\u4E0E\u6E20\u9053\u540D\u62FC\u63A5\u540E\uFF08zip \u6587\u4EF6\u540D\uFF09\u8D85\u8FC7\u957F\u5EA6\u9650\u5236\uFF1A");combinedViolations.forEach(v=>{lines.push(` - 主题 "${v.theme}" + 渠道 "${v.channel}" → "${v.combined}" `+`(${v.length} 个字符,超出 ${v.exceededBy} 个字符)`)});lines.push(" \u63D0\u793A\uFF1A\u90E8\u5206\u6E20\u9053\u53EF\u80FD\u5E26\u6709\u9501\u5B9A UI \u540E\u7F00\uFF08\u5982 google_L / google_P\uFF09\uFF0C\u62FC\u63A5\u540E\u957F\u5EA6\u4F1A\u66F4\u957F\uFF0C\u8BF7\u4E00\u5E76\u7EB3\u5165\u8003\u91CF\u3002")}return{success:false,message:`❌ 主题名称检查失败:\n${lines.join("\n")}`,data:{bareInvalidThemes,combinedViolations,maxLength:MAX_LENGTH}}}});// 预留:未来可添加更多检查器
155
40
  // checkers.set('assets', {
156
41
  // name: '资源检查',
157
42
  // description: '验证项目资源文件的完整性和规范性',
@@ -161,7 +46,6 @@ checkers.set('themeName', {
161
46
  // return { success: true, message: '资源检查通过' };
162
47
  // }
163
48
  // });
164
-
165
49
  // checkers.set('config', {
166
50
  // name: '配置检查',
167
51
  // description: '验证项目配置文件的正确性',
@@ -171,54 +55,23 @@ checkers.set('themeName', {
171
55
  // return { success: true, message: '配置检查通过' };
172
56
  // }
173
57
  // });
174
-
175
58
  // ============================================================
176
59
  // 检查器管理
177
60
  // ============================================================
178
-
179
61
  /**
180
62
  * 注册自定义检查器
181
63
  * @param {string} id - 检查器 ID
182
64
  * @param {Checker} checker - 检查器配置
183
- */
184
- function registerChecker(id, checker) {
185
- if (checkers.has(id)) {
186
- console.warn(`[警告] 检查器 "${id}" 已存在,将被覆盖`);
187
- }
188
- checkers.set(id, checker);
189
- }
190
-
191
- /**
65
+ */function registerChecker(id,checker){if(checkers.has(id)){console.warn(`[警告] 检查器 "${id}" 已存在,将被覆盖`)}checkers.set(id,checker)}/**
192
66
  * 启用/禁用检查器
193
67
  * @param {string} id - 检查器 ID
194
68
  * @param {boolean} enabled - 是否启用
195
- */
196
- function toggleChecker(id, enabled) {
197
- const checker = checkers.get(id);
198
- if (checker) {
199
- checker.enabled = enabled;
200
- } else {
201
- console.warn(`[警告] 未找到检查器: ${id}`);
202
- }
203
- }
204
-
205
- /**
69
+ */function toggleChecker(id,enabled){const checker=checkers.get(id);if(checker){checker.enabled=enabled}else{console.warn(`[警告] 未找到检查器: ${id}`)}}/**
206
70
  * 获取所有检查器列表
207
71
  * @returns {Array<{id: string, name: string, description: string, enabled: boolean}>}
208
- */
209
- function listCheckers() {
210
- return Array.from(checkers.entries()).map(([id, checker]) => ({
211
- id,
212
- name: checker.name,
213
- description: checker.description,
214
- enabled: checker.enabled
215
- }));
216
- }
217
-
218
- // ============================================================
72
+ */function listCheckers(){return Array.from(checkers.entries()).map(([id,checker])=>({id,name:checker.name,description:checker.description,enabled:checker.enabled}))}// ============================================================
219
73
  // 执行检查
220
74
  // ============================================================
221
-
222
75
  /**
223
76
  * 执行所有已启用的检查器
224
77
  * @param {string} projectRoot - 项目根目录
@@ -231,137 +84,22 @@ function listCheckers() {
231
84
  * @param {string[]} [options.themes] - 本次构建涉及的主题名称列表(供 themeName 检查器使用)
232
85
  * @param {string[]} [options.channels] - 本次构建涉及的渠道名称列表(供 themeName 检查器校验「主题名_渠道名」组合长度,可包含锁定 UI 后缀如 google_L / google_P)
233
86
  * @returns {Promise<{success: boolean, results: Map<string, CheckResult>}>}
234
- */
235
- async function runPreBuildChecks(projectRoot, options = {}) {
236
- const {
237
- only = [],
238
- skip = [],
239
- verbose = false,
240
- showDetails = true,
241
- failFast = false
242
- } = options;
243
-
244
- const results = new Map();
245
- let allSuccess = true;
246
-
247
- console.log('\n' + '═'.repeat(70));
248
- console.log('🔍 编译前检查');
249
- console.log('═'.repeat(70));
250
-
251
- // 确定要执行的检查器
252
- let checkersToRun = Array.from(checkers.entries()).filter(([id, checker]) => {
253
- // 如果指定了 only,只运行指定的
254
- if (only.length > 0 && !only.includes(id)) return false;
255
- // 跳过 skip 列表中的
256
- if (skip.includes(id)) return false;
257
- // 只运行启用的
258
- return checker.enabled;
259
- });
260
-
261
- if (checkersToRun.length === 0) {
262
- console.log('\n⚠️ 没有启用的检查器');
263
- console.log('═'.repeat(70) + '\n');
264
- return { success: true, results };
265
- }
266
-
267
- if (verbose) {
268
- console.log(`\n📋 将执行 ${checkersToRun.length} 个检查器:`);
269
- checkersToRun.forEach(([id, checker]) => {
270
- console.log(` - ${checker.name} (${id})`);
271
- });
272
- console.log('');
273
- }
274
-
275
- // 执行检查器
276
- for (const [id, checker] of checkersToRun) {
277
- try {
278
- console.log(`\n▶️ 执行检查: ${checker.name}`);
279
- console.log('-'.repeat(70));
280
-
281
- const result = await Promise.resolve(checker.validator(projectRoot, options));
282
- results.set(id, result);
283
-
284
- console.log(result.message);
285
-
286
- // 详细输出(针对埋点验证)
287
- if (showDetails && id === 'tracking' && result.data) {
288
- printValidationResult(result.data, showDetails);
289
- }
290
-
291
- if (!result.success) {
292
- allSuccess = false;
293
- if (failFast) {
294
- console.log('\n⚠️ failFast 模式:检测到失败,终止后续检查');
295
- break;
296
- }
297
- }
298
-
299
- } catch (error) {
300
- console.error(`\n❌ 检查器 "${checker.name}" 执行失败:`, error.message);
301
- results.set(id, {
302
- success: false,
303
- message: `执行出错: ${error.message}`,
304
- error
305
- });
306
- allSuccess = false;
307
-
308
- if (failFast) break;
309
- }
310
- }
311
-
312
- // 总结
313
- console.log('\n' + '═'.repeat(70));
314
- console.log('📊 检查总结');
315
- console.log('═'.repeat(70));
316
-
317
- const successCount = Array.from(results.values()).filter(r => r.success).length;
318
- const totalCount = results.size;
319
-
320
- console.log(`\n通过: ${successCount}/${totalCount}`);
321
-
322
- if (allSuccess) {
323
- console.log('\n✅ 所有检查通过,可以继续编译!');
324
- } else {
325
- console.log('\n❌ 部分检查失败,请修复后再编译。');
326
- }
327
-
328
- console.log('═'.repeat(70) + '\n');
329
-
330
- return {
331
- success: allSuccess,
332
- results
333
- };
334
- }
335
-
336
- /**
87
+ */async function runPreBuildChecks(projectRoot,options={}){const{only=[],skip=[],verbose=false,showDetails=true,failFast=false}=options;const results=new Map;let allSuccess=true;console.log("\n"+"\u2550".repeat(70));console.log("\uD83D\uDD0D \u7F16\u8BD1\u524D\u68C0\u67E5");console.log("\u2550".repeat(70));// 确定要执行的检查器
88
+ let checkersToRun=Array.from(checkers.entries()).filter(([id,checker])=>{// 如果指定了 only,只运行指定的
89
+ if(only.length>0&&!only.includes(id))return false;// 跳过 skip 列表中的
90
+ if(skip.includes(id))return false;// 只运行启用的
91
+ return checker.enabled});if(checkersToRun.length===0){console.log("\n\u26A0\uFE0F \u6CA1\u6709\u542F\u7528\u7684\u68C0\u67E5\u5668");console.log("\u2550".repeat(70)+"\n");return{success:true,results}}if(verbose){console.log(`\n📋 将执行 ${checkersToRun.length} 个检查器:`);checkersToRun.forEach(([id,checker])=>{console.log(` - ${checker.name} (${id})`)});console.log("")}// 执行检查器
92
+ for(const[id,checker]of checkersToRun){try{console.log(`\n▶️ 执行检查: ${checker.name}`);console.log("-".repeat(70));const result=await Promise.resolve(checker.validator(projectRoot,options));results.set(id,result);console.log(result.message);// 详细输出(针对埋点验证)
93
+ if(showDetails&&id==="tracking"&&result.data){printValidationResult(result.data,showDetails)}if(!result.success){allSuccess=false;if(failFast){console.log("\n\u26A0\uFE0F failFast \u6A21\u5F0F\uFF1A\u68C0\u6D4B\u5230\u5931\u8D25\uFF0C\u7EC8\u6B62\u540E\u7EED\u68C0\u67E5");break}}}catch(error){console.error(`\n❌ 检查器 "${checker.name}" 执行失败:`,error.message);results.set(id,{success:false,message:`执行出错: ${error.message}`,error});allSuccess=false;if(failFast)break}}// 总结
94
+ console.log("\n"+"\u2550".repeat(70));console.log("\uD83D\uDCCA \u68C0\u67E5\u603B\u7ED3");console.log("\u2550".repeat(70));const successCount=Array.from(results.values()).filter(r=>r.success).length;const totalCount=results.size;console.log(`\n通过: ${successCount}/${totalCount}`);if(allSuccess){console.log("\n\u2705 \u6240\u6709\u68C0\u67E5\u901A\u8FC7\uFF0C\u53EF\u4EE5\u7EE7\u7EED\u7F16\u8BD1\uFF01")}else{console.log("\n\u274C \u90E8\u5206\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u4FEE\u590D\u540E\u518D\u7F16\u8BD1\u3002")}console.log("\u2550".repeat(70)+"\n");return{success:allSuccess,results}}/**
337
95
  * 单独运行埋点验证(快捷方法)
338
96
  * @param {string} projectRoot - 项目根目录
339
97
  * @param {Object} [options] - 选项
340
98
  * @returns {Promise<CheckResult>}
341
- */
342
- async function runTrackingCheck(projectRoot, options = {}) {
343
- const checker = checkers.get('tracking');
344
- if (!checker) {
345
- throw new Error('埋点检查器未注册');
346
- }
347
-
348
- return await Promise.resolve(checker.validator(projectRoot, options));
349
- }
350
-
351
- // ============================================================
99
+ */async function runTrackingCheck(projectRoot,options={}){const checker=checkers.get("tracking");if(!checker){throw new Error("\u57CB\u70B9\u68C0\u67E5\u5668\u672A\u6CE8\u518C")}return await Promise.resolve(checker.validator(projectRoot,options))}// ============================================================
352
100
  // 导出
353
101
  // ============================================================
354
-
355
- module.exports = {
356
- // 主要函数
357
- runPreBuildChecks,
358
- runTrackingCheck,
359
-
360
- // 检查器管理
361
- registerChecker,
362
- toggleChecker,
363
- listCheckers,
364
-
365
- // 内部访问(供高级用户)
366
- checkers
367
- };
102
+ module.exports={// 主要函数
103
+ runPreBuildChecks,runTrackingCheck,// 检查器管理
104
+ registerChecker,toggleChecker,listCheckers,// 内部访问(供高级用户)
105
+ checkers};