mbler 0.2.4 → 0.2.7-rc.2

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.
package/dist/build.js CHANGED
@@ -2,25 +2,18 @@
2
2
 
3
3
  var mcxDef = require('@mbler/mcx-core');
4
4
  var _chalk = require('chalk');
5
- var jsonPlugin = require('@rollup/plugin-json');
6
- var resolvePlugin = require('@rollup/plugin-node-resolve');
7
5
  var minifyPlugin = require('@rollup/plugin-terser');
8
6
  var chokidar = require('chokidar');
9
- var fs = require('node:fs/promises');
7
+ var fs$1 = require('node:fs/promises');
10
8
  var path = require('node:path');
11
- var rollup = require('rollup');
9
+ var rolldown = require('rolldown');
12
10
  var readline = require('readline');
11
+ var fs = require('node:fs');
13
12
  var os = require('node:os');
14
- var npmRegistryFetch = require('npm-registry-fetch');
15
13
  require('node:child_process');
16
- var node_v8 = require('node:v8');
17
14
  var crypto = require('node:crypto');
18
- var fs$1 = require('node:fs');
19
15
  var node_process = require('node:process');
20
- var AdmZip = require('adm-zip');
21
- var commonjs = require('@rollup/plugin-commonjs');
22
16
  var mcxServer = require('@mbler/mcx-server');
23
- var typescript = require('@rollup/plugin-typescript');
24
17
  var ts = require('typescript');
25
18
  var runTsc_js = require('@volar/typescript/lib/quickstart/runTsc.js');
26
19
 
@@ -42,48 +35,395 @@ function _interopNamespaceDefault(e) {
42
35
  }
43
36
 
44
37
  var mcxDef__namespace = /*#__PURE__*/_interopNamespaceDefault(mcxDef);
45
- var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
38
+ var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs$1);
46
39
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
47
- var rollup__namespace = /*#__PURE__*/_interopNamespaceDefault(rollup);
48
40
  var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline);
