miaoda-expo-devkit 0.1.1-beta.2 → 0.1.1-beta.4
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/cli/lint.js +21 -0
- package/dist/metro.d.mts +2 -2
- package/dist/metro.d.ts +2 -2
- package/dist/metro.js +7 -6
- package/dist/metro.mjs +7 -6
- package/dist/rules/no-duplicate-expo-router-url.js +1 -1
- package/dist/stubs/lgui-control.js +18 -2
- package/oxlint-config.json +47 -0
- package/package.json +9 -5
package/dist/cli/lint.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/cli/lint.ts
|
|
5
|
+
var import_node_child_process = require("child_process");
|
|
6
|
+
var import_node_path = require("path");
|
|
7
|
+
var devkitRoot = (0, import_node_path.resolve)(__dirname, "../..");
|
|
8
|
+
var oxlintConfig = (0, import_node_path.join)(devkitRoot, "oxlint-config.json");
|
|
9
|
+
var biomeConfig = (0, import_node_path.join)(devkitRoot, "biome-config.json");
|
|
10
|
+
var targets = process.argv.slice(2);
|
|
11
|
+
var lintTargets = targets.length > 0 ? targets : ["src/"];
|
|
12
|
+
var failed = false;
|
|
13
|
+
var oxlint = (0, import_node_child_process.spawnSync)("oxlint", ["--config", oxlintConfig, ...lintTargets], {
|
|
14
|
+
stdio: "inherit"
|
|
15
|
+
});
|
|
16
|
+
if ((oxlint.status ?? 1) !== 0) failed = true;
|
|
17
|
+
var biome = (0, import_node_child_process.spawnSync)("biome", ["lint", "--config-path", biomeConfig, ...lintTargets], {
|
|
18
|
+
stdio: "inherit"
|
|
19
|
+
});
|
|
20
|
+
if ((biome.status ?? 1) !== 0) failed = true;
|
|
21
|
+
process.exit(failed ? 1 : 0);
|
package/dist/metro.d.mts
CHANGED
|
@@ -84,8 +84,8 @@ interface RouteEndpointOptions {
|
|
|
84
84
|
* 端点返回格式:
|
|
85
85
|
* {
|
|
86
86
|
* "routes": [
|
|
87
|
-
* { "title": "首页", "pageId": "/", "pageName": "index", "visible": true, "path": "index.tsx" },
|
|
88
|
-
* { "title": "id", "pageId": "/user/[id]", "pageName": "user-[id]", "visible": false, "path": "user/[id].tsx" }
|
|
87
|
+
* { "title": "首页", "pageId": "/", "pageName": "index", "visible": true, "path": "src/app/index.tsx" },
|
|
88
|
+
* { "title": "id", "pageId": "/user/[id]", "pageName": "user-[id]", "visible": false, "path": "src/app/user/[id].tsx" }
|
|
89
89
|
* ]
|
|
90
90
|
* }
|
|
91
91
|
*
|
package/dist/metro.d.ts
CHANGED
|
@@ -84,8 +84,8 @@ interface RouteEndpointOptions {
|
|
|
84
84
|
* 端点返回格式:
|
|
85
85
|
* {
|
|
86
86
|
* "routes": [
|
|
87
|
-
* { "title": "首页", "pageId": "/", "pageName": "index", "visible": true, "path": "index.tsx" },
|
|
88
|
-
* { "title": "id", "pageId": "/user/[id]", "pageName": "user-[id]", "visible": false, "path": "user/[id].tsx" }
|
|
87
|
+
* { "title": "首页", "pageId": "/", "pageName": "index", "visible": true, "path": "src/app/index.tsx" },
|
|
88
|
+
* { "title": "id", "pageId": "/user/[id]", "pageName": "user-[id]", "visible": false, "path": "src/app/user/[id].tsx" }
|
|
89
89
|
* ]
|
|
90
90
|
* }
|
|
91
91
|
*
|
package/dist/metro.js
CHANGED
|
@@ -44,7 +44,7 @@ var import_path2 = __toESM(require("path"));
|
|
|
44
44
|
var import_fs = __toESM(require("fs"));
|
|
45
45
|
var import_path = __toESM(require("path"));
|
|
46
46
|
var ROUTE_EXT = /\.(tsx|ts|jsx|js)$/;
|
|
47
|
-
function getRoutes(appDir) {
|
|
47
|
+
function getRoutes(appDir, rootDir) {
|
|
48
48
|
const routes = [];
|
|
49
49
|
function scan(dir, prefix) {
|
|
50
50
|
let entries;
|
|
@@ -70,17 +70,17 @@ function getRoutes(appDir) {
|
|
|
70
70
|
pageId: routePath,
|
|
71
71
|
pageName: routePath,
|
|
72
72
|
visible: !isDynamic,
|
|
73
|
-
path: import_path.default.relative(
|
|
73
|
+
path: import_path.default.relative(rootDir, fullPath)
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
scan(appDir, "");
|
|
79
|
-
return { routes };
|
|
79
|
+
return { data: routes };
|
|
80
80
|
}
|
|
81
|
-
function createRouteHandler(appDir) {
|
|
81
|
+
function createRouteHandler(appDir, rootDir) {
|
|
82
82
|
return (_req, res) => {
|
|
83
|
-
const routeTree = getRoutes(appDir);
|
|
83
|
+
const routeTree = getRoutes(appDir, rootDir);
|
|
84
84
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
85
85
|
res.end(JSON.stringify(routeTree, null, 2));
|
|
86
86
|
};
|
|
@@ -139,10 +139,11 @@ function withEntryInjection(config, options) {
|
|
|
139
139
|
var DEFAULT_ROUTE_ENDPOINT = "/__routes";
|
|
140
140
|
function withRouteEndpoint(config, options) {
|
|
141
141
|
const { appDir, endpoint = DEFAULT_ROUTE_ENDPOINT } = options;
|
|
142
|
+
const rootDir = config.projectRoot ?? process.cwd();
|
|
142
143
|
const upstream = config.server?.enhanceMiddleware ?? null;
|
|
143
144
|
const enhanceMiddleware = (middleware, metroServer) => {
|
|
144
145
|
const enhanced = upstream ? upstream(middleware, metroServer) : middleware;
|
|
145
|
-
return (0, import_connect.default)().use(enhanced).use(endpoint, createRouteHandler(appDir));
|
|
146
|
+
return (0, import_connect.default)().use(enhanced).use(endpoint, createRouteHandler(appDir, rootDir));
|
|
146
147
|
};
|
|
147
148
|
return {
|
|
148
149
|
...config,
|
package/dist/metro.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import path2 from "path";
|
|
|
7
7
|
import fs from "fs";
|
|
8
8
|
import path from "path";
|
|
9
9
|
var ROUTE_EXT = /\.(tsx|ts|jsx|js)$/;
|
|
10
|
-
function getRoutes(appDir) {
|
|
10
|
+
function getRoutes(appDir, rootDir) {
|
|
11
11
|
const routes = [];
|
|
12
12
|
function scan(dir, prefix) {
|
|
13
13
|
let entries;
|
|
@@ -33,17 +33,17 @@ function getRoutes(appDir) {
|
|
|
33
33
|
pageId: routePath,
|
|
34
34
|
pageName: routePath,
|
|
35
35
|
visible: !isDynamic,
|
|
36
|
-
path: path.relative(
|
|
36
|
+
path: path.relative(rootDir, fullPath)
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
scan(appDir, "");
|
|
42
|
-
return { routes };
|
|
42
|
+
return { data: routes };
|
|
43
43
|
}
|
|
44
|
-
function createRouteHandler(appDir) {
|
|
44
|
+
function createRouteHandler(appDir, rootDir) {
|
|
45
45
|
return (_req, res) => {
|
|
46
|
-
const routeTree = getRoutes(appDir);
|
|
46
|
+
const routeTree = getRoutes(appDir, rootDir);
|
|
47
47
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
48
48
|
res.end(JSON.stringify(routeTree, null, 2));
|
|
49
49
|
};
|
|
@@ -102,10 +102,11 @@ function withEntryInjection(config, options) {
|
|
|
102
102
|
var DEFAULT_ROUTE_ENDPOINT = "/__routes";
|
|
103
103
|
function withRouteEndpoint(config, options) {
|
|
104
104
|
const { appDir, endpoint = DEFAULT_ROUTE_ENDPOINT } = options;
|
|
105
|
+
const rootDir = config.projectRoot ?? process.cwd();
|
|
105
106
|
const upstream = config.server?.enhanceMiddleware ?? null;
|
|
106
107
|
const enhanceMiddleware = (middleware, metroServer) => {
|
|
107
108
|
const enhanced = upstream ? upstream(middleware, metroServer) : middleware;
|
|
108
|
-
return connect().use(enhanced).use(endpoint, createRouteHandler(appDir));
|
|
109
|
+
return connect().use(enhanced).use(endpoint, createRouteHandler(appDir, rootDir));
|
|
109
110
|
};
|
|
110
111
|
return {
|
|
111
112
|
...config,
|
|
@@ -118,7 +118,7 @@ var noDuplicateExpoRouterUrlRule = {
|
|
|
118
118
|
const others = files.filter((f) => f !== rel);
|
|
119
119
|
if (others.length === 0) return;
|
|
120
120
|
context.report({
|
|
121
|
-
loc: { line: 1, column: 0 },
|
|
121
|
+
loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
122
122
|
messageId: "duplicateUrl",
|
|
123
123
|
data: { url, other: others.join(", ") }
|
|
124
124
|
});
|
|
@@ -33,6 +33,20 @@ const THROTTLE_INTERVAL = 8;
|
|
|
33
33
|
const THROTTLE_OPTIONS = {
|
|
34
34
|
edges: ["leading", "trailing"]
|
|
35
35
|
};
|
|
36
|
+
function isInsideSvgButNotSvgElement(el) {
|
|
37
|
+
const tag = el.tagName.toLowerCase();
|
|
38
|
+
return tag !== "svg" && el.closest("svg") !== null;
|
|
39
|
+
}
|
|
40
|
+
function getTargetElement(el) {
|
|
41
|
+
const tag = el.tagName.toLowerCase();
|
|
42
|
+
if (tag === "html") {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (isInsideSvgButNotSvgElement(el)) {
|
|
46
|
+
return el.closest("svg");
|
|
47
|
+
}
|
|
48
|
+
return el;
|
|
49
|
+
}
|
|
36
50
|
function isEditorMessage(data) {
|
|
37
51
|
return typeof data === "object" && data !== null && typeof data.type === "string" && data.type.startsWith("editor-");
|
|
38
52
|
}
|
|
@@ -124,7 +138,8 @@ class EditorController {
|
|
|
124
138
|
* 设置当前悬停元素的 hover 样式
|
|
125
139
|
*/
|
|
126
140
|
this.onMouseOver = (e) => {
|
|
127
|
-
const
|
|
141
|
+
const rawNode = e.target;
|
|
142
|
+
const node = getTargetElement(rawNode);
|
|
128
143
|
if (!isEditable(node)) return;
|
|
129
144
|
if (this.hoverNode) {
|
|
130
145
|
const isActive = this.activeNode === this.hoverNode;
|
|
@@ -150,7 +165,8 @@ class EditorController {
|
|
|
150
165
|
this.onClick = (e) => {
|
|
151
166
|
e.stopPropagation();
|
|
152
167
|
e.preventDefault();
|
|
153
|
-
const
|
|
168
|
+
const rawNode = e.target;
|
|
169
|
+
const node = getTargetElement(rawNode);
|
|
154
170
|
if (!isEditable(node) || this.activeNode === node) return;
|
|
155
171
|
this.stopObservingActiveNode();
|
|
156
172
|
this.activeNode && removeActiveAttr(this.activeNode);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"plugins": ["typescript", "react"],
|
|
3
|
+
"jsPlugins": [
|
|
4
|
+
"eslint-plugin-expo",
|
|
5
|
+
{ "name": "expo-config-plugin", "specifier": "miaoda-expo-devkit/rules/no-undeclared-expo-plugin" },
|
|
6
|
+
{ "name": "expo-router", "specifier": "miaoda-expo-devkit/rules/no-unstable-expo-router" },
|
|
7
|
+
{ "name": "rn-web", "specifier": "miaoda-expo-devkit/rules/no-rn-alert" },
|
|
8
|
+
{ "name": "expo-router-url", "specifier": "miaoda-expo-devkit/rules/no-duplicate-expo-router-url" }
|
|
9
|
+
],
|
|
10
|
+
|
|
11
|
+
"categories": {
|
|
12
|
+
"correctness": "allow"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"rules": {
|
|
16
|
+
"expo-config-plugin/no-undeclared-expo-plugin": "error",
|
|
17
|
+
"expo-router/no-unstable-expo-router": "error",
|
|
18
|
+
"rn-web/no-rn-alert": "error",
|
|
19
|
+
"expo-router-url/no-duplicate-expo-router-url": "error",
|
|
20
|
+
|
|
21
|
+
"expo/no-dynamic-env-var": "error",
|
|
22
|
+
"expo/no-env-var-destructuring": "error",
|
|
23
|
+
"expo/use-dom-exports": "error",
|
|
24
|
+
|
|
25
|
+
"no-undef": "error",
|
|
26
|
+
"use-isnan": "error",
|
|
27
|
+
"valid-typeof": "error",
|
|
28
|
+
"no-dupe-keys": "error",
|
|
29
|
+
"no-duplicate-case": "error",
|
|
30
|
+
"no-dupe-class-members": "error",
|
|
31
|
+
|
|
32
|
+
"react/react-in-jsx-scope": "off",
|
|
33
|
+
"react/jsx-no-duplicate-props": "error",
|
|
34
|
+
"react/jsx-no-undef": "error"
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
"env": {
|
|
38
|
+
"browser": true
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
"globals": {
|
|
42
|
+
"__DEV__": "readonly",
|
|
43
|
+
"process": "readonly",
|
|
44
|
+
"global": "readonly",
|
|
45
|
+
"localStorage": "readonly"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miaoda-expo-devkit",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.4",
|
|
4
4
|
"description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"devkit-lint": "./dist/cli/lint.js"
|
|
11
|
+
},
|
|
9
12
|
"exports": {
|
|
10
13
|
".": {
|
|
11
14
|
"import": {
|
|
@@ -41,23 +44,24 @@
|
|
|
41
44
|
"./rules/no-unstable-expo-router": "./dist/rules/no-unstable-expo-router.js",
|
|
42
45
|
"./rules/no-rn-alert": "./dist/rules/no-rn-alert.js",
|
|
43
46
|
"./rules/no-duplicate-expo-router-url": "./dist/rules/no-duplicate-expo-router-url.js",
|
|
44
|
-
"./biome": "./biome-config.json"
|
|
47
|
+
"./biome": "./biome-config.json",
|
|
48
|
+
"./oxlint": "./oxlint-config.json"
|
|
45
49
|
},
|
|
46
50
|
"files": [
|
|
47
51
|
"dist",
|
|
48
52
|
"biome-config.json",
|
|
53
|
+
"oxlint-config.json",
|
|
49
54
|
"pnpm-config.json",
|
|
50
55
|
"!dist/**/*.map"
|
|
51
56
|
],
|
|
52
57
|
"scripts": {
|
|
53
58
|
"build": "tsup",
|
|
54
|
-
"prepare": "tsup",
|
|
55
59
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.check.json --noEmit",
|
|
56
60
|
"test": "vitest run",
|
|
57
61
|
"test:rules": "node --test --test-reporter=./src/rules/test-reporter.mjs src/rules/__tests__/*.test.ts",
|
|
58
62
|
"prepublishOnly": "pnpm run test && pnpm run build",
|
|
59
|
-
"release": "
|
|
60
|
-
"release:beta": "npm version prerelease --preid=beta &&
|
|
63
|
+
"release": "npm publish",
|
|
64
|
+
"release:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
|
|
61
65
|
"release:patch": "npm version patch && pnpm run release",
|
|
62
66
|
"release:minor": "npm version minor && pnpm run release",
|
|
63
67
|
"release:major": "npm version major && pnpm run release"
|