miaoda-expo-devkit 0.1.1-beta.21 → 0.1.1-beta.23

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.
@@ -14591,28 +14591,89 @@ var import_node_fs = __toESM(require("fs"));
14591
14591
  var import_node_path = __toESM(require("path"));
14592
14592
  var import_helper_module_imports = __toESM(require_lib4());
14593
14593
  var LUCIDE_REACT_NATIVE = "lucide-react-native";
14594
+ function resolveIconsLocation(moduleDir) {
14595
+ const lucideDistPath = import_node_path.default.dirname(import_node_path.default.dirname(require.resolve(LUCIDE_REACT_NATIVE)));
14596
+ if (moduleDir === "cjs") {
14597
+ const withSubdir = import_node_path.default.join(lucideDistPath, "cjs/icons");
14598
+ const hasSubdir = import_node_fs.default.existsSync(withSubdir);
14599
+ return {
14600
+ dir: hasSubdir ? withSubdir : import_node_path.default.join(lucideDistPath, "cjs"),
14601
+ ext: ".js",
14602
+ importBasePath: hasSubdir ? `${LUCIDE_REACT_NATIVE}/dist/cjs/icons` : `${LUCIDE_REACT_NATIVE}/dist/cjs`
14603
+ };
14604
+ }
14605
+ const dir = import_node_path.default.join(lucideDistPath, "esm/icons");
14606
+ const hasMjs = import_node_fs.default.readdirSync(dir).some((f) => f.endsWith(".mjs"));
14607
+ return {
14608
+ dir,
14609
+ ext: hasMjs ? ".mjs" : ".js",
14610
+ importBasePath: `${LUCIDE_REACT_NATIVE}/dist/esm/icons`
14611
+ };
14612
+ }
14594
14613
  var iconMapCache = /* @__PURE__ */ new Map();
