miaoda-expo-devkit 0.1.1-beta.37 → 0.1.1-beta.39
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/README.md +54 -4
- package/dist/metro.d.mts +33 -1
- package/dist/metro.d.ts +33 -1
- package/dist/metro.js +41 -2
- package/dist/metro.mjs +39 -2
- package/dist/rules/no-pressable-without-on-press.js +77 -0
- package/dist/stubs/expo-calendar-stub.js +353 -0
- package/oxlint-config.json +3 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Expo / React Native 开发环境工具集,通过 Metro 构建层注入以下
|
|
|
9
9
|
- **LogBox 屏蔽** — web 平台禁用 Expo 全屏错误遮罩
|
|
10
10
|
- **expo-notifications stub** — Expo Go(Android)中提供 no-op 实现,核心 API 调用时弹出带参数校验的调试 Alert,Dev Build 透传真实模块
|
|
11
11
|
- **expo-media-library stub** — Expo Go / Web 中提供 no-op 实现,`saveToLibraryAsync`、`createAssetAsync`、权限请求等 API 调用时弹出 Alert 提示,Dev Build 原生环境透传真实模块
|
|
12
|
+
- **expo-calendar stub** — Expo Go / Web 中提供 no-op 实现,`getEventsAsync`、`createEventAsync`、`getCalendarsAsync`、权限请求等核心 API 调用时弹出 Alert 提示并校验参数,Dev Build 原生环境透传真实模块
|
|
12
13
|
|
|
13
14
|
## 安装
|
|
14
15
|
|
|
@@ -39,11 +40,11 @@ const { withDevkit } = require('miaoda-expo-devkit/metro');
|
|
|
39
40
|
module.exports = withDevkit(getDefaultConfig(__dirname));
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
`withDevkit` 已内置所有 wrapper(含 expo-notifications、expo-media-library stub),无需手动叠加。也可单独使用各 wrapper:
|
|
43
|
+
`withDevkit` 已内置所有 wrapper(含 expo-notifications、expo-media-library、expo-calendar stub),无需手动叠加。也可单独使用各 wrapper:
|
|
43
44
|
|
|
44
45
|
```js
|
|
45
|
-
const { withDevStubs, withEntryInjection, withExpoMediaLibraryStub } = require('miaoda-expo-devkit/metro');
|
|
46
|
-
module.exports = withExpoMediaLibraryStub(withEntryInjection(withDevStubs(config)));
|
|
46
|
+
const { withDevStubs, withEntryInjection, withExpoMediaLibraryStub, withExpoCalendarStub } = require('miaoda-expo-devkit/metro');
|
|
47
|
+
module.exports = withExpoCalendarStub(withExpoMediaLibraryStub(withEntryInjection(withDevStubs(config))));
|
|
47
48
|
```
|
|
48
49
|
|
|
49
50
|
### Sentry 初始化
|
|
@@ -243,6 +244,11 @@ metro.config.js
|
|
|
243
244
|
│ ├─ Expo Go / Web:no-op + Alert 提示(不崩溃)
|
|
244
245
|
│ └─ Dev Build(原生):透传真实 expo-media-library
|
|
245
246
|
│
|
|
247
|
+
├─ withExpoCalendarStub → resolver.resolveRequest
|
|
248
|
+
│ └─ expo-calendar → dist/stubs/expo-calendar-stub.js (全平台)
|
|
249
|
+
│ ├─ Expo Go / Web:no-op + Alert 提示 + 参数校验(不崩溃)
|
|
250
|
+
│ └─ Dev Build(原生):透传真实 expo-calendar
|
|
251
|
+
│
|
|
246
252
|
└─ withEntryInjection → resolver.resolveRequest
|
|
247
253
|
└─ expo-router/entry-classic → dist/stubs/expo-router-entry-stub.js
|
|
248
254
|
├─ require('./entry-inject') ← 注入脚本(bundle 首部执行)
|
|
@@ -274,13 +280,14 @@ sentry-react-native-stub.js
|
|
|
274
280
|
| 子路径 | 文件 | 内容 |
|
|
275
281
|
|---|---|---|
|
|
276
282
|
| `.` | `dist/index.js` | `SentryCapture`、`MetroSymbolicator`、全部类型 |
|
|
277
|
-
| `./metro` | `dist/metro.js` | `withDevkit`、`withDevStubs`、`withEntryInjection`、`withExpoNotificationsStub`、`withExpoMediaLibraryStub` 等 |
|
|
283
|
+
| `./metro` | `dist/metro.js` | `withDevkit`、`withDevStubs`、`withEntryInjection`、`withExpoNotificationsStub`、`withExpoMediaLibraryStub`、`withExpoCalendarStub` 等 |
|
|
278
284
|
| `./babel-plugin-jsx-source` | `dist/babel/plugin-jsx-source.js` | Babel 插件:为 JSX 注入 source 信息 |
|
|
279
285
|
| `./babel-preset` | `dist/babel/preset.js` | Babel Preset:集成 jsx-source 和 lucide 插件 |
|
|
280
286
|
| `./sentry-react-native-stub` | `dist/stubs/sentry-react-native-stub.js` | `@sentry/react-native` 模块替换 stub |
|
|
281
287
|
| `./no-op-logbox` | `dist/stubs/no-op-logbox.js` | LogBox no-op stub |
|
|
282
288
|
| `./expo-notifications-stub` | `dist/stubs/expo-notifications-stub.js` | `expo-notifications` Expo Go Android stub |
|
|
283
289
|
| `./expo-media-library-stub` | `dist/stubs/expo-media-library-stub.js` | `expo-media-library` Expo Go / Web stub |
|
|
290
|
+
| `./expo-calendar-stub` | `dist/stubs/expo-calendar-stub.js` | `expo-calendar` Expo Go / Web stub |
|
|
284
291
|
|
|
285
292
|
---
|
|
286
293
|
|
|
@@ -445,6 +452,49 @@ Expo Go 扫码预览不支持访问手机相册
|
|
|
445
452
|
|
|
446
453
|
---
|
|
447
454
|
|
|
455
|
+
### expo-calendar-stub.js
|
|
456
|
+
|
|
457
|
+
`expo-calendar` 模块替换 stub,由 `withExpoCalendarStub()` 在 Metro 层注入(**全平台**)。
|
|
458
|
+
|
|
459
|
+
**背景:** `expo-calendar` 依赖原生系统日历 API,在 Expo Go 和 Web 环境中不可用,调用 `getEventsAsync` 等 API 会直接崩溃。
|
|
460
|
+
|
|
461
|
+
**运行时行为:**
|
|
462
|
+
- **Expo Go / Web**:提供 no-op 实现,以下 API 调用时弹出 Alert / Dialog 提示(不崩溃):
|
|
463
|
+
- `useCalendarPermissions()` / `useRemindersPermissions()` — 初始返回 `undetermined`,`requestPermission()` 弹 Alert
|
|
464
|
+
- `requestCalendarPermissionsAsync()` / `requestRemindersPermissionsAsync()` — 弹 Alert 提示,返回 denied
|
|
465
|
+
- `getCalendarPermissionsAsync()` / `getRemindersPermissionsAsync()` — 静默返回 denied
|
|
466
|
+
- `getCalendarsAsync(entityType?)` — 弹 Alert 显示查询类型,返回空数组
|
|
467
|
+
- `createCalendarAsync(details)` — 弹 Alert 含名称和颜色,校验 `details.title` 非空
|
|
468
|
+
- `updateCalendarAsync(id, details)` / `deleteCalendarAsync(id)` — 弹 Alert 含日历 ID,校验 ID 格式
|
|
469
|
+
- `getEventsAsync(calendarIds, startDate, endDate)` — 弹 Alert 含时间范围,校验 calendarIds 非空及日期合法性,返回空数组
|
|
470
|
+
- `createEventAsync(calendarId, eventData)` — 弹 Alert 含标题和时间,Android 下校验 startDate/endDate
|
|
471
|
+
- `updateEventAsync(id, details)` / `deleteEventAsync(id)` — 弹 Alert 含事件 ID,校验 ID 格式
|
|
472
|
+
- 其他未知 API — Proxy 兜底,静默返回 `undefined`;以 `PermissionsAsync` 结尾的 API 返回 denied 结构
|
|
473
|
+
- **Development Build(原生)**:透传真实 `expo-calendar`,功能完全正常
|
|
474
|
+
|
|
475
|
+
**枚举常量**(stub & Dev Build 均可用):
|
|
476
|
+
`EntityTypes`、`Frequency`、`Availability`、`CalendarType`、`EventStatus`、`SourceType`、
|
|
477
|
+
`AttendeeRole`、`AttendeeStatus`、`AttendeeType`、`AlarmMethod`、`EventAccessLevel`、
|
|
478
|
+
`CalendarAccessLevel`、`ReminderStatus`、`DayOfTheWeek`、`MonthOfTheYear`
|
|
479
|
+
|
|
480
|
+
**Alert 消息格式(合规示例):**
|
|
481
|
+
```
|
|
482
|
+
创建日历事件
|
|
483
|
+
秒哒扫码预览不支持访问手机日历
|
|
484
|
+
|
|
485
|
+
日历 ID: cal1
|
|
486
|
+
标题: 团队会议
|
|
487
|
+
开始: 2025/1/1 10:00:00
|
|
488
|
+
结束: 2025/1/1 11:00:00
|
|
489
|
+
|
|
490
|
+
✅ 参数合规
|
|
491
|
+
发布为正式 App 后可正常使用
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**手动验证:** 在 `devkit-e2e` App 中扫码进入「Calendar Stub 验证」页面,逐按钮触发并对照期望结果。
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
448
498
|
## Babel 插件:jsx-source
|
|
449
499
|
|
|
450
500
|
`babel-plugin-jsx-source` 为 JSX 元素注入 source 属性(文件路径、行列号),用于开发调试。通过 `dataSet` 对象注入,这是 React Web 可识别的数据通道。
|
package/dist/metro.d.mts
CHANGED
|
@@ -112,11 +112,13 @@ declare function withRouteEndpoint(config: MetroConfig, options: RouteEndpointOp
|
|
|
112
112
|
*
|
|
113
113
|
* 按固定顺序依次应用:
|
|
114
114
|
* withWorkspaceNodeModules — 修复沙箱中 node_modules 位于祖先目录时的模块解析问题
|
|
115
|
+
* withWasmSupport — 将 .wasm 加入 assetExts,修复 expo-sqlite web worker 打包失败
|
|
115
116
|
* withCssInterop — 为 expo-image / expo-camera 等注入 NativeWind cssInterop
|
|
116
117
|
* withEsbuildMinify — 将 Metro minifier 切换为 esbuild(仅生产构建生效)
|
|
117
118
|
* withLucideResolver — 消除 lucide 子路径未在 exports 声明时的 warning
|
|
118
119
|
* withExpoNotificationsStub — Android:expo-notifications → stub(Expo Go no-op,Dev Build 透传)
|
|
119
120
|
* withExpoMediaLibraryStub — Web / Expo Go:expo-media-library → stub(弹 Alert 提示,Dev Build 透传)
|
|
121
|
+
* withExpoCalendarStub — Web / Expo Go:expo-calendar → stub(弹 Alert 提示,Dev Build 透传)
|
|
120
122
|
* withEntryInjection — 在 expo-router 启动前注入脚本(仅 __DEV__)
|
|
121
123
|
* withDevStubs — 替换 Sentry DSN / 屏蔽 LogBox(仅 __DEV__)
|
|
122
124
|
* withRouteEndpoint — 添加 /__routes 端点(仅 __DEV__)
|
|
@@ -276,6 +278,23 @@ declare function withExpoNotificationsStub(config: MetroConfig): MetroConfig;
|
|
|
276
278
|
*/
|
|
277
279
|
declare function withExpoMediaLibraryStub(config: MetroConfig): MetroConfig;
|
|
278
280
|
|
|
281
|
+
/**
|
|
282
|
+
* withExpoCalendarStub — Web / Expo Go 将 expo-calendar 替换为 stub
|
|
283
|
+
*
|
|
284
|
+
* expo-calendar 依赖 native module,在 Web 和 Expo Go 中不可用。
|
|
285
|
+
* stub 在运行时通过 Platform.OS 和 isRunningInExpoGo() 判断:
|
|
286
|
+
* - Web / Expo Go:no-op(核心 API 弹 Alert 提示,不崩溃)
|
|
287
|
+
* - Development Build(原生):透传真实 expo-calendar,功能完全正常
|
|
288
|
+
*
|
|
289
|
+
* 此 wrapper 需要在开发和生产构建中均生效,因为 native module 缺失是运行时问题。
|
|
290
|
+
*/
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* @param config Metro config 对象
|
|
294
|
+
* @returns 注入 resolveRequest 后的新 Metro config
|
|
295
|
+
*/
|
|
296
|
+
declare function withExpoCalendarStub(config: MetroConfig): MetroConfig;
|
|
297
|
+
|
|
279
298
|
/**
|
|
280
299
|
* 将 Metro transformer 的 minifier 切换为 esbuild。
|
|
281
300
|
*
|
|
@@ -288,4 +307,17 @@ declare function withExpoMediaLibraryStub(config: MetroConfig): MetroConfig;
|
|
|
288
307
|
*/
|
|
289
308
|
declare function withEsbuildMinify(config: MetroConfig): MetroConfig;
|
|
290
309
|
|
|
291
|
-
|
|
310
|
+
/**
|
|
311
|
+
* withWasmSupport — 为 Metro 添加 .wasm 静态资源支持
|
|
312
|
+
*
|
|
313
|
+
* expo-sqlite 的 web worker(web/worker.ts)通过 ES import 加载
|
|
314
|
+
* wa-sqlite.wasm,Metro 默认 assetExts 不含 wasm,打包时报:
|
|
315
|
+
* Unable to resolve "./wa-sqlite/wa-sqlite.wasm" from "expo-sqlite/web/worker.ts"
|
|
316
|
+
*
|
|
317
|
+
* 将 wasm 加入 assetExts 后,Metro resolver 遇到 .wasm 导入时会将其
|
|
318
|
+
* 作为静态资源处理(同 ttf/png),不再尝试作为 JS 模块解析。
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
declare function withWasmSupport(config: MetroConfig): MetroConfig;
|
|
322
|
+
|
|
323
|
+
export { type DevkitOptions, type InjectOptions, type PatchNativeWindCacheOptions, type RouteEndpointOptions, patchNativeWindCachePath, withCssInterop, withDevStubs, withDevkit, withEntryInjection, withEsbuildMinify, withExpoCalendarStub, withExpoMediaLibraryStub, withExpoNotificationsStub, withLucideResolver, withNativeWind, withRouteEndpoint, withWasmSupport, withWorkspaceNodeModules };
|
package/dist/metro.d.ts
CHANGED
|
@@ -112,11 +112,13 @@ declare function withRouteEndpoint(config: MetroConfig, options: RouteEndpointOp
|
|
|
112
112
|
*
|
|
113
113
|
* 按固定顺序依次应用:
|
|
114
114
|
* withWorkspaceNodeModules — 修复沙箱中 node_modules 位于祖先目录时的模块解析问题
|
|
115
|
+
* withWasmSupport — 将 .wasm 加入 assetExts,修复 expo-sqlite web worker 打包失败
|
|
115
116
|
* withCssInterop — 为 expo-image / expo-camera 等注入 NativeWind cssInterop
|
|
116
117
|
* withEsbuildMinify — 将 Metro minifier 切换为 esbuild(仅生产构建生效)
|
|
117
118
|
* withLucideResolver — 消除 lucide 子路径未在 exports 声明时的 warning
|
|
118
119
|
* withExpoNotificationsStub — Android:expo-notifications → stub(Expo Go no-op,Dev Build 透传)
|
|
119
120
|
* withExpoMediaLibraryStub — Web / Expo Go:expo-media-library → stub(弹 Alert 提示,Dev Build 透传)
|
|
121
|
+
* withExpoCalendarStub — Web / Expo Go:expo-calendar → stub(弹 Alert 提示,Dev Build 透传)
|
|
120
122
|
* withEntryInjection — 在 expo-router 启动前注入脚本(仅 __DEV__)
|
|
121
123
|
* withDevStubs — 替换 Sentry DSN / 屏蔽 LogBox(仅 __DEV__)
|
|
122
124
|
* withRouteEndpoint — 添加 /__routes 端点(仅 __DEV__)
|
|
@@ -276,6 +278,23 @@ declare function withExpoNotificationsStub(config: MetroConfig): MetroConfig;
|
|
|
276
278
|
*/
|
|
277
279
|
declare function withExpoMediaLibraryStub(config: MetroConfig): MetroConfig;
|
|
278
280
|
|
|
281
|
+
/**
|
|
282
|
+
* withExpoCalendarStub — Web / Expo Go 将 expo-calendar 替换为 stub
|
|
283
|
+
*
|
|
284
|
+
* expo-calendar 依赖 native module,在 Web 和 Expo Go 中不可用。
|
|
285
|
+
* stub 在运行时通过 Platform.OS 和 isRunningInExpoGo() 判断:
|
|
286
|
+
* - Web / Expo Go:no-op(核心 API 弹 Alert 提示,不崩溃)
|
|
287
|
+
* - Development Build(原生):透传真实 expo-calendar,功能完全正常
|
|
288
|
+
*
|
|
289
|
+
* 此 wrapper 需要在开发和生产构建中均生效,因为 native module 缺失是运行时问题。
|
|
290
|
+
*/
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* @param config Metro config 对象
|
|
294
|
+
* @returns 注入 resolveRequest 后的新 Metro config
|
|
295
|
+
*/
|
|
296
|
+
declare function withExpoCalendarStub(config: MetroConfig): MetroConfig;
|
|
297
|
+
|
|
279
298
|
/**
|
|
280
299
|
* 将 Metro transformer 的 minifier 切换为 esbuild。
|
|
281
300
|
*
|
|
@@ -288,4 +307,17 @@ declare function withExpoMediaLibraryStub(config: MetroConfig): MetroConfig;
|
|
|
288
307
|
*/
|
|
289
308
|
declare function withEsbuildMinify(config: MetroConfig): MetroConfig;
|
|
290
309
|
|
|
291
|
-
|
|
310
|
+
/**
|
|
311
|
+
* withWasmSupport — 为 Metro 添加 .wasm 静态资源支持
|
|
312
|
+
*
|
|
313
|
+
* expo-sqlite 的 web worker(web/worker.ts)通过 ES import 加载
|
|
314
|
+
* wa-sqlite.wasm,Metro 默认 assetExts 不含 wasm,打包时报:
|
|
315
|
+
* Unable to resolve "./wa-sqlite/wa-sqlite.wasm" from "expo-sqlite/web/worker.ts"
|
|
316
|
+
*
|
|
317
|
+
* 将 wasm 加入 assetExts 后,Metro resolver 遇到 .wasm 导入时会将其
|
|
318
|
+
* 作为静态资源处理(同 ttf/png),不再尝试作为 JS 模块解析。
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
declare function withWasmSupport(config: MetroConfig): MetroConfig;
|
|
322
|
+
|
|
323
|
+
export { type DevkitOptions, type InjectOptions, type PatchNativeWindCacheOptions, type RouteEndpointOptions, patchNativeWindCachePath, withCssInterop, withDevStubs, withDevkit, withEntryInjection, withEsbuildMinify, withExpoCalendarStub, withExpoMediaLibraryStub, withExpoNotificationsStub, withLucideResolver, withNativeWind, withRouteEndpoint, withWasmSupport, withWorkspaceNodeModules };
|
package/dist/metro.js
CHANGED
|
@@ -36,11 +36,13 @@ __export(metro_exports, {
|
|
|
36
36
|
withDevkit: () => withDevkit,
|
|
37
37
|
withEntryInjection: () => withEntryInjection,
|
|
38
38
|
withEsbuildMinify: () => withEsbuildMinify,
|
|
39
|
+
withExpoCalendarStub: () => withExpoCalendarStub,
|
|
39
40
|
withExpoMediaLibraryStub: () => withExpoMediaLibraryStub,
|
|
40
41
|
withExpoNotificationsStub: () => withExpoNotificationsStub,
|
|
41
42
|
withLucideResolver: () => withLucideResolver,
|
|
42
43
|
withNativeWind: () => withNativeWind,
|
|
43
44
|
withRouteEndpoint: () => withRouteEndpoint,
|
|
45
|
+
withWasmSupport: () => withWasmSupport,
|
|
44
46
|
withWorkspaceNodeModules: () => withWorkspaceNodeModules
|
|
45
47
|
});
|
|
46
48
|
module.exports = __toCommonJS(metro_exports);
|
|
@@ -284,7 +286,7 @@ function withCssInterop(config) {
|
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
// src/metro/withDevkit.ts
|
|
287
|
-
var
|
|
289
|
+
var import_path11 = __toESM(require("path"));
|
|
288
290
|
|
|
289
291
|
// src/metro/withEsbuildMinify.ts
|
|
290
292
|
function withEsbuildMinify(config) {
|
|
@@ -383,20 +385,55 @@ function withExpoMediaLibraryStub(config) {
|
|
|
383
385
|
return { ...config, resolver: { ...config.resolver, resolveRequest } };
|
|
384
386
|
}
|
|
385
387
|
|
|
388
|
+
// src/metro/withExpoCalendarStub.ts
|
|
389
|
+
var import_path10 = __toESM(require("path"));
|
|
390
|
+
var EXPO_CALENDAR_STUB_FILENAME = "expo-calendar-stub.js";
|
|
391
|
+
var EXPO_CALENDAR_STUB_PATH = import_path10.default.resolve(
|
|
392
|
+
__dirname,
|
|
393
|
+
"stubs",
|
|
394
|
+
EXPO_CALENDAR_STUB_FILENAME
|
|
395
|
+
);
|
|
396
|
+
function withExpoCalendarStub(config) {
|
|
397
|
+
const upstream = config.resolver?.resolveRequest ?? null;
|
|
398
|
+
const resolveRequest = (context, moduleName, platform) => {
|
|
399
|
+
if (moduleName === "expo-calendar" && !context.originModulePath.includes(EXPO_CALENDAR_STUB_FILENAME)) {
|
|
400
|
+
return { filePath: EXPO_CALENDAR_STUB_PATH, type: "sourceFile" };
|
|
401
|
+
}
|
|
402
|
+
if (upstream) return upstream(context, moduleName, platform);
|
|
403
|
+
return context.resolveRequest(context, moduleName, platform);
|
|
404
|
+
};
|
|
405
|
+
return { ...config, resolver: { ...config.resolver, resolveRequest } };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/metro/withWasmSupport.ts
|
|
409
|
+
function withWasmSupport(config) {
|
|
410
|
+
const existing = config.resolver?.assetExts ?? [];
|
|
411
|
+
if (existing.includes("wasm")) return config;
|
|
412
|
+
return {
|
|
413
|
+
...config,
|
|
414
|
+
resolver: {
|
|
415
|
+
...config.resolver,
|
|
416
|
+
assetExts: [...existing, "wasm"]
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
386
421
|
// src/metro/withDevkit.ts
|
|
387
422
|
function withDevkit(config, options = {}) {
|
|
388
423
|
const projectRoot = config.projectRoot ?? process.cwd();
|
|
389
424
|
const { input = "./src/global.css" } = options;
|
|
390
425
|
config = withWorkspaceNodeModules(config);
|
|
426
|
+
config = withWasmSupport(config);
|
|
391
427
|
config = withCssInterop(config);
|
|
392
428
|
config = withEsbuildMinify(config);
|
|
393
429
|
config = withLucideResolver(config);
|
|
394
430
|
config = withExpoNotificationsStub(config);
|
|
395
431
|
config = withExpoMediaLibraryStub(config);
|
|
432
|
+
config = withExpoCalendarStub(config);
|
|
396
433
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
397
434
|
config = withEntryInjection(config);
|
|
398
435
|
config = withDevStubs(config);
|
|
399
|
-
config = withRouteEndpoint(config, { appDir:
|
|
436
|
+
config = withRouteEndpoint(config, { appDir: import_path11.default.join(projectRoot, "src", "app") });
|
|
400
437
|
}
|
|
401
438
|
return withNativeWind(config, { input, inlineRem: 16 });
|
|
402
439
|
}
|
|
@@ -416,11 +453,13 @@ try {
|
|
|
416
453
|
withDevkit,
|
|
417
454
|
withEntryInjection,
|
|
418
455
|
withEsbuildMinify,
|
|
456
|
+
withExpoCalendarStub,
|
|
419
457
|
withExpoMediaLibraryStub,
|
|
420
458
|
withExpoNotificationsStub,
|
|
421
459
|
withLucideResolver,
|
|
422
460
|
withNativeWind,
|
|
423
461
|
withRouteEndpoint,
|
|
462
|
+
withWasmSupport,
|
|
424
463
|
withWorkspaceNodeModules
|
|
425
464
|
});
|
|
426
465
|
//# sourceMappingURL=metro.js.map
|
package/dist/metro.mjs
CHANGED
|
@@ -244,7 +244,7 @@ function withCssInterop(config) {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
// src/metro/withDevkit.ts
|
|
247
|
-
import
|
|
247
|
+
import path11 from "path";
|
|
248
248
|
|
|
249
249
|
// src/metro/withEsbuildMinify.ts
|
|
250
250
|
function withEsbuildMinify(config) {
|
|
@@ -343,20 +343,55 @@ function withExpoMediaLibraryStub(config) {
|
|
|
343
343
|
return { ...config, resolver: { ...config.resolver, resolveRequest } };
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
+
// src/metro/withExpoCalendarStub.ts
|
|
347
|
+
import path10 from "path";
|
|
348
|
+
var EXPO_CALENDAR_STUB_FILENAME = "expo-calendar-stub.js";
|
|
349
|
+
var EXPO_CALENDAR_STUB_PATH = path10.resolve(
|
|
350
|
+
__dirname,
|
|
351
|
+
"stubs",
|
|
352
|
+
EXPO_CALENDAR_STUB_FILENAME
|
|
353
|
+
);
|
|
354
|
+
function withExpoCalendarStub(config) {
|
|
355
|
+
const upstream = config.resolver?.resolveRequest ?? null;
|
|
356
|
+
const resolveRequest = (context, moduleName, platform) => {
|
|
357
|
+
if (moduleName === "expo-calendar" && !context.originModulePath.includes(EXPO_CALENDAR_STUB_FILENAME)) {
|
|
358
|
+
return { filePath: EXPO_CALENDAR_STUB_PATH, type: "sourceFile" };
|
|
359
|
+
}
|
|
360
|
+
if (upstream) return upstream(context, moduleName, platform);
|
|
361
|
+
return context.resolveRequest(context, moduleName, platform);
|
|
362
|
+
};
|
|
363
|
+
return { ...config, resolver: { ...config.resolver, resolveRequest } };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/metro/withWasmSupport.ts
|
|
367
|
+
function withWasmSupport(config) {
|
|
368
|
+
const existing = config.resolver?.assetExts ?? [];
|
|
369
|
+
if (existing.includes("wasm")) return config;
|
|
370
|
+
return {
|
|
371
|
+
...config,
|
|
372
|
+
resolver: {
|
|
373
|
+
...config.resolver,
|
|
374
|
+
assetExts: [...existing, "wasm"]
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
346
379
|
// src/metro/withDevkit.ts
|
|
347
380
|
function withDevkit(config, options = {}) {
|
|
348
381
|
const projectRoot = config.projectRoot ?? process.cwd();
|
|
349
382
|
const { input = "./src/global.css" } = options;
|
|
350
383
|
config = withWorkspaceNodeModules(config);
|
|
384
|
+
config = withWasmSupport(config);
|
|
351
385
|
config = withCssInterop(config);
|
|
352
386
|
config = withEsbuildMinify(config);
|
|
353
387
|
config = withLucideResolver(config);
|
|
354
388
|
config = withExpoNotificationsStub(config);
|
|
355
389
|
config = withExpoMediaLibraryStub(config);
|
|
390
|
+
config = withExpoCalendarStub(config);
|
|
356
391
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
357
392
|
config = withEntryInjection(config);
|
|
358
393
|
config = withDevStubs(config);
|
|
359
|
-
config = withRouteEndpoint(config, { appDir:
|
|
394
|
+
config = withRouteEndpoint(config, { appDir: path11.join(projectRoot, "src", "app") });
|
|
360
395
|
}
|
|
361
396
|
return withNativeWind(config, { input, inlineRem: 16 });
|
|
362
397
|
}
|
|
@@ -375,11 +410,13 @@ export {
|
|
|
375
410
|
withDevkit,
|
|
376
411
|
withEntryInjection,
|
|
377
412
|
withEsbuildMinify,
|
|
413
|
+
withExpoCalendarStub,
|
|
378
414
|
withExpoMediaLibraryStub,
|
|
379
415
|
withExpoNotificationsStub,
|
|
380
416
|
withLucideResolver,
|
|
381
417
|
withNativeWind,
|
|
382
418
|
withRouteEndpoint,
|
|
419
|
+
withWasmSupport,
|
|
383
420
|
withWorkspaceNodeModules
|
|
384
421
|
};
|
|
385
422
|
//# sourceMappingURL=metro.mjs.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/rules/no-pressable-without-on-press.ts
|
|
21
|
+
var no_pressable_without_on_press_exports = {};
|
|
22
|
+
__export(no_pressable_without_on_press_exports, {
|
|
23
|
+
default: () => no_pressable_without_on_press_default
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(no_pressable_without_on_press_exports);
|
|
26
|
+
var PRESSABLE_COMPONENTS = /* @__PURE__ */ new Set([
|
|
27
|
+
"Pressable",
|
|
28
|
+
"TouchableOpacity",
|
|
29
|
+
"TouchableHighlight",
|
|
30
|
+
"TouchableNativeFeedback",
|
|
31
|
+
"TouchableWithoutFeedback"
|
|
32
|
+
]);
|
|
33
|
+
function hasOnPress(attrs) {
|
|
34
|
+
return attrs.some((attr) => {
|
|
35
|
+
if (attr.type !== "JSXAttribute") return false;
|
|
36
|
+
const n = attr.name;
|
|
37
|
+
return n.type === "JSXIdentifier" && n.name === "onPress";
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
var noPressableWithoutOnPressRule = {
|
|
41
|
+
meta: {
|
|
42
|
+
type: "problem",
|
|
43
|
+
docs: {
|
|
44
|
+
description: "Pressable-family components must have an onPress handler."
|
|
45
|
+
},
|
|
46
|
+
schema: [],
|
|
47
|
+
messages: {
|
|
48
|
+
missingOnPress: "<{{name}}> is missing onPress. Add: onPress={() => { /* handler */ }}"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
create(context) {
|
|
52
|
+
function check(node) {
|
|
53
|
+
const nameNode = node.name;
|
|
54
|
+
if (nameNode.type !== "JSXIdentifier") return;
|
|
55
|
+
const componentName = nameNode.name;
|
|
56
|
+
if (!componentName || !PRESSABLE_COMPONENTS.has(componentName)) return;
|
|
57
|
+
const attrs = node.attributes;
|
|
58
|
+
if (!hasOnPress(attrs)) {
|
|
59
|
+
context.report({
|
|
60
|
+
node,
|
|
61
|
+
messageId: "missingOnPress",
|
|
62
|
+
data: { name: componentName }
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
JSXOpeningElement: check,
|
|
68
|
+
JSXSelfClosingElement: check
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var plugin = {
|
|
73
|
+
meta: { name: "rn-pressable" },
|
|
74
|
+
rules: { "no-pressable-without-on-press": noPressableWithoutOnPressRule }
|
|
75
|
+
};
|
|
76
|
+
var no_pressable_without_on_press_default = plugin;
|
|
77
|
+
module.exports = module.exports.default;
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_react_native = require("react-native");
|
|
3
|
+
var import_expo = require("expo");
|
|
4
|
+
var import_web_stub_dialog = require("./web-stub-dialog");
|
|
5
|
+
if (import_react_native.Platform.OS !== "web" && !(0, import_expo.isRunningInExpoGo)()) {
|
|
6
|
+
module.exports = require("expo-calendar");
|
|
7
|
+
} else {
|
|
8
|
+
let showCalendarAlert = function(title, lines, isValid, errors) {
|
|
9
|
+
if (import_react_native.Platform.OS === "web") {
|
|
10
|
+
(0, import_web_stub_dialog.showWebStubDialog)({
|
|
11
|
+
title,
|
|
12
|
+
details: lines,
|
|
13
|
+
errors: !isValid && errors && errors.length > 0 ? errors : void 0
|
|
14
|
+
});
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const statusLine = isValid ? "\u2705 \u53C2\u6570\u5408\u89C4" : "\u274C \u53C2\u6570\u6709\u8BEF";
|
|
18
|
+
const parts = ["\u79D2\u54D2\u626B\u7801\u9884\u89C8\u4E0D\u652F\u6301\u8BBF\u95EE\u624B\u673A\u65E5\u5386", "", ...lines, "", statusLine];
|
|
19
|
+
if (!isValid && errors && errors.length > 0) {
|
|
20
|
+
parts.push(`\u95EE\u9898: ${errors.join(" / ")}`);
|
|
21
|
+
parts.push("");
|
|
22
|
+
parts.push("\u8BF7\u622A\u56FE\u53D1\u7ED9\u79D2\u54D2 Agent \u4FEE\u590D");
|
|
23
|
+
} else {
|
|
24
|
+
parts.push("");
|
|
25
|
+
parts.push("\u53D1\u5E03\u4E3A\u6B63\u5F0F App \u540E\u53EF\u6B63\u5E38\u4F7F\u7528");
|
|
26
|
+
}
|
|
27
|
+
import_react_native.Alert.alert(title, parts.join("\n"), [{ text: "\u77E5\u9053\u4E86" }]);
|
|
28
|
+
}, validateId = function(id, label = "id") {
|
|
29
|
+
const errors = [];
|
|
30
|
+
if (typeof id !== "string" || id.trim().length === 0) {
|
|
31
|
+
errors.push(`${label} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
|
|
32
|
+
}
|
|
33
|
+
return { ok: errors.length === 0, errors };
|
|
34
|
+
}, validateDate = function(value, label) {
|
|
35
|
+
const errors = [];
|
|
36
|
+
if (value == null) {
|
|
37
|
+
errors.push(`${label} \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
38
|
+
} else if (!(value instanceof Date) && typeof value !== "string") {
|
|
39
|
+
errors.push(`${label} \u5FC5\u987B\u662F Date \u6216\u65E5\u671F\u5B57\u7B26\u4E32`);
|
|
40
|
+
} else if (value instanceof Date && isNaN(value.getTime())) {
|
|
41
|
+
errors.push(`${label} \u662F\u65E0\u6548\u7684 Date \u5BF9\u8C61`);
|
|
42
|
+
}
|
|
43
|
+
return errors;
|
|
44
|
+
}, formatDateArg = function(value) {
|
|
45
|
+
if (value instanceof Date) return value.toLocaleString();
|
|
46
|
+
if (typeof value === "string") return value;
|
|
47
|
+
return String(value);
|
|
48
|
+
}, useCalendarPermissions = function() {
|
|
49
|
+
const [permission, setPermission] = useState(UNDETERMINED_PERMISSION);
|
|
50
|
+
const requestPermission = useCallback(async () => {
|
|
51
|
+
showCalendarAlert(
|
|
52
|
+
"\u8BF7\u6C42\u65E5\u5386\u6743\u9650",
|
|
53
|
+
["\u64CD\u4F5C: \u8BF7\u6C42\u8BBF\u95EE\u624B\u673A\u65E5\u5386\u6743\u9650", "\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u4E0B\u6A21\u62DF\u8FD4\u56DE\u672A\u6388\u6743", "\u53D1\u5E03\u6B63\u5F0F App \u540E\u4F1A\u5F39\u51FA\u7CFB\u7EDF\u6388\u6743\u5F39\u7A97"],
|
|
54
|
+
true
|
|
55
|
+
);
|
|
56
|
+
setPermission(DENIED_PERMISSION);
|
|
57
|
+
return DENIED_PERMISSION;
|
|
58
|
+
}, []);
|
|
59
|
+
const getPermission = useCallback(async () => permission, [permission]);
|
|
60
|
+
return [permission, requestPermission, getPermission];
|
|
61
|
+
}, useRemindersPermissions = function() {
|
|
62
|
+
const [permission, setPermission] = useState(UNDETERMINED_PERMISSION);
|
|
63
|
+
const requestPermission = useCallback(async () => {
|
|
64
|
+
showCalendarAlert(
|
|
65
|
+
"\u8BF7\u6C42\u63D0\u9192\u4E8B\u9879\u6743\u9650",
|
|
66
|
+
["\u64CD\u4F5C: \u8BF7\u6C42\u8BBF\u95EE\u624B\u673A\u63D0\u9192\u4E8B\u9879\u6743\u9650\uFF08iOS \u4E13\u5C5E\uFF09", "\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u4E0B\u6A21\u62DF\u8FD4\u56DE\u672A\u6388\u6743", "\u53D1\u5E03\u6B63\u5F0F App \u540E\u4F1A\u5F39\u51FA\u7CFB\u7EDF\u6388\u6743\u5F39\u7A97"],
|
|
67
|
+
true
|
|
68
|
+
);
|
|
69
|
+
setPermission(DENIED_PERMISSION);
|
|
70
|
+
return DENIED_PERMISSION;
|
|
71
|
+
}, []);
|
|
72
|
+
const getPermission = useCallback(async () => permission, [permission]);
|
|
73
|
+
return [permission, requestPermission, getPermission];
|
|
74
|
+
};
|
|
75
|
+
var showCalendarAlert2 = showCalendarAlert, validateId2 = validateId, validateDate2 = validateDate, formatDateArg2 = formatDateArg, useCalendarPermissions2 = useCalendarPermissions, useRemindersPermissions2 = useRemindersPermissions;
|
|
76
|
+
const UNDETERMINED_PERMISSION = {
|
|
77
|
+
status: "undetermined",
|
|
78
|
+
granted: false,
|
|
79
|
+
canAskAgain: true,
|
|
80
|
+
expires: "never"
|
|
81
|
+
};
|
|
82
|
+
const DENIED_PERMISSION = {
|
|
83
|
+
status: "denied",
|
|
84
|
+
granted: false,
|
|
85
|
+
canAskAgain: false,
|
|
86
|
+
expires: "never"
|
|
87
|
+
};
|
|
88
|
+
const { useState, useCallback } = require("react");
|
|
89
|
+
const requestCalendarPermissionsAsync = async () => {
|
|
90
|
+
showCalendarAlert(
|
|
91
|
+
"\u8BF7\u6C42\u65E5\u5386\u6743\u9650",
|
|
92
|
+
["\u64CD\u4F5C: \u8BF7\u6C42\u8BBF\u95EE\u624B\u673A\u65E5\u5386\u6743\u9650", "\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u4E0B\u6A21\u62DF\u8FD4\u56DE\u672A\u6388\u6743", "\u53D1\u5E03\u6B63\u5F0F App \u540E\u4F1A\u5F39\u51FA\u7CFB\u7EDF\u6388\u6743\u5F39\u7A97"],
|
|
93
|
+
true
|
|
94
|
+
);
|
|
95
|
+
return DENIED_PERMISSION;
|
|
96
|
+
};
|
|
97
|
+
const getCalendarPermissionsAsync = async () => DENIED_PERMISSION;
|
|
98
|
+
const requestRemindersPermissionsAsync = async () => {
|
|
99
|
+
showCalendarAlert(
|
|
100
|
+
"\u8BF7\u6C42\u63D0\u9192\u4E8B\u9879\u6743\u9650",
|
|
101
|
+
["\u64CD\u4F5C: \u8BF7\u6C42\u8BBF\u95EE\u624B\u673A\u63D0\u9192\u4E8B\u9879\u6743\u9650\uFF08iOS \u4E13\u5C5E\uFF09", "\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u4E0B\u6A21\u62DF\u8FD4\u56DE\u672A\u6388\u6743"],
|
|
102
|
+
true
|
|
103
|
+
);
|
|
104
|
+
return DENIED_PERMISSION;
|
|
105
|
+
};
|
|
106
|
+
const getRemindersPermissionsAsync = async () => DENIED_PERMISSION;
|
|
107
|
+
const requestPermissionsAsync = requestCalendarPermissionsAsync;
|
|
108
|
+
const getPermissionsAsync = getCalendarPermissionsAsync;
|
|
109
|
+
const isAvailableAsync = async () => false;
|
|
110
|
+
const getCalendarsAsync = async (entityType) => {
|
|
111
|
+
const typeStr = entityType != null ? String(entityType) : "\u5168\u90E8";
|
|
112
|
+
showCalendarAlert("\u83B7\u53D6\u65E5\u5386\u5217\u8868", [`\u7C7B\u578B: ${typeStr}`, "\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u8FD4\u56DE\u7A7A\u5217\u8868"], true);
|
|
113
|
+
return [];
|
|
114
|
+
};
|
|
115
|
+
const getDefaultCalendarAsync = async () => {
|
|
116
|
+
showCalendarAlert("\u83B7\u53D6\u9ED8\u8BA4\u65E5\u5386", ["\u64CD\u4F5C: \u83B7\u53D6\u7CFB\u7EDF\u9ED8\u8BA4\u65E5\u5386", "\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u4E0D\u652F\u6301"], false, ["\u65E0\u6CD5\u8BBF\u95EE\u7CFB\u7EDF\u65E5\u5386"]);
|
|
117
|
+
return void 0;
|
|
118
|
+
};
|
|
119
|
+
const createCalendarAsync = async (details) => {
|
|
120
|
+
const errors = [];
|
|
121
|
+
const d = details && typeof details === "object" ? details : {};
|
|
122
|
+
const titleVal = d["title"];
|
|
123
|
+
if (typeof titleVal !== "string" || titleVal.trim().length === 0) {
|
|
124
|
+
errors.push("details.title \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
125
|
+
}
|
|
126
|
+
const isValid = errors.length === 0;
|
|
127
|
+
const titleDisplay = typeof titleVal === "string" ? titleVal : "(\u672A\u586B\u5199)";
|
|
128
|
+
showCalendarAlert(
|
|
129
|
+
"\u521B\u5EFA\u65E5\u5386",
|
|
130
|
+
[`\u540D\u79F0: ${titleDisplay}`, `\u989C\u8272: ${d["color"] ?? "(\u672A\u8BBE\u7F6E)"}`],
|
|
131
|
+
isValid,
|
|
132
|
+
isValid ? void 0 : errors
|
|
133
|
+
);
|
|
134
|
+
return "stub";
|
|
135
|
+
};
|
|
136
|
+
const updateCalendarAsync = async (id, details) => {
|
|
137
|
+
const { ok: idOk, errors: idErrors } = validateId(id, "calendarId");
|
|
138
|
+
const d = details && typeof details === "object" ? details : {};
|
|
139
|
+
showCalendarAlert(
|
|
140
|
+
"\u66F4\u65B0\u65E5\u5386",
|
|
141
|
+
[
|
|
142
|
+
`\u65E5\u5386 ID: ${typeof id === "string" ? id : String(id)}`,
|
|
143
|
+
`\u66F4\u65B0\u5B57\u6BB5: ${Object.keys(d).join(", ") || "(\u65E0)"}`
|
|
144
|
+
],
|
|
145
|
+
idOk,
|
|
146
|
+
idOk ? void 0 : idErrors
|
|
147
|
+
);
|
|
148
|
+
return typeof id === "string" ? id : "stub";
|
|
149
|
+
};
|
|
150
|
+
const deleteCalendarAsync = async (id) => {
|
|
151
|
+
const { ok, errors } = validateId(id, "calendarId");
|
|
152
|
+
showCalendarAlert(
|
|
153
|
+
"\u5220\u9664\u65E5\u5386",
|
|
154
|
+
[`\u65E5\u5386 ID: ${typeof id === "string" ? id : String(id)}`],
|
|
155
|
+
ok,
|
|
156
|
+
ok ? void 0 : errors
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
const getEventsAsync = async (calendarIds, startDate, endDate) => {
|
|
160
|
+
const errors = [];
|
|
161
|
+
if (!Array.isArray(calendarIds) || calendarIds.length === 0) {
|
|
162
|
+
errors.push("calendarIds \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");
|
|
163
|
+
}
|
|
164
|
+
errors.push(...validateDate(startDate, "startDate"));
|
|
165
|
+
errors.push(...validateDate(endDate, "endDate"));
|
|
166
|
+
const isValid = errors.length === 0;
|
|
167
|
+
const idsStr = Array.isArray(calendarIds) ? `[${calendarIds.slice(0, 3).join(", ")}${calendarIds.length > 3 ? "\u2026" : ""}]` : String(calendarIds);
|
|
168
|
+
showCalendarAlert(
|
|
169
|
+
"\u67E5\u8BE2\u65E5\u5386\u4E8B\u4EF6",
|
|
170
|
+
[
|
|
171
|
+
`\u65E5\u5386 IDs: ${idsStr}`,
|
|
172
|
+
`\u5F00\u59CB\u65F6\u95F4: ${formatDateArg(startDate)}`,
|
|
173
|
+
`\u7ED3\u675F\u65F6\u95F4: ${formatDateArg(endDate)}`,
|
|
174
|
+
"\u79D2\u54D2\u9884\u89C8\u6A21\u5F0F\u8FD4\u56DE\u7A7A\u5217\u8868"
|
|
175
|
+
],
|
|
176
|
+
isValid,
|
|
177
|
+
isValid ? void 0 : errors
|
|
178
|
+
);
|
|
179
|
+
return [];
|
|
180
|
+
};
|
|
181
|
+
const getEventAsync = async (id) => {
|
|
182
|
+
const { ok, errors } = validateId(id, "eventId");
|
|
183
|
+
showCalendarAlert(
|
|
184
|
+
"\u83B7\u53D6\u65E5\u5386\u4E8B\u4EF6",
|
|
185
|
+
[`\u4E8B\u4EF6 ID: ${typeof id === "string" ? id : String(id)}`],
|
|
186
|
+
ok,
|
|
187
|
+
ok ? void 0 : errors
|
|
188
|
+
);
|
|
189
|
+
return void 0;
|
|
190
|
+
};
|
|
191
|
+
const createEventAsync = async (calendarId, eventData) => {
|
|
192
|
+
const errors = [];
|
|
193
|
+
const { errors: idErrors } = validateId(calendarId, "calendarId");
|
|
194
|
+
errors.push(...idErrors);
|
|
195
|
+
const data = eventData && typeof eventData === "object" ? eventData : {};
|
|
196
|
+
if (import_react_native.Platform.OS === "android") {
|
|
197
|
+
errors.push(...validateDate(data["startDate"], "eventData.startDate"));
|
|
198
|
+
errors.push(...validateDate(data["endDate"], "eventData.endDate"));
|
|
199
|
+
}
|
|
200
|
+
const titleVal = data["title"];
|
|
201
|
+
const titleDisplay = typeof titleVal === "string" ? titleVal : "(\u672A\u586B\u5199)";
|
|
202
|
+
const startDisplay = data["startDate"] != null ? formatDateArg(data["startDate"]) : "(\u672A\u8BBE\u7F6E)";
|
|
203
|
+
const endDisplay = data["endDate"] != null ? formatDateArg(data["endDate"]) : "(\u672A\u8BBE\u7F6E)";
|
|
204
|
+
const isValid = errors.length === 0;
|
|
205
|
+
showCalendarAlert(
|
|
206
|
+
"\u521B\u5EFA\u65E5\u5386\u4E8B\u4EF6",
|
|
207
|
+
[
|
|
208
|
+
`\u65E5\u5386 ID: ${typeof calendarId === "string" ? calendarId : String(calendarId)}`,
|
|
209
|
+
`\u6807\u9898: ${titleDisplay}`,
|
|
210
|
+
`\u5F00\u59CB: ${startDisplay}`,
|
|
211
|
+
`\u7ED3\u675F: ${endDisplay}`
|
|
212
|
+
],
|
|
213
|
+
isValid,
|
|
214
|
+
isValid ? void 0 : errors
|
|
215
|
+
);
|
|
216
|
+
return "stub";
|
|
217
|
+
};
|
|
218
|
+
const updateEventAsync = async (id, details) => {
|
|
219
|
+
const { ok, errors } = validateId(id, "eventId");
|
|
220
|
+
const d = details && typeof details === "object" ? details : {};
|
|
221
|
+
showCalendarAlert(
|
|
222
|
+
"\u66F4\u65B0\u65E5\u5386\u4E8B\u4EF6",
|
|
223
|
+
[
|
|
224
|
+
`\u4E8B\u4EF6 ID: ${typeof id === "string" ? id : String(id)}`,
|
|
225
|
+
`\u66F4\u65B0\u5B57\u6BB5: ${Object.keys(d).join(", ") || "(\u65E0)"}`
|
|
226
|
+
],
|
|
227
|
+
ok,
|
|
228
|
+
ok ? void 0 : errors
|
|
229
|
+
);
|
|
230
|
+
return typeof id === "string" ? id : "stub";
|
|
231
|
+
};
|
|
232
|
+
const deleteEventAsync = async (id) => {
|
|
233
|
+
const { ok, errors } = validateId(id, "eventId");
|
|
234
|
+
showCalendarAlert(
|
|
235
|
+
"\u5220\u9664\u65E5\u5386\u4E8B\u4EF6",
|
|
236
|
+
[`\u4E8B\u4EF6 ID: ${typeof id === "string" ? id : String(id)}`],
|
|
237
|
+
ok,
|
|
238
|
+
ok ? void 0 : errors
|
|
239
|
+
);
|
|
240
|
+
};
|
|
241
|
+
const enums = {
|
|
242
|
+
EntityTypes: { EVENT: "event", REMINDER: "reminder" },
|
|
243
|
+
Frequency: { DAILY: "daily", WEEKLY: "weekly", MONTHLY: "monthly", YEARLY: "yearly" },
|
|
244
|
+
Availability: {
|
|
245
|
+
NOT_SUPPORTED: "notSupported",
|
|
246
|
+
BUSY: "busy",
|
|
247
|
+
FREE: "free",
|
|
248
|
+
TENTATIVE: "tentative",
|
|
249
|
+
UNAVAILABLE: "unavailable"
|
|
250
|
+
},
|
|
251
|
+
CalendarType: {
|
|
252
|
+
LOCAL: "local",
|
|
253
|
+
CALDAV: "caldav",
|
|
254
|
+
EXCHANGE: "exchange",
|
|
255
|
+
SUBSCRIBED: "subscribed",
|
|
256
|
+
BIRTHDAYS: "birthdays",
|
|
257
|
+
UNKNOWN: "unknown"
|
|
258
|
+
},
|
|
259
|
+
EventStatus: { NONE: "none", CONFIRMED: "confirmed", TENTATIVE: "tentative", CANCELED: "canceled" },
|
|
260
|
+
SourceType: {
|
|
261
|
+
LOCAL: "local",
|
|
262
|
+
EXCHANGE: "exchange",
|
|
263
|
+
CALDAV: "caldav",
|
|
264
|
+
MOBILEME: "mobileme",
|
|
265
|
+
SUBSCRIBED: "subscribed",
|
|
266
|
+
BIRTHDAYS: "birthdays"
|
|
267
|
+
},
|
|
268
|
+
AttendeeRole: {
|
|
269
|
+
UNKNOWN: "unknown",
|
|
270
|
+
REQUIRED: "required",
|
|
271
|
+
OPTIONAL: "optional",
|
|
272
|
+
CHAIR: "chair",
|
|
273
|
+
NON_PARTICIPANT: "nonParticipant",
|
|
274
|
+
ATTENDEE: "attendee",
|
|
275
|
+
ORGANIZER: "organizer",
|
|
276
|
+
PERFORMER: "performer",
|
|
277
|
+
SPEAKER: "speaker",
|
|
278
|
+
NONE: "none"
|
|
279
|
+
},
|
|
280
|
+
AttendeeStatus: {
|
|
281
|
+
UNKNOWN: "unknown",
|
|
282
|
+
PENDING: "pending",
|
|
283
|
+
ACCEPTED: "accepted",
|
|
284
|
+
DECLINED: "declined",
|
|
285
|
+
TENTATIVE: "tentative",
|
|
286
|
+
DELEGATED: "delegated",
|
|
287
|
+
COMPLETED: "completed",
|
|
288
|
+
IN_PROCESS: "inProcess",
|
|
289
|
+
INVITED: "invited",
|
|
290
|
+
NONE: "none"
|
|
291
|
+
},
|
|
292
|
+
AttendeeType: {
|
|
293
|
+
UNKNOWN: "unknown",
|
|
294
|
+
PERSON: "person",
|
|
295
|
+
ROOM: "room",
|
|
296
|
+
GROUP: "group",
|
|
297
|
+
RESOURCE: "resource",
|
|
298
|
+
OPTIONAL: "optional",
|
|
299
|
+
REQUIRED: "required",
|
|
300
|
+
NONE: "none"
|
|
301
|
+
},
|
|
302
|
+
AlarmMethod: { ALARM: "alarm", ALERT: "alert", EMAIL: "email", SMS: "sms", DEFAULT: "default" },
|
|
303
|
+
EventAccessLevel: { CONFIDENTIAL: "confidential", PRIVATE: "private", PUBLIC: "public", DEFAULT: "default" },
|
|
304
|
+
CalendarAccessLevel: {
|
|
305
|
+
CONTRIBUTOR: "contributor",
|
|
306
|
+
EDITOR: "editor",
|
|
307
|
+
FREEBUSY: "freebusy",
|
|
308
|
+
OVERRIDE: "override",
|
|
309
|
+
OWNER: "owner",
|
|
310
|
+
READ: "read",
|
|
311
|
+
RESPOND: "respond",
|
|
312
|
+
ROOT: "root",
|
|
313
|
+
NONE: "none"
|
|
314
|
+
},
|
|
315
|
+
ReminderStatus: { COMPLETED: "completed", INCOMPLETE: "incomplete" },
|
|
316
|
+
PermissionStatus: { GRANTED: "granted", DENIED: "denied", UNDETERMINED: "undetermined" },
|
|
317
|
+
DayOfTheWeek: { SU: 1, MO: 2, TU: 3, WE: 4, TH: 5, FR: 6, SA: 7 },
|
|
318
|
+
MonthOfTheYear: { JAN: 1, FEB: 2, MAR: 3, APR: 4, MAY: 5, JUN: 6, JUL: 7, AUG: 8, SEP: 9, OCT: 10, NOV: 11, DEC: 12 },
|
|
319
|
+
CalendarDialogResultActions: { SAVED: "saved", CANCELED: "canceled", DELETED: "deleted" }
|
|
320
|
+
};
|
|
321
|
+
const coreHandlers = {
|
|
322
|
+
isAvailableAsync,
|
|
323
|
+
useCalendarPermissions,
|
|
324
|
+
useRemindersPermissions,
|
|
325
|
+
requestCalendarPermissionsAsync,
|
|
326
|
+
getCalendarPermissionsAsync,
|
|
327
|
+
requestRemindersPermissionsAsync,
|
|
328
|
+
getRemindersPermissionsAsync,
|
|
329
|
+
requestPermissionsAsync,
|
|
330
|
+
getPermissionsAsync,
|
|
331
|
+
getCalendarsAsync,
|
|
332
|
+
getDefaultCalendarAsync,
|
|
333
|
+
createCalendarAsync,
|
|
334
|
+
updateCalendarAsync,
|
|
335
|
+
deleteCalendarAsync,
|
|
336
|
+
getEventsAsync,
|
|
337
|
+
getEventAsync,
|
|
338
|
+
createEventAsync,
|
|
339
|
+
updateEventAsync,
|
|
340
|
+
deleteEventAsync
|
|
341
|
+
};
|
|
342
|
+
const noopPermission = async () => DENIED_PERMISSION;
|
|
343
|
+
const noop = async () => void 0;
|
|
344
|
+
module.exports = new Proxy(enums, {
|
|
345
|
+
get(target, key) {
|
|
346
|
+
if (key in target) return target[key];
|
|
347
|
+
if (key in coreHandlers) return coreHandlers[key];
|
|
348
|
+
if (key.endsWith("PermissionsAsync")) return noopPermission;
|
|
349
|
+
return noop;
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=expo-calendar-stub.js.map
|
package/oxlint-config.json
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
{ "name": "expo-router-url", "specifier": "miaoda-expo-devkit/rules/no-duplicate-expo-router-url" },
|
|
9
9
|
{ "name": "css-import", "specifier": "miaoda-expo-devkit/rules/no-missing-css-import" },
|
|
10
10
|
{ "name": "expo-router-layout", "specifier": "miaoda-expo-devkit/rules/no-invalid-tabs-screen" },
|
|
11
|
-
{ "name": "expo-router-dynamic-tab", "specifier": "miaoda-expo-devkit/rules/no-unregistered-dynamic-tab-route" }
|
|
11
|
+
{ "name": "expo-router-dynamic-tab", "specifier": "miaoda-expo-devkit/rules/no-unregistered-dynamic-tab-route" },
|
|
12
|
+
{ "name": "rn-pressable", "specifier": "miaoda-expo-devkit/rules/no-pressable-without-on-press" }
|
|
12
13
|
],
|
|
13
14
|
|
|
14
15
|
"categories": {
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
"css-import/no-missing-css-import": "error",
|
|
24
25
|
"expo-router-layout/no-invalid-tabs-screen": "error",
|
|
25
26
|
"expo-router-dynamic-tab/no-unregistered-dynamic-tab-route": "error",
|
|
27
|
+
"rn-pressable/no-pressable-without-on-press": "error",
|
|
26
28
|
|
|
27
29
|
"expo/no-dynamic-env-var": "error",
|
|
28
30
|
"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.39",
|
|
4
4
|
"description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"./no-op-logbox": "./dist/stubs/no-op-logbox.js",
|
|
47
47
|
"./expo-notifications-stub": "./dist/stubs/expo-notifications-stub.js",
|
|
48
48
|
"./expo-media-library-stub": "./dist/stubs/expo-media-library-stub.js",
|
|
49
|
+
"./expo-calendar-stub": "./dist/stubs/expo-calendar-stub.js",
|
|
49
50
|
"./rules/no-undeclared-expo-plugin": "./dist/rules/no-undeclared-expo-plugin.js",
|
|
50
51
|
"./rules/no-unused-expo-plugin": "./dist/rules/no-unused-expo-plugin.js",
|
|
51
52
|
"./rules/no-unstable-expo-router": "./dist/rules/no-unstable-expo-router.js",
|