49
- var fs__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(fs$1);
41
+ var fs__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(fs);
42
+
43
+ const LanguageNames = ['zh', 'en'];
44
+ const cmdList = [
45
+ 'c',
46
+ 'work',
47
+ 'help',
48
+ 'h',
49
+ 'init',
50
+ 'version',
51
+ 'build',
52
+ 'watch',
53
+ 'lang',
54
+ 'set-work-dir',
55
+ 'publish',
56
+ 'unpublish',
57
+ 'install',
58
+ 'uninstall',
59
+ 'login',
60
+ 'profile',
61
+ 'log',
62
+ 'view',
63
+ 'config',
64
+ ];
65
+ const templateMblerConfig = {
66
+ name: 'demo',
67
+ description: 'demo',
68
+ version: '0.0.0',
69
+ mcVersion: '1.21.100',
70
+ script: {
71
+ main: '',
72
+ },
73
+ minify: false,
74
+ outdir: {
75
+ behavior: '',
76
+ resources: '',
77
+ dist: '',
78
+ },
79
+ build: {
80
+ rollupPlugins: [],
81
+ cache: 'auto',
82
+ bundle: true,
83
+ outputDir: 'scripts',
84
+ outputFilename: '',
85
+ onEnd: () => { },
86
+ onStart: () => { },
87
+ onWarn: () => { },
88
+ },
89
+ };
90
+
91
+ var version = { version: "0.2.7-rc.1" };
92
+
93
+ var ZhLang = {
94
+ description: `MBLER
95
+ Minecraft Bedrock Edition
96
+ Addon Bulider In Nodejs
97
+ 在基岩版我的世界上的 nodejs 构建工具
98
+ 命令 : ${cmdList.join(', ')}
99
+ 帮助命令 :
100
+ help
101
+ 显示帮助信息
102
+ 第二个参数为要查询的命令名称或空
103
+ 别名: h
104
+ git https://github.com/RuanhoR/mbler/`,
105
+ help: {
106
+ cmds: cmdList,
107
+ help: 'mbler [help/h] [?:查看的命令名称]\n - 查看帮助',
108
+ h: '$help',
109
+ work: 'mbler [work/c] [?:相对或绝对路径]\n - 没有输入路径:查询当前工作目录\n - 输入路径:设置工作目录',
110
+ c: '$work',
111
+ init: 'mbler init\n - 初始化当前工作目录,可使用 mbler work 指定工作目录或使用参数一次确定(例: mbler init -in ./)\n - 将会询问选项以完成初始化',
112
+ build: 'mbler build\n - 在工作目录执行构建',
113
+ log: 'mbler log\n - 处理日志文件\n - mbler log point: 得到日志文件路径 \n - mbler log clean: 清除日志',
114
+ watch: 'mbler watch\n - 启动构建并开启监视模式,文件变化会自动重新构建',
115
+ lang: 'mbler lang\n- 无参数:显示当前语言\n- 跟 zh 或 en(如 mbler lang en): 设置语言',
116
+ version: 'mbler version - 版本管理命令\n- 无参数:显示当前版本和提交哈希\n- --show=<commit|version>:筛选显示内容\n- <新版本号>:更新package.json和配置文件的版本',
117
+ 'set-work-dir': 'mbler set-work-dir <on|off>\n - on: 启用工作目录功能\n - off: 禁用工作目录功能,直接使用 process.cwd()',
118
+ publish: 'mbler publish\n - 将你的附加包发布到 pmnx\n- 参数:\n- -tag: 版本标签名称\n- -build <skip|always>: 是否跳过构建(默认 always)',
119
+ uninstall: 'mbler uninstall @<scope>/<name>@version\n从你的游戏中移除一个包',
120
+ install: 'mbler install @<scope>/<name>@version\n将一个包安装到你的游戏中',
121
+ unpublish: 'mbler unpublish @<scope>/<name>@version\n从 pmnx 取消发布一个包',
122
+ login: 'mbler login <?:token>\n使用 token 登录你的 pmnx 账户\n- 如果没有 token,会向你请求',
123
+ profile: 'mbler profile\n显示当前登录账户信息',
124
+ view: 'mbler view @<scope>/<name>\n查看包的版本列表',
125
+ config: 'mbler config get <key>\nmbler config set <key> <value>\nmbler config point <path>\nmbler config point get',
126
+ },
127
+ init: {
128
+ useUI: '使用UI模块? (y/n): ',
129
+ useGIT: '初始化GIT仓库? (y/n): ',
130
+ name: '项目名称: ',
131
+ welcome: '欢迎使用Mbler初始化向导 语言:中文 mbler 版本: ' + version.version,
132
+ description: '项目描述: ',
133
+ initDes: '初始化依赖? (y/n): ',
134
+ lang: '选择项目语言: ',
135
+ betaApi: '使用Beta Api? (y/n): ',
136
+ mcVersion: '项目使用的mc版本(x.x.x): ',
137
+ noLanguare: '没有输入项目语言,这是必要的',
138
+ noName: '没有项目名称,这是必要的',
139
+ noMCVersion: "输入的 '支持的mc版本' 格式不对",
140
+ },
141
+ default: {
142
+ unexpected: '不正确的命令,',
143
+ youis: '你是否想说: ',
144
+ },
145
+ workdir: {
146
+ set: '[工作目录] 设置为: ',
147
+ nfound: '找不到输入文件夹(无法创建或不是文件夹)',
148
+ disabled: '工作目录功能已禁用,将使用当前目录',
149
+ enabled: '工作目录功能已启用',
150
+ invalidParam: '参数错误,请使用 on 或 off',
151
+ },
152
+ publish: {
153
+ askTip: '输入MCBE游戏绝对目录 (如 /sdcard/Android/data/com.mojang.minecraftpe/files/games),以进行下一步: ',
154
+ notLoggedIn: '未登录,请先执行 `mbler login <token>`',
155
+ progress: '进度: {progress}%',
156
+ publishFailed: '发布失败: {error}',
157
+ publishing: '正在发布...',
158
+ building: '正在构建项目...',
159
+ publishToMarket: '正在上传到市场...',
160
+ publishSuccess: '发布成功',
161
+ publishResult: '+ {name}@{version} ({tag})',
162
+ projectPathNotExist: '项目路径不存在',
163
+ outdirNotFound: '未找到构建输出目录配置',
164
+ outdirNotExist: '构建输出目录不存在',
165
+ readmeNotFound: '未找到 README 文件',
166
+ metadataInvalid: '元数据无效',
167
+ packageNameInvalid: '包名格式必须是 @scope/name',
168
+ notLoginError: '未登录',
169
+ tokenMissing: '获取 token 失败',
170
+ unpublishReqFailed: '取消发布请求失败',
171
+ createSessionFailed: '创建发布会话失败',
172
+ uploadZipFailed: '上传 zip 文件失败',
173
+ packageJsonNotFound: '未找到 package.json',
174
+ noBuildScript: 'package.json 中未找到 build 脚本',
175
+ buildFailed: '构建失败,退出码: {code}',
176
+ },
177
+ install: {
178
+ failedNoPackageJson: '安装失败:工作目录必须包含 package.json',
179
+ failedNoBuildScript: '安装失败:package.json 必须包含 build 脚本',
180
+ installing: '正在安装包 {pkg}...',
181
+ packageNotFound: '未找到包 {pkg}',
182
+ noVersion: '包 {pkg} 没有可用版本',
183
+ usingLatest: '使用最新版本 {version}',
184
+ noValidAddon: '包内未找到有效 addon',
185
+ success: '包 {pkg}@{version} 已安装为 {id}',
186
+ failed: '安装失败: {error}',
187
+ },
188
+ uninstall: {
189
+ success: '包 {pkg}@{version} 卸载成功',
190
+ failed: '卸载失败: {error}',
191
+ },
192
+ unpublish: {
193
+ success: '包 {pkg}@{version} 取消发布成功',
194
+ failed: '取消发布失败: {error}',
195
+ },
196
+ view: {
197
+ usage: 'mbler view @<scope>/<name>',
198
+ packageNotFound: '未找到包 {pkg}',
199
+ title: '包 {pkg} 版本列表:',
200
+ versionLine: '- {version} [{tag}] by {user} at {time}',
201
+ failed: '查看失败: {error}',
202
+ },
203
+ config: {
204
+ usage: 'mbler config get <key> | set <key> <value> | point <path> | point get',
205
+ missingArg: '参数不足',
206
+ getResult: '{key} = {value}',
207
+ setSuccess: '已设置 {key} = {value}',
208
+ pointGet: '当前配置文件: {path}',
209
+ pointSetSuccess: '配置文件指向已设置为: {path}',
210
+ pointSetFailed: '配置文件指向设置失败: {error}',
211
+ failed: '配置操作失败: {error}',
212
+ },
213
+ commander: {
214
+ selectTip: '(按 b 确认,n 键选择下一个)',
215
+ },
216
+ };
217
+
218
+ var enLang = {
219
+ description: 'MBLER\nMinecraft Bedrock Edition\nAddon Bulider In Nodejs\nnodejs build tools on bedrock version of minecraft\nCommands: ' +
220
+ cmdList.join(', ') +
221
+ '\nHelp command:\n help\n Show help information\n The second parameter is the name of the command to be queried or empty\n Alias: -h, -help\n git https://github.com/RuanhoR/mbler/',
222
+ help: {
223
+ cmds: cmdList,
224
+ help: 'mbler [help/h] [?: command name]\n - see tip',
225
+ h: '$help',
226
+ work: 'mbler [work/c] [?: path]\n - No input path: see current work dir\n - input path: set as current dir',
227
+ c: '$work',
228
+ init: 'mbler init\n - Init current work dir, you can use `mbler work` command or use command param(like be: mbler init -in ./)',
229
+ build: 'mbler build\n - perform a build using the library API',
230
+ b: '$build',
231
+ log: 'mbler log\n - Handler log file\n - mbler log point: Get log file path \n - mbler log clean: Remove Log',
232
+ watch: 'mbler watch\n - run build and enter watch mode; changes will trigger rebuilds',
233
+ lang: 'mbler lang [?:language]\n- No args: show current language\n- language = "zh” | “en": set language',
234
+ version: 'mbler version\n - Version control command\n- No args: Shows version + commit hash\n- --show=<commit|version>: Filters output\n- <new_version>: Updates version in both package.json and config file',
235
+ 'set-work-dir': 'mbler set-work-dir <on|off>\n - on: Enable work dir feature\n - off: Disable work dir feature, use process.cwd() directly',
236
+ publish: 'mbler publish\n - Publish your package to pmnx\n- Params:\n- -tag: version tag name\n- -build <skip|always>: skip or run build before publish (default: always)',
237
+ uninstall: 'mbler uninstall @<scope>/<name>@version\nRemove a package from your game',
238
+ install: 'mbler install @<scope>/<name>@version\nInstall a package to your game',
239
+ unpublish: 'mbler unpublish @<scope>/<name>@version\nUnpublish a package from pmnx',
240
+ login: 'mbler login <?:token>\nUse token login your pmnx account',
241
+ profile: 'mbler profile\nShow current logged-in account profile',
242
+ view: 'mbler view @<scope>/<name>\nShow package versions',
243
+ config: 'mbler config get <key>\nmbler config set <key> <value>\nmbler config point <path>\nmbler config point get',
244
+ },
245
+ init: {
246
+ useUI: 'Use UI? (y/n): ',
247
+ useGIT: 'Initialize GIT repository? (y/n): ',
248
+ name: 'Project name: ',
249
+ description: 'Project description: ',
250
+ initDes: 'Initialize dependencies? (y/n): ',
251
+ welcome: 'Welcome to use Mbler init wizard! Language: English mbler version: ' +
252
+ version.version,
253
+ lang: 'Project language: ',
254
+ betaApi: 'use beta api(y/n): ',
255
+ mcVersion: 'Minecraft version(be like: x.x.x): ',
256
+ noLanguare: 'project language is required',
257
+ noMCVersion: 'project mcVersion format is not right',
258
+ noName: 'project name is required',
259
+ },
260
+ default: {
261
+ unexpected: 'Not found this command,',
262
+ youis: 'You want to input: ',
263
+ },
264
+ workdir: {
265
+ set: '[path to]: ',
266
+ nfound: "not found this dir(can't create or not directory)",
267
+ disabled: 'Work dir disabled, will use current directory',
268
+ enabled: 'Work dir enabled',
269
+ invalidParam: 'Invalid parameter, use on or off',
270
+ },
271
+ publish: {
272
+ askTip: 'Plase input the absolute path of your MCBE game directory (like /sdcard/Android/data/com.mojang.minecraftpe/files/games) for next step: ',
273
+ notLoggedIn: 'Not logged in. Use `mbler login <token>` first.',
274
+ progress: 'Progress: {progress}%',
275
+ publishFailed: 'Publish failed: {error}',
276
+ publishing: 'Publishing...',
277
+ building: 'Building project...',
278
+ publishToMarket: 'Publishing to marketplace...',
279
+ publishSuccess: 'Publish successful',
280
+ publishResult: '+ {name}@{version} ({tag})',
281
+ projectPathNotExist: 'Project path does not exist',
282
+ outdirNotFound: 'Build output directories not found',
283
+ outdirNotExist: 'Build output directories do not exist',
284
+ readmeNotFound: 'README file not found',
285
+ metadataInvalid: 'Invalid metadata',
286
+ packageNameInvalid: 'Package name must be in the format of @scope/name',
287
+ notLoginError: 'Not logged in',
288
+ tokenMissing: 'Failed to get token',
289
+ unpublishReqFailed: 'Failed to unpublish package',
290
+ createSessionFailed: 'Failed to create publish session',
291
+ uploadZipFailed: 'Failed to upload zip file',
292
+ packageJsonNotFound: 'package.json not found',
293
+ noBuildScript: 'No build script found in package.json',
294
+ buildFailed: 'Build failed with code {code}',
295
+ },
296
+ install: {
297
+ failedNoPackageJson: 'Install failed: work directory must contain package.json',
298
+ failedNoBuildScript: 'Install failed: package.json must contain a build script',
299
+ installing: 'Installing package {pkg}...',
300
+ packageNotFound: 'Package {pkg} not found',
301
+ noVersion: 'Package {pkg} has no available version',
302
+ usingLatest: 'Using latest version {version}',
303
+ noValidAddon: 'No valid addon found in package',
304
+ success: 'Package {pkg}@{version} installed successfully as {id}',
305
+ failed: 'Install failed: {error}',
306
+ },
307
+ uninstall: {
308
+ success: 'Package {pkg}@{version} uninstalled successfully',
309
+ failed: 'Uninstall failed: {error}',
310
+ },
311
+ unpublish: {
312
+ success: 'Package {pkg}@{version} unpublished successfully',
313
+ failed: 'Unpublish failed: {error}',
314
+ },
315
+ view: {
316
+ usage: 'mbler view @<scope>/<name>',
317
+ packageNotFound: 'Package {pkg} not found',
318
+ title: 'Package {pkg} versions:',
319
+ versionLine: '- {version} [{tag}] by {user} at {time}',
320
+ failed: 'View failed: {error}',
321
+ },
322
+ config: {
323
+ usage: 'mbler config get <key> | set <key> <value> | point <path> | point get',
324
+ missingArg: 'Missing argument',
325
+ getResult: '{key} = {value}',
326
+ setSuccess: 'Set {key} = {value}',
327
+ pointGet: 'Current config file: {path}',
328
+ pointSetSuccess: 'Config file pointer set to: {path}',
329
+ pointSetFailed: 'Failed to set config pointer: {error}',
330
+ failed: 'Config command failed: {error}',
331
+ },
332
+ commander: {
333
+ selectTip: '(Press b to confirm, n to select next)',
334
+ },
335
+ };
336
+
337
+ const configPath = path.join(os.homedir(), // ~/.cache/mbler/lang.db: push language config
338
+ '.cache/mbler/lang.db');
339
+ function isLanguareName(language) {
340
+ return LanguageNames.includes(language);
341
+ }
342
+ class Lang {
343
+ currenyLang = 'zh';
344
+ init() {
345
+ try {
346
+ const TheyLang = fs.readFileSync(configPath, 'utf-8').toString().trim();
347
+ if (isLanguareName(TheyLang)) {
348
+ this.currenyLang = TheyLang;
349
+ }
350
+ else {
351
+ throw new Error('[setup lang]: set lang error');
352
+ }
353
+ }
354
+ catch {
355
+ this.currenyLang = 'zh';
356
+ }
357
+ }
358
+ set(newLang) {
359
+ if (LanguageNames.includes(newLang)) {
360
+ if (!fs.existsSync(configPath)) {
361
+ fs.mkdirSync(path.dirname(configPath), {
362
+ recursive: true,
363
+ });
364
+ }
365
+ fs.writeFileSync(configPath, newLang);
366
+ this.currenyLang = newLang;
367
+ return true;
368
+ }
369
+ return false;
370
+ }
371
+ get() {
372
+ try {
373
+ if (this.currenyLang == 'zh')
374
+ return ZhLang;
375
+ return enLang;
376
+ }
377
+ catch {
378
+ return ZhLang;
379
+ }
380
+ }
381
+ }
382
+ const lang = new Lang();
383
+ const i18n = {};
384
+ function Export(lang) {
385
+ const obj = lang.get();
386
+ Object.setPrototypeOf(i18n, {
387
+ ...obj,
388
+ __internal: {
389
+ class: lang,
390
+ set: (newLang) => {
391
+ lang.set(newLang);
392
+ Export(lang);
393
+ },
394
+ },
395
+ });
396
+ }
397
+ lang.init();
398
+ Export(lang);
50
399
 