14614
+ var aliasMap = null;
14615
+ function buildAliasMap(moduleDir) {
14616
+ if (aliasMap) return aliasMap;
14617
+ const { map: fileMap } = buildIconMap(moduleDir);
14618
+ const map = /* @__PURE__ */ new Map();
14619
+ const lucideDistPath = import_node_path.default.dirname(import_node_path.default.dirname(require.resolve(LUCIDE_REACT_NATIVE)));
14620
+ const cjsBundle = import_node_path.default.join(lucideDistPath, "cjs/lucide-react-native.js");
14621
+ if (import_node_fs.default.existsSync(cjsBundle)) {
14622
+ const content = import_node_fs.default.readFileSync(cjsBundle, "utf-8");
14623
+ const varToExportNames = /* @__PURE__ */ new Map();
14624
+ const re = /^exports\.(\w+)\s*=\s*(\w+);/gm;
14625
+ let m;
14626
+ while ((m = re.exec(content)) !== null) {
14627
+ const [, exportName, varName] = m;
14628
+ const group = varToExportNames.get(varName);
14629
+ if (group) {
14630
+ group.push(exportName);
14631
+ } else {
14632
+ varToExportNames.set(varName, [exportName]);
14633
+ }
14634
+ }
14635
+ for (const names of varToExportNames.values()) {
14636
+ if (names.length < 2) continue;
14637
+ const canonical = names.find((n) => fileMap.has(n.toLowerCase()));
14638
+ if (!canonical) continue;
14639
+ const canonicalLower = canonical.toLowerCase();
14640
+ for (const name of names) {
14641
+ const lower = name.toLowerCase();
14642
+ if (lower !== canonicalLower) {
14643
+ map.set(lower, canonicalLower);
14644
+ }
14645
+ }
14646
+ }
14647
+ }
14648
+ aliasMap = map;
14649
+ return map;
14650
+ }
14595
14651
  function buildIconMap(moduleDir) {
14596
14652
  const cached = iconMapCache.get(moduleDir);
14597
14653
  if (cached) return cached;
14598
- const lucideMain = require.resolve(LUCIDE_REACT_NATIVE);
14599
- const lucideDistPath = import_node_path.default.dirname(import_node_path.default.dirname(lucideMain));
14600
- const ext = moduleDir === "esm" ? ".mjs" : ".js";
14601
- const iconsDir = import_node_path.default.join(lucideDistPath, `${moduleDir}/icons`);
14654
+ const { dir, ext, importBasePath } = resolveIconsLocation(moduleDir);
14602
14655
  const map = /* @__PURE__ */ new Map();
14603
- for (const file of import_node_fs.default.readdirSync(iconsDir)) {
14604
- if (!file.endsWith(ext) || file.endsWith(`.map`)) continue;
14656
+ for (const file of import_node_fs.default.readdirSync(dir)) {
14657
+ if (!file.endsWith(ext) || file.endsWith(".map")) continue;
14605
14658
  const slug = import_node_path.default.basename(file, ext);
14606
14659
  map.set(slug.replace(/-/g, ""), slug);
14607
14660
  }
14608
- iconMapCache.set(moduleDir, map);
14609
- return map;
14661
+ const data = { map, importBasePath };
14662
+ iconMapCache.set(moduleDir, data);
14663
+ return data;
14610
14664
  }
14611
14665
  function resolveModule(useES, name) {
14612
14666
  const moduleDir = useES ? "esm" : "cjs";
14613
- const slug = buildIconMap(moduleDir).get(name.toLowerCase());
14667
+ const { map, importBasePath } = buildIconMap(moduleDir);
14668
+ let slug = map.get(name.toLowerCase());
14669
+ if (!slug) {
14670
+ const canonical = buildAliasMap(moduleDir).get(name.toLowerCase());
14671
+ if (canonical) {
14672
+ slug = map.get(canonical);
14673
+ }
14674
+ }
14614
14675
  if (slug) {
14615
- return `${LUCIDE_REACT_NATIVE}/dist/${moduleDir}/icons/${slug}`;
14676
+ return `${importBasePath}/${slug}`;
14616
14677
  }
14617
14678
  throw new Error(
14618
14679
  `lucide icon ${name} was not a known icon. Please check the icon name is correct.`
@@ -14637,6 +14698,13 @@ function lucideReactNativePlugin({ types: t }) {
14637
14698
  function matchesLucideIcon(nodePath, localName) {
14638
14699
  return specifiedLocal4Imported[localName] && nodePath.scope.hasBinding(localName) && nodePath.scope.getBinding(localName)?.path.type === "ImportSpecifier";
14639
14700
  }
14701
+ function replaceIconRef(nodePath, useES, makeNode) {
14702
+ const localName = nodePath.node.name;
14703
+ const iconImportedName = specifiedLocal4Imported[localName];
14704
+ if (!iconImportedName || !matchesLucideIcon(nodePath, localName) || isSpecialTypes(t, nodePath.parent)) return;
14705
+ const newNode = importMethod(useES, iconImportedName, nodePath, localName);
14706
+ nodePath.replaceWith(makeNode(newNode.name, nodePath.node));
14707
+ }
14640
14708
  return {
14641
14709
  name: LUCIDE_REACT_NATIVE,
14642
14710
  visitor: {
@@ -14699,23 +14767,14 @@ function lucideReactNativePlugin({ types: t }) {
14699
14767
  },
14700
14768
  // 处理 JSX 中的图标使用:<Star /> <BookHeart size={24} />
14701
14769
  JSXIdentifier(nodePath, state) {
14702
- const { name: localName } = nodePath.node;
14703
- const { useES = false } = state.opts;
14704
- const iconImportedName = specifiedLocal4Imported[localName];
14705
- if (matchesLucideIcon(nodePath, localName) && !isSpecialTypes(t, nodePath.parent) && iconImportedName) {
14706
- const newNode = importMethod(useES, iconImportedName, nodePath, localName);
14707
- nodePath.replaceWith(t.jsxIdentifier(newNode.name));
14708
- }
14770
+ replaceIconRef(nodePath, state.opts.useES ?? false, (name) => t.jsxIdentifier(name));
14709
14771
  },
14710
14772
  // 处理非 JSX 场景中的图标引用:React.createElement(Star)、const icon = Star
14711
14773
  Identifier(nodePath, state) {
14712
- const { name: localName } = nodePath.node;
14713
- const { useES = false } = state.opts;
14714
- const iconImportedName = specifiedLocal4Imported[localName];
14715
- if (matchesLucideIcon(nodePath, localName) && !isSpecialTypes(t, nodePath.parent) && iconImportedName) {
14716
- const newNode = importMethod(useES, iconImportedName, nodePath, localName);
14717
- nodePath.replaceWith({ type: newNode.type, name: newNode.name });
14718
- }
14774
+ replaceIconRef(nodePath, state.opts.useES ?? false, (name, orig) => ({
14775
+ type: orig.type,
14776
+ name
14777
+ }));
14719
14778
  }
14720
14779
  }
14721
14780
  };
@@ -42,10 +42,8 @@ function presetExpoDevkit(api, options = {}) {
42
42
  "nativewind/babel"
43
43
  ],
44
44
  plugins: [
45
- // lucide tree-shaking:暂时禁用
46
- // ...(lucide !== false
47
- // ? [[require.resolve('./plugin-lucide-react-native'), lucide]]
48
- // : []),
45
+ // lucide tree-shaking:所有环境都需要,Metro 不具备 tree-shaking 能力
46
+ ...lucide !== false ? [[require.resolve("./plugin-lucide-react-native"), lucide]] : [],
49
47
  // jsx-source 仅开发环境注入,生产无需调试元数据
50
48
  ...isDev ? [[require.resolve("./plugin-jsx-source"), { rootDir, excludePaths }]] : []
51
49
  ]
package/dist/metro.d.mts CHANGED
@@ -134,6 +134,7 @@ declare function withRouteEndpoint(config: MetroConfig, options: RouteEndpointOp
134
134
  *
135
135
  * withWorkspaceNodeModules — 修复沙箱中 node_modules 不在 projectRoot 内的问题
136
136
  * withCssInterop — 为 expo-image / expo-camera 注入 NativeWind cssInterop
137
+ * withLucideResolver — 消除 lucide 子路径未在 exports 中声明的警告
137
138
  * withExpoNotificationsStub — Android:expo-notifications → stub(Expo Go no-op,Dev Build 透传)
138
139
  * withEntryInjection — 在 expo-router 启动前注入脚本(仅 __DEV__)
139
140
  * withDevStubs — 替换 Sentry DSN / 屏蔽 LogBox(仅 __DEV__)
package/dist/metro.d.ts CHANGED
@@ -134,6 +134,7 @@ declare function withRouteEndpoint(config: MetroConfig, options: RouteEndpointOp
134
134
  *
135
135
  * withWorkspaceNodeModules — 修复沙箱中 node_modules 不在 projectRoot 内的问题
136
136
  * withCssInterop — 为 expo-image / expo-camera 注入 NativeWind cssInterop
137
+ * withLucideResolver — 消除 lucide 子路径未在 exports 中声明的警告
137
138
  * withExpoNotificationsStub — Android:expo-notifications → stub(Expo Go no-op,Dev Build 透传)
138
139
  * withEntryInjection — 在 expo-router 启动前注入脚本(仅 __DEV__)
139
140
  * withDevStubs — 替换 Sentry DSN / 屏蔽 LogBox(仅 __DEV__)
package/dist/metro.js CHANGED
@@ -300,6 +300,17 @@ function withEsbuildMinify(config) {
300
300
  }
301
301
 
302
302
  // src/metro/withDevkit.ts
303
+ function withLucideResolver(config) {
304
+ const upstream = config.resolver?.resolveRequest ?? null;
305
+ const resolveRequest = (context, moduleName, platform) => {
306
+ if (moduleName.startsWith("lucide-react-native/dist/")) {
307
+ return { filePath: require.resolve(moduleName), type: "sourceFile" };
308
+ }
309
+ if (upstream) return upstream(context, moduleName, platform);
310
+ return context.resolveRequest(context, moduleName, platform);
311
+ };
312
+ return { ...config, resolver: { ...config.resolver, resolveRequest } };
313
+ }
303
314
  var EXPO_NOTIFICATIONS_STUB_FILENAME = "expo-notifications-stub.js";
304
315
  var EXPO_NOTIFICATIONS_STUB_PATH = import_path7.default.resolve(__dirname, "stubs", EXPO_NOTIFICATIONS_STUB_FILENAME);
305
316
  function withExpoNotificationsStub(config) {
@@ -319,6 +330,7 @@ function withDevkit(config, options = {}) {
319
330
  config = withWorkspaceNodeModules(config);
320
331
  config = withCssInterop(config);
321
332
  config = withEsbuildMinify(config);
333
+ config = withLucideResolver(config);
322
334
  config = withExpoNotificationsStub(config);
323
335
  if (typeof __DEV__ !== "undefined" && __DEV__) {
324
336
  config = withEntryInjection(config);
package/dist/metro.mjs CHANGED
@@ -262,6 +262,17 @@ function withEsbuildMinify(config) {
262
262
  }
263
263
 
264
264
  // src/metro/withDevkit.ts
265
+ function withLucideResolver(config) {
266
+ const upstream = config.resolver?.resolveRequest ?? null;
267
+ const resolveRequest = (context, moduleName, platform) => {
268
+ if (moduleName.startsWith("lucide-react-native/dist/")) {
269
+ return { filePath: __require.resolve(moduleName), type: "sourceFile" };
270
+ }
271
+ if (upstream) return upstream(context, moduleName, platform);
272
+ return context.resolveRequest(context, moduleName, platform);
273
+ };
274
+ return { ...config, resolver: { ...config.resolver, resolveRequest } };
275
+ }
265
276
  var EXPO_NOTIFICATIONS_STUB_FILENAME = "expo-notifications-stub.js";
266
277
  var EXPO_NOTIFICATIONS_STUB_PATH = path7.resolve(__dirname, "stubs", EXPO_NOTIFICATIONS_STUB_FILENAME);
267
278
  function withExpoNotificationsStub(config) {
@@ -281,6 +292,7 @@ function withDevkit(config, options = {}) {
281
292
  config = withWorkspaceNodeModules(config);
282
293
  config = withCssInterop(config);
283
294
  config = withEsbuildMinify(config);
295
+ config = withLucideResolver(config);
284
296
  config = withExpoNotificationsStub(config);
285
297
  if (typeof __DEV__ !== "undefined" && __DEV__) {
286
298
  config = withEntryInjection(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miaoda-expo-devkit",
3
- "version": "0.1.1-beta.21",
3
+ "version": "0.1.1-beta.23",
4
4
  "description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",