@mbler/mcx-core 0.1.2-rc.1 → 0.1.2-rc.10

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/README.md CHANGED
@@ -1,5 +1,40 @@
1
- # mcx
2
-
3
- ## This is a DSL for build minecraft bedrock script
4
-
5
- Docs **[see this](https://mbler-docs.ruanhor.dpdns.org/guide/mcx)**
1
+ # @mbler/mcx-core
2
+
3
+ The MCX DSL compiler the core of the MCX ecosystem. Compiles `.mcx` source files into MCBE-compatible JSON components, UI forms, and event systems.
4
+
5
+ ## Pipeline
6
+
7
+ `.mcx` file → **parser** → AST → **transform** (Babel) → compiled JS → MCBE JSON
8
+
9
+ ## Features
10
+
11
+ - **MCX Parser** — Parses `.mcx` source into a tokenized AST (`tag`, `prop`)
12
+ - **Transform Pipeline** — Detects file type (`event`, `ui`, `component`, `app`) and generates compiled Babel AST
13
+ - **Component Compilation** — Runs component scripts in a sandboxed VM, generates MCBE JSON, executes file edit operations
14
+ - **CJS Transform** — Rewrites ESM imports to CommonJS `require()` for VM execution
15
+ - **Image Assets** — Compiles PNG, JPG, SVG, GIF image references into MCBE texture assets
16
+ - **Rollup/Rolldown Plugin** — Seamless `.mcx` file resolution and transformation in your build pipeline
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pnpm add -D @mbler/mcx-core
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ Add the plugin to your Rollup or Rolldown config:
27
+
28
+ ```ts
29
+ import { rollupPlugin } from '@mbler/mcx-core'
30
+
31
+ export default {
32
+ plugins: [rollupPlugin({ moduleDir: './modules', tsconfigPath: './tsconfig.json' })],
33
+ }
34
+ ```
35
+
36
+ For full documentation, visit the **[Docs](https://mbler-docs.ruanhor.dpdns.org/guide/mcx)**.
37
+
38
+ ## License
39
+
40
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as t from "@babel/types";
2
2
  import { ArgumentPlaceholder, CallExpression, ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, Expression, ImportDeclaration, SpreadElement } from "@babel/types";
3
3
  import * as Parser from "@babel/parser";
4
- import { BlockComponent, BlockComponent as BlockComponent$1, EnchantableSlot, EntityComponent, EntityComponent as EntityComponent$1, EntityComponentOptions, EntityJson, FoodEffect, GIFImageComponent, GIFImageComponent as GIFImageComponent$1, ItemComponent, ItemComponent as ItemComponent$1, ItemComponentOptions, ItemJson, JPGImageComponent, JPGImageComponent as JPGImageComponent$1, PNGImageComponent, PNGImageComponent as PNGImageComponent$1, ParticleType, Rarity, SVGImageComponent, SVGImageComponent as SVGImageComponent$1, SoundEvent } from "@mbler/mcx-component";
4
+ import { BlockComponent, BlockComponent as BlockComponent$1, EnchantableSlot, EntityComponent, EntityComponent as EntityComponent$1, EntityComponentOptions, FoodEffect, GIFImageComponent, GIFImageComponent as GIFImageComponent$1, ItemComponent, ItemComponent as ItemComponent$1, ItemComponentOptions, JPGImageComponent, JPGImageComponent as JPGImageComponent$1, PNGImageComponent, PNGImageComponent as PNGImageComponent$1, ParticleType, Rarity, SVGImageComponent, SVGImageComponent as SVGImageComponent$1, SoundEvent } from "@mbler/mcx-component";
5
5
  import { Plugin, TransformPluginContext } from "rollup";
6
6
  import { CompileOpt, CompileOpt as CompileOpt$1 } from "@mbler/mcx-types";
7
7
  import { Plugin as Plugin$1 } from "rolldown";
@@ -207,7 +207,7 @@ declare class Utils {
207
207
  static FileExist(path: string): Promise<boolean>;
208
208
  static readFile(filePath: string, opt?: ReadFileOpt): Promise<object | string>;
209
209
  static sleep(time: number): Promise<void>;
210
- static TypeVerify<T extends Record<string, any>, U extends TypeVerifyBody>(obj: T, types: U): obj is T & { [P in keyof U]: {
210
+ static TypeVerify<T extends Record<string, unknown>, U extends TypeVerifyBody>(obj: T, types: U): obj is T & { [P in keyof U]: {
211
211
  boolean: boolean;
212
212
  number: number;
213
213
  string: string;
@@ -263,7 +263,7 @@ declare const compileMCXFn: ((mcxCode: string) => MCXCompileData) & {
263
263
  cache: Record<string, MCXCompileData>;
264
264
  };
265
265
  declare namespace types_d_exports {
266
- export { BaseJson, DefineEntry, EnchantableSlot, EntityComponentOptions, EntityJson, FileBindSource, FileEditExpression, FileEditOption, FilePoint, FoodEffect, ItemComponentOptions, ItemJson, ParticleType, Rarity, SoundEvent, createFileEdit };
266
+ export { BaseJson, DefineEntry, EnchantableSlot, EntityComponentOptions, FileBindSource, FileEditExpression, FileEditOption, FilePoint, FoodEffect, ItemComponentOptions, ParticleType, Rarity, SoundEvent, createFileEdit };
267
267
  }
268
268
  interface FilePoint {
269
269
  base: 'behavior' | 'resources' | 'root';
@@ -293,7 +293,7 @@ type FileEditOption = {
293
293
  type: 'edit';
294
294
  id?: string;
295
295
  source: FilePoint | FileBindSource;
296
- expression: FileEditExpression<any>;
296
+ expression: FileEditExpression<Record<string, DefineEntry>>;
297
297
  } | {
298
298
  type: 'copy_assets';
299
299
  id?: string;
@@ -353,7 +353,7 @@ declare function clearCachedOptions(): void;
353
353
  * Resolve a FilePoint to an absolute path on disk.
354
354
  *
355
355
  * - `base: 'root'` is only allowed when the calling component originates from
356
- * @mbler/mcx-core (the `sourceIsMcxCore` flag). This prevents third-party
356
+ * @mbler/mcx-component (the `sourceIsMcxCore` flag). This prevents third-party
357
357
  * components from reading arbitrary filesystem locations.
358
358
  * - For `behavior` / `resources`, the file is resolved relative to the
359
359
  * corresponding output directory. A path-traversal check ensures the resolved
@@ -365,7 +365,7 @@ declare function resolveFilePoint(point: FilePoint, ctx: transformCtx, sourceIsM
365
365
  * Delegates to execEditInternal with a fresh limits counter.
366
366
  *
367
367
  * @param isMcxCoreSource - when true, the component originates from
368
- * @mbler/mcx-core and is exempt from file I/O limits and root base
368
+ * @mbler/mcx-component and is exempt from file I/O limits and root base
369
369
  * restrictions.
370
370
  */
371
371
  declare function execEdit(option: BaseJson['_meta']['file_edit'], ctx: transformCtx, isMcxCoreSource?: boolean): Promise<void>;
@@ -388,7 +388,7 @@ declare function generateItemTextureJson(output: {
388
388
  *
389
389
  * Per-component restrictions (checked after VM execution):
390
390
  * - path traversal guard on the output file point
391
- * - root base: only allowed if the export came from @mbler/mcx-core
391
+ * - root base: only allowed if the export came from @mbler/mcx-component
392
392
  * - file write limit (≤5) and read limit (≤1): only enforced for
393
393
  * non-mcx-core components
394
394
  */
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { n as __require, t as __exportAll } from "./chunk-DEq-mXcV.js";
2
2
  import * as Module from "node:module";
3
- import * as path$1 from "node:path";
4
- import path, { extname } from "node:path";
3
+ import { createRequire } from "node:module";
4
+ import * as path from "node:path";
5
+ import { extname } from "node:path";
5
6
  import * as t from "@babel/types";
6
7
  import { program } from "@babel/types";
7
8
  import * as fs from "node:fs/promises";
@@ -115,7 +116,7 @@ var Lexer$1 = class {
115
116
  }
116
117
  *tokenStream() {
117
118
  const tokenizer = new Tokenizer(this.text);
118
- for (const token of tokenizer.splitTokens()) {
119
+ for (const token of Array.from(tokenizer.splitTokens())) {
119
120
  if (!this.includeComments && token.type === "Comment") continue;
120
121
  yield token;
121
122
  }
@@ -192,8 +193,11 @@ var Parser$1 = class {
192
193
  inKey = false;
193
194
  inValue = true;
194
195
  const nextIndex = i + 1;
195
- nextIndex < tagContent.length && tagContent[nextIndex];
196
- quoteChar = null;
196
+ const nextChar = nextIndex < tagContent.length ? tagContent[nextIndex] : " ";
197
+ if (nextChar === "\"" || nextChar === "'") {
198
+ quoteChar = nextChar;
199
+ i = nextIndex;
200
+ } else quoteChar = " ";
197
201
  } else if (char === " " && inKey && currentKey) {
198
202
  attributes[currentKey.trim()] = "true";
199
203
  currentKey = "";
@@ -256,9 +260,11 @@ var Parser$1 = class {
256
260
  else stack.push(node);
257
261
  } else if (token.type === "TagEnd") {
258
262
  const name = token.data.replace(/^<\/\s*/, "").replace(/\s*>$/, "").trim();
263
+ let matched = false;
259
264
  for (let s = stack.length - 1; s >= 0; s--) {
260
265
  const candidate = stack[s];
261
266
  if (candidate && candidate.name === name) {
267
+ matched = true;
262
268
  candidate.end = token;
263
269
  candidate.loc.end = { ...token.end };
264
270
  stack.splice(s, 1);
@@ -267,6 +273,7 @@ var Parser$1 = class {
267
273
  break;
268
274
  }
269
275
  }
276
+ if (!matched) throw new Error(`Unmatched closing tag </${name}> at line ${token.start.line}, column ${token.start.column}`);
270
277
  }
271
278
  }
272
279
  while (stack.length > 0) {
@@ -453,9 +460,9 @@ var Utils$1 = class Utils$1 {
453
460
  const file = await readFile(fileDir, "utf-8");
454
461
  if (typeof file !== "string") throw new Error("[read file]: not found file " + fileDir);
455
462
  try {
456
- return Parser.parse(file).program;
463
+ return Parser.parse(file, parserOpt).program;
457
464
  } catch (err) {
458
- throw new Error("[compiler]: babel error" + err.stack);
465
+ throw new Error("[compiler]: babel error" + (err instanceof Error ? err.stack : String(err)));
459
466
  }
460
467
  }
461
468
  static async FileContent(fileDir) {
@@ -544,21 +551,26 @@ var CompileError = class extends Error {
544
551
  }
545
552
  };
546
553
  function extractLoc(node) {
547
- if (!node) return {
554
+ if (!node || typeof node !== "object") return {
548
555
  line: -1,
549
556
  column: -1
550
557
  };
551
- if (node.loc && node.loc.start) return {
552
- line: typeof node.loc.start.line === "number" ? node.loc.start.line : -1,
553
- column: typeof node.loc.start.column === "number" ? node.loc.start.column : -1
554
- };
555
- else if (node.loc && node.loc.column !== void 0) return {
556
- line: node.loc.line ?? -1,
557
- column: node.loc.column
558
+ const n = node;
559
+ const loc = n.loc;
560
+ if (loc?.start) {
561
+ const start = loc.start;
562
+ return {
563
+ line: typeof start.line === "number" ? start.line : -1,
564
+ column: typeof start.column === "number" ? start.column : -1
565
+ };
566
+ } else if (loc && loc.column !== void 0) return {
567
+ line: typeof loc.line === "number" ? loc.line : -1,
568
+ column: loc.column
558
569
  };
559
- if (node.start && typeof node.start.line === "number") return {
560
- line: node.start.line,
561
- column: node.start.column ?? -1
570
+ const start = n.start;
571
+ if (start && typeof start.line === "number") return {
572
+ line: start.line,
573
+ column: typeof start.column === "number" ? start.column : -1
562
574
  };
563
575
  return {
564
576
  line: -1,
@@ -913,7 +925,7 @@ var Utils = class Utils {
913
925
  return true;
914
926
  }
915
927
  static AbsoluteJoin(baseDir, inputPath) {
916
- return path$1.isAbsolute(inputPath) ? inputPath : path$1.join(baseDir, inputPath);
928
+ return path.isAbsolute(inputPath) ? inputPath : path.join(baseDir, inputPath);
917
929
  }
918
930
  };
919
931
  //#endregion
@@ -1054,16 +1066,32 @@ async function Comp$2(ctx) {
1054
1066
  column: uiClientTag.loc.start.column,
1055
1067
  line: uiClientTag.loc.start.line
1056
1068
  } : void 0);
1069
+ let _for;
1070
+ if (typeof uiClientTag.arr.for === "string") {
1071
+ const match = uiClientTag.arr.for.match(/^(\w+)\s+in\s+(\w+)$/);
1072
+ if (match) _for = {
1073
+ variable: match[1],
1074
+ useProp: match[2]
1075
+ };
1076
+ else internalCtx.rollupContext.error("[UI]: invalid for syntax, expected 'variable in propName'", uiClientTag.loc ? {
1077
+ column: uiClientTag.loc.start.column,
1078
+ line: uiClientTag.loc.start.line
1079
+ } : void 0);
1080
+ }
1081
+ let _if;
1082
+ if (typeof uiClientTag.arr.if === "string") _if = { useProp: uiClientTag.arr.if };
1057
1083
  UITree.push({
1058
1084
  arr: uiClientTag.arr,
1059
1085
  content: uiClientTag.content.map((i) => i.type == "TagContent" && i.data || "").join(""),
1060
1086
  type: uiClientTag.name,
1061
- loc: uiClientTag.loc
1087
+ loc: uiClientTag.loc,
1088
+ ..._for ? { for: _for } : {},
1089
+ ..._if ? { if: _if } : {}
1062
1090
  });
1063
1091
  }
1064
1092
  const parsedObj = [];
1065
- function pushToTree(name, params, content) {
1066
- parsedObj.push(t.objectExpression([
1093
+ function pushToTree(name, params, content, _for, _if) {
1094
+ const props = [
1067
1095
  t.objectProperty(t.identifier("type"), t.stringLiteral(name)),
1068
1096
  t.objectProperty(t.identifier("params"), t.objectExpression(Object.entries(params).map(([key, value]) => {
1069
1097
  const isDynamic = key.startsWith(":");
@@ -1071,10 +1099,16 @@ async function Comp$2(ctx) {
1071
1099
  return t.objectProperty(t.identifier(paramName), isDynamic ? t.objectExpression([t.objectProperty(t.identifier("useProp"), t.stringLiteral(String(value)))]) : typeof value == "boolean" ? t.booleanLiteral(value) : t.stringLiteral(value));
1072
1100
  }))),
1073
1101
  t.objectProperty(t.identifier("content"), content.startsWith("{{ ") && content.endsWith(" }}") ? t.objectExpression([t.objectProperty(t.identifier("useProp"), t.stringLiteral(content.slice(3, content.length - 3).trim()))]) : t.stringLiteral(content))
1074
- ]));
1102
+ ];
1103
+ if (_for) props.push(t.objectProperty(t.identifier("for"), t.objectExpression([t.objectProperty(t.identifier("variable"), t.stringLiteral(_for.variable)), t.objectProperty(t.identifier("useProp"), t.stringLiteral(_for.useProp))])));
1104
+ if (_if) props.push(t.objectProperty(t.identifier("if"), t.objectExpression([t.objectProperty(t.identifier("useProp"), t.stringLiteral(_if.useProp))])));
1105
+ parsedObj.push(t.objectExpression(props));
1075
1106
  }
1076
1107
  for (const tp of UITree) {
1077
1108
  const name = tp.type;
1109
+ const cleanedArr = { ...tp.arr };
1110
+ delete cleanedArr.for;
1111
+ delete cleanedArr.if;
1078
1112
  if ([
1079
1113
  "input",
1080
1114
  "dropdown",
@@ -1087,26 +1121,26 @@ async function Comp$2(ctx) {
1087
1121
  column: tp.loc.start.column
1088
1122
  } : void 0);
1089
1123
  MCXUIType = "ModalFormData";
1090
- pushToTree(name, tp.arr, tp.content);
1124
+ pushToTree(name, cleanedArr, tp.content, tp.for, tp.if);
1091
1125
  } else if (["button-m"].includes(name)) {
1092
1126
  if (MCXUIType && MCXUIType !== "MessageFormData") internalCtx.rollupContext.error("[UI]: ", tp.loc ? {
1093
1127
  line: tp.loc.start.line,
1094
1128
  column: tp.loc.start.column
1095
1129
  } : void 0);
1096
1130
  MCXUIType = "MessageFormData";
1097
- pushToTree(name, tp.arr, tp.content);
1131
+ pushToTree(name, cleanedArr, tp.content, tp.for, tp.if);
1098
1132
  } else if ([
1099
1133
  "body",
1100
1134
  "divider",
1101
1135
  "title",
1102
1136
  "label"
1103
- ].includes(name)) pushToTree(name, tp.arr, tp.content);
1137
+ ].includes(name)) pushToTree(name, cleanedArr, tp.content, tp.for, tp.if);
1104
1138
  else if (name == "button") {
1105
1139
  if (MCXUIType !== "ActionFormData" && MCXUIType) internalCtx.rollupContext.error("[UI]: don't support use button for messageFormData", tp.loc ? {
1106
1140
  line: tp.loc.start.line,
1107
1141
  column: tp.loc.start.column
1108
1142
  } : void 0);
1109
- pushToTree(name, tp.arr, tp.content);
1143
+ pushToTree(name, cleanedArr, tp.content, tp.for, tp.if);
1110
1144
  MCXUIType = "ActionFormData";
1111
1145
  } else internalCtx.rollupContext.error("[UI]: don't support tag: " + name, tp.loc ? {
1112
1146
  line: tp.loc.start.line,
@@ -1391,7 +1425,7 @@ var mcx_component_exports = /* @__PURE__ */ __exportAll({
1391
1425
  let cachedOption = {};
1392
1426
  /**
1393
1427
  * Security limits for file I/O operations inside file_edit expressions.
1394
- * Components from @mbler/mcx-core are exempt from these limits.
1428
+ * Components from @mbler/mcx-component are exempt from these limits.
1395
1429
  */
1396
1430
  const MAX_FILE_WRITES = 5;
1397
1431
  const MAX_FILE_READS = 1;
@@ -1403,7 +1437,7 @@ function clearCachedOptions() {
1403
1437
  * Resolve a FilePoint to an absolute path on disk.
1404
1438
  *
1405
1439
  * - `base: 'root'` is only allowed when the calling component originates from
1406
- * @mbler/mcx-core (the `sourceIsMcxCore` flag). This prevents third-party
1440
+ * @mbler/mcx-component (the `sourceIsMcxCore` flag). This prevents third-party
1407
1441
  * components from reading arbitrary filesystem locations.
1408
1442
  * - For `behavior` / `resources`, the file is resolved relative to the
1409
1443
  * corresponding output directory. A path-traversal check ensures the resolved
@@ -1411,7 +1445,7 @@ function clearCachedOptions() {
1411
1445
  */
1412
1446
  function resolveFilePoint(point, ctx, sourceIsMcxCore = false) {
1413
1447
  if (point.base === "root") {
1414
- if (!sourceIsMcxCore) throw new Error("[mcx component]: \"root\" base is only allowed for components imported from @mbler/mcx-core");
1448
+ if (!sourceIsMcxCore) throw new Error("[mcx component]: \"root\" base is only allowed for components imported from @mbler/mcx-component");
1415
1449
  return path.resolve(point.file);
1416
1450
  }
1417
1451
  let baseDir;
@@ -1469,13 +1503,13 @@ function collectExportSources(code) {
1469
1503
  return sources;
1470
1504
  }
1471
1505
  /**
1472
- * Validate that the component only imports from @mbler/mcx-core.
1506
+ * Validate that the component only imports from @mbler/mcx-component.
1473
1507
  * Non-mcx-core imports are collected and each unique offending package
1474
1508
  * triggers a console warning (once per package per file).
1475
1509
  * Relative imports ('./...', '../...') are silently allowed.
1476
1510
  */
1477
1511
  function checkComponentImports(sources, filePath) {
1478
- const allowedPackage = "@mbler/mcx-core";
1512
+ const allowedPackage = "@mbler/mcx-component";
1479
1513
  const warned = /* @__PURE__ */ new Set();
1480
1514
  for (const [, pkg] of Object.entries(sources)) if (pkg && !pkg.startsWith(allowedPackage) && !pkg.startsWith(".") && !warned.has(pkg)) {
1481
1515
  warned.add(pkg);
@@ -1487,7 +1521,7 @@ function checkComponentImports(sources, filePath) {
1487
1521
  * Delegates to execEditInternal with a fresh limits counter.
1488
1522
  *
1489
1523
  * @param isMcxCoreSource - when true, the component originates from
1490
- * @mbler/mcx-core and is exempt from file I/O limits and root base
1524
+ * @mbler/mcx-component and is exempt from file I/O limits and root base
1491
1525
  * restrictions.
1492
1526
  */
1493
1527
  async function execEdit(option, ctx, isMcxCoreSource = false) {
@@ -1579,7 +1613,7 @@ async function generateItemTextureJson(output) {
1579
1613
  *
1580
1614
  * Per-component restrictions (checked after VM execution):
1581
1615
  * - path traversal guard on the output file point
1582
- * - root base: only allowed if the export came from @mbler/mcx-core
1616
+ * - root base: only allowed if the export came from @mbler/mcx-component
1583
1617
  * - file write limit (≤5) and read limit (≤1): only enforced for
1584
1618
  * non-mcx-core components
1585
1619
  */
@@ -1593,7 +1627,7 @@ async function compileComponent(compiledCode, ctx) {
1593
1627
  const arg = data.arguments[0].arguments[0];
1594
1628
  if (arg && arg.type == "StringLiteral") {
1595
1629
  if (/^.+?\.(png|svg|jpg|jpeg|gif)$/.test(arg.value)) {
1596
- const imageComponentRequire = t.memberExpression(t.callExpression(t.identifier("require"), [t.stringLiteral("@mbler/mcx-core")]), t.identifier({
1630
+ const imageComponentRequire = t.memberExpression(t.callExpression(t.identifier("require"), [t.stringLiteral("@mbler/mcx-component")]), t.identifier({
1597
1631
  png: "PNGImageComponent",
1598
1632
  svg: "SVGImageComponent",
1599
1633
  jpg: "JPGImageComponent",
@@ -1617,7 +1651,7 @@ async function compileComponent(compiledCode, ctx) {
1617
1651
  const json = pointData.toJSON();
1618
1652
  if (!json._meta || !json._meta.type || !["item", "entity"].includes(json._meta.type)) throw new Error("[mcx component]: not mcx json component: unknown type");
1619
1653
  if (json._meta.file_edit) {
1620
- const isMcxCoreSource = (exportSources[pointExport] ?? "").startsWith("@mbler/mcx-core");
1654
+ const isMcxCoreSource = Object.values(exportSources).some((src) => src && src.startsWith("@mbler/mcx-component"));
1621
1655
  await execEdit(json._meta.file_edit, ctx, isMcxCoreSource);
1622
1656
  }
1623
1657
  delete json["_meta"];
@@ -1701,6 +1735,7 @@ async function transform(code, cache, id, context, opt, output) {
1701
1735
  });
1702
1736
  } catch (err) {
1703
1737
  context.error(createErrorProxy(err, id));
1738
+ return;
1704
1739
  }
1705
1740
  }
1706
1741
  //#endregion
@@ -1761,17 +1796,19 @@ function createMcxPlugin(opt, output) {
1761
1796
  if (exports) {
1762
1797
  const subImport = subPath.startsWith("./") ? subPath : `./${subPath}`;
1763
1798
  if (typeof exports === "object" && exports !== null) {
1764
- if (exports[subImport]) {
1765
- const target = exports[subImport];
1799
+ const exp = exports;
1800
+ if (exp[subImport]) {
1801
+ const target = exp[subImport];
1766
1802
  if (typeof target === "string") return path.join(pkgDir, target);
1767
1803
  else if (typeof target === "object" && target !== null) {
1768
- if (target.import) return path.join(pkgDir, target.import);
1769
- return path.join(pkgDir, target.default || Object.values(target)[0]);
1804
+ const targetObj = target;
1805
+ if (targetObj.import) return path.join(pkgDir, targetObj.import);
1806
+ return path.join(pkgDir, targetObj.default || Object.values(targetObj)[0]);
1770
1807
  }
1771
1808
  }
1772
1809
  if (subImport.endsWith("/") || subImport.endsWith("/*")) {
1773
1810
  const dirMapping = subImport.slice(0, -1);
1774
- for (const [key, value] of Object.entries(exports)) if (key.startsWith(dirMapping) && key !== dirMapping) {
1811
+ for (const [key, value] of Object.entries(exp)) if (key.startsWith(dirMapping) && key !== dirMapping) {
1775
1812
  const target = value;
1776
1813
  return path.join(pkgDir, target);
1777
1814
  }
@@ -1792,6 +1829,10 @@ function createMcxPlugin(opt, output) {
1792
1829
  }
1793
1830
  return null;
1794
1831
  } else {
1832
+ if (imp) try {
1833
+ const resolved = createRequire(imp).resolve(id);
1834
+ if (resolved) return resolved;
1835
+ } catch {}
1795
1836
  const isScopedPackage = id.startsWith("@");
1796
1837
  const parts = id.split("/");
1797
1838
  const pkgName = isScopedPackage ? `${parts[0]}/${parts[1]}` : parts[0];
@@ -1827,14 +1868,11 @@ function createMcxPlugin(opt, output) {
1827
1868
  compileData = cache.has(id) ? cache.get(id) : compileMCXFn(code);
1828
1869
  cache.set(id, compileData);
1829
1870
  } catch (err) {
1830
- if (err instanceof CompileError) {
1831
- const error = err;
1832
- this.error(error.message, {
1833
- column: error.loc.column,
1834
- line: error.loc.line
1835
- });
1836
- }
1837
- this.error(err instanceof Error ? `${err.message} : ${err.stack}` : String(err));
1871
+ if (err instanceof CompileError) this.error(err.message, {
1872
+ column: err.loc.column,
1873
+ line: err.loc.line
1874
+ });
1875
+ else this.error(err instanceof Error ? `${err.message} : ${err.stack}` : String(err));
1838
1876
  return;
1839
1877
  }
1840
1878
  compileData.setFilePath(id);