miaoda-expo-devkit 0.1.1-beta.12 → 0.1.1-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/metro.d.mts CHANGED
@@ -99,8 +99,7 @@ declare function withEntryInjection(config: MetroConfig, options?: InjectOptions
99
99
  * 端点(默认 /__routes)返回 JSON 格式的路由树:
100
100
  * {
101
101
  * "routes": [
102
- * { "title": "首页", "pageId": "/", "pageName": "index", "visible": true, "path": "src/app/index.tsx" },
103
- * { "title": "id", "pageId": "/user/[id]", "pageName": "user-[id]", "visible": false, "path": "src/app/user/[id].tsx" }
102
+ * { "title": "首页", "pageId": "/", "pageName": "index", "path": "src/app/index.tsx" }
104
103
  * ]
105
104
  * }
106
105
  *
package/dist/metro.d.ts CHANGED
@@ -99,8 +99,7 @@ declare function withEntryInjection(config: MetroConfig, options?: InjectOptions
99
99
  * 端点(默认 /__routes)返回 JSON 格式的路由树:
100
100
  * {
101
101
  * "routes": [
102
- * { "title": "首页", "pageId": "/", "pageName": "index", "visible": true, "path": "src/app/index.tsx" },
103
- * { "title": "id", "pageId": "/user/[id]", "pageName": "user-[id]", "visible": false, "path": "src/app/user/[id].tsx" }
102
+ * { "title": "首页", "pageId": "/", "pageName": "index", "path": "src/app/index.tsx" }
104
103
  * ]
105
104
  * }
106
105
  *
package/dist/metro.js CHANGED
@@ -156,15 +156,13 @@ function getRoutes(appDir, rootDir) {
156
156
  scan(fullPath, nextPrefix);
157
157
  } else if (ROUTE_EXT.test(entry.name)) {
158
158
  const baseName = entry.name.replace(ROUTE_EXT, "");
159
- if (baseName === "_layout") continue;
159
+ if (baseName === "_layout" || /\[.*\]/.test(baseName)) continue;
160
160
  const segment = baseName === "index" ? "" : `/${baseName}`;
161
161
  const routePath = `${prefix}${segment}` || "/";
162
- const isDynamic = /\[.*\]/.test(baseName);
163
162
  routes.push({
164
- title: routePath,
163
+ title: routePath.replace(/^\//, "") || "/",
165
164
  pageId: routePath,
166
165
  pageName: routePath,
167
- visible: !isDynamic,
168
166
  path: import_path4.default.relative(rootDir, fullPath)
169
167
  });
170
168
  }
package/dist/metro.mjs CHANGED
@@ -119,15 +119,13 @@ function getRoutes(appDir, rootDir) {
119
119
  scan(fullPath, nextPrefix);
120
120
  } else if (ROUTE_EXT.test(entry.name)) {
121
121
  const baseName = entry.name.replace(ROUTE_EXT, "");
122
- if (baseName === "_layout") continue;
122
+ if (baseName === "_layout" || /\[.*\]/.test(baseName)) continue;
123
123
  const segment = baseName === "index" ? "" : `/${baseName}`;
124
124
  const routePath = `${prefix}${segment}` || "/";
125
- const isDynamic = /\[.*\]/.test(baseName);
126
125
  routes.push({
127
- title: routePath,
126
+ title: routePath.replace(/^\//, "") || "/",
128
127
  pageId: routePath,
129
128
  pageName: routePath,
130
- visible: !isDynamic,
131
129
  path: path4.relative(rootDir, fullPath)
132
130
  });
133
131
  }
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/rules/no-unused-expo-plugin.ts
31
+ var no_unused_expo_plugin_exports = {};
32
+ __export(no_unused_expo_plugin_exports, {
33
+ default: () => no_unused_expo_plugin_default
34
+ });
35
+ module.exports = __toCommonJS(no_unused_expo_plugin_exports);
36
+ var import_node_fs = __toESM(require("fs"));
37
+ var import_node_path = __toESM(require("path"));
38
+ var KNOWN_CONFIG_PLUGIN_PACKAGES = /* @__PURE__ */ new Set([
39
+ "expo-apple-authentication",
40
+ "expo-asset",
41
+ "expo-audio",
42
+ "expo-background-fetch",
43
+ "expo-background-task",
44
+ "expo-brightness",
45
+ "expo-brownfield",
46
+ "expo-build-properties",
47
+ "expo-calendar",
48
+ "expo-camera",
49
+ "expo-cellular",
50
+ "expo-contacts",
51
+ "expo-dev-client",
52
+ "expo-dev-launcher",
53
+ "expo-dev-menu",
54
+ "expo-document-picker",
55
+ "expo-file-system",
56
+ "expo-font",
57
+ "expo-image",
58
+ "expo-image-picker",
59
+ "expo-local-authentication",
60
+ "expo-localization",
61
+ "expo-location",
62
+ "expo-mail-composer",
63
+ "expo-maps",
64
+ "expo-media-library",
65
+ "expo-modules-test-core",
66
+ "expo-navigation-bar",
67
+ "expo-notifications",
68
+ "expo-router",
69
+ "expo-screen-orientation",
70
+ "expo-secure-store",
71
+ "expo-sensors",
72
+ "expo-sharing",
73
+ "expo-splash-screen",
74
+ "expo-sqlite",
75
+ "expo-system-ui",
76
+ "expo-task-manager",
77
+ "expo-tracking-transparency",
78
+ "expo-updates",
79
+ "expo-video",
80
+ "expo-web-browser",
81
+ "expo-widgets"
82
+ ]);
83
+ var pluginsCache = /* @__PURE__ */ new Map();
84
+ var depsCache = /* @__PURE__ */ new Map();
85
+ function findProjectRoot(startPath) {
86
+ let dir = import_node_path.default.dirname(startPath);
87
+ while (dir !== import_node_path.default.dirname(dir)) {
88
+ if (import_node_fs.default.existsSync(import_node_path.default.join(dir, "package.json"))) {
89
+ return dir;
90
+ }
91
+ dir = import_node_path.default.dirname(dir);
92
+ }
93
+ return dir;
94
+ }
95
+ function getPluginsFromAppJson(projectRoot) {
96
+ if (pluginsCache.has(projectRoot)) return pluginsCache.get(projectRoot);
97
+ const appJsonPath = import_node_path.default.join(projectRoot, "app.json");
98
+ try {
99
+ const raw = JSON.parse(import_node_fs.default.readFileSync(appJsonPath, "utf-8"));
100
+ const entries = raw?.expo?.plugins ?? [];
101
+ const names = entries.map((entry) => Array.isArray(entry) ? entry[0] : entry);
102
+ pluginsCache.set(projectRoot, names);
103
+ return names;
104
+ } catch {
105
+ pluginsCache.set(projectRoot, []);
106
+ return [];
107
+ }
108
+ }
109
+ function getInstalledDeps(projectRoot) {
110
+ if (depsCache.has(projectRoot)) return depsCache.get(projectRoot);
111
+ const pkgPath = import_node_path.default.join(projectRoot, "package.json");
112
+ try {
113
+ const raw = JSON.parse(import_node_fs.default.readFileSync(pkgPath, "utf-8"));
114
+ const deps = /* @__PURE__ */ new Set([
115
+ ...Object.keys(raw["dependencies"] ?? {}),
116
+ ...Object.keys(raw["devDependencies"] ?? {}),
117
+ ...Object.keys(raw["peerDependencies"] ?? {}),
118
+ ...Object.keys(raw["optionalDependencies"] ?? {})
119
+ ]);
120
+ depsCache.set(projectRoot, deps);
121
+ return deps;
122
+ } catch {
123
+ depsCache.set(projectRoot, /* @__PURE__ */ new Set());
124
+ return /* @__PURE__ */ new Set();
125
+ }
126
+ }
127
+ var noUnusedExpoPluginRule = {
128
+ meta: {
129
+ type: "problem",
130
+ docs: {
131
+ description: "Ensure Expo Config Plugins declared in app.json's plugins array are installed in package.json."
132
+ },
133
+ schema: [],
134
+ messages: {
135
+ notInstalled: "'{{packageName}}' is declared in app.json \u2192 expo.plugins but is not installed in package.json."
136
+ }
137
+ },
138
+ create(context) {
139
+ const projectRoot = findProjectRoot(context.filename);
140
+ const declaredPlugins = getPluginsFromAppJson(projectRoot);
141
+ const installedDeps = getInstalledDeps(projectRoot);
142
+ return {
143
+ Program(node) {
144
+ for (const pkg of declaredPlugins) {
145
+ if (!KNOWN_CONFIG_PLUGIN_PACKAGES.has(pkg)) continue;
146
+ if (installedDeps.has(pkg)) continue;
147
+ context.report({
148
+ node,
149
+ messageId: "notInstalled",
150
+ data: { packageName: pkg }
151
+ });
152
+ }
153
+ }
154
+ };
155
+ }
156
+ };
157
+ var plugin = {
158
+ meta: { name: "expo-unused-config-plugin" },
159
+ rules: { "no-unused-expo-plugin": noUnusedExpoPluginRule }
160
+ };
161
+ var no_unused_expo_plugin_default = plugin;
162
+ module.exports = module.exports.default;
@@ -198,6 +198,20 @@ class EditorController {
198
198
  THROTTLE_INTERVAL,
199
199
  THROTTLE_OPTIONS
200
200
  );
201
+ /**
202
+ * 监听message消息,接收自父窗口发送的信息
203
+ */
204
+ this.onMessage = (e) => {
205
+ if (!isEditorMessage(e.data)) return;
206
+ switch (e.data.type) {
207
+ case "editor-clear-selection":
208
+ this.clearSelection();
209
+ break;
210
+ case "editor-delete":
211
+ this.deleteActiveNode();
212
+ break;
213
+ }
214
+ };
201
215
  }
202
216
  /**
203
217
  * 初始化编辑器
@@ -209,6 +223,7 @@ class EditorController {
209
223
  const { signal } = this.abortController;
210
224
  const opts = { capture: true, signal };
211
225
  this.removeSelectorStyle = (0, import_css_control.injectSelectorModeStyle)();
226
+ window.addEventListener("message", this.onMessage, { signal });
212
227
  document.addEventListener("mouseover", this.onMouseOver, opts);
213
228
  document.addEventListener("mouseleave", this.onMouseLeave, opts);
214
229
  document.addEventListener("click", this.onClick, opts);
@@ -312,6 +327,32 @@ class EditorController {
312
327
  }
313
328
  this.siblingNodes = [];
314
329
  }
330
+ /**
331
+ * 清除选中状态
332
+ * 移除 active 节点的选中样式、兄弟节点高亮、hover 状态,并停止属性观察
333
+ */
334
+ clearSelection() {
335
+ if (this.activeNode) {
336
+ this.stopObservingActiveNode();
337
+ removeActiveAttr(this.activeNode);
338
+ this.activeNode = null;
339
+ }
340
+ this.clearSiblingHighlights();
341
+ this.onMouseLeave();
342
+ }
343
+ /**
344
+ * 删除当前选中的元素
345
+ * 断开观察器,移除 DOM 节点,并通知父窗口清除状态
346
+ */
347
+ deleteActiveNode() {
348
+ if (!this.activeNode) return;
349
+ this.stopObservingActiveNode();
350
+ this.clearSiblingHighlights();
351
+ removeActiveAttr(this.activeNode);
352
+ this.activeNode.remove();
353
+ this.activeNode = null;
354
+ postToParent("iframe-node-clear");
355
+ }
315
356
  }
316
357
  let controller = null;
317
358
  function onGlobalMessage(e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miaoda-expo-devkit",
3
- "version": "0.1.1-beta.12",
3
+ "version": "0.1.1-beta.13",
4
4
  "description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
@@ -41,6 +41,7 @@
41
41
  "./sentry-react-native-stub": "./dist/stubs/sentry-react-native-stub.js",
42
42
  "./no-op-logbox": "./dist/stubs/no-op-logbox.js",
43
43
  "./rules/no-undeclared-expo-plugin": "./dist/rules/no-undeclared-expo-plugin.js",
44
+ "./rules/no-unused-expo-plugin": "./dist/rules/no-unused-expo-plugin.js",
44
45
  "./rules/no-unstable-expo-router": "./dist/rules/no-unstable-expo-router.js",
45
46
  "./rules/no-rn-alert": "./dist/rules/no-rn-alert.js",
46
47
  "./rules/no-duplicate-expo-router-url": "./dist/rules/no-duplicate-expo-router-url.js",
@@ -59,7 +60,6 @@
59
60
  "build": "tsup",
60
61
  "typecheck": "tsc --noEmit && tsc -p tsconfig.check.json --noEmit",
61
62
  "test": "vitest run",
62
- "test:rules": "node --test --test-reporter=./src/rules/test-reporter.mjs src/rules/__tests__/*.test.ts",
63
63
  "prepublishOnly": "pnpm run test && pnpm run build",
64
64
  "release": "npm publish",
65
65
  "release:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
@@ -77,7 +77,12 @@
77
77
  "peerDependencies": {
78
78
  "@sentry/core": "^10.38.0",
79
79
  "@sentry/react-native": ">=8.0.0",
80
- "react-native": ">=0.72.0"
80
+ "metro": ">=0.80.0",
81
+ "metro-config": ">=0.80.0",
82
+ "metro-resolver": ">=0.80.0",
83
+ "nativewind": ">=4.0.0",
84
+ "react-native": ">=0.79.0",
85
+ "react-native-css-interop": ">=0.2.0"
81
86
  },
82
87
  "peerDependenciesMeta": {
83
88
  "@sentry/core": {
@@ -85,6 +90,21 @@
85
90
  },
86
91
  "@sentry/react-native": {
87
92
  "optional": true
93
+ },
94
+ "metro": {
95
+ "optional": true
96
+ },
97
+ "metro-config": {
98
+ "optional": true
99
+ },
100
+ "metro-resolver": {
101
+ "optional": true
102
+ },
103
+ "nativewind": {
104
+ "optional": true
105
+ },
106
+ "react-native-css-interop": {
107
+ "optional": true
88
108
  }
89
109
  },
90
110
  "publishConfig": {
@@ -101,8 +121,8 @@
101
121
  "metro": "^0.83.0",
102
122
  "metro-config": "^0.83.0",
103
123
  "metro-resolver": "^0.83.0",
104
- "oxlint": "^1.60.0",
124
+ "oxlint": "catalog:",
105
125
  "tsup": "^8.5.1",
106
- "vitest": "^3.0.0"
126
+ "vitest": "^4.1.5"
107
127
  }
108
128
  }