diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..7643c98
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,74 @@
+name: CI
+
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+
+# Cancel in-progress runs when a new commit is pushed
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20.x
+ cache: 'pnpm'
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Run type check
+ run: pnpm run typecheck
+
+ - name: Run tests with coverage
+ run: pnpm run test:coverage
+
+ - name: Upload coverage reports
+ uses: codecov/codecov-action@v4
+ with:
+ fail_ci_if_error: false
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+
+ build:
+ runs-on: ubuntu-latest
+ needs: test
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20.x
+ cache: 'pnpm'
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build
+ run: pnpm run build
+
+ - name: Verify build output exists
+ run: |
+ test -d lib/commonjs || (echo "lib/commonjs not found" && exit 1)
+ test -d lib/module || (echo "lib/module not found" && exit 1)
+ test -d lib/typescript || (echo "lib/typescript not found" && exit 1)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..808d63d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
+node_modules
+
+# Build output (top-level lib/ directory only, not src/lib/)
+/lib/
+
+# IDE
+.idea/
+.vscode/
+*.swp
+*.swo
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Test coverage
+coverage/
+
+# Logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Environment
+.env
+.env.local
+.env.*.local
diff --git a/README.md b/README.md
index b56c29d..ec64059 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,302 @@
-# sdk-react-native
+# @formo/react-native-analytics
+
+Formo Analytics SDK for React Native - Track wallet events and user analytics in mobile dApps.
+
+## Installation
+
+```bash
+npm install @formo/react-native-analytics @react-native-async-storage/async-storage
+
+# or with yarn
+yarn add @formo/react-native-analytics @react-native-async-storage/async-storage
+
+# or with pnpm
+pnpm add @formo/react-native-analytics @react-native-async-storage/async-storage
+```
+
+### iOS Setup
+
+```bash
+cd ios && pod install
+```
+
+## Quick Start
+
+### 1. Wrap your app with the provider
+
+```tsx
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import { FormoAnalyticsProvider } from '@formo/react-native-analytics';
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+### 2. Use the hook in your components
+
+```tsx
+import { useFormo } from '@formo/react-native-analytics';
+import { useEffect } from 'react';
+
+function HomeScreen() {
+ const formo = useFormo();
+
+ useEffect(() => {
+ // Track screen view
+ formo.screen('Home');
+ }, []);
+
+ const handleSignUp = () => {
+ // Track custom event
+ formo.track('Sign Up Button Pressed', {
+ screen: 'Home',
+ });
+ };
+
+ return ;
+}
+```
+
+## Wagmi Integration
+
+For dApps using Wagmi for wallet connections, you can enable automatic wallet event tracking:
+
+```tsx
+import { QueryClient } from '@tanstack/react-query';
+import { createConfig } from 'wagmi';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import { FormoAnalyticsProvider } from '@formo/react-native-analytics';
+
+const queryClient = new QueryClient();
+const wagmiConfig = createConfig({
+ // your wagmi config
+});
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+This automatically tracks:
+- Wallet connections and disconnections
+- Chain changes
+- Signature requests (with QueryClient)
+- Transaction events (with QueryClient)
+
+## API Reference
+
+### FormoAnalyticsProvider Props
+
+| Prop | Type | Required | Description |
+|------|------|----------|-------------|
+| `writeKey` | `string` | Yes | Your Formo write key |
+| `asyncStorage` | `AsyncStorageInterface` | Yes | AsyncStorage instance |
+| `options` | `Options` | No | Configuration options |
+| `disabled` | `boolean` | No | Disable analytics |
+
+### Options
+
+```typescript
+interface Options {
+ // Wagmi integration
+ wagmi?: {
+ config: any; // Wagmi config from createConfig()
+ queryClient?: any; // TanStack QueryClient for mutation tracking
+ };
+
+ // App information
+ app?: {
+ name?: string;
+ version?: string;
+ build?: string;
+ bundleId?: string;
+ };
+
+ // Event batching
+ flushAt?: number; // Batch size (default: 20)
+ flushInterval?: number; // Flush interval in ms (default: 30000)
+ retryCount?: number; // Retry count (default: 3)
+ maxQueueSize?: number; // Max queue size in bytes (default: 500KB)
+
+ // Autocapture control
+ autocapture?: boolean | {
+ connect?: boolean;
+ disconnect?: boolean;
+ signature?: boolean;
+ transaction?: boolean;
+ chain?: boolean;
+ };
+
+ // Tracking control
+ tracking?: boolean | {
+ excludeChains?: number[];
+ };
+
+ // Logging
+ logger?: {
+ enabled?: boolean;
+ levels?: ('debug' | 'info' | 'warn' | 'error' | 'log')[];
+ };
+
+ // Custom API host
+ apiHost?: string;
+
+ // Ready callback
+ ready?: (formo: IFormoAnalytics) => void;
+}
+```
+
+### useFormo Hook Methods
+
+#### `screen(name, properties?, context?, callback?)`
+Track a screen view.
+
+```typescript
+formo.screen('Profile', { userId: '123' });
+```
+
+#### `track(event, properties?, context?, callback?)`
+Track a custom event.
+
+```typescript
+formo.track('Purchase Completed', {
+ revenue: 99.99,
+ currency: 'USD',
+ productId: 'nft-001',
+});
+```
+
+#### `identify(params, properties?, context?, callback?)`
+Identify a user by their wallet address.
+
+```typescript
+formo.identify({
+ address: '0x1234...',
+ userId: 'user-123',
+ providerName: 'MetaMask',
+ rdns: 'io.metamask',
+});
+```
+
+#### `connect(params, properties?, context?, callback?)`
+Track wallet connection.
+
+```typescript
+formo.connect({
+ chainId: 1,
+ address: '0x1234...',
+});
+```
+
+#### `disconnect(params?, properties?, context?, callback?)`
+Track wallet disconnection.
+
+```typescript
+formo.disconnect({
+ chainId: 1,
+ address: '0x1234...',
+});
+```
+
+#### `chain(params, properties?, context?, callback?)`
+Track chain change.
+
+```typescript
+formo.chain({
+ chainId: 137,
+ address: '0x1234...',
+});
+```
+
+#### `signature(params, properties?, context?, callback?)`
+Track signature event.
+
+```typescript
+import { SignatureStatus } from '@formo/react-native-analytics';
+
+formo.signature({
+ status: SignatureStatus.CONFIRMED,
+ chainId: 1,
+ address: '0x1234...',
+ message: 'Sign this message',
+ signatureHash: '0xabcd...',
+});
+```
+
+#### `transaction(params, properties?, context?, callback?)`
+Track transaction event.
+
+```typescript
+import { TransactionStatus } from '@formo/react-native-analytics';
+
+formo.transaction({
+ status: TransactionStatus.BROADCASTED,
+ chainId: 1,
+ address: '0x1234...',
+ to: '0x5678...',
+ value: '1000000000000000000',
+ transactionHash: '0xdef...',
+});
+```
+
+#### Consent Management
+
+```typescript
+// Opt out of tracking (GDPR compliance)
+formo.optOutTracking();
+
+// Check opt-out status
+const isOptedOut = formo.hasOptedOutTracking();
+
+// Opt back in
+formo.optInTracking();
+```
+
+## Event Types
+
+The SDK automatically enriches events with mobile-specific context:
+
+- Device information (OS, version, model)
+- Screen dimensions and density
+- Locale and timezone
+- App information (if provided)
+- Anonymous ID (persistent across sessions)
+
+## Offline Support
+
+Events are queued locally and sent when the device has network connectivity. Events are automatically flushed when:
+
+- The batch size is reached (default: 20 events)
+- The flush interval passes (default: 30 seconds)
+- The app goes to background
+
+## License
+
+MIT
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..e390110
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,7 @@
+module.exports = {
+ presets: [
+ ['@babel/preset-env', { targets: { node: 'current' } }],
+ '@babel/preset-typescript',
+ ['@babel/preset-react', { runtime: 'automatic' }],
+ ],
+};
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..a10852f
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,30 @@
+/** @type {import('jest').Config} */
+module.exports = {
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
+ testMatch: ['**/__tests__/**/*.test.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
+ transform: {
+ '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
+ },
+ moduleNameMapper: {
+ '^@formo/react-native-analytics$': '/src/index',
+ },
+ setupFilesAfterEnv: ['/jest.setup.js'],
+ testEnvironment: 'node',
+ collectCoverageFrom: [
+ 'src/**/*.{ts,tsx}',
+ '!src/**/*.d.ts',
+ '!src/index.ts',
+ '!src/types/**/*',
+ ],
+ coverageThreshold: {
+ global: {
+ branches: 20,
+ functions: 30,
+ lines: 20,
+ statements: 20,
+ },
+ },
+ clearMocks: true,
+ resetMocks: true,
+ restoreMocks: true,
+};
diff --git a/jest.setup.js b/jest.setup.js
new file mode 100644
index 0000000..7a3cdfb
--- /dev/null
+++ b/jest.setup.js
@@ -0,0 +1,121 @@
+// Jest setup file for React Native SDK tests
+
+// Mock React Native modules
+jest.mock('react-native', () => ({
+ Platform: {
+ OS: 'ios',
+ Version: '17.0',
+ select: jest.fn((options) => options.ios),
+ },
+ Dimensions: {
+ get: jest.fn(() => ({ width: 375, height: 812, scale: 3 })),
+ },
+ AppState: {
+ currentState: 'active',
+ addEventListener: jest.fn(() => ({ remove: jest.fn() })),
+ },
+ NativeModules: {
+ RNDeviceInfo: {
+ deviceId: 'test-device-id',
+ model: 'iPhone 14',
+ systemName: 'iOS',
+ systemVersion: '17.0',
+ appVersion: '1.0.0',
+ buildNumber: '1',
+ bundleId: 'com.test.app',
+ isTablet: false,
+ getUniqueId: jest.fn().mockResolvedValue('test-unique-id'),
+ },
+ },
+}));
+
+// Mock react-native-device-info
+jest.mock('react-native-device-info', () => ({
+ getUniqueId: jest.fn().mockResolvedValue('test-device-id'),
+ getModel: jest.fn().mockReturnValue('iPhone 14'),
+ getSystemName: jest.fn().mockReturnValue('iOS'),
+ getSystemVersion: jest.fn().mockReturnValue('17.0'),
+ getVersion: jest.fn().mockReturnValue('1.0.0'),
+ getBuildNumber: jest.fn().mockReturnValue('1'),
+ getBundleId: jest.fn().mockReturnValue('com.test.app'),
+ isTablet: jest.fn().mockReturnValue(false),
+ getCarrier: jest.fn().mockResolvedValue('Test Carrier'),
+ getDeviceName: jest.fn().mockResolvedValue('Test Device'),
+ getManufacturer: jest.fn().mockResolvedValue('Apple'),
+ getBrand: jest.fn().mockReturnValue('Apple'),
+ getDeviceType: jest.fn().mockReturnValue('Handset'),
+ hasNotch: jest.fn().mockReturnValue(true),
+ getDeviceId: jest.fn().mockReturnValue('iPhone14,2'),
+ isEmulator: jest.fn().mockResolvedValue(false),
+ isLandscape: jest.fn().mockResolvedValue(false),
+ getApplicationName: jest.fn().mockReturnValue('Test App'),
+ getFirstInstallTime: jest.fn().mockResolvedValue(1704067200000),
+ getLastUpdateTime: jest.fn().mockResolvedValue(1704067200000),
+ getTotalMemory: jest.fn().mockResolvedValue(6000000000),
+ getUsedMemory: jest.fn().mockResolvedValue(2000000000),
+ getUserAgent: jest.fn().mockResolvedValue('Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)'),
+}));
+
+// Mock expo-device (optional peer dependency)
+jest.mock('expo-device', () => ({
+ deviceName: 'Test Device',
+ deviceYearClass: 2023,
+ isDevice: true,
+ brand: 'Apple',
+ manufacturer: 'Apple',
+ modelName: 'iPhone 14',
+ modelId: 'iPhone14,2',
+ osName: 'iOS',
+ osVersion: '17.0',
+ osBuildId: '21A5248v',
+ platformApiLevel: null,
+ deviceType: 1, // PHONE
+}), { virtual: true });
+
+// Mock expo-application (optional peer dependency)
+jest.mock('expo-application', () => ({
+ applicationName: 'Test App',
+ applicationId: 'com.test.app',
+ nativeApplicationVersion: '1.0.0',
+ nativeBuildVersion: '1',
+}), { virtual: true });
+
+// Mock @react-native-community/netinfo
+jest.mock('@react-native-community/netinfo', () => ({
+ fetch: jest.fn().mockResolvedValue({
+ type: 'wifi',
+ isConnected: true,
+ isInternetReachable: true,
+ details: {
+ ssid: 'TestNetwork',
+ },
+ }),
+ addEventListener: jest.fn(() => jest.fn()),
+}));
+
+// Mock @react-native-async-storage/async-storage
+jest.mock('@react-native-async-storage/async-storage', () => ({
+ setItem: jest.fn().mockResolvedValue(null),
+ getItem: jest.fn().mockResolvedValue(null),
+ removeItem: jest.fn().mockResolvedValue(null),
+ multiGet: jest.fn().mockResolvedValue([]),
+ multiSet: jest.fn().mockResolvedValue(null),
+ multiRemove: jest.fn().mockResolvedValue(null),
+ getAllKeys: jest.fn().mockResolvedValue([]),
+ clear: jest.fn().mockResolvedValue(null),
+}));
+
+// Global fetch mock
+global.fetch = jest.fn().mockResolvedValue({
+ ok: true,
+ json: jest.fn().mockResolvedValue({}),
+});
+
+// Silence console during tests (optional - comment out for debugging)
+// global.console = {
+// ...console,
+// log: jest.fn(),
+// info: jest.fn(),
+// warn: jest.fn(),
+// debug: jest.fn(),
+// };
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..8d12be5
--- /dev/null
+++ b/package.json
@@ -0,0 +1,123 @@
+{
+ "name": "@formo/react-native-analytics",
+ "version": "1.0.0",
+ "description": "Formo Analytics SDK for React Native - Track wallet events and user analytics in mobile dApps",
+ "packageManager": "pnpm@9.0.0",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/getformo/sdk.git",
+ "directory": "packages/formo-react-native-sdk"
+ },
+ "main": "lib/commonjs/index.js",
+ "module": "lib/module/index.js",
+ "types": "lib/typescript/index.d.ts",
+ "react-native": "src/index.ts",
+ "source": "src/index.ts",
+ "files": [
+ "src",
+ "lib",
+ "!**/__tests__",
+ "!**/__fixtures__",
+ "!**/__mocks__"
+ ],
+ "exports": {
+ ".": {
+ "import": "./lib/module/index.js",
+ "require": "./lib/commonjs/index.js",
+ "types": "./lib/typescript/index.d.ts"
+ }
+ },
+ "private": false,
+ "publishConfig": {
+ "access": "public",
+ "provenance": true
+ },
+ "author": "Formo ",
+ "license": "MIT",
+ "keywords": [
+ "react-native",
+ "analytics",
+ "crypto",
+ "web3",
+ "wallet",
+ "ethereum",
+ "wagmi",
+ "mobile",
+ "formo"
+ ],
+ "scripts": {
+ "build": "bob build",
+ "clean": "rm -rf lib",
+ "lint": "eslint '{src,test}/**/*.{ts,tsx}'",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:coverage": "jest --coverage",
+ "typecheck": "tsc --noEmit"
+ },
+ "peerDependencies": {
+ "@react-native-async-storage/async-storage": ">=1.17.0",
+ "@tanstack/react-query": ">=5.0.0",
+ "expo-application": ">=5.0.0",
+ "expo-device": ">=5.0.0",
+ "react": ">=18.0.0",
+ "react-native": ">=0.70.0",
+ "react-native-device-info": ">=10.0.0",
+ "wagmi": ">=2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": false
+ },
+ "@tanstack/react-query": {
+ "optional": true
+ },
+ "expo-application": {
+ "optional": true
+ },
+ "expo-device": {
+ "optional": true
+ },
+ "react-native-device-info": {
+ "optional": true
+ },
+ "wagmi": {
+ "optional": true
+ }
+ },
+ "dependencies": {
+ "@react-native-community/netinfo": "^11.5.1",
+ "ethereum-cryptography": "3.2.0"
+ },
+ "devDependencies": {
+ "@babel/preset-env": "^7.29.0",
+ "@babel/preset-react": "^7.28.5",
+ "@babel/preset-typescript": "^7.28.5",
+ "@react-native-async-storage/async-storage": "^1.21.0",
+ "@react-native/babel-preset": "^0.73.0",
+ "@types/jest": "^29.5.12",
+ "@types/react": "^18.0.25",
+ "babel-jest": "^29.7.0",
+ "expo-application": "^6.0.0",
+ "expo-device": "^7.0.0",
+ "jest": "^29.7.0",
+ "react": "^18.3.1",
+ "react-native": "^0.73.0",
+ "react-native-builder-bob": "^0.23.0",
+ "react-native-device-info": "^14.0.0",
+ "typescript": "^5.7.3"
+ },
+ "react-native-builder-bob": {
+ "source": "src",
+ "output": "lib",
+ "targets": [
+ "commonjs",
+ "module",
+ [
+ "typescript",
+ {
+ "project": "tsconfig.build.json"
+ }
+ ]
+ ]
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..bd46620
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,9185 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@react-native-community/netinfo':
+ specifier: ^11.5.1
+ version: 11.5.1(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ '@tanstack/react-query':
+ specifier: '>=5.0.0'
+ version: 5.90.20(react@18.3.1)
+ ethereum-cryptography:
+ specifier: 3.2.0
+ version: 3.2.0
+ wagmi:
+ specifier: '>=2.0.0'
+ version: 3.4.1(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@18.3.1))(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(viem@2.45.0(typescript@5.9.3))
+ devDependencies:
+ '@babel/preset-env':
+ specifier: ^7.29.0
+ version: 7.29.0(@babel/core@7.28.6)
+ '@babel/preset-react':
+ specifier: ^7.28.5
+ version: 7.28.5(@babel/core@7.28.6)
+ '@babel/preset-typescript':
+ specifier: ^7.28.5
+ version: 7.28.5(@babel/core@7.28.6)
+ '@react-native-async-storage/async-storage':
+ specifier: ^1.21.0
+ version: 1.24.0(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ '@react-native/babel-preset':
+ specifier: ^0.73.0
+ version: 0.73.21(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ '@types/jest':
+ specifier: ^29.5.12
+ version: 29.5.14
+ '@types/react':
+ specifier: ^18.0.25
+ version: 18.3.27
+ babel-jest:
+ specifier: ^29.7.0
+ version: 29.7.0(@babel/core@7.28.6)
+ expo-application:
+ specifier: ^6.0.0
+ version: 6.1.5(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))
+ expo-device:
+ specifier: ^7.0.0
+ version: 7.1.4(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))
+ jest:
+ specifier: ^29.7.0
+ version: 29.7.0(@types/node@25.1.0)
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-native:
+ specifier: ^0.73.0
+ version: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+ react-native-builder-bob:
+ specifier: ^0.23.0
+ version: 0.23.2
+ react-native-device-info:
+ specifier: ^14.0.0
+ version: 14.1.1(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+
+packages:
+
+ '@0no-co/graphql.web@1.2.0':
+ resolution: {integrity: sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==}
+ peerDependencies:
+ graphql: ^14.0.0 || ^15.0.0 || ^16.0.0
+ peerDependenciesMeta:
+ graphql:
+ optional: true
+
+ '@adraffy/ens-normalize@1.11.1':
+ resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==}
+
+ '@babel/code-frame@7.10.4':
+ resolution: {integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==}
+
+ '@babel/code-frame@7.28.6':
+ resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/code-frame@7.29.0':
+ resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.28.6':
+ resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.29.0':
+ resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.28.6':
+ resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.28.6':
+ resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.29.0':
+ resolution: {integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-annotate-as-pure@7.27.3':
+ resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.28.6':
+ resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-create-class-features-plugin@7.28.6':
+ resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-create-regexp-features-plugin@7.28.5':
+ resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-define-polyfill-provider@0.6.6':
+ resolution: {integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ '@babel/helper-environment-visitor@7.24.7':
+ resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-member-expression-to-functions@7.28.5':
+ resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.28.6':
+ resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.28.6':
+ resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-optimise-call-expression@7.27.1':
+ resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-plugin-utils@7.28.6':
+ resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-remap-async-to-generator@7.27.1':
+ resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-replace-supers@7.28.6':
+ resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.28.5':
+ resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-wrap-function@7.28.6':
+ resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.28.6':
+ resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/highlight@7.25.9':
+ resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.28.6':
+ resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/parser@7.29.0':
+ resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5':
+ resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1':
+ resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1':
+ resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1':
+ resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.13.0
+
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6':
+ resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-proposal-async-generator-functions@7.20.7':
+ resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-class-properties@7.18.6':
+ resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-decorators@7.29.0':
+ resolution: {integrity: sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-export-default-from@7.27.1':
+ resolution: {integrity: sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6':
+ resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-numeric-separator@7.18.6':
+ resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-object-rest-spread@7.20.7':
+ resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-optional-catch-binding@7.18.6':
+ resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-optional-chaining@7.21.0':
+ resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==}
+ engines: {node: '>=6.9.0'}
+ deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2':
+ resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-async-generators@7.8.4':
+ resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-bigint@7.8.3':
+ resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-class-properties@7.12.13':
+ resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-class-static-block@7.14.5':
+ resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-decorators@7.28.6':
+ resolution: {integrity: sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-dynamic-import@7.8.3':
+ resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-export-default-from@7.28.6':
+ resolution: {integrity: sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-flow@7.28.6':
+ resolution: {integrity: sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-assertions@7.28.6':
+ resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-attributes@7.28.6':
+ resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-meta@7.10.4':
+ resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-json-strings@7.8.3':
+ resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-jsx@7.28.6':
+ resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-logical-assignment-operators@7.10.4':
+ resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3':
+ resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-numeric-separator@7.10.4':
+ resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-object-rest-spread@7.8.3':
+ resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-optional-catch-binding@7.8.3':
+ resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-optional-chaining@7.8.3':
+ resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-private-property-in-object@7.14.5':
+ resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-top-level-await@7.14.5':
+ resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-typescript@7.28.6':
+ resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-unicode-sets-regex@7.18.6':
+ resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-arrow-functions@7.27.1':
+ resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-async-generator-functions@7.28.6':
+ resolution: {integrity: sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-async-generator-functions@7.29.0':
+ resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-async-to-generator@7.28.6':
+ resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-block-scoped-functions@7.27.1':
+ resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-block-scoping@7.28.6':
+ resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-class-properties@7.28.6':
+ resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-class-static-block@7.28.6':
+ resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.12.0
+
+ '@babel/plugin-transform-classes@7.28.6':
+ resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-computed-properties@7.28.6':
+ resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-destructuring@7.28.5':
+ resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-dotall-regex@7.28.6':
+ resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-duplicate-keys@7.27.1':
+ resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0':
+ resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-dynamic-import@7.27.1':
+ resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-explicit-resource-management@7.28.6':
+ resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-exponentiation-operator@7.28.6':
+ resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-export-namespace-from@7.27.1':
+ resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-flow-strip-types@7.27.1':
+ resolution: {integrity: sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-for-of@7.27.1':
+ resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-function-name@7.27.1':
+ resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-json-strings@7.28.6':
+ resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-literals@7.27.1':
+ resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-logical-assignment-operators@7.28.6':
+ resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-member-expression-literals@7.27.1':
+ resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-amd@7.27.1':
+ resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-commonjs@7.28.6':
+ resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-systemjs@7.29.0':
+ resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-umd@7.27.1':
+ resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-named-capturing-groups-regex@7.27.1':
+ resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-named-capturing-groups-regex@7.29.0':
+ resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-new-target@7.27.1':
+ resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-nullish-coalescing-operator@7.28.6':
+ resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-numeric-separator@7.28.6':
+ resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-object-rest-spread@7.28.6':
+ resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-object-super@7.27.1':
+ resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-optional-catch-binding@7.28.6':
+ resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-optional-chaining@7.28.6':
+ resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-parameters@7.27.7':
+ resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-private-methods@7.28.6':
+ resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-private-property-in-object@7.28.6':
+ resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-property-literals@7.27.1':
+ resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-display-name@7.28.0':
+ resolution: {integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-development@7.27.1':
+ resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1':
+ resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1':
+ resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx@7.28.6':
+ resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-pure-annotations@7.27.1':
+ resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-regenerator@7.28.6':
+ resolution: {integrity: sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-regenerator@7.29.0':
+ resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-regexp-modifiers@7.28.6':
+ resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-reserved-words@7.27.1':
+ resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-runtime@7.28.5':
+ resolution: {integrity: sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-shorthand-properties@7.27.1':
+ resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-spread@7.28.6':
+ resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-sticky-regex@7.27.1':
+ resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-template-literals@7.27.1':
+ resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-typeof-symbol@7.27.1':
+ resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-typescript@7.28.6':
+ resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-escapes@7.27.1':
+ resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-property-regex@7.28.6':
+ resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-regex@7.27.1':
+ resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-sets-regex@7.28.6':
+ resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/preset-env@7.29.0':
+ resolution: {integrity: sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/preset-flow@7.27.1':
+ resolution: {integrity: sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/preset-modules@0.1.6-no-external-plugins':
+ resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
+
+ '@babel/preset-react@7.28.5':
+ resolution: {integrity: sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/preset-typescript@7.28.5':
+ resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/register@7.28.6':
+ resolution: {integrity: sha512-pgcbbEl/dWQYb6L6Yew6F94rdwygfuv+vJ/tXfwIOYAfPB6TNWpXUMEtEq3YuTeHRdvMIhvz13bkT9CNaS+wqA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.28.6':
+ resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.28.6':
+ resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.28.6':
+ resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.29.0':
+ resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.28.6':
+ resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.29.0':
+ resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
+ engines: {node: '>=6.9.0'}
+
+ '@bcoe/v8-coverage@0.2.3':
+ resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+
+ '@expo/cli@54.0.23':
+ resolution: {integrity: sha512-km0h72SFfQCmVycH/JtPFTVy69w6Lx1cHNDmfLfQqgKFYeeHTjx7LVDP4POHCtNxFP2UeRazrygJhlh4zz498g==}
+ hasBin: true
+ peerDependencies:
+ expo: '*'
+ expo-router: '*'
+ react-native: '*'
+ peerDependenciesMeta:
+ expo-router:
+ optional: true
+ react-native:
+ optional: true
+
+ '@expo/code-signing-certificates@0.0.6':
+ resolution: {integrity: sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w==}
+
+ '@expo/config-plugins@54.0.4':
+ resolution: {integrity: sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q==}
+
+ '@expo/config-types@54.0.10':
+ resolution: {integrity: sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA==}
+
+ '@expo/config@12.0.13':
+ resolution: {integrity: sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ==}
+
+ '@expo/devcert@1.2.1':
+ resolution: {integrity: sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==}
+
+ '@expo/devtools@0.1.8':
+ resolution: {integrity: sha512-SVLxbuanDjJPgc0sy3EfXUMLb/tXzp6XIHkhtPVmTWJAp+FOr6+5SeiCfJrCzZFet0Ifyke2vX3sFcKwEvCXwQ==}
+ peerDependencies:
+ react: '*'
+ react-native: '*'
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-native:
+ optional: true
+
+ '@expo/env@2.0.8':
+ resolution: {integrity: sha512-5VQD6GT8HIMRaSaB5JFtOXuvfDVU80YtZIuUT/GDhUF782usIXY13Tn3IdDz1Tm/lqA9qnRZQ1BF4t7LlvdJPA==}
+
+ '@expo/fingerprint@0.15.4':
+ resolution: {integrity: sha512-eYlxcrGdR2/j2M6pEDXo9zU9KXXF1vhP+V+Tl+lyY+bU8lnzrN6c637mz6Ye3em2ANy8hhUR03Raf8VsT9Ogng==}
+ hasBin: true
+
+ '@expo/image-utils@0.8.8':
+ resolution: {integrity: sha512-HHHaG4J4nKjTtVa1GG9PCh763xlETScfEyNxxOvfTRr8IKPJckjTyqSLEtdJoFNJ1vqiABEjW7tqGhqGibZLeA==}
+
+ '@expo/json-file@10.0.8':
+ resolution: {integrity: sha512-9LOTh1PgKizD1VXfGQ88LtDH0lRwq9lsTb4aichWTWSWqy3Ugfkhfm3BhzBIkJJfQQ5iJu3m/BoRlEIjoCGcnQ==}
+
+ '@expo/metro-config@54.0.14':
+ resolution: {integrity: sha512-hxpLyDfOR4L23tJ9W1IbJJsG7k4lv2sotohBm/kTYyiG+pe1SYCAWsRmgk+H42o/wWf/HQjE5k45S5TomGLxNA==}
+ peerDependencies:
+ expo: '*'
+ peerDependenciesMeta:
+ expo:
+ optional: true
+
+ '@expo/metro@54.2.0':
+ resolution: {integrity: sha512-h68TNZPGsk6swMmLm9nRSnE2UXm48rWwgcbtAHVMikXvbxdS41NDHHeqg1rcQ9AbznDRp6SQVC2MVpDnsRKU1w==}
+
+ '@expo/osascript@2.3.8':
+ resolution: {integrity: sha512-/TuOZvSG7Nn0I8c+FcEaoHeBO07yu6vwDgk7rZVvAXoeAK5rkA09jRyjYsZo+0tMEFaToBeywA6pj50Mb3ny9w==}
+ engines: {node: '>=12'}
+
+ '@expo/package-manager@1.9.10':
+ resolution: {integrity: sha512-axJm+NOj3jVxep49va/+L3KkF3YW/dkV+RwzqUJedZrv4LeTqOG4rhrCaCPXHTvLqCTDKu6j0Xyd28N7mnxsGA==}
+
+ '@expo/plist@0.4.8':
+ resolution: {integrity: sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ==}
+
+ '@expo/prebuild-config@54.0.8':
+ resolution: {integrity: sha512-EA7N4dloty2t5Rde+HP0IEE+nkAQiu4A/+QGZGT9mFnZ5KKjPPkqSyYcRvP5bhQE10D+tvz6X0ngZpulbMdbsg==}
+ peerDependencies:
+ expo: '*'
+
+ '@expo/schema-utils@0.1.8':
+ resolution: {integrity: sha512-9I6ZqvnAvKKDiO+ZF8BpQQFYWXOJvTAL5L/227RUbWG1OVZDInFifzCBiqAZ3b67NRfeAgpgvbA7rejsqhY62A==}
+
+ '@expo/sdk-runtime-versions@1.0.0':
+ resolution: {integrity: sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==}
+
+ '@expo/spawn-async@1.7.2':
+ resolution: {integrity: sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==}
+ engines: {node: '>=12'}
+
+ '@expo/sudo-prompt@9.3.2':
+ resolution: {integrity: sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==}
+
+ '@expo/vector-icons@15.0.3':
+ resolution: {integrity: sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==}
+ peerDependencies:
+ expo-font: '>=14.0.4'
+ react: '*'
+ react-native: '*'
+
+ '@expo/ws-tunnel@1.0.6':
+ resolution: {integrity: sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q==}
+
+ '@expo/xcpretty@4.4.0':
+ resolution: {integrity: sha512-o2qDlTqJ606h4xR36H2zWTywmZ3v3842K6TU8Ik2n1mfW0S580VHlt3eItVYdLYz+klaPp7CXqanja8eASZjRw==}
+ hasBin: true
+
+ '@hapi/hoek@9.3.0':
+ resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
+
+ '@hapi/topo@5.1.0':
+ resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
+
+ '@isaacs/balanced-match@4.0.1':
+ resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/brace-expansion@5.0.1':
+ resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/fs-minipass@4.0.1':
+ resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+ engines: {node: '>=18.0.0'}
+
+ '@isaacs/ttlcache@1.4.1':
+ resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==}
+ engines: {node: '>=12'}
+
+ '@istanbuljs/load-nyc-config@1.1.0':
+ resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
+ engines: {node: '>=8'}
+
+ '@istanbuljs/schema@0.1.3':
+ resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+ engines: {node: '>=8'}
+
+ '@jest/console@29.7.0':
+ resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/core@29.7.0':
+ resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ '@jest/create-cache-key-function@29.7.0':
+ resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/environment@29.7.0':
+ resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/expect-utils@29.7.0':
+ resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/expect@29.7.0':
+ resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/fake-timers@29.7.0':
+ resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/globals@29.7.0':
+ resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/reporters@29.7.0':
+ resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ '@jest/schemas@29.6.3':
+ resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/source-map@29.6.3':
+ resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/test-result@29.7.0':
+ resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/test-sequencer@29.7.0':
+ resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/transform@29.7.0':
+ resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jest/types@26.6.2':
+ resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==}
+ engines: {node: '>= 10.14.2'}
+
+ '@jest/types@29.6.3':
+ resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/source-map@0.3.11':
+ resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@noble/ciphers@1.3.0':
+ resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@noble/curves@1.9.0':
+ resolution: {integrity: sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@noble/curves@1.9.1':
+ resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@noble/hashes@1.8.0':
+ resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@react-native-async-storage/async-storage@1.24.0':
+ resolution: {integrity: sha512-W4/vbwUOYOjco0x3toB8QCr7EjIP6nE9G7o8PMguvvjYT5Awg09lyV4enACRx4s++PPulBiBSjL0KTFx2u0Z/g==}
+ peerDependencies:
+ react-native: ^0.0.0-0 || >=0.60 <1.0
+
+ '@react-native-community/cli-clean@12.3.7':
+ resolution: {integrity: sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ==}
+
+ '@react-native-community/cli-config@12.3.7':
+ resolution: {integrity: sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw==}
+
+ '@react-native-community/cli-debugger-ui@12.3.7':
+ resolution: {integrity: sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q==}
+
+ '@react-native-community/cli-doctor@12.3.7':
+ resolution: {integrity: sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg==}
+
+ '@react-native-community/cli-hermes@12.3.7':
+ resolution: {integrity: sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg==}
+
+ '@react-native-community/cli-platform-android@12.3.7':
+ resolution: {integrity: sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ==}
+
+ '@react-native-community/cli-platform-ios@12.3.7':
+ resolution: {integrity: sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow==}
+
+ '@react-native-community/cli-plugin-metro@12.3.7':
+ resolution: {integrity: sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg==}
+
+ '@react-native-community/cli-server-api@12.3.7':
+ resolution: {integrity: sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg==}
+
+ '@react-native-community/cli-tools@12.3.7':
+ resolution: {integrity: sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw==}
+
+ '@react-native-community/cli-types@12.3.7':
+ resolution: {integrity: sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w==}
+
+ '@react-native-community/cli@12.3.7':
+ resolution: {integrity: sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ '@react-native-community/netinfo@11.5.1':
+ resolution: {integrity: sha512-ZiLvVoNW6fIOZqU99Jdm+dfwv2T76AHifKtEDydPQOkzKg/xLIkSrOEMUigkmlNQu4MeCgFJlrapscbRzU+bKg==}
+ peerDependencies:
+ react: '*'
+ react-native: '>=0.59'
+
+ '@react-native/assets-registry@0.73.1':
+ resolution: {integrity: sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==}
+ engines: {node: '>=18'}
+
+ '@react-native/babel-plugin-codegen@0.73.4':
+ resolution: {integrity: sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==}
+ engines: {node: '>=18'}
+
+ '@react-native/babel-plugin-codegen@0.81.5':
+ resolution: {integrity: sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==}
+ engines: {node: '>= 20.19.4'}
+
+ '@react-native/babel-preset@0.73.21':
+ resolution: {integrity: sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@babel/core': '*'
+
+ '@react-native/babel-preset@0.81.5':
+ resolution: {integrity: sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==}
+ engines: {node: '>= 20.19.4'}
+ peerDependencies:
+ '@babel/core': '*'
+
+ '@react-native/codegen@0.73.3':
+ resolution: {integrity: sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@babel/preset-env': ^7.1.6
+
+ '@react-native/codegen@0.81.5':
+ resolution: {integrity: sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==}
+ engines: {node: '>= 20.19.4'}
+ peerDependencies:
+ '@babel/core': '*'
+
+ '@react-native/community-cli-plugin@0.73.18':
+ resolution: {integrity: sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww==}
+ engines: {node: '>=18'}
+
+ '@react-native/debugger-frontend@0.73.3':
+ resolution: {integrity: sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==}
+ engines: {node: '>=18'}
+
+ '@react-native/debugger-frontend@0.81.5':
+ resolution: {integrity: sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==}
+ engines: {node: '>= 20.19.4'}
+
+ '@react-native/dev-middleware@0.73.8':
+ resolution: {integrity: sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==}
+ engines: {node: '>=18'}
+
+ '@react-native/dev-middleware@0.81.5':
+ resolution: {integrity: sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==}
+ engines: {node: '>= 20.19.4'}
+
+ '@react-native/gradle-plugin@0.73.5':
+ resolution: {integrity: sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA==}
+ engines: {node: '>=18'}
+
+ '@react-native/js-polyfills@0.73.1':
+ resolution: {integrity: sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==}
+ engines: {node: '>=18'}
+
+ '@react-native/metro-babel-transformer@0.73.15':
+ resolution: {integrity: sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@babel/core': '*'
+
+ '@react-native/normalize-colors@0.73.2':
+ resolution: {integrity: sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==}
+
+ '@react-native/normalize-colors@0.81.5':
+ resolution: {integrity: sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==}
+
+ '@react-native/virtualized-lists@0.73.4':
+ resolution: {integrity: sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ react-native: '*'
+
+ '@scure/base@1.2.6':
+ resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==}
+
+ '@scure/bip32@1.7.0':
+ resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==}
+
+ '@scure/bip39@1.6.0':
+ resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==}
+
+ '@sideway/address@4.1.5':
+ resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==}
+
+ '@sideway/formula@3.0.1':
+ resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==}
+
+ '@sideway/pinpoint@2.0.0':
+ resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
+
+ '@sinclair/typebox@0.27.8':
+ resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
+
+ '@sinonjs/commons@3.0.1':
+ resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==}
+
+ '@sinonjs/fake-timers@10.3.0':
+ resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==}
+
+ '@tanstack/query-core@5.90.20':
+ resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==}
+
+ '@tanstack/react-query@5.90.20':
+ resolution: {integrity: sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==}
+ peerDependencies:
+ react: ^18 || ^19
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
+ '@types/graceful-fs@4.1.9':
+ resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
+
+ '@types/istanbul-lib-coverage@2.0.6':
+ resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
+
+ '@types/istanbul-lib-report@3.0.3':
+ resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
+
+ '@types/istanbul-reports@3.0.4':
+ resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
+
+ '@types/jest@29.5.14':
+ resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==}
+
+ '@types/node@25.1.0':
+ resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==}
+
+ '@types/parse-json@4.0.2':
+ resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
+
+ '@types/prop-types@15.7.15':
+ resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
+
+ '@types/react@18.3.27':
+ resolution: {integrity: sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==}
+
+ '@types/stack-utils@2.0.3':
+ resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
+
+ '@types/yargs-parser@21.0.3':
+ resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
+
+ '@types/yargs@15.0.20':
+ resolution: {integrity: sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg==}
+
+ '@types/yargs@17.0.35':
+ resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==}
+
+ '@ungap/structured-clone@1.3.0':
+ resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+
+ '@urql/core@5.2.0':
+ resolution: {integrity: sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A==}
+
+ '@urql/exchange-retry@1.3.2':
+ resolution: {integrity: sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg==}
+ peerDependencies:
+ '@urql/core': ^5.0.0
+
+ '@wagmi/connectors@7.1.5':
+ resolution: {integrity: sha512-+hrb4RJywjGtUsDZNLSc4eOF+jD6pVkCZ/KFi24p993u0ymsm/kGTLXjhYx5r8Rf/cxFHEiaQaRnEfB9qyDJyw==}
+ peerDependencies:
+ '@base-org/account': ^2.5.1
+ '@coinbase/wallet-sdk': ^4.3.6
+ '@gemini-wallet/core': ~0.3.1
+ '@metamask/sdk': ~0.33.1
+ '@safe-global/safe-apps-provider': ~0.18.6
+ '@safe-global/safe-apps-sdk': ^9.1.0
+ '@wagmi/core': 3.3.1
+ '@walletconnect/ethereum-provider': ^2.21.1
+ porto: ~0.2.35
+ typescript: '>=5.7.3'
+ viem: 2.x
+ peerDependenciesMeta:
+ '@base-org/account':
+ optional: true
+ '@coinbase/wallet-sdk':
+ optional: true
+ '@gemini-wallet/core':
+ optional: true
+ '@metamask/sdk':
+ optional: true
+ '@safe-global/safe-apps-provider':
+ optional: true
+ '@safe-global/safe-apps-sdk':
+ optional: true
+ '@walletconnect/ethereum-provider':
+ optional: true
+ porto:
+ optional: true
+ typescript:
+ optional: true
+
+ '@wagmi/core@3.3.1':
+ resolution: {integrity: sha512-0Q8VYnVNPHe/gZsvj+Zddt8VpmKoMHXoVd887svL21QGKXEIVYiV/8R3qMv0SyC7q+GbQ5x9xezB56u3S8bWAQ==}
+ peerDependencies:
+ '@tanstack/query-core': '>=5.0.0'
+ ox: '>=0.11.1'
+ typescript: '>=5.7.3'
+ viem: 2.x
+ peerDependenciesMeta:
+ '@tanstack/query-core':
+ optional: true
+ ox:
+ optional: true
+ typescript:
+ optional: true
+
+ '@xmldom/xmldom@0.8.11':
+ resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
+ engines: {node: '>=10.0.0'}
+
+ abitype@1.2.3:
+ resolution: {integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==}
+ peerDependencies:
+ typescript: '>=5.0.4'
+ zod: ^3.22.0 || ^4.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ zod:
+ optional: true
+
+ abort-controller@3.0.0:
+ resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
+ engines: {node: '>=6.5'}
+
+ accepts@1.3.8:
+ resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+ engines: {node: '>= 0.6'}
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ aggregate-error@3.1.0:
+ resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
+ engines: {node: '>=8'}
+
+ anser@1.4.10:
+ resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==}
+
+ ansi-escapes@4.3.2:
+ resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+ engines: {node: '>=8'}
+
+ ansi-fragments@0.2.1:
+ resolution: {integrity: sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==}
+
+ ansi-regex@4.1.1:
+ resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
+ engines: {node: '>=6'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ appdirsjs@1.2.7:
+ resolution: {integrity: sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==}
+
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+
+ asap@2.0.6:
+ resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
+
+ ast-types@0.15.2:
+ resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==}
+ engines: {node: '>=4'}
+
+ astral-regex@1.0.0:
+ resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==}
+ engines: {node: '>=4'}
+
+ async-limiter@1.0.1:
+ resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==}
+
+ babel-core@7.0.0-bridge.0:
+ resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ babel-jest@29.7.0:
+ resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ peerDependencies:
+ '@babel/core': ^7.8.0
+
+ babel-plugin-istanbul@6.1.1:
+ resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==}
+ engines: {node: '>=8'}
+
+ babel-plugin-jest-hoist@29.6.3:
+ resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ babel-plugin-polyfill-corejs2@0.4.15:
+ resolution: {integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-polyfill-corejs3@0.13.0:
+ resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-polyfill-corejs3@0.14.0:
+ resolution: {integrity: sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-polyfill-regenerator@0.6.6:
+ resolution: {integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-react-compiler@1.0.0:
+ resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==}
+
+ babel-plugin-react-native-web@0.21.2:
+ resolution: {integrity: sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==}
+
+ babel-plugin-syntax-hermes-parser@0.29.1:
+ resolution: {integrity: sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==}
+
+ babel-plugin-transform-flow-enums@0.0.2:
+ resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==}
+
+ babel-preset-current-node-syntax@1.2.0:
+ resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0 || ^8.0.0-0
+
+ babel-preset-expo@54.0.10:
+ resolution: {integrity: sha512-wTt7POavLFypLcPW/uC5v8y+mtQKDJiyGLzYCjqr9tx0Qc3vCXcDKk1iCFIj/++Iy5CWhhTflEa7VvVPNWeCfw==}
+ peerDependencies:
+ '@babel/runtime': ^7.20.0
+ expo: '*'
+ react-refresh: '>=0.14.0 <1.0.0'
+ peerDependenciesMeta:
+ '@babel/runtime':
+ optional: true
+ expo:
+ optional: true
+
+ babel-preset-jest@29.6.3:
+ resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ baseline-browser-mapping@2.9.19:
+ resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==}
+ hasBin: true
+
+ better-opn@3.0.2:
+ resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
+ engines: {node: '>=12.0.0'}
+
+ big-integer@1.6.52:
+ resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
+ engines: {node: '>=0.6'}
+
+ bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+ bplist-creator@0.1.0:
+ resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==}
+
+ bplist-parser@0.3.1:
+ resolution: {integrity: sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==}
+ engines: {node: '>= 5.10.0'}
+
+ bplist-parser@0.3.2:
+ resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==}
+ engines: {node: '>= 5.10.0'}
+
+ brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
+
+ brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.28.1:
+ resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ bser@2.1.1:
+ resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
+
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+ bytes@3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+
+ caller-callsite@2.0.0:
+ resolution: {integrity: sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==}
+ engines: {node: '>=4'}
+
+ caller-path@2.0.0:
+ resolution: {integrity: sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==}
+ engines: {node: '>=4'}
+
+ callsites@2.0.0:
+ resolution: {integrity: sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==}
+ engines: {node: '>=4'}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+
+ camelcase@5.3.1:
+ resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+ engines: {node: '>=6'}
+
+ camelcase@6.3.0:
+ resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+ engines: {node: '>=10'}
+
+ caniuse-lite@1.0.30001766:
+ resolution: {integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==}
+
+ chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ char-regex@1.0.2:
+ resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
+ engines: {node: '>=10'}
+
+ chownr@3.0.0:
+ resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+ engines: {node: '>=18'}
+
+ chrome-launcher@0.15.2:
+ resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==}
+ engines: {node: '>=12.13.0'}
+ hasBin: true
+
+ chromium-edge-launcher@0.2.0:
+ resolution: {integrity: sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==}
+
+ chromium-edge-launcher@1.0.0:
+ resolution: {integrity: sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==}
+
+ ci-info@2.0.0:
+ resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==}
+
+ ci-info@3.9.0:
+ resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
+ engines: {node: '>=8'}
+
+ cjs-module-lexer@1.4.3:
+ resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==}
+
+ clean-stack@2.2.0:
+ resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
+ engines: {node: '>=6'}
+
+ cli-cursor@2.1.0:
+ resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==}
+ engines: {node: '>=4'}
+
+ cli-cursor@3.1.0:
+ resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
+ engines: {node: '>=8'}
+
+ cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+
+ cliui@6.0.0:
+ resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
+
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
+ clone-deep@4.0.1:
+ resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
+ engines: {node: '>=6'}
+
+ clone@1.0.4:
+ resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
+ engines: {node: '>=0.8'}
+
+ co@4.6.0:
+ resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
+ engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
+
+ collect-v8-coverage@1.0.3:
+ resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==}
+
+ color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ colorette@1.4.0:
+ resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
+
+ command-exists@1.2.9:
+ resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==}
+
+ commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+
+ commander@9.5.0:
+ resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
+ engines: {node: ^12.20.0 || >=14}
+
+ commondir@1.0.1:
+ resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+
+ compressible@2.0.18:
+ resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
+ engines: {node: '>= 0.6'}
+
+ compression@1.8.1:
+ resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==}
+ engines: {node: '>= 0.8.0'}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ connect@3.7.0:
+ resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==}
+ engines: {node: '>= 0.10.0'}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ core-js-compat@3.48.0:
+ resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==}
+
+ core-util-is@1.0.3:
+ resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
+
+ cosmiconfig@5.2.1:
+ resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==}
+ engines: {node: '>=4'}
+
+ cosmiconfig@7.1.0:
+ resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
+ engines: {node: '>=10'}
+
+ create-jest@29.7.0:
+ resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ hasBin: true
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ crypto-random-string@2.0.0:
+ resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
+ engines: {node: '>=8'}
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ dayjs@1.11.19:
+ resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==}
+
+ debug@2.6.9:
+ resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decamelize@1.2.0:
+ resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+ engines: {node: '>=0.10.0'}
+
+ dedent@0.7.0:
+ resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
+
+ dedent@1.7.1:
+ resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==}
+ peerDependencies:
+ babel-plugin-macros: ^3.1.0
+ peerDependenciesMeta:
+ babel-plugin-macros:
+ optional: true
+
+ deep-extend@0.6.0:
+ resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+ engines: {node: '>=4.0.0'}
+
+ deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+
+ defaults@1.0.4:
+ resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+
+ define-lazy-prop@2.0.0:
+ resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
+ engines: {node: '>=8'}
+
+ del@6.1.1:
+ resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==}
+ engines: {node: '>=10'}
+
+ denodeify@1.2.1:
+ resolution: {integrity: sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==}
+
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
+ deprecated-react-native-prop-types@5.0.0:
+ resolution: {integrity: sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==}
+ engines: {node: '>=18'}
+
+ destroy@1.2.0:
+ resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
+ engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ detect-newline@3.1.0:
+ resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
+ engines: {node: '>=8'}
+
+ diff-sequences@29.6.3:
+ resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+
+ dotenv-expand@11.0.7:
+ resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==}
+ engines: {node: '>=12'}
+
+ dotenv@16.4.7:
+ resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
+ engines: {node: '>=12'}
+
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
+ electron-to-chromium@1.5.279:
+ resolution: {integrity: sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==}
+
+ emittery@0.13.1:
+ resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
+ engines: {node: '>=12'}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ encodeurl@1.0.2:
+ resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+ engines: {node: '>= 0.8'}
+
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
+ end-of-stream@1.4.5:
+ resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
+ env-editor@0.4.2:
+ resolution: {integrity: sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==}
+ engines: {node: '>=8'}
+
+ envinfo@7.21.0:
+ resolution: {integrity: sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ error-ex@1.3.4:
+ resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
+
+ error-stack-parser@2.1.4:
+ resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==}
+
+ errorhandler@1.5.2:
+ resolution: {integrity: sha512-kNAL7hESndBCrWwS72QyV3IVOTrVmj9D062FV5BQswNL5zEdeRmz/WJFyh6Aj/plvvSOrzddkxW57HgkZcR9Fw==}
+ engines: {node: '>= 0.8'}
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+ escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+
+ escape-string-regexp@2.0.0:
+ resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
+ engines: {node: '>=8'}
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ ethereum-cryptography@3.2.0:
+ resolution: {integrity: sha512-Urr5YVsalH+Jo0sYkTkv1MyI9bLYZwW8BENZCeE1QYaTHETEYx0Nv/SVsWkSqpYrzweg6d8KMY1wTjH/1m/BIg==}
+ engines: {node: ^14.21.3 || >=16, npm: '>=9'}
+
+ event-target-shim@5.0.1:
+ resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
+ engines: {node: '>=6'}
+
+ eventemitter3@5.0.1:
+ resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
+
+ exec-async@2.2.0:
+ resolution: {integrity: sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw==}
+
+ execa@4.1.0:
+ resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
+ engines: {node: '>=10'}
+
+ execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+
+ exit@0.1.2:
+ resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==}
+ engines: {node: '>= 0.8.0'}
+
+ expect@29.7.0:
+ resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ expo-application@6.1.5:
+ resolution: {integrity: sha512-ToImFmzw8luY043pWFJhh2ZMm4IwxXoHXxNoGdlhD4Ym6+CCmkAvCglg0FK8dMLzAb+/XabmOE7Rbm8KZb6NZg==}
+ peerDependencies:
+ expo: '*'
+
+ expo-asset@12.0.12:
+ resolution: {integrity: sha512-CsXFCQbx2fElSMn0lyTdRIyKlSXOal6ilLJd+yeZ6xaC7I9AICQgscY5nj0QcwgA+KYYCCEQEBndMsmj7drOWQ==}
+ peerDependencies:
+ expo: '*'
+ react: '*'
+ react-native: '*'
+
+ expo-constants@18.0.13:
+ resolution: {integrity: sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==}
+ peerDependencies:
+ expo: '*'
+ react-native: '*'
+
+ expo-device@7.1.4:
+ resolution: {integrity: sha512-HS04IiE1Fy0FRjBLurr9e5A6yj3kbmQB+2jCZvbSGpsjBnCLdSk/LCii4f5VFhPIBWJLyYuN5QqJyEAw6BcS4Q==}
+ peerDependencies:
+ expo: '*'
+
+ expo-file-system@19.0.21:
+ resolution: {integrity: sha512-s3DlrDdiscBHtab/6W1osrjGL+C2bvoInPJD7sOwmxfJ5Woynv2oc+Fz1/xVXaE/V7HE/+xrHC/H45tu6lZzzg==}
+ peerDependencies:
+ expo: '*'
+ react-native: '*'
+
+ expo-font@14.0.11:
+ resolution: {integrity: sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==}
+ peerDependencies:
+ expo: '*'
+ react: '*'
+ react-native: '*'
+
+ expo-keep-awake@15.0.8:
+ resolution: {integrity: sha512-YK9M1VrnoH1vLJiQzChZgzDvVimVoriibiDIFLbQMpjYBnvyfUeHJcin/Gx1a+XgupNXy92EQJLgI/9ZuXajYQ==}
+ peerDependencies:
+ expo: '*'
+ react: '*'
+
+ expo-modules-autolinking@3.0.24:
+ resolution: {integrity: sha512-TP+6HTwhL7orDvsz2VzauyQlXJcAWyU3ANsZ7JGL4DQu8XaZv/A41ZchbtAYLfozNA2Ya1Hzmhx65hXryBMjaQ==}
+ hasBin: true
+
+ expo-modules-core@3.0.29:
+ resolution: {integrity: sha512-LzipcjGqk8gvkrOUf7O2mejNWugPkf3lmd9GkqL9WuNyeN2fRwU0Dn77e3ZUKI3k6sI+DNwjkq4Nu9fNN9WS7Q==}
+ peerDependencies:
+ react: '*'
+ react-native: '*'
+
+ expo-server@1.0.5:
+ resolution: {integrity: sha512-IGR++flYH70rhLyeXF0Phle56/k4cee87WeQ4mamS+MkVAVP+dDlOHf2nN06Z9Y2KhU0Gp1k+y61KkghF7HdhA==}
+ engines: {node: '>=20.16.0'}
+
+ expo@54.0.33:
+ resolution: {integrity: sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==}
+ hasBin: true
+ peerDependencies:
+ '@expo/dom-webview': '*'
+ '@expo/metro-runtime': '*'
+ react: '*'
+ react-native: '*'
+ react-native-webview: '*'
+ peerDependenciesMeta:
+ '@expo/dom-webview':
+ optional: true
+ '@expo/metro-runtime':
+ optional: true
+ react-native-webview:
+ optional: true
+
+ exponential-backoff@3.1.3:
+ resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fast-xml-parser@4.5.3:
+ resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==}
+ hasBin: true
+
+ fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+ fb-watchman@2.0.2:
+ resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ finalhandler@1.1.2:
+ resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==}
+ engines: {node: '>= 0.8'}
+
+ find-cache-dir@2.1.0:
+ resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==}
+ engines: {node: '>=6'}
+
+ find-up@3.0.0:
+ resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
+ engines: {node: '>=6'}
+
+ find-up@4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
+ flow-enums-runtime@0.0.6:
+ resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==}
+
+ flow-parser@0.206.0:
+ resolution: {integrity: sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==}
+ engines: {node: '>=0.4.0'}
+
+ fontfaceobserver@2.3.0:
+ resolution: {integrity: sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==}
+
+ freeport-async@2.0.0:
+ resolution: {integrity: sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==}
+ engines: {node: '>=8'}
+
+ fresh@0.5.2:
+ resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
+ engines: {node: '>= 0.6'}
+
+ fs-extra@10.1.0:
+ resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+ engines: {node: '>=12'}
+
+ fs-extra@8.1.0:
+ resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
+ engines: {node: '>=6 <7 || >=8'}
+
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
+ get-package-type@0.1.0:
+ resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
+ engines: {node: '>=8.0.0'}
+
+ get-stream@5.2.0:
+ resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
+ engines: {node: '>=8'}
+
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
+ getenv@2.0.0:
+ resolution: {integrity: sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==}
+ engines: {node: '>=6'}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob@13.0.1:
+ resolution: {integrity: sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==}
+ engines: {node: 20 || >=22}
+
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Glob versions prior to v9 are no longer supported
+
+ glob@8.1.0:
+ resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
+ engines: {node: '>=12'}
+ deprecated: Glob versions prior to v9 are no longer supported
+
+ global-dirs@0.1.1:
+ resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==}
+ engines: {node: '>=4'}
+
+ globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ hermes-estree@0.15.0:
+ resolution: {integrity: sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==}
+
+ hermes-estree@0.23.1:
+ resolution: {integrity: sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==}
+
+ hermes-estree@0.29.1:
+ resolution: {integrity: sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==}
+
+ hermes-estree@0.32.0:
+ resolution: {integrity: sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==}
+
+ hermes-parser@0.15.0:
+ resolution: {integrity: sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==}
+
+ hermes-parser@0.23.1:
+ resolution: {integrity: sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==}
+
+ hermes-parser@0.29.1:
+ resolution: {integrity: sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==}
+
+ hermes-parser@0.32.0:
+ resolution: {integrity: sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==}
+
+ hermes-profile-transformer@0.0.6:
+ resolution: {integrity: sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==}
+ engines: {node: '>=8'}
+
+ hosted-git-info@7.0.2:
+ resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
+ engines: {node: ^16.14.0 || >=18.0.0}
+
+ html-escaper@2.0.2:
+ resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
+ http-errors@2.0.1:
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
+ engines: {node: '>= 0.8'}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ human-signals@1.1.1:
+ resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==}
+ engines: {node: '>=8.12.0'}
+
+ human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ image-size@1.2.1:
+ resolution: {integrity: sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==}
+ engines: {node: '>=16.x'}
+ hasBin: true
+
+ import-fresh@2.0.0:
+ resolution: {integrity: sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==}
+ engines: {node: '>=4'}
+
+ import-fresh@3.3.1:
+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+ engines: {node: '>=6'}
+
+ import-local@3.2.0:
+ resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+
+ indent-string@4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ini@1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+
+ invariant@2.2.4:
+ resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
+
+ is-absolute@1.0.0:
+ resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==}
+ engines: {node: '>=0.10.0'}
+
+ is-arrayish@0.2.1:
+ resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+
+ is-core-module@2.16.1:
+ resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
+ engines: {node: '>= 0.4'}
+
+ is-directory@0.3.1:
+ resolution: {integrity: sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==}
+ engines: {node: '>=0.10.0'}
+
+ is-docker@2.2.1:
+ resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@2.0.0:
+ resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==}
+ engines: {node: '>=4'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-generator-fn@2.1.0:
+ resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==}
+ engines: {node: '>=6'}
+
+ is-git-dirty@2.0.2:
+ resolution: {integrity: sha512-U3YCo+GKR/rDsY7r0v/LBICbQwsx859tDQnAT+v0E/zCDeWbQ1TUt1FtyExeyik7VIJlYOLHCIifLdz71HDalg==}
+ engines: {node: '>=10'}
+
+ is-git-repository@2.0.0:
+ resolution: {integrity: sha512-HDO50CG5suIAcmqG4F1buqVXEZRPn+RaXIn9pFKq/947FBo2bCRwK7ZluEVZOy99a4IQyqsjbKEpAiOXCccOHQ==}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-interactive@1.0.0:
+ resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
+ engines: {node: '>=8'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-path-cwd@2.2.0:
+ resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
+ engines: {node: '>=6'}
+
+ is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+
+ is-plain-obj@2.1.0:
+ resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
+ engines: {node: '>=8'}
+
+ is-plain-object@2.0.4:
+ resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
+ engines: {node: '>=0.10.0'}
+
+ is-relative@1.0.0:
+ resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==}
+ engines: {node: '>=0.10.0'}
+
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
+ is-unc-path@1.0.0:
+ resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-unicode-supported@0.1.0:
+ resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
+ engines: {node: '>=10'}
+
+ is-windows@1.0.2:
+ resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
+ engines: {node: '>=0.10.0'}
+
+ is-wsl@1.1.0:
+ resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==}
+ engines: {node: '>=4'}
+
+ is-wsl@2.2.0:
+ resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
+ engines: {node: '>=8'}
+
+ isarray@1.0.0:
+ resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ isobject@3.0.1:
+ resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
+ engines: {node: '>=0.10.0'}
+
+ isows@1.0.7:
+ resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==}
+ peerDependencies:
+ ws: '*'
+
+ istanbul-lib-coverage@3.2.2:
+ resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+ engines: {node: '>=8'}
+
+ istanbul-lib-instrument@5.2.1:
+ resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==}
+ engines: {node: '>=8'}
+
+ istanbul-lib-instrument@6.0.3:
+ resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-report@3.0.1:
+ resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-source-maps@4.0.1:
+ resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
+ engines: {node: '>=10'}
+
+ istanbul-reports@3.2.0:
+ resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
+ engines: {node: '>=8'}
+
+ jest-changed-files@29.7.0:
+ resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-circus@29.7.0:
+ resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-cli@29.7.0:
+ resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ hasBin: true
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ jest-config@29.7.0:
+ resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ peerDependencies:
+ '@types/node': '*'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ ts-node:
+ optional: true
+
+ jest-diff@29.7.0:
+ resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-docblock@29.7.0:
+ resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-each@29.7.0:
+ resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-environment-node@29.7.0:
+ resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-get-type@29.6.3:
+ resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-haste-map@29.7.0:
+ resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-leak-detector@29.7.0:
+ resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-matcher-utils@29.7.0:
+ resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-message-util@29.7.0:
+ resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-mock@29.7.0:
+ resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-pnp-resolver@1.2.3:
+ resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
+ engines: {node: '>=6'}
+ peerDependencies:
+ jest-resolve: '*'
+ peerDependenciesMeta:
+ jest-resolve:
+ optional: true
+
+ jest-regex-util@29.6.3:
+ resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-resolve-dependencies@29.7.0:
+ resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-resolve@29.7.0:
+ resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-runner@29.7.0:
+ resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-runtime@29.7.0:
+ resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-snapshot@29.7.0:
+ resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-util@29.7.0:
+ resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-validate@29.7.0:
+ resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-watcher@29.7.0:
+ resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest-worker@29.7.0:
+ resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ jest@29.7.0:
+ resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ hasBin: true
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ jimp-compact@0.16.1:
+ resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==}
+
+ joi@17.13.3:
+ resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ js-yaml@3.14.2:
+ resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==}
+ hasBin: true
+
+ js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+
+ jsc-android@250231.0.0:
+ resolution: {integrity: sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==}
+
+ jsc-safe-url@0.2.4:
+ resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==}
+
+ jscodeshift@0.14.0:
+ resolution: {integrity: sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==}
+ hasBin: true
+ peerDependencies:
+ '@babel/preset-env': ^7.1.6
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json-parse-better-errors@1.0.2:
+ resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
+
+ json-parse-even-better-errors@2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsonfile@4.0.0:
+ resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+
+ jsonfile@6.2.0:
+ resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
+
+ kind-of@6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+
+ kleur@3.0.3:
+ resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+ engines: {node: '>=6'}
+
+ kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+
+ lan-network@0.1.7:
+ resolution: {integrity: sha512-mnIlAEMu4OyEvUNdzco9xpuB9YVcPkQec+QsgycBCtPZvEqWPCDPfbAE4OJMdBBWpZWtpCn1xw9jJYlwjWI5zQ==}
+ hasBin: true
+
+ leven@3.1.0:
+ resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+ engines: {node: '>=6'}
+
+ lighthouse-logger@1.4.2:
+ resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==}
+
+ lightningcss-android-arm64@1.31.1:
+ resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.31.1:
+ resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.31.1:
+ resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.31.1:
+ resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.31.1:
+ resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.31.1:
+ resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-arm64-musl@1.31.1:
+ resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-x64-gnu@1.31.1:
+ resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-linux-x64-musl@1.31.1:
+ resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.31.1:
+ resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.31.1:
+ resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.31.1:
+ resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
+ engines: {node: '>= 12.0.0'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ locate-path@3.0.0:
+ resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
+ engines: {node: '>=6'}
+
+ locate-path@5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
+ lodash.debounce@4.0.8:
+ resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
+
+ lodash.throttle@4.1.1:
+ resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
+
+ log-symbols@2.2.0:
+ resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==}
+ engines: {node: '>=4'}
+
+ log-symbols@4.1.0:
+ resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
+ engines: {node: '>=10'}
+
+ logkitty@0.7.1:
+ resolution: {integrity: sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==}
+ hasBin: true
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ lru-cache@11.2.5:
+ resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==}
+ engines: {node: 20 || >=22}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ make-dir@2.1.0:
+ resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
+ engines: {node: '>=6'}
+
+ make-dir@4.0.0:
+ resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+ engines: {node: '>=10'}
+
+ makeerror@1.0.12:
+ resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
+
+ marky@1.3.0:
+ resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==}
+
+ memoize-one@5.2.1:
+ resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
+
+ merge-options@3.0.4:
+ resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==}
+ engines: {node: '>=10'}
+
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ metro-babel-transformer@0.80.12:
+ resolution: {integrity: sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg==}
+ engines: {node: '>=18'}
+
+ metro-babel-transformer@0.83.3:
+ resolution: {integrity: sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==}
+ engines: {node: '>=20.19.4'}
+
+ metro-cache-key@0.80.12:
+ resolution: {integrity: sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA==}
+ engines: {node: '>=18'}
+
+ metro-cache-key@0.83.3:
+ resolution: {integrity: sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==}
+ engines: {node: '>=20.19.4'}
+
+ metro-cache@0.80.12:
+ resolution: {integrity: sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA==}
+ engines: {node: '>=18'}
+
+ metro-cache@0.83.3:
+ resolution: {integrity: sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==}
+ engines: {node: '>=20.19.4'}
+
+ metro-config@0.80.12:
+ resolution: {integrity: sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ==}
+ engines: {node: '>=18'}
+
+ metro-config@0.83.3:
+ resolution: {integrity: sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==}
+ engines: {node: '>=20.19.4'}
+
+ metro-core@0.80.12:
+ resolution: {integrity: sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw==}
+ engines: {node: '>=18'}
+
+ metro-core@0.83.3:
+ resolution: {integrity: sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==}
+ engines: {node: '>=20.19.4'}
+
+ metro-file-map@0.80.12:
+ resolution: {integrity: sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw==}
+ engines: {node: '>=18'}
+
+ metro-file-map@0.83.3:
+ resolution: {integrity: sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==}
+ engines: {node: '>=20.19.4'}
+
+ metro-minify-terser@0.80.12:
+ resolution: {integrity: sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ==}
+ engines: {node: '>=18'}
+
+ metro-minify-terser@0.83.3:
+ resolution: {integrity: sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==}
+ engines: {node: '>=20.19.4'}
+
+ metro-resolver@0.80.12:
+ resolution: {integrity: sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw==}
+ engines: {node: '>=18'}
+
+ metro-resolver@0.83.3:
+ resolution: {integrity: sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==}
+ engines: {node: '>=20.19.4'}
+
+ metro-runtime@0.80.12:
+ resolution: {integrity: sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw==}
+ engines: {node: '>=18'}
+
+ metro-runtime@0.83.3:
+ resolution: {integrity: sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw==}
+ engines: {node: '>=20.19.4'}
+
+ metro-source-map@0.80.12:
+ resolution: {integrity: sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw==}
+ engines: {node: '>=18'}
+
+ metro-source-map@0.83.3:
+ resolution: {integrity: sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg==}
+ engines: {node: '>=20.19.4'}
+
+ metro-symbolicate@0.80.12:
+ resolution: {integrity: sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ metro-symbolicate@0.83.3:
+ resolution: {integrity: sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==}
+ engines: {node: '>=20.19.4'}
+ hasBin: true
+
+ metro-transform-plugins@0.80.12:
+ resolution: {integrity: sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA==}
+ engines: {node: '>=18'}
+
+ metro-transform-plugins@0.83.3:
+ resolution: {integrity: sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==}
+ engines: {node: '>=20.19.4'}
+
+ metro-transform-worker@0.80.12:
+ resolution: {integrity: sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA==}
+ engines: {node: '>=18'}
+
+ metro-transform-worker@0.83.3:
+ resolution: {integrity: sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==}
+ engines: {node: '>=20.19.4'}
+
+ metro@0.80.12:
+ resolution: {integrity: sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ metro@0.83.3:
+ resolution: {integrity: sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==}
+ engines: {node: '>=20.19.4'}
+ hasBin: true
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ mime@1.6.0:
+ resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ mime@2.6.0:
+ resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
+ engines: {node: '>=4.0.0'}
+ hasBin: true
+
+ mimic-fn@1.2.0:
+ resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==}
+ engines: {node: '>=4'}
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
+ minimatch@10.1.2:
+ resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==}
+ engines: {node: 20 || >=22}
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minizlib@3.1.0:
+ resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
+ engines: {node: '>= 18'}
+
+ mipd@0.0.7:
+ resolution: {integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==}
+ peerDependencies:
+ typescript: '>=5.0.4'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ mkdirp@0.5.6:
+ resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+ hasBin: true
+
+ mkdirp@1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ ms@2.0.0:
+ resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+ negotiator@0.6.3:
+ resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+ engines: {node: '>= 0.6'}
+
+ negotiator@0.6.4:
+ resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
+ engines: {node: '>= 0.6'}
+
+ neo-async@2.6.2:
+ resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+
+ nested-error-stacks@2.0.1:
+ resolution: {integrity: sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==}
+
+ nocache@3.0.4:
+ resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==}
+ engines: {node: '>=12.0.0'}
+
+ node-abort-controller@3.1.1:
+ resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
+
+ node-dir@0.1.17:
+ resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==}
+ engines: {node: '>= 0.10.5'}
+
+ node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
+ node-forge@1.3.3:
+ resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==}
+ engines: {node: '>= 6.13.0'}
+
+ node-int64@0.4.0:
+ resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
+
+ node-releases@2.0.27:
+ resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+
+ node-stream-zip@1.15.0:
+ resolution: {integrity: sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==}
+ engines: {node: '>=0.12.0'}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ npm-package-arg@11.0.3:
+ resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==}
+ engines: {node: ^16.14.0 || >=18.0.0}
+
+ npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+
+ nullthrows@1.1.1:
+ resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==}
+
+ ob1@0.80.12:
+ resolution: {integrity: sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw==}
+ engines: {node: '>=18'}
+
+ ob1@0.83.3:
+ resolution: {integrity: sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA==}
+ engines: {node: '>=20.19.4'}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ on-finished@2.3.0:
+ resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
+ engines: {node: '>= 0.8'}
+
+ on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+
+ on-headers@1.1.0:
+ resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==}
+ engines: {node: '>= 0.8'}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ onetime@2.0.1:
+ resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==}
+ engines: {node: '>=4'}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
+ open@6.4.0:
+ resolution: {integrity: sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==}
+ engines: {node: '>=8'}
+
+ open@7.4.2:
+ resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==}
+ engines: {node: '>=8'}
+
+ open@8.4.2:
+ resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
+ engines: {node: '>=12'}
+
+ ora@3.4.0:
+ resolution: {integrity: sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==}
+ engines: {node: '>=6'}
+
+ ora@5.4.1:
+ resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
+ engines: {node: '>=10'}
+
+ ox@0.11.3:
+ resolution: {integrity: sha512-1bWYGk/xZel3xro3l8WGg6eq4YEKlaqvyMtVhfMFpbJzK2F6rj4EDRtqDCWVEJMkzcmEi9uW2QxsqELokOlarw==}
+ peerDependencies:
+ typescript: '>=5.4.0'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
+ p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+
+ p-locate@3.0.0:
+ resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
+ engines: {node: '>=6'}
+
+ p-locate@4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+
+ p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+
+ p-map@4.0.0:
+ resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
+ engines: {node: '>=10'}
+
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
+ parse-json@4.0.0:
+ resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==}
+ engines: {node: '>=4'}
+
+ parse-json@5.2.0:
+ resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+ engines: {node: '>=8'}
+
+ parse-png@2.1.0:
+ resolution: {integrity: sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==}
+ engines: {node: '>=10'}
+
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
+ path-exists@3.0.0:
+ resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
+ engines: {node: '>=4'}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ path-scurry@2.0.1:
+ resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
+ engines: {node: 20 || >=22}
+
+ path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@3.0.1:
+ resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==}
+ engines: {node: '>=10'}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pify@4.0.1:
+ resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
+ engines: {node: '>=6'}
+
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
+ pkg-dir@3.0.0:
+ resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==}
+ engines: {node: '>=6'}
+
+ pkg-dir@4.2.0:
+ resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
+ engines: {node: '>=8'}
+
+ plist@3.1.0:
+ resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
+ engines: {node: '>=10.4.0'}
+
+ pngjs@3.4.0:
+ resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==}
+ engines: {node: '>=4.0.0'}
+
+ postcss@8.4.49:
+ resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ pretty-bytes@5.6.0:
+ resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
+ engines: {node: '>=6'}
+
+ pretty-format@26.6.2:
+ resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==}
+ engines: {node: '>= 10'}
+
+ pretty-format@29.7.0:
+ resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ proc-log@4.2.0:
+ resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ process-nextick-args@2.0.1:
+ resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+
+ progress@2.0.3:
+ resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+ engines: {node: '>=0.4.0'}
+
+ promise@8.3.0:
+ resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==}
+
+ prompts@2.4.2:
+ resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+ engines: {node: '>= 6'}
+
+ prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+
+ pump@3.0.3:
+ resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ pure-rand@6.1.0:
+ resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
+
+ qrcode-terminal@0.11.0:
+ resolution: {integrity: sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==}
+ hasBin: true
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ queue@6.0.2:
+ resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==}
+
+ range-parser@1.2.1:
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+ engines: {node: '>= 0.6'}
+
+ rc@1.2.8:
+ resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+ hasBin: true
+
+ react-devtools-core@4.28.5:
+ resolution: {integrity: sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==}
+
+ react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+
+ react-is@17.0.2:
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+
+ react-is@18.3.1:
+ resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+
+ react-native-builder-bob@0.23.2:
+ resolution: {integrity: sha512-ehv2XKS9cvPR5JR7FIpSx3qY7tULkljT2Kb82FBAxXsFLjqlRU1WfqHRLh6lytL2XqAxLQODpPfHUH53SsXnag==}
+ engines: {node: '>= 18.0.0'}
+ hasBin: true
+
+ react-native-device-info@14.1.1:
+ resolution: {integrity: sha512-lXFpe6DJmzbQXNLWxlMHP2xuTU5gwrKAvI8dCAZuERhW9eOXSubOQIesk9lIBnsi9pI19GMrcpJEvs4ARPRYmw==}
+ peerDependencies:
+ react-native: '*'
+
+ react-native@0.73.11:
+ resolution: {integrity: sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg==}
+ engines: {node: '>=18'}
+ hasBin: true
+ peerDependencies:
+ react: 18.2.0
+
+ react-refresh@0.14.2:
+ resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
+ engines: {node: '>=0.10.0'}
+
+ react-shallow-renderer@16.15.0:
+ resolution: {integrity: sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==}
+ peerDependencies:
+ react: ^16.0.0 || ^17.0.0 || ^18.0.0
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ readable-stream@2.3.8:
+ resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
+ readline@1.3.0:
+ resolution: {integrity: sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==}
+
+ recast@0.21.5:
+ resolution: {integrity: sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==}
+ engines: {node: '>= 4'}
+
+ regenerate-unicode-properties@10.2.2:
+ resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==}
+ engines: {node: '>=4'}
+
+ regenerate@1.4.2:
+ resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
+
+ regenerator-runtime@0.13.11:
+ resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
+
+ regexpu-core@6.4.0:
+ resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==}
+ engines: {node: '>=4'}
+
+ regjsgen@0.8.0:
+ resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==}
+
+ regjsparser@0.13.0:
+ resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==}
+ hasBin: true
+
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
+ require-main-filename@2.0.0:
+ resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
+
+ requireg@0.2.2:
+ resolution: {integrity: sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==}
+ engines: {node: '>= 4.0.0'}
+
+ resolve-cwd@3.0.0:
+ resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
+ engines: {node: '>=8'}
+
+ resolve-from@3.0.0:
+ resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==}
+ engines: {node: '>=4'}
+
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+
+ resolve-global@1.0.0:
+ resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==}
+ engines: {node: '>=8'}
+
+ resolve-workspace-root@2.0.1:
+ resolution: {integrity: sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==}
+
+ resolve.exports@2.0.3:
+ resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==}
+ engines: {node: '>=10'}
+
+ resolve@1.22.11:
+ resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
+ resolve@1.7.1:
+ resolution: {integrity: sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==}
+
+ restore-cursor@2.0.0:
+ resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==}
+ engines: {node: '>=4'}
+
+ restore-cursor@3.1.0:
+ resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
+ engines: {node: '>=8'}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rimraf@2.6.3:
+ resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==}
+ deprecated: Rimraf versions prior to v4 are no longer supported
+ hasBin: true
+
+ rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ deprecated: Rimraf versions prior to v4 are no longer supported
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safe-buffer@5.1.2:
+ resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ sax@1.4.4:
+ resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==}
+ engines: {node: '>=11.0.0'}
+
+ scheduler@0.24.0-canary-efb381bbf-20230505:
+ resolution: {integrity: sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==}
+
+ semver@5.7.2:
+ resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
+ hasBin: true
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ send@0.19.2:
+ resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
+ engines: {node: '>= 0.8.0'}
+
+ serialize-error@2.1.0:
+ resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==}
+ engines: {node: '>=0.10.0'}
+
+ serve-static@1.16.3:
+ resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
+ engines: {node: '>= 0.8.0'}
+
+ set-blocking@2.0.0:
+ resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
+ shallow-clone@3.0.1:
+ resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
+ engines: {node: '>=8'}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ shell-quote@1.8.3:
+ resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
+ engines: {node: '>= 0.4'}
+
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ simple-plist@1.3.1:
+ resolution: {integrity: sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==}
+
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+ slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+
+ slice-ansi@2.1.0:
+ resolution: {integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==}
+ engines: {node: '>=6'}
+
+ slugify@1.6.6:
+ resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==}
+ engines: {node: '>=8.0.0'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ source-map-support@0.5.13:
+ resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
+
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.5.7:
+ resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.7.6:
+ resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
+ engines: {node: '>= 12'}
+
+ sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
+ stack-utils@2.0.6:
+ resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
+ engines: {node: '>=10'}
+
+ stackframe@1.3.4:
+ resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==}
+
+ stacktrace-parser@0.1.11:
+ resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==}
+ engines: {node: '>=6'}
+
+ statuses@1.5.0:
+ resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==}
+ engines: {node: '>= 0.6'}
+
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
+ stream-buffers@2.2.0:
+ resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==}
+ engines: {node: '>= 0.10.0'}
+
+ string-length@4.0.2:
+ resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
+ engines: {node: '>=10'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string_decoder@1.1.1:
+ resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
+
+ string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+ strip-ansi@5.2.0:
+ resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==}
+ engines: {node: '>=6'}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-bom@4.0.0:
+ resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
+ engines: {node: '>=8'}
+
+ strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+
+ strip-json-comments@2.0.1:
+ resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+ engines: {node: '>=0.10.0'}
+
+ strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+
+ strnum@1.1.2:
+ resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==}
+
+ structured-headers@0.4.1:
+ resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==}
+
+ sucrase@3.35.1:
+ resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
+ sudo-prompt@9.2.1:
+ resolution: {integrity: sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==}
+ deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+
+ supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+
+ supports-hyperlinks@2.3.0:
+ resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==}
+ engines: {node: '>=8'}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ tar@7.5.7:
+ resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==}
+ engines: {node: '>=18'}
+
+ temp-dir@2.0.0:
+ resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
+ engines: {node: '>=8'}
+
+ temp@0.8.4:
+ resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==}
+ engines: {node: '>=6.0.0'}
+
+ terminal-link@2.1.1:
+ resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==}
+ engines: {node: '>=8'}
+
+ terser@5.46.0:
+ resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ test-exclude@6.0.0:
+ resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
+ engines: {node: '>=8'}
+
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
+ throat@5.0.0:
+ resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==}
+
+ through2@2.0.5:
+ resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ tmpl@1.0.5:
+ resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
+ tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ type-detect@4.0.8:
+ resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+ engines: {node: '>=4'}
+
+ type-fest@0.21.3:
+ resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+ engines: {node: '>=10'}
+
+ type-fest@0.7.1:
+ resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==}
+ engines: {node: '>=8'}
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ ua-parser-js@0.7.41:
+ resolution: {integrity: sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==}
+ hasBin: true
+
+ unc-path-regex@0.1.2:
+ resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==}
+ engines: {node: '>=0.10.0'}
+
+ undici-types@7.16.0:
+ resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
+
+ undici@6.23.0:
+ resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==}
+ engines: {node: '>=18.17'}
+
+ unicode-canonical-property-names-ecmascript@2.0.1:
+ resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
+ engines: {node: '>=4'}
+
+ unicode-match-property-ecmascript@2.0.0:
+ resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==}
+ engines: {node: '>=4'}
+
+ unicode-match-property-value-ecmascript@2.2.1:
+ resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==}
+ engines: {node: '>=4'}
+
+ unicode-property-aliases-ecmascript@2.2.0:
+ resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==}
+ engines: {node: '>=4'}
+
+ unique-string@2.0.0:
+ resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
+ engines: {node: '>=8'}
+
+ universalify@0.1.2:
+ resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
+ engines: {node: '>= 4.0.0'}
+
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
+ update-browserslist-db@1.2.3:
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ use-sync-external-store@1.4.0:
+ resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ utils-merge@1.0.1:
+ resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
+ engines: {node: '>= 0.4.0'}
+
+ uuid@7.0.3:
+ resolution: {integrity: sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==}
+ hasBin: true
+
+ v8-to-istanbul@9.3.0:
+ resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
+ engines: {node: '>=10.12.0'}
+
+ validate-npm-package-name@5.0.1:
+ resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
+ viem@2.45.0:
+ resolution: {integrity: sha512-iVA9qrAgRdtpWa80lCZ6Jri6XzmLOwwA1wagX2HnKejKeliFLpON0KOdyfqvcy+gUpBVP59LBxP2aKiL3aj8fg==}
+ peerDependencies:
+ typescript: '>=5.0.4'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ vlq@1.0.1:
+ resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==}
+
+ wagmi@3.4.1:
+ resolution: {integrity: sha512-v6svxWxfIqV82lXNclOMn+h0SYCtXtxf0HWCwyjIJPZH1SR7yRqyQguWUDQtzvNSefFQEoCk+MVOX9nTR5d4Zw==}
+ peerDependencies:
+ '@tanstack/react-query': '>=5.0.0'
+ react: '>=18'
+ typescript: '>=5.7.3'
+ viem: 2.x
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ walker@1.0.8:
+ resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
+
+ wcwidth@1.0.1:
+ resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ webidl-conversions@5.0.0:
+ resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==}
+ engines: {node: '>=8'}
+
+ whatwg-fetch@3.6.20:
+ resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==}
+
+ whatwg-url-without-unicode@8.0.0-3:
+ resolution: {integrity: sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==}
+ engines: {node: '>=10'}
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
+ which-module@2.0.1:
+ resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ wonka@6.3.5:
+ resolution: {integrity: sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw==}
+
+ wrap-ansi@6.2.0:
+ resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+ engines: {node: '>=8'}
+
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ write-file-atomic@2.4.3:
+ resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==}
+
+ write-file-atomic@4.0.2:
+ resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
+ engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+
+ ws@6.2.3:
+ resolution: {integrity: sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: ^5.0.2
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ ws@7.5.10:
+ resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==}
+ engines: {node: '>=8.3.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: ^5.0.2
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ ws@8.18.3:
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xcode@3.0.1:
+ resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==}
+ engines: {node: '>=10.0.0'}
+
+ xml2js@0.6.0:
+ resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==}
+ engines: {node: '>=4.0.0'}
+
+ xmlbuilder@11.0.1:
+ resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
+ engines: {node: '>=4.0'}
+
+ xmlbuilder@15.1.1:
+ resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
+ engines: {node: '>=8.0'}
+
+ xtend@4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
+
+ y18n@4.0.3:
+ resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yallist@5.0.0:
+ resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+ engines: {node: '>=18'}
+
+ yaml@1.10.2:
+ resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
+ engines: {node: '>= 6'}
+
+ yaml@2.8.2:
+ resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
+ yargs-parser@18.1.3:
+ resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
+ engines: {node: '>=6'}
+
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@15.4.1:
+ resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
+ engines: {node: '>=8'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
+ yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+
+ zustand@5.0.0:
+ resolution: {integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==}
+ engines: {node: '>=12.20.0'}
+ peerDependencies:
+ '@types/react': '>=18.0.0'
+ immer: '>=9.0.6'
+ react: '>=18.0.0'
+ use-sync-external-store: '>=1.2.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ use-sync-external-store:
+ optional: true
+
+snapshots:
+
+ '@0no-co/graphql.web@1.2.0': {}
+
+ '@adraffy/ens-normalize@1.11.1': {}
+
+ '@babel/code-frame@7.10.4':
+ dependencies:
+ '@babel/highlight': 7.25.9
+
+ '@babel/code-frame@7.28.6':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/code-frame@7.29.0':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.28.6': {}
+
+ '@babel/compat-data@7.29.0': {}
+
+ '@babel/core@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helpers': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.28.6':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/generator@7.29.0':
+ dependencies:
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-annotate-as-pure@7.27.3':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@babel/helper-compilation-targets@7.28.6':
+ dependencies:
+ '@babel/compat-data': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.28.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-member-expression-to-functions': 7.28.5
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/traverse': 7.28.6
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ regexpu-core: 6.4.0
+ semver: 6.3.1
+
+ '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ debug: 4.4.3
+ lodash.debounce: 4.0.8
+ resolve: 1.22.11
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-environment-visitor@7.24.7':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@babel/helper-globals@7.28.0': {}
+
+ '@babel/helper-member-expression-to-functions@7.28.5':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-imports@7.28.6':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-optimise-call-expression@7.27.1':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@babel/helper-plugin-utils@7.28.6': {}
+
+ '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-wrap-function': 7.28.6
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-replace-supers@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-member-expression-to-functions': 7.28.5
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.28.5': {}
+
+ '@babel/helper-validator-option@7.27.1': {}
+
+ '@babel/helper-wrap-function@7.28.6':
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helpers@7.28.6':
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+
+ '@babel/highlight@7.25.9':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/parser@7.28.6':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@babel/parser@7.29.0':
+ dependencies:
+ '@babel/types': 7.29.0
+
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-environment-visitor': 7.24.7
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-proposal-decorators@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-decorators': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-proposal-export-default-from@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6)
+
+ '@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6)
+
+ '@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/compat-data': 7.28.6
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+
+ '@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6)
+
+ '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+
+ '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-decorators@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-export-default-from@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-flow@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-async-generator-functions@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6)
+ '@babel/traverse': 7.29.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-classes@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-globals': 7.28.0
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/template': 7.28.6
+
+ '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6)
+
+ '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.29.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-runtime@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.28.6)
+ babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.6)
+ babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.28.6)
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-spread@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6)
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/preset-env@7.29.0(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/compat-data': 7.29.0
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.28.6)
+ '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.6)
+ babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.28.6)
+ babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.28.6)
+ babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.28.6)
+ core-js-compat: 3.48.0
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/preset-flow@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6)
+
+ '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/types': 7.28.6
+ esutils: 2.0.3
+
+ '@babel/preset-react@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/preset-typescript@7.28.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/register@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ clone-deep: 4.0.1
+ find-cache-dir: 2.1.0
+ make-dir: 2.1.0
+ pirates: 4.0.7
+ source-map-support: 0.5.21
+
+ '@babel/runtime@7.28.6': {}
+
+ '@babel/template@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+
+ '@babel/traverse@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/traverse@7.29.0':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/generator': 7.29.0
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.29.0
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.28.6':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
+ '@babel/types@7.29.0':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
+ '@bcoe/v8-coverage@0.2.3': {}
+
+ '@expo/cli@54.0.23(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))':
+ dependencies:
+ '@0no-co/graphql.web': 1.2.0
+ '@expo/code-signing-certificates': 0.0.6
+ '@expo/config': 12.0.13
+ '@expo/config-plugins': 54.0.4
+ '@expo/devcert': 1.2.1
+ '@expo/env': 2.0.8
+ '@expo/image-utils': 0.8.8
+ '@expo/json-file': 10.0.8
+ '@expo/metro': 54.2.0
+ '@expo/metro-config': 54.0.14(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))
+ '@expo/osascript': 2.3.8
+ '@expo/package-manager': 1.9.10
+ '@expo/plist': 0.4.8
+ '@expo/prebuild-config': 54.0.8(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))
+ '@expo/schema-utils': 0.1.8
+ '@expo/spawn-async': 1.7.2
+ '@expo/ws-tunnel': 1.0.6
+ '@expo/xcpretty': 4.4.0
+ '@react-native/dev-middleware': 0.81.5
+ '@urql/core': 5.2.0
+ '@urql/exchange-retry': 1.3.2(@urql/core@5.2.0)
+ accepts: 1.3.8
+ arg: 5.0.2
+ better-opn: 3.0.2
+ bplist-creator: 0.1.0
+ bplist-parser: 0.3.2
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ compression: 1.8.1
+ connect: 3.7.0
+ debug: 4.4.3
+ env-editor: 0.4.2
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ expo-server: 1.0.5
+ freeport-async: 2.0.0
+ getenv: 2.0.0
+ glob: 13.0.1
+ lan-network: 0.1.7
+ minimatch: 9.0.5
+ node-forge: 1.3.3
+ npm-package-arg: 11.0.3
+ ora: 3.4.0
+ picomatch: 3.0.1
+ pretty-bytes: 5.6.0
+ pretty-format: 29.7.0
+ progress: 2.0.3
+ prompts: 2.4.2
+ qrcode-terminal: 0.11.0
+ require-from-string: 2.0.2
+ requireg: 0.2.2
+ resolve: 1.22.11
+ resolve-from: 5.0.0
+ resolve.exports: 2.0.3
+ semver: 7.7.3
+ send: 0.19.2
+ slugify: 1.6.6
+ source-map-support: 0.5.21
+ stacktrace-parser: 0.1.11
+ structured-headers: 0.4.1
+ tar: 7.5.7
+ terminal-link: 2.1.1
+ undici: 6.23.0
+ wrap-ansi: 7.0.0
+ ws: 8.18.3
+ optionalDependencies:
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+ transitivePeerDependencies:
+ - bufferutil
+ - graphql
+ - supports-color
+ - utf-8-validate
+
+ '@expo/code-signing-certificates@0.0.6':
+ dependencies:
+ node-forge: 1.3.3
+
+ '@expo/config-plugins@54.0.4':
+ dependencies:
+ '@expo/config-types': 54.0.10
+ '@expo/json-file': 10.0.8
+ '@expo/plist': 0.4.8
+ '@expo/sdk-runtime-versions': 1.0.0
+ chalk: 4.1.2
+ debug: 4.4.3
+ getenv: 2.0.0
+ glob: 13.0.1
+ resolve-from: 5.0.0
+ semver: 7.7.3
+ slash: 3.0.0
+ slugify: 1.6.6
+ xcode: 3.0.1
+ xml2js: 0.6.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@expo/config-types@54.0.10': {}
+
+ '@expo/config@12.0.13':
+ dependencies:
+ '@babel/code-frame': 7.10.4
+ '@expo/config-plugins': 54.0.4
+ '@expo/config-types': 54.0.10
+ '@expo/json-file': 10.0.8
+ deepmerge: 4.3.1
+ getenv: 2.0.0
+ glob: 13.0.1
+ require-from-string: 2.0.2
+ resolve-from: 5.0.0
+ resolve-workspace-root: 2.0.1
+ semver: 7.7.3
+ slugify: 1.6.6
+ sucrase: 3.35.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@expo/devcert@1.2.1':
+ dependencies:
+ '@expo/sudo-prompt': 9.3.2
+ debug: 3.2.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@expo/devtools@0.1.8(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ chalk: 4.1.2
+ optionalDependencies:
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ '@expo/env@2.0.8':
+ dependencies:
+ chalk: 4.1.2
+ debug: 4.4.3
+ dotenv: 16.4.7
+ dotenv-expand: 11.0.7
+ getenv: 2.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@expo/fingerprint@0.15.4':
+ dependencies:
+ '@expo/spawn-async': 1.7.2
+ arg: 5.0.2
+ chalk: 4.1.2
+ debug: 4.4.3
+ getenv: 2.0.0
+ glob: 13.0.1
+ ignore: 5.3.2
+ minimatch: 9.0.5
+ p-limit: 3.1.0
+ resolve-from: 5.0.0
+ semver: 7.7.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@expo/image-utils@0.8.8':
+ dependencies:
+ '@expo/spawn-async': 1.7.2
+ chalk: 4.1.2
+ getenv: 2.0.0
+ jimp-compact: 0.16.1
+ parse-png: 2.1.0
+ resolve-from: 5.0.0
+ resolve-global: 1.0.0
+ semver: 7.7.3
+ temp-dir: 2.0.0
+ unique-string: 2.0.0
+
+ '@expo/json-file@10.0.8':
+ dependencies:
+ '@babel/code-frame': 7.10.4
+ json5: 2.2.3
+
+ '@expo/metro-config@54.0.14(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@expo/config': 12.0.13
+ '@expo/env': 2.0.8
+ '@expo/json-file': 10.0.8
+ '@expo/metro': 54.2.0
+ '@expo/spawn-async': 1.7.2
+ browserslist: 4.28.1
+ chalk: 4.1.2
+ debug: 4.4.3
+ dotenv: 16.4.7
+ dotenv-expand: 11.0.7
+ getenv: 2.0.0
+ glob: 13.0.1
+ hermes-parser: 0.29.1
+ jsc-safe-url: 0.2.4
+ lightningcss: 1.31.1
+ minimatch: 9.0.5
+ postcss: 8.4.49
+ resolve-from: 5.0.0
+ optionalDependencies:
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ '@expo/metro@54.2.0':
+ dependencies:
+ metro: 0.83.3
+ metro-babel-transformer: 0.83.3
+ metro-cache: 0.83.3
+ metro-cache-key: 0.83.3
+ metro-config: 0.83.3
+ metro-core: 0.83.3
+ metro-file-map: 0.83.3
+ metro-minify-terser: 0.83.3
+ metro-resolver: 0.83.3
+ metro-runtime: 0.83.3
+ metro-source-map: 0.83.3
+ metro-symbolicate: 0.83.3
+ metro-transform-plugins: 0.83.3
+ metro-transform-worker: 0.83.3
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ '@expo/osascript@2.3.8':
+ dependencies:
+ '@expo/spawn-async': 1.7.2
+ exec-async: 2.2.0
+
+ '@expo/package-manager@1.9.10':
+ dependencies:
+ '@expo/json-file': 10.0.8
+ '@expo/spawn-async': 1.7.2
+ chalk: 4.1.2
+ npm-package-arg: 11.0.3
+ ora: 3.4.0
+ resolve-workspace-root: 2.0.1
+
+ '@expo/plist@0.4.8':
+ dependencies:
+ '@xmldom/xmldom': 0.8.11
+ base64-js: 1.5.1
+ xmlbuilder: 15.1.1
+
+ '@expo/prebuild-config@54.0.8(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))':
+ dependencies:
+ '@expo/config': 12.0.13
+ '@expo/config-plugins': 54.0.4
+ '@expo/config-types': 54.0.10
+ '@expo/image-utils': 0.8.8
+ '@expo/json-file': 10.0.8
+ '@react-native/normalize-colors': 0.81.5
+ debug: 4.4.3
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ resolve-from: 5.0.0
+ semver: 7.7.3
+ xml2js: 0.6.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@expo/schema-utils@0.1.8': {}
+
+ '@expo/sdk-runtime-versions@1.0.0': {}
+
+ '@expo/spawn-async@1.7.2':
+ dependencies:
+ cross-spawn: 7.0.6
+
+ '@expo/sudo-prompt@9.3.2': {}
+
+ '@expo/vector-icons@15.0.3(expo-font@14.0.11(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ expo-font: 14.0.11(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ '@expo/ws-tunnel@1.0.6': {}
+
+ '@expo/xcpretty@4.4.0':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ chalk: 4.1.2
+ js-yaml: 4.1.1
+
+ '@hapi/hoek@9.3.0': {}
+
+ '@hapi/topo@5.1.0':
+ dependencies:
+ '@hapi/hoek': 9.3.0
+
+ '@isaacs/balanced-match@4.0.1': {}
+
+ '@isaacs/brace-expansion@5.0.1':
+ dependencies:
+ '@isaacs/balanced-match': 4.0.1
+
+ '@isaacs/fs-minipass@4.0.1':
+ dependencies:
+ minipass: 7.1.2
+
+ '@isaacs/ttlcache@1.4.1': {}
+
+ '@istanbuljs/load-nyc-config@1.1.0':
+ dependencies:
+ camelcase: 5.3.1
+ find-up: 4.1.0
+ get-package-type: 0.1.0
+ js-yaml: 3.14.2
+ resolve-from: 5.0.0
+
+ '@istanbuljs/schema@0.1.3': {}
+
+ '@jest/console@29.7.0':
+ dependencies:
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ chalk: 4.1.2
+ jest-message-util: 29.7.0
+ jest-util: 29.7.0
+ slash: 3.0.0
+
+ '@jest/core@29.7.0':
+ dependencies:
+ '@jest/console': 29.7.0
+ '@jest/reporters': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ exit: 0.1.2
+ graceful-fs: 4.2.11
+ jest-changed-files: 29.7.0
+ jest-config: 29.7.0(@types/node@25.1.0)
+ jest-haste-map: 29.7.0
+ jest-message-util: 29.7.0
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-resolve-dependencies: 29.7.0
+ jest-runner: 29.7.0
+ jest-runtime: 29.7.0
+ jest-snapshot: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ jest-watcher: 29.7.0
+ micromatch: 4.0.8
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-ansi: 6.0.1
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
+ '@jest/create-cache-key-function@29.7.0':
+ dependencies:
+ '@jest/types': 29.6.3
+
+ '@jest/environment@29.7.0':
+ dependencies:
+ '@jest/fake-timers': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ jest-mock: 29.7.0
+
+ '@jest/expect-utils@29.7.0':
+ dependencies:
+ jest-get-type: 29.6.3
+
+ '@jest/expect@29.7.0':
+ dependencies:
+ expect: 29.7.0
+ jest-snapshot: 29.7.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/fake-timers@29.7.0':
+ dependencies:
+ '@jest/types': 29.6.3
+ '@sinonjs/fake-timers': 10.3.0
+ '@types/node': 25.1.0
+ jest-message-util: 29.7.0
+ jest-mock: 29.7.0
+ jest-util: 29.7.0
+
+ '@jest/globals@29.7.0':
+ dependencies:
+ '@jest/environment': 29.7.0
+ '@jest/expect': 29.7.0
+ '@jest/types': 29.6.3
+ jest-mock: 29.7.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/reporters@29.7.0':
+ dependencies:
+ '@bcoe/v8-coverage': 0.2.3
+ '@jest/console': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ '@jridgewell/trace-mapping': 0.3.31
+ '@types/node': 25.1.0
+ chalk: 4.1.2
+ collect-v8-coverage: 1.0.3
+ exit: 0.1.2
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ istanbul-lib-coverage: 3.2.2
+ istanbul-lib-instrument: 6.0.3
+ istanbul-lib-report: 3.0.1
+ istanbul-lib-source-maps: 4.0.1
+ istanbul-reports: 3.2.0
+ jest-message-util: 29.7.0
+ jest-util: 29.7.0
+ jest-worker: 29.7.0
+ slash: 3.0.0
+ string-length: 4.0.2
+ strip-ansi: 6.0.1
+ v8-to-istanbul: 9.3.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/schemas@29.6.3':
+ dependencies:
+ '@sinclair/typebox': 0.27.8
+
+ '@jest/source-map@29.6.3':
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.31
+ callsites: 3.1.0
+ graceful-fs: 4.2.11
+
+ '@jest/test-result@29.7.0':
+ dependencies:
+ '@jest/console': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/istanbul-lib-coverage': 2.0.6
+ collect-v8-coverage: 1.0.3
+
+ '@jest/test-sequencer@29.7.0':
+ dependencies:
+ '@jest/test-result': 29.7.0
+ graceful-fs: 4.2.11
+ jest-haste-map: 29.7.0
+ slash: 3.0.0
+
+ '@jest/transform@29.7.0':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@jest/types': 29.6.3
+ '@jridgewell/trace-mapping': 0.3.31
+ babel-plugin-istanbul: 6.1.1
+ chalk: 4.1.2
+ convert-source-map: 2.0.0
+ fast-json-stable-stringify: 2.1.0
+ graceful-fs: 4.2.11
+ jest-haste-map: 29.7.0
+ jest-regex-util: 29.6.3
+ jest-util: 29.7.0
+ micromatch: 4.0.8
+ pirates: 4.0.7
+ slash: 3.0.0
+ write-file-atomic: 4.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/types@26.6.2':
+ dependencies:
+ '@types/istanbul-lib-coverage': 2.0.6
+ '@types/istanbul-reports': 3.0.4
+ '@types/node': 25.1.0
+ '@types/yargs': 15.0.20
+ chalk: 4.1.2
+
+ '@jest/types@29.6.3':
+ dependencies:
+ '@jest/schemas': 29.6.3
+ '@types/istanbul-lib-coverage': 2.0.6
+ '@types/istanbul-reports': 3.0.4
+ '@types/node': 25.1.0
+ '@types/yargs': 17.0.35
+ chalk: 4.1.2
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/source-map@0.3.11':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ '@noble/ciphers@1.3.0': {}
+
+ '@noble/curves@1.9.0':
+ dependencies:
+ '@noble/hashes': 1.8.0
+
+ '@noble/curves@1.9.1':
+ dependencies:
+ '@noble/hashes': 1.8.0
+
+ '@noble/hashes@1.8.0': {}
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.1
+
+ '@react-native-async-storage/async-storage@1.24.0(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))':
+ dependencies:
+ merge-options: 3.0.4
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ '@react-native-community/cli-clean@12.3.7':
+ dependencies:
+ '@react-native-community/cli-tools': 12.3.7
+ chalk: 4.1.2
+ execa: 5.1.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-config@12.3.7':
+ dependencies:
+ '@react-native-community/cli-tools': 12.3.7
+ chalk: 4.1.2
+ cosmiconfig: 5.2.1
+ deepmerge: 4.3.1
+ glob: 7.2.3
+ joi: 17.13.3
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-debugger-ui@12.3.7':
+ dependencies:
+ serve-static: 1.16.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@react-native-community/cli-doctor@12.3.7':
+ dependencies:
+ '@react-native-community/cli-config': 12.3.7
+ '@react-native-community/cli-platform-android': 12.3.7
+ '@react-native-community/cli-platform-ios': 12.3.7
+ '@react-native-community/cli-tools': 12.3.7
+ chalk: 4.1.2
+ command-exists: 1.2.9
+ deepmerge: 4.3.1
+ envinfo: 7.21.0
+ execa: 5.1.1
+ hermes-profile-transformer: 0.0.6
+ node-stream-zip: 1.15.0
+ ora: 5.4.1
+ semver: 7.7.3
+ strip-ansi: 5.2.0
+ wcwidth: 1.0.1
+ yaml: 2.8.2
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-hermes@12.3.7':
+ dependencies:
+ '@react-native-community/cli-platform-android': 12.3.7
+ '@react-native-community/cli-tools': 12.3.7
+ chalk: 4.1.2
+ hermes-profile-transformer: 0.0.6
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-platform-android@12.3.7':
+ dependencies:
+ '@react-native-community/cli-tools': 12.3.7
+ chalk: 4.1.2
+ execa: 5.1.1
+ fast-xml-parser: 4.5.3
+ glob: 7.2.3
+ logkitty: 0.7.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-platform-ios@12.3.7':
+ dependencies:
+ '@react-native-community/cli-tools': 12.3.7
+ chalk: 4.1.2
+ execa: 5.1.1
+ fast-xml-parser: 4.5.3
+ glob: 7.2.3
+ ora: 5.4.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-plugin-metro@12.3.7': {}
+
+ '@react-native-community/cli-server-api@12.3.7':
+ dependencies:
+ '@react-native-community/cli-debugger-ui': 12.3.7
+ '@react-native-community/cli-tools': 12.3.7
+ compression: 1.8.1
+ connect: 3.7.0
+ errorhandler: 1.5.2
+ nocache: 3.0.4
+ pretty-format: 26.6.2
+ serve-static: 1.16.3
+ ws: 7.5.10
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - supports-color
+ - utf-8-validate
+
+ '@react-native-community/cli-tools@12.3.7':
+ dependencies:
+ appdirsjs: 1.2.7
+ chalk: 4.1.2
+ find-up: 5.0.0
+ mime: 2.6.0
+ node-fetch: 2.7.0
+ open: 6.4.0
+ ora: 5.4.1
+ semver: 7.7.3
+ shell-quote: 1.8.3
+ sudo-prompt: 9.2.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@react-native-community/cli-types@12.3.7':
+ dependencies:
+ joi: 17.13.3
+
+ '@react-native-community/cli@12.3.7':
+ dependencies:
+ '@react-native-community/cli-clean': 12.3.7
+ '@react-native-community/cli-config': 12.3.7
+ '@react-native-community/cli-debugger-ui': 12.3.7
+ '@react-native-community/cli-doctor': 12.3.7
+ '@react-native-community/cli-hermes': 12.3.7
+ '@react-native-community/cli-plugin-metro': 12.3.7
+ '@react-native-community/cli-server-api': 12.3.7
+ '@react-native-community/cli-tools': 12.3.7
+ '@react-native-community/cli-types': 12.3.7
+ chalk: 4.1.2
+ commander: 9.5.0
+ deepmerge: 4.3.1
+ execa: 5.1.1
+ find-up: 4.1.0
+ fs-extra: 8.1.0
+ graceful-fs: 4.2.11
+ prompts: 2.4.2
+ semver: 7.7.3
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - supports-color
+ - utf-8-validate
+
+ '@react-native-community/netinfo@11.5.1(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ '@react-native/assets-registry@0.73.1': {}
+
+ '@react-native/babel-plugin-codegen@0.73.4(@babel/preset-env@7.29.0(@babel/core@7.28.6))':
+ dependencies:
+ '@react-native/codegen': 0.73.3(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ transitivePeerDependencies:
+ - '@babel/preset-env'
+ - supports-color
+
+ '@react-native/babel-plugin-codegen@0.81.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@react-native/codegen': 0.81.5(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - supports-color
+
+ '@react-native/babel-preset@0.73.21(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.28.6)
+ '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.28.6)
+ '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.28.6)
+ '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-runtime': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/template': 7.28.6
+ '@react-native/babel-plugin-codegen': 0.73.4(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6)
+ react-refresh: 0.14.2
+ transitivePeerDependencies:
+ - '@babel/preset-env'
+ - supports-color
+
+ '@react-native/babel-preset@0.81.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-generator-functions': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-regenerator': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-runtime': 7.28.5(@babel/core@7.28.6)
+ '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/template': 7.28.6
+ '@react-native/babel-plugin-codegen': 0.81.5(@babel/core@7.28.6)
+ babel-plugin-syntax-hermes-parser: 0.29.1
+ babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6)
+ react-refresh: 0.14.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@react-native/codegen@0.73.3(@babel/preset-env@7.29.0(@babel/core@7.28.6))':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/preset-env': 7.29.0(@babel/core@7.28.6)
+ flow-parser: 0.206.0
+ glob: 7.2.3
+ invariant: 2.2.4
+ jscodeshift: 0.14.0(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ mkdirp: 0.5.6
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@react-native/codegen@0.81.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ glob: 7.2.3
+ hermes-parser: 0.29.1
+ invariant: 2.2.4
+ nullthrows: 1.1.1
+ yargs: 17.7.2
+
+ '@react-native/community-cli-plugin@0.73.18(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))':
+ dependencies:
+ '@react-native-community/cli-server-api': 12.3.7
+ '@react-native-community/cli-tools': 12.3.7
+ '@react-native/dev-middleware': 0.73.8
+ '@react-native/metro-babel-transformer': 0.73.15(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ chalk: 4.1.2
+ execa: 5.1.1
+ metro: 0.80.12
+ metro-config: 0.80.12
+ metro-core: 0.80.12
+ node-fetch: 2.7.0
+ readline: 1.3.0
+ transitivePeerDependencies:
+ - '@babel/core'
+ - '@babel/preset-env'
+ - bufferutil
+ - encoding
+ - supports-color
+ - utf-8-validate
+
+ '@react-native/debugger-frontend@0.73.3': {}
+
+ '@react-native/debugger-frontend@0.81.5': {}
+
+ '@react-native/dev-middleware@0.73.8':
+ dependencies:
+ '@isaacs/ttlcache': 1.4.1
+ '@react-native/debugger-frontend': 0.73.3
+ chrome-launcher: 0.15.2
+ chromium-edge-launcher: 1.0.0
+ connect: 3.7.0
+ debug: 2.6.9
+ node-fetch: 2.7.0
+ open: 7.4.2
+ serve-static: 1.16.3
+ temp-dir: 2.0.0
+ ws: 6.2.3
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - supports-color
+ - utf-8-validate
+
+ '@react-native/dev-middleware@0.81.5':
+ dependencies:
+ '@isaacs/ttlcache': 1.4.1
+ '@react-native/debugger-frontend': 0.81.5
+ chrome-launcher: 0.15.2
+ chromium-edge-launcher: 0.2.0
+ connect: 3.7.0
+ debug: 4.4.3
+ invariant: 2.2.4
+ nullthrows: 1.1.1
+ open: 7.4.2
+ serve-static: 1.16.3
+ ws: 6.2.3
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ '@react-native/gradle-plugin@0.73.5': {}
+
+ '@react-native/js-polyfills@0.73.1': {}
+
+ '@react-native/metro-babel-transformer@0.73.15(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@react-native/babel-preset': 0.73.21(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ hermes-parser: 0.15.0
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - '@babel/preset-env'
+ - supports-color
+
+ '@react-native/normalize-colors@0.73.2': {}
+
+ '@react-native/normalize-colors@0.81.5': {}
+
+ '@react-native/virtualized-lists@0.73.4(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))':
+ dependencies:
+ invariant: 2.2.4
+ nullthrows: 1.1.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ '@scure/base@1.2.6': {}
+
+ '@scure/bip32@1.7.0':
+ dependencies:
+ '@noble/curves': 1.9.0
+ '@noble/hashes': 1.8.0
+ '@scure/base': 1.2.6
+
+ '@scure/bip39@1.6.0':
+ dependencies:
+ '@noble/hashes': 1.8.0
+ '@scure/base': 1.2.6
+
+ '@sideway/address@4.1.5':
+ dependencies:
+ '@hapi/hoek': 9.3.0
+
+ '@sideway/formula@3.0.1': {}
+
+ '@sideway/pinpoint@2.0.0': {}
+
+ '@sinclair/typebox@0.27.8': {}
+
+ '@sinonjs/commons@3.0.1':
+ dependencies:
+ type-detect: 4.0.8
+
+ '@sinonjs/fake-timers@10.3.0':
+ dependencies:
+ '@sinonjs/commons': 3.0.1
+
+ '@tanstack/query-core@5.90.20': {}
+
+ '@tanstack/react-query@5.90.20(react@18.3.1)':
+ dependencies:
+ '@tanstack/query-core': 5.90.20
+ react: 18.3.1
+
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@types/graceful-fs@4.1.9':
+ dependencies:
+ '@types/node': 25.1.0
+
+ '@types/istanbul-lib-coverage@2.0.6': {}
+
+ '@types/istanbul-lib-report@3.0.3':
+ dependencies:
+ '@types/istanbul-lib-coverage': 2.0.6
+
+ '@types/istanbul-reports@3.0.4':
+ dependencies:
+ '@types/istanbul-lib-report': 3.0.3
+
+ '@types/jest@29.5.14':
+ dependencies:
+ expect: 29.7.0
+ pretty-format: 29.7.0
+
+ '@types/node@25.1.0':
+ dependencies:
+ undici-types: 7.16.0
+
+ '@types/parse-json@4.0.2': {}
+
+ '@types/prop-types@15.7.15': {}
+
+ '@types/react@18.3.27':
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
+
+ '@types/stack-utils@2.0.3': {}
+
+ '@types/yargs-parser@21.0.3': {}
+
+ '@types/yargs@15.0.20':
+ dependencies:
+ '@types/yargs-parser': 21.0.3
+
+ '@types/yargs@17.0.35':
+ dependencies:
+ '@types/yargs-parser': 21.0.3
+
+ '@ungap/structured-clone@1.3.0': {}
+
+ '@urql/core@5.2.0':
+ dependencies:
+ '@0no-co/graphql.web': 1.2.0
+ wonka: 6.3.5
+ transitivePeerDependencies:
+ - graphql
+
+ '@urql/exchange-retry@1.3.2(@urql/core@5.2.0)':
+ dependencies:
+ '@urql/core': 5.2.0
+ wonka: 6.3.5
+
+ '@wagmi/connectors@7.1.5(@wagmi/core@3.3.1(@tanstack/query-core@5.90.20)(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.45.0(typescript@5.9.3)))(typescript@5.9.3)(viem@2.45.0(typescript@5.9.3))':
+ dependencies:
+ '@wagmi/core': 3.3.1(@tanstack/query-core@5.90.20)(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.45.0(typescript@5.9.3))
+ viem: 2.45.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
+ '@wagmi/core@3.3.1(@tanstack/query-core@5.90.20)(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.45.0(typescript@5.9.3))':
+ dependencies:
+ eventemitter3: 5.0.1
+ mipd: 0.0.7(typescript@5.9.3)
+ viem: 2.45.0(typescript@5.9.3)
+ zustand: 5.0.0(@types/react@18.3.27)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1))
+ optionalDependencies:
+ '@tanstack/query-core': 5.90.20
+ ox: 0.11.3(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@types/react'
+ - immer
+ - react
+ - use-sync-external-store
+
+ '@xmldom/xmldom@0.8.11': {}
+
+ abitype@1.2.3(typescript@5.9.3):
+ optionalDependencies:
+ typescript: 5.9.3
+
+ abort-controller@3.0.0:
+ dependencies:
+ event-target-shim: 5.0.1
+
+ accepts@1.3.8:
+ dependencies:
+ mime-types: 2.1.35
+ negotiator: 0.6.3
+
+ acorn@8.15.0: {}
+
+ agent-base@7.1.4: {}
+
+ aggregate-error@3.1.0:
+ dependencies:
+ clean-stack: 2.2.0
+ indent-string: 4.0.0
+
+ anser@1.4.10: {}
+
+ ansi-escapes@4.3.2:
+ dependencies:
+ type-fest: 0.21.3
+
+ ansi-fragments@0.2.1:
+ dependencies:
+ colorette: 1.4.0
+ slice-ansi: 2.1.0
+ strip-ansi: 5.2.0
+
+ ansi-regex@4.1.1: {}
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@3.2.1:
+ dependencies:
+ color-convert: 1.9.3
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ ansi-styles@5.2.0: {}
+
+ any-promise@1.3.0: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ appdirsjs@1.2.7: {}
+
+ arg@5.0.2: {}
+
+ argparse@1.0.10:
+ dependencies:
+ sprintf-js: 1.0.3
+
+ argparse@2.0.1: {}
+
+ array-union@2.1.0: {}
+
+ asap@2.0.6: {}
+
+ ast-types@0.15.2:
+ dependencies:
+ tslib: 2.8.1
+
+ astral-regex@1.0.0: {}
+
+ async-limiter@1.0.1: {}
+
+ babel-core@7.0.0-bridge.0(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+
+ babel-jest@29.7.0(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@jest/transform': 29.7.0
+ '@types/babel__core': 7.20.5
+ babel-plugin-istanbul: 6.1.1
+ babel-preset-jest: 29.6.3(@babel/core@7.28.6)
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ slash: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-istanbul@6.1.1:
+ dependencies:
+ '@babel/helper-plugin-utils': 7.28.6
+ '@istanbuljs/load-nyc-config': 1.1.0
+ '@istanbuljs/schema': 0.1.3
+ istanbul-lib-instrument: 5.2.1
+ test-exclude: 6.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-jest-hoist@29.6.3:
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+ '@types/babel__core': 7.20.5
+ '@types/babel__traverse': 7.28.0
+
+ babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.28.6):
+ dependencies:
+ '@babel/compat-data': 7.28.6
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.28.6)
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.28.6)
+ core-js-compat: 3.48.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.28.6)
+ core-js-compat: 3.48.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-react-compiler@1.0.0:
+ dependencies:
+ '@babel/types': 7.28.6
+
+ babel-plugin-react-native-web@0.21.2: {}
+
+ babel-plugin-syntax-hermes-parser@0.29.1:
+ dependencies:
+ hermes-parser: 0.29.1
+
+ babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.28.6):
+ dependencies:
+ '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6)
+ transitivePeerDependencies:
+ - '@babel/core'
+
+ babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.6)
+ '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6)
+ '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6)
+
+ babel-preset-expo@54.0.10(@babel/core@7.28.6)(@babel/runtime@7.28.6)(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-refresh@0.14.2):
+ dependencies:
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/plugin-proposal-decorators': 7.29.0(@babel/core@7.28.6)
+ '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-runtime': 7.28.5(@babel/core@7.28.6)
+ '@babel/preset-react': 7.28.5(@babel/core@7.28.6)
+ '@babel/preset-typescript': 7.28.5(@babel/core@7.28.6)
+ '@react-native/babel-preset': 0.81.5(@babel/core@7.28.6)
+ babel-plugin-react-compiler: 1.0.0
+ babel-plugin-react-native-web: 0.21.2
+ babel-plugin-syntax-hermes-parser: 0.29.1
+ babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6)
+ debug: 4.4.3
+ react-refresh: 0.14.2
+ resolve-from: 5.0.0
+ optionalDependencies:
+ '@babel/runtime': 7.28.6
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - supports-color
+
+ babel-preset-jest@29.6.3(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ babel-plugin-jest-hoist: 29.6.3
+ babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6)
+
+ balanced-match@1.0.2: {}
+
+ base64-js@1.5.1: {}
+
+ baseline-browser-mapping@2.9.19: {}
+
+ better-opn@3.0.2:
+ dependencies:
+ open: 8.4.2
+
+ big-integer@1.6.52: {}
+
+ bl@4.1.0:
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
+ bplist-creator@0.1.0:
+ dependencies:
+ stream-buffers: 2.2.0
+
+ bplist-parser@0.3.1:
+ dependencies:
+ big-integer: 1.6.52
+
+ bplist-parser@0.3.2:
+ dependencies:
+ big-integer: 1.6.52
+
+ brace-expansion@1.1.12:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.2:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ browserslist@4.28.1:
+ dependencies:
+ baseline-browser-mapping: 2.9.19
+ caniuse-lite: 1.0.30001766
+ electron-to-chromium: 1.5.279
+ node-releases: 2.0.27
+ update-browserslist-db: 1.2.3(browserslist@4.28.1)
+
+ bser@2.1.1:
+ dependencies:
+ node-int64: 0.4.0
+
+ buffer-from@1.1.2: {}
+
+ buffer@5.7.1:
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+
+ bytes@3.1.2: {}
+
+ caller-callsite@2.0.0:
+ dependencies:
+ callsites: 2.0.0
+
+ caller-path@2.0.0:
+ dependencies:
+ caller-callsite: 2.0.0
+
+ callsites@2.0.0: {}
+
+ callsites@3.1.0: {}
+
+ camelcase@5.3.1: {}
+
+ camelcase@6.3.0: {}
+
+ caniuse-lite@1.0.30001766: {}
+
+ chalk@2.4.2:
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ char-regex@1.0.2: {}
+
+ chownr@3.0.0: {}
+
+ chrome-launcher@0.15.2:
+ dependencies:
+ '@types/node': 25.1.0
+ escape-string-regexp: 4.0.0
+ is-wsl: 2.2.0
+ lighthouse-logger: 1.4.2
+ transitivePeerDependencies:
+ - supports-color
+
+ chromium-edge-launcher@0.2.0:
+ dependencies:
+ '@types/node': 25.1.0
+ escape-string-regexp: 4.0.0
+ is-wsl: 2.2.0
+ lighthouse-logger: 1.4.2
+ mkdirp: 1.0.4
+ rimraf: 3.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ chromium-edge-launcher@1.0.0:
+ dependencies:
+ '@types/node': 25.1.0
+ escape-string-regexp: 4.0.0
+ is-wsl: 2.2.0
+ lighthouse-logger: 1.4.2
+ mkdirp: 1.0.4
+ rimraf: 3.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ ci-info@2.0.0: {}
+
+ ci-info@3.9.0: {}
+
+ cjs-module-lexer@1.4.3: {}
+
+ clean-stack@2.2.0: {}
+
+ cli-cursor@2.1.0:
+ dependencies:
+ restore-cursor: 2.0.0
+
+ cli-cursor@3.1.0:
+ dependencies:
+ restore-cursor: 3.1.0
+
+ cli-spinners@2.9.2: {}
+
+ cliui@6.0.0:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 6.2.0
+
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ clone-deep@4.0.1:
+ dependencies:
+ is-plain-object: 2.0.4
+ kind-of: 6.0.3
+ shallow-clone: 3.0.1
+
+ clone@1.0.4: {}
+
+ co@4.6.0: {}
+
+ collect-v8-coverage@1.0.3: {}
+
+ color-convert@1.9.3:
+ dependencies:
+ color-name: 1.1.3
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.3: {}
+
+ color-name@1.1.4: {}
+
+ colorette@1.4.0: {}
+
+ command-exists@1.2.9: {}
+
+ commander@2.20.3: {}
+
+ commander@4.1.1: {}
+
+ commander@7.2.0: {}
+
+ commander@9.5.0: {}
+
+ commondir@1.0.1: {}
+
+ compressible@2.0.18:
+ dependencies:
+ mime-db: 1.54.0
+
+ compression@1.8.1:
+ dependencies:
+ bytes: 3.1.2
+ compressible: 2.0.18
+ debug: 2.6.9
+ negotiator: 0.6.4
+ on-headers: 1.1.0
+ safe-buffer: 5.2.1
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ concat-map@0.0.1: {}
+
+ connect@3.7.0:
+ dependencies:
+ debug: 2.6.9
+ finalhandler: 1.1.2
+ parseurl: 1.3.3
+ utils-merge: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ convert-source-map@2.0.0: {}
+
+ core-js-compat@3.48.0:
+ dependencies:
+ browserslist: 4.28.1
+
+ core-util-is@1.0.3: {}
+
+ cosmiconfig@5.2.1:
+ dependencies:
+ import-fresh: 2.0.0
+ is-directory: 0.3.1
+ js-yaml: 3.14.2
+ parse-json: 4.0.0
+
+ cosmiconfig@7.1.0:
+ dependencies:
+ '@types/parse-json': 4.0.2
+ import-fresh: 3.3.1
+ parse-json: 5.2.0
+ path-type: 4.0.0
+ yaml: 1.10.2
+
+ create-jest@29.7.0(@types/node@25.1.0):
+ dependencies:
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ exit: 0.1.2
+ graceful-fs: 4.2.11
+ jest-config: 29.7.0(@types/node@25.1.0)
+ jest-util: 29.7.0
+ prompts: 2.4.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ crypto-random-string@2.0.0: {}
+
+ csstype@3.2.3: {}
+
+ dayjs@1.11.19: {}
+
+ debug@2.6.9:
+ dependencies:
+ ms: 2.0.0
+
+ debug@3.2.7:
+ dependencies:
+ ms: 2.1.3
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ decamelize@1.2.0: {}
+
+ dedent@0.7.0: {}
+
+ dedent@1.7.1: {}
+
+ deep-extend@0.6.0: {}
+
+ deepmerge@4.3.1: {}
+
+ defaults@1.0.4:
+ dependencies:
+ clone: 1.0.4
+
+ define-lazy-prop@2.0.0: {}
+
+ del@6.1.1:
+ dependencies:
+ globby: 11.1.0
+ graceful-fs: 4.2.11
+ is-glob: 4.0.3
+ is-path-cwd: 2.2.0
+ is-path-inside: 3.0.3
+ p-map: 4.0.0
+ rimraf: 3.0.2
+ slash: 3.0.0
+
+ denodeify@1.2.1: {}
+
+ depd@2.0.0: {}
+
+ deprecated-react-native-prop-types@5.0.0:
+ dependencies:
+ '@react-native/normalize-colors': 0.73.2
+ invariant: 2.2.4
+ prop-types: 15.8.1
+
+ destroy@1.2.0: {}
+
+ detect-libc@2.1.2: {}
+
+ detect-newline@3.1.0: {}
+
+ diff-sequences@29.6.3: {}
+
+ dir-glob@3.0.1:
+ dependencies:
+ path-type: 4.0.0
+
+ dotenv-expand@11.0.7:
+ dependencies:
+ dotenv: 16.4.7
+
+ dotenv@16.4.7: {}
+
+ ee-first@1.1.1: {}
+
+ electron-to-chromium@1.5.279: {}
+
+ emittery@0.13.1: {}
+
+ emoji-regex@8.0.0: {}
+
+ encodeurl@1.0.2: {}
+
+ encodeurl@2.0.0: {}
+
+ end-of-stream@1.4.5:
+ dependencies:
+ once: 1.4.0
+
+ env-editor@0.4.2: {}
+
+ envinfo@7.21.0: {}
+
+ error-ex@1.3.4:
+ dependencies:
+ is-arrayish: 0.2.1
+
+ error-stack-parser@2.1.4:
+ dependencies:
+ stackframe: 1.3.4
+
+ errorhandler@1.5.2:
+ dependencies:
+ accepts: 1.3.8
+ escape-html: 1.0.3
+
+ escalade@3.2.0: {}
+
+ escape-html@1.0.3: {}
+
+ escape-string-regexp@1.0.5: {}
+
+ escape-string-regexp@2.0.0: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ esprima@4.0.1: {}
+
+ esutils@2.0.3: {}
+
+ etag@1.8.1: {}
+
+ ethereum-cryptography@3.2.0:
+ dependencies:
+ '@noble/ciphers': 1.3.0
+ '@noble/curves': 1.9.0
+ '@noble/hashes': 1.8.0
+ '@scure/bip32': 1.7.0
+ '@scure/bip39': 1.6.0
+
+ event-target-shim@5.0.1: {}
+
+ eventemitter3@5.0.1: {}
+
+ exec-async@2.2.0: {}
+
+ execa@4.1.0:
+ dependencies:
+ cross-spawn: 7.0.6
+ get-stream: 5.2.0
+ human-signals: 1.1.1
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
+ execa@5.1.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
+ exit@0.1.2: {}
+
+ expect@29.7.0:
+ dependencies:
+ '@jest/expect-utils': 29.7.0
+ jest-get-type: 29.6.3
+ jest-matcher-utils: 29.7.0
+ jest-message-util: 29.7.0
+ jest-util: 29.7.0
+
+ expo-application@6.1.5(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)):
+ dependencies:
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+
+ expo-asset@12.0.12(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@expo/image-utils': 0.8.8
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ expo-constants: 18.0.13(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ expo-constants@18.0.13(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)):
+ dependencies:
+ '@expo/config': 12.0.13
+ '@expo/env': 2.0.8
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ expo-device@7.1.4(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)):
+ dependencies:
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ ua-parser-js: 0.7.41
+
+ expo-file-system@19.0.21(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)):
+ dependencies:
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ expo-font@14.0.11(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1):
+ dependencies:
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ fontfaceobserver: 2.3.0
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ expo-keep-awake@15.0.8(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react@18.3.1):
+ dependencies:
+ expo: 54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+
+ expo-modules-autolinking@3.0.24:
+ dependencies:
+ '@expo/spawn-async': 1.7.2
+ chalk: 4.1.2
+ commander: 7.2.0
+ require-from-string: 2.0.2
+ resolve-from: 5.0.0
+
+ expo-modules-core@3.0.29(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1):
+ dependencies:
+ invariant: 2.2.4
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ expo-server@1.0.5: {}
+
+ expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.28.6
+ '@expo/cli': 54.0.23(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ '@expo/config': 12.0.13
+ '@expo/config-plugins': 54.0.4
+ '@expo/devtools': 0.1.8(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ '@expo/fingerprint': 0.15.4
+ '@expo/metro': 54.2.0
+ '@expo/metro-config': 54.0.14(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))
+ '@expo/vector-icons': 15.0.3(expo-font@14.0.11(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ '@ungap/structured-clone': 1.3.0
+ babel-preset-expo: 54.0.10(@babel/core@7.28.6)(@babel/runtime@7.28.6)(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-refresh@0.14.2)
+ expo-asset: 12.0.12(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ expo-constants: 18.0.13(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ expo-file-system: 19.0.21(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ expo-font: 14.0.11(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ expo-keep-awake: 15.0.8(expo@54.0.33(@babel/core@7.28.6)(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ expo-modules-autolinking: 3.0.24
+ expo-modules-core: 3.0.29(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))(react@18.3.1)
+ pretty-format: 29.7.0
+ react: 18.3.1
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+ react-refresh: 0.14.2
+ whatwg-url-without-unicode: 8.0.0-3
+ transitivePeerDependencies:
+ - '@babel/core'
+ - bufferutil
+ - expo-router
+ - graphql
+ - supports-color
+ - utf-8-validate
+
+ exponential-backoff@3.1.3: {}
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-xml-parser@4.5.3:
+ dependencies:
+ strnum: 1.1.2
+
+ fastq@1.20.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fb-watchman@2.0.2:
+ dependencies:
+ bser: 2.1.1
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ finalhandler@1.1.2:
+ dependencies:
+ debug: 2.6.9
+ encodeurl: 1.0.2
+ escape-html: 1.0.3
+ on-finished: 2.3.0
+ parseurl: 1.3.3
+ statuses: 1.5.0
+ unpipe: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ find-cache-dir@2.1.0:
+ dependencies:
+ commondir: 1.0.1
+ make-dir: 2.1.0
+ pkg-dir: 3.0.0
+
+ find-up@3.0.0:
+ dependencies:
+ locate-path: 3.0.0
+
+ find-up@4.1.0:
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flow-enums-runtime@0.0.6: {}
+
+ flow-parser@0.206.0: {}
+
+ fontfaceobserver@2.3.0: {}
+
+ freeport-async@2.0.0: {}
+
+ fresh@0.5.2: {}
+
+ fs-extra@10.1.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.2.0
+ universalify: 2.0.1
+
+ fs-extra@8.1.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 4.0.0
+ universalify: 0.1.2
+
+ fs.realpath@1.0.0: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ gensync@1.0.0-beta.2: {}
+
+ get-caller-file@2.0.5: {}
+
+ get-package-type@0.1.0: {}
+
+ get-stream@5.2.0:
+ dependencies:
+ pump: 3.0.3
+
+ get-stream@6.0.1: {}
+
+ getenv@2.0.0: {}
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob@13.0.1:
+ dependencies:
+ minimatch: 10.1.2
+ minipass: 7.1.2
+ path-scurry: 2.0.1
+
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
+ glob@8.1.0:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 5.1.6
+ once: 1.4.0
+
+ global-dirs@0.1.1:
+ dependencies:
+ ini: 1.3.8
+
+ globby@11.1.0:
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.3
+ ignore: 5.3.2
+ merge2: 1.4.1
+ slash: 3.0.0
+
+ graceful-fs@4.2.11: {}
+
+ has-flag@3.0.0: {}
+
+ has-flag@4.0.0: {}
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ hermes-estree@0.15.0: {}
+
+ hermes-estree@0.23.1: {}
+
+ hermes-estree@0.29.1: {}
+
+ hermes-estree@0.32.0: {}
+
+ hermes-parser@0.15.0:
+ dependencies:
+ hermes-estree: 0.15.0
+
+ hermes-parser@0.23.1:
+ dependencies:
+ hermes-estree: 0.23.1
+
+ hermes-parser@0.29.1:
+ dependencies:
+ hermes-estree: 0.29.1
+
+ hermes-parser@0.32.0:
+ dependencies:
+ hermes-estree: 0.32.0
+
+ hermes-profile-transformer@0.0.6:
+ dependencies:
+ source-map: 0.7.6
+
+ hosted-git-info@7.0.2:
+ dependencies:
+ lru-cache: 10.4.3
+
+ html-escaper@2.0.2: {}
+
+ http-errors@2.0.1:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.2
+ toidentifier: 1.0.1
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ human-signals@1.1.1: {}
+
+ human-signals@2.1.0: {}
+
+ ieee754@1.2.1: {}
+
+ ignore@5.3.2: {}
+
+ image-size@1.2.1:
+ dependencies:
+ queue: 6.0.2
+
+ import-fresh@2.0.0:
+ dependencies:
+ caller-path: 2.0.0
+ resolve-from: 3.0.0
+
+ import-fresh@3.3.1:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ import-local@3.2.0:
+ dependencies:
+ pkg-dir: 4.2.0
+ resolve-cwd: 3.0.0
+
+ imurmurhash@0.1.4: {}
+
+ indent-string@4.0.0: {}
+
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
+ ini@1.3.8: {}
+
+ invariant@2.2.4:
+ dependencies:
+ loose-envify: 1.4.0
+
+ is-absolute@1.0.0:
+ dependencies:
+ is-relative: 1.0.0
+ is-windows: 1.0.2
+
+ is-arrayish@0.2.1: {}
+
+ is-core-module@2.16.1:
+ dependencies:
+ hasown: 2.0.2
+
+ is-directory@0.3.1: {}
+
+ is-docker@2.2.1: {}
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@2.0.0: {}
+
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-generator-fn@2.1.0: {}
+
+ is-git-dirty@2.0.2:
+ dependencies:
+ execa: 4.1.0
+ is-git-repository: 2.0.0
+
+ is-git-repository@2.0.0:
+ dependencies:
+ execa: 4.1.0
+ is-absolute: 1.0.0
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-interactive@1.0.0: {}
+
+ is-number@7.0.0: {}
+
+ is-path-cwd@2.2.0: {}
+
+ is-path-inside@3.0.3: {}
+
+ is-plain-obj@2.1.0: {}
+
+ is-plain-object@2.0.4:
+ dependencies:
+ isobject: 3.0.1
+
+ is-relative@1.0.0:
+ dependencies:
+ is-unc-path: 1.0.0
+
+ is-stream@2.0.1: {}
+
+ is-unc-path@1.0.0:
+ dependencies:
+ unc-path-regex: 0.1.2
+
+ is-unicode-supported@0.1.0: {}
+
+ is-windows@1.0.2: {}
+
+ is-wsl@1.1.0: {}
+
+ is-wsl@2.2.0:
+ dependencies:
+ is-docker: 2.2.1
+
+ isarray@1.0.0: {}
+
+ isexe@2.0.0: {}
+
+ isobject@3.0.1: {}
+
+ isows@1.0.7(ws@8.18.3):
+ dependencies:
+ ws: 8.18.3
+
+ istanbul-lib-coverage@3.2.2: {}
+
+ istanbul-lib-instrument@5.2.1:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ '@istanbuljs/schema': 0.1.3
+ istanbul-lib-coverage: 3.2.2
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ istanbul-lib-instrument@6.0.3:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ '@istanbuljs/schema': 0.1.3
+ istanbul-lib-coverage: 3.2.2
+ semver: 7.7.3
+ transitivePeerDependencies:
+ - supports-color
+
+ istanbul-lib-report@3.0.1:
+ dependencies:
+ istanbul-lib-coverage: 3.2.2
+ make-dir: 4.0.0
+ supports-color: 7.2.0
+
+ istanbul-lib-source-maps@4.0.1:
+ dependencies:
+ debug: 4.4.3
+ istanbul-lib-coverage: 3.2.2
+ source-map: 0.6.1
+ transitivePeerDependencies:
+ - supports-color
+
+ istanbul-reports@3.2.0:
+ dependencies:
+ html-escaper: 2.0.2
+ istanbul-lib-report: 3.0.1
+
+ jest-changed-files@29.7.0:
+ dependencies:
+ execa: 5.1.1
+ jest-util: 29.7.0
+ p-limit: 3.1.0
+
+ jest-circus@29.7.0:
+ dependencies:
+ '@jest/environment': 29.7.0
+ '@jest/expect': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ chalk: 4.1.2
+ co: 4.6.0
+ dedent: 1.7.1
+ is-generator-fn: 2.1.0
+ jest-each: 29.7.0
+ jest-matcher-utils: 29.7.0
+ jest-message-util: 29.7.0
+ jest-runtime: 29.7.0
+ jest-snapshot: 29.7.0
+ jest-util: 29.7.0
+ p-limit: 3.1.0
+ pretty-format: 29.7.0
+ pure-rand: 6.1.0
+ slash: 3.0.0
+ stack-utils: 2.0.6
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
+ jest-cli@29.7.0(@types/node@25.1.0):
+ dependencies:
+ '@jest/core': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ create-jest: 29.7.0(@types/node@25.1.0)
+ exit: 0.1.2
+ import-local: 3.2.0
+ jest-config: 29.7.0(@types/node@25.1.0)
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
+ jest-config@29.7.0(@types/node@25.1.0):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@jest/test-sequencer': 29.7.0
+ '@jest/types': 29.6.3
+ babel-jest: 29.7.0(@babel/core@7.28.6)
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ deepmerge: 4.3.1
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ jest-circus: 29.7.0
+ jest-environment-node: 29.7.0
+ jest-get-type: 29.6.3
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-runner: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 25.1.0
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
+ jest-diff@29.7.0:
+ dependencies:
+ chalk: 4.1.2
+ diff-sequences: 29.6.3
+ jest-get-type: 29.6.3
+ pretty-format: 29.7.0
+
+ jest-docblock@29.7.0:
+ dependencies:
+ detect-newline: 3.1.0
+
+ jest-each@29.7.0:
+ dependencies:
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ jest-get-type: 29.6.3
+ jest-util: 29.7.0
+ pretty-format: 29.7.0
+
+ jest-environment-node@29.7.0:
+ dependencies:
+ '@jest/environment': 29.7.0
+ '@jest/fake-timers': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ jest-mock: 29.7.0
+ jest-util: 29.7.0
+
+ jest-get-type@29.6.3: {}
+
+ jest-haste-map@29.7.0:
+ dependencies:
+ '@jest/types': 29.6.3
+ '@types/graceful-fs': 4.1.9
+ '@types/node': 25.1.0
+ anymatch: 3.1.3
+ fb-watchman: 2.0.2
+ graceful-fs: 4.2.11
+ jest-regex-util: 29.6.3
+ jest-util: 29.7.0
+ jest-worker: 29.7.0
+ micromatch: 4.0.8
+ walker: 1.0.8
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ jest-leak-detector@29.7.0:
+ dependencies:
+ jest-get-type: 29.6.3
+ pretty-format: 29.7.0
+
+ jest-matcher-utils@29.7.0:
+ dependencies:
+ chalk: 4.1.2
+ jest-diff: 29.7.0
+ jest-get-type: 29.6.3
+ pretty-format: 29.7.0
+
+ jest-message-util@29.7.0:
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@jest/types': 29.6.3
+ '@types/stack-utils': 2.0.3
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ micromatch: 4.0.8
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ stack-utils: 2.0.6
+
+ jest-mock@29.7.0:
+ dependencies:
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ jest-util: 29.7.0
+
+ jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
+ optionalDependencies:
+ jest-resolve: 29.7.0
+
+ jest-regex-util@29.6.3: {}
+
+ jest-resolve-dependencies@29.7.0:
+ dependencies:
+ jest-regex-util: 29.6.3
+ jest-snapshot: 29.7.0
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-resolve@29.7.0:
+ dependencies:
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ jest-haste-map: 29.7.0
+ jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0)
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ resolve: 1.22.11
+ resolve.exports: 2.0.3
+ slash: 3.0.0
+
+ jest-runner@29.7.0:
+ dependencies:
+ '@jest/console': 29.7.0
+ '@jest/environment': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ chalk: 4.1.2
+ emittery: 0.13.1
+ graceful-fs: 4.2.11
+ jest-docblock: 29.7.0
+ jest-environment-node: 29.7.0
+ jest-haste-map: 29.7.0
+ jest-leak-detector: 29.7.0
+ jest-message-util: 29.7.0
+ jest-resolve: 29.7.0
+ jest-runtime: 29.7.0
+ jest-util: 29.7.0
+ jest-watcher: 29.7.0
+ jest-worker: 29.7.0
+ p-limit: 3.1.0
+ source-map-support: 0.5.13
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-runtime@29.7.0:
+ dependencies:
+ '@jest/environment': 29.7.0
+ '@jest/fake-timers': 29.7.0
+ '@jest/globals': 29.7.0
+ '@jest/source-map': 29.6.3
+ '@jest/test-result': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ chalk: 4.1.2
+ cjs-module-lexer: 1.4.3
+ collect-v8-coverage: 1.0.3
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ jest-haste-map: 29.7.0
+ jest-message-util: 29.7.0
+ jest-mock: 29.7.0
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-snapshot: 29.7.0
+ jest-util: 29.7.0
+ slash: 3.0.0
+ strip-bom: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-snapshot@29.7.0:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6)
+ '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6)
+ '@babel/types': 7.28.6
+ '@jest/expect-utils': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6)
+ chalk: 4.1.2
+ expect: 29.7.0
+ graceful-fs: 4.2.11
+ jest-diff: 29.7.0
+ jest-get-type: 29.6.3
+ jest-matcher-utils: 29.7.0
+ jest-message-util: 29.7.0
+ jest-util: 29.7.0
+ natural-compare: 1.4.0
+ pretty-format: 29.7.0
+ semver: 7.7.3
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-util@29.7.0:
+ dependencies:
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ graceful-fs: 4.2.11
+ picomatch: 2.3.1
+
+ jest-validate@29.7.0:
+ dependencies:
+ '@jest/types': 29.6.3
+ camelcase: 6.3.0
+ chalk: 4.1.2
+ jest-get-type: 29.6.3
+ leven: 3.1.0
+ pretty-format: 29.7.0
+
+ jest-watcher@29.7.0:
+ dependencies:
+ '@jest/test-result': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 25.1.0
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ emittery: 0.13.1
+ jest-util: 29.7.0
+ string-length: 4.0.2
+
+ jest-worker@29.7.0:
+ dependencies:
+ '@types/node': 25.1.0
+ jest-util: 29.7.0
+ merge-stream: 2.0.0
+ supports-color: 8.1.1
+
+ jest@29.7.0(@types/node@25.1.0):
+ dependencies:
+ '@jest/core': 29.7.0
+ '@jest/types': 29.6.3
+ import-local: 3.2.0
+ jest-cli: 29.7.0(@types/node@25.1.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
+ jimp-compact@0.16.1: {}
+
+ joi@17.13.3:
+ dependencies:
+ '@hapi/hoek': 9.3.0
+ '@hapi/topo': 5.1.0
+ '@sideway/address': 4.1.5
+ '@sideway/formula': 3.0.1
+ '@sideway/pinpoint': 2.0.0
+
+ js-tokens@4.0.0: {}
+
+ js-yaml@3.14.2:
+ dependencies:
+ argparse: 1.0.10
+ esprima: 4.0.1
+
+ js-yaml@4.1.1:
+ dependencies:
+ argparse: 2.0.1
+
+ jsc-android@250231.0.0: {}
+
+ jsc-safe-url@0.2.4: {}
+
+ jscodeshift@0.14.0(@babel/preset-env@7.29.0(@babel/core@7.28.6)):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6)
+ '@babel/preset-env': 7.29.0(@babel/core@7.28.6)
+ '@babel/preset-flow': 7.27.1(@babel/core@7.28.6)
+ '@babel/preset-typescript': 7.28.5(@babel/core@7.28.6)
+ '@babel/register': 7.28.6(@babel/core@7.28.6)
+ babel-core: 7.0.0-bridge.0(@babel/core@7.28.6)
+ chalk: 4.1.2
+ flow-parser: 0.206.0
+ graceful-fs: 4.2.11
+ micromatch: 4.0.8
+ neo-async: 2.6.2
+ node-dir: 0.1.17
+ recast: 0.21.5
+ temp: 0.8.4
+ write-file-atomic: 2.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ jsesc@3.1.0: {}
+
+ json-parse-better-errors@1.0.2: {}
+
+ json-parse-even-better-errors@2.3.1: {}
+
+ json5@2.2.3: {}
+
+ jsonfile@4.0.0:
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ jsonfile@6.2.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ kind-of@6.0.3: {}
+
+ kleur@3.0.3: {}
+
+ kleur@4.1.5: {}
+
+ lan-network@0.1.7: {}
+
+ leven@3.1.0: {}
+
+ lighthouse-logger@1.4.2:
+ dependencies:
+ debug: 2.6.9
+ marky: 1.3.0
+ transitivePeerDependencies:
+ - supports-color
+
+ lightningcss-android-arm64@1.31.1:
+ optional: true
+
+ lightningcss-darwin-arm64@1.31.1:
+ optional: true
+
+ lightningcss-darwin-x64@1.31.1:
+ optional: true
+
+ lightningcss-freebsd-x64@1.31.1:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.31.1:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.31.1:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.31.1:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.31.1:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.31.1:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.31.1:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.31.1:
+ optional: true
+
+ lightningcss@1.31.1:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.31.1
+ lightningcss-darwin-arm64: 1.31.1
+ lightningcss-darwin-x64: 1.31.1
+ lightningcss-freebsd-x64: 1.31.1
+ lightningcss-linux-arm-gnueabihf: 1.31.1
+ lightningcss-linux-arm64-gnu: 1.31.1
+ lightningcss-linux-arm64-musl: 1.31.1
+ lightningcss-linux-x64-gnu: 1.31.1
+ lightningcss-linux-x64-musl: 1.31.1
+ lightningcss-win32-arm64-msvc: 1.31.1
+ lightningcss-win32-x64-msvc: 1.31.1
+
+ lines-and-columns@1.2.4: {}
+
+ locate-path@3.0.0:
+ dependencies:
+ p-locate: 3.0.0
+ path-exists: 3.0.0
+
+ locate-path@5.0.0:
+ dependencies:
+ p-locate: 4.1.0
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ lodash.debounce@4.0.8: {}
+
+ lodash.throttle@4.1.1: {}
+
+ log-symbols@2.2.0:
+ dependencies:
+ chalk: 2.4.2
+
+ log-symbols@4.1.0:
+ dependencies:
+ chalk: 4.1.2
+ is-unicode-supported: 0.1.0
+
+ logkitty@0.7.1:
+ dependencies:
+ ansi-fragments: 0.2.1
+ dayjs: 1.11.19
+ yargs: 15.4.1
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ lru-cache@10.4.3: {}
+
+ lru-cache@11.2.5: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ make-dir@2.1.0:
+ dependencies:
+ pify: 4.0.1
+ semver: 5.7.2
+
+ make-dir@4.0.0:
+ dependencies:
+ semver: 7.7.3
+
+ makeerror@1.0.12:
+ dependencies:
+ tmpl: 1.0.5
+
+ marky@1.3.0: {}
+
+ memoize-one@5.2.1: {}
+
+ merge-options@3.0.4:
+ dependencies:
+ is-plain-obj: 2.1.0
+
+ merge-stream@2.0.0: {}
+
+ merge2@1.4.1: {}
+
+ metro-babel-transformer@0.80.12:
+ dependencies:
+ '@babel/core': 7.28.6
+ flow-enums-runtime: 0.0.6
+ hermes-parser: 0.23.1
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-babel-transformer@0.83.3:
+ dependencies:
+ '@babel/core': 7.28.6
+ flow-enums-runtime: 0.0.6
+ hermes-parser: 0.32.0
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-cache-key@0.80.12:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+
+ metro-cache-key@0.83.3:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+
+ metro-cache@0.80.12:
+ dependencies:
+ exponential-backoff: 3.1.3
+ flow-enums-runtime: 0.0.6
+ metro-core: 0.80.12
+
+ metro-cache@0.83.3:
+ dependencies:
+ exponential-backoff: 3.1.3
+ flow-enums-runtime: 0.0.6
+ https-proxy-agent: 7.0.6
+ metro-core: 0.83.3
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-config@0.80.12:
+ dependencies:
+ connect: 3.7.0
+ cosmiconfig: 5.2.1
+ flow-enums-runtime: 0.0.6
+ jest-validate: 29.7.0
+ metro: 0.80.12
+ metro-cache: 0.80.12
+ metro-core: 0.80.12
+ metro-runtime: 0.80.12
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ metro-config@0.83.3:
+ dependencies:
+ connect: 3.7.0
+ flow-enums-runtime: 0.0.6
+ jest-validate: 29.7.0
+ metro: 0.83.3
+ metro-cache: 0.83.3
+ metro-core: 0.83.3
+ metro-runtime: 0.83.3
+ yaml: 2.8.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ metro-core@0.80.12:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+ lodash.throttle: 4.1.1
+ metro-resolver: 0.80.12
+
+ metro-core@0.83.3:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+ lodash.throttle: 4.1.1
+ metro-resolver: 0.83.3
+
+ metro-file-map@0.80.12:
+ dependencies:
+ anymatch: 3.1.3
+ debug: 2.6.9
+ fb-watchman: 2.0.2
+ flow-enums-runtime: 0.0.6
+ graceful-fs: 4.2.11
+ invariant: 2.2.4
+ jest-worker: 29.7.0
+ micromatch: 4.0.8
+ node-abort-controller: 3.1.1
+ nullthrows: 1.1.1
+ walker: 1.0.8
+ optionalDependencies:
+ fsevents: 2.3.3
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-file-map@0.83.3:
+ dependencies:
+ debug: 4.4.3
+ fb-watchman: 2.0.2
+ flow-enums-runtime: 0.0.6
+ graceful-fs: 4.2.11
+ invariant: 2.2.4
+ jest-worker: 29.7.0
+ micromatch: 4.0.8
+ nullthrows: 1.1.1
+ walker: 1.0.8
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-minify-terser@0.80.12:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+ terser: 5.46.0
+
+ metro-minify-terser@0.83.3:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+ terser: 5.46.0
+
+ metro-resolver@0.80.12:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+
+ metro-resolver@0.83.3:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+
+ metro-runtime@0.80.12:
+ dependencies:
+ '@babel/runtime': 7.28.6
+ flow-enums-runtime: 0.0.6
+
+ metro-runtime@0.83.3:
+ dependencies:
+ '@babel/runtime': 7.28.6
+ flow-enums-runtime: 0.0.6
+
+ metro-source-map@0.80.12:
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ flow-enums-runtime: 0.0.6
+ invariant: 2.2.4
+ metro-symbolicate: 0.80.12
+ nullthrows: 1.1.1
+ ob1: 0.80.12
+ source-map: 0.5.7
+ vlq: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-source-map@0.83.3:
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.6'
+ '@babel/types': 7.28.6
+ flow-enums-runtime: 0.0.6
+ invariant: 2.2.4
+ metro-symbolicate: 0.83.3
+ nullthrows: 1.1.1
+ ob1: 0.83.3
+ source-map: 0.5.7
+ vlq: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-symbolicate@0.80.12:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+ invariant: 2.2.4
+ metro-source-map: 0.80.12
+ nullthrows: 1.1.1
+ source-map: 0.5.7
+ through2: 2.0.5
+ vlq: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-symbolicate@0.83.3:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+ invariant: 2.2.4
+ metro-source-map: 0.83.3
+ nullthrows: 1.1.1
+ source-map: 0.5.7
+ vlq: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-transform-plugins@0.80.12:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ flow-enums-runtime: 0.0.6
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-transform-plugins@0.83.3:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ flow-enums-runtime: 0.0.6
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ metro-transform-worker@0.80.12:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ flow-enums-runtime: 0.0.6
+ metro: 0.80.12
+ metro-babel-transformer: 0.80.12
+ metro-cache: 0.80.12
+ metro-cache-key: 0.80.12
+ metro-minify-terser: 0.80.12
+ metro-source-map: 0.80.12
+ metro-transform-plugins: 0.80.12
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ metro-transform-worker@0.83.3:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ flow-enums-runtime: 0.0.6
+ metro: 0.83.3
+ metro-babel-transformer: 0.83.3
+ metro-cache: 0.83.3
+ metro-cache-key: 0.83.3
+ metro-minify-terser: 0.83.3
+ metro-source-map: 0.83.3
+ metro-transform-plugins: 0.83.3
+ nullthrows: 1.1.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ metro@0.80.12:
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ accepts: 1.3.8
+ chalk: 4.1.2
+ ci-info: 2.0.0
+ connect: 3.7.0
+ debug: 2.6.9
+ denodeify: 1.2.1
+ error-stack-parser: 2.1.4
+ flow-enums-runtime: 0.0.6
+ graceful-fs: 4.2.11
+ hermes-parser: 0.23.1
+ image-size: 1.2.1
+ invariant: 2.2.4
+ jest-worker: 29.7.0
+ jsc-safe-url: 0.2.4
+ lodash.throttle: 4.1.1
+ metro-babel-transformer: 0.80.12
+ metro-cache: 0.80.12
+ metro-cache-key: 0.80.12
+ metro-config: 0.80.12
+ metro-core: 0.80.12
+ metro-file-map: 0.80.12
+ metro-resolver: 0.80.12
+ metro-runtime: 0.80.12
+ metro-source-map: 0.80.12
+ metro-symbolicate: 0.80.12
+ metro-transform-plugins: 0.80.12
+ metro-transform-worker: 0.80.12
+ mime-types: 2.1.35
+ nullthrows: 1.1.1
+ serialize-error: 2.1.0
+ source-map: 0.5.7
+ strip-ansi: 6.0.1
+ throat: 5.0.0
+ ws: 7.5.10
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ metro@0.83.3:
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/core': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ accepts: 1.3.8
+ chalk: 4.1.2
+ ci-info: 2.0.0
+ connect: 3.7.0
+ debug: 4.4.3
+ error-stack-parser: 2.1.4
+ flow-enums-runtime: 0.0.6
+ graceful-fs: 4.2.11
+ hermes-parser: 0.32.0
+ image-size: 1.2.1
+ invariant: 2.2.4
+ jest-worker: 29.7.0
+ jsc-safe-url: 0.2.4
+ lodash.throttle: 4.1.1
+ metro-babel-transformer: 0.83.3
+ metro-cache: 0.83.3
+ metro-cache-key: 0.83.3
+ metro-config: 0.83.3
+ metro-core: 0.83.3
+ metro-file-map: 0.83.3
+ metro-resolver: 0.83.3
+ metro-runtime: 0.83.3
+ metro-source-map: 0.83.3
+ metro-symbolicate: 0.83.3
+ metro-transform-plugins: 0.83.3
+ metro-transform-worker: 0.83.3
+ mime-types: 2.1.35
+ nullthrows: 1.1.1
+ serialize-error: 2.1.0
+ source-map: 0.5.7
+ throat: 5.0.0
+ ws: 7.5.10
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-db@1.54.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mime@1.6.0: {}
+
+ mime@2.6.0: {}
+
+ mimic-fn@1.2.0: {}
+
+ mimic-fn@2.1.0: {}
+
+ minimatch@10.1.2:
+ dependencies:
+ '@isaacs/brace-expansion': 5.0.1
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.12
+
+ minimatch@5.1.6:
+ dependencies:
+ brace-expansion: 2.0.2
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.2
+
+ minimist@1.2.8: {}
+
+ minipass@7.1.2: {}
+
+ minizlib@3.1.0:
+ dependencies:
+ minipass: 7.1.2
+
+ mipd@0.0.7(typescript@5.9.3):
+ optionalDependencies:
+ typescript: 5.9.3
+
+ mkdirp@0.5.6:
+ dependencies:
+ minimist: 1.2.8
+
+ mkdirp@1.0.4: {}
+
+ ms@2.0.0: {}
+
+ ms@2.1.3: {}
+
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ nanoid@3.3.11: {}
+
+ natural-compare@1.4.0: {}
+
+ negotiator@0.6.3: {}
+
+ negotiator@0.6.4: {}
+
+ neo-async@2.6.2: {}
+
+ nested-error-stacks@2.0.1: {}
+
+ nocache@3.0.4: {}
+
+ node-abort-controller@3.1.1: {}
+
+ node-dir@0.1.17:
+ dependencies:
+ minimatch: 3.1.2
+
+ node-fetch@2.7.0:
+ dependencies:
+ whatwg-url: 5.0.0
+
+ node-forge@1.3.3: {}
+
+ node-int64@0.4.0: {}
+
+ node-releases@2.0.27: {}
+
+ node-stream-zip@1.15.0: {}
+
+ normalize-path@3.0.0: {}
+
+ npm-package-arg@11.0.3:
+ dependencies:
+ hosted-git-info: 7.0.2
+ proc-log: 4.2.0
+ semver: 7.7.3
+ validate-npm-package-name: 5.0.1
+
+ npm-run-path@4.0.1:
+ dependencies:
+ path-key: 3.1.1
+
+ nullthrows@1.1.1: {}
+
+ ob1@0.80.12:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+
+ ob1@0.83.3:
+ dependencies:
+ flow-enums-runtime: 0.0.6
+
+ object-assign@4.1.1: {}
+
+ on-finished@2.3.0:
+ dependencies:
+ ee-first: 1.1.1
+
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
+ on-headers@1.1.0: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ onetime@2.0.1:
+ dependencies:
+ mimic-fn: 1.2.0
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
+ open@6.4.0:
+ dependencies:
+ is-wsl: 1.1.0
+
+ open@7.4.2:
+ dependencies:
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+
+ open@8.4.2:
+ dependencies:
+ define-lazy-prop: 2.0.0
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+
+ ora@3.4.0:
+ dependencies:
+ chalk: 2.4.2
+ cli-cursor: 2.1.0
+ cli-spinners: 2.9.2
+ log-symbols: 2.2.0
+ strip-ansi: 5.2.0
+ wcwidth: 1.0.1
+
+ ora@5.4.1:
+ dependencies:
+ bl: 4.1.0
+ chalk: 4.1.2
+ cli-cursor: 3.1.0
+ cli-spinners: 2.9.2
+ is-interactive: 1.0.0
+ is-unicode-supported: 0.1.0
+ log-symbols: 4.1.0
+ strip-ansi: 6.0.1
+ wcwidth: 1.0.1
+
+ ox@0.11.3(typescript@5.9.3):
+ dependencies:
+ '@adraffy/ens-normalize': 1.11.1
+ '@noble/ciphers': 1.3.0
+ '@noble/curves': 1.9.1
+ '@noble/hashes': 1.8.0
+ '@scure/bip32': 1.7.0
+ '@scure/bip39': 1.6.0
+ abitype: 1.2.3(typescript@5.9.3)
+ eventemitter3: 5.0.1
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - zod
+
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@3.0.0:
+ dependencies:
+ p-limit: 2.3.0
+
+ p-locate@4.1.0:
+ dependencies:
+ p-limit: 2.3.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ p-map@4.0.0:
+ dependencies:
+ aggregate-error: 3.1.0
+
+ p-try@2.2.0: {}
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ parse-json@4.0.0:
+ dependencies:
+ error-ex: 1.3.4
+ json-parse-better-errors: 1.0.2
+
+ parse-json@5.2.0:
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ error-ex: 1.3.4
+ json-parse-even-better-errors: 2.3.1
+ lines-and-columns: 1.2.4
+
+ parse-png@2.1.0:
+ dependencies:
+ pngjs: 3.4.0
+
+ parseurl@1.3.3: {}
+
+ path-exists@3.0.0: {}
+
+ path-exists@4.0.0: {}
+
+ path-is-absolute@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-parse@1.0.7: {}
+
+ path-scurry@2.0.1:
+ dependencies:
+ lru-cache: 11.2.5
+ minipass: 7.1.2
+
+ path-type@4.0.0: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ picomatch@3.0.1: {}
+
+ picomatch@4.0.3: {}
+
+ pify@4.0.1: {}
+
+ pirates@4.0.7: {}
+
+ pkg-dir@3.0.0:
+ dependencies:
+ find-up: 3.0.0
+
+ pkg-dir@4.2.0:
+ dependencies:
+ find-up: 4.1.0
+
+ plist@3.1.0:
+ dependencies:
+ '@xmldom/xmldom': 0.8.11
+ base64-js: 1.5.1
+ xmlbuilder: 15.1.1
+
+ pngjs@3.4.0: {}
+
+ postcss@8.4.49:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ pretty-bytes@5.6.0: {}
+
+ pretty-format@26.6.2:
+ dependencies:
+ '@jest/types': 26.6.2
+ ansi-regex: 5.0.1
+ ansi-styles: 4.3.0
+ react-is: 17.0.2
+
+ pretty-format@29.7.0:
+ dependencies:
+ '@jest/schemas': 29.6.3
+ ansi-styles: 5.2.0
+ react-is: 18.3.1
+
+ proc-log@4.2.0: {}
+
+ process-nextick-args@2.0.1: {}
+
+ progress@2.0.3: {}
+
+ promise@8.3.0:
+ dependencies:
+ asap: 2.0.6
+
+ prompts@2.4.2:
+ dependencies:
+ kleur: 3.0.3
+ sisteransi: 1.0.5
+
+ prop-types@15.8.1:
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+
+ pump@3.0.3:
+ dependencies:
+ end-of-stream: 1.4.5
+ once: 1.4.0
+
+ punycode@2.3.1: {}
+
+ pure-rand@6.1.0: {}
+
+ qrcode-terminal@0.11.0: {}
+
+ queue-microtask@1.2.3: {}
+
+ queue@6.0.2:
+ dependencies:
+ inherits: 2.0.4
+
+ range-parser@1.2.1: {}
+
+ rc@1.2.8:
+ dependencies:
+ deep-extend: 0.6.0
+ ini: 1.3.8
+ minimist: 1.2.8
+ strip-json-comments: 2.0.1
+
+ react-devtools-core@4.28.5:
+ dependencies:
+ shell-quote: 1.8.3
+ ws: 7.5.10
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ react-is@16.13.1: {}
+
+ react-is@17.0.2: {}
+
+ react-is@18.3.1: {}
+
+ react-native-builder-bob@0.23.2:
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.28.6)
+ '@babel/preset-env': 7.29.0(@babel/core@7.28.6)
+ '@babel/preset-flow': 7.27.1(@babel/core@7.28.6)
+ '@babel/preset-react': 7.28.5(@babel/core@7.28.6)
+ '@babel/preset-typescript': 7.28.5(@babel/core@7.28.6)
+ browserslist: 4.28.1
+ cosmiconfig: 7.1.0
+ cross-spawn: 7.0.6
+ dedent: 0.7.0
+ del: 6.1.1
+ fs-extra: 10.1.0
+ glob: 8.1.0
+ is-git-dirty: 2.0.2
+ json5: 2.2.3
+ kleur: 4.1.5
+ prompts: 2.4.2
+ which: 2.0.2
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - supports-color
+
+ react-native-device-info@14.1.1(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)):
+ dependencies:
+ react-native: 0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1)
+
+ react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1):
+ dependencies:
+ '@jest/create-cache-key-function': 29.7.0
+ '@react-native-community/cli': 12.3.7
+ '@react-native-community/cli-platform-android': 12.3.7
+ '@react-native-community/cli-platform-ios': 12.3.7
+ '@react-native/assets-registry': 0.73.1
+ '@react-native/codegen': 0.73.3(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ '@react-native/community-cli-plugin': 0.73.18(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))
+ '@react-native/gradle-plugin': 0.73.5
+ '@react-native/js-polyfills': 0.73.1
+ '@react-native/normalize-colors': 0.73.2
+ '@react-native/virtualized-lists': 0.73.4(react-native@0.73.11(@babel/core@7.28.6)(@babel/preset-env@7.29.0(@babel/core@7.28.6))(react@18.3.1))
+ abort-controller: 3.0.0
+ anser: 1.4.10
+ ansi-regex: 5.0.1
+ base64-js: 1.5.1
+ chalk: 4.1.2
+ deprecated-react-native-prop-types: 5.0.0
+ event-target-shim: 5.0.1
+ flow-enums-runtime: 0.0.6
+ invariant: 2.2.4
+ jest-environment-node: 29.7.0
+ jsc-android: 250231.0.0
+ memoize-one: 5.2.1
+ metro-runtime: 0.80.12
+ metro-source-map: 0.80.12
+ mkdirp: 0.5.6
+ nullthrows: 1.1.1
+ pretty-format: 26.6.2
+ promise: 8.3.0
+ react: 18.3.1
+ react-devtools-core: 4.28.5
+ react-refresh: 0.14.2
+ react-shallow-renderer: 16.15.0(react@18.3.1)
+ regenerator-runtime: 0.13.11
+ scheduler: 0.24.0-canary-efb381bbf-20230505
+ stacktrace-parser: 0.1.11
+ whatwg-fetch: 3.6.20
+ ws: 6.2.3
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - '@babel/core'
+ - '@babel/preset-env'
+ - bufferutil
+ - encoding
+ - supports-color
+ - utf-8-validate
+
+ react-refresh@0.14.2: {}
+
+ react-shallow-renderer@16.15.0(react@18.3.1):
+ dependencies:
+ object-assign: 4.1.1
+ react: 18.3.1
+ react-is: 18.3.1
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ readable-stream@2.3.8:
+ dependencies:
+ core-util-is: 1.0.3
+ inherits: 2.0.4
+ isarray: 1.0.0
+ process-nextick-args: 2.0.1
+ safe-buffer: 5.1.2
+ string_decoder: 1.1.1
+ util-deprecate: 1.0.2
+
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+
+ readline@1.3.0: {}
+
+ recast@0.21.5:
+ dependencies:
+ ast-types: 0.15.2
+ esprima: 4.0.1
+ source-map: 0.6.1
+ tslib: 2.8.1
+
+ regenerate-unicode-properties@10.2.2:
+ dependencies:
+ regenerate: 1.4.2
+
+ regenerate@1.4.2: {}
+
+ regenerator-runtime@0.13.11: {}
+
+ regexpu-core@6.4.0:
+ dependencies:
+ regenerate: 1.4.2
+ regenerate-unicode-properties: 10.2.2
+ regjsgen: 0.8.0
+ regjsparser: 0.13.0
+ unicode-match-property-ecmascript: 2.0.0
+ unicode-match-property-value-ecmascript: 2.2.1
+
+ regjsgen@0.8.0: {}
+
+ regjsparser@0.13.0:
+ dependencies:
+ jsesc: 3.1.0
+
+ require-directory@2.1.1: {}
+
+ require-from-string@2.0.2: {}
+
+ require-main-filename@2.0.0: {}
+
+ requireg@0.2.2:
+ dependencies:
+ nested-error-stacks: 2.0.1
+ rc: 1.2.8
+ resolve: 1.7.1
+
+ resolve-cwd@3.0.0:
+ dependencies:
+ resolve-from: 5.0.0
+
+ resolve-from@3.0.0: {}
+
+ resolve-from@4.0.0: {}
+
+ resolve-from@5.0.0: {}
+
+ resolve-global@1.0.0:
+ dependencies:
+ global-dirs: 0.1.1
+
+ resolve-workspace-root@2.0.1: {}
+
+ resolve.exports@2.0.3: {}
+
+ resolve@1.22.11:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ resolve@1.7.1:
+ dependencies:
+ path-parse: 1.0.7
+
+ restore-cursor@2.0.0:
+ dependencies:
+ onetime: 2.0.1
+ signal-exit: 3.0.7
+
+ restore-cursor@3.1.0:
+ dependencies:
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+
+ reusify@1.1.0: {}
+
+ rimraf@2.6.3:
+ dependencies:
+ glob: 7.2.3
+
+ rimraf@3.0.2:
+ dependencies:
+ glob: 7.2.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-buffer@5.1.2: {}
+
+ safe-buffer@5.2.1: {}
+
+ sax@1.4.4: {}
+
+ scheduler@0.24.0-canary-efb381bbf-20230505:
+ dependencies:
+ loose-envify: 1.4.0
+
+ semver@5.7.2: {}
+
+ semver@6.3.1: {}
+
+ semver@7.7.3: {}
+
+ send@0.19.2:
+ dependencies:
+ debug: 2.6.9
+ depd: 2.0.0
+ destroy: 1.2.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 0.5.2
+ http-errors: 2.0.1
+ mime: 1.6.0
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ serialize-error@2.1.0: {}
+
+ serve-static@1.16.3:
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 0.19.2
+ transitivePeerDependencies:
+ - supports-color
+
+ set-blocking@2.0.0: {}
+
+ setprototypeof@1.2.0: {}
+
+ shallow-clone@3.0.1:
+ dependencies:
+ kind-of: 6.0.3
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ shell-quote@1.8.3: {}
+
+ signal-exit@3.0.7: {}
+
+ simple-plist@1.3.1:
+ dependencies:
+ bplist-creator: 0.1.0
+ bplist-parser: 0.3.1
+ plist: 3.1.0
+
+ sisteransi@1.0.5: {}
+
+ slash@3.0.0: {}
+
+ slice-ansi@2.1.0:
+ dependencies:
+ ansi-styles: 3.2.1
+ astral-regex: 1.0.0
+ is-fullwidth-code-point: 2.0.0
+
+ slugify@1.6.6: {}
+
+ source-map-js@1.2.1: {}
+
+ source-map-support@0.5.13:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.5.7: {}
+
+ source-map@0.6.1: {}
+
+ source-map@0.7.6: {}
+
+ sprintf-js@1.0.3: {}
+
+ stack-utils@2.0.6:
+ dependencies:
+ escape-string-regexp: 2.0.0
+
+ stackframe@1.3.4: {}
+
+ stacktrace-parser@0.1.11:
+ dependencies:
+ type-fest: 0.7.1
+
+ statuses@1.5.0: {}
+
+ statuses@2.0.2: {}
+
+ stream-buffers@2.2.0: {}
+
+ string-length@4.0.2:
+ dependencies:
+ char-regex: 1.0.2
+ strip-ansi: 6.0.1
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string_decoder@1.1.1:
+ dependencies:
+ safe-buffer: 5.1.2
+
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ strip-ansi@5.2.0:
+ dependencies:
+ ansi-regex: 4.1.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-bom@4.0.0: {}
+
+ strip-final-newline@2.0.0: {}
+
+ strip-json-comments@2.0.1: {}
+
+ strip-json-comments@3.1.1: {}
+
+ strnum@1.1.2: {}
+
+ structured-headers@0.4.1: {}
+
+ sucrase@3.35.1:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ commander: 4.1.1
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ tinyglobby: 0.2.15
+ ts-interface-checker: 0.1.13
+
+ sudo-prompt@9.2.1: {}
+
+ supports-color@5.5.0:
+ dependencies:
+ has-flag: 3.0.0
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-color@8.1.1:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-hyperlinks@2.3.0:
+ dependencies:
+ has-flag: 4.0.0
+ supports-color: 7.2.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ tar@7.5.7:
+ dependencies:
+ '@isaacs/fs-minipass': 4.0.1
+ chownr: 3.0.0
+ minipass: 7.1.2
+ minizlib: 3.1.0
+ yallist: 5.0.0
+
+ temp-dir@2.0.0: {}
+
+ temp@0.8.4:
+ dependencies:
+ rimraf: 2.6.3
+
+ terminal-link@2.1.1:
+ dependencies:
+ ansi-escapes: 4.3.2
+ supports-hyperlinks: 2.3.0
+
+ terser@5.46.0:
+ dependencies:
+ '@jridgewell/source-map': 0.3.11
+ acorn: 8.15.0
+ commander: 2.20.3
+ source-map-support: 0.5.21
+
+ test-exclude@6.0.0:
+ dependencies:
+ '@istanbuljs/schema': 0.1.3
+ glob: 7.2.3
+ minimatch: 3.1.2
+
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
+ throat@5.0.0: {}
+
+ through2@2.0.5:
+ dependencies:
+ readable-stream: 2.3.8
+ xtend: 4.0.2
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tmpl@1.0.5: {}
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ toidentifier@1.0.1: {}
+
+ tr46@0.0.3: {}
+
+ ts-interface-checker@0.1.13: {}
+
+ tslib@2.8.1: {}
+
+ type-detect@4.0.8: {}
+
+ type-fest@0.21.3: {}
+
+ type-fest@0.7.1: {}
+
+ typescript@5.9.3: {}
+
+ ua-parser-js@0.7.41: {}
+
+ unc-path-regex@0.1.2: {}
+
+ undici-types@7.16.0: {}
+
+ undici@6.23.0: {}
+
+ unicode-canonical-property-names-ecmascript@2.0.1: {}
+
+ unicode-match-property-ecmascript@2.0.0:
+ dependencies:
+ unicode-canonical-property-names-ecmascript: 2.0.1
+ unicode-property-aliases-ecmascript: 2.2.0
+
+ unicode-match-property-value-ecmascript@2.2.1: {}
+
+ unicode-property-aliases-ecmascript@2.2.0: {}
+
+ unique-string@2.0.0:
+ dependencies:
+ crypto-random-string: 2.0.0
+
+ universalify@0.1.2: {}
+
+ universalify@2.0.1: {}
+
+ unpipe@1.0.0: {}
+
+ update-browserslist-db@1.2.3(browserslist@4.28.1):
+ dependencies:
+ browserslist: 4.28.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ use-sync-external-store@1.4.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
+ util-deprecate@1.0.2: {}
+
+ utils-merge@1.0.1: {}
+
+ uuid@7.0.3: {}
+
+ v8-to-istanbul@9.3.0:
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.31
+ '@types/istanbul-lib-coverage': 2.0.6
+ convert-source-map: 2.0.0
+
+ validate-npm-package-name@5.0.1: {}
+
+ vary@1.1.2: {}
+
+ viem@2.45.0(typescript@5.9.3):
+ dependencies:
+ '@noble/curves': 1.9.1
+ '@noble/hashes': 1.8.0
+ '@scure/bip32': 1.7.0
+ '@scure/bip39': 1.6.0
+ abitype: 1.2.3(typescript@5.9.3)
+ isows: 1.0.7(ws@8.18.3)
+ ox: 0.11.3(typescript@5.9.3)
+ ws: 8.18.3
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+ - zod
+
+ vlq@1.0.1: {}
+
+ wagmi@3.4.1(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@18.3.1))(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(viem@2.45.0(typescript@5.9.3)):
+ dependencies:
+ '@tanstack/react-query': 5.90.20(react@18.3.1)
+ '@wagmi/connectors': 7.1.5(@wagmi/core@3.3.1(@tanstack/query-core@5.90.20)(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.45.0(typescript@5.9.3)))(typescript@5.9.3)(viem@2.45.0(typescript@5.9.3))
+ '@wagmi/core': 3.3.1(@tanstack/query-core@5.90.20)(@types/react@18.3.27)(ox@0.11.3(typescript@5.9.3))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.45.0(typescript@5.9.3))
+ react: 18.3.1
+ use-sync-external-store: 1.4.0(react@18.3.1)
+ viem: 2.45.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@base-org/account'
+ - '@coinbase/wallet-sdk'
+ - '@gemini-wallet/core'
+ - '@metamask/sdk'
+ - '@safe-global/safe-apps-provider'
+ - '@safe-global/safe-apps-sdk'
+ - '@tanstack/query-core'
+ - '@types/react'
+ - '@walletconnect/ethereum-provider'
+ - immer
+ - ox
+ - porto
+
+ walker@1.0.8:
+ dependencies:
+ makeerror: 1.0.12
+
+ wcwidth@1.0.1:
+ dependencies:
+ defaults: 1.0.4
+
+ webidl-conversions@3.0.1: {}
+
+ webidl-conversions@5.0.0: {}
+
+ whatwg-fetch@3.6.20: {}
+
+ whatwg-url-without-unicode@8.0.0-3:
+ dependencies:
+ buffer: 5.7.1
+ punycode: 2.3.1
+ webidl-conversions: 5.0.0
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+
+ which-module@2.0.1: {}
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wonka@6.3.5: {}
+
+ wrap-ansi@6.2.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrappy@1.0.2: {}
+
+ write-file-atomic@2.4.3:
+ dependencies:
+ graceful-fs: 4.2.11
+ imurmurhash: 0.1.4
+ signal-exit: 3.0.7
+
+ write-file-atomic@4.0.2:
+ dependencies:
+ imurmurhash: 0.1.4
+ signal-exit: 3.0.7
+
+ ws@6.2.3:
+ dependencies:
+ async-limiter: 1.0.1
+
+ ws@7.5.10: {}
+
+ ws@8.18.3: {}
+
+ xcode@3.0.1:
+ dependencies:
+ simple-plist: 1.3.1
+ uuid: 7.0.3
+
+ xml2js@0.6.0:
+ dependencies:
+ sax: 1.4.4
+ xmlbuilder: 11.0.1
+
+ xmlbuilder@11.0.1: {}
+
+ xmlbuilder@15.1.1: {}
+
+ xtend@4.0.2: {}
+
+ y18n@4.0.3: {}
+
+ y18n@5.0.8: {}
+
+ yallist@3.1.1: {}
+
+ yallist@5.0.0: {}
+
+ yaml@1.10.2: {}
+
+ yaml@2.8.2: {}
+
+ yargs-parser@18.1.3:
+ dependencies:
+ camelcase: 5.3.1
+ decamelize: 1.2.0
+
+ yargs-parser@21.1.1: {}
+
+ yargs@15.4.1:
+ dependencies:
+ cliui: 6.0.0
+ decamelize: 1.2.0
+ find-up: 4.1.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ require-main-filename: 2.0.0
+ set-blocking: 2.0.0
+ string-width: 4.2.3
+ which-module: 2.0.1
+ y18n: 4.0.3
+ yargs-parser: 18.1.3
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
+ yocto-queue@0.1.0: {}
+
+ zustand@5.0.0(@types/react@18.3.27)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)):
+ optionalDependencies:
+ '@types/react': 18.3.27
+ react: 18.3.1
+ use-sync-external-store: 1.4.0(react@18.3.1)
diff --git a/src/FormoAnalytics.ts b/src/FormoAnalytics.ts
new file mode 100644
index 0000000..2b89649
--- /dev/null
+++ b/src/FormoAnalytics.ts
@@ -0,0 +1,653 @@
+/**
+ * FormoAnalytics for React Native
+ *
+ * Main SDK class for tracking wallet events and user analytics in mobile dApps
+ */
+
+import {
+ EVENTS_API_HOST,
+ EventType,
+ LOCAL_ANONYMOUS_ID_KEY,
+ SESSION_USER_ID_KEY,
+ CONSENT_OPT_OUT_KEY,
+ TEventType,
+} from "./constants";
+import { initStorageManager, storage, AsyncStorageInterface } from "./lib/storage";
+import { EventManager, EventQueue, IEventManager } from "./lib/event";
+import { logger, Logger } from "./lib/logger";
+import {
+ setConsentFlag,
+ getConsentFlag,
+ removeConsentFlag,
+} from "./lib/consent";
+import { FormoAnalyticsSession } from "./lib/session";
+import { WagmiEventHandler } from "./lib/wagmi";
+import {
+ Address,
+ ChainID,
+ Config,
+ IFormoAnalytics,
+ IFormoEventContext,
+ IFormoEventProperties,
+ Options,
+ SignatureStatus,
+ TrackingOptions,
+ TransactionStatus,
+} from "./types";
+import { toChecksumAddress, getValidAddress } from "./utils";
+
+export class FormoAnalytics implements IFormoAnalytics {
+ private session: FormoAnalyticsSession;
+ private eventManager: IEventManager;
+ private eventQueue: EventQueue;
+ private wagmiHandler?: WagmiEventHandler;
+
+ config: Config;
+ currentChainId?: ChainID;
+ currentAddress?: Address;
+ currentUserId?: string = "";
+
+ private constructor(
+ public readonly writeKey: string,
+ public options: Options = {}
+ ) {
+ this.config = { writeKey };
+
+ this.session = new FormoAnalyticsSession();
+ this.currentUserId =
+ (storage().get(SESSION_USER_ID_KEY) as string) || undefined;
+
+ // Bind methods
+ this.identify = this.identify.bind(this);
+ this.connect = this.connect.bind(this);
+ this.disconnect = this.disconnect.bind(this);
+ this.chain = this.chain.bind(this);
+ this.signature = this.signature.bind(this);
+ this.transaction = this.transaction.bind(this);
+ this.detect = this.detect.bind(this);
+ this.track = this.track.bind(this);
+ this.screen = this.screen.bind(this);
+ this.isAutocaptureEnabled = this.isAutocaptureEnabled.bind(this);
+
+ // Initialize logger
+ Logger.init({
+ enabled: options.logger?.enabled || false,
+ enabledLevels: options.logger?.levels || [],
+ });
+
+ // Initialize event queue
+ this.eventQueue = new EventQueue(this.config.writeKey, {
+ apiHost: options.apiHost || EVENTS_API_HOST,
+ flushAt: options.flushAt,
+ retryCount: options.retryCount,
+ maxQueueSize: options.maxQueueSize,
+ flushInterval: options.flushInterval,
+ });
+
+ // Initialize event manager
+ this.eventManager = new EventManager(this.eventQueue, options);
+
+ // Check consent status
+ if (this.hasOptedOutTracking()) {
+ logger.info("User has previously opted out of tracking");
+ }
+
+ // Initialize Wagmi handler if provided and config is valid
+ if (options.wagmi?.config) {
+ logger.info("FormoAnalytics: Initializing in Wagmi mode");
+ this.wagmiHandler = new WagmiEventHandler(
+ this,
+ options.wagmi.config,
+ options.wagmi.queryClient
+ );
+ } else if (options.wagmi) {
+ logger.warn("FormoAnalytics: wagmi option provided but config is missing");
+ }
+ }
+
+ /**
+ * Initialize the SDK
+ * @param writeKey - Your Formo write key
+ * @param options - Configuration options
+ * @param asyncStorage - AsyncStorage instance from @react-native-async-storage/async-storage
+ */
+ static async init(
+ writeKey: string,
+ options?: Options,
+ asyncStorage?: AsyncStorageInterface
+ ): Promise {
+ const storageManager = initStorageManager(writeKey);
+
+ // Initialize storage with AsyncStorage if provided
+ if (asyncStorage) {
+ await storageManager.initialize(asyncStorage);
+ }
+
+ const analytics = new FormoAnalytics(writeKey, options);
+
+ // Call ready callback
+ if (options?.ready) {
+ options.ready(analytics);
+ }
+
+ return analytics;
+ }
+
+ /**
+ * Track a screen view (mobile equivalent of page view)
+ */
+ public async screen(
+ name: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ // Note: shouldTrack() is called in trackEvent() - no need to check here
+ await this.trackEvent(
+ EventType.SCREEN,
+ { name },
+ properties,
+ context,
+ callback
+ );
+ }
+
+ /**
+ * Set traffic source from deep link URL
+ * Parses UTM parameters and referrer information from URL
+ * This is automatically persisted for the session
+ *
+ * @param url - Deep link URL (e.g., "myapp://product?utm_source=facebook&ref=friend123")
+ *
+ * @example
+ * ```tsx
+ * import { Linking } from 'react-native';
+ *
+ * // Listen for deep links
+ * Linking.addEventListener('url', (event) => {
+ * formo.setTrafficSourceFromUrl(event.url);
+ * });
+ *
+ * // Or get initial URL
+ * Linking.getInitialURL().then((url) => {
+ * if (url) formo.setTrafficSourceFromUrl(url);
+ * });
+ * ```
+ */
+ public setTrafficSourceFromUrl(url: string): void {
+ const { parseTrafficSource, storeTrafficSource } = require("./utils/trafficSource");
+ const trafficSource = parseTrafficSource(url);
+ storeTrafficSource(trafficSource);
+ logger.debug("Traffic source set from URL:", trafficSource);
+ }
+
+ /**
+ * Reset the current user session
+ */
+ public reset(): void {
+ this.currentUserId = undefined;
+ storage().remove(LOCAL_ANONYMOUS_ID_KEY);
+ storage().remove(SESSION_USER_ID_KEY);
+ this.session.clear();
+ }
+
+ /**
+ * Clean up resources
+ */
+ public async cleanup(): Promise {
+ logger.info("FormoAnalytics: Cleaning up resources");
+
+ if (this.wagmiHandler) {
+ this.wagmiHandler.cleanup();
+ this.wagmiHandler = undefined;
+ }
+
+ if (this.eventQueue) {
+ await this.eventQueue.cleanup();
+ }
+
+ logger.info("FormoAnalytics: Cleanup complete");
+ }
+
+ /**
+ * Track wallet connect event
+ */
+ async connect(
+ { chainId, address }: { chainId: ChainID; address: Address },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ if (chainId === null || chainId === undefined || Number(chainId) === 0) {
+ logger.warn("Connect: Chain ID cannot be null, undefined, or 0");
+ return;
+ }
+ if (!address) {
+ logger.warn("Connect: Address cannot be empty");
+ return;
+ }
+
+ const checksummedAddress = this.validateAndChecksumAddress(address);
+ if (!checksummedAddress) {
+ logger.warn(`Connect: Invalid address provided ("${address}")`);
+ return;
+ }
+
+ // Track event before updating state so connect events TO excluded chains are tracked
+ await this.trackEvent(
+ EventType.CONNECT,
+ { chainId, address: checksummedAddress },
+ properties,
+ context,
+ callback
+ );
+
+ this.currentChainId = chainId;
+ this.currentAddress = checksummedAddress;
+ }
+
+ /**
+ * Track wallet disconnect event
+ */
+ async disconnect(
+ params?: { chainId?: ChainID; address?: Address },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ const chainId = params?.chainId || this.currentChainId;
+ const address = params?.address || this.currentAddress;
+
+ logger.info("Disconnect: Emitting disconnect event with:", {
+ chainId,
+ address,
+ });
+
+ await this.trackEvent(
+ EventType.DISCONNECT,
+ {
+ ...(chainId && { chainId }),
+ ...(address && { address }),
+ },
+ properties,
+ context,
+ callback
+ );
+
+ this.currentAddress = undefined;
+ this.currentChainId = undefined;
+ }
+
+ /**
+ * Track chain change event
+ */
+ async chain(
+ { chainId, address }: { chainId: ChainID; address?: Address },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ if (!chainId || Number(chainId) === 0) {
+ logger.warn("FormoAnalytics::chain: chainId cannot be empty or 0");
+ return;
+ }
+ if (isNaN(Number(chainId))) {
+ logger.warn("FormoAnalytics::chain: chainId must be a valid number");
+ return;
+ }
+ if (!address && !this.currentAddress) {
+ logger.warn("FormoAnalytics::chain: address was empty and no previous address recorded");
+ return;
+ }
+
+ // Track event before updating currentChainId so shouldTrack uses the previous chain
+ // This ensures chain change events TO excluded chains are still tracked
+ await this.trackEvent(
+ EventType.CHAIN,
+ { chainId, address: address || this.currentAddress },
+ properties,
+ context,
+ callback
+ );
+
+ this.currentChainId = chainId;
+ }
+
+ /**
+ * Track signature event
+ */
+ async signature(
+ {
+ status,
+ chainId,
+ address,
+ message,
+ signatureHash,
+ }: {
+ status: SignatureStatus;
+ chainId: ChainID;
+ address: Address;
+ message: string;
+ signatureHash?: string;
+ },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ if (chainId === null || chainId === undefined || Number(chainId) === 0) {
+ logger.warn("Signature: Chain ID cannot be null, undefined, or 0");
+ return;
+ }
+ if (!address) {
+ logger.warn("Signature: Address cannot be empty");
+ return;
+ }
+ await this.trackEvent(
+ EventType.SIGNATURE,
+ {
+ status,
+ chainId,
+ address,
+ message,
+ ...(signatureHash && { signatureHash }),
+ },
+ properties,
+ context,
+ callback
+ );
+ }
+
+ /**
+ * Track transaction event
+ */
+ async transaction(
+ {
+ status,
+ chainId,
+ address,
+ data,
+ to,
+ value,
+ transactionHash,
+ }: {
+ status: TransactionStatus;
+ chainId: ChainID;
+ address: Address;
+ data?: string;
+ to?: string;
+ value?: string;
+ transactionHash?: string;
+ },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ if (chainId === null || chainId === undefined || Number(chainId) === 0) {
+ logger.warn("Transaction: Chain ID cannot be null, undefined, or 0");
+ return;
+ }
+ if (!address) {
+ logger.warn("Transaction: Address cannot be empty");
+ return;
+ }
+ await this.trackEvent(
+ EventType.TRANSACTION,
+ {
+ status,
+ chainId,
+ address,
+ data,
+ to,
+ value,
+ ...(transactionHash && { transactionHash }),
+ },
+ properties,
+ context,
+ callback
+ );
+ }
+
+ /**
+ * Track identify event
+ */
+ async identify(
+ params: {
+ address: Address;
+ providerName?: string;
+ userId?: string;
+ rdns?: string;
+ },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ try {
+ const { userId, address, providerName, rdns } = params;
+ logger.info("Identify", address, userId, providerName, rdns);
+
+ let validAddress: Address | undefined = undefined;
+ if (address) {
+ validAddress = this.validateAndChecksumAddress(address);
+ if (!validAddress) {
+ logger.warn(`Identify: Invalid address provided ("${address}")`);
+ return;
+ }
+ this.currentAddress = validAddress;
+ } else {
+ this.currentAddress = undefined;
+ }
+
+ if (userId) {
+ this.currentUserId = userId;
+ storage().set(SESSION_USER_ID_KEY, userId);
+ }
+
+ // Check for duplicate identify
+ const isAlreadyIdentified = validAddress
+ ? this.session.isWalletIdentified(validAddress, rdns || "")
+ : false;
+
+ if (isAlreadyIdentified) {
+ logger.info(
+ `Identify: Wallet ${providerName || "Unknown"} with address ${validAddress} already identified`
+ );
+ return;
+ }
+
+ // Mark as identified
+ if (validAddress) {
+ this.session.markWalletIdentified(validAddress, rdns || "");
+ }
+
+ await this.trackEvent(
+ EventType.IDENTIFY,
+ { address: validAddress, providerName, userId, rdns },
+ properties,
+ context,
+ callback
+ );
+ } catch (e) {
+ logger.log("identify error", e);
+ }
+ }
+
+ /**
+ * Track detect wallet event
+ */
+ async detect(
+ { providerName, rdns }: { providerName: string; rdns: string },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ if (this.session.isWalletDetected(rdns)) {
+ logger.warn(`Detect: Wallet ${providerName} already detected in this session`);
+ return;
+ }
+
+ this.session.markWalletDetected(rdns);
+ await this.trackEvent(
+ EventType.DETECT,
+ { providerName, rdns },
+ properties,
+ context,
+ callback
+ );
+ }
+
+ /**
+ * Track custom event
+ */
+ async track(
+ event: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ await this.trackEvent(
+ EventType.TRACK,
+ { event },
+ properties,
+ context,
+ callback
+ );
+ }
+
+ /**
+ * Opt out of tracking
+ */
+ public optOutTracking(): void {
+ logger.info("Opting out of tracking");
+ setConsentFlag(this.writeKey, CONSENT_OPT_OUT_KEY, "true");
+ this.eventQueue.clear();
+ this.reset();
+ logger.info("Successfully opted out of tracking");
+ }
+
+ /**
+ * Opt back into tracking
+ */
+ public optInTracking(): void {
+ logger.info("Opting back into tracking");
+ removeConsentFlag(this.writeKey, CONSENT_OPT_OUT_KEY);
+ logger.info("Successfully opted back into tracking");
+ }
+
+ /**
+ * Check if user has opted out
+ */
+ public hasOptedOutTracking(): boolean {
+ return getConsentFlag(this.writeKey, CONSENT_OPT_OUT_KEY) === "true";
+ }
+
+ /**
+ * Check if autocapture is enabled for event type
+ */
+ public isAutocaptureEnabled(
+ eventType: "connect" | "disconnect" | "signature" | "transaction" | "chain"
+ ): boolean {
+ if (this.options.autocapture === undefined) {
+ return true;
+ }
+
+ if (typeof this.options.autocapture === "boolean") {
+ return this.options.autocapture;
+ }
+
+ if (
+ this.options.autocapture !== null &&
+ typeof this.options.autocapture === "object"
+ ) {
+ const eventConfig = this.options.autocapture[eventType];
+ return eventConfig !== false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Internal method to track events
+ * This is the single enforcement point for shouldTrack() - all public tracking
+ * methods (track, screen, connect, etc.) route through here
+ */
+ private async trackEvent(
+ type: TEventType,
+ payload?: Record,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ try {
+ if (!this.shouldTrack()) {
+ logger.info(`Skipping ${type} event due to tracking configuration`);
+ return;
+ }
+
+ await this.eventManager.addEvent(
+ {
+ type,
+ ...payload,
+ properties,
+ context,
+ callback,
+ } as any,
+ this.currentAddress,
+ this.currentUserId
+ );
+ } catch (error) {
+ logger.error("Error tracking event:", error);
+ }
+ }
+
+ /**
+ * Check if tracking should be enabled
+ */
+ private shouldTrack(): boolean {
+ // Check consent
+ if (this.hasOptedOutTracking()) {
+ return false;
+ }
+
+ // Check tracking option
+ if (typeof this.options.tracking === "boolean") {
+ return this.options.tracking;
+ }
+
+ // Handle object configuration
+ if (
+ this.options.tracking !== null &&
+ typeof this.options.tracking === "object" &&
+ !Array.isArray(this.options.tracking)
+ ) {
+ const { excludeChains = [] } = this.options.tracking as TrackingOptions;
+
+ if (
+ excludeChains.length > 0 &&
+ this.currentChainId &&
+ excludeChains.includes(this.currentChainId)
+ ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ // Default: track
+ return true;
+ }
+
+ /**
+ * Validate and checksum address
+ */
+ private validateAndChecksumAddress(address: string): Address | undefined {
+ const validAddress = getValidAddress(address);
+ return validAddress ? toChecksumAddress(validAddress) : undefined;
+ }
+
+ /**
+ * Flush pending events
+ */
+ public async flush(): Promise {
+ await this.eventQueue.flush();
+ }
+}
diff --git a/src/FormoAnalyticsProvider.tsx b/src/FormoAnalyticsProvider.tsx
new file mode 100644
index 0000000..93aa443
--- /dev/null
+++ b/src/FormoAnalyticsProvider.tsx
@@ -0,0 +1,314 @@
+import React, {
+ createContext,
+ useContext,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
+ FC,
+} from "react";
+import { FormoAnalytics } from "./FormoAnalytics";
+import { initStorageManager, AsyncStorageInterface } from "./lib/storage";
+import { logger } from "./lib/logger";
+import { FormoAnalyticsProviderProps, IFormoAnalytics } from "./types";
+
+// Default context with no-op methods
+const defaultContext: IFormoAnalytics = {
+ chain: () => Promise.resolve(),
+ screen: () => Promise.resolve(),
+ reset: () => {},
+ cleanup: () => Promise.resolve(),
+ detect: () => Promise.resolve(),
+ connect: () => Promise.resolve(),
+ disconnect: () => Promise.resolve(),
+ signature: () => Promise.resolve(),
+ transaction: () => Promise.resolve(),
+ identify: () => Promise.resolve(),
+ track: () => Promise.resolve(),
+ setTrafficSourceFromUrl: () => {},
+ optOutTracking: () => {},
+ optInTracking: () => {},
+ hasOptedOutTracking: () => false,
+};
+
+export const FormoAnalyticsContext =
+ createContext(defaultContext);
+
+export interface FormoAnalyticsProviderPropsWithStorage
+ extends FormoAnalyticsProviderProps {
+ /**
+ * AsyncStorage instance from @react-native-async-storage/async-storage
+ * Required for persistent storage
+ */
+ asyncStorage?: AsyncStorageInterface;
+ /**
+ * Callback when SDK is ready
+ * Note: Use useCallback to avoid re-initialization on every render
+ */
+ onReady?: (sdk: IFormoAnalytics) => void;
+ /**
+ * Callback when SDK initialization fails
+ * Note: Use useCallback to avoid re-initialization on every render
+ */
+ onError?: (error: Error) => void;
+}
+
+/**
+ * Formo Analytics Provider for React Native
+ *
+ * Wraps your app to provide analytics context
+ *
+ * @example
+ * ```tsx
+ * import AsyncStorage from '@react-native-async-storage/async-storage';
+ * import { FormoAnalyticsProvider } from '@formo/react-native-analytics';
+ *
+ * function App() {
+ * return (
+ *
+ *
+ *
+ * );
+ * }
+ * ```
+ */
+export const FormoAnalyticsProvider: FC = (
+ props
+) => {
+ const { writeKey, disabled = false, children } = props;
+
+ if (!writeKey) {
+ logger.error("FormoAnalyticsProvider: No Write Key provided");
+ return (
+
+ {children}
+
+ );
+ }
+
+ if (disabled) {
+ logger.warn("FormoAnalytics is disabled");
+ return (
+
+ {children}
+
+ );
+ }
+
+ return ;
+};
+
+const InitializedAnalytics: FC = ({
+ writeKey,
+ options,
+ asyncStorage,
+ onReady,
+ onError,
+ children,
+}) => {
+ const [sdk, setSdk] = useState(defaultContext);
+ const sdkRef = useRef(defaultContext);
+ const storageInitKeyRef = useRef(null);
+ const cleanupPromiseRef = useRef>(Promise.resolve());
+ const initializationIdRef = useRef(0);
+
+ // Only initialize storage manager when writeKey changes, not on every render
+ if (storageInitKeyRef.current !== writeKey) {
+ initStorageManager(writeKey);
+ storageInitKeyRef.current = writeKey;
+ }
+
+ // Store callbacks and options in refs to avoid re-initialization when references change
+ // This fixes the issue where inline arrow functions cause repeated SDK init
+ const onReadyRef = useRef(onReady);
+ const onErrorRef = useRef(onError);
+ const optionsRef = useRef(options);
+
+ // Update refs when values change (without triggering effect)
+ useEffect(() => {
+ onReadyRef.current = onReady;
+ }, [onReady]);
+
+ useEffect(() => {
+ onErrorRef.current = onError;
+ }, [onError]);
+
+ useEffect(() => {
+ optionsRef.current = options;
+ }, [options]);
+
+ // Extract individual option values to avoid reference equality issues with options object
+ const tracking = options?.tracking;
+ const autocapture = options?.autocapture;
+ const apiHost = options?.apiHost;
+ const flushAt = options?.flushAt;
+ const flushInterval = options?.flushInterval;
+ const retryCount = options?.retryCount;
+ const maxQueueSize = options?.maxQueueSize;
+ const loggerOption = options?.logger;
+ const app = options?.app;
+ const hasReady = !!options?.ready;
+ const wagmiConfig = options?.wagmi?.config;
+ const wagmiQueryClient = options?.wagmi?.queryClient;
+
+ // Create stable key from serializable options
+ const optionsKey = useMemo(() => {
+ const serializableOptions = {
+ tracking,
+ autocapture,
+ apiHost,
+ flushAt,
+ flushInterval,
+ retryCount,
+ maxQueueSize,
+ logger: loggerOption,
+ app,
+ hasReady,
+ };
+
+ try {
+ return JSON.stringify(serializableOptions);
+ } catch (error) {
+ logger.warn("Failed to serialize options, using timestamp", error);
+ return Date.now().toString();
+ }
+ }, [tracking, autocapture, apiHost, flushAt, flushInterval, retryCount, maxQueueSize, loggerOption, app, hasReady]);
+
+ useEffect(() => {
+ // Increment initialization ID to track which initialization is current
+ const currentInitId = ++initializationIdRef.current;
+ let isCleanedUp = false;
+
+ const initialize = async () => {
+ // Wait for any pending cleanup to complete before re-initializing
+ // This prevents race conditions between cleanup and init
+ await cleanupPromiseRef.current;
+
+ // Check if this initialization is still current after awaiting cleanup
+ if (currentInitId !== initializationIdRef.current || isCleanedUp) {
+ logger.debug("Skipping stale initialization");
+ return;
+ }
+
+ // Clean up existing SDK and await flush completion
+ if (sdkRef.current && sdkRef.current !== defaultContext) {
+ logger.log("Cleaning up existing FormoAnalytics SDK instance");
+ const cleanup = sdkRef.current.cleanup();
+ cleanupPromiseRef.current = cleanup;
+ await cleanup;
+ sdkRef.current = defaultContext;
+ setSdk(defaultContext);
+ }
+
+ // Check again after cleanup
+ if (currentInitId !== initializationIdRef.current || isCleanedUp) {
+ logger.debug("Skipping stale initialization after cleanup");
+ return;
+ }
+
+ try {
+ // Use optionsRef.current to ensure we have the latest options
+ const sdkInstance = await FormoAnalytics.init(
+ writeKey,
+ optionsRef.current,
+ asyncStorage
+ );
+
+ // Verify this initialization is still current
+ if (currentInitId !== initializationIdRef.current || isCleanedUp) {
+ logger.log("Initialization superseded, cleaning up new instance");
+ await sdkInstance.cleanup();
+ return;
+ }
+
+ setSdk(sdkInstance);
+ sdkRef.current = sdkInstance;
+ logger.log("Successfully initialized FormoAnalytics SDK");
+
+ // Call onReady callback using the ref (stable reference)
+ onReadyRef.current?.(sdkInstance);
+ } catch (error) {
+ if (currentInitId === initializationIdRef.current && !isCleanedUp) {
+ logger.error("Failed to initialize FormoAnalytics SDK", error);
+ // Call onError callback using the ref (stable reference)
+ onErrorRef.current?.(error instanceof Error ? error : new Error(String(error)));
+ }
+ }
+ };
+
+ initialize();
+
+ return () => {
+ isCleanedUp = true;
+
+ if (sdkRef.current && sdkRef.current !== defaultContext) {
+ logger.log("Cleaning up FormoAnalytics SDK instance");
+ // Store cleanup promise so next initialization can await it
+ const cleanup = sdkRef.current.cleanup().catch((error) => {
+ logger.error("Error during SDK cleanup:", error);
+ });
+ cleanupPromiseRef.current = cleanup;
+ sdkRef.current = defaultContext;
+ }
+ };
+ // Note: onReady and onError are NOT in the dependency array
+ // They are accessed via refs to prevent re-initialization
+ // wagmiConfig and wagmiQueryClient are tracked separately since they're not serializable
+ }, [writeKey, optionsKey, asyncStorage, wagmiConfig, wagmiQueryClient]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+/**
+ * Hook to access Formo Analytics
+ *
+ * @example
+ * ```tsx
+ * import { useFormo } from '@formo/react-native-analytics';
+ *
+ * function MyScreen() {
+ * const formo = useFormo();
+ *
+ * useEffect(() => {
+ * formo.screen('Home');
+ * }, []);
+ *
+ * const handleButtonPress = () => {
+ * formo.track('Button Pressed', { buttonName: 'signup' });
+ * };
+ *
+ * return ;
+ * }
+ * ```
+ */
+// Track if the useFormo warning has been logged to avoid console spam
+let hasLoggedUseFormoWarning = false;
+
+export const useFormo = (): IFormoAnalytics => {
+ const context = useContext(FormoAnalyticsContext);
+
+ // Check if SDK has been initialized (context will be defaultContext before init completes)
+ // Only log the warning once to avoid flooding the console during async initialization
+ if (context === defaultContext && !hasLoggedUseFormoWarning) {
+ hasLoggedUseFormoWarning = true;
+ logger.warn(
+ "useFormo called before SDK initialization complete. " +
+ "Ensure FormoAnalyticsProvider is mounted and writeKey is provided."
+ );
+ }
+
+ // Reset the warning flag when SDK is initialized so it can warn again after a reset
+ if (context !== defaultContext) {
+ hasLoggedUseFormoWarning = false;
+ }
+
+ return context;
+};
diff --git a/src/__tests__/FormoAnalytics.test.ts b/src/__tests__/FormoAnalytics.test.ts
new file mode 100644
index 0000000..41f4090
--- /dev/null
+++ b/src/__tests__/FormoAnalytics.test.ts
@@ -0,0 +1,430 @@
+import { SignatureStatus, TransactionStatus } from '../types';
+
+// Mock instances that persist across tests
+const mockStorageInstance = {
+ get: jest.fn(),
+ set: jest.fn(),
+ remove: jest.fn(),
+ isAvailable: jest.fn(),
+};
+
+const mockStorageManager = {
+ initialize: jest.fn(),
+ getPrimaryStorage: jest.fn(),
+ getStorage: jest.fn(),
+};
+
+const mockEventManager = {
+ addEvent: jest.fn(),
+};
+
+const mockEventQueue = {
+ flush: jest.fn(),
+ clear: jest.fn(),
+ cleanup: jest.fn(),
+};
+
+const mockSession = {
+ isWalletDetected: jest.fn(),
+ isWalletIdentified: jest.fn(),
+ markWalletDetected: jest.fn(),
+ markWalletIdentified: jest.fn(),
+ clear: jest.fn(),
+};
+
+// Mock dependencies
+jest.mock('../lib/storage', () => ({
+ __esModule: true,
+ initStorageManager: jest.fn(),
+ storage: jest.fn(),
+ getStorageManager: jest.fn(),
+}));
+
+jest.mock('../lib/event', () => ({
+ __esModule: true,
+ EventManager: jest.fn(),
+ EventQueue: jest.fn(),
+}));
+
+jest.mock('../lib/session', () => ({
+ __esModule: true,
+ FormoAnalyticsSession: jest.fn(),
+}));
+
+jest.mock('../lib/consent', () => ({
+ __esModule: true,
+ setConsentFlag: jest.fn(),
+ getConsentFlag: jest.fn(),
+ removeConsentFlag: jest.fn(),
+}));
+
+jest.mock('../lib/logger', () => ({
+ __esModule: true,
+ logger: {
+ info: jest.fn(),
+ warn: jest.fn(),
+ error: jest.fn(),
+ debug: jest.fn(),
+ log: jest.fn(),
+ },
+ Logger: {
+ init: jest.fn(),
+ },
+}));
+
+// Import after mocking
+import { FormoAnalytics } from '../FormoAnalytics';
+import { initStorageManager, storage } from '../lib/storage';
+import { EventManager, EventQueue } from '../lib/event';
+import { FormoAnalyticsSession } from '../lib/session';
+import { setConsentFlag, getConsentFlag, removeConsentFlag } from '../lib/consent';
+
+// Helper to setup all mock implementations
+const setupMocks = () => {
+ // Storage mocks
+ mockStorageInstance.get.mockReturnValue(null);
+ mockStorageInstance.set.mockReturnValue(undefined);
+ mockStorageInstance.remove.mockReturnValue(undefined);
+ mockStorageInstance.isAvailable.mockReturnValue(true);
+
+ mockStorageManager.initialize.mockResolvedValue(undefined);
+ mockStorageManager.getPrimaryStorage.mockReturnValue(mockStorageInstance);
+ mockStorageManager.getStorage.mockReturnValue(mockStorageInstance);
+
+ (initStorageManager as jest.Mock).mockReturnValue(mockStorageManager);
+ (storage as jest.Mock).mockReturnValue(mockStorageInstance);
+
+ // Event mocks
+ mockEventManager.addEvent.mockResolvedValue(undefined);
+ mockEventQueue.flush.mockResolvedValue(undefined);
+ mockEventQueue.clear.mockReturnValue(undefined);
+ mockEventQueue.cleanup.mockResolvedValue(undefined);
+
+ (EventManager as jest.Mock).mockImplementation(() => mockEventManager);
+ (EventQueue as jest.Mock).mockImplementation(() => mockEventQueue);
+
+ // Session mocks
+ mockSession.isWalletDetected.mockReturnValue(false);
+ mockSession.isWalletIdentified.mockReturnValue(false);
+ mockSession.markWalletDetected.mockReturnValue(undefined);
+ mockSession.markWalletIdentified.mockReturnValue(undefined);
+ mockSession.clear.mockReturnValue(undefined);
+
+ (FormoAnalyticsSession as jest.Mock).mockImplementation(() => mockSession);
+
+ // Consent mocks
+ (getConsentFlag as jest.Mock).mockReturnValue(null);
+};
+
+describe('FormoAnalytics', () => {
+ let analytics: FormoAnalytics;
+ const writeKey = 'test-write-key';
+
+ beforeEach(async () => {
+ // Re-setup mock implementations after clearMocks
+ setupMocks();
+ analytics = await FormoAnalytics.init(writeKey);
+ });
+
+ describe('init()', () => {
+ it('should initialize with writeKey', async () => {
+ const instance = await FormoAnalytics.init('my-key');
+ expect(instance.config.writeKey).toBe('my-key');
+ });
+
+ it('should call initStorageManager with writeKey', async () => {
+ await FormoAnalytics.init('my-key');
+ expect(initStorageManager).toHaveBeenCalledWith('my-key');
+ });
+
+ it('should call ready callback if provided', async () => {
+ const readyCallback = jest.fn();
+ await FormoAnalytics.init('my-key', { ready: readyCallback });
+ expect(readyCallback).toHaveBeenCalled();
+ });
+
+ it('should initialize storage with asyncStorage if provided', async () => {
+ const mockAsyncStorage = {
+ getItem: jest.fn(),
+ setItem: jest.fn(),
+ removeItem: jest.fn(),
+ };
+
+ await FormoAnalytics.init('my-key', {}, mockAsyncStorage as any);
+
+ expect(mockStorageManager.initialize).toHaveBeenCalledWith(mockAsyncStorage);
+ });
+ });
+
+ describe('connect()', () => {
+ it('should not track if chainId is null', async () => {
+ await analytics.connect({ chainId: null as any, address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2' });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if chainId is 0', async () => {
+ await analytics.connect({ chainId: 0, address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2' });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if address is empty', async () => {
+ await analytics.connect({ chainId: 1, address: '' });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if address is invalid', async () => {
+ await analytics.connect({ chainId: 1, address: 'invalid-address' });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should track valid connect event', async () => {
+ await analytics.connect({
+ chainId: 1,
+ address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2',
+ });
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+
+ it('should update currentChainId and currentAddress after connect', async () => {
+ await analytics.connect({
+ chainId: 1,
+ address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2',
+ });
+
+ expect(analytics.currentChainId).toBe(1);
+ expect(analytics.currentAddress).toBeDefined();
+ });
+ });
+
+ describe('disconnect()', () => {
+ it('should track disconnect event', async () => {
+ await analytics.disconnect();
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+
+ it('should clear currentAddress and currentChainId after disconnect', async () => {
+ analytics.currentChainId = 1;
+ analytics.currentAddress = '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2';
+
+ await analytics.disconnect();
+
+ expect(analytics.currentChainId).toBeUndefined();
+ expect(analytics.currentAddress).toBeUndefined();
+ });
+ });
+
+ describe('chain()', () => {
+ beforeEach(async () => {
+ // Set up a connected state
+ analytics.currentAddress = '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2';
+ analytics.currentChainId = 1;
+ });
+
+ it('should not track if chainId is empty', async () => {
+ await analytics.chain({ chainId: 0 });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if chainId is invalid', async () => {
+ await analytics.chain({ chainId: NaN });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if no address is available', async () => {
+ analytics.currentAddress = undefined;
+
+ await analytics.chain({ chainId: 137 });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should track valid chain change event', async () => {
+ await analytics.chain({ chainId: 137 });
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+
+ it('should update currentChainId after chain change', async () => {
+ await analytics.chain({ chainId: 137 });
+
+ expect(analytics.currentChainId).toBe(137);
+ });
+ });
+
+ describe('signature()', () => {
+ it('should not track if chainId is invalid', async () => {
+ await analytics.signature({
+ status: SignatureStatus.REQUESTED,
+ chainId: 0,
+ address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2',
+ message: 'test message',
+ });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if address is empty', async () => {
+ await analytics.signature({
+ status: SignatureStatus.REQUESTED,
+ chainId: 1,
+ address: '',
+ message: 'test message',
+ });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should track valid signature event', async () => {
+ await analytics.signature({
+ status: SignatureStatus.CONFIRMED,
+ chainId: 1,
+ address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2',
+ message: 'test message',
+ signatureHash: '0xabc123',
+ });
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+ });
+
+ describe('transaction()', () => {
+ it('should not track if chainId is invalid', async () => {
+ await analytics.transaction({
+ status: TransactionStatus.STARTED,
+ chainId: 0,
+ address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2',
+ });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should not track if address is empty', async () => {
+ await analytics.transaction({
+ status: TransactionStatus.STARTED,
+ chainId: 1,
+ address: '',
+ });
+
+ expect(mockEventManager.addEvent).not.toHaveBeenCalled();
+ });
+
+ it('should track valid transaction event', async () => {
+ await analytics.transaction({
+ status: TransactionStatus.CONFIRMED,
+ chainId: 1,
+ address: '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2',
+ transactionHash: '0xdef456',
+ value: '1000000000000000000',
+ });
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+ });
+
+ describe('track()', () => {
+ it('should track custom events', async () => {
+ await analytics.track('button_click', { button_id: 'submit' });
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+ });
+
+ describe('screen()', () => {
+ it('should track screen views', async () => {
+ await analytics.screen('HomeScreen', { section: 'featured' });
+
+ expect(mockEventManager.addEvent).toHaveBeenCalled();
+ });
+ });
+
+ describe('opt-out tracking', () => {
+ it('should return false for hasOptedOutTracking by default', () => {
+ expect(analytics.hasOptedOutTracking()).toBe(false);
+ });
+
+ it('should set opt-out flag when optOutTracking is called', async () => {
+ analytics.optOutTracking();
+
+ expect(setConsentFlag).toHaveBeenCalled();
+ });
+
+ it('should remove opt-out flag when optInTracking is called', () => {
+ analytics.optInTracking();
+
+ expect(removeConsentFlag).toHaveBeenCalled();
+ });
+ });
+
+ describe('isAutocaptureEnabled()', () => {
+ it('should return true by default', () => {
+ expect(analytics.isAutocaptureEnabled('connect')).toBe(true);
+ expect(analytics.isAutocaptureEnabled('disconnect')).toBe(true);
+ expect(analytics.isAutocaptureEnabled('signature')).toBe(true);
+ expect(analytics.isAutocaptureEnabled('transaction')).toBe(true);
+ expect(analytics.isAutocaptureEnabled('chain')).toBe(true);
+ });
+
+ it('should return false when autocapture is disabled globally', async () => {
+ const instance = await FormoAnalytics.init('key', { autocapture: false });
+
+ expect(instance.isAutocaptureEnabled('connect')).toBe(false);
+ expect(instance.isAutocaptureEnabled('transaction')).toBe(false);
+ });
+
+ it('should return false for specific disabled event types', async () => {
+ const instance = await FormoAnalytics.init('key', {
+ autocapture: {
+ connect: true,
+ disconnect: false,
+ signature: true,
+ transaction: false,
+ chain: true,
+ },
+ });
+
+ expect(instance.isAutocaptureEnabled('connect')).toBe(true);
+ expect(instance.isAutocaptureEnabled('disconnect')).toBe(false);
+ expect(instance.isAutocaptureEnabled('transaction')).toBe(false);
+ });
+ });
+
+ describe('reset()', () => {
+ it('should clear currentUserId', () => {
+ analytics.currentUserId = 'user-123';
+
+ analytics.reset();
+
+ expect(analytics.currentUserId).toBeUndefined();
+ });
+
+ it('should remove storage keys', () => {
+ analytics.reset();
+
+ expect(mockStorageInstance.remove).toHaveBeenCalled();
+ });
+ });
+
+ describe('flush()', () => {
+ it('should call eventQueue.flush()', async () => {
+ await analytics.flush();
+
+ expect(mockEventQueue.flush).toHaveBeenCalled();
+ });
+ });
+
+ describe('cleanup()', () => {
+ it('should call eventQueue.cleanup()', async () => {
+ await analytics.cleanup();
+
+ expect(mockEventQueue.cleanup).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/__tests__/address.test.ts b/src/__tests__/address.test.ts
new file mode 100644
index 0000000..fcc6940
--- /dev/null
+++ b/src/__tests__/address.test.ts
@@ -0,0 +1,139 @@
+import {
+ isValidAddress,
+ toChecksumAddress,
+ getValidAddress,
+ isBlockedAddress,
+} from '../utils/address';
+
+describe('address utilities', () => {
+ describe('isValidAddress()', () => {
+ it('should return true for valid lowercase address', () => {
+ expect(isValidAddress('0x742d35cc6634c0532925a3b844bc9e7595f3f6d2')).toBe(true);
+ });
+
+ it('should return true for valid uppercase address', () => {
+ expect(isValidAddress('0x742D35CC6634C0532925A3B844BC9E7595F3F6D2')).toBe(true);
+ });
+
+ it('should return true for valid mixed case address', () => {
+ expect(isValidAddress('0x742d35Cc6634C0532925a3b844Bc9e7595F3f6d2')).toBe(true);
+ });
+
+ it('should return false for address without 0x prefix', () => {
+ expect(isValidAddress('742d35cc6634c0532925a3b844bc9e7595f3f6d2')).toBe(false);
+ });
+
+ it('should return false for address that is too short', () => {
+ expect(isValidAddress('0x742d35cc6634c0532925a3b844bc9e7595f3f6')).toBe(false);
+ });
+
+ it('should return false for address that is too long', () => {
+ expect(isValidAddress('0x742d35cc6634c0532925a3b844bc9e7595f3f6d2a')).toBe(false);
+ });
+
+ it('should return false for address with invalid characters', () => {
+ expect(isValidAddress('0x742d35cc6634c0532925a3b844bc9e7595f3f6gz')).toBe(false);
+ });
+
+ it('should return false for empty string', () => {
+ expect(isValidAddress('')).toBe(false);
+ });
+
+ it('should return false for null/undefined', () => {
+ expect(isValidAddress(null as unknown as string)).toBe(false);
+ expect(isValidAddress(undefined as unknown as string)).toBe(false);
+ });
+
+ it('should return false for non-string values', () => {
+ expect(isValidAddress(123 as unknown as string)).toBe(false);
+ expect(isValidAddress({} as unknown as string)).toBe(false);
+ });
+ });
+
+ describe('toChecksumAddress()', () => {
+ it('should convert to EIP-55 checksum format', () => {
+ const input = '0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed';
+ const expected = '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed';
+ expect(toChecksumAddress(input)).toBe(expected);
+ });
+
+ it('should handle already checksummed address', () => {
+ const checksummed = '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed';
+ expect(toChecksumAddress(checksummed)).toBe(checksummed);
+ });
+
+ it('should handle uppercase address', () => {
+ const uppercase = '0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED';
+ const expected = '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed';
+ expect(toChecksumAddress(uppercase)).toBe(expected);
+ });
+
+ it('should return invalid address unchanged', () => {
+ const invalid = 'not-an-address';
+ expect(toChecksumAddress(invalid)).toBe(invalid);
+ });
+
+ it('should handle zero address', () => {
+ const zeroAddress = '0x0000000000000000000000000000000000000000';
+ expect(toChecksumAddress(zeroAddress)).toBe(zeroAddress);
+ });
+
+ it('should handle well-known addresses correctly', () => {
+ // Vitalik's address (well-known checksum)
+ const input = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045';
+ const expected = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045';
+ expect(toChecksumAddress(input)).toBe(expected);
+ });
+ });
+
+ describe('getValidAddress()', () => {
+ it('should return trimmed address for valid input', () => {
+ const input = ' 0x742d35cc6634c0532925a3b844bc9e7595f3f6d2 ';
+ expect(getValidAddress(input)).toBe('0x742d35cc6634c0532925a3b844bc9e7595f3f6d2');
+ });
+
+ it('should return null for invalid address', () => {
+ expect(getValidAddress('invalid')).toBeNull();
+ });
+
+ it('should return null for empty string', () => {
+ expect(getValidAddress('')).toBeNull();
+ });
+
+ it('should return null for null', () => {
+ expect(getValidAddress(null)).toBeNull();
+ });
+
+ it('should return null for undefined', () => {
+ expect(getValidAddress(undefined)).toBeNull();
+ });
+
+ it('should return valid address without modification', () => {
+ const valid = '0x742d35Cc6634C0532925a3b844Bc9e7595F3f6d2';
+ expect(getValidAddress(valid)).toBe(valid);
+ });
+ });
+
+ describe('isBlockedAddress()', () => {
+ it('should return true for zero address', () => {
+ expect(isBlockedAddress('0x0000000000000000000000000000000000000000')).toBe(true);
+ });
+
+ it('should return true for dead address', () => {
+ expect(isBlockedAddress('0x000000000000000000000000000000000000dead')).toBe(true);
+ });
+
+ it('should return true for blocked addresses regardless of case', () => {
+ expect(isBlockedAddress('0x0000000000000000000000000000000000000000')).toBe(true);
+ expect(isBlockedAddress('0x000000000000000000000000000000000000DEAD')).toBe(true);
+ });
+
+ it('should return false for normal addresses', () => {
+ expect(isBlockedAddress('0x742d35cc6634c0532925a3b844bc9e7595f3f6d2')).toBe(false);
+ });
+
+ it('should return false for addresses similar to blocked ones', () => {
+ expect(isBlockedAddress('0x0000000000000000000000000000000000000001')).toBe(false);
+ });
+ });
+});
diff --git a/src/__tests__/consent.test.ts b/src/__tests__/consent.test.ts
new file mode 100644
index 0000000..d8639de
--- /dev/null
+++ b/src/__tests__/consent.test.ts
@@ -0,0 +1,112 @@
+import {
+ setConsentFlag,
+ getConsentFlag,
+ removeConsentFlag,
+} from '../lib/consent';
+import { storage } from '../lib/storage';
+
+// Mock the storage module
+jest.mock('../lib/storage', () => ({
+ storage: jest.fn(() => ({
+ get: jest.fn(),
+ set: jest.fn(),
+ remove: jest.fn(),
+ })),
+}));
+
+describe('consent utilities', () => {
+ let mockStorage: {
+ get: jest.Mock;
+ set: jest.Mock;
+ remove: jest.Mock;
+ };
+
+ beforeEach(() => {
+ mockStorage = {
+ get: jest.fn(),
+ set: jest.fn(),
+ remove: jest.fn(),
+ };
+ (storage as jest.Mock).mockReturnValue(mockStorage);
+ });
+
+ describe('setConsentFlag()', () => {
+ it('should set a consent flag in storage', () => {
+ setConsentFlag('write-key', 'opt_out', 'true');
+
+ expect(mockStorage.set).toHaveBeenCalledWith('consent_opt_out', 'true');
+ });
+
+ it('should handle different flag values', () => {
+ setConsentFlag('write-key', 'tracking', 'false');
+
+ expect(mockStorage.set).toHaveBeenCalledWith('consent_tracking', 'false');
+ });
+
+ it('should not throw when storage fails', () => {
+ mockStorage.set.mockImplementation(() => {
+ throw new Error('Storage error');
+ });
+
+ expect(() => setConsentFlag('write-key', 'opt_out', 'true')).not.toThrow();
+ });
+ });
+
+ describe('getConsentFlag()', () => {
+ it('should get a consent flag from storage', () => {
+ mockStorage.get.mockReturnValue('true');
+
+ const result = getConsentFlag('write-key', 'opt_out');
+
+ expect(mockStorage.get).toHaveBeenCalledWith('consent_opt_out');
+ expect(result).toBe('true');
+ });
+
+ it('should return null when flag does not exist', () => {
+ mockStorage.get.mockReturnValue(null);
+
+ const result = getConsentFlag('write-key', 'opt_out');
+
+ expect(result).toBeNull();
+ });
+
+ it('should return null when storage fails', () => {
+ mockStorage.get.mockImplementation(() => {
+ throw new Error('Storage error');
+ });
+
+ const result = getConsentFlag('write-key', 'opt_out');
+
+ expect(result).toBeNull();
+ });
+ });
+
+ describe('removeConsentFlag()', () => {
+ it('should remove a consent flag from storage', () => {
+ removeConsentFlag('write-key', 'opt_out');
+
+ expect(mockStorage.remove).toHaveBeenCalledWith('consent_opt_out');
+ });
+
+ it('should not throw when storage fails', () => {
+ mockStorage.remove.mockImplementation(() => {
+ throw new Error('Storage error');
+ });
+
+ expect(() => removeConsentFlag('write-key', 'opt_out')).not.toThrow();
+ });
+ });
+
+ describe('key generation', () => {
+ it('should use consistent key format', () => {
+ setConsentFlag('my-key', 'analytics', 'enabled');
+ getConsentFlag('my-key', 'analytics');
+ removeConsentFlag('my-key', 'analytics');
+
+ // All operations should use the same key format
+ expect(mockStorage.set).toHaveBeenCalledWith('consent_analytics', 'enabled');
+ expect(mockStorage.get).toHaveBeenCalledWith('consent_analytics');
+ expect(mockStorage.remove).toHaveBeenCalledWith('consent_analytics');
+ });
+ });
+});
diff --git a/src/__tests__/hash.test.ts b/src/__tests__/hash.test.ts
new file mode 100644
index 0000000..66930fd
--- /dev/null
+++ b/src/__tests__/hash.test.ts
@@ -0,0 +1,83 @@
+import { hash, generateUUID } from '../utils/hash';
+
+describe('hash utilities', () => {
+ describe('hash()', () => {
+ it('should return a 64-character hex string (full SHA-256)', async () => {
+ const result = await hash('test input');
+ expect(result).toHaveLength(64);
+ expect(result).toMatch(/^[a-f0-9]{64}$/);
+ });
+
+ it('should produce consistent hashes for the same input', async () => {
+ const input = 'consistent input';
+ const hash1 = await hash(input);
+ const hash2 = await hash(input);
+ expect(hash1).toBe(hash2);
+ });
+
+ it('should produce different hashes for different inputs', async () => {
+ const hash1 = await hash('input 1');
+ const hash2 = await hash('input 2');
+ expect(hash1).not.toBe(hash2);
+ });
+
+ it('should handle empty string', async () => {
+ const result = await hash('');
+ expect(result).toHaveLength(64);
+ expect(result).toMatch(/^[a-f0-9]{64}$/);
+ });
+
+ it('should handle unicode characters', async () => {
+ const result = await hash('Hello 世界 🌍');
+ expect(result).toHaveLength(64);
+ expect(result).toMatch(/^[a-f0-9]{64}$/);
+ });
+
+ it('should handle long strings', async () => {
+ const longString = 'a'.repeat(10000);
+ const result = await hash(longString);
+ expect(result).toHaveLength(64);
+ expect(result).toMatch(/^[a-f0-9]{64}$/);
+ });
+
+ it('should match known SHA-256 hash', async () => {
+ // SHA-256 of "hello" is well-known
+ const result = await hash('hello');
+ expect(result).toBe('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824');
+ });
+ });
+
+ describe('generateUUID()', () => {
+ it('should return a valid UUID v4 format', () => {
+ const uuid = generateUUID();
+ // UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+ expect(uuid).toMatch(
+ /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
+ );
+ });
+
+ it('should have version 4 in the correct position', () => {
+ const uuid = generateUUID();
+ expect(uuid.charAt(14)).toBe('4');
+ });
+
+ it('should have valid variant bits', () => {
+ const uuid = generateUUID();
+ // Position 19 should be 8, 9, a, or b
+ expect(['8', '9', 'a', 'b']).toContain(uuid.charAt(19));
+ });
+
+ it('should generate unique UUIDs', () => {
+ const uuids = new Set();
+ for (let i = 0; i < 100; i++) {
+ uuids.add(generateUUID());
+ }
+ expect(uuids.size).toBe(100);
+ });
+
+ it('should have the correct length (36 characters with hyphens)', () => {
+ const uuid = generateUUID();
+ expect(uuid).toHaveLength(36);
+ });
+ });
+});
diff --git a/src/__tests__/helpers.test.ts b/src/__tests__/helpers.test.ts
new file mode 100644
index 0000000..9733ae7
--- /dev/null
+++ b/src/__tests__/helpers.test.ts
@@ -0,0 +1,267 @@
+import {
+ clampNumber,
+ isUndefined,
+ toSnakeCase,
+ mergeDeepRight,
+ getActionDescriptor,
+ isNetworkError,
+} from '../utils/helpers';
+
+describe('helper utilities', () => {
+ describe('clampNumber()', () => {
+ it('should return value when within range', () => {
+ expect(clampNumber(5, 10, 0)).toBe(5);
+ });
+
+ it('should return min when value is below min', () => {
+ expect(clampNumber(-5, 10, 0)).toBe(0);
+ });
+
+ it('should return max when value is above max', () => {
+ expect(clampNumber(15, 10, 0)).toBe(10);
+ });
+
+ it('should handle equal min and max', () => {
+ expect(clampNumber(5, 5, 5)).toBe(5);
+ });
+
+ it('should handle negative ranges', () => {
+ expect(clampNumber(-15, -5, -20)).toBe(-15);
+ expect(clampNumber(-25, -5, -20)).toBe(-20);
+ expect(clampNumber(0, -5, -20)).toBe(-5);
+ });
+
+ it('should handle decimal values', () => {
+ expect(clampNumber(0.5, 1.0, 0.0)).toBe(0.5);
+ expect(clampNumber(-0.1, 1.0, 0.0)).toBe(0.0);
+ expect(clampNumber(1.5, 1.0, 0.0)).toBe(1.0);
+ });
+ });
+
+ describe('isUndefined()', () => {
+ it('should return true for undefined', () => {
+ expect(isUndefined(undefined)).toBe(true);
+ });
+
+ it('should return false for null', () => {
+ expect(isUndefined(null)).toBe(false);
+ });
+
+ it('should return false for empty string', () => {
+ expect(isUndefined('')).toBe(false);
+ });
+
+ it('should return false for 0', () => {
+ expect(isUndefined(0)).toBe(false);
+ });
+
+ it('should return false for false', () => {
+ expect(isUndefined(false)).toBe(false);
+ });
+
+ it('should return false for objects', () => {
+ expect(isUndefined({})).toBe(false);
+ expect(isUndefined([])).toBe(false);
+ });
+ });
+
+ describe('toSnakeCase()', () => {
+ it('should convert simple camelCase keys', () => {
+ const input = { firstName: 'John', lastName: 'Doe' };
+ const expected = { first_name: 'John', last_name: 'Doe' };
+ expect(toSnakeCase(input)).toEqual(expected);
+ });
+
+ it('should handle PascalCase', () => {
+ const input = { FirstName: 'John' };
+ const expected = { first_name: 'John' };
+ expect(toSnakeCase(input)).toEqual(expected);
+ });
+
+ it('should handle acronyms correctly', () => {
+ const input = { userID: 123, xmlParser: true, getHTTPResponse: 'ok' };
+ const expected = { user_id: 123, xml_parser: true, get_http_response: 'ok' };
+ expect(toSnakeCase(input)).toEqual(expected);
+ });
+
+ it('should handle nested objects', () => {
+ const input = {
+ userInfo: {
+ firstName: 'John',
+ addressDetails: { streetName: 'Main St' },
+ },
+ };
+ const expected = {
+ user_info: {
+ first_name: 'John',
+ address_details: { street_name: 'Main St' },
+ },
+ };
+ expect(toSnakeCase(input)).toEqual(expected);
+ });
+
+ it('should handle arrays with objects', () => {
+ const input = {
+ users: [
+ { firstName: 'John' },
+ { firstName: 'Jane' },
+ ],
+ };
+ const expected = {
+ users: [
+ { first_name: 'John' },
+ { first_name: 'Jane' },
+ ],
+ };
+ expect(toSnakeCase(input)).toEqual(expected);
+ });
+
+ it('should preserve non-object array items', () => {
+ const input = { items: ['one', 'two', 3, null] };
+ const expected = { items: ['one', 'two', 3, null] };
+ expect(toSnakeCase(input)).toEqual(expected);
+ });
+
+ it('should preserve Date objects', () => {
+ const date = new Date('2024-01-01');
+ const input = { createdAt: date };
+ const result = toSnakeCase(input) as Record;
+ expect(result['created_at']).toBe(date);
+ });
+
+ it('should handle empty objects', () => {
+ expect(toSnakeCase({})).toEqual({});
+ });
+
+ it('should handle already snake_case keys', () => {
+ const input = { already_snake: 'value' };
+ expect(toSnakeCase(input)).toEqual({ already_snake: 'value' });
+ });
+ });
+
+ describe('mergeDeepRight()', () => {
+ it('should merge simple objects', () => {
+ const target = { a: 1, b: 2 };
+ const source = { b: 3, c: 4 };
+ expect(mergeDeepRight(target, source)).toEqual({ a: 1, b: 3, c: 4 });
+ });
+
+ it('should merge nested objects deeply', () => {
+ const target = { a: { x: 1, y: 2 }, b: 3 } as Record;
+ const source = { a: { y: 3, z: 4 } } as Record;
+ expect(mergeDeepRight(target, source)).toEqual({
+ a: { x: 1, y: 3, z: 4 },
+ b: 3,
+ });
+ });
+
+ it('should not mutate original objects', () => {
+ const target = { a: 1 } as Record;
+ const source = { b: 2 } as Record;
+ const result = mergeDeepRight(target, source);
+ expect(target).toEqual({ a: 1 });
+ expect(source).toEqual({ b: 2 });
+ expect(result).toEqual({ a: 1, b: 2 });
+ });
+
+ it('should handle arrays by replacing', () => {
+ const target = { items: [1, 2, 3] };
+ const source = { items: [4, 5] };
+ expect(mergeDeepRight(target, source)).toEqual({ items: [4, 5] });
+ });
+
+ it('should handle null values in source', () => {
+ const target = { a: 1, b: { c: 2 } } as Record;
+ const source = { b: null } as Record;
+ const result = mergeDeepRight(target, source);
+ expect(result.b).toBeNull();
+ });
+
+ it('should ignore undefined values in source', () => {
+ const target = { a: 1, b: 2 };
+ const source = { b: undefined };
+ expect(mergeDeepRight(target, source)).toEqual({ a: 1, b: 2 });
+ });
+
+ it('should handle empty objects', () => {
+ expect(mergeDeepRight({}, { a: 1 })).toEqual({ a: 1 });
+ expect(mergeDeepRight({ a: 1 }, {})).toEqual({ a: 1 });
+ });
+ });
+
+ describe('getActionDescriptor()', () => {
+ it('should return track:event for track type with event property', () => {
+ expect(getActionDescriptor('track', { event: 'button_click' })).toBe(
+ 'track:button_click'
+ );
+ });
+
+ it('should return screen:name for screen type with name property', () => {
+ expect(getActionDescriptor('screen', { name: 'HomeScreen' })).toBe(
+ 'screen:HomeScreen'
+ );
+ });
+
+ it('should return type for track without event', () => {
+ expect(getActionDescriptor('track', { other: 'value' })).toBe('track');
+ });
+
+ it('should return type for screen without name', () => {
+ expect(getActionDescriptor('screen', { other: 'value' })).toBe('screen');
+ });
+
+ it('should return type for other event types', () => {
+ expect(getActionDescriptor('connect', { address: '0x...' })).toBe('connect');
+ expect(getActionDescriptor('disconnect', {})).toBe('disconnect');
+ });
+
+ it('should handle null/undefined properties', () => {
+ expect(getActionDescriptor('track', null)).toBe('track');
+ expect(getActionDescriptor('screen', undefined)).toBe('screen');
+ });
+ });
+
+ describe('isNetworkError()', () => {
+ it('should return true for "Network request failed"', () => {
+ expect(isNetworkError(new Error('Network request failed'))).toBe(true);
+ });
+
+ it('should return true for "Failed to fetch"', () => {
+ expect(isNetworkError(new Error('Failed to fetch'))).toBe(true);
+ });
+
+ it('should return true for "Network Error"', () => {
+ expect(isNetworkError(new Error('Network Error'))).toBe(true);
+ });
+
+ it('should return true for timeout errors', () => {
+ expect(isNetworkError(new Error('Request timeout'))).toBe(true);
+ expect(isNetworkError(new Error('ETIMEDOUT'))).toBe(true);
+ });
+
+ it('should return true for connection errors', () => {
+ expect(isNetworkError(new Error('ECONNREFUSED'))).toBe(true);
+ expect(isNetworkError(new Error('ENOTFOUND'))).toBe(true);
+ });
+
+ it('should be case insensitive', () => {
+ expect(isNetworkError(new Error('NETWORK REQUEST FAILED'))).toBe(true);
+ expect(isNetworkError(new Error('network error'))).toBe(true);
+ });
+
+ it('should return false for other errors', () => {
+ expect(isNetworkError(new Error('Invalid JSON'))).toBe(false);
+ expect(isNetworkError(new Error('Unauthorized'))).toBe(false);
+ });
+
+ it('should return false for null/undefined', () => {
+ expect(isNetworkError(null)).toBe(false);
+ expect(isNetworkError(undefined)).toBe(false);
+ });
+
+ it('should handle string errors', () => {
+ expect(isNetworkError('Network request failed')).toBe(true);
+ expect(isNetworkError('Some other error')).toBe(false);
+ });
+ });
+});
diff --git a/src/__tests__/session.test.ts b/src/__tests__/session.test.ts
new file mode 100644
index 0000000..2640e0e
--- /dev/null
+++ b/src/__tests__/session.test.ts
@@ -0,0 +1,151 @@
+import { FormoAnalyticsSession } from '../lib/session';
+import { storage } from '../lib/storage';
+
+// Mock the storage module
+jest.mock('../lib/storage', () => ({
+ storage: jest.fn(() => ({
+ get: jest.fn(),
+ set: jest.fn(),
+ remove: jest.fn(),
+ })),
+}));
+
+describe('FormoAnalyticsSession', () => {
+ let session: FormoAnalyticsSession;
+ let mockStorage: {
+ get: jest.Mock;
+ set: jest.Mock;
+ remove: jest.Mock;
+ };
+
+ beforeEach(() => {
+ mockStorage = {
+ get: jest.fn().mockReturnValue(null),
+ set: jest.fn(),
+ remove: jest.fn(),
+ };
+ (storage as jest.Mock).mockReturnValue(mockStorage);
+ session = new FormoAnalyticsSession();
+ });
+
+ describe('wallet detection', () => {
+ it('should return false for undetected wallet', () => {
+ expect(session.isWalletDetected('io.metamask')).toBe(false);
+ });
+
+ it('should return true after marking wallet as detected', () => {
+ session.markWalletDetected('io.metamask');
+ expect(session.isWalletDetected('io.metamask')).toBe(true);
+ });
+
+ it('should track multiple wallets independently', () => {
+ session.markWalletDetected('io.metamask');
+ session.markWalletDetected('com.coinbase.wallet');
+
+ expect(session.isWalletDetected('io.metamask')).toBe(true);
+ expect(session.isWalletDetected('com.coinbase.wallet')).toBe(true);
+ expect(session.isWalletDetected('com.phantom')).toBe(false);
+ });
+
+ it('should save to storage when marking detected', () => {
+ session.markWalletDetected('io.metamask');
+ expect(mockStorage.set).toHaveBeenCalled();
+ });
+ });
+
+ describe('wallet identification', () => {
+ const address = '0x742d35cc6634c0532925a3b844bc9e7595f3f6d2';
+ const rdns = 'io.metamask';
+
+ it('should return false for unidentified wallet', () => {
+ expect(session.isWalletIdentified(address, rdns)).toBe(false);
+ });
+
+ it('should return true after marking wallet as identified', () => {
+ session.markWalletIdentified(address, rdns);
+ expect(session.isWalletIdentified(address, rdns)).toBe(true);
+ });
+
+ it('should be case insensitive for addresses', () => {
+ session.markWalletIdentified(address.toLowerCase(), rdns);
+ expect(session.isWalletIdentified(address.toUpperCase(), rdns)).toBe(true);
+ });
+
+ it('should track different address+rdns combinations independently', () => {
+ const address2 = '0x1234567890123456789012345678901234567890';
+
+ session.markWalletIdentified(address, rdns);
+ session.markWalletIdentified(address2, 'com.coinbase.wallet');
+
+ expect(session.isWalletIdentified(address, rdns)).toBe(true);
+ expect(session.isWalletIdentified(address2, 'com.coinbase.wallet')).toBe(true);
+ expect(session.isWalletIdentified(address, 'com.coinbase.wallet')).toBe(false);
+ expect(session.isWalletIdentified(address2, rdns)).toBe(false);
+ });
+
+ it('should save to storage when marking identified', () => {
+ session.markWalletIdentified(address, rdns);
+ expect(mockStorage.set).toHaveBeenCalled();
+ });
+ });
+
+ describe('clear()', () => {
+ it('should clear all detected and identified wallets', () => {
+ session.markWalletDetected('io.metamask');
+ session.markWalletIdentified('0x123', 'io.metamask');
+
+ session.clear();
+
+ expect(session.isWalletDetected('io.metamask')).toBe(false);
+ expect(session.isWalletIdentified('0x123', 'io.metamask')).toBe(false);
+ });
+
+ it('should remove from storage when clearing', () => {
+ session.clear();
+ expect(mockStorage.remove).toHaveBeenCalledTimes(2);
+ });
+ });
+
+ describe('loading from storage', () => {
+ it('should load detected wallets from storage', () => {
+ mockStorage.get.mockImplementation((key: string) => {
+ if (key.includes('detected')) {
+ return JSON.stringify(['io.metamask', 'com.coinbase.wallet']);
+ }
+ return null;
+ });
+
+ const loadedSession = new FormoAnalyticsSession();
+
+ expect(loadedSession.isWalletDetected('io.metamask')).toBe(true);
+ expect(loadedSession.isWalletDetected('com.coinbase.wallet')).toBe(true);
+ });
+
+ it('should load identified wallets from storage', () => {
+ mockStorage.get.mockImplementation((key: string) => {
+ if (key.includes('identified')) {
+ return JSON.stringify(['0x123:io.metamask']);
+ }
+ return null;
+ });
+
+ const loadedSession = new FormoAnalyticsSession();
+
+ expect(loadedSession.isWalletIdentified('0x123', 'io.metamask')).toBe(true);
+ });
+
+ it('should handle invalid JSON in storage gracefully', () => {
+ mockStorage.get.mockReturnValue('invalid json');
+
+ expect(() => new FormoAnalyticsSession()).not.toThrow();
+ });
+
+ it('should handle empty storage', () => {
+ mockStorage.get.mockReturnValue(null);
+
+ const loadedSession = new FormoAnalyticsSession();
+
+ expect(loadedSession.isWalletDetected('anything')).toBe(false);
+ });
+ });
+});
diff --git a/src/__tests__/storage.test.ts b/src/__tests__/storage.test.ts
new file mode 100644
index 0000000..cb60cef
--- /dev/null
+++ b/src/__tests__/storage.test.ts
@@ -0,0 +1,121 @@
+import MemoryStorage from '../lib/storage/MemoryStorage';
+
+describe('MemoryStorage', () => {
+ let storage: MemoryStorage;
+
+ beforeEach(() => {
+ storage = new MemoryStorage('test-write-key');
+ });
+
+ describe('isAvailable()', () => {
+ it('should always return true', () => {
+ expect(storage.isAvailable()).toBe(true);
+ });
+ });
+
+ describe('getKey()', () => {
+ it('should generate prefixed key', () => {
+ const key = storage.getKey('myKey');
+ expect(key).toBe('formo_rn_test-write-key_myKey');
+ });
+
+ it('should handle special characters in key', () => {
+ const key = storage.getKey('my-special_key.123');
+ expect(key).toBe('formo_rn_test-write-key_my-special_key.123');
+ });
+ });
+
+ describe('set() and get()', () => {
+ it('should store and retrieve a value', () => {
+ storage.set('testKey', 'testValue');
+ expect(storage.get('testKey')).toBe('testValue');
+ });
+
+ it('should return null for non-existent key', () => {
+ expect(storage.get('nonExistent')).toBeNull();
+ });
+
+ it('should overwrite existing value', () => {
+ storage.set('key', 'value1');
+ storage.set('key', 'value2');
+ expect(storage.get('key')).toBe('value2');
+ });
+
+ it('should store empty string', () => {
+ storage.set('emptyKey', '');
+ expect(storage.get('emptyKey')).toBe('');
+ });
+
+ it('should handle JSON strings', () => {
+ const json = JSON.stringify({ foo: 'bar', num: 123 });
+ storage.set('jsonKey', json);
+ expect(JSON.parse(storage.get('jsonKey')!)).toEqual({ foo: 'bar', num: 123 });
+ });
+ });
+
+ describe('setAsync() and getAsync()', () => {
+ it('should store and retrieve a value asynchronously', async () => {
+ await storage.setAsync('asyncKey', 'asyncValue');
+ const value = await storage.getAsync('asyncKey');
+ expect(value).toBe('asyncValue');
+ });
+
+ it('should return null for non-existent key', async () => {
+ const value = await storage.getAsync('nonExistent');
+ expect(value).toBeNull();
+ });
+ });
+
+ describe('remove()', () => {
+ it('should remove an existing key', () => {
+ storage.set('toRemove', 'value');
+ expect(storage.get('toRemove')).toBe('value');
+
+ storage.remove('toRemove');
+ expect(storage.get('toRemove')).toBeNull();
+ });
+
+ it('should not throw when removing non-existent key', () => {
+ expect(() => storage.remove('nonExistent')).not.toThrow();
+ });
+ });
+
+ describe('removeAsync()', () => {
+ it('should remove an existing key asynchronously', async () => {
+ await storage.setAsync('toRemove', 'value');
+ await storage.removeAsync('toRemove');
+ expect(await storage.getAsync('toRemove')).toBeNull();
+ });
+ });
+
+ describe('clear()', () => {
+ it('should remove all stored values', () => {
+ storage.set('key1', 'value1');
+ storage.set('key2', 'value2');
+ storage.set('key3', 'value3');
+
+ storage.clear();
+
+ expect(storage.get('key1')).toBeNull();
+ expect(storage.get('key2')).toBeNull();
+ expect(storage.get('key3')).toBeNull();
+ });
+
+ it('should not throw when storage is already empty', () => {
+ expect(() => storage.clear()).not.toThrow();
+ });
+ });
+
+ describe('isolation between instances', () => {
+ it('should isolate data between different write keys', () => {
+ const storage1 = new MemoryStorage('key1');
+ const storage2 = new MemoryStorage('key2');
+
+ storage1.set('shared', 'value1');
+ storage2.set('shared', 'value2');
+
+ expect(storage1.get('shared')).toBe('value1');
+ expect(storage2.get('shared')).toBe('value2');
+ });
+ });
+});
diff --git a/src/constants/config.ts b/src/constants/config.ts
new file mode 100644
index 0000000..4a7ab42
--- /dev/null
+++ b/src/constants/config.ts
@@ -0,0 +1,62 @@
+export const EVENTS_API_ORIGIN = "https://events.formo.so";
+export const EVENTS_API_HOST = `${EVENTS_API_ORIGIN}/v0/raw_events`;
+
+export const EVENTS_API_REQUEST_HEADER = (writeKey: string) => ({
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${writeKey}`,
+});
+
+// Timezone to country mapping
+export const COUNTRY_LIST: Record = {
+ // Africa
+ "Africa/Abidjan": "CI",
+ "Africa/Accra": "GH",
+ "Africa/Addis_Ababa": "ET",
+ "Africa/Algiers": "DZ",
+ "Africa/Cairo": "EG",
+ "Africa/Casablanca": "MA",
+ "Africa/Johannesburg": "ZA",
+ "Africa/Lagos": "NG",
+ "Africa/Nairobi": "KE",
+ // America
+ "America/Anchorage": "US",
+ "America/Argentina/Buenos_Aires": "AR",
+ "America/Bogota": "CO",
+ "America/Chicago": "US",
+ "America/Denver": "US",
+ "America/Los_Angeles": "US",
+ "America/Mexico_City": "MX",
+ "America/New_York": "US",
+ "America/Phoenix": "US",
+ "America/Sao_Paulo": "BR",
+ "America/Toronto": "CA",
+ "America/Vancouver": "CA",
+ // Asia
+ "Asia/Bangkok": "TH",
+ "Asia/Dubai": "AE",
+ "Asia/Ho_Chi_Minh": "VN",
+ "Asia/Hong_Kong": "HK",
+ "Asia/Jakarta": "ID",
+ "Asia/Kolkata": "IN",
+ "Asia/Manila": "PH",
+ "Asia/Seoul": "KR",
+ "Asia/Shanghai": "CN",
+ "Asia/Singapore": "SG",
+ "Asia/Taipei": "TW",
+ "Asia/Tokyo": "JP",
+ // Australia
+ "Australia/Melbourne": "AU",
+ "Australia/Sydney": "AU",
+ // Europe
+ "Europe/Amsterdam": "NL",
+ "Europe/Berlin": "DE",
+ "Europe/London": "GB",
+ "Europe/Madrid": "ES",
+ "Europe/Moscow": "RU",
+ "Europe/Paris": "FR",
+ "Europe/Rome": "IT",
+ "Europe/Zurich": "CH",
+ // Pacific
+ "Pacific/Auckland": "NZ",
+ "Pacific/Honolulu": "US",
+};
diff --git a/src/constants/events.ts b/src/constants/events.ts
new file mode 100644
index 0000000..5770194
--- /dev/null
+++ b/src/constants/events.ts
@@ -0,0 +1,26 @@
+export enum EventType {
+ PAGE = "page",
+ SCREEN = "screen",
+ IDENTIFY = "identify",
+ DETECT = "detect",
+ CONNECT = "connect",
+ DISCONNECT = "disconnect",
+ CHAIN = "chain",
+ SIGNATURE = "signature",
+ TRANSACTION = "transaction",
+ TRACK = "track",
+}
+
+export enum EventChannel {
+ WEB = "web",
+ MOBILE = "mobile",
+ SERVER = "server",
+ SOURCE = "source",
+}
+
+export type TEventType = Lowercase;
+export type TEventChannel = Lowercase;
+
+// React Native SDK uses mobile channel
+export const CHANNEL: TEventChannel = "mobile";
+export const VERSION = "1";
diff --git a/src/constants/index.ts b/src/constants/index.ts
new file mode 100644
index 0000000..1e65cd7
--- /dev/null
+++ b/src/constants/index.ts
@@ -0,0 +1,3 @@
+export * from "./events";
+export * from "./config";
+export * from "./storage";
diff --git a/src/constants/storage.ts b/src/constants/storage.ts
new file mode 100644
index 0000000..df1ead0
--- /dev/null
+++ b/src/constants/storage.ts
@@ -0,0 +1,14 @@
+// Storage keys for React Native SDK
+export const STORAGE_PREFIX = "formo_rn_";
+
+// Local storage keys (persistent)
+export const LOCAL_ANONYMOUS_ID_KEY = "anonymous_id";
+
+// Session storage keys (cleared on app restart)
+export const SESSION_USER_ID_KEY = "user_id";
+export const SESSION_TRAFFIC_SOURCE_KEY = "traffic_source";
+export const SESSION_WALLET_DETECTED_KEY = "wallet_detected";
+export const SESSION_WALLET_IDENTIFIED_KEY = "wallet_identified";
+
+// Consent keys
+export const CONSENT_OPT_OUT_KEY = "opt_out_tracking";
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..0b72fb1
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,55 @@
+/**
+ * Formo Analytics SDK for React Native
+ *
+ * Track wallet events and user analytics in mobile dApps
+ *
+ * @example
+ * ```tsx
+ * import AsyncStorage from '@react-native-async-storage/async-storage';
+ * import { FormoAnalyticsProvider, useFormo } from '@formo/react-native-analytics';
+ *
+ * // Wrap your app with the provider
+ * function App() {
+ * return (
+ *
+ *
+ *
+ * );
+ * }
+ *
+ * // Use the hook in your components
+ * function MyScreen() {
+ * const formo = useFormo();
+ *
+ * useEffect(() => {
+ * formo.screen('Home');
+ * }, []);
+ *
+ * return ...;
+ * }
+ * ```
+ */
+
+// Main exports
+export { FormoAnalytics } from "./FormoAnalytics";
+export {
+ FormoAnalyticsProvider,
+ FormoAnalyticsContext,
+ useFormo,
+} from "./FormoAnalyticsProvider";
+
+// Types
+export * from "./types";
+
+// Event types for manual event tracking
+export { SignatureStatus, TransactionStatus } from "./types/events";
+
+// Storage types for custom storage implementations
+export type { AsyncStorageInterface } from "./lib/storage";
diff --git a/src/lib/consent/index.ts b/src/lib/consent/index.ts
new file mode 100644
index 0000000..b30816f
--- /dev/null
+++ b/src/lib/consent/index.ts
@@ -0,0 +1,52 @@
+import { storage } from "../storage";
+import { logger } from "../logger";
+
+/**
+ * Get consent storage key
+ * Note: The storage adapter already prefixes keys with formo_rn_{writeKey}_
+ * so we just need a simple consent prefix here
+ */
+function getConsentKey(_writeKey: string, key: string): string {
+ return `consent_${key}`;
+}
+
+/**
+ * Set a consent flag
+ */
+export function setConsentFlag(
+ writeKey: string,
+ key: string,
+ value: string
+): void {
+ try {
+ const consentKey = getConsentKey(writeKey, key);
+ storage().set(consentKey, value);
+ } catch (error) {
+ logger.error("Consent: Failed to set flag", error);
+ }
+}
+
+/**
+ * Get a consent flag
+ */
+export function getConsentFlag(writeKey: string, key: string): string | null {
+ try {
+ const consentKey = getConsentKey(writeKey, key);
+ return storage().get(consentKey);
+ } catch (error) {
+ logger.error("Consent: Failed to get flag", error);
+ return null;
+ }
+}
+
+/**
+ * Remove a consent flag
+ */
+export function removeConsentFlag(writeKey: string, key: string): void {
+ try {
+ const consentKey = getConsentKey(writeKey, key);
+ storage().remove(consentKey);
+ } catch (error) {
+ logger.error("Consent: Failed to remove flag", error);
+ }
+}
diff --git a/src/lib/event/EventFactory.ts b/src/lib/event/EventFactory.ts
new file mode 100644
index 0000000..987b697
--- /dev/null
+++ b/src/lib/event/EventFactory.ts
@@ -0,0 +1,665 @@
+import { Platform, NativeModules, Dimensions } from "react-native";
+import NetInfo from "@react-native-community/netinfo";
+
+// Lazy load device info to handle Expo Go where native modules may not exist
+let DeviceInfo: typeof import("react-native-device-info").default | null = null;
+let ExpoDevice: typeof import("expo-device") | null = null;
+let ExpoApplication: typeof import("expo-application") | null = null;
+
+// Try to load react-native-device-info (works in bare RN and dev builds)
+try {
+ DeviceInfo = require("react-native-device-info").default;
+} catch {
+ // Not available - try Expo alternatives
+}
+
+// Try to load Expo modules (works in Expo Go and Expo dev builds)
+try {
+ ExpoDevice = require("expo-device");
+} catch {
+ // Not available
+}
+
+try {
+ ExpoApplication = require("expo-application");
+} catch {
+ // Not available
+}
+import { COUNTRY_LIST, LOCAL_ANONYMOUS_ID_KEY, CHANNEL, VERSION } from "../../constants";
+import {
+ Address,
+ APIEvent,
+ ChainID,
+ IFormoEvent,
+ IFormoEventContext,
+ IFormoEventProperties,
+ Nullable,
+ Options,
+ SignatureStatus,
+ TransactionStatus,
+} from "../../types";
+import {
+ toChecksumAddress,
+ getValidAddress,
+ toSnakeCase,
+ mergeDeepRight,
+ getStoredTrafficSource,
+} from "../../utils";
+import { getCurrentTimeFormatted } from "../../utils/timestamp";
+import { generateUUID } from "../../utils/hash";
+import { logger } from "../logger";
+import { storage } from "../storage";
+import { IEventFactory } from "./types";
+
+// SDK version
+const SDK_VERSION = "1.0.0";
+
+/**
+ * Generate or retrieve anonymous ID
+ */
+function generateAnonymousId(key: string): string {
+ const existing = storage().get(key);
+ if (existing) {
+ return existing;
+ }
+
+ const newId = generateUUID();
+ storage().set(key, newId);
+ return newId;
+}
+
+/**
+ * Event factory for React Native
+ * Creates event payloads with mobile-specific context
+ */
+class EventFactory implements IEventFactory {
+ private options?: Options;
+
+ constructor(options?: Options) {
+ this.options = options;
+ }
+
+ /**
+ * Get device timezone
+ */
+ private getTimezone(): string {
+ try {
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
+ } catch (error) {
+ logger.error("Error resolving timezone:", error);
+ return "";
+ }
+ }
+
+ /**
+ * Get location from timezone
+ */
+ private getLocation(): string {
+ try {
+ const timezone = this.getTimezone();
+ if (timezone in COUNTRY_LIST) {
+ return COUNTRY_LIST[timezone] ?? timezone;
+ }
+ return timezone;
+ } catch (error) {
+ logger.error("Error resolving location:", error);
+ return "";
+ }
+ }
+
+ /**
+ * Get device language/locale
+ */
+ private getLanguage(): string {
+ try {
+ // Try to get the device locale
+ const locale =
+ Platform.OS === "ios"
+ ? NativeModules.SettingsManager?.settings?.AppleLocale ||
+ NativeModules.SettingsManager?.settings?.AppleLanguages?.[0]
+ : NativeModules.I18nManager?.localeIdentifier;
+
+ return locale || "en";
+ } catch (error) {
+ logger.debug("Error resolving language:", error);
+ return "en";
+ }
+ }
+
+ /**
+ * Get screen dimensions
+ */
+ private getScreen(): {
+ screen_width: number;
+ screen_height: number;
+ screen_density: number;
+ } {
+ try {
+ const { width, height, scale } = Dimensions.get("screen");
+ return {
+ screen_width: Math.round(width),
+ screen_height: Math.round(height),
+ screen_density: scale,
+ };
+ } catch (error) {
+ logger.error("Error resolving screen properties:", error);
+ return {
+ screen_width: 0,
+ screen_height: 0,
+ screen_density: 1,
+ };
+ }
+ }
+
+ /**
+ * Get network information
+ */
+ private async getNetworkInfo(): Promise<{
+ network_wifi?: boolean;
+ network_cellular?: boolean;
+ network_carrier?: string;
+ }> {
+ try {
+ const netState = await NetInfo.fetch();
+
+ const networkInfo: {
+ network_wifi?: boolean;
+ network_cellular?: boolean;
+ network_carrier?: string;
+ } = {};
+
+ // Set connection type flags
+ if (netState.type === "wifi") {
+ networkInfo.network_wifi = true;
+ networkInfo.network_cellular = false;
+ } else if (netState.type === "cellular") {
+ networkInfo.network_wifi = false;
+ networkInfo.network_cellular = true;
+
+ // Get carrier name for cellular connections
+ if (netState.details && "carrier" in netState.details) {
+ networkInfo.network_carrier = netState.details.carrier || undefined;
+ }
+ } else {
+ // Other types (ethernet, bluetooth, wimax, vpn, other, unknown, none)
+ networkInfo.network_wifi = false;
+ networkInfo.network_cellular = false;
+ }
+
+ return networkInfo;
+ } catch (error) {
+ logger.debug("Error getting network info:", error);
+ return {};
+ }
+ }
+
+ /**
+ * Get device information
+ * Supports both react-native-device-info (bare RN) and expo-device/expo-application (Expo Go)
+ */
+ private async getDeviceInfo(): Promise<{
+ os_name: string;
+ os_version: string;
+ device_model: string;
+ device_manufacturer: string;
+ device_name: string;
+ device_type: string;
+ user_agent: string;
+ app_name: string;
+ app_version: string;
+ app_build: string;
+ app_bundle_id: string;
+ }> {
+ // Try react-native-device-info first (bare RN and Expo dev builds)
+ if (DeviceInfo) {
+ try {
+ const [model, manufacturer, deviceName, userAgent, isTablet] = await Promise.all([
+ DeviceInfo.getModel(),
+ DeviceInfo.getManufacturer(),
+ DeviceInfo.getDeviceName(),
+ DeviceInfo.getUserAgent(),
+ DeviceInfo.isTablet(),
+ ]);
+
+ return {
+ os_name: Platform.OS,
+ os_version: DeviceInfo.getSystemVersion(),
+ device_model: model,
+ device_manufacturer: manufacturer,
+ device_name: deviceName,
+ device_type: isTablet ? "tablet" : "mobile",
+ user_agent: userAgent,
+ app_name: DeviceInfo.getApplicationName(),
+ app_version: DeviceInfo.getVersion(),
+ app_build: DeviceInfo.getBuildNumber(),
+ app_bundle_id: DeviceInfo.getBundleId(),
+ };
+ } catch (error) {
+ logger.debug("Error using react-native-device-info, falling back:", error);
+ }
+ }
+
+ // Fall back to Expo modules (Expo Go)
+ if (ExpoDevice || ExpoApplication) {
+ try {
+ const isTablet = ExpoDevice?.deviceType === ExpoDevice?.DeviceType?.TABLET;
+ return {
+ os_name: ExpoDevice?.osName || Platform.OS,
+ os_version: ExpoDevice?.osVersion || String(Platform.Version),
+ device_model: ExpoDevice?.modelName || "Unknown",
+ device_manufacturer: ExpoDevice?.manufacturer || "Unknown",
+ device_name: ExpoDevice?.deviceName || "Unknown Device",
+ device_type: isTablet ? "tablet" : "mobile",
+ user_agent: "",
+ app_name: ExpoApplication?.applicationName || "",
+ app_version: ExpoApplication?.nativeApplicationVersion || "",
+ app_build: ExpoApplication?.nativeBuildVersion || "",
+ app_bundle_id: ExpoApplication?.applicationId || "",
+ };
+ } catch (error) {
+ logger.debug("Error using Expo device modules:", error);
+ }
+ }
+
+ // Final fallback - minimal info from Platform
+ logger.debug("No device info modules available, using Platform defaults");
+ return {
+ os_name: Platform.OS,
+ os_version: String(Platform.Version),
+ device_model: "Unknown",
+ device_manufacturer: "Unknown",
+ device_name: "Unknown Device",
+ device_type: "mobile",
+ user_agent: "",
+ app_name: "",
+ app_version: "",
+ app_build: "",
+ app_bundle_id: "",
+ };
+ }
+
+ /**
+ * Generate context with mobile-specific metadata
+ */
+ private async generateContext(
+ context?: IFormoEventContext
+ ): Promise {
+ const language = this.getLanguage();
+ const timezone = this.getTimezone();
+ const location = this.getLocation();
+ const deviceInfo = await this.getDeviceInfo();
+ const networkInfo = await this.getNetworkInfo();
+ const screenInfo = this.getScreen();
+
+ // Get stored traffic source from session (UTM params, referrer from deep links)
+ const storedTrafficSource = getStoredTrafficSource();
+
+ const defaultContext: IFormoEventContext = {
+ locale: language,
+ timezone,
+ location,
+ library_name: "Formo React Native SDK",
+ library_version: SDK_VERSION,
+ ...deviceInfo,
+ ...networkInfo,
+ ...screenInfo,
+ // App info from options (overrides auto-detected values)
+ ...(this.options?.app?.name && { app_name: this.options.app.name }),
+ ...(this.options?.app?.version && { app_version: this.options.app.version }),
+ ...(this.options?.app?.build && { app_build: this.options.app.build }),
+ ...(this.options?.app?.bundleId && { app_bundle_id: this.options.app.bundleId }),
+ // Traffic source (UTM params, referrer) from session
+ ...(storedTrafficSource || {}),
+ };
+
+ const mergedContext = mergeDeepRight(
+ defaultContext,
+ context || {}
+ ) as IFormoEventContext;
+
+ return mergedContext;
+ }
+
+ /**
+ * Create enriched event with common properties
+ */
+ private async getEnrichedEvent(
+ formoEvent: Partial,
+ context?: IFormoEventContext
+ ): Promise {
+ const commonEventData: Partial = {
+ context: await this.generateContext(context),
+ original_timestamp: getCurrentTimeFormatted(),
+ user_id: formoEvent.user_id,
+ type: formoEvent.type,
+ channel: CHANNEL,
+ version: VERSION,
+ };
+
+ commonEventData.anonymous_id = generateAnonymousId(LOCAL_ANONYMOUS_ID_KEY);
+
+ // Handle address - convert undefined to null for consistency
+ const validAddress = getValidAddress(formoEvent.address);
+ if (validAddress) {
+ commonEventData.address = toChecksumAddress(validAddress);
+ } else {
+ commonEventData.address = null;
+ }
+
+ const processedEvent = mergeDeepRight(
+ formoEvent as Record,
+ commonEventData as Record
+ ) as unknown as IFormoEvent;
+
+ if (processedEvent.event === undefined) {
+ processedEvent.event = null;
+ }
+
+ if (processedEvent.properties === undefined) {
+ processedEvent.properties = null;
+ }
+
+ return toSnakeCase(processedEvent as unknown as Record) as unknown as IFormoEvent;
+ }
+
+ /**
+ * Generate screen view event (mobile equivalent of page)
+ */
+ async generateScreenEvent(
+ name: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const props = { ...(properties ?? {}), name };
+
+ const screenEvent: Partial = {
+ properties: props,
+ type: "screen",
+ };
+
+ return this.getEnrichedEvent(screenEvent, context);
+ }
+
+ async generateDetectWalletEvent(
+ providerName: string,
+ rdns: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const detectEvent: Partial = {
+ properties: {
+ providerName,
+ rdns,
+ ...properties,
+ },
+ type: "detect",
+ };
+
+ return this.getEnrichedEvent(detectEvent, context);
+ }
+
+ async generateIdentifyEvent(
+ providerName: string,
+ rdns: string,
+ address: Nullable,
+ userId?: Nullable,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const identifyEvent: Partial = {
+ properties: {
+ providerName,
+ rdns,
+ ...properties,
+ },
+ user_id: userId,
+ address,
+ type: "identify",
+ };
+
+ return this.getEnrichedEvent(identifyEvent, context);
+ }
+
+ async generateConnectEvent(
+ chainId: ChainID,
+ address: Address,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const connectEvent: Partial = {
+ properties: {
+ chainId,
+ ...properties,
+ },
+ address,
+ type: "connect",
+ };
+
+ return this.getEnrichedEvent(connectEvent, context);
+ }
+
+ async generateDisconnectEvent(
+ chainId?: ChainID,
+ address?: Address,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const disconnectEvent: Partial = {
+ properties: {
+ chainId,
+ ...properties,
+ },
+ address,
+ type: "disconnect",
+ };
+
+ return this.getEnrichedEvent(disconnectEvent, context);
+ }
+
+ async generateChainChangedEvent(
+ chainId: ChainID,
+ address: Address,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const chainEvent: Partial = {
+ properties: {
+ chainId,
+ ...properties,
+ },
+ address,
+ type: "chain",
+ };
+
+ return this.getEnrichedEvent(chainEvent, context);
+ }
+
+ async generateSignatureEvent(
+ status: SignatureStatus,
+ chainId: ChainID,
+ address: Address,
+ message: string,
+ signatureHash?: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const signatureEvent: Partial = {
+ properties: {
+ status,
+ chainId,
+ message,
+ ...(signatureHash && { signatureHash }),
+ ...properties,
+ },
+ address,
+ type: "signature",
+ };
+
+ return this.getEnrichedEvent(signatureEvent, context);
+ }
+
+ async generateTransactionEvent(
+ status: TransactionStatus,
+ chainId: ChainID,
+ address: Address,
+ data: string,
+ to: string,
+ value: string,
+ transactionHash?: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const transactionEvent: Partial = {
+ properties: {
+ status,
+ chainId,
+ data,
+ to,
+ value,
+ ...(transactionHash && { transactionHash }),
+ ...properties,
+ },
+ address,
+ type: "transaction",
+ };
+
+ return this.getEnrichedEvent(transactionEvent, context);
+ }
+
+ async generateTrackEvent(
+ event: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise {
+ const trackEvent: Partial = {
+ properties: {
+ ...properties,
+ ...(properties?.revenue !== undefined && {
+ revenue: Number(properties.revenue),
+ currency: (typeof properties?.currency === "string"
+ ? properties.currency
+ : "USD"
+ ).toLowerCase(),
+ }),
+ ...(properties?.points !== undefined && {
+ points: Number(properties.points),
+ }),
+ ...(properties?.volume !== undefined && {
+ volume: Number(properties.volume),
+ }),
+ },
+ event,
+ type: "track",
+ };
+
+ return this.getEnrichedEvent(trackEvent, context);
+ }
+
+ /**
+ * Create event from API event type
+ */
+ async create(
+ event: APIEvent,
+ address?: Address,
+ userId?: string
+ ): Promise {
+ let formoEvent: Partial = {};
+
+ switch (event.type) {
+ case "screen":
+ formoEvent = await this.generateScreenEvent(
+ event.name,
+ event.properties,
+ event.context
+ );
+ break;
+ case "detect":
+ formoEvent = await this.generateDetectWalletEvent(
+ event.providerName,
+ event.rdns,
+ event.properties,
+ event.context
+ );
+ break;
+ case "identify":
+ formoEvent = await this.generateIdentifyEvent(
+ event.providerName,
+ event.rdns,
+ event.address,
+ event.userId,
+ event.properties,
+ event.context
+ );
+ break;
+ case "chain":
+ formoEvent = await this.generateChainChangedEvent(
+ event.chainId,
+ event.address,
+ event.properties,
+ event.context
+ );
+ break;
+ case "connect":
+ formoEvent = await this.generateConnectEvent(
+ event.chainId,
+ event.address,
+ event.properties,
+ event.context
+ );
+ break;
+ case "disconnect":
+ formoEvent = await this.generateDisconnectEvent(
+ event.chainId,
+ event.address,
+ event.properties,
+ event.context
+ );
+ break;
+ case "signature":
+ formoEvent = await this.generateSignatureEvent(
+ event.status,
+ event.chainId,
+ event.address,
+ event.message,
+ event.signatureHash,
+ event.properties,
+ event.context
+ );
+ break;
+ case "transaction":
+ formoEvent = await this.generateTransactionEvent(
+ event.status,
+ event.chainId,
+ event.address,
+ event.data,
+ event.to,
+ event.value,
+ event.transactionHash,
+ event.properties,
+ event.context
+ );
+ break;
+ case "track":
+ default:
+ formoEvent = await this.generateTrackEvent(
+ event.event,
+ event.properties,
+ event.context
+ );
+ break;
+ }
+
+ // Set address if not already set by the specific event generator
+ if (formoEvent.address === undefined || formoEvent.address === null) {
+ const validAddress = getValidAddress(address);
+ formoEvent.address = validAddress
+ ? toChecksumAddress(validAddress)
+ : null;
+ }
+ formoEvent.user_id = userId || null;
+
+ return formoEvent as IFormoEvent;
+ }
+}
+
+export { EventFactory };
diff --git a/src/lib/event/EventManager.ts b/src/lib/event/EventManager.ts
new file mode 100644
index 0000000..a36830b
--- /dev/null
+++ b/src/lib/event/EventManager.ts
@@ -0,0 +1,50 @@
+import { Address, APIEvent, Options } from "../../types";
+import { logger } from "../logger";
+import { EventFactory } from "./EventFactory";
+import { IEventFactory, IEventManager, IEventQueue } from "./types";
+import { isBlockedAddress } from "../../utils/address";
+
+/**
+ * Event manager for React Native SDK
+ * Generates valid event payloads and queues them for processing
+ */
+class EventManager implements IEventManager {
+ eventQueue: IEventQueue;
+ eventFactory: IEventFactory;
+
+ constructor(eventQueue: IEventQueue, options?: Options) {
+ this.eventQueue = eventQueue;
+ this.eventFactory = new EventFactory(options);
+ }
+
+ /**
+ * Add event to queue
+ */
+ async addEvent(
+ event: APIEvent,
+ address?: Address,
+ userId?: string
+ ): Promise {
+ const { callback, ..._event } = event;
+ const formoEvent = await this.eventFactory.create(_event, address, userId);
+
+ // Check if the final event has a blocked address
+ if (formoEvent.address && isBlockedAddress(formoEvent.address)) {
+ logger.warn(
+ `Event blocked: Address ${formoEvent.address} is in the blocked list`
+ );
+ return;
+ }
+
+ await this.eventQueue.enqueue(formoEvent, (err, _, data) => {
+ if (err) {
+ logger.error("Error sending events:", err);
+ } else {
+ logger.info(`Events sent successfully: ${(data as unknown[])?.length ?? 0} events`);
+ }
+ callback?.(err, _, data);
+ });
+ }
+}
+
+export { EventManager };
diff --git a/src/lib/event/EventQueue.ts b/src/lib/event/EventQueue.ts
new file mode 100644
index 0000000..7dad374
--- /dev/null
+++ b/src/lib/event/EventQueue.ts
@@ -0,0 +1,371 @@
+import { AppState, AppStateStatus } from "react-native";
+import { IFormoEvent, IFormoEventPayload } from "../../types";
+import { EVENTS_API_REQUEST_HEADER } from "../../constants";
+import {
+ clampNumber,
+ getActionDescriptor,
+ millisecondsToSecond,
+ isNetworkError,
+} from "../../utils";
+import { hash } from "../../utils/hash";
+import { toDateHourMinute } from "../../utils/timestamp";
+import { logger } from "../logger";
+import { IEventQueue } from "./types";
+
+type QueueItem = {
+ message: IFormoEventPayload;
+ callback: (...args: unknown[]) => void;
+ hash: string;
+};
+
+type IFormoEventFlushPayload = IFormoEventPayload & {
+ sent_at: string;
+};
+
+interface Options {
+ apiHost: string;
+ flushAt?: number;
+ flushInterval?: number;
+ retryCount?: number;
+ maxQueueSize?: number;
+}
+
+const DEFAULT_RETRY = 3;
+const MAX_RETRY = 5;
+const MIN_RETRY = 1;
+
+const DEFAULT_FLUSH_AT = 20;
+const MAX_FLUSH_AT = 20;
+const MIN_FLUSH_AT = 1;
+
+const DEFAULT_QUEUE_SIZE = 1_024 * 500; // 500kB
+const MAX_QUEUE_SIZE = 1_024 * 500; // 500kB
+const MIN_QUEUE_SIZE = 200; // 200 bytes
+
+const DEFAULT_FLUSH_INTERVAL = 1_000 * 30; // 30 seconds
+const MAX_FLUSH_INTERVAL = 1_000 * 300; // 5 minutes
+const MIN_FLUSH_INTERVAL = 1_000 * 10; // 10 seconds
+
+const noop = () => {};
+
+/**
+ * Event queue for React Native
+ * Handles batching, flushing, and retries with app lifecycle awareness
+ */
+export class EventQueue implements IEventQueue {
+ private writeKey: string;
+ private apiHost: string;
+ private queue: QueueItem[] = [];
+ private timer: ReturnType | null = null;
+ private flushAt: number;
+ private flushIntervalMs: number;
+ private maxQueueSize: number;
+ private retryCount: number;
+ private payloadHashes: Set = new Set();
+ private flushMutex: Promise = Promise.resolve();
+ private appStateSubscription: { remove: () => void } | null = null;
+
+ constructor(writeKey: string, options: Options) {
+ this.writeKey = writeKey;
+ this.apiHost = options.apiHost;
+ this.retryCount = clampNumber(
+ options.retryCount || DEFAULT_RETRY,
+ MAX_RETRY,
+ MIN_RETRY
+ );
+ this.flushAt = clampNumber(
+ options.flushAt || DEFAULT_FLUSH_AT,
+ MAX_FLUSH_AT,
+ MIN_FLUSH_AT
+ );
+ this.maxQueueSize = clampNumber(
+ options.maxQueueSize || DEFAULT_QUEUE_SIZE,
+ MAX_QUEUE_SIZE,
+ MIN_QUEUE_SIZE
+ );
+ this.flushIntervalMs = clampNumber(
+ options.flushInterval || DEFAULT_FLUSH_INTERVAL,
+ MAX_FLUSH_INTERVAL,
+ MIN_FLUSH_INTERVAL
+ );
+ // Set up app state listener for React Native
+ this.setupAppStateListener();
+ }
+
+ /**
+ * Set up listener for app state changes
+ * Flush events when app goes to background
+ */
+ private setupAppStateListener(): void {
+ this.appStateSubscription = AppState.addEventListener(
+ "change",
+ this.handleAppStateChange.bind(this)
+ );
+ }
+
+ /**
+ * Handle app state changes
+ */
+ private handleAppStateChange(nextAppState: AppStateStatus): void {
+ // Flush when app goes to background or becomes inactive
+ if (nextAppState === "background" || nextAppState === "inactive") {
+ logger.debug("EventQueue: App going to background, flushing events");
+ this.flush().catch((error) => {
+ logger.error("EventQueue: Failed to flush on background", error);
+ });
+ }
+ }
+
+ /**
+ * Generate message ID for deduplication
+ */
+ private async generateMessageId(event: IFormoEvent): Promise {
+ const formattedTimestamp = toDateHourMinute(
+ new Date(event.original_timestamp)
+ );
+ const eventForHashing = { ...event, original_timestamp: formattedTimestamp };
+ const eventString = JSON.stringify(eventForHashing);
+ return hash(eventString);
+ }
+
+ /**
+ * Check if event is a duplicate
+ */
+ private isDuplicate(eventId: string): boolean {
+ if (this.payloadHashes.has(eventId)) return true;
+ this.payloadHashes.add(eventId);
+ return false;
+ }
+
+ /**
+ * Add event to queue
+ */
+ async enqueue(
+ event: IFormoEvent,
+ callback?: (...args: unknown[]) => void
+ ): Promise {
+ callback = callback || noop;
+
+ const message_id = await this.generateMessageId(event);
+
+ // Check for duplicate
+ if (this.isDuplicate(message_id)) {
+ logger.warn(
+ `Event already enqueued, try again after ${millisecondsToSecond(
+ this.flushIntervalMs
+ )} seconds.`
+ );
+ return;
+ }
+
+ this.queue.push({
+ message: { ...event, message_id },
+ callback,
+ hash: message_id,
+ });
+
+ logger.log(
+ `Event enqueued: ${getActionDescriptor(event.type, event.properties)}`
+ );
+
+ const hasReachedFlushAt = this.queue.length >= this.flushAt;
+ const hasReachedQueueSize =
+ this.queue.reduce(
+ (acc, item) => acc + JSON.stringify(item).length,
+ 0
+ ) >= this.maxQueueSize;
+
+ if (hasReachedFlushAt || hasReachedQueueSize) {
+ // Clear timer to prevent double flush
+ if (this.timer) {
+ clearTimeout(this.timer);
+ this.timer = null;
+ }
+ // Flush uses internal mutex to serialize operations
+ this.flush().catch((error) => {
+ logger.error("EventQueue: Failed to flush on threshold", error);
+ });
+ return;
+ }
+
+ if (this.flushIntervalMs && !this.timer) {
+ this.timer = setTimeout(this.flush.bind(this), this.flushIntervalMs);
+ }
+ }
+
+ /**
+ * Flush events to API
+ * Uses a mutex to ensure only one flush operation runs at a time,
+ * preventing race conditions with re-queued items on failure.
+ */
+ async flush(callback?: (...args: unknown[]) => void): Promise {
+ callback = callback || noop;
+
+ if (this.timer) {
+ clearTimeout(this.timer);
+ this.timer = null;
+ }
+
+ // Use mutex to serialize flush operations and prevent race conditions
+ const previousMutex = this.flushMutex;
+ let resolveMutex: () => void;
+ this.flushMutex = new Promise((resolve) => {
+ resolveMutex = resolve;
+ });
+
+ try {
+ // Wait for any previous flush to complete
+ await previousMutex;
+
+ if (!this.queue.length) {
+ callback();
+ return;
+ }
+
+ const items = this.queue.splice(0, this.flushAt);
+
+ const sentAt = new Date().toISOString();
+ const data: IFormoEventFlushPayload[] = items.map((item) => ({
+ ...item.message,
+ sent_at: sentAt,
+ }));
+
+ const done = (err?: Error) => {
+ items.forEach(({ message, callback: itemCallback }) =>
+ itemCallback(err, message, data)
+ );
+ callback!(err, data);
+ };
+
+ try {
+ await this.sendWithRetry(data);
+ // Only remove hashes after successful send
+ items.forEach((item) => this.payloadHashes.delete(item.hash));
+ done();
+ logger.info(`Events sent successfully: ${data.length} events`);
+ } catch (err) {
+ // Re-add items to the front of the queue for retry on next flush
+ // Note: We intentionally keep hashes in payloadHashes to prevent duplicate
+ // events from being enqueued while these items are pending retry.
+ this.queue.unshift(...items);
+ done(err as Error);
+ logger.error("Error sending events, re-queued for retry:", err);
+ throw err;
+ }
+ } finally {
+ resolveMutex!();
+ }
+ }
+
+ /**
+ * Send events with retry logic
+ */
+ private async sendWithRetry(
+ data: IFormoEventFlushPayload[],
+ attempt = 0
+ ): Promise {
+ try {
+ const response = await fetch(this.apiHost, {
+ method: "POST",
+ headers: EVENTS_API_REQUEST_HEADER(this.writeKey),
+ body: JSON.stringify(data),
+ });
+
+ if (!response.ok) {
+ const shouldRetry = this.shouldRetry(response.status);
+ if (shouldRetry && attempt < this.retryCount) {
+ const delay = Math.pow(2, attempt) * 1000;
+ await new Promise((resolve) => setTimeout(() => resolve(), delay));
+ return this.sendWithRetry(data, attempt + 1);
+ }
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ } catch (error) {
+ if (isNetworkError(error) && attempt < this.retryCount) {
+ const delay = Math.pow(2, attempt) * 1000;
+ logger.warn(`Network error, retrying in ${delay}ms...`);
+ await new Promise((resolve) => setTimeout(() => resolve(), delay));
+ return this.sendWithRetry(data, attempt + 1);
+ }
+ throw error;
+ }
+ }
+
+ /**
+ * Check if error should be retried
+ */
+ private shouldRetry(status: number): boolean {
+ // Retry on server errors (5xx) and rate limiting (429)
+ return (status >= 500 && status <= 599) || status === 429;
+ }
+
+ /**
+ * Discard all pending events without sending them.
+ * Used when the user opts out of tracking to prevent queued events
+ * from being sent after consent is revoked.
+ */
+ public clear(): void {
+ this.queue = [];
+ this.payloadHashes.clear();
+
+ if (this.timer) {
+ clearTimeout(this.timer);
+ this.timer = null;
+ }
+
+ logger.debug("EventQueue: Cleared all pending events");
+ }
+
+ /**
+ * Clean up resources, flushing any pending events first
+ */
+ public async cleanup(): Promise {
+ // Flush all remaining queued events before teardown
+ // Loop until queue is empty since flush() only sends flushAt events per call
+ // Safety limit prevents infinite loops if flush silently fails
+ const maxAttempts = Math.ceil(this.queue.length / this.flushAt) + 3;
+ let attempts = 0;
+ const initialQueueLength = this.queue.length;
+
+ while (this.queue.length > 0 && attempts < maxAttempts) {
+ const queueLengthBefore = this.queue.length;
+ try {
+ await this.flush();
+ } catch (error) {
+ logger.error("EventQueue: Failed to flush during cleanup", error);
+ // Break on error to avoid infinite loop if flush keeps failing
+ break;
+ }
+
+ // If queue length didn't decrease, flush is silently failing
+ if (this.queue.length >= queueLengthBefore) {
+ logger.warn("EventQueue: Flush did not reduce queue size, aborting cleanup");
+ break;
+ }
+
+ attempts++;
+ }
+
+ if (attempts >= maxAttempts && this.queue.length > 0) {
+ logger.warn(
+ `EventQueue: Cleanup safety limit reached. Discarding ${this.queue.length} events.`
+ );
+ this.queue = [];
+ this.payloadHashes.clear();
+ }
+
+ if (initialQueueLength > 0) {
+ logger.debug(`EventQueue: Cleanup completed, flushed ${initialQueueLength - this.queue.length} events`);
+ }
+
+ if (this.timer) {
+ clearTimeout(this.timer);
+ this.timer = null;
+ }
+
+ if (this.appStateSubscription) {
+ this.appStateSubscription.remove();
+ this.appStateSubscription = null;
+ }
+ }
+}
diff --git a/src/lib/event/index.ts b/src/lib/event/index.ts
new file mode 100644
index 0000000..d592a38
--- /dev/null
+++ b/src/lib/event/index.ts
@@ -0,0 +1,4 @@
+export * from "./EventFactory";
+export * from "./EventManager";
+export * from "./EventQueue";
+export * from "./types";
diff --git a/src/lib/event/types.ts b/src/lib/event/types.ts
new file mode 100644
index 0000000..b854115
--- /dev/null
+++ b/src/lib/event/types.ts
@@ -0,0 +1,104 @@
+import {
+ Address,
+ APIEvent,
+ IFormoEvent,
+ IFormoEventContext,
+ IFormoEventProperties,
+ Nullable,
+ SignatureStatus,
+ TransactionStatus,
+ ChainID,
+} from "../../types";
+
+export interface IEventFactory {
+ create(
+ event: APIEvent,
+ address?: Address,
+ userId?: string
+ ): Promise;
+
+ generateScreenEvent(
+ name: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateDetectWalletEvent(
+ providerName: string,
+ rdns: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateIdentifyEvent(
+ providerName: string,
+ rdns: string,
+ address: Nullable,
+ userId?: Nullable,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateConnectEvent(
+ chainId: ChainID,
+ address: Address,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateDisconnectEvent(
+ chainId?: ChainID,
+ address?: Address,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateChainChangedEvent(
+ chainId: ChainID,
+ address: Address,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateSignatureEvent(
+ status: SignatureStatus,
+ chainId: ChainID,
+ address: Address,
+ message: string,
+ signatureHash?: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateTransactionEvent(
+ status: TransactionStatus,
+ chainId: ChainID,
+ address: Address,
+ data: string,
+ to: string,
+ value: string,
+ transactionHash?: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+
+ generateTrackEvent(
+ event: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext
+ ): Promise;
+}
+
+export interface IEventManager {
+ addEvent(event: APIEvent, address?: Address, userId?: string): Promise;
+}
+
+export interface IEventQueue {
+ enqueue(
+ event: IFormoEvent,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ flush(callback?: (...args: unknown[]) => void): Promise;
+ clear(): void;
+ cleanup(): Promise;
+}
diff --git a/src/lib/logger/index.ts b/src/lib/logger/index.ts
new file mode 100644
index 0000000..a91cf52
--- /dev/null
+++ b/src/lib/logger/index.ts
@@ -0,0 +1,56 @@
+export type LogLevel = "debug" | "info" | "warn" | "error" | "log";
+
+interface LoggerConfig {
+ enabled?: boolean;
+ enabledLevels?: LogLevel[];
+}
+
+class LoggerClass {
+ private config: LoggerConfig = {
+ enabled: false,
+ enabledLevels: [],
+ };
+
+ init(config: LoggerConfig) {
+ this.config = config;
+ }
+
+ private shouldLog(level: LogLevel): boolean {
+ if (!this.config.enabled) return false;
+ if (this.config.enabledLevels?.length === 0) return true;
+ return this.config.enabledLevels?.includes(level) ?? false;
+ }
+
+ debug(...args: unknown[]) {
+ if (this.shouldLog("debug")) {
+ console.debug("[Formo RN]", ...args);
+ }
+ }
+
+ info(...args: unknown[]) {
+ if (this.shouldLog("info")) {
+ console.info("[Formo RN]", ...args);
+ }
+ }
+
+ warn(...args: unknown[]) {
+ if (this.shouldLog("warn")) {
+ console.warn("[Formo RN]", ...args);
+ }
+ }
+
+ error(...args: unknown[]) {
+ if (this.shouldLog("error")) {
+ console.error("[Formo RN]", ...args);
+ }
+ }
+
+ log(...args: unknown[]) {
+ if (this.shouldLog("log")) {
+ console.log("[Formo RN]", ...args);
+ }
+ }
+}
+
+export const Logger = new LoggerClass();
+export const logger = Logger;
diff --git a/src/lib/session/index.ts b/src/lib/session/index.ts
new file mode 100644
index 0000000..ab97e3c
--- /dev/null
+++ b/src/lib/session/index.ts
@@ -0,0 +1,103 @@
+import {
+ SESSION_WALLET_DETECTED_KEY,
+ SESSION_WALLET_IDENTIFIED_KEY,
+} from "../../constants";
+import { storage } from "../storage";
+import { logger } from "../logger";
+
+export { SESSION_WALLET_DETECTED_KEY, SESSION_WALLET_IDENTIFIED_KEY };
+
+/**
+ * Session manager for tracking wallet detection and identification
+ * Persists to session storage to avoid duplicate detection/identification events
+ * within the same session
+ */
+export class FormoAnalyticsSession {
+ private detectedWallets: Set = new Set();
+ private identifiedWallets: Set = new Set();
+
+ constructor() {
+ this.loadFromStorage();
+ }
+
+ /**
+ * Load session state from storage
+ */
+ private loadFromStorage(): void {
+ try {
+ const detected = storage().get(SESSION_WALLET_DETECTED_KEY);
+ if (detected) {
+ const parsed = JSON.parse(detected) as string[];
+ this.detectedWallets = new Set(parsed);
+ }
+
+ const identified = storage().get(SESSION_WALLET_IDENTIFIED_KEY);
+ if (identified) {
+ const parsed = JSON.parse(identified) as string[];
+ this.identifiedWallets = new Set(parsed);
+ }
+ } catch (error) {
+ logger.debug("Session: Failed to load from storage", error);
+ }
+ }
+
+ /**
+ * Save session state to storage
+ */
+ private saveToStorage(): void {
+ try {
+ storage().set(
+ SESSION_WALLET_DETECTED_KEY,
+ JSON.stringify(Array.from(this.detectedWallets))
+ );
+ storage().set(
+ SESSION_WALLET_IDENTIFIED_KEY,
+ JSON.stringify(Array.from(this.identifiedWallets))
+ );
+ } catch (error) {
+ logger.debug("Session: Failed to save to storage", error);
+ }
+ }
+
+ /**
+ * Check if a wallet has been detected in this session
+ */
+ public isWalletDetected(rdns: string): boolean {
+ return this.detectedWallets.has(rdns);
+ }
+
+ /**
+ * Mark a wallet as detected
+ */
+ public markWalletDetected(rdns: string): void {
+ this.detectedWallets.add(rdns);
+ this.saveToStorage();
+ }
+
+ /**
+ * Check if a wallet + address combination has been identified
+ */
+ public isWalletIdentified(address: string, rdns: string): boolean {
+ const key = `${address.toLowerCase()}:${rdns}`;
+ return this.identifiedWallets.has(key);
+ }
+
+ /**
+ * Mark a wallet + address combination as identified
+ */
+ public markWalletIdentified(address: string, rdns: string): void {
+ const key = `${address.toLowerCase()}:${rdns}`;
+ this.identifiedWallets.add(key);
+ this.saveToStorage();
+ }
+
+ /**
+ * Clear all session data
+ */
+ public clear(): void {
+ this.detectedWallets.clear();
+ this.identifiedWallets.clear();
+ storage().remove(SESSION_WALLET_DETECTED_KEY);
+ storage().remove(SESSION_WALLET_IDENTIFIED_KEY);
+ }
+}
diff --git a/src/lib/storage/AsyncStorageAdapter.ts b/src/lib/storage/AsyncStorageAdapter.ts
new file mode 100644
index 0000000..4eec6b7
--- /dev/null
+++ b/src/lib/storage/AsyncStorageAdapter.ts
@@ -0,0 +1,173 @@
+import StorageBlueprint from "./StorageBlueprint";
+import { AsyncStorageInterface } from "./types";
+import { logger } from "../logger";
+
+/**
+ * AsyncStorage adapter for React Native
+ * Provides persistent storage across app restarts
+ */
+class AsyncStorageAdapter extends StorageBlueprint {
+ private asyncStorage: AsyncStorageInterface | null = null;
+ private cache: Map = new Map();
+
+ constructor(writeKey: string, asyncStorage?: AsyncStorageInterface) {
+ super(writeKey);
+ if (asyncStorage) {
+ this.asyncStorage = asyncStorage;
+ }
+ }
+
+ /**
+ * Initialize with AsyncStorage instance and preload all Formo keys
+ * This ensures consent flags and other critical data are available synchronously
+ */
+ public async initialize(asyncStorage: AsyncStorageInterface): Promise {
+ this.asyncStorage = asyncStorage;
+
+ // Preload all Formo keys into cache for synchronous access
+ // This is critical for consent checks on cold start (GDPR compliance)
+ try {
+ const allKeys = await asyncStorage.getAllKeys();
+ // getKey("") returns "formo_rn_{writeKey}_" - use this exact prefix
+ // to avoid matching keys from other instances (e.g., "abc" matching "abc123")
+ const formoPrefix = this.getKey("");
+
+ // Filter to only our keys (exact prefix match including trailing underscore)
+ const formoKeys = allKeys.filter((key) => key.startsWith(formoPrefix));
+
+ if (formoKeys.length > 0) {
+ const pairs = await asyncStorage.multiGet(formoKeys);
+ for (const [key, value] of pairs) {
+ if (value !== null) {
+ this.cache.set(key, value);
+ }
+ }
+ logger.debug(
+ `AsyncStorageAdapter: Preloaded ${formoKeys.length} keys into cache`
+ );
+ }
+ } catch (error) {
+ logger.error("AsyncStorageAdapter: Failed to preload keys", error);
+ }
+
+ logger.debug("AsyncStorageAdapter: Initialized");
+ }
+
+ public isAvailable(): boolean {
+ return this.asyncStorage !== null;
+ }
+
+ /**
+ * Synchronous get from cache (may return stale data)
+ * Use getAsync for guaranteed fresh data
+ */
+ public get(key: string): string | null {
+ const cachedValue = this.cache.get(this.getKey(key));
+ if (cachedValue !== undefined) {
+ return cachedValue;
+ }
+
+ // Trigger async fetch to populate cache
+ this.getAsync(key).catch(() => {
+ // Ignore errors in background fetch
+ });
+
+ return null;
+ }
+
+ /**
+ * Async get from storage
+ */
+ public async getAsync(key: string): Promise {
+ if (!this.asyncStorage) {
+ return this.cache.get(this.getKey(key)) ?? null;
+ }
+
+ try {
+ const fullKey = this.getKey(key);
+ const value = await this.asyncStorage.getItem(fullKey);
+
+ if (value !== null) {
+ this.cache.set(fullKey, value);
+ }
+
+ return value;
+ } catch (error) {
+ logger.error("AsyncStorageAdapter: Failed to get item", error);
+ return this.cache.get(this.getKey(key)) ?? null;
+ }
+ }
+
+ /**
+ * Synchronous set (writes to cache immediately, persists async)
+ */
+ public set(key: string, value: string): void {
+ const fullKey = this.getKey(key);
+ this.cache.set(fullKey, value);
+
+ // Persist asynchronously
+ this.setAsync(key, value).catch((error) => {
+ logger.error("AsyncStorageAdapter: Failed to persist item", error);
+ });
+ }
+
+ /**
+ * Async set to storage
+ */
+ public async setAsync(key: string, value: string): Promise {
+ const fullKey = this.getKey(key);
+ this.cache.set(fullKey, value);
+
+ if (!this.asyncStorage) {
+ return;
+ }
+
+ try {
+ await this.asyncStorage.setItem(fullKey, value);
+ } catch (error) {
+ logger.error("AsyncStorageAdapter: Failed to set item", error);
+ throw error;
+ }
+ }
+
+ /**
+ * Synchronous remove (removes from cache immediately, persists async)
+ */
+ public remove(key: string): void {
+ const fullKey = this.getKey(key);
+ this.cache.delete(fullKey);
+
+ // Persist asynchronously
+ this.removeAsync(key).catch((error) => {
+ logger.error("AsyncStorageAdapter: Failed to remove item", error);
+ });
+ }
+
+ /**
+ * Async remove from storage
+ */
+ public async removeAsync(key: string): Promise {
+ const fullKey = this.getKey(key);
+ this.cache.delete(fullKey);
+
+ if (!this.asyncStorage) {
+ return;
+ }
+
+ try {
+ await this.asyncStorage.removeItem(fullKey);
+ } catch (error) {
+ logger.error("AsyncStorageAdapter: Failed to remove item", error);
+ throw error;
+ }
+ }
+
+ /**
+ * Clear all cached data
+ */
+ public clearCache(): void {
+ this.cache.clear();
+ }
+}
+
+export default AsyncStorageAdapter;
diff --git a/src/lib/storage/MemoryStorage.ts b/src/lib/storage/MemoryStorage.ts
new file mode 100644
index 0000000..5aac1b2
--- /dev/null
+++ b/src/lib/storage/MemoryStorage.ts
@@ -0,0 +1,43 @@
+import StorageBlueprint from "./StorageBlueprint";
+
+/**
+ * In-memory storage fallback
+ * Data is lost when the app is closed
+ */
+class MemoryStorage extends StorageBlueprint {
+ private storage: Map = new Map();
+
+ public isAvailable(): boolean {
+ return true;
+ }
+
+ public get(key: string): string | null {
+ return this.storage.get(this.getKey(key)) ?? null;
+ }
+
+ public async getAsync(key: string): Promise {
+ return this.get(key);
+ }
+
+ public set(key: string, value: string): void {
+ this.storage.set(this.getKey(key), value);
+ }
+
+ public async setAsync(key: string, value: string): Promise {
+ this.set(key, value);
+ }
+
+ public remove(key: string): void {
+ this.storage.delete(this.getKey(key));
+ }
+
+ public async removeAsync(key: string): Promise {
+ this.remove(key);
+ }
+
+ public clear(): void {
+ this.storage.clear();
+ }
+}
+
+export default MemoryStorage;
diff --git a/src/lib/storage/StorageBlueprint.ts b/src/lib/storage/StorageBlueprint.ts
new file mode 100644
index 0000000..59d4ba5
--- /dev/null
+++ b/src/lib/storage/StorageBlueprint.ts
@@ -0,0 +1,30 @@
+import { STORAGE_PREFIX } from "../../constants";
+import { IStorage } from "./types";
+
+/**
+ * Base storage class with key prefixing
+ */
+abstract class StorageBlueprint implements IStorage {
+ protected writeKey: string;
+
+ constructor(writeKey: string) {
+ this.writeKey = writeKey;
+ }
+
+ /**
+ * Generate storage key with prefix
+ */
+ public getKey(key: string): string {
+ return `${STORAGE_PREFIX}${this.writeKey}_${key}`;
+ }
+
+ abstract isAvailable(): boolean;
+ abstract get(key: string): string | null;
+ abstract getAsync(key: string): Promise;
+ abstract set(key: string, value: string): void;
+ abstract setAsync(key: string, value: string): Promise;
+ abstract remove(key: string): void;
+ abstract removeAsync(key: string): Promise;
+}
+
+export default StorageBlueprint;
diff --git a/src/lib/storage/StorageManager.ts b/src/lib/storage/StorageManager.ts
new file mode 100644
index 0000000..c924bed
--- /dev/null
+++ b/src/lib/storage/StorageManager.ts
@@ -0,0 +1,112 @@
+import { logger } from "../logger";
+import AsyncStorageAdapter from "./AsyncStorageAdapter";
+import MemoryStorage from "./MemoryStorage";
+import { IStorage, StorageType, AsyncStorageInterface } from "./types";
+
+/**
+ * Storage manager for React Native SDK
+ * Uses AsyncStorage as primary storage with MemoryStorage fallback
+ */
+export class StorageManager {
+ private storages: Map = new Map();
+
+ constructor(private readonly writeKey: string) {}
+
+ /**
+ * Initialize with AsyncStorage instance
+ * This should be called during SDK initialization
+ */
+ public async initialize(asyncStorage: AsyncStorageInterface): Promise {
+ // Create and initialize the AsyncStorage adapter directly.
+ // We bypass getStorage() here because it checks isAvailable() which
+ // returns false on an uninitialized adapter and would fall back to
+ // MemoryStorage, causing a crash when we call adapter.initialize().
+ const adapter = new AsyncStorageAdapter(this.writeKey);
+ await adapter.initialize(asyncStorage);
+ this.storages.set("asyncStorage", adapter);
+
+ logger.debug("StorageManager: Initialized with AsyncStorage");
+ }
+
+ /**
+ * Get storage instance by type
+ */
+ public getStorage(type: StorageType): IStorage {
+ if (!this.storages.has(type)) {
+ const storage = this.createStorage(type);
+
+ // If storage is not available, fallback to memory and cache the fallback
+ if (!storage.isAvailable() && type !== "memoryStorage") {
+ logger.warn(
+ `Storage ${type} is not available, falling back to memoryStorage`
+ );
+ const fallback = this.getStorage("memoryStorage");
+ this.storages.set(type, fallback);
+ return fallback;
+ }
+
+ this.storages.set(type, storage);
+ }
+
+ return this.storages.get(type)!;
+ }
+
+ /**
+ * Create storage instance
+ */
+ private createStorage(type: StorageType): IStorage {
+ switch (type) {
+ case "asyncStorage":
+ return new AsyncStorageAdapter(this.writeKey);
+
+ case "memoryStorage":
+ default:
+ return new MemoryStorage(this.writeKey);
+ }
+ }
+
+ /**
+ * Get primary storage (AsyncStorage with fallback)
+ */
+ public getPrimaryStorage(): IStorage {
+ const asyncStorage = this.getStorage("asyncStorage");
+ if (asyncStorage.isAvailable()) {
+ return asyncStorage;
+ }
+ return this.getStorage("memoryStorage");
+ }
+}
+
+// Global storage manager instance
+let storageManagerInstance: StorageManager | null = null;
+
+/**
+ * Initialize global storage manager
+ */
+export function initStorageManager(writeKey: string): StorageManager {
+ if (!storageManagerInstance || storageManagerInstance["writeKey"] !== writeKey) {
+ // Clean up old instance before creating new one
+ if (storageManagerInstance) {
+ logger.debug("StorageManager: Replacing instance with new writeKey");
+ }
+ storageManagerInstance = new StorageManager(writeKey);
+ }
+ return storageManagerInstance;
+}
+
+/**
+ * Get global storage manager instance
+ */
+export function getStorageManager(): StorageManager | null {
+ return storageManagerInstance;
+}
+
+/**
+ * Get primary storage
+ */
+export function storage(): IStorage {
+ if (!storageManagerInstance) {
+ throw new Error("StorageManager not initialized. Call initStorageManager first.");
+ }
+ return storageManagerInstance.getPrimaryStorage();
+}
diff --git a/src/lib/storage/index.ts b/src/lib/storage/index.ts
new file mode 100644
index 0000000..a21299e
--- /dev/null
+++ b/src/lib/storage/index.ts
@@ -0,0 +1,4 @@
+export * from "./StorageManager";
+export * from "./types";
+export { default as AsyncStorageAdapter } from "./AsyncStorageAdapter";
+export { default as MemoryStorage } from "./MemoryStorage";
diff --git a/src/lib/storage/types.ts b/src/lib/storage/types.ts
new file mode 100644
index 0000000..a7fadf0
--- /dev/null
+++ b/src/lib/storage/types.ts
@@ -0,0 +1,23 @@
+export type StorageType = "asyncStorage" | "memoryStorage";
+
+export interface IStorage {
+ isAvailable(): boolean;
+ get(key: string): string | null;
+ getAsync(key: string): Promise;
+ set(key: string, value: string): void;
+ setAsync(key: string, value: string): Promise;
+ remove(key: string): void;
+ removeAsync(key: string): Promise;
+ getKey(key: string): string;
+}
+
+export interface AsyncStorageInterface {
+ getItem(key: string): Promise;
+ setItem(key: string, value: string): Promise;
+ removeItem(key: string): Promise;
+ getAllKeys(): Promise;
+ multiGet(keys: readonly string[]): Promise;
+ multiSet?(keyValuePairs: [string, string][]): Promise;
+ multiRemove(keys: readonly string[]): Promise;
+ clear?(): Promise;
+}
diff --git a/src/lib/wagmi/WagmiEventHandler.ts b/src/lib/wagmi/WagmiEventHandler.ts
new file mode 100644
index 0000000..5ce8f41
--- /dev/null
+++ b/src/lib/wagmi/WagmiEventHandler.ts
@@ -0,0 +1,574 @@
+/**
+ * WagmiEventHandler for React Native
+ *
+ * Handles wallet event tracking by hooking into Wagmi v2's config.subscribe()
+ * and TanStack Query's MutationCache.
+ */
+
+import { SignatureStatus, TransactionStatus } from "../../types/events";
+import { logger } from "../logger";
+import {
+ WagmiConfig,
+ WagmiState,
+ QueryClient,
+ MutationCacheEvent,
+ UnsubscribeFn,
+ WagmiTrackingState,
+ WagmiMutationKey,
+} from "./types";
+
+// Interface for FormoAnalytics to avoid circular dependency
+interface IFormoAnalyticsInstance {
+ connect(
+ params: { chainId: number; address: string },
+ properties?: Record
+ ): Promise;
+ disconnect(params?: {
+ chainId?: number;
+ address?: string;
+ }): Promise;
+ chain(params: { chainId: number; address?: string }): Promise;
+ signature(params: {
+ status: SignatureStatus;
+ chainId: number;
+ address: string;
+ message: string;
+ signatureHash?: string;
+ }): Promise;
+ transaction(params: {
+ status: TransactionStatus;
+ chainId: number;
+ address: string;
+ data?: string;
+ to?: string;
+ value?: string;
+ transactionHash?: string;
+ }): Promise;
+ isAutocaptureEnabled(
+ eventType: "connect" | "disconnect" | "signature" | "transaction" | "chain"
+ ): boolean;
+}
+
+export class WagmiEventHandler {
+ private formo: IFormoAnalyticsInstance;
+ private wagmiConfig: WagmiConfig;
+ private queryClient?: QueryClient;
+ private unsubscribers: UnsubscribeFn[] = [];
+ private trackingState: WagmiTrackingState = {
+ isProcessing: false,
+ };
+ private processedMutations = new Set();
+ private pendingStatusChanges: Array<{
+ status: WagmiState["status"];
+ prevStatus: WagmiState["status"];
+ }> = [];
+
+ constructor(
+ formoAnalytics: IFormoAnalyticsInstance,
+ wagmiConfig: WagmiConfig,
+ queryClient?: QueryClient
+ ) {
+ this.formo = formoAnalytics;
+ this.wagmiConfig = wagmiConfig;
+ this.queryClient = queryClient;
+
+ logger.info("WagmiEventHandler: Initializing Wagmi integration");
+
+ this.setupConnectionListeners();
+
+ if (this.queryClient) {
+ this.setupMutationTracking();
+ } else {
+ logger.warn(
+ "WagmiEventHandler: QueryClient not provided, signature and transaction events will not be tracked"
+ );
+ }
+ }
+
+ /**
+ * Set up listeners for wallet connection, disconnection, and chain changes
+ */
+ private setupConnectionListeners(): void {
+ logger.info("WagmiEventHandler: Setting up connection listeners");
+
+ // Subscribe to status changes
+ const statusUnsubscribe = this.wagmiConfig.subscribe(
+ (state: WagmiState) => state.status,
+ (status, prevStatus) => {
+ this.handleStatusChange(status, prevStatus);
+ }
+ );
+ this.unsubscribers.push(statusUnsubscribe);
+
+ // Subscribe to chain ID changes
+ const chainIdUnsubscribe = this.wagmiConfig.subscribe(
+ (state: WagmiState) => state.chainId,
+ (chainId, prevChainId) => {
+ this.handleChainChange(chainId, prevChainId);
+ }
+ );
+ this.unsubscribers.push(chainIdUnsubscribe);
+
+ logger.info("WagmiEventHandler: Connection listeners set up successfully");
+ }
+
+ // Maximum pending status changes to prevent unbounded queue growth
+ private static readonly MAX_PENDING_STATUS_CHANGES = 10;
+
+ /**
+ * Handle status changes (connect/disconnect)
+ */
+ private async handleStatusChange(
+ status: WagmiState["status"],
+ prevStatus: WagmiState["status"]
+ ): Promise {
+ if (this.trackingState.isProcessing) {
+ // Limit queue size to prevent unbounded growth during rapid status changes
+ if (this.pendingStatusChanges.length >= WagmiEventHandler.MAX_PENDING_STATUS_CHANGES) {
+ logger.warn("WagmiEventHandler: Pending status change queue full, dropping oldest");
+ this.pendingStatusChanges.shift();
+ }
+ // Queue status change to process after current one completes
+ this.pendingStatusChanges.push({ status, prevStatus });
+ logger.debug(
+ "WagmiEventHandler: Queuing status change for later processing"
+ );
+ return;
+ }
+
+ this.trackingState.isProcessing = true;
+
+ try {
+ // Process current status change
+ await this.processStatusChange(status, prevStatus);
+
+ // Process pending status changes iteratively (inline, no recursion)
+ while (this.pendingStatusChanges.length > 0) {
+ const pending = this.pendingStatusChanges.shift()!;
+ await this.processStatusChange(pending.status, pending.prevStatus);
+ }
+ } finally {
+ this.trackingState.isProcessing = false;
+ }
+ }
+
+ /**
+ * Process a single status change (extracted for iterative processing)
+ */
+ private async processStatusChange(
+ status: WagmiState["status"],
+ prevStatus: WagmiState["status"]
+ ): Promise {
+ try {
+ const state = this.getState();
+ const address = this.getConnectedAddress(state);
+ const chainId = state.chainId;
+
+ logger.info("WagmiEventHandler: Status changed", {
+ status,
+ prevStatus,
+ address,
+ chainId,
+ });
+
+ // Handle disconnect
+ if (status === "disconnected" && prevStatus === "connected") {
+ if (this.formo.isAutocaptureEnabled("disconnect")) {
+ await this.formo.disconnect({
+ chainId: this.trackingState.lastChainId,
+ address: this.trackingState.lastAddress,
+ });
+ }
+ this.trackingState.lastAddress = undefined;
+ this.trackingState.lastChainId = undefined;
+ }
+
+ // Handle connect
+ if (status === "connected" && prevStatus !== "connected") {
+ if (address && chainId !== undefined) {
+ this.trackingState.lastAddress = address;
+ this.trackingState.lastChainId = chainId;
+
+ if (this.formo.isAutocaptureEnabled("connect")) {
+ const connectorName = this.getConnectorName(state);
+ const connectorId = this.getConnectorId(state);
+ await this.formo.connect(
+ { chainId, address },
+ {
+ ...(connectorName && { providerName: connectorName }),
+ // Connector ID is typically the rdns for EIP-6963 wallets
+ ...(connectorId && { rdns: connectorId }),
+ }
+ );
+ }
+ }
+ }
+
+ this.trackingState.lastStatus = status;
+ } catch (error) {
+ logger.error("WagmiEventHandler: Error handling status change:", error);
+ }
+ }
+
+ /**
+ * Handle chain ID changes
+ */
+ private async handleChainChange(
+ chainId: number | undefined,
+ prevChainId: number | undefined
+ ): Promise {
+ // Skip if no change, chainId is undefined, or this is initial connection (prevChainId undefined)
+ if (chainId === prevChainId || chainId === undefined || prevChainId === undefined) {
+ return;
+ }
+
+ const state = this.getState();
+ if (state.status !== "connected") {
+ return;
+ }
+
+ const address = this.getConnectedAddress(state);
+ if (!address) {
+ logger.warn("WagmiEventHandler: Chain changed but no address found");
+ return;
+ }
+
+ logger.info("WagmiEventHandler: Chain changed", {
+ chainId,
+ prevChainId,
+ address,
+ });
+
+ this.trackingState.lastChainId = chainId;
+
+ if (this.formo.isAutocaptureEnabled("chain")) {
+ try {
+ await this.formo.chain({ chainId, address });
+ } catch (error) {
+ logger.error("WagmiEventHandler: Error tracking chain change:", error);
+ }
+ }
+ }
+
+ /**
+ * Set up mutation tracking for signatures and transactions
+ */
+ private setupMutationTracking(): void {
+ if (!this.queryClient) {
+ return;
+ }
+
+ logger.info("WagmiEventHandler: Setting up mutation tracking");
+
+ const mutationCache = this.queryClient.getMutationCache();
+ const unsubscribe = mutationCache.subscribe((event: MutationCacheEvent) => {
+ this.handleMutationEvent(event);
+ });
+
+ this.unsubscribers.push(unsubscribe);
+ logger.info("WagmiEventHandler: Mutation tracking set up successfully");
+ }
+
+ /**
+ * Handle mutation cache events
+ */
+ private handleMutationEvent(event: MutationCacheEvent): void {
+ if (event.type !== "updated") {
+ return;
+ }
+
+ const mutation = event.mutation;
+ const mutationKey = mutation.options.mutationKey;
+
+ if (!mutationKey || mutationKey.length === 0) {
+ return;
+ }
+
+ const mutationType = mutationKey[0] as string;
+ const state = mutation.state;
+
+ const mutationStateKey = `${mutation.mutationId}:${state.status}`;
+
+ if (this.processedMutations.has(mutationStateKey)) {
+ return;
+ }
+
+ this.processedMutations.add(mutationStateKey);
+
+ logger.debug("WagmiEventHandler: Mutation event", {
+ mutationType,
+ mutationId: mutation.mutationId,
+ status: state.status,
+ });
+
+ if (mutationType === "signMessage" || mutationType === "signTypedData") {
+ this.handleSignatureMutation(
+ mutationType as WagmiMutationKey,
+ mutation
+ );
+ }
+
+ if (
+ mutationType === "sendTransaction" ||
+ mutationType === "writeContract"
+ ) {
+ this.handleTransactionMutation(
+ mutationType as WagmiMutationKey,
+ mutation
+ );
+ }
+
+ // Cleanup old mutations
+ if (this.processedMutations.size > 1000) {
+ const entries = Array.from(this.processedMutations);
+ for (let i = 0; i < 500; i++) {
+ const entry = entries[i];
+ if (entry) {
+ this.processedMutations.delete(entry);
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle signature mutations
+ */
+ private handleSignatureMutation(
+ mutationType: WagmiMutationKey,
+ mutation: MutationCacheEvent["mutation"]
+ ): void {
+ if (!this.formo.isAutocaptureEnabled("signature")) {
+ return;
+ }
+
+ const state = mutation.state;
+ const variables = state.variables || {};
+ const chainId = this.trackingState.lastChainId;
+ const address = this.trackingState.lastAddress;
+
+ if (!address) {
+ logger.warn(
+ "WagmiEventHandler: Signature event but no address available"
+ );
+ return;
+ }
+
+ if (!chainId || chainId === 0) {
+ logger.warn(
+ "WagmiEventHandler: Signature event but no valid chainId available"
+ );
+ return;
+ }
+
+ try {
+ let status: SignatureStatus;
+ let signatureHash: string | undefined;
+
+ if (state.status === "pending") {
+ status = SignatureStatus.REQUESTED;
+ } else if (state.status === "success") {
+ status = SignatureStatus.CONFIRMED;
+ signatureHash = state.data as string;
+ } else if (state.status === "error") {
+ status = SignatureStatus.REJECTED;
+ } else {
+ return;
+ }
+
+ let message: string;
+ if (mutationType === "signMessage") {
+ message = (variables.message as string) || "";
+ } else {
+ message = JSON.stringify(variables.message || variables.types || {});
+ }
+
+ logger.info("WagmiEventHandler: Tracking signature event", {
+ status,
+ mutationType,
+ address,
+ chainId,
+ });
+
+ this.formo.signature({
+ status,
+ chainId,
+ address,
+ message,
+ ...(signatureHash && { signatureHash }),
+ }).catch((error) => {
+ logger.error("WagmiEventHandler: Error tracking signature:", error);
+ });
+ } catch (error) {
+ logger.error(
+ "WagmiEventHandler: Error handling signature mutation:",
+ error
+ );
+ }
+ }
+
+ /**
+ * Handle transaction mutations
+ */
+ private handleTransactionMutation(
+ mutationType: WagmiMutationKey,
+ mutation: MutationCacheEvent["mutation"]
+ ): void {
+ if (!this.formo.isAutocaptureEnabled("transaction")) {
+ return;
+ }
+
+ const state = mutation.state;
+ const variables = state.variables || {};
+ const chainId =
+ this.trackingState.lastChainId ||
+ (variables.chainId as number | undefined);
+ // Only use variables.account as fallback, not variables.address which is the contract address
+ const address =
+ this.trackingState.lastAddress ||
+ (variables.account as string | undefined);
+
+ if (!address) {
+ logger.warn(
+ "WagmiEventHandler: Transaction event but no address available"
+ );
+ return;
+ }
+
+ if (!chainId || chainId === 0) {
+ logger.warn(
+ "WagmiEventHandler: Transaction event but no valid chainId available"
+ );
+ return;
+ }
+
+ try {
+ let status: TransactionStatus;
+ let transactionHash: string | undefined;
+
+ if (state.status === "pending") {
+ status = TransactionStatus.STARTED;
+ } else if (state.status === "success") {
+ status = TransactionStatus.BROADCASTED;
+ transactionHash = state.data as string;
+ } else if (state.status === "error") {
+ status = TransactionStatus.REJECTED;
+ } else {
+ return;
+ }
+
+ const data = variables.data as string | undefined;
+ const to =
+ (variables.to as string | undefined) ||
+ (variables.address as string | undefined);
+ const value = variables.value?.toString();
+
+ logger.info("WagmiEventHandler: Tracking transaction event", {
+ status,
+ mutationType,
+ address,
+ chainId,
+ transactionHash,
+ });
+
+ this.formo.transaction({
+ status,
+ chainId,
+ address,
+ ...(data && { data }),
+ ...(to && { to }),
+ ...(value && { value }),
+ ...(transactionHash && { transactionHash }),
+ }).catch((error) => {
+ logger.error("WagmiEventHandler: Error tracking transaction:", error);
+ });
+ } catch (error) {
+ logger.error(
+ "WagmiEventHandler: Error handling transaction mutation:",
+ error
+ );
+ }
+ }
+
+ /**
+ * Get current Wagmi state
+ */
+ private getState(): WagmiState {
+ if (typeof this.wagmiConfig.getState === "function") {
+ return this.wagmiConfig.getState();
+ }
+
+ if (this.wagmiConfig.state) {
+ return this.wagmiConfig.state;
+ }
+
+ logger.warn(
+ "WagmiEventHandler: Unable to get state from config, returning default state"
+ );
+ return {
+ status: "disconnected",
+ connections: new Map(),
+ current: undefined,
+ chainId: undefined,
+ };
+ }
+
+ /**
+ * Get connected address from state
+ */
+ private getConnectedAddress(state: WagmiState): string | undefined {
+ if (!state.current) {
+ return undefined;
+ }
+
+ const connection = state.connections.get(state.current);
+ if (!connection || connection.accounts.length === 0) {
+ return undefined;
+ }
+
+ return connection.accounts[0];
+ }
+
+ /**
+ * Get connector name from state
+ */
+ private getConnectorName(state: WagmiState): string | undefined {
+ if (!state.current) {
+ return undefined;
+ }
+
+ const connection = state.connections.get(state.current);
+ return connection?.connector.name;
+ }
+
+ /**
+ * Get connector ID from state (typically the rdns for EIP-6963 wallets)
+ */
+ private getConnectorId(state: WagmiState): string | undefined {
+ if (!state.current) {
+ return undefined;
+ }
+
+ const connection = state.connections.get(state.current);
+ return connection?.connector.id;
+ }
+
+ /**
+ * Clean up subscriptions
+ */
+ public cleanup(): void {
+ logger.info("WagmiEventHandler: Cleaning up subscriptions");
+
+ for (const unsubscribe of this.unsubscribers) {
+ try {
+ unsubscribe();
+ } catch (error) {
+ logger.error("WagmiEventHandler: Error during cleanup:", error);
+ }
+ }
+
+ this.unsubscribers = [];
+ this.processedMutations.clear();
+ this.pendingStatusChanges = [];
+ logger.info("WagmiEventHandler: Cleanup complete");
+ }
+}
diff --git a/src/lib/wagmi/index.ts b/src/lib/wagmi/index.ts
new file mode 100644
index 0000000..c2c1d2a
--- /dev/null
+++ b/src/lib/wagmi/index.ts
@@ -0,0 +1,2 @@
+export * from "./WagmiEventHandler";
+export * from "./types";
diff --git a/src/lib/wagmi/types.ts b/src/lib/wagmi/types.ts
new file mode 100644
index 0000000..4d4eb3d
--- /dev/null
+++ b/src/lib/wagmi/types.ts
@@ -0,0 +1,71 @@
+/**
+ * Wagmi types for React Native SDK
+ */
+
+export interface WagmiState {
+ status: "connecting" | "connected" | "disconnected" | "reconnecting";
+ connections: Map<
+ string,
+ {
+ accounts: readonly string[];
+ chainId: number;
+ connector: {
+ name: string;
+ /** Connector ID - for EIP-6963 injected wallets, this is typically the rdns */
+ id: string;
+ type?: string;
+ icon?: string;
+ };
+ }
+ >;
+ current?: string;
+ chainId?: number;
+}
+
+export interface WagmiConfig {
+ subscribe: (
+ selector: (state: WagmiState) => T,
+ listener: (selectedState: T, prevSelectedState: T) => void
+ ) => () => void;
+ getState?: () => WagmiState;
+ state?: WagmiState;
+}
+
+export interface QueryClient {
+ getMutationCache: () => MutationCache;
+}
+
+export interface MutationCache {
+ subscribe: (callback: (event: MutationCacheEvent) => void) => () => void;
+}
+
+export interface MutationCacheEvent {
+ type: "added" | "updated" | "removed";
+ mutation: {
+ mutationId: number;
+ options: {
+ mutationKey?: readonly string[];
+ };
+ state: {
+ status: "idle" | "pending" | "success" | "error";
+ data?: unknown;
+ error?: unknown;
+ variables?: Record;
+ };
+ };
+}
+
+export type UnsubscribeFn = () => void;
+
+export interface WagmiTrackingState {
+ isProcessing: boolean;
+ lastAddress?: string;
+ lastChainId?: number;
+ lastStatus?: WagmiState["status"];
+}
+
+export type WagmiMutationKey =
+ | "signMessage"
+ | "signTypedData"
+ | "sendTransaction"
+ | "writeContract";
diff --git a/src/types/base.ts b/src/types/base.ts
new file mode 100644
index 0000000..4f039de
--- /dev/null
+++ b/src/types/base.ts
@@ -0,0 +1,237 @@
+import { ReactNode } from "react";
+import { LogLevel } from "../lib/logger";
+import {
+ IFormoEventContext,
+ IFormoEventProperties,
+ SignatureStatus,
+ TransactionStatus,
+} from "./events";
+
+export type Nullable = T | null;
+// Decimal chain ID
+export type ChainID = number;
+
+// Address (EVM, Solana, etc.)
+export type Address = string;
+
+export type ValidInputTypes = Uint8Array | bigint | string | number | boolean;
+
+export interface IFormoAnalytics {
+ screen(
+ name: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ reset(): void;
+ cleanup(): Promise;
+ detect(
+ params: { rdns: string; providerName: string },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ connect(
+ params: { chainId: ChainID; address: Address },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ disconnect(
+ params?: { chainId?: ChainID; address?: Address },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ chain(
+ params: { chainId: ChainID; address?: Address },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ signature(
+ params: {
+ status: SignatureStatus;
+ chainId: ChainID;
+ address: Address;
+ message: string;
+ signatureHash?: string;
+ },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ transaction(
+ params: {
+ status: TransactionStatus;
+ chainId: ChainID;
+ address: Address;
+ data?: string;
+ to?: string;
+ value?: string;
+ transactionHash?: string;
+ },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ identify(
+ params: {
+ address: Address;
+ providerName?: string;
+ userId?: string;
+ rdns?: string;
+ },
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+ track(
+ event: string,
+ properties?: IFormoEventProperties,
+ context?: IFormoEventContext,
+ callback?: (...args: unknown[]) => void
+ ): Promise;
+
+ // Traffic source management
+ setTrafficSourceFromUrl(url: string): void;
+
+ // Consent management methods
+ optOutTracking(): void;
+ optInTracking(): void;
+ hasOptedOutTracking(): boolean;
+}
+
+export interface Config {
+ writeKey: string;
+}
+
+/**
+ * Configuration options for controlling tracking exclusions
+ */
+export interface TrackingOptions {
+ excludeChains?: ChainID[];
+}
+
+/**
+ * Configuration options for controlling wallet event autocapture
+ * All events are enabled by default unless explicitly set to false
+ */
+export interface AutocaptureOptions {
+ /**
+ * Track wallet connect events
+ * @default true
+ */
+ connect?: boolean;
+
+ /**
+ * Track wallet disconnect events
+ * @default true
+ */
+ disconnect?: boolean;
+
+ /**
+ * Track wallet signature events (personal_sign, eth_signTypedData_v4)
+ * @default true
+ */
+ signature?: boolean;
+
+ /**
+ * Track wallet transaction events (eth_sendTransaction)
+ * @default true
+ */
+ transaction?: boolean;
+
+ /**
+ * Track wallet chain change events
+ * @default true
+ */
+ chain?: boolean;
+}
+
+/**
+ * Configuration options for Wagmi integration
+ * Allows the SDK to hook into Wagmi v2 wallet events
+ */
+export interface WagmiOptions {
+ /**
+ * Wagmi config instance from createConfig()
+ * The SDK will subscribe to this config's state changes to track wallet events
+ */
+ config: any;
+
+ /**
+ * Optional QueryClient instance from @tanstack/react-query
+ * Required for tracking signature and transaction events via mutation cache
+ * If not provided, only connection/disconnection/chain events will be tracked
+ */
+ queryClient?: any;
+}
+
+/**
+ * App information for context enrichment
+ */
+export interface AppInfo {
+ /**
+ * App name
+ */
+ name?: string;
+
+ /**
+ * App version
+ */
+ version?: string;
+
+ /**
+ * App build number
+ */
+ build?: string;
+
+ /**
+ * Bundle/package identifier
+ */
+ bundleId?: string;
+}
+
+export interface Options {
+ tracking?: boolean | TrackingOptions;
+ /**
+ * Control wallet event autocapture
+ * - `false`: Disable all wallet autocapture
+ * - `true`: Enable all wallet events (default)
+ * - `AutocaptureOptions`: Granular control over specific events
+ * @default true
+ */
+ autocapture?: boolean | AutocaptureOptions;
+ /**
+ * Wagmi integration configuration
+ * When provided, the SDK will hook into Wagmi's event system
+ * @requires wagmi@>=2.0.0
+ * @requires @tanstack/react-query@>=5.0.0 (for mutation tracking)
+ */
+ wagmi?: WagmiOptions;
+ /**
+ * Custom API host for sending events
+ */
+ apiHost?: string;
+ flushAt?: number;
+ flushInterval?: number;
+ retryCount?: number;
+ maxQueueSize?: number;
+ logger?: {
+ enabled?: boolean;
+ levels?: LogLevel[];
+ };
+ /**
+ * App information for context enrichment
+ */
+ app?: AppInfo;
+ ready?: (formo: IFormoAnalytics) => void;
+}
+
+export interface FormoAnalyticsProviderProps {
+ writeKey: string;
+ options?: Options;
+ disabled?: boolean;
+ children: ReactNode;
+}
diff --git a/src/types/events.ts b/src/types/events.ts
new file mode 100644
index 0000000..8fa5c12
--- /dev/null
+++ b/src/types/events.ts
@@ -0,0 +1,137 @@
+import { Address, ChainID, Nullable } from "./base";
+import { TEventChannel, TEventType } from "../constants";
+
+export type AnonymousID = string;
+
+export interface ICommonProperties {
+ anonymous_id: AnonymousID;
+ user_id: Nullable;
+ address: Nullable;
+ type: TEventType;
+ channel: TEventChannel;
+ version: string;
+ original_timestamp: string;
+ event?: Nullable;
+}
+
+export type IFormoEventProperties = Record;
+export type IFormoEventContext = Record;
+
+export type UTMParameters = {
+ utm_source: string;
+ utm_medium: string;
+ utm_campaign: string;
+ utm_term: string;
+ utm_content: string;
+};
+
+export type ITrafficSource = UTMParameters & {
+ ref: string;
+ referrer: string;
+};
+
+export interface IFormoEvent extends ICommonProperties {
+ context: Nullable;
+ properties: Nullable;
+}
+
+export type IFormoEventPayload = IFormoEvent & {
+ message_id: string;
+};
+
+//#region Specific Event Types
+export interface ScreenAPIEvent {
+ type: "screen";
+ name: string;
+}
+
+export interface DetectAPIEvent {
+ type: "detect";
+ providerName: string;
+ rdns: string;
+}
+
+export interface IdentifyAPIEvent {
+ type: "identify";
+ address: string;
+ providerName: string;
+ rdns: string;
+ userId?: Nullable;
+}
+
+export interface ChainAPIEvent {
+ type: "chain";
+ chainId: ChainID;
+ address: Address;
+}
+
+export interface TransactionAPIEvent {
+ type: "transaction";
+ status: TransactionStatus;
+ chainId: ChainID;
+ address: Address;
+ data: string;
+ to: string;
+ value: string;
+ transactionHash?: string;
+}
+
+export interface SignatureAPIEvent {
+ type: "signature";
+ status: SignatureStatus;
+ chainId: ChainID;
+ address: Address;
+ message: string;
+ signatureHash?: string;
+}
+
+export interface ConnectAPIEvent {
+ type: "connect";
+ chainId: ChainID;
+ address: Address;
+}
+
+export interface DisconnectAPIEvent {
+ type: "disconnect";
+ chainId?: ChainID;
+ address?: Address;
+}
+
+export interface TrackAPIEvent {
+ type: "track";
+ event: string;
+ volume?: number;
+ revenue?: number;
+ currency?: string;
+ points?: number;
+}
+
+export type APIEvent = {
+ properties?: IFormoEventProperties;
+ context?: IFormoEventContext;
+ callback?: (...args: unknown[]) => void;
+} & (
+ | ScreenAPIEvent
+ | DetectAPIEvent
+ | IdentifyAPIEvent
+ | ChainAPIEvent
+ | TransactionAPIEvent
+ | SignatureAPIEvent
+ | ConnectAPIEvent
+ | DisconnectAPIEvent
+ | TrackAPIEvent
+);
+
+export enum SignatureStatus {
+ REQUESTED = "requested",
+ REJECTED = "rejected",
+ CONFIRMED = "confirmed",
+}
+
+export enum TransactionStatus {
+ STARTED = "started",
+ REJECTED = "rejected",
+ BROADCASTED = "broadcasted",
+ CONFIRMED = "confirmed",
+ REVERTED = "reverted",
+}
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..ba257e3
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,2 @@
+export * from "./base";
+export * from "./events";
diff --git a/src/utils/address.ts b/src/utils/address.ts
new file mode 100644
index 0000000..42c5219
--- /dev/null
+++ b/src/utils/address.ts
@@ -0,0 +1,84 @@
+/**
+ * Address validation and checksum utilities
+ *
+ * Uses ethereum-cryptography for proper EIP-55 checksum computation
+ */
+
+import { keccak256 } from "ethereum-cryptography/keccak.js";
+import { utf8ToBytes } from "ethereum-cryptography/utils.js";
+
+/**
+ * Convert Uint8Array to hex string
+ */
+function toHex(bytes: Uint8Array): string {
+ return Array.from(bytes)
+ .map((b) => b.toString(16).padStart(2, "0"))
+ .join("");
+}
+
+/**
+ * Check if a string is a valid Ethereum address
+ */
+export function isValidAddress(address: string): boolean {
+ if (!address) return false;
+ if (typeof address !== "string") return false;
+
+ // Check if it matches basic hex address format
+ return /^0x[a-fA-F0-9]{40}$/.test(address);
+}
+
+/**
+ * Convert address to EIP-55 checksum format
+ *
+ * Uses keccak256 from ethereum-cryptography for correct checksumming
+ * See: https://eips.ethereum.org/EIPS/eip-55
+ */
+export function toChecksumAddress(address: string): string {
+ if (!isValidAddress(address)) {
+ return address;
+ }
+
+ const lowercaseAddress = address.toLowerCase().replace("0x", "");
+ const hash = toHex(keccak256(utf8ToBytes(lowercaseAddress)));
+
+ let checksumAddress = "0x";
+
+ for (let i = 0; i < lowercaseAddress.length; i++) {
+ const char = lowercaseAddress[i];
+ if (char && parseInt(hash[i] || "0", 16) >= 8) {
+ checksumAddress += char.toUpperCase();
+ } else {
+ checksumAddress += char;
+ }
+ }
+
+ return checksumAddress;
+}
+
+/**
+ * Get valid address or null
+ */
+export function getValidAddress(
+ address: string | undefined | null
+): string | null {
+ if (!address) return null;
+ const trimmed = typeof address === "string" ? address.trim() : address;
+ if (!isValidAddress(trimmed)) return null;
+ return trimmed;
+}
+
+/**
+ * Blocked addresses that should not emit events
+ * (zero address, dead address)
+ */
+const BLOCKED_ADDRESSES = new Set([
+ "0x0000000000000000000000000000000000000000",
+ "0x000000000000000000000000000000000000dead",
+]);
+
+/**
+ * Check if address is in blocked list
+ */
+export function isBlockedAddress(address: string): boolean {
+ return BLOCKED_ADDRESSES.has(address.toLowerCase());
+}
diff --git a/src/utils/hash.ts b/src/utils/hash.ts
new file mode 100644
index 0000000..5d807f5
--- /dev/null
+++ b/src/utils/hash.ts
@@ -0,0 +1,23 @@
+import { sha256 } from "ethereum-cryptography/sha256";
+import { utf8ToBytes, bytesToHex } from "ethereum-cryptography/utils";
+
+/**
+ * Generate a SHA-256 hash for event deduplication
+ * Returns full 64 hex chars to match web SDK format
+ */
+export async function hash(input: string): Promise {
+ const bytes = utf8ToBytes(input);
+ const hashBytes = sha256(bytes);
+ return bytesToHex(hashBytes);
+}
+
+/**
+ * Generate a UUID v4
+ */
+export function generateUUID(): string {
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
+ const r = (Math.random() * 16) | 0;
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
+ return v.toString(16);
+ });
+}
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts
new file mode 100644
index 0000000..916be7c
--- /dev/null
+++ b/src/utils/helpers.ts
@@ -0,0 +1,139 @@
+/**
+ * Clamp a number between min and max values
+ */
+export function clampNumber(value: number, max: number, min: number): number {
+ return Math.min(Math.max(value, min), max);
+}
+
+/**
+ * Check if value is undefined
+ */
+export function isUndefined(value: unknown): value is undefined {
+ return value === undefined;
+}
+
+/**
+ * Convert a camelCase/PascalCase string to snake_case
+ * Handles consecutive uppercase letters (acronyms) correctly:
+ * - "userID" -> "user_id"
+ * - "XMLParser" -> "xml_parser"
+ * - "getHTTPResponse" -> "get_http_response"
+ */
+function camelToSnake(str: string): string {
+ return str
+ // Insert underscore before sequences of uppercase followed by lowercase (e.g., "XMLParser" -> "XML_Parser")
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
+ // Insert underscore before single uppercase preceded by lowercase (e.g., "userID" -> "user_ID")
+ .replace(/([a-z\d])([A-Z])/g, "$1_$2")
+ .toLowerCase();
+}
+
+/**
+ * Check if value is a plain object (not Date, Map, Set, RegExp, etc.)
+ */
+function isPlainObject(value: unknown): value is Record {
+ if (value === null || typeof value !== "object") {
+ return false;
+ }
+ const proto = Object.getPrototypeOf(value);
+ return proto === Object.prototype || proto === null;
+}
+
+/**
+ * Convert object keys to snake_case (recursively handles nested objects and arrays)
+ * Preserves Date, Map, Set, RegExp, and other built-in objects unchanged
+ */
+export function toSnakeCase>(obj: T): T {
+ const result: Record = {};
+
+ for (const [key, value] of Object.entries(obj)) {
+ const snakeKey = camelToSnake(key);
+
+ if (Array.isArray(value)) {
+ // Recursively convert plain objects inside arrays
+ result[snakeKey] = value.map((item) =>
+ isPlainObject(item) ? toSnakeCase(item) : item
+ );
+ } else if (isPlainObject(value)) {
+ result[snakeKey] = toSnakeCase(value);
+ } else {
+ // Preserve Date, Map, Set, RegExp, and other built-in objects unchanged
+ result[snakeKey] = value;
+ }
+ }
+
+ return result as T;
+}
+
+/**
+ * Deep merge two objects
+ */
+export function mergeDeepRight>(
+ target: T,
+ source: Partial
+): T {
+ const output = { ...target };
+
+ for (const key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ const sourceValue = source[key];
+ const targetValue = output[key];
+
+ if (
+ sourceValue !== null &&
+ typeof sourceValue === "object" &&
+ !Array.isArray(sourceValue) &&
+ targetValue !== null &&
+ typeof targetValue === "object" &&
+ !Array.isArray(targetValue)
+ ) {
+ output[key] = mergeDeepRight(
+ targetValue as Record,
+ sourceValue as Record
+ ) as T[Extract];
+ } else if (sourceValue !== undefined) {
+ output[key] = sourceValue as T[Extract];
+ }
+ }
+ }
+
+ return output;
+}
+
+/**
+ * Get action descriptor for logging
+ */
+export function getActionDescriptor(
+ type: string,
+ properties?: Record | null
+): string {
+ if (type === "track" && properties?.event) {
+ return `track:${properties.event}`;
+ }
+ if (type === "screen" && properties?.name) {
+ return `screen:${properties.name}`;
+ }
+ return type;
+}
+
+/**
+ * Check if error is a network error
+ */
+export function isNetworkError(error: unknown): boolean {
+ if (!error) return false;
+
+ const message = error instanceof Error ? error.message : String(error);
+ const networkErrorMessages = [
+ "Network request failed",
+ "Failed to fetch",
+ "Network Error",
+ "timeout",
+ "ETIMEDOUT",
+ "ECONNREFUSED",
+ "ENOTFOUND",
+ ];
+
+ return networkErrorMessages.some((msg) =>
+ message.toLowerCase().includes(msg.toLowerCase())
+ );
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 0000000..b933b7b
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1,5 @@
+export * from "./address";
+export * from "./hash";
+export * from "./timestamp";
+export * from "./helpers";
+export * from "./trafficSource";
diff --git a/src/utils/timestamp.ts b/src/utils/timestamp.ts
new file mode 100644
index 0000000..ebf0802
--- /dev/null
+++ b/src/utils/timestamp.ts
@@ -0,0 +1,25 @@
+/**
+ * Get current time in ISO format
+ */
+export function getCurrentTimeFormatted(): string {
+ return new Date().toISOString();
+}
+
+/**
+ * Format date to YYYY-MM-DD HH:mm format for hashing
+ */
+export function toDateHourMinute(date: Date): string {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ return `${year}-${month}-${day} ${hours}:${minutes}`;
+}
+
+/**
+ * Convert milliseconds to seconds
+ */
+export function millisecondsToSecond(ms: number): number {
+ return Math.floor(ms / 1000);
+}
diff --git a/src/utils/trafficSource.ts b/src/utils/trafficSource.ts
new file mode 100644
index 0000000..88311e4
--- /dev/null
+++ b/src/utils/trafficSource.ts
@@ -0,0 +1,132 @@
+/**
+ * Traffic Source Utilities
+ * Parse UTM parameters and referral information from URLs
+ */
+
+import { logger } from "../lib/logger";
+import { storage } from "../lib/storage";
+import { SESSION_TRAFFIC_SOURCE_KEY } from "../constants";
+import type { ITrafficSource } from "../types";
+
+/**
+ * Parse UTM parameters and referral info from URL
+ * Supports both web URLs (https://) and deep link URLs (myapp://)
+ */
+export function parseTrafficSource(url: string): Partial {
+ try {
+ // Handle deep link URLs that may not have standard URL format
+ let urlObj: URL;
+
+ try {
+ urlObj = new URL(url);
+ } catch {
+ // If URL parsing fails, try to extract query string manually
+ const queryStart = url.indexOf("?");
+ if (queryStart === -1) {
+ return { referrer: url };
+ }
+
+ // Create a fake URL for parsing query params
+ urlObj = new URL(`http://localhost${url.substring(queryStart)}`);
+ }
+
+ const params = urlObj.searchParams;
+ const trafficSource: Partial = {};
+
+ // Extract UTM parameters
+ if (params.has("utm_source")) trafficSource.utm_source = params.get("utm_source")!;
+ if (params.has("utm_medium")) trafficSource.utm_medium = params.get("utm_medium")!;
+ if (params.has("utm_campaign")) trafficSource.utm_campaign = params.get("utm_campaign")!;
+ if (params.has("utm_term")) trafficSource.utm_term = params.get("utm_term")!;
+ if (params.has("utm_content")) trafficSource.utm_content = params.get("utm_content")!;
+
+ // Extract referral codes (check common parameter names)
+ const refParams = ["ref", "referral", "refcode", "referrer_code"];
+ for (const param of refParams) {
+ if (params.has(param)) {
+ trafficSource.ref = params.get(param)!;
+ break;
+ }
+ }
+
+ // Store the full URL as referrer
+ trafficSource.referrer = url;
+
+ return trafficSource;
+ } catch (error) {
+ logger.error("Error parsing traffic source from URL:", error);
+ return { referrer: url };
+ }
+}
+
+/**
+ * Store traffic source in session storage
+ * Only stores if we have actual UTM or ref data
+ */
+export function storeTrafficSource(trafficSource: Partial): void {
+ try {
+ // Check if we have meaningful data to store (not just referrer)
+ const hasData =
+ trafficSource.utm_source ||
+ trafficSource.utm_medium ||
+ trafficSource.utm_campaign ||
+ trafficSource.utm_term ||
+ trafficSource.utm_content ||
+ trafficSource.ref;
+
+ if (hasData || trafficSource.referrer) {
+ storage().set(SESSION_TRAFFIC_SOURCE_KEY, JSON.stringify(trafficSource));
+ logger.debug("Stored traffic source:", trafficSource);
+ }
+ } catch (error) {
+ logger.error("Error storing traffic source:", error);
+ }
+}
+
+/**
+ * Get stored traffic source from session
+ * Returns undefined if no traffic source is stored
+ */
+export function getStoredTrafficSource(): Partial | undefined {
+ try {
+ const stored = storage().get(SESSION_TRAFFIC_SOURCE_KEY);
+ if (stored && typeof stored === "string") {
+ return JSON.parse(stored) as Partial;
+ }
+ } catch (error) {
+ logger.debug("Failed to get stored traffic source:", error);
+ }
+ return undefined;
+}
+
+/**
+ * Clear stored traffic source from session
+ */
+export function clearTrafficSource(): void {
+ try {
+ storage().remove(SESSION_TRAFFIC_SOURCE_KEY);
+ logger.debug("Cleared traffic source from session");
+ } catch (error) {
+ logger.error("Error clearing traffic source:", error);
+ }
+}
+
+/**
+ * Merge stored traffic source with current context
+ * Stored traffic source is used as fallback - current context takes priority
+ */
+export function mergeWithStoredTrafficSource(
+ context?: Record
+): Record {
+ const stored = getStoredTrafficSource();
+
+ if (!stored) {
+ return context || {};
+ }
+
+ // Merge: stored values as base, context values override
+ return {
+ ...stored,
+ ...(context || {}),
+ };
+}
diff --git a/src/version.ts b/src/version.ts
new file mode 100644
index 0000000..5957b07
--- /dev/null
+++ b/src/version.ts
@@ -0,0 +1 @@
+export const version = "1.0.0";
diff --git a/tsconfig.build.json b/tsconfig.build.json
new file mode 100644
index 0000000..bcec3b2
--- /dev/null
+++ b/tsconfig.build.json
@@ -0,0 +1,13 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "noEmit": false,
+ "declaration": true,
+ "declarationMap": true,
+ "emitDeclarationOnly": true,
+ "outDir": "./lib/typescript",
+ "rootDir": "./src"
+ },
+ "include": ["src"],
+ "exclude": ["**/__tests__", "**/__mocks__"]
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..71b5938
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "rootDir": ".",
+ "paths": {
+ "@formo/react-native-analytics": ["./src/index"]
+ },
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "jsx": "react",
+ "lib": ["ESNext"],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "noEmit": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitReturns": true,
+ "noImplicitUseStrict": false,
+ "noStrictGenericChecks": false,
+ "noUncheckedIndexedAccess": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "target": "ESNext",
+ "verbatimModuleSyntax": false
+ },
+ "include": ["src"]
+}