From 316e5def7297780a17a97deef8b452ef37ecdcb0 Mon Sep 17 00:00:00 2001 From: Florian Egger Date: Tue, 12 May 2026 22:29:38 +0200 Subject: [PATCH] Refactor mobile to fix dependency resolution and add polyfills Update Expo and React dependencies to compatible versions. Create a custom Metro config to resolve module conflicts in the workspace and map Jest modules to local node_modules. Add a SharedArrayBuffer polyfill for older runtimes and introduce an adapter for expo-notifications to abstract direct imports. --- apps/mobile/App.tsx | 2 +- apps/mobile/index.ts | 1 + apps/mobile/jest.config.cjs | 8 + apps/mobile/metro.config.js | 27 ++ apps/mobile/package.json | 16 +- apps/mobile/src/__tests__/eventStore.test.ts | 6 +- .../src/__tests__/notifications.test.ts | 4 +- .../mobile/src/polyfills/sharedArrayBuffer.ts | 78 ++++ apps/mobile/src/services/expoNotifications.ts | 12 + apps/mobile/src/services/notifications.ts | 4 +- apps/mobile/src/store/eventStore.ts | 4 +- package-lock.json | 357 +++++++++++------- package.json | 2 +- 13 files changed, 371 insertions(+), 150 deletions(-) create mode 100644 apps/mobile/metro.config.js create mode 100644 apps/mobile/src/polyfills/sharedArrayBuffer.ts create mode 100644 apps/mobile/src/services/expoNotifications.ts diff --git a/apps/mobile/App.tsx b/apps/mobile/App.tsx index bbf1809..c66b7db 100644 --- a/apps/mobile/App.tsx +++ b/apps/mobile/App.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import * as Notifications from 'expo-notifications'; +import * as Notifications from './src/services/expoNotifications'; import AppNavigator from './src/navigation/AppNavigator'; export default function App() { diff --git a/apps/mobile/index.ts b/apps/mobile/index.ts index 1d6e981..96c00d5 100644 --- a/apps/mobile/index.ts +++ b/apps/mobile/index.ts @@ -1,3 +1,4 @@ +import './src/polyfills/sharedArrayBuffer'; import { registerRootComponent } from 'expo'; import App from './App'; diff --git a/apps/mobile/jest.config.cjs b/apps/mobile/jest.config.cjs index b8480c5..2f7ae1e 100644 --- a/apps/mobile/jest.config.cjs +++ b/apps/mobile/jest.config.cjs @@ -1,4 +1,12 @@ module.exports = { preset: 'jest-expo', testMatch: ['**/__tests__/**/*.test.[jt]s?(x)'], + moduleNameMapper: { + '^react$': '/node_modules/react', + '^react-test-renderer$': '/node_modules/react-test-renderer', + '^react-native-safe-area-context$': '/node_modules/react-native-safe-area-context', + '^react-native-screens$': '/node_modules/react-native-screens', + '^@react-native-async-storage/async-storage$': + '/node_modules/@react-native-async-storage/async-storage', + }, }; diff --git a/apps/mobile/metro.config.js b/apps/mobile/metro.config.js new file mode 100644 index 0000000..f6a5189 --- /dev/null +++ b/apps/mobile/metro.config.js @@ -0,0 +1,27 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { getDefaultConfig } from 'expo/metro-config.js'; + +const projectRoot = path.dirname(fileURLToPath(import.meta.url)); +const workspaceRoot = path.resolve(projectRoot, '../..'); + +const config = getDefaultConfig(projectRoot); + +config.resolver.disableHierarchicalLookup = true; +config.resolver.nodeModulesPaths = [ + path.resolve(projectRoot, 'node_modules'), + path.resolve(workspaceRoot, 'node_modules'), +]; +config.resolver.extraNodeModules = { + react: path.resolve(projectRoot, 'node_modules/react'), + 'react-test-renderer': path.resolve(projectRoot, 'node_modules/react-test-renderer'), + 'react-native-safe-area-context': path.resolve(projectRoot, 'node_modules/react-native-safe-area-context'), + 'react-native-screens': path.resolve(projectRoot, 'node_modules/react-native-screens'), + '@react-native-async-storage/async-storage': path.resolve( + projectRoot, + 'node_modules/@react-native-async-storage/async-storage', + ), + 'expo-application': path.resolve(projectRoot, 'node_modules/expo-notifications/node_modules/expo-application'), +}; + +export default config; diff --git a/apps/mobile/package.json b/apps/mobile/package.json index a7d0a4d..e0a4a08 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -13,20 +13,20 @@ "test": "jest" }, "dependencies": { - "@react-native-async-storage/async-storage": "^3.0.2", + "@react-native-async-storage/async-storage": "2.2.0", "@react-navigation/native": "^7.2.4", "@react-navigation/native-stack": "^7.14.14", "@timetoleave/api-client": "*", "@timetoleave/core": "*", "expo": "~54.0.33", - "expo-calendar": "^55.0.14", - "expo-location": "^55.1.9", - "expo-notifications": "^55.0.22", + "expo-calendar": "~15.0.8", + "expo-location": "~19.0.8", + "expo-notifications": "~0.32.17", "expo-status-bar": "~3.0.9", - "react": "19.2.4", + "react": "19.1.0", "react-native": "0.81.5", - "react-native-safe-area-context": "^5.7.0", - "react-native-screens": "^4.24.0" + "react-native-safe-area-context": "~5.6.0", + "react-native-screens": "~4.16.0" }, "devDependencies": { "@eslint/js": "^9.39.4", @@ -36,7 +36,7 @@ "eslint-plugin-react": "^7.37.5", "jest": "^29.7.0", "jest-expo": "~54.0.0", - "react-test-renderer": "19.2.4", + "react-test-renderer": "19.1.0", "ts-jest": "^29.4.9", "typescript": "~5.9.2", "typescript-eslint": "^8.59.3" diff --git a/apps/mobile/src/__tests__/eventStore.test.ts b/apps/mobile/src/__tests__/eventStore.test.ts index 655a9cd..66d1737 100644 --- a/apps/mobile/src/__tests__/eventStore.test.ts +++ b/apps/mobile/src/__tests__/eventStore.test.ts @@ -12,7 +12,7 @@ import { rescheduleAllNotifications } from '../store/eventStore'; import { calculateLeaveByTime } from '../services/notifications'; -import * as Notifications from 'expo-notifications'; +import * as Notifications from '../services/expoNotifications'; // Mock AsyncStorage jest.mock('@react-native-async-storage/async-storage', () => ({ @@ -21,8 +21,8 @@ jest.mock('@react-native-async-storage/async-storage', () => ({ removeItem: jest.fn(), })); -// Mock expo-notifications -jest.mock('expo-notifications', () => ({ +// Mock notification adapter +jest.mock('../services/expoNotifications', () => ({ getAllScheduledNotificationsAsync: jest.fn(), cancelScheduledNotificationAsync: jest.fn(), cancelAllScheduledNotificationsAsync: jest.fn(), diff --git a/apps/mobile/src/__tests__/notifications.test.ts b/apps/mobile/src/__tests__/notifications.test.ts index 6d9d776..3679e11 100644 --- a/apps/mobile/src/__tests__/notifications.test.ts +++ b/apps/mobile/src/__tests__/notifications.test.ts @@ -1,6 +1,6 @@ // Tests for notification service -// Mock expo-notifications before importing -jest.mock('expo-notifications', () => ({ +// Mock notification adapter before importing +jest.mock('../services/expoNotifications', () => ({ setNotificationHandler: jest.fn(), requestPermissionsAsync: jest.fn().mockResolvedValue({ status: 'granted' }), scheduleNotificationAsync: jest.fn().mockResolvedValue({ identifier: 'mock-id' }), diff --git a/apps/mobile/src/polyfills/sharedArrayBuffer.ts b/apps/mobile/src/polyfills/sharedArrayBuffer.ts new file mode 100644 index 0000000..e1e8551 --- /dev/null +++ b/apps/mobile/src/polyfills/sharedArrayBuffer.ts @@ -0,0 +1,78 @@ +const globalScope = globalThis as Record; +const stringPrototype = String.prototype as typeof String.prototype & { + isWellFormed?: () => boolean; + toWellFormed?: () => string; +}; + +const arrayBufferByteLength = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength')?.get; + +function toWellFormedString(value: string): string { + let result = ''; + + for (let index = 0; index < value.length; index += 1) { + const code = value.charCodeAt(index); + + if (code >= 0xd800 && code <= 0xdbff) { + const next = value.charCodeAt(index + 1); + if (next >= 0xdc00 && next <= 0xdfff) { + result += value[index] + value[index + 1]; + index += 1; + } else { + result += '\uFFFD'; + } + } else if (code >= 0xdc00 && code <= 0xdfff) { + result += '\uFFFD'; + } else { + result += value[index]; + } + } + + return result; +} + +if (typeof stringPrototype.toWellFormed !== 'function') { + Object.defineProperty(String.prototype, 'toWellFormed', { + configurable: true, + value() { + return toWellFormedString(String(this)); + }, + }); +} + +if (typeof stringPrototype.isWellFormed !== 'function') { + Object.defineProperty(String.prototype, 'isWellFormed', { + configurable: true, + value() { + const value = String(this); + return toWellFormedString(value) === value; + }, + }); +} + +if (!Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'resizable')) { + Object.defineProperty(ArrayBuffer.prototype, 'resizable', { + configurable: true, + get() { + return false; + }, + }); +} + +if (typeof globalScope.SharedArrayBuffer === 'undefined') { + class SharedArrayBufferPolyfill extends ArrayBuffer { + get byteLength() { + return arrayBufferByteLength?.call(this) ?? 0; + } + + get growable() { + return false; + } + } + + Object.defineProperty(SharedArrayBufferPolyfill.prototype, Symbol.toStringTag, { + configurable: true, + value: 'SharedArrayBuffer', + }); + + globalScope.SharedArrayBuffer = SharedArrayBufferPolyfill; +} diff --git a/apps/mobile/src/services/expoNotifications.ts b/apps/mobile/src/services/expoNotifications.ts new file mode 100644 index 0000000..08d99c0 --- /dev/null +++ b/apps/mobile/src/services/expoNotifications.ts @@ -0,0 +1,12 @@ +export { requestPermissionsAsync } from 'expo-notifications/build/NotificationPermissions.js'; +export { setNotificationHandler } from 'expo-notifications/build/NotificationsHandler.js'; +export { default as getAllScheduledNotificationsAsync } from 'expo-notifications/build/getAllScheduledNotificationsAsync.js'; +export { default as cancelScheduledNotificationAsync } from 'expo-notifications/build/cancelScheduledNotificationAsync.js'; +export { default as cancelAllScheduledNotificationsAsync } from 'expo-notifications/build/cancelAllScheduledNotificationsAsync.js'; +export { default as scheduleNotificationAsync } from 'expo-notifications/build/scheduleNotificationAsync.js'; +export { SchedulableTriggerInputTypes } from 'expo-notifications/build/Notifications.types.js'; +export type { + NotificationBehavior, + NotificationRequest, + NotificationRequestInput, +} from 'expo-notifications/build/Notifications.types.js'; diff --git a/apps/mobile/src/services/notifications.ts b/apps/mobile/src/services/notifications.ts index 1d07f7e..5862954 100644 --- a/apps/mobile/src/services/notifications.ts +++ b/apps/mobile/src/services/notifications.ts @@ -1,5 +1,5 @@ -import * as Notifications from 'expo-notifications'; -import { SchedulableTriggerInputTypes } from 'expo-notifications'; +import * as Notifications from './expoNotifications'; +import { SchedulableTriggerInputTypes } from './expoNotifications'; import type { Event, Journey, ReminderSettings } from '@timetoleave/core'; // Register for push notification permissions diff --git a/apps/mobile/src/store/eventStore.ts b/apps/mobile/src/store/eventStore.ts index 187f9c0..b2162f1 100644 --- a/apps/mobile/src/store/eventStore.ts +++ b/apps/mobile/src/store/eventStore.ts @@ -1,7 +1,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; import type { Event, Station, ReminderSettings } from '@timetoleave/core'; -import * as Notifications from 'expo-notifications'; -import { SchedulableTriggerInputTypes } from 'expo-notifications'; +import * as Notifications from '../services/expoNotifications'; +import { SchedulableTriggerInputTypes } from '../services/expoNotifications'; // ── Keys ─────────────────────────────── diff --git a/package-lock.json b/package-lock.json index d88a96b..33b136b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,20 +16,20 @@ "name": "@timetoleave/mobile", "version": "1.0.0", "dependencies": { - "@react-native-async-storage/async-storage": "^3.0.2", + "@react-native-async-storage/async-storage": "2.2.0", "@react-navigation/native": "^7.2.4", "@react-navigation/native-stack": "^7.14.14", "@timetoleave/api-client": "*", "@timetoleave/core": "*", "expo": "~54.0.33", - "expo-calendar": "^55.0.14", - "expo-location": "^55.1.9", - "expo-notifications": "^55.0.22", + "expo-calendar": "~15.0.8", + "expo-location": "~19.0.8", + "expo-notifications": "~0.32.17", "expo-status-bar": "~3.0.9", - "react": "19.2.4", + "react": "19.1.0", "react-native": "0.81.5", - "react-native-safe-area-context": "^5.7.0", - "react-native-screens": "^4.24.0" + "react-native-safe-area-context": "~5.6.0", + "react-native-screens": "~4.16.0" }, "devDependencies": { "@eslint/js": "^9.39.4", @@ -39,12 +39,127 @@ "eslint-plugin-react": "^7.37.5", "jest": "^29.7.0", "jest-expo": "~54.0.0", - "react-test-renderer": "19.2.4", + "react-test-renderer": "19.1.0", "ts-jest": "^29.4.9", "typescript": "~5.9.2", "typescript-eslint": "^8.59.3" } }, + "apps/mobile/node_modules/@react-native-async-storage/async-storage": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz", + "integrity": "sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.65 <1.0" + } + }, + "apps/mobile/node_modules/expo-calendar": { + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/expo-calendar/-/expo-calendar-15.0.8.tgz", + "integrity": "sha512-i+ojy6zFnWSPb2DYp4L4W4U5iVI+NXnuHr3xysShoV8znNOmixP1TOYuJXt5Lpz+BpHCWseU31gV1E5SSkIKsw==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react-native": "*" + } + }, + "apps/mobile/node_modules/expo-location": { + "version": "19.0.8", + "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-19.0.8.tgz", + "integrity": "sha512-H/FI75VuJ1coodJbbMu82pf+Zjess8X8Xkiv9Bv58ZgPKS/2ztjC1YO1/XMcGz7+s9DrbLuMIw22dFuP4HqneA==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "apps/mobile/node_modules/expo-notifications": { + "version": "0.32.17", + "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-0.32.17.tgz", + "integrity": "sha512-lwwzn7tImuzTzn9PAglZlS2VfZEvsfFGJTK9Eb8I4cqkGh2DI23YJFJH+WPEIu4QhDvk5JeBjklenJ8IZbmA4A==", + "license": "MIT", + "dependencies": { + "@expo/image-utils": "^0.8.8", + "@ide/backoff": "^1.0.0", + "abort-controller": "^3.0.0", + "assert": "^2.0.0", + "badgin": "^1.1.5", + "expo-application": "~7.0.8", + "expo-constants": "~18.0.13" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "apps/mobile/node_modules/expo-notifications/node_modules/expo-application": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-7.0.8.tgz", + "integrity": "sha512-qFGyxk7VJbrNOQWBbE09XUuGuvkOgFS9QfToaK2FdagM2aQ+x3CvGV2DuVgl/l4ZxPgIf3b/MNh9xHpwSwn74Q==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "apps/mobile/node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "apps/mobile/node_modules/react-native-safe-area-context": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", + "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "apps/mobile/node_modules/react-native-screens": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz", + "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==", + "license": "MIT", + "dependencies": { + "react-freeze": "^1.0.0", + "react-native-is-edge-to-edge": "^1.2.1", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "apps/mobile/node_modules/react-test-renderer": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-19.1.0.tgz", + "integrity": "sha512-jXkSl3CpvPYEF+p/eGDLB4sPoDX8pKkYvRl9+rR8HxLY0X04vW7hCm1/0zHoUSjPZ3bDa+wXWNTDVIw/R8aDVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "react-is": "^19.1.0", + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "apps/mobile/node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "dev": true, + "license": "MIT" + }, "apps/web": { "name": "@timetoleave/web", "version": "1.0.0", @@ -2742,6 +2857,12 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@ide/backoff": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@ide/backoff/-/backoff-1.0.0.tgz", + "integrity": "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==", + "license": "MIT" + }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", @@ -4658,19 +4779,6 @@ "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@react-native-async-storage/async-storage": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-3.0.2.tgz", - "integrity": "sha512-XP0zDIl+1XoeuQ7f878qXKdl77zLwzLALPpxvNRc7ZtDh9ew36WSvOdQOhFkexMySapFAWxEbZxS8K8J2DU4eg==", - "license": "MIT", - "dependencies": { - "idb": "8.0.3" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, "node_modules/@react-native/assets-registry": { "version": "0.81.5", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz", @@ -7227,6 +7335,19 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "license": "MIT" }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -7271,7 +7392,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" @@ -7776,7 +7896,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -7795,7 +7914,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -7809,7 +7927,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -8499,7 +8616,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -8526,7 +8642,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", @@ -8683,7 +8798,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -8863,7 +8977,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8917,7 +9030,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -9592,15 +9704,6 @@ } } }, - "node_modules/expo-application": { - "version": "55.0.14", - "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-55.0.14.tgz", - "integrity": "sha512-NgqDIt3eCf4aVLp1L6AcEanCYoyJeuBsGrgGSzOIvxAsOvp5X3SYKW3ROgpKUnLQEKMWlzwETpjsUGszcqkk8g==", - "license": "MIT", - "peerDependencies": { - "expo": "*" - } - }, "node_modules/expo-asset": { "version": "12.0.13", "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-12.0.13.tgz", @@ -9616,16 +9719,6 @@ "react-native": "*" } }, - "node_modules/expo-calendar": { - "version": "55.0.14", - "resolved": "https://registry.npmjs.org/expo-calendar/-/expo-calendar-55.0.14.tgz", - "integrity": "sha512-DndwzRNrjyjaMRY9ob/X8TdptLcpckVMGnv8rMjABH2jMWToeLElgq7lttytCTAoablZfVLowcizdD+GwSqNzw==", - "license": "MIT", - "peerDependencies": { - "expo": "*", - "react-native": "*" - } - }, "node_modules/expo-constants": { "version": "18.0.13", "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz", @@ -9674,18 +9767,6 @@ "react": "*" } }, - "node_modules/expo-location": { - "version": "55.1.9", - "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-55.1.9.tgz", - "integrity": "sha512-PIH9/qeyhtGh190FyIJNZYHXZOoi42SbVHY9IoTMBmqWLHf1BJyGhPpFlaLBSCjxObqfVZmrWsN5dtjueSwYQA==", - "license": "MIT", - "dependencies": { - "@expo/image-utils": "^0.8.13" - }, - "peerDependencies": { - "expo": "*" - } - }, "node_modules/expo-modules-autolinking": { "version": "3.0.25", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.25.tgz", @@ -9715,51 +9796,6 @@ "react-native": "*" } }, - "node_modules/expo-notifications": { - "version": "55.0.22", - "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-55.0.22.tgz", - "integrity": "sha512-Rwvsp/lAEXfDYBxkQZpaLF9ZB25cJ/yfHhD/ESclbPesN0nbQBZ/5rGb1xS/saANtkStbEGfDlA80uHh2zEpsA==", - "license": "MIT", - "dependencies": { - "@expo/image-utils": "^0.8.13", - "abort-controller": "^3.0.0", - "badgin": "^1.1.5", - "expo-application": "~55.0.14", - "expo-constants": "~55.0.15" - }, - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" - } - }, - "node_modules/expo-notifications/node_modules/@expo/env": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.1.2.tgz", - "integrity": "sha512-RJtGFfj/ygO/6zcVbV3cckHf4THcEkv5IZft1GjCB3dfT6axvzvIwXE9EiQqQYmGHcQ+ZrvC8xZcIhiHba0pYg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "debug": "^4.3.4", - "getenv": "^2.0.0" - }, - "engines": { - "node": ">=20.12.0" - } - }, - "node_modules/expo-notifications/node_modules/expo-constants": { - "version": "55.0.16", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-55.0.16.tgz", - "integrity": "sha512-Z15/No94UHoogD+pulxjudGAeOHTEIWZgb/vnX48Wx5D+apWTeCbnKxQZZtGQlosvduYL5kaic2/W8U+NHfBQQ==", - "license": "MIT", - "dependencies": { - "@expo/env": "~2.1.2" - }, - "peerDependencies": { - "expo": "*", - "react-native": "*" - } - }, "node_modules/expo-server": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-1.0.6.tgz", @@ -10026,7 +10062,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, "license": "MIT", "dependencies": { "is-callable": "^1.2.7" @@ -10137,7 +10172,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10165,7 +10199,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -10199,7 +10232,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -10362,7 +10394,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10425,7 +10456,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -10454,7 +10484,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10467,7 +10496,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -10639,12 +10667,6 @@ "node": ">=0.10.0" } }, - "node_modules/idb": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.3.tgz", - "integrity": "sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==", - "license": "ISC" - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -10802,6 +10824,22 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -10907,7 +10945,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -11030,7 +11067,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.4", @@ -11072,6 +11108,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -11111,6 +11163,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -11122,7 +11183,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -11218,7 +11278,6 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, "license": "MIT", "dependencies": { "which-typed-array": "^1.1.16" @@ -14428,7 +14487,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -14447,6 +14505,18 @@ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", "license": "MIT" }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -15267,11 +15337,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -15281,7 +15366,6 @@ "version": "4.1.7", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", @@ -15888,7 +15972,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -16332,6 +16415,7 @@ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.7.0.tgz", "integrity": "sha512-/9/MtQz8ODphjsLdZ+GZAIcC/RtoqW9EeShf7Uvnfgm/pzYrJ75y3PV/J1wuAV1T5Dye5ygq4EAW20RoBq0ABQ==", "license": "MIT", + "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -16342,6 +16426,7 @@ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.24.0.tgz", "integrity": "sha512-SyoiGaDofiyGPFrUkn1oGsAzkRuX1JUvTD9YQQK3G1JGQ5VWkvHgYSsc1K9OrLsDQxN7NmV71O0sHCAh8cBetA==", "license": "MIT", + "peer": true, "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" @@ -16915,7 +17000,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -17086,7 +17170,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -18673,6 +18756,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -19100,7 +19196,6 @@ "version": "1.1.20", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", - "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", diff --git a/package.json b/package.json index a0fbda1..a42baca 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,6 @@ "typecheck:mobile": "npm run typecheck -w apps/mobile" }, "overrides": { - "react-test-renderer": "19.2.4" + "react-test-renderer": "19.1.0" } }