51
- // 启用 raw mode 和键盘事件(仅在 TTY 环境中)
52
400
  if (process.stdin.isTTY) {
53
401
  process.stdin.setRawMode(true);
54
402
  readline__namespace.emitKeypressEvents(process.stdin);
55
403
  }
56
404
  const promises = [];
57
405
  const tasks = [];
58
- process.on("exit", (code) => {
59
- process.stdout.write("\x1b[?25h");
406
+ process.on('exit', (_code) => {
407
+ process.stdout.write('\x1b[?25h');
60
408
  });
61
409
  const endTasks = [];
62
410
  function onEnd(task) {
63
411
  endTasks.push(task);
64
412
  }
65
- click("c", {
413
+ click('c', {
66
414
  ctrl: true,
67
415
  }).then(() => {
68
416
  endTasks.forEach((task) => task());
69
417
  process.exit(0);
70
418
  });
71
- /**
72
- * 监听键盘输入并触发对应的 Promise 或任务
73
- */
74
419
  function handler(name, { ctrl, alt, }, raw) {
75
- // 查找是否有匹配的 Promise 等待触发
76
420
  const find = promises.find((e) => e.name === name && e.ctrl === ctrl && e.alt === alt);
77
421
  if (find) {
78
422
  find.resolve();
79
423
  promises.splice(promises.indexOf(find), 1);
80
424
  }
81
- // 通知所有注册的监听任务
82
425
  tasks.forEach((item) => item(name, ctrl, alt, raw));
83
426
  }
84
- /**
85
- * 模拟等待某个按键被按下,返回一个 Promise
86
- */
87
427
  function click(name, { ctrl = false, alt = false, }) {
88
428
  return new Promise((resolve) => {
89
429
  promises.push({
@@ -94,36 +434,21 @@ function click(name, { ctrl = false, alt = false, }) {
94
434
  });
95
435
  });
96
436
  }
97
- /**
98
- * 工具类:提供控制台交互功能,比如高亮菜单渲染、交互式选择等
99
- */
100
437
  class Input {
101
- /**
102
- * 渲染一个字符串数组,高亮当前选中的项
103
- * @param arr 菜单项数组
104
- * @param index 当前选中索引
105
- * @returns 格式化后的字符串
106
- */
107
438
  static render(arr, index) {
108
439
  return arr
109
440
  .map((item, pindex) => {
110
441
  if (pindex === index)
111
- return "\x1b[1m\x1b[32m" + item + "\x1b[0m"; // 亮绿,高亮
112
- return "\x1b[1m\x1b[33m" + item + "\x1b[0m"; // 亮黄
442
+ return '\x1b[1m\x1b[32m' + item + '\x1b[0m'; // 亮绿,高亮
443
+ return '\x1b[1m\x1b[33m' + item + '\x1b[0m'; // 亮黄
113
444
  })
114
- .join(" ");
445
+ .join(' ');
115
446
  }
116
- /**
117
- * 提供一个交互式菜单选择器
118
- * @param tip 提示文本
119
- * @param arr 选项数组
120
- * @returns 用户选中的选项内容(Promise<string>)
121
- */
122
447
  static select(tip, arr) {
123
448
  let index = 0;
124
449
  let win = false;
125
- console.log(`\x1b[2K\x1b[47m\x1b[1m\x1b[30m${tip} (按 b 确认,n 键选择下一个) \x1b[0m\x1b[?25l`);
126
- console.log(Input.render(arr, index) + "\n\x1b[1A");
450
+ console.log(`\x1b[2K\x1b[47m\x1b[1m\x1b[30m${tip} ${i18n.commander.selectTip} \x1b[0m\x1b[?25l`);
451
+ console.log(Input.render(arr, index) + '\n\x1b[1A');
127
452
  const handlerNext = () => {
128
453
  if (win)
129
454
  return;
@@ -131,39 +456,32 @@ class Input {
131
456
  if (index >= arr.length)
132
457
  index = 0;
133
458
  console.log(`\x1b[1A${Input.render(arr, index)}\n\x1b[1A`);
134
- click("n", {
459
+ click('n', {
135
460
  ctrl: false,
136
461
  alt: false,
137
462
  }).then(handlerNext);
138
463
  };
139
464
  return new Promise((resolve) => {
140
- // 监听 n 按键来切换选项
141
- click("n", {
465
+ click('n', {
142
466
  ctrl: false,
143
467
  alt: false,
144
468
  }).then(handlerNext);
145
- // 监听 b 按键来确认选择
146
- click("b", {
469
+ click('b', {
147
470
  ctrl: false,
148
471
  alt: false,
149
472
  }).then(() => {
150
473
  win = true;
151
- process.stdout.write("\x1b[?25h");
474
+ process.stdout.write('\x1b[?25h');
152
475
  resolve(arr[index]);
153
476
  });
154
477
  });
155
478
  }
156
- /**
157
- * 注册一个全局任务,每次按键都会被调用
158
- * @param task 回调函数
159
- */
160
479
  static use(task) {
161
480
  tasks.push(task);
162
481
  }
163
482
  }
164
- // 监听键盘输入事件
165
- process.stdin.on("keypress", (str, key) => {
166
- const rawKeyName = key?.name || "";
483
+ process.stdin.on('keypress', (str, key) => {
484
+ const rawKeyName = key?.name || '';
167
485
  const ctrl = Boolean(key?.ctrl);
168
486
  const alt = Boolean(key?.alt);
169
487
  handler(rawKeyName, {
@@ -172,98 +490,147 @@ process.stdin.on("keypress", (str, key) => {
172
490
  }, str);
173
491
  });
174
492
 
175
- const templateMblerConfig = {
176
- name: 'demo',
177
- description: 'demo',
178
- version: '0.0.0',
179
- mcVersion: '1.21.100',
180
- script: {
181
- main: '',
182
- },
183
- minify: false,
184
- outdir: {
185
- behavior: '',
186
- resources: '',
187
- dist: '',
188
- },
189
- build: {
190
- rollupPlugins: [],
191
- cache: "auto",
192
- bundle: true,
193
- onEnd: () => { },
194
- onStart: () => { },
195
- onWarn: () => { }
493
+ const logFile = path.join(os.homedir(), '.cache/mbler/latest.log');
494
+ function _clean(promise) {
495
+ return () => {
496
+ Logger.run = Logger.run.filter((item) => {
497
+ return item !== promise;
498
+ });
499
+ };
500
+ }
501
+ async function FileExsit$1(file) {
502
+ try {
503
+ const f = await fs$1.stat(file);
504
+ if (f)
505
+ return true;
196
506
  }
197
- };
507
+ catch {
508
+ return false;
509
+ }
510
+ return false;
511
+ }
512
+ function writeLog(logContent) {
513
+ async function write() {
514
+ try {
515
+ const dir = path.dirname(logFile);
516
+ if (!(await FileExsit$1(dir))) {
517
+ // ensure the directory exists, root-to-leaf
518
+ await fs$1.mkdir(dir, { recursive: true }).catch(() => void 0);
519
+ }
520
+ // if file does not exist, create it (touch)
521
+ if (!(await FileExsit$1(logFile))) {
522
+ await fs$1.writeFile(logFile, '');
523
+ }
524
+ }
525
+ catch (err) {
526
+ // if we can't prepare the log file, output to stderr but don't crash
527
+ console.error('[logger] unable to prepare log file:', err);
528
+ return;
529
+ }
530
+ try {
531
+ await fs$1.appendFile(logFile, '\n' + logContent);
532
+ }
533
+ catch (err) {
534
+ console.error('[logger] failed to append to log file:', err);
535
+ }
536
+ }
537
+ const asy = write();
538
+ Logger.run.push(asy.then(_clean(asy)));
539
+ }
540
+ class Logger {
541
+ static LogFile = logFile;
542
+ static run = [];
543
+ static _b(tag, msg, t) {
544
+ const date = new Date();
545
+ const logContent = [
546
+ `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`,
547
+ `[${t} ${tag}]`,
548
+ msg,
549
+ ].join(' ');
550
+ writeLog(logContent);
551
+ }
552
+ static w(tag, msg) {
553
+ Logger._b(tag, msg, 'WARN');
554
+ }
555
+ static e(tag, msg) {
556
+ Logger._b(tag, msg, 'ERROR');
557
+ }
558
+ static i(tag, msg) {
559
+ Logger._b(tag, msg, 'INFO');
560
+ }
561
+ static d(tag, msg) {
562
+ Logger._b(tag, msg, 'DEBUG');
563
+ }
564
+ }
198
565
 
199
566
  const BuildConfig = {
200
- ConfigFile: "mbler.config.js",
567
+ ConfigFile: 'mbler.config.js',
201
568
  salt: {
202
- header: "d61e721d-a2c9-4535-8054-0183bce24767",
203
- sapi: "33e2c698-908f-45ab-8a9f-66018f8486ed",
204
- module: "cbbacfa4-8b1e-4a9c-9cbd-7a0d2e5f0b3c",
569
+ header: 'd61e721d-a2c9-4535-8054-0183bce24767',
570
+ sapi: '33e2c698-908f-45ab-8a9f-66018f8486ed',
571
+ module: 'cbbacfa4-8b1e-4a9c-9cbd-7a0d2e5f0b3c',
205
572
  },
206
- behavior: "behavior",
207
- resources: "resources",
573
+ behavior: 'behavior',
574
+ resources: 'resources',
208
575
  includes: {
209
576
  public: {
210
- "pack_icon.png": "file",
211
- "manifest.json": "file",
577
+ 'pack_icon.png': 'file',
578
+ 'manifest.json': 'file',
212
579
  },
213
580
  resources: {
214
- "biomes_client.json": "file",
215
- "blocks.json": "file",
216
- "bug_pack_icon.png": "file",
217
- "contents.json": "file",
218
- "loading_messages.json": "file",
219
- "manifest_publish.json": "file",
220
- "signatures.json": "file",
221
- "sounds.json": "file",
222
- "splashes.json": "file",
223
- animation_controllers: "directory",
224
- animations: "directory",
225
- attachables: "directory",
226
- biomes: "directory",
227
- cameras: "directory",
228
- entity: "directory",
229
- fogs: "directory",
230
- font: "directory",
231
- items: "directory",
232
- library: "directory",
233
- materials: "directory",
234
- models: "directory",
235
- particles: "directory",
236
- render_controllers: "directory",
237
- sounds: "directory",
238
- texts: "directory",
239
- textures: "directory",
581
+ 'biomes_client.json': 'file',
582
+ 'blocks.json': 'file',
583
+ 'bug_pack_icon.png': 'file',
584
+ 'contents.json': 'file',
585
+ 'loading_messages.json': 'file',
586
+ 'manifest_publish.json': 'file',
587
+ 'signatures.json': 'file',
588
+ 'sounds.json': 'file',
589
+ 'splashes.json': 'file',
590
+ animation_controllers: 'directory',
591
+ animations: 'directory',
592
+ attachables: 'directory',
593
+ biomes: 'directory',
594
+ cameras: 'directory',
595
+ entity: 'directory',
596
+ fogs: 'directory',
597
+ font: 'directory',
598
+ items: 'directory',
599
+ library: 'directory',
600
+ materials: 'directory',
601
+ models: 'directory',
602
+ particles: 'directory',
603
+ render_controllers: 'directory',
604
+ sounds: 'directory',
605
+ texts: 'directory',
606
+ textures: 'directory',
240
607
  },
241
608
  behavior: {
242
- aim_assist: "directory",
243
- animation_controllers: "directory",
244
- animations: "directory",
245
- behavior_trees: "directory",
246
- biomes: "directory",
247
- blocks: "directory",
248
- cameras: "directory",
249
- dimensions: "directory",
250
- entities: "directory",
251
- feature_rules: "directory",
252
- features: "directory",
253
- functions: "directory",
254
- item_catalog: "directory",
255
- items: "directory",
256
- loot_tables: "directory",
257
- recipes: "directory",
258
- scripts: "skip", // special handling
259
- spawn_rules: "directory",
260
- structures: "directory",
261
- texts: "directory",
262
- trading: "directory",
263
- worldgen: "directory",
264
- "contents.json": "file",
265
- "manifest_publish.json": "file",
266
- "signatures.json": "file",
609
+ aim_assist: 'directory',
610
+ animation_controllers: 'directory',
611
+ animations: 'directory',
612
+ behavior_trees: 'directory',
613
+ biomes: 'directory',
614
+ blocks: 'directory',
615
+ cameras: 'directory',
616
+ dimensions: 'directory',
617
+ entities: 'directory',
618
+ feature_rules: 'directory',
619
+ features: 'directory',
620
+ functions: 'directory',
621
+ item_catalog: 'directory',
622
+ items: 'directory',
623
+ loot_tables: 'directory',
624
+ recipes: 'directory',
625
+ scripts: 'skip', // special handling
626
+ spawn_rules: 'directory',
627
+ structures: 'directory',
628
+ texts: 'directory',
629
+ trading: 'directory',
630
+ worldgen: 'directory',
631
+ 'contents.json': 'file',
632
+ 'manifest_publish.json': 'file',
633
+ 'signatures.json': 'file',
267
634
  },
268
635
  },
269
636
  };
@@ -290,14 +657,32 @@ async function ReadProjectMblerConfig(project) {
290
657
  throw new Error(`[read config]: read config from '${project}' error: Unexpected '${key}'`);
291
658
  }
292
659
  }
293
- return file;
660
+ const config = {
661
+ ...templateMblerConfig,
662
+ ...file,
663
+ };
664
+ try {
665
+ const pkgRaw = await fs__namespace.readFile(path__namespace.join(project, 'package.json'), 'utf-8');
666
+ const pkg = JSON.parse(pkgRaw);
667
+ if (pkg.name)
668
+ config.name = pkg.name;
669
+ if (pkg.version)
670
+ config.version = pkg.version;
671
+ }
672
+ catch {
673
+ // fallback to mbler.config.js or template defaults
674
+ }
675
+ if (!config.name)
676
+ config.name = 'unknown';
677
+ if (!config.version)
678
+ config.version = '0.0.0';
679
+ return config;
294
680
  }
295
681
  /**
296
682
  * Print a single-line message to stdout with a trailing newline.
297
683
  * Exported here so other modules (for example `build`) do not need
298
684
  * to import from `cli`, avoiding a circular dependency.
299
685
  */
300
- // IO缓冲队列,避免多线程写入冲突
301
686
  let outputQueue = [];
302
687
  let isFlushing = false;
303
688
  async function flushOutputQueue() {
@@ -316,11 +701,13 @@ async function flushOutputQueue() {
316
701
  isFlushing = false;
317
702
  }
318
703
  }
319
- process.on("exit", flushOutputQueue);
704
+ process.on('exit', flushOutputQueue);
320
705
  function showText(text, needNextLine = true) {
321
- outputQueue.push(text + (needNextLine ? '\n' : ""));
706
+ outputQueue.push(text + (needNextLine ? '\n' : ''));
322
707
  if (!isFlushing) {
323
- Promise.resolve().then(() => flushOutputQueue()).catch(() => {
708
+ Promise.resolve()
709
+ .then(() => flushOutputQueue())
710
+ .catch(() => {
324
711
  outputQueue = [];
325
712
  isFlushing = false;
326
713
  });
@@ -403,165 +790,54 @@ function compareVersion(a, b) {
403
790
  };
404
791
  }))();
405
792
 
406
- const logFile = path.join(os.homedir(), ".cache/mbler/latest.log");
407
- function _clean(promise) {
408
- return () => {
409
- Logger.run = Logger.run.filter((item) => {
410
- return item !== promise;
411
- });
412
- };
413
- }
414
- function writeLog(logContent) {
415
- async function write() {
416
- try {
417
- const dir = path.dirname(logFile);
418
- if (!(await FileExsit(dir))) {
419
- // ensure the directory exists, root-to-leaf
420
- await fs.mkdir(dir, { recursive: true }).catch(() => void 0);
421
- }
422
- // if file does not exist, create it (touch)
423
- if (!(await FileExsit(logFile))) {
424
- await fs.writeFile(logFile, "");
425
- }
426
- }
427
- catch (err) {
428
- // if we can't prepare the log file, output to stderr but don't crash
429
- console.error("[logger] unable to prepare log file:", err);
430
- return;
431
- }
432
- try {
433
- await fs.appendFile(logFile, "\n" + logContent);
434
- }
435
- catch (err) {
436
- console.error("[logger] failed to append to log file:", err);
437
- }
438
- }
439
- const asy = write();
440
- Logger.run.push(asy.then(_clean(asy)));
441
- }
442
- class Logger {
443
- // 写入日志池
444
- static LogFile = logFile;
445
- static run = [];
446
- static _b(tag, msg, t) {
447
- const date = new Date();
448
- const logContent = [
449
- `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`,
450
- `[${t} ${tag}]`,
451
- msg,
452
- ].join(" ");
453
- writeLog(logContent);
454
- }
455
- static w(tag, msg) {
456
- Logger._b(tag, msg, "WARN");
457
- }
458
- static e(tag, msg) {
459
- Logger._b(tag, msg, "ERROR");
460
- }
461
- static i(tag, msg) {
462
- Logger._b(tag, msg, "INFO");
463
- }
464
- static d(tag, msg) {
465
- Logger._b(tag, msg, "DEBUG");
466
- }
467
- }
468
-
469
793
  class BuildCacheManager {
470
- projectRoot;
471
794
  isWatch;
472
- cacheDir;
473
- cacheFile;
474
795
  mode;
475
- memoryCache;
476
- constructor(projectRoot, mode, isWatch) {
477
- this.projectRoot = projectRoot;
796
+ constructor(_projectRoot, mode, isWatch, _cachePath) {
478
797
  this.isWatch = isWatch;
479
- this.cacheDir = path.join(this.projectRoot, ".mbler", "cache");
480
- this.cacheFile = path.join(this.cacheDir, "rollup.cache.bin");
481
798
  this.mode = this.resolveMode(mode);
482
799
  }
483
800
  getMode() {
484
801
  return this.mode;
485
802
  }
486
- async getRollupCache() {
487
- if (this.mode === "none")
488
- return undefined;
489
- if (this.mode === "memory")
490
- return this.memoryCache;
491
- if (this.memoryCache)
492
- return this.memoryCache;
493
- try {
494
- const raw = await fs.readFile(this.cacheFile);
495
- this.memoryCache = node_v8.deserialize(raw);
496
- return this.memoryCache;
497
- }
498
- catch {
499
- return undefined;
500
- }
501
- }
502
- getWatchCacheOption() {
503
- if (this.mode === "none")
504
- return false;
505
- return true;
506
- }
507
- async saveRollupCache(cache) {
508
- if (!cache || this.mode === "none")
509
- return;
510
- this.memoryCache = cache;
511
- if (this.mode !== "file")
512
- return;
513
- try {
514
- await fs.mkdir(this.cacheDir, { recursive: true });
515
- await fs.writeFile(this.cacheFile, node_v8.serialize(cache));
516
- }
517
- catch (error) {
518
- Logger.w("BuildCache", `failed to write file cache: ${error}`);
519
- }
803
+ shouldUseIncrementalBuild() {
804
+ return this.mode !== 'none';
520
805
  }
521
806
  resolveMode(mode) {
522
- const value = mode ?? "auto";
523
- if (value === "none")
524
- return "none";
525
- if (value === "memory") {
526
- if (this.isWatch)
527
- return "memory";
528
- return "none";
529
- }
530
- if (value === "file" || value === "filesystem")
531
- return "file";
532
- // auto: watch mode uses memory, non-watch uses file
533
- return this.isWatch ? "memory" : "file";
807
+ const value = mode ?? 'auto';
808
+ if (value === 'none')
809
+ return 'none';
810
+ return 'file';
534
811
  }
535
812
  }
536
813
 
537
- // 该模块用于从字符串生成哈希转 uuid
814
+ /**
815
+ * @description To generate uuid
816
+ */
538
817
  const fromString = (input, salt = '') => {
539
818
  const combinedInput = salt + input;
540
- const hash = crypto
541
- .createHash('sha256')
542
- .update(combinedInput)
543
- .digest('hex');
544
- const base = hash
545
- .slice(0, 32); // 取前 32 个 hex 字符(16 字节)
819
+ const hash = crypto.createHash('sha256').update(combinedInput).digest('hex');
820
+ const base = hash.slice(0, 32);
546
821
  const ls = '89ab';
547
822
  const r = (t) => ls[(combinedInput.length + t + salt.length) % ls.length];
548
- // 构造成标准 UUID v4 格式:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
823
+ // build to:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
549
824
  const uuid = `${base.substring(0, 8)}-${base.substring(8, 12)}-4${base.substring(12, 15)}-8${r(1)}${r(2)}${r(3)}-${base.substring(18, 30)}`;
550
825
  return uuid;
551
826
  };
552
827
  ({
553
- uuid: crypto.randomUUID
828
+ uuid: crypto.randomUUID,
554
829
  });
555
830
 
556
831
  const config = {
557
- tmpdir: path__namespace.join(os.tmpdir(), ".mbler")};
832
+ tmpdir: path__namespace.join(os.tmpdir(), '.mbler')};
558
833
 
559
834
  /**
560
835
  * Compare two dotted version strings ("major.minor.patch").
561
836
  * Returns negative if a < b, positive if a > b, zero if equal.
562
837
  */
563
- const exp = (function () {
564
- const cacheFile = path__namespace.join(config.tmpdir, "_sapi_version.json");
838
+ const Sapi = function () {
839
+ const { json } = require('npm-registry-fetch');
840
+ const cacheFile = path__namespace.join(config.tmpdir, '_sapi_version.json');
565
841
  // cacheData is an array of entries keyed by the embedded mc version string
566
842
  let cacheData = null;
567
843
  /**
@@ -570,7 +846,7 @@ const exp = (function () {
570
846
  * recent formal/beta release we were able to parse.
571
847
  */
572
848
  async function fetchData(pkgName) {
573
- const data = (await npmRegistryFetch.json(`/${pkgName}`));
849
+ const data = (await json(`/${pkgName}`));
574
850
  const pkgVersions = Object.keys(data.versions);
575
851
  const reValue = {};
576
852
  // helper to extract the embedded MC version ("yyyy") from a full
@@ -587,7 +863,11 @@ const exp = (function () {
587
863
  const isStable = /(?:-stable)(?:$|[-.])/.test(v);
588
864
  let entry = reValue[mcVersion];
589
865
  if (!entry) {
590
- entry = { formal: "", beta: "", _v: -1 };
866
+ entry = {
867
+ formal: '',
868
+ beta: '',
869
+ _v: -1,
870
+ };
591
871
  reValue[mcVersion] = entry;
592
872
  }
593
873
  if (isStable) {
@@ -610,8 +890,8 @@ const exp = (function () {
610
890
  }
611
891
  async function refresh() {
612
892
  // grab the two packages we care about and merge the keys
613
- const serverMap = await fetchData("@minecraft/server");
614
- const uiMap = await fetchData("@minecraft/server-ui");
893
+ const serverMap = await fetchData('@minecraft/server');
894
+ const uiMap = await fetchData('@minecraft/server-ui');
615
895
  const versions = new Set([
616
896
  ...Object.keys(serverMap),
617
897
  ...Object.keys(uiMap),
@@ -621,24 +901,38 @@ const exp = (function () {
621
901
  arr.push({
622
902
  version: ver,
623
903
  server: serverMap[ver]
624
- ? { formal: serverMap[ver].formal, beta: serverMap[ver].beta }
625
- : { formal: "", beta: "" },
626
- "server-ui": uiMap[ver]
627
- ? { formal: uiMap[ver].formal, beta: uiMap[ver].beta }
628
- : { formal: "", beta: "" },
904
+ ? {
905
+ formal: serverMap[ver].formal,
906
+ beta: serverMap[ver].beta,
907
+ }
908
+ : {
909
+ formal: '',
910
+ beta: '',
911
+ },
912
+ 'server-ui': uiMap[ver]
913
+ ? {
914
+ formal: uiMap[ver].formal,
915
+ beta: uiMap[ver].beta,
916
+ }
917
+ : {
918
+ formal: '',
919
+ beta: '',
920
+ },
629
921
  });
630
922
  }
631
923
  arr.sort((a, b) => compareVersion(a.version, b.version));
632
924
  cacheData = arr;
633
925
  await fs__namespace$1.promises
634
- .mkdir(config.tmpdir, { recursive: true })
926
+ .mkdir(config.tmpdir, {
927
+ recursive: true,
928
+ })
635
929
  .catch(() => void 0);
636
- await fs__namespace$1.promises.writeFile(cacheFile, JSON.stringify(arr, null, 2), "utf-8");
930
+ await fs__namespace$1.promises.writeFile(cacheFile, JSON.stringify(arr, null, 2), 'utf-8');
637
931
  }
638
- async function generateVersion(module, mcVersion, isBeta) {
932
+ async function generateVersion(module, mcVersion, isBeta, withFull = false) {
639
933
  if (!cacheData) {
640
934
  try {
641
- const txt = await fs__namespace$1.promises.readFile(cacheFile, "utf-8");
935
+ const txt = await fs__namespace$1.promises.readFile(cacheFile, 'utf-8');
642
936
  cacheData = JSON.parse(txt);
643
937
  }
644
938
  catch {
@@ -646,7 +940,7 @@ const exp = (function () {
646
940
  }
647
941
  }
648
942
  if (!cacheData) {
649
- throw new Error("unable to load sapi cache data");
943
+ throw new Error('unable to load sapi cache data');
650
944
  }
651
945
  // try exact match first
652
946
  let entry = cacheData.find((e) => e.version === mcVersion);
@@ -667,26 +961,50 @@ const exp = (function () {
667
961
  }
668
962
  entry = candidate;
669
963
  }
670
- const moduleKey = module === "@minecraft/server" ? "server" : "server-ui";
964
+ const moduleKey = module === '@minecraft/server' ? 'server' : 'server-ui';
671
965
  const entryModule = entry[moduleKey];
672
966
  let result = isBeta ? entryModule.beta : entryModule.formal;
673
967
  if (!result) {
674
968
  // fall back to whatever is available
675
969
  result = entryModule.formal || entryModule.beta;
676
970
  }
677
- const tmp = result.split("-").slice(0, 2);
678
- tmp[1] = tmp[1].split(".")[0];
679
- result = tmp.join("-");
680
- return result || "";
971
+ if (withFull)
972
+ return result || '';
973
+ else {
974
+ const tmp = result.split('-').slice(0, 2);
975
+ tmp[1] = tmp[1].split('.')[0];
976
+ result = tmp.join('-');
977
+ return result || 'error';
978
+ }
681
979
  }
682
980
  return {
683
981
  refresh,
684
982
  generateVersion,
685
983
  };
686
- })();
984
+ };
985
+ let sapiEmul = null;
986
+ var Sapi$1 = new Proxy({}, {
987
+ get(_, p) {
988
+ if (!sapiEmul)
989
+ sapiEmul = Sapi();
990
+ return sapiEmul[p];
991
+ },
992
+ set(_, p, n) {
993
+ if (!sapiEmul)
994
+ sapiEmul = Sapi();
995
+ sapiEmul[p] = n;
996
+ return true;
997
+ },
998
+ });
999
+ function evalVersion(result) {
1000
+ const tmp = result.split('-').slice(0, 2);
1001
+ tmp[1] = tmp[1].split('.')[0];
1002
+ result = tmp.join('-');
1003
+ return result;
1004
+ }
687
1005
 
688
1006
  async function generateManifest(config, type) {
689
- const hashRaw = `${config.name}-${type}-${config.script?.lang || "js"}--mbler-hash-raw--:build-manifest`;
1007
+ const hashRaw = `${config.name}-${type}-${config.script?.lang || 'js'}--mbler-hash-raw--:build-manifest`;
690
1008
  const manifest = {
691
1009
  format_version: 2,
692
1010
  header: {
@@ -694,10 +1012,10 @@ async function generateManifest(config, type) {
694
1012
  description: config.description,
695
1013
  uuid: fromString(hashRaw, BuildConfig.salt.header),
696
1014
  version: stringToNumberArray(config.version),
697
- min_engine_version: stringToNumberArray(typeof config.mcVersion === "string"
1015
+ min_engine_version: stringToNumberArray(typeof config.mcVersion === 'string'
698
1016
  ? config.mcVersion
699
1017
  : (() => {
700
- throw new Error("mcVersion in mblerconfig should be a string");
1018
+ throw new Error('mcVersion in mblerconfig should be a string');
701
1019
  })()),
702
1020
  },
703
1021
  modules: [
@@ -709,80 +1027,106 @@ async function generateManifest(config, type) {
709
1027
  },
710
1028
  ],
711
1029
  };
712
- if (type === "data" && config.script) {
713
- let entry = config.script.main || "scripts/index.js";
714
- if (config.script.lang == "mcx" && config.build?.bundle) {
715
- entry = "scripts/index.js";
1030
+ if (type === 'data' && config.script) {
1031
+ const isBundle = config.build?.bundle !== false;
1032
+ const outputDir = config.build?.outputDir || 'scripts';
1033
+ let entry;
1034
+ if (isBundle) {
1035
+ let filename = config.script.main || 'index.js';
1036
+ if (config.build?.outputFilename) {
1037
+ filename = config.build.outputFilename;
1038
+ }
1039
+ const extName = path.extname(filename);
1040
+ if (extName !== '.js') {
1041
+ filename = filename.slice(0, -extName.length) + '.js';
1042
+ }
1043
+ if (config.script.lang == 'mcx') {
1044
+ entry = `${outputDir}/index.js`;
1045
+ }
1046
+ else {
1047
+ entry = `${outputDir}/${filename}`;
1048
+ }
716
1049
  }
717
1050
  else {
718
- entry = `scripts/${entry}`;
719
- }
720
- const extName = path.extname(entry);
721
- if (extName !== ".js") {
722
- entry = entry.slice(0, -extName.length) + ".js";
1051
+ entry = `${outputDir}/${config.script.main || 'index.js'}`;
1052
+ const extName = path.extname(entry);
1053
+ if (extName !== '.js') {
1054
+ entry = entry.slice(0, -extName.length) + '.js';
1055
+ }
723
1056
  }
724
1057
  manifest.modules.push({
725
- type: "script",
1058
+ type: 'script',
726
1059
  entry: entry,
727
- language: "javascript",
1060
+ language: 'javascript',
728
1061
  uuid: fromString(hashRaw, BuildConfig.salt.sapi),
729
1062
  description: `sapi generate by mbler, weclome to download and star at https://github.com/RuanhoR/mbler`,
730
1063
  version: stringToNumberArray(config.version),
731
1064
  });
732
- manifest.capabilities = ["script_eval"];
1065
+ manifest.capabilities = ['script_eval'];
733
1066
  manifest.dependencies = [
734
1067
  {
735
- module_name: "@minecraft/server",
736
- version: (await exp.generateVersion("@minecraft/server", config.mcVersion, config.script?.UseBeta || false)), // only major.minor.patch, remove -beta or -rc
1068
+ module_name: '@minecraft/server',
1069
+ version: evalVersion(await Sapi$1.generateVersion('@minecraft/server', config.mcVersion, config.script?.UseBeta || false, false)), // only major.minor.patch, remove -beta or -rc
737
1070
  },
738
1071
  ];
739
1072
  if (config.script.ui) {
740
1073
  manifest.dependencies.push({
741
- module_name: "@minecraft/server-ui",
742
- version: (await exp.generateVersion("@minecraft/server-ui", config.mcVersion, config.script?.UseBeta || false)), // only major.minor.patch, remove -beta or -rc
1074
+ module_name: '@minecraft/server-ui',
1075
+ version: evalVersion(await Sapi$1.generateVersion('@minecraft/server-ui', config.mcVersion, config.script?.UseBeta || false, false)), // only major.minor.patch, remove -beta or -rc
743
1076
  });
744
1077
  }
745
1078
  }
746
1079
  return manifest;
747
1080
  }
748
1081
 
749
- function createFullZip(dir) {
750
- const zip = new AdmZip();
751
- zip.addLocalFolder(dir);
752
- return zip;
753
- }
754
- async function createZipWithMoreFolder(dir) {
755
- const zip = new AdmZip();
756
- for (const folder of dir) {
757
- await zip.addLocalFolderPromise(folder[0], {
758
- zipPath: folder[1]
759
- });
1082
+ function Release() {
1083
+ const AdmZip = require('adm-zip');
1084
+ function createFullZip(dir) {
1085
+ const zip = new AdmZip();
1086
+ zip.addLocalFolder(dir);
1087
+ return zip;
760
1088
  }
761
- return zip;
762
- }
763
- async function generateRelease(build) {
764
- if (!build.outdirs)
765
- throw new Error("invalid Build");
766
- if (node_process.env.BUILD_MODULE !== "release")
767
- return;
768
- let zip;
769
- if (build.module == "all") {
770
- zip = await createZipWithMoreFolder([
771
- [build.outdirs?.behavior, "behavior"],
772
- [build.outdirs?.resources, "resources"]
773
- ]);
774
- }
775
- else if (build.module == "behavior") {
776
- zip = createFullZip(build.outdirs?.behavior);
777
- }
778
- else {
779
- zip = createFullZip(build.outdirs?.resources);
1089
+ async function createZipWithMoreFolder(dir) {
1090
+ const zip = new AdmZip();
1091
+ for (const folder of dir) {
1092
+ await zip.addLocalFolderPromise(folder[0], {
1093
+ zipPath: folder[1],
1094
+ });
1095
+ }
1096
+ return zip;
780
1097
  }
781
- await zip.writeZipPromise(build.outdirs?.dist);
1098
+ return async function generateRelease(build) {
1099
+ if (!build.outdirs)
1100
+ throw new Error('invalid Build');
1101
+ if (node_process.env.BUILD_MODULE !== 'release')
1102
+ return;
1103
+ let zip;
1104
+ if (build.module == 'all') {
1105
+ zip = await createZipWithMoreFolder([
1106
+ [build.outdirs?.behavior, 'behavior'],
1107
+ [build.outdirs?.resources, 'resources'],
1108
+ ]);
1109
+ }
1110
+ else if (build.module == 'behavior') {
1111
+ zip = createFullZip(build.outdirs?.behavior);
1112
+ }
1113
+ else {
1114
+ zip = createFullZip(build.outdirs?.resources);
1115
+ }
1116
+ await zip.writeZipPromise(build.outdirs?.dist);
1117
+ };
782
1118
  }
1119
+ let releaseEmul = null;
1120
+ const generateRelease = (...argv) => {
1121
+ if (!releaseEmul)
1122
+ releaseEmul = Release();
1123
+ return releaseEmul(...argv);
1124
+ };
783
1125
 
784
1126
  // cjs support
785
- const chalk$1 = _chalk instanceof Function ? _chalk : _chalk.default;
1127
+ const chalk$1 = _chalk instanceof Function
1128
+ ? _chalk
1129
+ : _chalk.default;
786
1130
  class Postgress {
787
1131
  max;
788
1132
  constructor(max) {
@@ -800,7 +1144,7 @@ class Postgress {
800
1144
  const progressText = `\n\u001B[1A\r[${progressBar}] ${percentText} (${current}/${this.max})`;
801
1145
  showText(progressText, false);
802
1146
  if (current == this.max) {
803
- showText("", true);
1147
+ showText('', true);
804
1148
  }
805
1149
  }
806
1150
  }
@@ -809,7 +1153,7 @@ class Postgress {
809
1153
  * 运行 MCX TypeScript 编译器
810
1154
  * 为 .mcx 文件提供 TypeScript 类型检查支持
811
1155
  */
812
- function runTSC(tscpath = require.resolve("typescript/lib/tsc")) {
1156
+ function runTSC(tscpath = require.resolve('typescript/lib/tsc')) {
813
1157
  runTsc_js.runTsc(tscpath, {
814
1158
  extraSupportedExtensions: ['.mcx'],
815
1159
  extraExtensionsToRemove: ['.mcx'],
@@ -818,8 +1162,10 @@ function runTSC(tscpath = require.resolve("typescript/lib/tsc")) {
818
1162
  });
819
1163
  }
820
1164
 
821
- // cjs support
822
- const chalk = _chalk instanceof Function ? _chalk : _chalk.default;
1165
+ // cjs support (Why is chalk's type so weak? )
1166
+ const chalk = _chalk instanceof Function
1167
+ ? _chalk
1168
+ : _chalk.default;
823
1169
  class Build {
824
1170
  baseBuildDir;
825
1171
  resolve;
@@ -835,12 +1181,13 @@ class Build {
835
1181
  this.isWatch = isWatch;
836
1182
  try {
837
1183
  const tsModule = ts;
838
- this.mcxLanguagePluginCreator = mcxServer.createMCXLanguagePlugin;
1184
+ this.mcxLanguagePluginCreator =
1185
+ mcxServer.createMCXLanguagePlugin;
839
1186
  this.mcxTs = tsModule;
840
1187
  }
841
1188
  catch (error) {
842
1189
  this.mcxTs = ts;
843
- Logger.w("Build", `Failed to initialize MCX language plugin: ${error}`);
1190
+ Logger.w('Build', `Failed to initialize MCX language plugin: ${error}`);
844
1191
  }
845
1192
  }
846
1193
  /**
@@ -855,7 +1202,7 @@ class Build {
855
1202
  onEnd(() => {
856
1203
  if (this.watchers) {
857
1204
  this.watchers.chokidar.close();
858
- this.watchers.rollup.close();
1205
+ this.watchers.rollup?.close();
859
1206
  }
860
1207
  });
861
1208
  await this._watch();
@@ -908,7 +1255,7 @@ class Build {
908
1255
  closeWatchers() {
909
1256
  if (this.watchers) {
910
1257
  this.watchers.chokidar.close();
911
- this.watchers.rollup.close();
1258
+ this.watchers.rollup?.close();
912
1259
  this.watchers = null;
913
1260
  }
914
1261
  }
@@ -968,7 +1315,7 @@ class Build {
968
1315
  this.currentConfig = await ReadProjectMblerConfig(this.baseBuildDir);
969
1316
  if (this.currentConfig.build)
970
1317
  this.buildConfig = this.currentConfig.build;
971
- this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch);
1318
+ this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch, this.buildConfig?.cachePath);
972
1319
  if (this.buildConfig?.onStart)
973
1320
  await this.buildConfig.onStart(this.currentConfig);
974
1321
  this.loadData();
@@ -978,38 +1325,48 @@ class Build {
978
1325
  await this.handlerManifest();
979
1326
  if (!this.isWatch)
980
1327
  progress.update(30);
981
- const rBuild = (await this.createRollup());
982
- if (!this.rollupPlugin || !this.outdirs) {
983
- throw new Error(`[build addon]: can't resolve rollup instance`);
984
- }
985
- if (!this.isWatch)
986
- progress.update(50);
987
- // write script
988
- let output = this.currentConfig.script?.main;
989
- if (!output)
990
- output = "index.js";
991
- if (path.extname(output) !== "js")
992
- output = output.slice(0, output.length - path.extname(output).length) + ".js";
993
- if (this.currentConfig.script)
994
- await rBuild.write(this.currentConfig.build?.bundle ? {
995
- file: join(path.join(this.outdirs.behavior, "scripts"), output),
996
- format: 'esm',
997
- sourcemap: false,
998
- } :
999
- {
1000
- dir: path.join(this.outdirs.behavior, "scripts"),
1328
+ const isBundle = this.currentConfig.build?.bundle !== false;
1329
+ if (this.currentConfig.script) {
1330
+ if (isBundle) {
1331
+ const rBuild = (await this.createRollup());
1332
+ if (!this.rollupPlugin || !this.outdirs) {
1333
+ throw new Error(`[build addon]: can't resolve rollup instance`);
1334
+ }
1335
+ if (!this.isWatch)
1336
+ progress.update(50);
1337
+ // write script
1338
+ let output = this.currentConfig.script?.main;
1339
+ if (!output)
1340
+ output = 'index.js';
1341
+ if (path.extname(output) !== 'js')
1342
+ output =
1343
+ output.slice(0, output.length - path.extname(output).length) + '.js';
1344
+ if (this.buildConfig?.outputFilename)
1345
+ output = this.buildConfig.outputFilename;
1346
+ const outputDir = this.buildConfig?.outputDir || 'scripts';
1347
+ await rBuild.write({
1348
+ file: join(path.join(this.outdirs.behavior, outputDir), output),
1001
1349
  format: 'esm',
1002
1350
  sourcemap: false,
1003
- chunkFileNames: '[name].js',
1004
1351
  });
1005
- await this.cacheManager?.saveRollupCache(rBuild.cache);
1352
+ }
1353
+ else {
1354
+ // bundle: false – skip rollup, copy source scripts directly
1355
+ const srcScriptDir = path.join(this.srcDirs.behavior, 'scripts');
1356
+ const outputDir = this.buildConfig?.outputDir || 'scripts';
1357
+ const outPath = path.join(this.outdirs.behavior, outputDir);
1358
+ if (await FileExsit(srcScriptDir)) {
1359
+ await fs__namespace.cp(srcScriptDir, outPath, { recursive: true, force: true });
1360
+ }
1361
+ }
1362
+ }
1006
1363
  if (!this.isWatch)
1007
1364
  progress.update(70);
1008
1365
  if (!this.outdirs || !this.module)
1009
1366
  throw new Error(`[build addon]: can't resolve outdirs`);
1010
1367
  await generateRelease({
1011
1368
  outdirs: this.outdirs,
1012
- module: this.module
1369
+ module: this.module,
1013
1370
  });
1014
1371
  if (!this.isWatch)
1015
1372
  progress.update(80);
@@ -1035,13 +1392,7 @@ class Build {
1035
1392
  if (!(await FileExsit(main))) {
1036
1393
  throw new Error(`[build addon]: main script ${main} is not exist: can't resolve entry`);
1037
1394
  }
1038
- const plugin = [
1039
- jsonPlugin(),
1040
- resolvePlugin({
1041
- extensions: ['.ts', '.js', '.json'],
1042
- }),
1043
- commonjs()
1044
- ];
1395
+ const plugin = [];
1045
1396
  const moduleDir = path.join(this.baseBuildDir, 'node_modules');
1046
1397
  if (!(await FileExsit(moduleDir))) {
1047
1398
  throw new Error(`[build addon]: node_modules is not exist in project root: can't resolve node_modules for rollup: ${moduleDir}`);
@@ -1059,23 +1410,6 @@ class Build {
1059
1410
  if (this.buildConfig?.rollupPlugins) {
1060
1411
  plugin.push(...this.buildConfig.rollupPlugins);
1061
1412
  }
1062
- if (this.currentConfig.script.lang == "ts") {
1063
- const tsconfigPath = path.join(this.baseBuildDir, 'tsconfig.json');
1064
- if (!(await FileExsit(tsconfigPath))) {
1065
- throw new Error(`[build addon]: ts-lang: tsconfig.json is not exist in project root: can't resolve tsconfig for rollup: ${tsconfigPath}`);
1066
- }
1067
- plugin.push(typescript({
1068
- sourceMap: false,
1069
- tsconfig: tsconfigPath,
1070
- exclude: [
1071
- this.outdirs.behavior,
1072
- this.outdirs.resources
1073
- ],
1074
- include: [
1075
- this.srcDirs.behavior
1076
- ]
1077
- }));
1078
- }
1079
1413
  if (this.currentConfig.script?.lang == 'mcx') {
1080
1414
  try {
1081
1415
  const tsconfigPath = path.join(this.baseBuildDir, 'tsconfig.json');
@@ -1087,38 +1421,50 @@ class Build {
1087
1421
  tsconfigPath: tsconfigPath,
1088
1422
  sourcemap: false,
1089
1423
  ts: this.mcxTs,
1090
- mcxLanguagePlugin: this.mcxLanguagePluginCreator
1091
1424
  };
1092
1425
  if (this.mcxLanguagePluginCreator) {
1093
1426
  pluginConfig.mcxLanguagePlugin = this.mcxLanguagePluginCreator;
1094
1427
  }
1095
- plugin.push(mcxDef__namespace.plugin(pluginConfig, this.outdirs));
1428
+ plugin.push(mcxDef__namespace.rolldownPlugin(pluginConfig, this.outdirs));
1096
1429
  }
1097
1430
  catch (err) {
1098
- throw new Error(`[build addon]: mcx plugin is required but '@mbler/mcx-core' could not be loaded: ${err}`);
1431
+ throw new Error(`[build addon]: mcx plugin is required but '@mbler/mcx-core' could not be loaded: ${err}`, { cause: err });
1099
1432
  }
1100
1433
  }
1101
1434
  // save plugin array for watcher re-use
1102
1435
  this.rollupPlugin = plugin;
1103
1436
  const rollupOption = {
1104
1437
  input: main,
1105
- external: ['@minecraft/server', '@minecraft/server-ui'],
1438
+ external: [
1439
+ '@minecraft/server',
1440
+ '@minecraft/server-ui',
1441
+ ...(this.buildConfig?.rollupExternal ?? []),
1442
+ ],
1106
1443
  plugins: plugin,
1107
- cache: await this.cacheManager?.getRollupCache(),
1444
+ experimental: {
1445
+ ...(this.cacheManager?.shouldUseIncrementalBuild()
1446
+ ? { incrementalBuild: true }
1447
+ : {}),
1448
+ },
1108
1449
  };
1109
- if (this.buildConfig?.onWarn)
1110
- rollupOption.onwarn = (warning) => {
1111
- this.buildConfig?.onWarn?.(this.currentConfig, warning instanceof Error ? warning : new Error(warning.message));
1450
+ if (this.buildConfig?.onWarn) {
1451
+ const onWarn = (warning, _defaultHandler) => {
1452
+ const msg = typeof warning === 'string'
1453
+ ? warning
1454
+ : warning.message || 'Unknown warning';
1455
+ this.buildConfig?.onWarn?.(this.currentConfig, new Error(msg));
1112
1456
  };
1457
+ rollupOption.onwarn = onWarn;
1458
+ }
1113
1459
  if (this.buildConfig?.onEnd) {
1114
1460
  plugin.push({
1115
1461
  name: 'build-end-plugin',
1116
1462
  buildEnd: () => {
1117
1463
  return this.buildConfig?.onEnd?.(this.currentConfig);
1118
- }
1464
+ },
1119
1465
  });
1120
1466
  }
1121
- return await rollup__namespace.rollup(rollupOption);
1467
+ return await rolldown.rolldown(rollupOption);
1122
1468
  }
1123
1469
  /**
1124
1470
  * Internal helper invoked by {@link watch}.
@@ -1129,7 +1475,7 @@ class Build {
1129
1475
  if (!this.init) {
1130
1476
  await this.build();
1131
1477
  }
1132
- this.createWatcher();
1478
+ await this.createWatcher();
1133
1479
  // watchers field is populated by createWatcher
1134
1480
  }
1135
1481
  isParent(parent, dir) {
@@ -1152,7 +1498,7 @@ class Build {
1152
1498
  }
1153
1499
  return false;
1154
1500
  }
1155
- createRollupWatcher() {
1501
+ async createRollupWatcher() {
1156
1502
  if (!this.srcDirs ||
1157
1503
  !this.outdirs ||
1158
1504
  !this.currentConfig ||
@@ -1160,24 +1506,31 @@ class Build {
1160
1506
  throw new Error(`[build addon]: can't first can this method`);
1161
1507
  let output = this.currentConfig.script?.main;
1162
1508
  if (!output)
1163
- output = "index.js";
1164
- if (path.extname(output) !== "js")
1165
- output = output.slice(0, output.length - path.extname(output).length) + ".js";
1166
- const rollupWatcher = rollup__namespace.watch({
1509
+ output = 'index.js';
1510
+ if (path.extname(output) !== 'js')
1511
+ output =
1512
+ output.slice(0, output.length - path.extname(output).length) + '.js';
1513
+ if (this.buildConfig?.outputFilename)
1514
+ output = this.buildConfig.outputFilename;
1515
+ const outputDir = this.buildConfig?.outputDir || 'scripts';
1516
+ const rollupWatcher = rolldown.watch({
1167
1517
  input: path.join(this.srcDirs.behavior, 'scripts', this.currentConfig?.script?.main || ''),
1168
- external: ['@minecraft/server', '@minecraft/server-ui'],
1518
+ external: [
1519
+ '@minecraft/server',
1520
+ '@minecraft/server-ui',
1521
+ ...(this.buildConfig?.rollupExternal ?? []),
1522
+ ],
1169
1523
  plugins: this.rollupPlugin,
1170
- output: this.currentConfig.build?.bundle ? {
1171
- file: join(path.join(this.outdirs.behavior, "scripts"), output),
1172
- format: 'esm',
1173
- sourcemap: false,
1174
- } : {
1175
- dir: join(path.join(this.outdirs.behavior, "scripts"), output),
1524
+ experimental: {
1525
+ ...(this.cacheManager?.shouldUseIncrementalBuild()
1526
+ ? { incrementalBuild: true }
1527
+ : {}),
1528
+ },
1529
+ output: {
1530
+ file: join(path.join(this.outdirs.behavior, outputDir), output),
1176
1531
  format: 'esm',
1177
- chunkFileNames: '[name].js',
1178
1532
  sourcemap: false,
1179
1533
  },
1180
- cache: this.cacheManager?.getWatchCacheOption() ?? true,
1181
1534
  watch: {
1182
1535
  clearScreen: false,
1183
1536
  include: path.join(this.srcDirs.behavior, 'scripts/**/*'),
@@ -1203,28 +1556,32 @@ class Build {
1203
1556
  else if (event.code === 'END') {
1204
1557
  Logger.i('Watcher', `rebuild success`);
1205
1558
  }
1206
- else if (event.code === 'BUNDLE_END') {
1207
- await this.cacheManager?.saveRollupCache(event.result?.cache);
1208
- }
1559
+ else if (event.code === 'BUNDLE_END') ;
1209
1560
  });
1210
1561
  return rollupWatcher;
1211
1562
  }
1212
1563
  async onChange(filePath) {
1564
+ const isBundle = this.currentConfig?.build?.bundle !== false;
1213
1565
  if (!this.srcDirs ||
1214
1566
  !this.outdirs ||
1215
1567
  !this.currentConfig ||
1216
- !this.rollupPlugin ||
1568
+ (isBundle && !this.rollupPlugin) ||
1217
1569
  !this.watchers)
1218
1570
  throw new Error(`[build addon]: can't first can this method`);
1219
- const isConfigChange = path.relative(path.join(this.baseBuildDir, 'mbler.config.json'), filePath) === '';
1220
- const isBehaviorChange = this.isParent(this.srcDirs.behavior, filePath) && !this.isParent(path.join(this.srcDirs.behavior, 'scripts'), filePath);
1571
+ const isConfigChange = path.relative(path.join(this.baseBuildDir, BuildConfig.ConfigFile), filePath) === '';
1572
+ const isPkgChange = path.relative(path.join(this.baseBuildDir, 'package.json'), filePath) ===
1573
+ '';
1574
+ const isScriptsChange = !isBundle &&
1575
+ this.isParent(path.join(this.srcDirs.behavior, 'scripts'), filePath);
1576
+ const isBehaviorChange = this.isParent(this.srcDirs.behavior, filePath) &&
1577
+ !this.isParent(path.join(this.srcDirs.behavior, 'scripts'), filePath);
1221
1578
  const isResourcesChange = this.isParent(this.srcDirs.resources, filePath);
1222
- if (isConfigChange) {
1579
+ if (isConfigChange || isPkgChange) {
1223
1580
  const oldConfig = this.currentConfig;
1224
- Logger.i('Watcher', 'detected mbler.config.json change, reload config');
1581
+ Logger.i('Watcher', 'detected config change, reload config');
1225
1582
  this.currentConfig = await ReadProjectMblerConfig(this.baseBuildDir);
1226
1583
  this.buildConfig = this.currentConfig.build || null;
1227
- this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch);
1584
+ this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch, this.buildConfig?.cachePath);
1228
1585
  this.loadData();
1229
1586
  if (this.isChange(oldConfig, this.currentConfig, [
1230
1587
  'name',
@@ -1234,12 +1591,31 @@ class Build {
1234
1591
  ])) {
1235
1592
  await this.handlerManifest();
1236
1593
  }
1237
- if (this.isChange(oldConfig, this.currentConfig, ['script', 'outdir'])) {
1238
- this.watchers.rollup.close();
1239
- await this.createRollup();
1240
- this.watchers.rollup = this.createRollupWatcher();
1594
+ if (this.isChange(oldConfig, this.currentConfig, ['script', 'outdir', 'build'])) {
1595
+ const newIsBundle = this.currentConfig.build?.bundle !== false;
1596
+ if (newIsBundle && this.watchers.rollup) {
1597
+ this.watchers.rollup.close();
1598
+ await this.createRollup();
1599
+ this.watchers.rollup = await this.createRollupWatcher();
1600
+ }
1601
+ else if (newIsBundle) {
1602
+ await this.createRollup();
1603
+ this.watchers.rollup = await this.createRollupWatcher();
1604
+ }
1605
+ else {
1606
+ if (this.watchers.rollup) {
1607
+ this.watchers.rollup.close();
1608
+ }
1609
+ this.watchers.rollup = null;
1610
+ }
1241
1611
  }
1242
1612
  }
1613
+ // if bundle: false and a script file changed, copy it directly
1614
+ if (isScriptsChange) {
1615
+ const outputDir = this.buildConfig?.outputDir || 'scripts';
1616
+ const relativePath = path.relative(path.join(this.srcDirs.behavior, 'scripts'), filePath);
1617
+ await fs__namespace.cp(filePath, path.join(this.outdirs.behavior, outputDir, relativePath), { recursive: true, force: true });
1618
+ }
1243
1619
  // if behavior or resources change, we can just copy the changed file instead of copy all files again.
1244
1620
  if (isBehaviorChange || isResourcesChange) {
1245
1621
  const handlerBP = async () => {
@@ -1269,8 +1645,9 @@ class Build {
1269
1645
  }
1270
1646
  showText(`[${chalk.green('mbler')}] ${chalk.bgYellow(`file changed: ${filePath}`)}`);
1271
1647
  }
1272
- createWatcher() {
1273
- if (!this.srcDirs || !this.outdirs || !this.rollupPlugin)
1648
+ async createWatcher() {
1649
+ const isBundle = this.currentConfig?.build?.bundle !== false;
1650
+ if (!this.srcDirs || !this.outdirs || (isBundle && !this.rollupPlugin))
1274
1651
  throw new Error(`[build addon]: can't first can this method`);
1275
1652
  const chokidar$1 = chokidar.watch(this.baseBuildDir, {
1276
1653
  ignored: [
@@ -1286,11 +1663,19 @@ class Build {
1286
1663
  await this.onChange(filePath);
1287
1664
  };
1288
1665
  chokidar$1.on('change', onChange);
1289
- const rollupWatcher = this.createRollupWatcher();
1290
- this.watchers = {
1291
- chokidar: chokidar$1,
1292
- rollup: rollupWatcher,
1293
- };
1666
+ if (isBundle && this.currentConfig?.script) {
1667
+ const rollupWatcher = await this.createRollupWatcher();
1668
+ this.watchers = {
1669
+ chokidar: chokidar$1,
1670
+ rollup: rollupWatcher,
1671
+ };
1672
+ }
1673
+ else {
1674
+ this.watchers = {
1675
+ chokidar: chokidar$1,
1676
+ rollup: null,
1677
+ };
1678
+ }
1294
1679
  }
1295
1680
  async handlerManifest() {
1296
1681
  if (!this.currentConfig || !this.outdirs || !this.srcDirs || !this.module)
@@ -1325,7 +1710,7 @@ class Build {
1325
1710
  const json = JSON.parse(content);
1326
1711
  otherManifestOption.behavior = json;
1327
1712
  }
1328
- catch (err) {
1713
+ catch (_err) {
1329
1714
  Logger.w('Build', 'invalid manifest.json in behavior');
1330
1715
  }
1331
1716
  }
@@ -1339,7 +1724,7 @@ class Build {
1339
1724
  const json = JSON.parse(content);
1340
1725
  otherManifestOption.resources = json;
1341
1726
  }
1342
- catch (err) {
1727
+ catch (_err) {
1343
1728
  Logger.w('Build', 'invalid manifest.json in resources');
1344
1729
  }
1345
1730
  }
@@ -1467,6 +1852,7 @@ function watch(cliParam, work) {
1467
1852
 
1468
1853
  exports.Build = Build;
1469
1854
  exports.McxTsc = runTSC;
1855
+ exports.Sapi = Sapi$1;
1470
1856
  exports.build = build;
1471
1857
  exports.watch = watch;
1472
1858
  //# sourceMappingURL=build.js.map