miaoda-expo-devkit 0.1.1-beta.57 → 0.1.1-beta.59

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.
@@ -0,0 +1,105 @@
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-missing-image-import.ts
31
+ var no_missing_image_import_exports = {};
32
+ __export(no_missing_image_import_exports, {
33
+ default: () => no_missing_image_import_default
34
+ });
35
+ module.exports = __toCommonJS(no_missing_image_import_exports);
36
+ var import_node_fs = __toESM(require("fs"));
37
+ var import_node_path2 = __toESM(require("path"));
38
+ var import_oxc_resolver = require("oxc-resolver");
39
+
40
+ // src/rules/utils.ts
41
+ var import_node_path = __toESM(require("path"));
42
+ var import_package_up = require("package-up");
43
+ function findProjectRoot(startPath) {
44
+ const pkgPath = (0, import_package_up.packageUpSync)({ cwd: import_node_path.default.dirname(startPath) });
45
+ return pkgPath ? import_node_path.default.dirname(pkgPath) : null;
46
+ }
47
+
48
+ // src/rules/no-missing-image-import.ts
49
+ var IMAGE_EXTENSION = /\.(png|jpe?g|gif|webp|svg|bmp|ico)$/i;
50
+ var resolverCache = /* @__PURE__ */ new Map();
51
+ function getResolver(projectRoot) {
52
+ let resolver = resolverCache.get(projectRoot);
53
+ if (!resolver) {
54
+ resolver = new import_oxc_resolver.ResolverFactory({
55
+ extensions: [".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico"],
56
+ conditionNames: ["import", "require", "node", "default"],
57
+ // tsconfig 支持路径别名(如 @/* → src/*)
58
+ tsconfig: {
59
+ configFile: import_node_path2.default.join(projectRoot, "tsconfig.json"),
60
+ references: "auto"
61
+ }
62
+ });
63
+ resolverCache.set(projectRoot, resolver);
64
+ }
65
+ return resolver;
66
+ }
67
+ var noMissingImageImportRule = {
68
+ meta: {
69
+ type: "problem",
70
+ docs: {
71
+ description: "Disallow image imports that reference non-existent files."
72
+ },
73
+ schema: [],
74
+ messages: {
75
+ imageNotFound: "Image file '{{source}}' does not exist."
76
+ }
77
+ },
78
+ create(context) {
79
+ const projectRoot = findProjectRoot(context.filename) ?? import_node_path2.default.dirname(context.filename);
80
+ const resolver = getResolver(projectRoot);
81
+ const currentDir = import_node_path2.default.dirname(context.filename);
82
+ function check(node, source) {
83
+ if (!IMAGE_EXTENSION.test(source)) return;
84
+ try {
85
+ const result = resolver.sync(currentDir, source);
86
+ if (!result.path || !import_node_fs.default.existsSync(result.path)) {
87
+ context.report({ node, messageId: "imageNotFound", data: { source } });
88
+ }
89
+ } catch {
90
+ context.report({ node, messageId: "imageNotFound", data: { source } });
91
+ }
92
+ }
93
+ return {
94
+ ImportDeclaration(node) {
95
+ check(node, node.source.value);
96
+ }
97
+ };
98
+ }
99
+ };
100
+ var plugin = {
101
+ meta: { name: "image-import" },
102
+ rules: { "no-missing-image-import": noMissingImageImportRule }
103
+ };
104
+ var no_missing_image_import_default = plugin;
105
+ module.exports = module.exports.default;
@@ -85,7 +85,6 @@ var KNOWN_CONFIG_PLUGIN_PACKAGES = /* @__PURE__ */ new Set([
85
85
  "expo-sharing",
86
86
  "expo-splash-screen",
87
87
  "expo-sqlite",
88
- "expo-status-bar",
89
88
  "expo-system-ui",
90
89
  "expo-task-manager",
91
90
  "expo-tracking-transparency",
@@ -83,7 +83,6 @@ var KNOWN_CONFIG_PLUGIN_PACKAGES = /* @__PURE__ */ new Set([
83
83
  "expo-sharing",
84
84
  "expo-splash-screen",
85
85
  "expo-sqlite",
86
- "expo-status-bar",
87
86
  "expo-system-ui",
88
87
  "expo-task-manager",
89
88
  "expo-tracking-transparency",
@@ -93,6 +92,9 @@ var KNOWN_CONFIG_PLUGIN_PACKAGES = /* @__PURE__ */ new Set([
93
92
  "expo-widgets"
94
93
  ]);
95
94
  var PACKAGES_WITHOUT_CONFIG_PLUGIN = /* @__PURE__ */ new Set([
95
+ // @react-native-async-storage/async-storage 本身不含 config plugin,
96
+ // 需改用 @react-native-async-storage/expo-with-async-storage
97
+ "@react-native-async-storage/async-storage",
96
98
  "expo-age-range",
97
99
  "expo-app-integrity",
98
100
  "expo-application",
@@ -119,6 +121,7 @@ var PACKAGES_WITHOUT_CONFIG_PLUGIN = /* @__PURE__ */ new Set([
119
121
  "expo-print",
120
122
  "expo-screen-capture",
121
123
  "expo-sms",
124
+ "expo-status-bar",
122
125
  "expo-speech",
123
126
  "expo-store-review",
124
127
  "expo-symbols",
@@ -127,6 +130,7 @@ var PACKAGES_WITHOUT_CONFIG_PLUGIN = /* @__PURE__ */ new Set([
127
130
  ]);
128
131
  var pluginsCache = /* @__PURE__ */ new Map();
129
132
  var depsCache = /* @__PURE__ */ new Map();
133
+ var reportedRoots = /* @__PURE__ */ new Set();
130
134
  function getPluginsFromAppJson(projectRoot) {
131
135
  if (pluginsCache.has(projectRoot)) return pluginsCache.get(projectRoot);
132
136
  const appJsonPath = import_node_path2.default.join(projectRoot, "app.json");
@@ -174,10 +178,12 @@ var noUnusedExpoPluginRule = {
174
178
  create(context) {
175
179
  const projectRoot = findProjectRoot(context.filename);
176
180
  if (!projectRoot) return {};
181
+ if (reportedRoots.has(projectRoot)) return {};
177
182
  const declaredPlugins = getPluginsFromAppJson(projectRoot);
178
183
  const installedDeps = getInstalledDeps(projectRoot);
179
184
  return {
180
185
  Program(node) {
186
+ reportedRoots.add(projectRoot);
181
187
  for (const pkg of declaredPlugins) {
182
188
  if (PACKAGES_WITHOUT_CONFIG_PLUGIN.has(pkg)) {
183
189
  context.report({ node, messageId: "noConfigPlugin", data: { packageName: pkg } });
@@ -11,7 +11,9 @@
11
11
  { "name": "expo-router-dynamic-tab", "specifier": "miaoda-expo-devkit/rules/no-unregistered-dynamic-tab-route" },
12
12
  { "name": "rn-pressable", "specifier": "miaoda-expo-devkit/rules/no-pressable-without-on-press" },
13
13
  { "name": "expo-video-compat", "specifier": "miaoda-expo-devkit/rules/no-expo-video-compat" },
14
- { "name": "rn-style", "specifier": "miaoda-expo-devkit/rules/no-inline-box-shadow-string" }
14
+ { "name": "rn-style", "specifier": "miaoda-expo-devkit/rules/no-inline-box-shadow-string" },
15
+ { "name": "expo-unused-config-plugin", "specifier": "miaoda-expo-devkit/rules/no-unused-expo-plugin" },
16
+ { "name": "image-import", "specifier": "miaoda-expo-devkit/rules/no-missing-image-import" }
15
17
  ],
16
18
 
17
19
  "categories": {
@@ -29,6 +31,8 @@
29
31
  "rn-pressable/no-pressable-without-on-press": "error",
30
32
  "expo-video-compat/no-expo-video-compat": "warn",
31
33
  "rn-style/no-inline-box-shadow-string": "error",
34
+ "expo-unused-config-plugin/no-unused-expo-plugin": "error",
35
+ "image-import/no-missing-image-import": "error",
32
36
 
33
37
  "expo/no-dynamic-env-var": "error",
34
38
  "expo/no-env-var-destructuring": "error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miaoda-expo-devkit",
3
- "version": "0.1.1-beta.57",
3
+ "version": "0.1.1-beta.59",
4
4
  "description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
@@ -61,6 +61,7 @@
61
61
  "./rules/no-pressable-without-on-press": "./dist/rules/no-pressable-without-on-press.js",
62
62
  "./rules/no-expo-video-compat": "./dist/rules/no-expo-video-compat.js",
63
63
  "./rules/no-inline-box-shadow-string": "./dist/rules/no-inline-box-shadow-string.js",
64
+ "./rules/no-missing-image-import": "./dist/rules/no-missing-image-import.js",
64
65
  "./biome": "./biome-config.json",
65
66
  "./oxlint": "./oxlint-config.json",
66
67
  "./tsconfig-base": "./tsconfig-base.json"