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