@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,337 +1,32 @@
1
- 'use strict';
2
-
3
- const path = require('path');
4
- const fs = require('fs');
5
- const { options } = require('../../options.js');
6
- const { mergeOptions } = require('../../utils/mergeOptions.js');
7
- const { buildDefines } = require('../../utils/buildDefines.js');
8
- const { logOptions } = require('../../utils/logOptions.js');
9
- const { getOrGenerateFontCSS } = require('../../utils/fontResolver.js');
10
- const { socialMediaVitePlugin } = require('../../plugins/socialMediaVitePlugin.js');
11
-
12
- // ── 公共 Vite 插件(供项目 vite.config.ts 直接引用) ──
13
-
14
- /** JSON5 文件加载插件 */
15
- function json5Plugin() {
16
- return {
17
- name: 'vite-plugin-json5',
18
- transform(code, id) {
19
- if (id.endsWith('.json5')) {
20
- const JSON5 = require('json5');
21
- const raw = fs.readFileSync(id, 'utf-8');
22
- const parsed = JSON5.parse(raw);
23
- return {
24
- code: `export default ${JSON.stringify(parsed)};`,
25
- map: null,
26
- };
27
- }
28
- },
29
- };
30
- }
31
-
32
- /** 资源内联插件(模拟 webpack 的 asset/inline 行为) */
33
- function assetInlinePlugin() {
34
- return {
35
- name: 'vite-plugin-asset-inline',
36
- enforce: 'pre',
37
- transform(code, id) {
38
- // .atlas 文件 -> base64 data URL
39
- if (id.endsWith('.atlas')) {
40
- const content = fs.readFileSync(id);
41
- const base64 = content.toString('base64');
42
- return {
43
- code: `export default "data:text/atlas;base64,${base64}";`,
44
- map: null,
45
- };
46
- }
47
- // .fnt 文件 -> base64 data URL
48
- if (id.endsWith('.fnt')) {
49
- const content = fs.readFileSync(id);
50
- const base64 = content.toString('base64');
51
- return {
52
- code: `export default "data:text/plain;base64,${base64}";`,
53
- map: null,
54
- };
55
- }
56
- // .xml 文件 -> 原始文本
57
- if (id.endsWith('.xml')) {
58
- const raw = fs.readFileSync(id, 'utf-8');
59
- return {
60
- code: `export default ${JSON.stringify(raw)};`,
61
- map: null,
62
- };
63
- }
64
- },
65
- };
66
- }
67
-
68
- /** 字体注入插件(dev 模式:读取字体文件 base64 内联到 index.html) */
69
- function fontFamilyPlugin() {
70
- let _themeName = null;
71
- let _themeConfig = null;
72
-
73
- // 检测当前主题名(与 build.js 中 detectCurrentTheme 逻辑一致)
74
- function detectTheme() {
75
- const root = process.cwd();
76
- const buildsConfigPath = path.join(root, 'builds.config.js');
77
- let config = { sourceDir: 'src/theme', entryFile: 'src/theme/index.ts' };
78
- if (fs.existsSync(buildsConfigPath)) {
79
- try {
80
- delete require.cache[require.resolve(buildsConfigPath)];
81
- const buildsConfig = require(buildsConfigPath);
82
- if (buildsConfig.themes) {
83
- config = { ...config, ...buildsConfig.themes };
84
- }
85
- } catch (_) { /* ignore */ }
86
- }
87
- let name = null;
88
- const entryPath = path.join(root, config.entryFile);
89
- if (fs.existsSync(entryPath)) {
90
- const content = fs.readFileSync(entryPath, 'utf8');
91
- const match = content.match(/from\s+['"]\.\/([^'"]+)['"]/);
92
- if (match) name = match[1];
93
- }
94
- return { themeName: name, themeConfig: config };
95
- }
96
-
97
- return {
98
- name: 'vite-plugin-font-family',
99
- apply: 'serve',
100
- transformIndexHtml: {
101
- order: 'pre',
102
- handler() {
103
- if (_themeName === null) {
104
- const detected = detectTheme();
105
- _themeName = detected.themeName;
106
- _themeConfig = detected.themeConfig;
107
- }
108
- if (!_themeName) return '';
109
- const css = getOrGenerateFontCSS({
110
- projectRoot: process.cwd(),
111
- themeName: _themeName,
112
- themeConfig: _themeConfig,
113
- });
114
- return css ? [{ tag: 'style', attrs: { 'data-playable-fonts': '' }, children: css.replace(/<\/?style[^>]*>/g, ''), injectTo: 'head' }] : [];
115
- },
116
- },
117
- };
118
- }
119
-
120
- // ── makeViteDevConfig / runViteDev ──
121
-
1
+ "use strict";const path=require("path");const fs=require("fs");const{options}=require("../../options.js");const{mergeOptions}=require("../../utils/mergeOptions.js");const{buildDefines}=require("../../utils/buildDefines.js");const{logOptions}=require("../../utils/logOptions.js");const{getOrGenerateFontCSS}=require("../../utils/fontResolver.js");const{socialMediaVitePlugin}=require("../../plugins/socialMediaVitePlugin.js");// ── 公共 Vite 插件(供项目 vite.config.ts 直接引用) ──
2
+ /** JSON5 文件加载插件 */function json5Plugin(){return{name:"vite-plugin-json5",transform(code,id){if(id.endsWith(".json5")){const JSON5=require("json5");const raw=fs.readFileSync(id,"utf-8");const parsed=JSON5.parse(raw);return{code:`export default ${JSON.stringify(parsed)};`,map:null}}}}}/** 资源内联插件(模拟 webpack 的 asset/inline 行为) */function assetInlinePlugin(){return{name:"vite-plugin-asset-inline",enforce:"pre",transform(code,id){// .atlas 文件 -> base64 data URL
3
+ if(id.endsWith(".atlas")){const content=fs.readFileSync(id);const base64=content.toString("base64");return{code:`export default "data:text/atlas;base64,${base64}";`,map:null}}// .fnt 文件 -> base64 data URL
4
+ if(id.endsWith(".fnt")){const content=fs.readFileSync(id);const base64=content.toString("base64");return{code:`export default "data:text/plain;base64,${base64}";`,map:null}}// .xml 文件 -> 原始文本
5
+ if(id.endsWith(".xml")){const raw=fs.readFileSync(id,"utf-8");return{code:`export default ${JSON.stringify(raw)};`,map:null}}}}}/** 字体注入插件(dev 模式:读取字体文件 base64 内联到 index.html) */function fontFamilyPlugin(){let _themeName=null;let _themeConfig=null;// 检测当前主题名(与 build.js 中 detectCurrentTheme 逻辑一致)
6
+ function detectTheme(){const root=process.cwd();const buildsConfigPath=path.join(root,"builds.config.js");let config={sourceDir:"src/theme",entryFile:"src/theme/index.ts"};if(fs.existsSync(buildsConfigPath)){try{delete require.cache[require.resolve(buildsConfigPath)];const buildsConfig=require(buildsConfigPath);if(buildsConfig.themes){config={...config,...buildsConfig.themes}}}catch(_){/* ignore */}}let name=null;const entryPath=path.join(root,config.entryFile);if(fs.existsSync(entryPath)){const content=fs.readFileSync(entryPath,"utf8");const match=content.match(/from\s+['"]\.\/([^'"]+)['"]/);if(match)name=match[1]}return{themeName:name,themeConfig:config}}return{name:"vite-plugin-font-family",apply:"serve",transformIndexHtml:{order:"pre",handler(){if(_themeName===null){const detected=detectTheme();_themeName=detected.themeName;_themeConfig=detected.themeConfig}if(!_themeName)return"";const css=getOrGenerateFontCSS({projectRoot:process.cwd(),themeName:_themeName,themeConfig:_themeConfig});return css?[{tag:"style",attrs:{"data-playable-fonts":""},children:css.replace(/<\/?style[^>]*>/g,""),injectTo:"head"}]:[]}}}}// ── makeViteDevConfig / runViteDev ──
122
7
  /**
123
8
  * 创建 Vite 开发配置
124
9
  * @param {Partial<import('./index').CLIOptions>} [customOptions] - 自定义选项,会与默认选项合并
125
10
  * @param {Record<string, any>} [customDefines] - 额外的 define 常量
126
11
  * @param {import('vite').UserConfig} [viteCustomConfig] - 自定义 Vite 配置,会与默认配置合并
127
12
  * @returns {import('vite').UserConfig} 最终的 Vite 开发配置
128
- */
129
- function makeViteDevConfig(customOptions, customDefines, viteCustomConfig) {
130
- const devOptions = mergeOptions(options, customOptions);
131
- logOptions(devOptions);
132
- customDefines = customDefines || {};
133
- viteCustomConfig = viteCustomConfig || {};
134
-
135
- // 构建 define 常量(复用 webpack 的 buildDefines 逻辑)
136
- const defines = {
137
- ...buildDefines(),
138
- ...devOptions.defines,
139
- __DEV__: JSON.stringify(devOptions['dev'] === undefined ? true : devOptions['dev']),
140
- ...customDefines,
141
- };
142
-
143
- // 解析 tsconfig/jsconfig 路径别名
144
- const tsConfigPath = path.resolve(devOptions.tsConfig || 'tsconfig.json');
145
- const jsConfigPath = path.resolve(devOptions.jsConfig || 'jsconfig.json');
146
- let aliasConfig = {};
147
-
148
- // 尝试从 tsconfig/jsconfig 中读取 paths 配置
149
- let configFilePath = null;
150
- if (fs.existsSync(tsConfigPath)) {
151
- configFilePath = tsConfigPath;
152
- } else if (fs.existsSync(jsConfigPath)) {
153
- configFilePath = jsConfigPath;
154
- }
155
-
156
- if (configFilePath) {
157
- try {
158
- const JSON5 = require('json5');
159
- const configContent = fs.readFileSync(configFilePath, 'utf-8');
160
- const config = JSON5.parse(configContent);
161
- const paths = config.compilerOptions?.paths || {};
162
- for (const [alias, targets] of Object.entries(paths)) {
163
- // 将 tsconfig paths 格式 "foo/*" -> ["src/foo/*"] 转换为 vite alias
164
- const cleanAlias = alias.replace('/*', '');
165
- const cleanTarget = targets[0]?.replace('/*', '') || '';
166
- if (cleanAlias && cleanTarget) {
167
- aliasConfig[cleanAlias] = path.resolve(cleanTarget);
168
- }
169
- }
170
- } catch (err) {
171
- console.log('\x1b[33m⚠️ 读取路径配置失败: ' + err.message + '\x1b[0m');
172
- }
173
- }
174
-
175
- // 默认别名
176
- aliasConfig = {
177
- assets: path.resolve('assets'),
178
- '@': path.resolve('src'),
179
- ...aliasConfig,
180
- };
181
-
182
- /** @type {import('vite').UserConfig} */
183
- const viteConfig = {
184
- root: '.',
185
- resolve: {
186
- alias: aliasConfig,
187
- },
188
- plugins: [json5Plugin(), assetInlinePlugin(), fontFamilyPlugin(), socialMediaVitePlugin()],
189
- define: defines,
190
- server: {
191
- port: devOptions['port'] || 3000,
192
- open: devOptions['open'] || false,
193
- },
194
- build: {
195
- outDir: devOptions['outDir'] || 'dist',
196
- sourcemap: true,
197
- },
198
- };
199
-
200
- // 合并自定义配置
201
- if (viteCustomConfig) {
202
- const { plugins: customPlugins, define: customDefine, resolve: customResolve, server: customServer, build: customBuild, ...rest } = viteCustomConfig;
203
-
204
- if (customPlugins) {
205
- viteConfig.plugins = [...viteConfig.plugins, ...customPlugins];
206
- }
207
- if (customDefine) {
208
- viteConfig.define = { ...viteConfig.define, ...customDefine };
209
- }
210
- if (customResolve) {
211
- viteConfig.resolve = {
212
- ...viteConfig.resolve,
213
- ...customResolve,
214
- alias: { ...viteConfig.resolve.alias, ...(customResolve.alias || {}) },
215
- };
216
- }
217
- if (customServer) {
218
- viteConfig.server = { ...viteConfig.server, ...customServer };
219
- }
220
- if (customBuild) {
221
- viteConfig.build = { ...viteConfig.build, ...customBuild };
222
- }
223
- Object.assign(viteConfig, rest);
224
- }
225
-
226
- return viteConfig;
227
- }
228
-
229
- /**
13
+ */function makeViteDevConfig(customOptions,customDefines,viteCustomConfig){const devOptions=mergeOptions(options,customOptions);logOptions(devOptions);customDefines=customDefines||{};viteCustomConfig=viteCustomConfig||{};// 构建 define 常量(复用 webpack 的 buildDefines 逻辑)
14
+ const defines={...buildDefines(),...devOptions.defines,__DEV__:JSON.stringify(devOptions["dev"]===undefined?true:devOptions["dev"]),...customDefines};// 解析 tsconfig/jsconfig 路径别名
15
+ const tsConfigPath=path.resolve(devOptions.tsConfig||"tsconfig.json");const jsConfigPath=path.resolve(devOptions.jsConfig||"jsconfig.json");let aliasConfig={};// 尝试从 tsconfig/jsconfig 中读取 paths 配置
16
+ let configFilePath=null;if(fs.existsSync(tsConfigPath)){configFilePath=tsConfigPath}else if(fs.existsSync(jsConfigPath)){configFilePath=jsConfigPath}if(configFilePath){try{var _config$compilerOptio;const JSON5=require("json5");const configContent=fs.readFileSync(configFilePath,"utf-8");const config=JSON5.parse(configContent);const paths=((_config$compilerOptio=config.compilerOptions)===null||_config$compilerOptio===void 0?void 0:_config$compilerOptio.paths)||{};for(const[alias,targets]of Object.entries(paths)){var _targets$;// 将 tsconfig paths 格式 "foo/*" -> ["src/foo/*"] 转换为 vite alias
17
+ const cleanAlias=alias.replace("/*","");const cleanTarget=((_targets$=targets[0])===null||_targets$===void 0?void 0:_targets$.replace("/*",""))||"";if(cleanAlias&&cleanTarget){aliasConfig[cleanAlias]=path.resolve(cleanTarget)}}}catch(err){console.log("\x1B[33m\u26A0\uFE0F \u8BFB\u53D6\u8DEF\u5F84\u914D\u7F6E\u5931\u8D25: "+err.message+"\x1B[0m")}}// 默认别名
18
+ aliasConfig={assets:path.resolve("assets"),"@":path.resolve("src"),...aliasConfig};/** @type {import('vite').UserConfig} */const viteConfig={root:".",resolve:{alias:aliasConfig},plugins:[json5Plugin(),assetInlinePlugin(),fontFamilyPlugin(),socialMediaVitePlugin()],define:defines,server:{port:devOptions["port"]||3000,open:devOptions["open"]||false},build:{outDir:devOptions["outDir"]||"dist",sourcemap:true}};// 合并自定义配置
19
+ if(viteCustomConfig){const{plugins:customPlugins,define:customDefine,resolve:customResolve,server:customServer,build:customBuild,...rest}=viteCustomConfig;if(customPlugins){viteConfig.plugins=[...viteConfig.plugins,...customPlugins]}if(customDefine){viteConfig.define={...viteConfig.define,...customDefine}}if(customResolve){viteConfig.resolve={...viteConfig.resolve,...customResolve,alias:{...viteConfig.resolve.alias,...(customResolve.alias||{})}}}if(customServer){viteConfig.server={...viteConfig.server,...customServer}}if(customBuild){viteConfig.build={...viteConfig.build,...customBuild}}Object.assign(viteConfig,rest)}return viteConfig}/**
230
20
  * 深度合并两个 Vite 配置对象。override 覆盖 base。
231
21
  * 数组会拼接(plugins),其余字段浅覆盖。
232
- */
233
- function deepMergeViteConfig(base, override) {
234
- if (!override || typeof override !== 'object') return base;
235
- const result = { ...base };
236
- for (const key of Object.keys(override)) {
237
- const bv = base[key];
238
- const ov = override[key];
239
- if (key === 'plugins' && Array.isArray(bv) && Array.isArray(ov)) {
240
- result[key] = [...bv, ...ov];
241
- } else if (
242
- ov !== null && typeof ov === 'object' && !Array.isArray(ov) &&
243
- bv !== null && typeof bv === 'object' && !Array.isArray(bv)
244
- ) {
245
- result[key] = { ...bv, ...ov };
246
- } else {
247
- result[key] = ov;
248
- }
249
- }
250
- return result;
251
- }
252
-
253
- /**
22
+ */function deepMergeViteConfig(base,override){if(!override||typeof override!=="object")return base;const result={...base};for(const key of Object.keys(override)){const bv=base[key];const ov=override[key];if(key==="plugins"&&Array.isArray(bv)&&Array.isArray(ov)){result[key]=[...bv,...ov]}else if(ov!==null&&typeof ov==="object"&&!Array.isArray(ov)&&bv!==null&&typeof bv==="object"&&!Array.isArray(bv)){result[key]={...bv,...ov}}else{result[key]=ov}}return result}/**
254
23
  * 尝试加载项目根目录的 vite.config.ts。
255
- */
256
- async function loadProjectViteConfig(root) {
257
- const candidates = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];
258
- let configPath = null;
259
- for (const c of candidates) {
260
- const p = path.join(root, c);
261
- if (fs.existsSync(p)) { configPath = p; break; }
262
- }
263
- if (!configPath) return null;
264
-
265
- const { createRequire } = require('module');
266
- let projRequire;
267
- try {
268
- projRequire = createRequire(path.join(root, 'package.json'));
269
- } catch (_) {
270
- projRequire = createRequire(path.join(root, 'noop.js'));
271
- }
272
-
273
- let loadConfigFromFile;
274
- try {
275
- loadConfigFromFile = projRequire('vite').loadConfigFromFile;
276
- } catch (_) {
277
- try {
278
- loadConfigFromFile = projRequire('vite/dist/node/config').loadConfigFromFile;
279
- } catch (_2) {
280
- console.log('\x1b[33m⚠️ [vite] Cannot load project config (loadConfigFromFile unavailable), using scripts default\x1b[0m');
281
- return null;
282
- }
283
- }
284
-
285
- if (!loadConfigFromFile) return null;
286
-
287
- try {
288
- const result = await loadConfigFromFile(
289
- { command: 'serve', mode: process.env.NODE_ENV || 'development' },
290
- configPath,
291
- root
292
- );
293
- if (result && result.config) {
294
- console.log(`[vite] Loaded project config: ${path.relative(root, configPath)}`);
295
- return result.config;
296
- }
297
- return null;
298
- } catch (err) {
299
- console.log(`\x1b[33m⚠️ [vite] Failed to load ${path.relative(root, configPath)}: ${err.message}, using scripts default\x1b[0m`);
300
- return null;
301
- }
302
- }
303
-
304
- /**
24
+ */async function loadProjectViteConfig(root){const candidates=["vite.config.ts","vite.config.js","vite.config.mjs"];let configPath=null;for(const c of candidates){const p=path.join(root,c);if(fs.existsSync(p)){configPath=p;break}}if(!configPath)return null;const{createRequire}=require("module");let projRequire;try{projRequire=createRequire(path.join(root,"package.json"))}catch(_){projRequire=createRequire(path.join(root,"noop.js"))}let loadConfigFromFile;try{loadConfigFromFile=projRequire("vite").loadConfigFromFile}catch(_){try{loadConfigFromFile=projRequire("vite/dist/node/config").loadConfigFromFile}catch(_2){console.log("\x1B[33m\u26A0\uFE0F [vite] Cannot load project config (loadConfigFromFile unavailable), using scripts default\x1B[0m");return null}}if(!loadConfigFromFile)return null;try{const result=await loadConfigFromFile({command:"serve",mode:process.env.NODE_ENV||"development"},configPath,root);if(result&&result.config){console.log(`[vite] Loaded project config: ${path.relative(root,configPath)}`);return result.config}return null}catch(err){console.log(`\x1b[33m⚠️ [vite] Failed to load ${path.relative(root,configPath)}: ${err.message}, using scripts default\x1b[0m`);return null}}/**
305
25
  * 启动 Vite 开发服务器。
306
26
  *
307
27
  * 配置优先级(从低到高):
308
28
  * 1. makeViteDevConfig 构建的默认配置(fontFamilyPlugin、json5Plugin 等)
309
29
  * 2. 项目根目录的 vite.config.ts(如果存在,覆盖/扩充默认配置)
310
30
  * 3. 传入的 viteConfig / customOptions / customDefines / viteCustomConfig
311
- */
312
- async function runViteDev(viteConfig, customOptions, customDefines, viteCustomConfig) {
313
- if (!viteConfig) {
314
- viteConfig = makeViteDevConfig(customOptions, customDefines, viteCustomConfig);
315
- }
316
-
317
- const projectRoot = process.cwd();
318
- const projectConfig = await loadProjectViteConfig(projectRoot);
319
- if (projectConfig) {
320
- viteConfig = deepMergeViteConfig(viteConfig, projectConfig);
321
- }
322
-
323
- const { createRequire } = require('module');
324
- const projRequire = createRequire(path.join(projectRoot, 'package.json'));
325
- const { createServer } = projRequire('vite');
326
- const server = await createServer({ ...viteConfig, configFile: false });
327
- await server.listen();
328
- server.printUrls();
329
- }
330
-
331
- // ── 导出 ──
332
-
333
- exports.json5Plugin = json5Plugin;
334
- exports.assetInlinePlugin = assetInlinePlugin;
335
- exports.fontFamilyPlugin = fontFamilyPlugin;
336
- exports.makeViteDevConfig = makeViteDevConfig;
337
- exports.runViteDev = runViteDev;
31
+ */async function runViteDev(viteConfig,customOptions,customDefines,viteCustomConfig){if(!viteConfig){viteConfig=makeViteDevConfig(customOptions,customDefines,viteCustomConfig)}const projectRoot=process.cwd();const projectConfig=await loadProjectViteConfig(projectRoot);if(projectConfig){viteConfig=deepMergeViteConfig(viteConfig,projectConfig)}const{createRequire}=require("module");const projRequire=createRequire(path.join(projectRoot,"package.json"));const{createServer}=projRequire("vite");const server=await createServer({...viteConfig,configFile:false});await server.listen();server.printUrls()}// ── 导出 ──
32
+ exports.json5Plugin=json5Plugin;exports.assetInlinePlugin=assetInlinePlugin;exports.fontFamilyPlugin=fontFamilyPlugin;exports.makeViteDevConfig=makeViteDevConfig;exports.runViteDev=runViteDev;