miaoda-expo-devkit 0.1.1-beta.79 → 0.1.1-beta.80
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,127 @@
|
|
|
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-notification-asset.ts
|
|
31
|
+
var no_missing_notification_asset_exports = {};
|
|
32
|
+
__export(no_missing_notification_asset_exports, {
|
|
33
|
+
default: () => no_missing_notification_asset_default
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(no_missing_notification_asset_exports);
|
|
36
|
+
var import_node_fs = __toESM(require("fs"));
|
|
37
|
+
var import_node_path2 = __toESM(require("path"));
|
|
38
|
+
|
|
39
|
+
// src/rules/utils.ts
|
|
40
|
+
var import_node_path = __toESM(require("path"));
|
|
41
|
+
var import_package_up = require("package-up");
|
|
42
|
+
function findProjectRoot(startPath) {
|
|
43
|
+
const pkgPath = (0, import_package_up.packageUpSync)({ cwd: import_node_path.default.dirname(startPath) });
|
|
44
|
+
return pkgPath ? import_node_path.default.dirname(pkgPath) : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/rules/no-missing-notification-asset.ts
|
|
48
|
+
var appJsonCache = /* @__PURE__ */ new Map();
|
|
49
|
+
var reportedRoots = /* @__PURE__ */ new Set();
|
|
50
|
+
function readAppJson(projectRoot) {
|
|
51
|
+
if (appJsonCache.has(projectRoot)) return appJsonCache.get(projectRoot);
|
|
52
|
+
try {
|
|
53
|
+
const raw = JSON.parse(
|
|
54
|
+
import_node_fs.default.readFileSync(import_node_path2.default.join(projectRoot, "app.json"), "utf-8")
|
|
55
|
+
);
|
|
56
|
+
appJsonCache.set(projectRoot, raw);
|
|
57
|
+
return raw;
|
|
58
|
+
} catch {
|
|
59
|
+
appJsonCache.set(projectRoot, null);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function getNotificationPluginOptions(plugins) {
|
|
64
|
+
for (const entry of plugins) {
|
|
65
|
+
if (entry === "expo-notifications") return {};
|
|
66
|
+
if (Array.isArray(entry) && entry[0] === "expo-notifications") {
|
|
67
|
+
const opts = entry[1];
|
|
68
|
+
if (opts != null && typeof opts === "object") return opts;
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
function isRemoteUrl(value) {
|
|
75
|
+
return value.startsWith("http://") || value.startsWith("https://");
|
|
76
|
+
}
|
|
77
|
+
var noMissingNotificationAssetRule = {
|
|
78
|
+
meta: {
|
|
79
|
+
type: "problem",
|
|
80
|
+
docs: {
|
|
81
|
+
description: "Ensure local asset files referenced by expo-notifications plugin (icon, sounds) exist on disk."
|
|
82
|
+
},
|
|
83
|
+
schema: [],
|
|
84
|
+
messages: {
|
|
85
|
+
missingIcon: 'expo-notifications plugin references icon "{{path}}" but the file does not exist.',
|
|
86
|
+
missingSound: 'expo-notifications plugin references sound "{{path}}" but the file does not exist.'
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
create(context) {
|
|
90
|
+
const projectRoot = findProjectRoot(context.filename);
|
|
91
|
+
if (!projectRoot) return {};
|
|
92
|
+
if (reportedRoots.has(projectRoot)) return {};
|
|
93
|
+
return {
|
|
94
|
+
Program(node) {
|
|
95
|
+
reportedRoots.add(projectRoot);
|
|
96
|
+
const appJson = readAppJson(projectRoot);
|
|
97
|
+
if (!appJson) return;
|
|
98
|
+
const plugins = appJson.expo?.plugins ?? [];
|
|
99
|
+
const options = getNotificationPluginOptions(plugins);
|
|
100
|
+
if (!options) return;
|
|
101
|
+
if (options.icon && typeof options.icon === "string" && !isRemoteUrl(options.icon)) {
|
|
102
|
+
const iconPath = import_node_path2.default.resolve(projectRoot, options.icon);
|
|
103
|
+
if (!import_node_fs.default.existsSync(iconPath)) {
|
|
104
|
+
context.report({ node, messageId: "missingIcon", data: { path: options.icon } });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const sounds = options.sounds;
|
|
108
|
+
if (sounds) {
|
|
109
|
+
const soundList = Array.isArray(sounds) ? sounds : [sounds];
|
|
110
|
+
for (const sound of soundList) {
|
|
111
|
+
if (typeof sound !== "string" || isRemoteUrl(sound)) continue;
|
|
112
|
+
const soundPath = import_node_path2.default.resolve(projectRoot, sound);
|
|
113
|
+
if (!import_node_fs.default.existsSync(soundPath)) {
|
|
114
|
+
context.report({ node, messageId: "missingSound", data: { path: sound } });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var plugin = {
|
|
123
|
+
meta: { name: "expo-notifications-assets" },
|
|
124
|
+
rules: { "no-missing-notification-asset": noMissingNotificationAssetRule }
|
|
125
|
+
};
|
|
126
|
+
var no_missing_notification_asset_default = plugin;
|
|
127
|
+
module.exports = module.exports.default;
|
|
@@ -0,0 +1,126 @@
|
|
|
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-splash-screen-missing-image.ts
|
|
31
|
+
var no_splash_screen_missing_image_exports = {};
|
|
32
|
+
__export(no_splash_screen_missing_image_exports, {
|
|
33
|
+
default: () => no_splash_screen_missing_image_default
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(no_splash_screen_missing_image_exports);
|
|
36
|
+
var import_node_fs = __toESM(require("fs"));
|
|
37
|
+
var import_node_path2 = __toESM(require("path"));
|
|
38
|
+
|
|
39
|
+
// src/rules/utils.ts
|
|
40
|
+
var import_node_path = __toESM(require("path"));
|
|
41
|
+
var import_package_up = require("package-up");
|
|
42
|
+
function findProjectRoot(startPath) {
|
|
43
|
+
const pkgPath = (0, import_package_up.packageUpSync)({ cwd: import_node_path.default.dirname(startPath) });
|
|
44
|
+
return pkgPath ? import_node_path.default.dirname(pkgPath) : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/rules/no-splash-screen-missing-image.ts
|
|
48
|
+
var appJsonCache = /* @__PURE__ */ new Map();
|
|
49
|
+
var reportedRoots = /* @__PURE__ */ new Set();
|
|
50
|
+
function readAppJson(projectRoot) {
|
|
51
|
+
if (appJsonCache.has(projectRoot)) return appJsonCache.get(projectRoot);
|
|
52
|
+
try {
|
|
53
|
+
const raw = JSON.parse(
|
|
54
|
+
import_node_fs.default.readFileSync(import_node_path2.default.join(projectRoot, "app.json"), "utf-8")
|
|
55
|
+
);
|
|
56
|
+
appJsonCache.set(projectRoot, raw);
|
|
57
|
+
return raw;
|
|
58
|
+
} catch {
|
|
59
|
+
appJsonCache.set(projectRoot, null);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function getSplashPluginEntry(plugins) {
|
|
64
|
+
for (const entry of plugins) {
|
|
65
|
+
if (entry === "expo-splash-screen") return { found: true, options: void 0 };
|
|
66
|
+
if (Array.isArray(entry) && entry[0] === "expo-splash-screen") {
|
|
67
|
+
const opts = entry[1];
|
|
68
|
+
return {
|
|
69
|
+
found: true,
|
|
70
|
+
options: opts != null && typeof opts === "object" ? opts : void 0
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { found: false };
|
|
75
|
+
}
|
|
76
|
+
function hasImageFields(fields) {
|
|
77
|
+
return !!(fields.image || fields.mdpi || fields.hdpi || fields.xhdpi || fields.xxhdpi || fields.xxxhdpi || fields.drawable?.icon);
|
|
78
|
+
}
|
|
79
|
+
function hasAndroidSplashImage(appJson, options) {
|
|
80
|
+
if (options !== void 0) {
|
|
81
|
+
const { ios: iosOpts, android: androidOpts, ...otherOpts } = options;
|
|
82
|
+
const isLegacy = !!iosOpts && !androidOpts && Object.keys(otherOpts).length === 0;
|
|
83
|
+
if (!isLegacy) {
|
|
84
|
+
return hasImageFields({ ...otherOpts, ...androidOpts });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const androidSplash = appJson.expo?.android?.splash;
|
|
88
|
+
if (androidSplash && hasImageFields(androidSplash)) return true;
|
|
89
|
+
return !!appJson.expo?.splash?.image;
|
|
90
|
+
}
|
|
91
|
+
var noSplashScreenMissingImageRule = {
|
|
92
|
+
meta: {
|
|
93
|
+
type: "problem",
|
|
94
|
+
docs: {
|
|
95
|
+
description: 'Ensure expo-splash-screen has an image configured. Omitting it causes Android build failure: "resource drawable/splashscreen_logo not found".'
|
|
96
|
+
},
|
|
97
|
+
schema: [],
|
|
98
|
+
messages: {
|
|
99
|
+
missingImage: "'expo-splash-screen' is declared in plugins but no splash image is configured. Add expo.splash.image to app.json, or pass image via plugin options. Without an image Android builds fail with: resource drawable/splashscreen_logo not found."
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
create(context) {
|
|
103
|
+
const projectRoot = findProjectRoot(context.filename);
|
|
104
|
+
if (!projectRoot) return {};
|
|
105
|
+
if (reportedRoots.has(projectRoot)) return {};
|
|
106
|
+
return {
|
|
107
|
+
Program(node) {
|
|
108
|
+
reportedRoots.add(projectRoot);
|
|
109
|
+
const appJson = readAppJson(projectRoot);
|
|
110
|
+
if (!appJson) return;
|
|
111
|
+
const plugins = appJson.expo?.plugins ?? [];
|
|
112
|
+
const entry = getSplashPluginEntry(plugins);
|
|
113
|
+
if (!entry.found) return;
|
|
114
|
+
if (!hasAndroidSplashImage(appJson, entry.options)) {
|
|
115
|
+
context.report({ node, messageId: "missingImage" });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
var plugin = {
|
|
122
|
+
meta: { name: "expo-splash-config" },
|
|
123
|
+
rules: { "no-splash-screen-missing-image": noSplashScreenMissingImageRule }
|
|
124
|
+
};
|
|
125
|
+
var no_splash_screen_missing_image_default = plugin;
|
|
126
|
+
module.exports = module.exports.default;
|
|
@@ -21,7 +21,8 @@ __export(no_op_logbox_exports, {
|
|
|
21
21
|
default: () => no_op_logbox_default,
|
|
22
22
|
dismissGlobalErrorOverlay: () => dismissGlobalErrorOverlay,
|
|
23
23
|
presentGlobalErrorOverlay: () => presentGlobalErrorOverlay,
|
|
24
|
-
setupLogBox: () => setupLogBox
|
|
24
|
+
setupLogBox: () => setupLogBox,
|
|
25
|
+
withoutANSIColorStyles: () => withoutANSIColorStyles
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(no_op_logbox_exports);
|
|
27
28
|
const LogBox = {
|
|
@@ -47,10 +48,12 @@ const presentGlobalErrorOverlay = () => {
|
|
|
47
48
|
};
|
|
48
49
|
const dismissGlobalErrorOverlay = () => {
|
|
49
50
|
};
|
|
51
|
+
const withoutANSIColorStyles = (s) => typeof s === "string" ? s.replace(/[][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "") : s;
|
|
50
52
|
// Annotate the CommonJS export names for ESM import in node:
|
|
51
53
|
0 && (module.exports = {
|
|
52
54
|
dismissGlobalErrorOverlay,
|
|
53
55
|
presentGlobalErrorOverlay,
|
|
54
|
-
setupLogBox
|
|
56
|
+
setupLogBox,
|
|
57
|
+
withoutANSIColorStyles
|
|
55
58
|
});
|
|
56
59
|
//# sourceMappingURL=no-op-logbox.js.map
|
package/oxlint-config.json
CHANGED
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
{ "name": "expo-video-compat", "specifier": "miaoda-expo-devkit/rules/no-expo-video-compat" },
|
|
14
14
|
{ "name": "rn-style", "specifier": "miaoda-expo-devkit/rules/no-inline-box-shadow-string" },
|
|
15
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" }
|
|
16
|
+
{ "name": "image-import", "specifier": "miaoda-expo-devkit/rules/no-missing-image-import" },
|
|
17
|
+
{ "name": "expo-splash-config", "specifier": "miaoda-expo-devkit/rules/no-splash-screen-missing-image" },
|
|
18
|
+
{ "name": "expo-notifications-assets", "specifier": "miaoda-expo-devkit/rules/no-missing-notification-asset" }
|
|
17
19
|
],
|
|
18
20
|
|
|
19
21
|
"categories": {
|
|
@@ -33,6 +35,8 @@
|
|
|
33
35
|
"rn-style/no-inline-box-shadow-string": "error",
|
|
34
36
|
"expo-unused-config-plugin/no-unused-expo-plugin": "error",
|
|
35
37
|
"image-import/no-missing-image-import": "error",
|
|
38
|
+
"expo-splash-config/no-splash-screen-missing-image": "error",
|
|
39
|
+
"expo-notifications-assets/no-missing-notification-asset": "error",
|
|
36
40
|
|
|
37
41
|
"expo/no-dynamic-env-var": "error",
|
|
38
42
|
"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.
|
|
3
|
+
"version": "0.1.1-beta.80",
|
|
4
4
|
"description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -62,6 +62,8 @@
|
|
|
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
64
|
"./rules/no-missing-image-import": "./dist/rules/no-missing-image-import.js",
|
|
65
|
+
"./rules/no-splash-screen-missing-image": "./dist/rules/no-splash-screen-missing-image.js",
|
|
66
|
+
"./rules/no-missing-notification-asset": "./dist/rules/no-missing-notification-asset.js",
|
|
65
67
|
"./biome": "./biome-config.json",
|
|
66
68
|
"./oxlint": "./oxlint-config.json",
|
|
67
69
|
"./tsconfig-base": "./tsconfig-base.json"
|