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 +1 -2
- package/dist/metro.d.ts +1 -2
- package/dist/metro.js +2 -4
- package/dist/metro.mjs +2 -4
- package/dist/rules/no-unused-expo-plugin.js +162 -0
- package/dist/stubs/lgui-control.js +41 -0
- package/package.json +25 -5
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", "
|
|
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", "
|
|
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.
|
|
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
|
-
"
|
|
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": "
|
|
124
|
+
"oxlint": "catalog:",
|
|
105
125
|
"tsup": "^8.5.1",
|
|
106
|
-
"vitest": "^
|
|
126
|
+
"vitest": "^4.1.5"
|
|
107
127
|
}
|
|
108
128
|
}
|