diff --git a/package.json b/package.json
index 728516a943..fc53e721cb 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"start:react-native:ios:dogfood": "yarn workspace @stream-io/video-react-native-dogfood run ios",
"start:react-native:android:dogfood": "yarn workspace @stream-io/video-react-native-dogfood run android",
"build:styling": "yarn workspace @stream-io/video-styling run build",
+ "build:callingx": "yarn workspace react-native-callingx run build",
"start:styling": "yarn workspace @stream-io/video-styling run start",
"build:client": "yarn workspace @stream-io/video-client run build",
"start:client": "yarn workspace @stream-io/video-client run start",
@@ -30,7 +31,7 @@
"build:video-filters-react-native": "yarn workspace @stream-io/video-filters-react-native run build",
"build:noise-cancellation-react-native": "yarn workspace @stream-io/noise-cancellation-react-native run build",
"build:react:deps": "yarn build:client && yarn build:styling && yarn build:react:bindings && yarn build:video-filters-web && yarn build:audio-filters-web && yarn build:react:sdk",
- "build:react-native:deps": "yarn build:client && yarn build:react:bindings && yarn build:video-filters-react-native && yarn build:noise-cancellation-react-native && yarn build:react-native:sdk",
+ "build:react-native:deps": "yarn build:client && yarn build:react:bindings && yarn build:video-filters-react-native && yarn build:noise-cancellation-react-native && yarn build:callingx && yarn build:react-native:sdk",
"build:vercel": "yarn build:react:deps && yarn build:react:dogfood",
"start:egress": "yarn workspace @stream-io/egress-composite start",
"build:egress": "yarn workspace @stream-io/egress-composite build",
diff --git a/packages/react-native-callingx/.editorconfig b/packages/react-native-callingx/.editorconfig
new file mode 100644
index 0000000000..65365be68e
--- /dev/null
+++ b/packages/react-native-callingx/.editorconfig
@@ -0,0 +1,15 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+
+indent_style = space
+indent_size = 2
+
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
diff --git a/packages/react-native-callingx/.gitattributes b/packages/react-native-callingx/.gitattributes
new file mode 100644
index 0000000000..e27f70fa49
--- /dev/null
+++ b/packages/react-native-callingx/.gitattributes
@@ -0,0 +1,3 @@
+*.pbxproj -text
+# specific for windows script files
+*.bat text eol=crlf
diff --git a/packages/react-native-callingx/.nvmrc b/packages/react-native-callingx/.nvmrc
new file mode 100644
index 0000000000..c004e356d6
--- /dev/null
+++ b/packages/react-native-callingx/.nvmrc
@@ -0,0 +1 @@
+v22.20.0
diff --git a/packages/react-native-callingx/.watchmanconfig b/packages/react-native-callingx/.watchmanconfig
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/react-native-callingx/.watchmanconfig
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/react-native-callingx/CODE_OF_CONDUCT.md b/packages/react-native-callingx/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..8b4fcfd341
--- /dev/null
+++ b/packages/react-native-callingx/CODE_OF_CONDUCT.md
@@ -0,0 +1,132 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+- The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+[INSERT CONTACT METHOD].
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/packages/react-native-callingx/CONTRIBUTING.md b/packages/react-native-callingx/CONTRIBUTING.md
new file mode 100644
index 0000000000..fe8c655768
--- /dev/null
+++ b/packages/react-native-callingx/CONTRIBUTING.md
@@ -0,0 +1,129 @@
+# Contributing
+
+Contributions are always welcome, no matter how large or small!
+
+We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. Before contributing, please read the [code of conduct](./CODE_OF_CONDUCT.md).
+
+## Development workflow
+
+This project is a monorepo managed using [Yarn workspaces](https://yarnpkg.com/features/workspaces). It contains the following packages:
+
+- The library package in the root directory.
+- An example app in the `example/` directory.
+
+To get started with the project, make sure you have the correct version of [Node.js](https://nodejs.org/) installed. See the [`.nvmrc`](./.nvmrc) file for the version used in this project.
+
+Run `yarn` in the root directory to install the required dependencies for each package:
+
+```sh
+yarn
+```
+
+> Since the project relies on Yarn workspaces, you cannot use [`npm`](https://github.com/npm/cli) for development without manually migrating.
+
+The [example app](/example/) demonstrates usage of the library. You need to run it to test any changes you make.
+
+It is configured to use the local version of the library, so any changes you make to the library's source code will be reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a rebuild, but native code changes will require a rebuild of the example app.
+
+If you want to use Android Studio or Xcode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/CallingxExample.xcworkspace` in Xcode and find the source files at `Pods > Development Pods > react-native-callingx`.
+
+To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-callingx` under `Android`.
+
+You can use various commands from the root directory to work with the project.
+
+To start the packager:
+
+```sh
+yarn example start
+```
+
+To run the example app on Android:
+
+```sh
+yarn example android
+```
+
+To run the example app on iOS:
+
+```sh
+yarn example ios
+```
+
+To confirm that the app is running with the new architecture, you can check the Metro logs for a message like this:
+
+```sh
+Running "CallingxExample" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1}
+```
+
+Note the `"fabric":true` and `"concurrentRoot":true` properties.
+
+Make sure your code passes TypeScript:
+
+```sh
+yarn typecheck
+```
+
+To check for linting errors, run the following:
+
+```sh
+yarn lint
+```
+
+To fix formatting errors, run the following:
+
+```sh
+yarn lint --fix
+```
+
+Remember to add tests for your change if possible. Run the unit tests by:
+
+```sh
+yarn test
+```
+
+### Commit message convention
+
+We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
+
+- `fix`: bug fixes, e.g. fix crash due to deprecated method.
+- `feat`: new features, e.g. add new method to the module.
+- `refactor`: code refactor, e.g. migrate from class components to hooks.
+- `docs`: changes into documentation, e.g. add usage example for the module.
+- `test`: adding or updating tests, e.g. add integration tests using detox.
+- `chore`: tooling changes, e.g. change CI config.
+
+Our pre-commit hooks verify that your commit message matches this format when committing.
+
+### Publishing to npm
+
+We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc.
+
+To publish new versions, run the following:
+
+```sh
+yarn release
+```
+
+### Scripts
+
+The `package.json` file contains various scripts for common tasks:
+
+- `yarn`: setup project by installing dependencies.
+- `yarn typecheck`: type-check files with TypeScript.
+- `yarn lint`: lint files with [ESLint](https://eslint.org/).
+- `yarn test`: run unit tests with [Jest](https://jestjs.io/).
+- `yarn example start`: start the Metro server for the example app.
+- `yarn example android`: run the example app on Android.
+- `yarn example ios`: run the example app on iOS.
+
+### Sending a pull request
+
+> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
+
+When you're sending a pull request:
+
+- Prefer small pull requests focused on one change.
+- Verify that linters and tests are passing.
+- Review the documentation to make sure it looks good.
+- Follow the pull request template when opening a pull request.
+- For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.
diff --git a/packages/react-native-callingx/Callingx.podspec b/packages/react-native-callingx/Callingx.podspec
new file mode 100644
index 0000000000..de77381a5d
--- /dev/null
+++ b/packages/react-native-callingx/Callingx.podspec
@@ -0,0 +1,21 @@
+require "json"
+
+package = JSON.parse(File.read(File.join(__dir__, "package.json")))
+
+Pod::Spec.new do |s|
+ s.name = "Callingx"
+ s.version = package["version"]
+ s.summary = package["description"]
+ s.homepage = package["homepage"]
+ s.license = package["license"]
+ s.authors = package["author"]
+
+ s.platforms = { :ios => min_ios_version_supported }
+ s.source = { :git => "https://github.com/greenfrvr/react-native-callingx.git", :tag => "#{s.version}" }
+
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
+ # s.private_header_files = "ios/**/*.h"
+ s.public_header_files = "ios/CallingxPublic.h" #this is needed to make static methods visible
+
+ install_modules_dependencies(s)
+end
diff --git a/packages/react-native-callingx/LICENSE b/packages/react-native-callingx/LICENSE
new file mode 100644
index 0000000000..e64a3f45af
--- /dev/null
+++ b/packages/react-native-callingx/LICENSE
@@ -0,0 +1,20 @@
+MIT License
+
+Copyright (c) 2025 Artsiom Grintsevich
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/react-native-callingx/README.md b/packages/react-native-callingx/README.md
new file mode 100644
index 0000000000..d9bbff63e5
--- /dev/null
+++ b/packages/react-native-callingx/README.md
@@ -0,0 +1,412 @@
+# react-native-callingx
+
+A React Native Turbo Module for seamless native calling integration. This library provides a unified API to integrate with **CallKit** on iOS and the **Telecom/ConnectionService** API on Android, enabling your app to display system-level calling UI and interact with native call controls.
+
+## Features
+
+- 📞 **Incoming call UI** — Display native incoming call screens (even when the app is killed)
+- 📲 **Outgoing call registration** — Register outgoing calls with the system
+- 🎛️ **Call controls** — Mute, hold, end calls with native system integration
+- 🔔 **Custom notifications** — Configurable Android notification channels
+- ⚡ **Turbo Module** — Built with the New Architecture for optimal performance
+- 📱 **Background support** — Handle calls when the app is backgrounded or killed
+
+## Requirements
+
+- React Native 0.73+ (New Architecture / Turbo Modules)
+- iOS 13.0+
+- Android API 26+ (Android 8.0 Oreo)
+
+## Installation
+
+```sh
+npm install react-native-callingx
+# or
+yarn add react-native-callingx
+```
+
+### iOS Setup
+
+1. Add the required background modes to your `Info.plist`:
+
+```xml
+UIBackgroundModes
+
+ voip
+ audio
+
+```
+
+2. Run pod install:
+
+```sh
+cd ios && pod install
+```
+
+3. For VoIP push notifications, configure your `AppDelegate` to report incoming calls:
+
+```objc
+#import
+
+- (void)pushRegistry:(PKPushRegistry *)registry
+didReceiveIncomingPushWithPayload:(PKPushPayload *)payload
+ forType:(PKPushType)type
+withCompletionHandler:(void (^)(void))completion {
+
+ // Extract call information from payload
+ NSString *callId = payload.dictionaryPayload[@"call_id"];
+ NSString *callerName = payload.dictionaryPayload[@"caller_name"];
+ NSString *handle = payload.dictionaryPayload[@"handle"];
+ BOOL hasVideo = [payload.dictionaryPayload[@"has_video"] boolValue];
+
+ [Callingx reportNewIncomingCall:callId
+ handle:handle
+ handleType:@"generic"
+ hasVideo:hasVideo
+ localizedCallerName:callerName
+ supportsHolding:YES
+ supportsDTMF:NO
+ supportsGrouping:NO
+ supportsUngrouping:NO
+ fromPushKit:YES
+ payload:payload.dictionaryPayload
+ withCompletionHandler:completion];
+}
+```
+
+### Android Setup
+
+Handle incoming call intents in your `MainActivity`:
+
+```kotlin
+import android.content.Intent
+import android.os.Bundle
+import com.callingx.CallingxModule
+
+class MainActivity : ReactActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ CallingxModule.handleCallingIntent(this, intent)
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ CallingxModule.handleCallingIntent(this, intent)
+ }
+}
+```
+
+## Usage
+
+### Setup
+
+Initialize the module with platform-specific configuration:
+
+```typescript
+import { CallingxModule } from 'react-native-callingx';
+
+// Setup must be called before any other method
+CallingxModule.setup({
+ ios: {
+ appName: 'My App',
+ supportsVideo: true,
+ maximumCallsPerCallGroup: 1,
+ maximumCallGroups: 1,
+ handleType: 'generic', // 'generic' | 'number' | 'phone' | 'email'
+ },
+ android: {
+ incomingChannel: {
+ id: 'incoming_calls',
+ name: 'Incoming Calls',
+ sound: 'ringtone', // optional custom sound
+ vibration: true,
+ },
+ outgoingChannel: {
+ id: 'ongoing_calls',
+ name: 'Ongoing Calls',
+ },
+ // Optional: transform display text
+ titleTransformer: (name) => `Call from ${name}`,
+ subtitleTransformer: (phoneNumber) => phoneNumber,
+ },
+});
+```
+
+### Request Permissions
+
+Before displaying calls, request the required permissions:
+
+```typescript
+const permissions = await CallingxModule.requestPermissions();
+console.log('Audio permission:', permissions.recordAudio);
+console.log('Notification permission:', permissions.postNotifications);
+```
+
+### Display Incoming Call
+
+Show the native incoming call UI:
+
+```typescript
+await CallingxModule.displayIncomingCall(
+ 'unique-call-id',
+ '+1234567890', // phone number / handle
+ 'John Doe', // caller name
+ true // has video
+);
+```
+
+### Start Outgoing Call
+
+Register an outgoing call with the system:
+
+```typescript
+await CallingxModule.startCall(
+ 'unique-call-id',
+ '+1234567890',
+ 'John Doe',
+ false // audio only
+);
+```
+
+### Answer Call
+
+Answer an incoming call programmatically:
+
+```typescript
+await CallingxModule.answerIncomingCall('unique-call-id');
+```
+
+### Activate Call
+
+Mark a call as active (connected):
+
+```typescript
+await CallingxModule.setCurrentCallActive('unique-call-id');
+```
+
+### End Call
+
+End a call with a specific reason:
+
+```typescript
+import type { EndCallReason } from 'react-native-callingx';
+
+// Available reasons: 'local' | 'remote' | 'rejected' | 'busy' |
+// 'answeredElsewhere' | 'missed' | 'error'
+await CallingxModule.endCallWithReason('unique-call-id', 'remote');
+```
+
+### Mute/Unmute
+
+Toggle call mute state:
+
+```typescript
+await CallingxModule.setMutedCall('unique-call-id', true); // mute
+await CallingxModule.setMutedCall('unique-call-id', false); // unmute
+```
+
+### Hold/Unhold
+
+Toggle call hold state:
+
+```typescript
+await CallingxModule.setOnHoldCall('unique-call-id', true); // hold
+await CallingxModule.setOnHoldCall('unique-call-id', false); // unhold
+```
+
+### Update Display
+
+Update the caller information during a call:
+
+```typescript
+await CallingxModule.updateDisplay(
+ 'unique-call-id',
+ '+1234567890',
+ 'Updated Name'
+);
+```
+
+### Event Listeners
+
+Subscribe to call events:
+
+```typescript
+import { CallingxModule } from 'react-native-callingx';
+import type { EventName } from 'react-native-callingx';
+
+// Answer event - user answered from system UI
+const answerSubscription = CallingxModule.addEventListener(
+ 'answerCall',
+ (params) => {
+ console.log('Call answered:', params.callId);
+ }
+);
+
+// End event - call ended
+const endSubscription = CallingxModule.addEventListener('endCall', (params) => {
+ console.log('Call ended:', params.callId, 'Cause:', params.cause);
+});
+
+// Hold toggle event
+const holdSubscription = CallingxModule.addEventListener(
+ 'didToggleHoldCallAction',
+ (params) => {
+ console.log('Hold toggled:', params.callId, 'On hold:', params.hold);
+ }
+);
+
+// Mute toggle event
+const muteSubscription = CallingxModule.addEventListener(
+ 'didPerformSetMutedCallAction',
+ (params) => {
+ console.log('Mute toggled:', params.callId, 'Muted:', params.muted);
+ }
+);
+
+// Start call action (outgoing call initiated from system)
+const startSubscription = CallingxModule.addEventListener(
+ 'didReceiveStartCallAction',
+ (params) => {
+ console.log('Start call action:', params.callId);
+ }
+);
+
+// Clean up when done
+answerSubscription.remove();
+endSubscription.remove();
+// ... remove other subscriptions
+```
+
+### Handle Initial Events
+
+When the app is launched from a killed state by a call action, retrieve queued events:
+
+```typescript
+// Get events that occurred before the module was initialized
+const initialEvents = CallingxModule.getInitialEvents();
+initialEvents.forEach((event) => {
+ console.log('Initial event:', event.eventName, event.params);
+});
+
+// Clear initial events after processing
+await CallingxModule.clearInitialEvents();
+```
+
+### Background Tasks (Android)
+
+Run background tasks for call-related operations:
+
+```typescript
+// Start a managed background task
+await CallingxModule.startBackgroundTask(async (taskData, stopTask) => {
+ try {
+ // Perform background work (e.g., connect to call server)
+ await connectToCallServer();
+ } finally {
+ stopTask(); // Always call when done
+ }
+});
+
+// Or stop manually
+await CallingxModule.stopBackgroundTask();
+```
+
+## API Reference
+
+### CallingxModule
+
+| Method | Description |
+| ---------------------------------------------------------------- | ---------------------------------------------------- |
+| `setup(options)` | Initialize the module with platform-specific options |
+| `requestPermissions()` | Request required permissions (audio, notifications) |
+| `checkPermissions()` | Check current permission status |
+| `displayIncomingCall(callId, phoneNumber, callerName, hasVideo)` | Display incoming call UI |
+| `answerIncomingCall(callId)` | Answer an incoming call |
+| `startCall(callId, phoneNumber, callerName, hasVideo)` | Register an outgoing call |
+| `setCurrentCallActive(callId)` | Mark call as active/connected |
+| `updateDisplay(callId, phoneNumber, callerName)` | Update caller display info |
+| `endCallWithReason(callId, reason)` | End call with specified reason |
+| `setMutedCall(callId, isMuted)` | Toggle call mute state |
+| `setOnHoldCall(callId, isOnHold)` | Toggle call hold state |
+| `addEventListener(eventName, callback)` | Subscribe to call events |
+| `getInitialEvents()` | Get queued events from app launch |
+| `clearInitialEvents()` | Clear queued initial events |
+| `startBackgroundTask(taskProvider)` | Start Android background task |
+| `stopBackgroundTask()` | Stop Android background task |
+| `log(message, level)` | Log message to native console |
+
+### Events
+
+| Event | Parameters | Description |
+| ------------------------------ | ------------------- | --------------------------------- |
+| `answerCall` | `{ callId }` | User answered call from system UI |
+| `endCall` | `{ callId, cause }` | Call ended |
+| `didToggleHoldCallAction` | `{ callId, hold }` | Hold state changed |
+| `didPerformSetMutedCallAction` | `{ callId, muted }` | Mute state changed |
+| `didReceiveStartCallAction` | `{ callId }` | Outgoing call action received |
+
+### Types
+
+```typescript
+type EndCallReason =
+ | 'local' // Call ended by local user
+ | 'remote' // Call ended by remote party
+ | 'rejected' // Call was rejected
+ | 'busy' // Remote party is busy
+ | 'answeredElsewhere' // Answered on another device
+ | 'missed' // Call was missed
+ | 'error'; // Call failed due to error
+
+type CallingExpiOSOptions = {
+ appName: string;
+ supportsVideo?: boolean;
+ maximumCallsPerCallGroup?: number;
+ maximumCallGroups?: number;
+ handleType?: 'generic' | 'number' | 'phone' | 'email';
+};
+
+type CallingExpAndroidOptions = {
+ incomingChannel?: {
+ id: string;
+ name: string;
+ sound?: string;
+ vibration?: boolean;
+ };
+ outgoingChannel?: {
+ id: string;
+ name: string;
+ sound?: string;
+ vibration?: boolean;
+ };
+};
+
+type PermissionsResult = {
+ recordAudio: boolean;
+ postNotifications: boolean;
+};
+```
+
+## Troubleshooting
+
+### iOS
+
+- **Incoming call not showing**: Ensure `voip` background mode is enabled and VoIP push certificate is configured
+- **CallKit errors**: Check that `appName` is set in setup options
+- **Audio issues**: The module automatically configures the audio session, but ensure no conflicts with other audio libraries
+
+### Android
+
+- **Notifications not showing**: Check POST_NOTIFICATIONS permission on Android 13+
+- **Call not answered on tap**: Ensure `handleCallingIntent` is called in both `onCreate` and `onNewIntent` in your MainActivity
+
+## Contributing
+
+See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
+
+## License
+
+MIT
+
+---
+
+Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
diff --git a/packages/react-native-callingx/android/build.gradle b/packages/react-native-callingx/android/build.gradle
new file mode 100644
index 0000000000..dd344a9b40
--- /dev/null
+++ b/packages/react-native-callingx/android/build.gradle
@@ -0,0 +1,81 @@
+buildscript {
+ ext.getExtOrDefault = {name ->
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['Callingx_' + name]
+ }
+
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath "com.android.tools.build:gradle:8.7.2"
+ // noinspection DifferentKotlinGradleVersion
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
+ }
+}
+
+
+apply plugin: "com.android.library"
+apply plugin: "kotlin-android"
+apply plugin: "kotlin-parcelize"
+
+apply plugin: "com.facebook.react"
+
+def getExtOrIntegerDefault(name) {
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Callingx_" + name]).toInteger()
+}
+
+android {
+ namespace "com.callingx"
+
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
+
+ defaultConfig {
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
+ }
+
+ buildFeatures {
+ buildConfig true
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ }
+ }
+
+ lintOptions {
+ disable "GradleCompatible"
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ sourceSets {
+ main {
+ java.srcDirs += [
+ "generated/java",
+ "generated/jni",
+ "build/generated/source/codegen/java",
+ "build/generated/source/codegen/jni"
+ ]
+ }
+ }
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+def kotlin_version = getExtOrDefault("kotlinVersion")
+
+dependencies {
+ implementation "com.facebook.react:react-android"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation "androidx.core:core-telecom:1.0.1"
+}
diff --git a/packages/react-native-callingx/android/gradle.properties b/packages/react-native-callingx/android/gradle.properties
new file mode 100644
index 0000000000..6567d6ce3d
--- /dev/null
+++ b/packages/react-native-callingx/android/gradle.properties
@@ -0,0 +1,5 @@
+Callingx_kotlinVersion=2.0.21
+Callingx_minSdkVersion=24
+Callingx_targetSdkVersion=34
+Callingx_compileSdkVersion=35
+Callingx_ndkVersion=27.1.12297006
diff --git a/packages/react-native-callingx/android/src/main/AndroidManifest.xml b/packages/react-native-callingx/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..dae1911c08
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/CallService.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/CallService.kt
new file mode 100644
index 0000000000..caf82c1ac3
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/CallService.kt
@@ -0,0 +1,364 @@
+package com.callingx
+
+import CallRepository
+import android.app.Service
+import android.content.Intent
+import android.net.Uri
+import android.os.Binder
+import android.os.Build
+import android.os.Bundle
+import android.os.IBinder
+import android.telecom.DisconnectCause
+import android.util.Log
+import com.callingx.model.Call
+import com.callingx.model.CallAction
+import com.callingx.notifications.CallNotificationManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
+
+/**
+ * This service handles the app call logic (show notification, record mic, display audio, etc..). It
+ * can get started by the user or by an upcoming push notification to start a call.
+ *
+ * It holds the call scope used to register a call with the Telecom SDK in our
+ * TelecomCallRepository.
+ *
+ * When registering a call with the Telecom SDK and displaying a CallStyle notification, the SDK
+ * will grant you foreground service delegation so there is no need to make this a FGS.
+ *
+ * Note: you could potentially make this service run in a different process since audio or video
+ * calls can consume significant memory, although that would require more complex setup to make it
+ * work across multiple process.
+ */
+class CallService : Service(), CallRepository.Listener {
+
+ companion object {
+ private const val TAG = "[Callingx] CallService"
+
+ internal const val EXTRA_CALL_ID = "extra_call_id"
+ internal const val EXTRA_NAME = "extra_name"
+ internal const val EXTRA_URI = "extra_uri"
+ internal const val EXTRA_IS_VIDEO = "extra_is_video"
+ internal const val EXTRA_DISPLAY_TITLE = "displayTitle"
+ internal const val EXTRA_DISPLAY_SUBTITLE = "displaySubtitle"
+ internal const val EXTRA_DISPLAY_OPTIONS = "display_options"
+ // Background task extras
+ internal const val EXTRA_TASK_NAME = "task_name"
+ internal const val EXTRA_TASK_DATA = "task_data"
+ internal const val EXTRA_TASK_TIMEOUT = "task_timeout"
+
+ internal const val ACTION_INCOMING_CALL = "incoming_call"
+ internal const val ACTION_OUTGOING_CALL = "outgoing_call"
+ internal const val ACTION_UPDATE_CALL = "update_call"
+ internal const val ACTION_START_BACKGROUND_TASK = "start_background_task"
+ internal const val ACTION_STOP_BACKGROUND_TASK = "stop_background_task"
+ internal const val ACTION_STOP_SERVICE = "stop_service"
+ }
+
+ inner class CallServiceBinder : Binder() {
+ fun getService(): CallService = this@CallService
+ }
+
+ private lateinit var headlessJSManager: HeadlessTaskManager
+ private lateinit var notificationManager: CallNotificationManager
+ private lateinit var callRepository: CallRepository
+
+ private val binder = CallServiceBinder()
+ private val scope: CoroutineScope = CoroutineScope(SupervisorJob())
+
+ private var isInForeground = false
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(TAG, "[service] onCreate: TelecomCallService created")
+
+ notificationManager = CallNotificationManager(applicationContext)
+ headlessJSManager = HeadlessTaskManager(applicationContext)
+ callRepository = CallRepositoryFactory.create(applicationContext)
+ callRepository.setListener(this)
+
+ sendBroadcastEvent(CallingxModule.SERVICE_READY_ACTION)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ Log.d(TAG, "[service] onDestroy: TelecomCallService destroyed")
+
+ notificationManager.cancelNotifications()
+ notificationManager.stopRingtone()
+ callRepository.release()
+ headlessJSManager.release()
+
+ if (isInForeground) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ isInForeground = false
+ }
+
+ scope.cancel()
+ }
+
+ override fun onTaskRemoved(rootIntent: Intent?) {
+ super.onTaskRemoved(rootIntent)
+ Log.d(TAG, "[service] onTaskRemoved: Task removed")
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ Log.d(TAG, "[service] onStartCommand: Received intent with action: ${intent?.action}")
+
+ if (intent == null || intent.action == null) {
+ Log.w(TAG, "[service] onStartCommand: Intent is null, returning START_NOT_STICKY")
+ return START_NOT_STICKY
+ }
+
+ when (intent.action) {
+ ACTION_INCOMING_CALL -> {
+ registerCall(intent, true)
+ }
+ ACTION_OUTGOING_CALL -> {
+ registerCall(intent, false)
+ }
+ ACTION_START_BACKGROUND_TASK -> {
+ if (!isInForeground) {
+ Log.d(TAG, "[service] onStartCommand: Starting foreground for background task")
+ // for now bg task is intended to be used after a call registered and
+ // notification is shown, so we don't need to show a separate notification for
+ // bg task
+ // startForeground(CallNotificationManager.NOTIFICATION_ID, notification)
+ isInForeground = true
+ }
+
+ val taskName = intent.getStringExtra(EXTRA_TASK_NAME)!!
+ val taskData = intent.getBundleExtra(EXTRA_TASK_DATA)!!
+ val taskTimeout = intent.getLongExtra(EXTRA_TASK_TIMEOUT, 0)
+ startBackgroundTask(taskName, taskData, taskTimeout)
+ }
+ ACTION_STOP_BACKGROUND_TASK -> {
+ stopBackgroundTask()
+ }
+ ACTION_UPDATE_CALL -> {
+ // TODO: update the call details
+ // updateServiceState(telecomRepository.currentCall.value) // not used for now
+ }
+ else -> {
+ Log.e(TAG, "[service] onStartCommand: Unknown action: ${intent.action}")
+ throw IllegalArgumentException("Unknown action")
+ }
+ }
+
+ return START_STICKY
+ }
+
+ override fun onBind(intent: Intent): IBinder? = binder
+
+ override fun onUnbind(intent: Intent): Boolean {
+ Log.d(TAG, "[service] onUnbind: Service unbound")
+ return super.onUnbind(intent)
+ }
+
+ override fun onCallStateChanged(call: Call) {
+ Log.d(TAG, "[service] onCallStateChanged: Call state changed: ${call::class.simpleName}")
+ Log.d(TAG, "[service] updateServiceState: Updating service state for call type: ${call}")
+ when (call) {
+ is Call.Registered -> {
+ Log.d(
+ TAG,
+ "[service] updateServiceState: Call registered - Active: ${call.isActive}, OnHold: ${call.isOnHold}, Muted: ${call.isMuted}"
+ )
+
+ if (call.isIncoming()) {
+ if (!call.isActive) notificationManager.startRingtone()
+ else notificationManager.stopRingtone()
+ }
+ // Update the call state.
+ if (isInForeground) {
+ Log.d(
+ TAG,
+ "[service] updateServiceState: Updating notification for call: ${call.id}"
+ )
+ notificationManager.updateCallNotification(call)
+ } else {
+ Log.d(
+ TAG,
+ "[service] updateServiceState: Starting foreground for call: ${call.id}"
+ )
+ val notification = notificationManager.createNotification(call)
+ startForeground(CallNotificationManager.NOTIFICATION_ID, notification)
+ isInForeground = true
+ }
+ }
+ is Call.Unregistered -> {
+ Log.d(TAG, "[service] updateServiceState: Call unregistered, stopping service")
+ notificationManager.updateCallNotification(call)
+
+ if (isInForeground) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ isInForeground = false
+ }
+
+ notificationManager.stopRingtone()
+ stopSelf()
+ }
+ is Call.None -> {
+ Log.d(TAG, "[service] updateServiceState: No active call, stopping audio loop")
+ notificationManager.updateCallNotification(call)
+
+ if (isInForeground) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ isInForeground = false
+ }
+ notificationManager.stopRingtone()
+ }
+ }
+ }
+
+ override fun onIsCallAnswered(callId: String, source: CallRepository.EventSource) {
+ sendBroadcastEvent(CallingxModule.CALL_ANSWERED_ACTION) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ putExtra(CallingxModule.EXTRA_SOURCE, source.name.lowercase())
+ }
+ }
+
+ override fun onIsCallDisconnected(
+ callId: String?,
+ cause: DisconnectCause,
+ source: CallRepository.EventSource
+ ) {
+ // we're not passing the callId here to prevent infinite loops
+ // callEnd event with callId will sent only when after interaction with notification buttons
+ sendBroadcastEvent(CallingxModule.CALL_END_ACTION) {
+ if (callId != null) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ }
+ putExtra(CallingxModule.EXTRA_DISCONNECT_CAUSE, getDisconnectCauseString(cause))
+ putExtra(CallingxModule.EXTRA_SOURCE, source.name.lowercase())
+ }
+ }
+
+ override fun onIsCallInactive(callId: String) {
+ sendBroadcastEvent(CallingxModule.CALL_INACTIVE_ACTION) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ }
+ }
+
+ override fun onIsCallActive(callId: String) {
+ sendBroadcastEvent(CallingxModule.CALL_ACTIVE_ACTION) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ }
+ }
+
+ override fun onCallRegistered(callId: String) {
+ Log.d(TAG, "[service] onCallRegistered: Call registered: $callId")
+ sendBroadcastEvent(CallingxModule.CALL_REGISTERED_ACTION) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ }
+ }
+
+ override fun onMuteCallChanged(callId: String, isMuted: Boolean) {
+ Log.d(TAG, "[service] onMuteCallChanged: Call muted: $callId, $isMuted")
+ sendBroadcastEvent(CallingxModule.CALL_MUTED_ACTION) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ putExtra(CallingxModule.EXTRA_MUTED, isMuted)
+ }
+ }
+
+ override fun onCallEndpointChanged(callId: String, endpoint: String) {
+ Log.d(TAG, "[service] onCallEndpointChanged: Call endpoint changed: $callId, $endpoint")
+ sendBroadcastEvent(CallingxModule.CALL_ENDPOINT_CHANGED_ACTION) {
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ putExtra(CallingxModule.EXTRA_AUDIO_ENDPOINT, endpoint)
+ }
+ }
+
+ public fun isCallRegistered(callId: String): Boolean {
+ val currentCall = callRepository.currentCall.value
+ return currentCall is Call.Registered && currentCall.id == callId
+ }
+
+ public fun hasRegisteredCall(): Boolean {
+ val currentCall = callRepository.currentCall.value
+ return currentCall is Call.Registered
+ }
+
+ public fun processAction(action: CallAction) {
+ Log.d(TAG, "[service] processAction: Processing action: ${action::class.simpleName}")
+ val currentCall = callRepository.currentCall.value
+ if (currentCall is Call.Registered) {
+ currentCall.processAction(action)
+ } else {
+ Log.e(TAG, "[service] processAction: Call not registered, ignoring action")
+ }
+ }
+
+ public fun startBackgroundTask(taskName: String, data: Bundle, timeout: Long) {
+ Log.d(
+ TAG,
+ "[service] startBackgroundTask: Starting background task: $taskName, $data, $timeout"
+ )
+ headlessJSManager.startHeadlessTask(taskName, data, timeout)
+ }
+
+ public fun stopBackgroundTask() {
+ Log.d(TAG, "[service] stopBackgroundTask: Stopping background task")
+ headlessJSManager.stopHeadlessTask()
+ }
+
+ private fun registerCall(intent: Intent, incoming: Boolean) {
+ Log.d(TAG, "[service] registerCall: ${if (incoming) "in" else "out"} call")
+
+ // If we have an ongoing call ignore command
+ if (callRepository.currentCall.value is Call.Registered) {
+ Log.w(TAG, "[service] registerCall: Call already registered, ignoring new call request")
+ return
+ }
+
+ val callId = intent.getStringExtra(EXTRA_CALL_ID)!!
+ val name = intent.getStringExtra(EXTRA_NAME)!!
+ val isVideo = intent.getBooleanExtra(EXTRA_IS_VIDEO, false)
+ val uri =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ intent.getParcelableExtra(EXTRA_URI, Uri::class.java)!!
+ } else {
+ @Suppress("DEPRECATION") intent.getParcelableExtra(EXTRA_URI)!!
+ }
+ val displayOptions = intent.getBundleExtra(EXTRA_DISPLAY_OPTIONS)
+
+ Log.d(TAG, "[service] registerCall: Call details - Name: $name, URI: $uri")
+
+ scope.launch {
+ try {
+ callRepository.registerCall(
+ callId,
+ name,
+ uri,
+ incoming,
+ isVideo,
+ displayOptions,
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, "[service] registerCall: Error registering call: ${e.message}")
+ }
+ }
+ }
+
+ private fun sendBroadcastEvent(action: String, applyParams: Intent.() -> Unit = {}) {
+ val intent =
+ Intent(action).apply {
+ setPackage(packageName)
+ applyParams(this)
+ }
+ Log.d(TAG, "[service] sendBroadcastEvent: Sending broadcast event: ${intent.action}")
+ sendBroadcast(intent)
+ }
+
+ // private fun hasMicPermission(): Boolean {
+ // val hasPermission =
+ // PermissionChecker.checkSelfPermission(
+ // this,
+ // Manifest.permission.RECORD_AUDIO,
+ // ) == PermissionChecker.PERMISSION_GRANTED
+ // Log.d(TAG, "[service] hasMicPermission: Mic permission granted = $hasPermission")
+ // return hasPermission
+ // }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/CallingxModule.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/CallingxModule.kt
new file mode 100644
index 0000000000..cff64b2d61
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/CallingxModule.kt
@@ -0,0 +1,592 @@
+package com.callingx
+
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.ServiceConnection
+import android.os.Build
+import android.os.Bundle
+import android.os.IBinder
+import android.telecom.DisconnectCause
+import android.util.Log
+import androidx.core.content.ContextCompat
+import androidx.core.net.toUri
+import com.callingx.model.CallAction
+import com.callingx.notifications.NotificationChannelsManager
+import com.callingx.notifications.NotificationsConfig
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.bridge.LifecycleEventListener
+import com.facebook.react.bridge.Promise
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReadableMap
+import com.facebook.react.bridge.WritableArray
+import com.facebook.react.bridge.WritableMap
+import com.facebook.react.bridge.WritableNativeArray
+import com.facebook.react.module.annotations.ReactModule
+import com.facebook.react.modules.core.DeviceEventManagerModule
+
+@ReactModule(name = CallingxModule.NAME)
+class CallingxModule(reactContext: ReactApplicationContext) : NativeCallingxSpec(reactContext) {
+
+ companion object {
+ const val TAG = "[Callingx] CallingxModule"
+ const val NAME = "Callingx"
+
+ const val EXTRA_CALL_ID = "call_id"
+ const val EXTRA_MUTED = "is_muted"
+ const val EXTRA_ON_HOLD = "hold"
+ const val EXTRA_DISCONNECT_CAUSE = "disconnect_cause"
+ const val EXTRA_AUDIO_ENDPOINT = "audio_endpoint"
+ const val EXTRA_SOURCE = "source"
+
+ const val CALL_REGISTERED_ACTION = "call_registered"
+ const val CALL_ANSWERED_ACTION = "call_answered"
+ // const val CALL_DISCONNECTED_ACTION = "call_disconnected"
+ const val CALL_INACTIVE_ACTION = "call_inactive"
+ const val CALL_ACTIVE_ACTION = "call_active"
+ const val CALL_MUTED_ACTION = "call_muted"
+ const val CALL_ENDPOINT_CHANGED_ACTION = "call_endpoint_changed"
+ const val CALL_END_ACTION = "call_end"
+
+ const val SERVICE_READY_ACTION = "service_ready"
+ }
+
+ private enum class BindingState {
+ UNBOUND,
+ BINDING,
+ BOUND
+ }
+
+ private var callService: CallService? = null
+ private var bindingState = BindingState.UNBOUND
+
+ private var delayedEvents = WritableNativeArray()
+ private var isModuleInitialized = false
+
+ private val notificationChannelsManager = NotificationChannelsManager(reactApplicationContext)
+ private val callEventBroadcastReceiver = CallEventBroadcastReceiver()
+ private val appStateListener =
+ object : LifecycleEventListener {
+ override fun onHostResume() {}
+
+ override fun onHostPause() {}
+
+ override fun onHostDestroy() {
+ // App destroyed - force unbind
+ Log.d(TAG, "[module] onHostDestroy: App destroyed")
+ unbindServiceSafely()
+ }
+ }
+
+ init {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ reactContext.registerReceiver(
+ callEventBroadcastReceiver,
+ getReceiverFilter(),
+ Context.RECEIVER_NOT_EXPORTED
+ )
+ } else {
+ @Suppress("UnspecifiedRegisterReceiverFlag")
+ reactContext.registerReceiver(callEventBroadcastReceiver, getReceiverFilter())
+ }
+ }
+
+ override fun getName(): String = NAME
+
+ override fun initialize() {
+ super.initialize()
+ reactApplicationContext.addLifecycleEventListener(appStateListener)
+
+ tryToBindIfNeeded()
+
+ Log.d(TAG, "[module] initialize: Initializing module")
+ }
+
+ override fun invalidate() {
+ super.invalidate()
+ Log.d(TAG, "[module] invalidate: Invalidating module")
+
+ unbindServiceSafely()
+
+ reactApplicationContext.removeLifecycleEventListener(appStateListener)
+ reactApplicationContext.unregisterReceiver(callEventBroadcastReceiver)
+ isModuleInitialized = false
+ }
+
+ override fun setupiOS(options: ReadableMap) {
+ // leave empty
+ }
+
+ override fun setupAndroid(options: ReadableMap) {
+ Log.d(TAG, "[module] setupAndroid: Setting up Android: $options")
+ val notificationsConfig =
+ NotificationsConfig.saveNotificationsConfig(reactApplicationContext, options)
+ notificationChannelsManager.setNotificationsConfig(notificationsConfig)
+ notificationChannelsManager.createNotificationChannels()
+
+ isModuleInitialized = true
+ }
+
+ override fun canPostNotifications(): Boolean {
+ return notificationChannelsManager.getNotificationStatus().canPost
+ }
+
+ override fun getInitialEvents(): WritableArray {
+ // NOTE: writabel native array can be consumed only once, think of getting rid from clear
+ // event and clear eat immidiate after getting initial events
+ val events = delayedEvents
+ delayedEvents = WritableNativeArray()
+ return events
+ }
+
+ override fun clearInitialEvents(promise: Promise) {
+ delayedEvents = WritableNativeArray()
+ promise.resolve(true)
+ }
+
+ override fun setCurrentCallActive(callId: String, promise: Promise) {
+ Log.d(TAG, "[module] activateCall: Activating call: $callId")
+ executeServiceAction(CallAction.Activate, promise)
+ }
+
+ override fun displayIncomingCall(
+ callId: String,
+ phoneNumber: String,
+ callerName: String,
+ hasVideo: Boolean,
+ displayOptions: ReadableMap?,
+ promise: Promise
+ ) {
+ Log.d(
+ TAG,
+ "[module] displayIncomingCall: Displaying incoming call: $callId, $phoneNumber, $callerName, $hasVideo"
+ )
+ if (!notificationChannelsManager.getNotificationStatus().canPost) {
+ promise.reject("ERROR", "Notifications are not granted")
+ return
+ }
+
+ startCallService(
+ CallService.ACTION_INCOMING_CALL,
+ callId,
+ callerName,
+ phoneNumber,
+ hasVideo,
+ displayOptions
+ )
+ promise.resolve(true)
+ }
+
+ override fun answerIncomingCall(callId: String, promise: Promise) {
+ Log.d(TAG, "[module] answerIncomingCall: Answering call: $callId")
+ // TODO: get the call type from the call attributes
+ val isAudioCall = true // TODO: get the call type from the call attributes
+ // registeredCall.callAttributes.callType ==
+ // CallAttributesCompat.CALL_TYPE_AUDIO_CALL
+ // currentCall?.processAction(TelecomCallAction.Answer(isAudioCall))
+ executeServiceAction(CallAction.Answer(isAudioCall), promise)
+ }
+
+ override fun startCall(
+ callId: String,
+ phoneNumber: String,
+ callerName: String,
+ hasVideo: Boolean,
+ displayOptions: ReadableMap?,
+ promise: Promise
+ ) {
+ Log.d(
+ TAG,
+ "[module] startCall: Starting outgoing call: $callId, $phoneNumber, $callerName, $hasVideo, $displayOptions"
+ )
+ if (!notificationChannelsManager.getNotificationStatus().canPost) {
+ promise.reject("ERROR", "Notifications are not granted")
+ return
+ }
+
+ startCallService(
+ CallService.ACTION_OUTGOING_CALL,
+ callId,
+ callerName,
+ phoneNumber,
+ hasVideo,
+ displayOptions
+ )
+ promise.resolve(true)
+ }
+
+ override fun updateDisplay(
+ callId: String,
+ phoneNumber: String,
+ callerName: String,
+ displayOptions: ReadableMap?,
+ promise: Promise
+ ) {
+ Log.d(TAG, "[module] updateDisplay: Updating display: $callId, $phoneNumber, $callerName")
+ if (!notificationChannelsManager.getNotificationStatus().canPost) {
+ promise.reject("ERROR", "Notifications are not granted")
+ return
+ }
+
+ startCallService(
+ CallService.ACTION_UPDATE_CALL,
+ callId,
+ callerName,
+ phoneNumber,
+ false,
+ displayOptions,
+ )
+ promise.resolve(true)
+ }
+
+ override fun endCallWithReason(callId: String, reason: Double, promise: Promise) {
+ Log.d(TAG, "[module] endCallWithReason: Ending call: $callId, $reason")
+ val action = CallAction.Disconnect(DisconnectCause(reason.toInt()))
+ executeServiceAction(action, promise)
+ }
+
+ override fun endCall(callId: String, promise: Promise) {
+ Log.d(TAG, "[module] endCall: Ending call: $callId")
+ val action = CallAction.Disconnect(DisconnectCause(DisconnectCause.LOCAL))
+ executeServiceAction(action, promise)
+ }
+
+ override fun isCallRegistered(callId: String): Boolean {
+ val isCallRegistered = callService?.isCallRegistered(callId) ?: false
+ Log.d(TAG, "[module] isCallRegistered: Is call registered: $isCallRegistered")
+ return isCallRegistered
+ }
+
+ override fun hasRegisteredCall(): Boolean {
+ val hasRegisteredCall = callService?.hasRegisteredCall() ?: false
+ Log.d(TAG, "[module] hasRegisteredCall: Has registered call: $hasRegisteredCall")
+ return hasRegisteredCall
+ }
+
+ override fun setMutedCall(callId: String, isMuted: Boolean, promise: Promise) {
+ Log.d(TAG, "[module] setMutedCall: Setting muted call: $callId, $isMuted")
+ val action = CallAction.ToggleMute(isMuted)
+ executeServiceAction(action, promise)
+ }
+
+ override fun setOnHoldCall(callId: String, isOnHold: Boolean, promise: Promise) {
+ Log.d(TAG, "[module] setOnHoldCall: Setting on hold call: $callId, $isOnHold")
+ val action = if (isOnHold) CallAction.Hold else CallAction.Activate
+ executeServiceAction(action, promise)
+ }
+
+ override fun startBackgroundTask(taskName: String, timeout: Double, promise: Promise) {
+ Log.d(TAG, "[module] startBackgroundTask: Starting background task: $taskName, $timeout")
+
+ Intent(reactApplicationContext, CallService::class.java)
+ .apply {
+ this.action = CallService.ACTION_START_BACKGROUND_TASK
+ putExtra(CallService.EXTRA_TASK_NAME, taskName)
+ putExtra(CallService.EXTRA_TASK_DATA, Bundle())
+ putExtra(CallService.EXTRA_TASK_TIMEOUT, timeout.toLong())
+ }
+ .also { ContextCompat.startForegroundService(reactApplicationContext, it) }
+
+ promise.resolve(true)
+ }
+
+ override fun stopBackgroundTask(taskName: String, promise: Promise) {
+ Log.d(TAG, "[module] stopBackgroundTask: Stopping background task: $taskName")
+
+ Intent(reactApplicationContext, CallService::class.java)
+ .apply {
+ this.action = CallService.ACTION_STOP_BACKGROUND_TASK
+ putExtra(CallService.EXTRA_TASK_NAME, taskName)
+ }
+ .also { ContextCompat.startForegroundService(reactApplicationContext, it) }
+
+ promise.resolve(true)
+ }
+
+ override fun log(message: String, level: String) {
+ Log.d(TAG, "[module] log: $message, $level")
+ when (level) {
+ "debug" -> Log.d(TAG, "[module] log: $message")
+ "info" -> Log.i(TAG, "[module] log: $message")
+ "warn" -> Log.w(TAG, "[module] log: $message")
+ "error" -> Log.e(TAG, "[module] log: $message")
+ }
+ }
+
+ private fun startCallService(
+ action: String,
+ callId: String,
+ callerName: String,
+ phoneNumber: String,
+ hasVideo: Boolean,
+ displayOptions: ReadableMap?
+ ) {
+ Intent(reactApplicationContext, CallService::class.java)
+ .apply {
+ this.action = action
+ putExtra(CallService.EXTRA_CALL_ID, callId)
+ putExtra(CallService.EXTRA_NAME, callerName)
+ putExtra(CallService.EXTRA_URI, phoneNumber.toUri())
+ putExtra(CallService.EXTRA_IS_VIDEO, hasVideo)
+ putExtra(CallService.EXTRA_DISPLAY_OPTIONS, Arguments.toBundle(displayOptions))
+ }
+ .also { ContextCompat.startForegroundService(reactApplicationContext, it) }
+ }
+
+ private fun executeServiceAction(action: CallAction, promise: Promise) {
+ Log.d(TAG, "[module] executeServiceAction: Executing service action: $action")
+ when (bindingState) {
+ BindingState.BOUND -> {
+ if (callService != null) {
+ callService?.processAction(action)
+ promise.resolve(true)
+ } else {
+ promise.reject("ERROR", "Service reference lost")
+ }
+ }
+ BindingState.BINDING -> {
+ Log.d(TAG, "executeServiceAction: Service binding, queueing action")
+ promise.reject(
+ "SERVICE_BINDING",
+ "Service is connecting, please try again in a moment"
+ )
+ }
+ BindingState.UNBOUND -> {
+ promise.reject(
+ "SERVICE_NOT_CONNECTED",
+ "Service not connected. Call may not be active."
+ )
+ }
+ }
+ }
+
+ private fun sendJSEvent(eventName: String, params: WritableMap? = null) {
+ if (isModuleInitialized && reactApplicationContext.hasActiveReactInstance()) {
+ val paramsMap =
+ Arguments.createMap().apply {
+ params?.let {
+ it.toHashMap().forEach { key, value ->
+ if (value is Boolean) {
+ putBoolean(key, value)
+ } else {
+ putString(key, value.toString())
+ }
+ }
+ }
+ }
+ reactApplicationContext
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
+ .emit(eventName, params)
+
+ val value =
+ Arguments.createMap().apply {
+ putString("eventName", eventName)
+ putMap("params", paramsMap)
+ }
+ emitOnNewEvent(value)
+ } else {
+ Arguments.createMap()
+ .apply {
+ putString("name", eventName)
+ putMap("params", params)
+ }
+ .also { delayedEvents.pushMap(it) }
+ }
+ }
+
+ private fun getReceiverFilter(): IntentFilter =
+ IntentFilter().apply {
+ addAction(CALL_REGISTERED_ACTION)
+ addAction(CALL_ANSWERED_ACTION)
+ addAction(CALL_ACTIVE_ACTION)
+ addAction(CALL_INACTIVE_ACTION)
+ addAction(CALL_MUTED_ACTION)
+ addAction(CALL_ENDPOINT_CHANGED_ACTION)
+ addAction(CALL_END_ACTION)
+ addAction(SERVICE_READY_ACTION)
+ }
+
+ private fun bindToServiceIfNeeded() {
+ when (bindingState) {
+ BindingState.BOUND -> {
+ Log.d(TAG, "[module] bindToServiceIfNeeded: Already bound")
+ return
+ }
+ BindingState.BINDING -> {
+ Log.d(TAG, "[module] bindToServiceIfNeeded: Already binding")
+ return
+ }
+ BindingState.UNBOUND -> {
+ Log.d(TAG, "[module] bindToServiceIfNeeded: Attempting to bind")
+ val intent = Intent(reactApplicationContext, CallService::class.java)
+ try {
+ val success =
+ reactApplicationContext.bindService(
+ intent,
+ serviceConnection,
+ Context.BIND_AUTO_CREATE or Context.BIND_IMPORTANT
+ )
+ if (success) {
+ bindingState = BindingState.BINDING
+ Log.d(TAG, "[module] bindToServiceIfNeeded: Bind request successful")
+ } else {
+ Log.e(TAG, "[module] bindToServiceIfNeeded: Bind request failed")
+ bindingState = BindingState.UNBOUND
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, "[module] bindToServiceIfNeeded: Exception during bind", e)
+ bindingState = BindingState.UNBOUND
+ }
+ }
+ }
+ }
+
+ private fun unbindServiceSafely() {
+ Log.d(TAG, "[module] unbindServiceSafely: Unbinding service")
+ if (bindingState == BindingState.BOUND || bindingState == BindingState.BINDING) {
+ try {
+ reactApplicationContext.unbindService(serviceConnection)
+ Log.d(TAG, "[module] unbindServiceSafely: Successfully unbound")
+ } catch (e: IllegalArgumentException) {
+ Log.w(
+ TAG,
+ "[module] unbindServiceSafely: Service not registered or already unbound"
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, "[module] unbindServiceSafely: Error unbinding service", e)
+ } finally {
+ bindingState = BindingState.UNBOUND
+ callService = null
+ }
+ }
+ }
+
+ private fun tryToBindIfNeeded() {
+ val intent = Intent(reactApplicationContext, CallService::class.java)
+ try {
+ val success =
+ reactApplicationContext.bindService(
+ intent,
+ serviceConnection,
+ 0 // No flags - only bind if service exists
+ )
+ if (success) {
+ bindingState = BindingState.BINDING
+ Log.d(TAG, "[module] checkForExistingService: Service exists, binding")
+ } else {
+ Log.d(TAG, "[module] checkForExistingService: No existing service")
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, "[module] checkForExistingService: Error checking for service", e)
+ }
+ }
+
+ private inner class CallEventBroadcastReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val action = intent.action
+ val callId = intent.getStringExtra(EXTRA_CALL_ID)
+
+ Log.d(
+ TAG,
+ "[module] onReceive: Received intent: $action callId: $callId callService: ${callService != null}"
+ )
+
+ if (action == SERVICE_READY_ACTION) {
+ Log.d(TAG, "[module] onReceive: Service is ready, initiating binding")
+ bindToServiceIfNeeded()
+ return
+ }
+
+ if (action == null) {
+ Log.e(TAG, "[module] onReceive: Received intent with null action or callId")
+ return
+ }
+
+ val params = Arguments.createMap()
+ if (callId != null) {
+ params.putString("callId", callId)
+ }
+
+ when (action) {
+ CALL_REGISTERED_ACTION -> {
+ sendJSEvent("didReceiveStartCallAction", params)
+ }
+ CALL_ANSWERED_ACTION -> {
+ if (intent.hasExtra(EXTRA_SOURCE)) {
+ params.putString("source", intent.getStringExtra(EXTRA_SOURCE))
+ }
+ sendJSEvent("answerCall", params)
+ }
+ CALL_END_ACTION -> {
+ if (callId == null) {
+ // means the call was disconnected, we're ready to unbind the service
+ unbindServiceSafely()
+ }
+
+ params.putString("cause", intent.getStringExtra(EXTRA_DISCONNECT_CAUSE))
+ if (intent.hasExtra(EXTRA_SOURCE)) {
+ params.putString("source", intent.getStringExtra(EXTRA_SOURCE))
+ }
+ sendJSEvent("endCall", params)
+ }
+ CALL_INACTIVE_ACTION -> {
+ params.putBoolean("hold", true)
+ sendJSEvent("didToggleHoldCallAction", params)
+ }
+ CALL_ACTIVE_ACTION -> {
+ params.putBoolean("hold", false)
+ sendJSEvent("didToggleHoldCallAction", params)
+ }
+ CALL_MUTED_ACTION -> {
+ if (intent.hasExtra(EXTRA_MUTED)) {
+ params.putBoolean("muted", intent.getBooleanExtra(EXTRA_MUTED, false))
+ }
+ sendJSEvent("didPerformSetMutedCallAction", params)
+ }
+ CALL_ENDPOINT_CHANGED_ACTION -> {
+ if (intent.hasExtra(EXTRA_AUDIO_ENDPOINT)) {
+ params.putString("output", intent.getStringExtra(EXTRA_AUDIO_ENDPOINT))
+ }
+ sendJSEvent("didChangeAudioRoute", params)
+ }
+ }
+ }
+ }
+
+ private val serviceConnection =
+ object : ServiceConnection {
+ override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
+ Log.d(TAG, "[module] onServiceConnected: Service connected")
+ val binder = service as? CallService.CallServiceBinder
+ callService = binder?.getService()
+ bindingState = BindingState.BOUND
+ }
+
+ override fun onServiceDisconnected(name: ComponentName?) {
+ Log.d(TAG, "onServiceDisconnected: Service disconnected unexpectedly")
+ callService = null
+ bindingState = BindingState.UNBOUND
+ }
+
+ override fun onBindingDied(name: ComponentName?) {
+ Log.e(TAG, "[module] onBindingDied: Service binding died")
+ callService = null
+ bindingState = BindingState.UNBOUND
+
+ // Must unbind to clean up the dead binding
+ try {
+ reactApplicationContext.unbindService(this)
+ } catch (e: Exception) {
+ Log.w(TAG, "[module] onBindingDied: Error unbinding dead connection", e)
+ }
+ }
+
+ override fun onNullBinding(name: ComponentName?) {
+ Log.e(TAG, "[module] onNullBinding: Service returned null binding")
+ bindingState = BindingState.UNBOUND
+ callService = null
+ }
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/CallingxPackage.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/CallingxPackage.kt
new file mode 100644
index 0000000000..f7ca68c6b7
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/CallingxPackage.kt
@@ -0,0 +1,16 @@
+package com.callingx
+
+import com.facebook.react.BaseReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.module.model.ReactModuleInfo
+import com.facebook.react.module.model.ReactModuleInfoProvider
+
+class CallingPackage : BaseReactPackage() {
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
+ if (name == CallingxModule.NAME) CallingxModule(reactContext) else null
+
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider {
+ mapOf(CallingxModule.NAME to ReactModuleInfo(CallingxModule.NAME, CallingxModule.NAME, false, false, false, true))
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/HeadlessTaskManager.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/HeadlessTaskManager.kt
new file mode 100644
index 0000000000..a3ecb1c4d4
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/HeadlessTaskManager.kt
@@ -0,0 +1,165 @@
+package com.callingx
+
+import android.content.Context
+import android.os.Bundle
+import android.util.Log
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactHost
+import com.facebook.react.ReactInstanceEventListener
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.bridge.ReactContext
+import com.facebook.react.bridge.UiThreadUtil
+import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
+import com.facebook.react.jstasks.HeadlessJsTaskConfig
+import com.facebook.react.jstasks.HeadlessJsTaskContext
+import com.facebook.react.jstasks.HeadlessJsTaskEventListener
+
+class HeadlessTaskManager(private val context: Context) : HeadlessJsTaskEventListener {
+
+ private var activeTaskId: Int? = null
+
+ companion object {
+ private const val TAG = "TelecomHeadlessJSHelper"
+ }
+
+ public fun startHeadlessTask(taskName: String, data: Bundle, timeout: Long) {
+ if (activeTaskId != null) {
+ Log.w(TAG, "startHeadlessTask: Task already starting or active, ignoring new task request")
+ return
+ }
+
+ if (UiThreadUtil.isOnUiThread()) {
+ startTask(HeadlessJsTaskConfig(taskName, Arguments.fromBundle(data), timeout, true))
+ } else {
+ UiThreadUtil.runOnUiThread(
+ Runnable {
+ startTask(HeadlessJsTaskConfig(taskName, Arguments.fromBundle(data), timeout, true))
+ }
+ )
+ }
+ }
+
+ public fun stopHeadlessTask() {
+ Log.d(TAG, "stopHeadlessTask: Stopping headless task")
+ activeTaskId?.let { taskId ->
+ if (UiThreadUtil.isOnUiThread()) {
+ stopTask(taskId)
+ } else {
+ UiThreadUtil.runOnUiThread(Runnable { stopTask(taskId) })
+ }
+ }
+ }
+
+ protected fun startTask(taskConfig: HeadlessJsTaskConfig) {
+ UiThreadUtil.assertOnUiThread()
+ // acquireWakeLockNow(this)
+
+ val context = reactContext
+ if (context == null) {
+ createReactContextAndScheduleTask(taskConfig)
+ } else {
+ invokeStartTask(context, taskConfig)
+ }
+ }
+
+ private fun invokeStartTask(reactContext: ReactContext, taskConfig: HeadlessJsTaskConfig) {
+ Log.d(TAG, "invokeStartTask: Invoking start task")
+ val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactContext)
+ headlessJsTaskContext.addTaskEventListener(this)
+
+ UiThreadUtil.runOnUiThread {
+ val taskId = headlessJsTaskContext.startTask(taskConfig)
+ activeTaskId = taskId
+ }
+ }
+
+ private fun stopTask(taskId: Int) {
+ reactContext?.let { context ->
+ val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(context)
+ if (headlessJsTaskContext.isTaskRunning(taskId)) {
+ headlessJsTaskContext.finishTask(taskId)
+ Log.d(TAG, "Stopped task: $taskId")
+ }
+ }
+ }
+
+ fun release() {
+ stopHeadlessTask()
+
+ reactContext?.let { context ->
+ val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(context)
+ headlessJsTaskContext.removeTaskEventListener(this)
+ }
+ // wakeLock?.release()
+ }
+
+ override fun onHeadlessJsTaskStart(taskId: Int) {
+ Log.d(TAG, "onHeadlessJsTaskStart: Task started: $taskId")
+ }
+
+ override fun onHeadlessJsTaskFinish(taskId: Int) {
+ Log.d(TAG, "onHeadlessJsTaskFinish: Task finished: $taskId")
+ activeTaskId = null
+ }
+
+ /**
+ * Get the [ReactNativeHost] used by this app. By default, assumes [getApplication] is an instance
+ * of [ReactApplication] and calls [ReactApplication.reactNativeHost].
+ *
+ * Override this method if your application class does not implement `ReactApplication` or you
+ * simply have a different mechanism for storing a `ReactNativeHost`, e.g. as a static field
+ * somewhere.
+ */
+ @Suppress("DEPRECATION")
+ protected open val reactNativeHost: ReactNativeHost
+ get() = (context.applicationContext as ReactApplication).reactNativeHost
+
+ /**
+ * Get the [ReactHost] used by this app. By default, assumes [getApplication] is an instance of
+ * [ReactApplication] and calls [ReactApplication.reactHost]. This method assumes it is called in
+ * new architecture and returns null if not.
+ */
+ protected open val reactHost: ReactHost?
+ get() = (context.applicationContext as ReactApplication).reactHost
+
+ protected val reactContext: ReactContext?
+ get() {
+ if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
+ val reactHost =
+ checkNotNull(reactHost) { "ReactHost is not initialized in New Architecture" }
+ return reactHost.currentReactContext
+ } else {
+ val reactInstanceManager = reactNativeHost.reactInstanceManager
+ return reactInstanceManager.currentReactContext
+ }
+ }
+
+ private fun createReactContextAndScheduleTask(taskConfig: HeadlessJsTaskConfig) {
+ if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
+ val reactHost = checkNotNull(reactHost)
+ reactHost.addReactInstanceEventListener(
+ object : ReactInstanceEventListener {
+ override fun onReactContextInitialized(context: ReactContext) {
+ Log.d(TAG, "createReactContextAndScheduleTask: React context initialized")
+ invokeStartTask(context, taskConfig)
+ reactHost.removeReactInstanceEventListener(this)
+ }
+ }
+ )
+ reactHost.start()
+ } else {
+ val reactInstanceManager = reactNativeHost.reactInstanceManager
+ reactInstanceManager.addReactInstanceEventListener(
+ object : ReactInstanceEventListener {
+ override fun onReactContextInitialized(context: ReactContext) {
+ Log.d(TAG, "createReactContextAndScheduleTask: React context initialized")
+ invokeStartTask(context, taskConfig)
+ reactInstanceManager.removeReactInstanceEventListener(this)
+ }
+ }
+ )
+ reactInstanceManager.createReactContextInBackground()
+ }
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/ResourceUtils.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/ResourceUtils.kt
new file mode 100644
index 0000000000..c0d01f7e89
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/ResourceUtils.kt
@@ -0,0 +1,60 @@
+package com.callingx
+
+import android.content.Context
+import android.media.RingtoneManager
+import android.net.Uri
+import android.util.Log
+import androidx.core.net.toUri
+
+
+object ResourceUtils {
+ private const val TAG = "[Callingx] ResourceUtils"
+
+ private val resourceIdCache = mutableMapOf()
+
+ private fun getResourceIdByName(context: Context, name: String?, type: String): Int {
+ if (name.isNullOrEmpty()) {
+ return 0
+ }
+
+ val normalizedName = name.lowercase().replace("-", "_")
+ val key = "${normalizedName}_$type"
+
+ synchronized(resourceIdCache) {
+ resourceIdCache[key]?.let {
+ return it
+ }
+
+ val packageName = context.packageName
+
+ val id = context.resources.getIdentifier(normalizedName, type, packageName)
+ resourceIdCache[key] = id
+ return id
+ }
+ }
+
+ fun getSoundUri(context: Context, sound: String?): Uri? {
+ Log.d(TAG, "getSoundUri: Getting sound URI for: $sound")
+ return when {
+ sound == null -> null
+ sound.contains("://") -> sound.toUri()
+ sound.equals("default", ignoreCase = true) -> {
+ RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
+ }
+
+ else -> {
+ // The API user is attempting to set a sound by file name, verify it exists
+ var soundResourceId = getResourceIdByName(context, sound, "raw")
+ if (soundResourceId == 0 && sound.contains(".")) {
+ soundResourceId = getResourceIdByName(context, sound.substringBeforeLast('.'), "raw")
+ }
+ if (soundResourceId == 0) {
+ null
+ } else {
+ // Use the actual sound name vs the resource ID, to obtain a stable URI, Issue #341
+ "android.resource://${context.packageName}/raw/$sound".toUri()
+ }
+ }
+ }
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/Utils.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/Utils.kt
new file mode 100644
index 0000000000..aa46143723
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/Utils.kt
@@ -0,0 +1,16 @@
+package com.callingx
+
+import android.telecom.DisconnectCause
+
+fun getDisconnectCauseString(cause: DisconnectCause): String {
+ return when (cause.code) {
+ DisconnectCause.LOCAL -> "local"
+ DisconnectCause.REMOTE -> "remote"
+ DisconnectCause.REJECTED -> "rejected"
+ DisconnectCause.BUSY -> "busy"
+ DisconnectCause.ANSWERED_ELSEWHERE -> "answeredElsewhere"
+ DisconnectCause.MISSED -> "missed"
+ DisconnectCause.ERROR -> "error"
+ else -> cause.toString()
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/model/Call.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/model/Call.kt
new file mode 100644
index 0000000000..513c6b9ea1
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/model/Call.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.callingx.model
+
+import android.os.ParcelUuid
+import android.os.Bundle
+import android.telecom.DisconnectCause
+import androidx.core.telecom.CallAttributesCompat
+import androidx.core.telecom.CallEndpointCompat
+import kotlinx.coroutines.channels.Channel
+
+/**
+ * Custom representation of a call state.
+ */
+sealed class Call {
+
+ /**
+ * There is no current or past calls in the stack
+ */
+ object None : Call()
+
+ /**
+ * Represents a registered call with the telecom stack with the values provided by the
+ * Telecom SDK
+ */
+ data class Registered(
+ val id: String,
+ val callAttributes: CallAttributesCompat,
+ val displayOptions: Bundle?,
+ val isActive: Boolean,
+ val isOnHold: Boolean,
+ val isMuted: Boolean,
+ val errorCode: Int?,
+ val currentCallEndpoint: CallEndpointCompat?,
+ val availableCallEndpoints: List,
+ internal val actionSource: Channel,
+ ) : Call() {
+
+ /**
+ * @return true if it's an incoming registered call, false otherwise
+ */
+ fun isIncoming() = callAttributes.direction == CallAttributesCompat.DIRECTION_INCOMING
+
+ /**
+ * Sends an action to the call session. It will be processed if it's still registered.
+ *
+ * @return true if the action was sent, false otherwise
+ */
+ fun processAction(action: CallAction) = actionSource.trySend(action).isSuccess
+ }
+
+ /**
+ * Represent a previously registered call that was disconnected
+ */
+ data class Unregistered(
+ val id: String,
+ val callAttributes: CallAttributesCompat,
+ val disconnectCause: DisconnectCause,
+ ) : Call()
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/model/CallAction.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/model/CallAction.kt
new file mode 100644
index 0000000000..a3ffe40c84
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/model/CallAction.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.callingx.model
+
+import android.os.ParcelUuid
+import android.os.Parcelable
+import android.telecom.DisconnectCause
+import kotlinx.parcelize.Parcelize
+
+/**
+ * Simple interface to represent related call actions to communicate with the registered call scope
+ * in the [TelecomCallRepository.registerCall]
+ *
+ * Note: we are using [Parcelize] to make the actions parcelable so they can be directly used in the
+ * call notification.
+ */
+sealed interface CallAction : Parcelable {
+ @Parcelize
+ data class Answer(val isAudioCall: Boolean) : CallAction
+
+ @Parcelize
+ data class Disconnect(val cause: DisconnectCause) : CallAction
+
+ @Parcelize
+ object Hold : CallAction
+
+ @Parcelize
+ object Activate : CallAction
+
+ @Parcelize
+ data class ToggleMute(val isMute: Boolean) : CallAction
+
+ @Parcelize
+ data class SwitchAudioEndpoint(val endpointId: ParcelUuid) : CallAction
+
+ @Parcelize
+ data class TransferCall(val endpointId: ParcelUuid) : CallAction
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/CallNotificationManager.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/CallNotificationManager.kt
new file mode 100644
index 0000000000..2f91e3885e
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/CallNotificationManager.kt
@@ -0,0 +1,193 @@
+package com.callingx.notifications
+
+import android.app.Notification
+import android.content.Context
+import android.media.Ringtone
+import android.media.RingtoneManager
+import android.os.Build
+import android.telecom.DisconnectCause
+import android.util.Log
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import androidx.core.app.Person
+import androidx.core.graphics.drawable.IconCompat
+import com.callingx.CallService
+import com.callingx.CallingxModule
+import com.callingx.R
+import com.callingx.ResourceUtils
+import com.callingx.getDisconnectCauseString
+import com.callingx.model.Call
+
+/**
+ * Handles call status changes and updates the notification accordingly. For more guidance around
+ * notifications check https://developer.android.com/develop/ui/views/notifications
+ *
+ * @see updateCallNotification
+ */
+class CallNotificationManager(
+ private val context: Context,
+ private val notificationManager: NotificationManagerCompat =
+ NotificationManagerCompat.from(context)
+) {
+
+ internal companion object {
+ private const val TAG = "[Callingx] CallNotificationManager"
+
+ const val NOTIFICATION_ID = 200
+ }
+
+ private var notificationsConfig = NotificationsConfig.loadNotificationsConfig(context)
+
+ private var ringtone: Ringtone? = null
+
+ private var hasBecameActive = false
+
+ fun createNotification(call: Call.Registered): Notification {
+ Log.d(TAG, "[notifications] createNotification: Creating notification for call ID: ${call.id}")
+
+ val contentIntent =
+ NotificationIntentFactory.getLaunchActivityIntent(
+ context,
+ CallingxModule.CALL_ANSWERED_ACTION,
+ call.id
+ )
+ val callStyle = createCallStyle(call)
+ val channelId = getChannelId(call)
+ Log.d(TAG, "[notifications] createNotification: Channel ID: $channelId")
+
+ val builder =
+ NotificationCompat.Builder(context, channelId)
+ .setContentIntent(contentIntent)
+ .setFullScreenIntent(contentIntent, true)
+ .setStyle(callStyle)
+ .setSmallIcon(R.drawable.ic_round_call_24)
+ .setCategory(NotificationCompat.CATEGORY_CALL)
+ .setPriority(NotificationCompat.PRIORITY_MAX)
+ .setOngoing(true)
+
+ if (!hasBecameActive && call.isActive) {
+ Log.d(TAG, "[notifications] createNotification: Setting when to current time")
+ builder.setWhen(System.currentTimeMillis())
+ builder.setUsesChronometer(true)
+ builder.setShowWhen(true)
+ hasBecameActive = true
+ }
+
+ call.displayOptions?.let {
+ if (it.containsKey(CallService.EXTRA_DISPLAY_SUBTITLE)) {
+ builder.setContentText(it.getString(CallService.EXTRA_DISPLAY_SUBTITLE))
+ }
+ }
+
+ return builder.build()
+ }
+
+ fun updateCallNotification(call: Call) {
+ when (call) {
+ Call.None, is Call.Unregistered -> {
+ Log.d(TAG, "[notifications] updateCallNotification: Dismissing notification (call is None or Unregistered)")
+ notificationManager.cancel(NOTIFICATION_ID)
+ }
+ is Call.Registered -> {
+ val notification = createNotification(call)
+ notificationManager.notify(NOTIFICATION_ID, notification)
+ Log.d(TAG, "[notifications] updateCallNotification: Notification posted successfully")
+ }
+ }
+ }
+
+ fun cancelNotifications() {
+ notificationManager.cancel(NOTIFICATION_ID)
+ hasBecameActive = false
+ }
+
+ fun startRingtone() {
+ if (ringtone?.isPlaying == true) {
+ Log.d(TAG, "[notifications] startRingtone: Ringtone already playing")
+ return
+ }
+
+ val soundUri =
+ ResourceUtils.getSoundUri(context, notificationsConfig.incomingChannel.sound)
+ ?: RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
+
+ ringtone = RingtoneManager.getRingtone(context, soundUri)
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ ringtone?.isLooping = true
+ }
+
+ ringtone?.play()
+ Log.d(TAG, "[notifications] startRingtone: Ringtone started")
+ }
+
+ fun stopRingtone() {
+ if (ringtone?.isPlaying == true) {
+ ringtone?.stop()
+ Log.d(TAG, "[notifications] stopRingtone: Ringtone stopped")
+ }
+ ringtone = null
+ }
+
+ private fun getChannelId(call: Call.Registered): String {
+ return if (call.isIncoming() && !call.isActive) {
+ notificationsConfig.incomingChannel.id
+ } else {
+ notificationsConfig.outgoingChannel.id
+ }
+ }
+
+ private fun createCallStyle(call: Call.Registered): NotificationCompat.CallStyle {
+ val caller = createPerson(call)
+
+ if (call.isIncoming() && !call.isActive) {
+ return NotificationCompat.CallStyle.forIncomingCall(
+ caller,
+ NotificationIntentFactory.getPendingBroadcastIntent(
+ context,
+ CallingxModule.CALL_END_ACTION,
+ call.id
+ ) {
+ putExtra(
+ CallingxModule.EXTRA_DISCONNECT_CAUSE,
+ getDisconnectCauseString(DisconnectCause(DisconnectCause.REJECTED))
+ )
+ putExtra(CallingxModule.EXTRA_SOURCE, CallRepository.EventSource.SYS.name.lowercase())
+ },
+ NotificationIntentFactory.getPendingNotificationIntent(
+ context,
+ CallingxModule.CALL_ANSWERED_ACTION,
+ call.id,
+ CallRepository.EventSource.SYS.name.lowercase()
+ )
+ )
+ }
+
+ return NotificationCompat.CallStyle.forOngoingCall(
+ caller,
+ NotificationIntentFactory.getPendingBroadcastIntent(
+ context,
+ CallingxModule.CALL_END_ACTION,
+ call.id
+ ) {
+ putExtra(
+ CallingxModule.EXTRA_DISCONNECT_CAUSE,
+ getDisconnectCauseString(DisconnectCause(DisconnectCause.LOCAL))
+ )
+ putExtra(CallingxModule.EXTRA_SOURCE, CallRepository.EventSource.SYS.name.lowercase())
+ },
+ )
+ }
+
+ private fun createPerson(call: Call.Registered): Person {
+ val displayCallerName = call.displayOptions?.getString(CallService.EXTRA_DISPLAY_TITLE)
+ val address = call.callAttributes.address.toString()
+
+ return Person.Builder()
+ .setName(displayCallerName ?: call.callAttributes.displayName)
+ .setUri(address)
+ .setIcon(IconCompat.createWithResource(context, R.drawable.ic_user))
+ .setImportant(true)
+ .build()
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationChannelsManager.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationChannelsManager.kt
new file mode 100644
index 0000000000..6a5c558e6a
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationChannelsManager.kt
@@ -0,0 +1,113 @@
+package com.callingx.notifications
+
+import android.Manifest
+import android.content.Context
+import android.os.Build
+import android.util.Log
+import androidx.core.app.NotificationChannelCompat
+import androidx.core.app.NotificationManagerCompat
+import androidx.core.content.PermissionChecker
+
+class NotificationChannelsManager(
+ private val context: Context,
+ private val notificationManager: NotificationManagerCompat =
+ NotificationManagerCompat.from(context)
+) {
+
+ private var notificationsConfig: NotificationsConfig.Channels? = null
+
+ companion object {
+ private const val TAG = "[Callingx] NotificationChannelsManager"
+ }
+
+ data class NotificationStatus(
+ val canPost: Boolean,
+ val hasPermissions: Boolean,
+ val areNotificationsEnabled: Boolean,
+ val isIncomingChannelEnabled: Boolean,
+ val isOutgoingChannelEnabled: Boolean,
+ )
+
+ fun setNotificationsConfig(notificationsConfig: NotificationsConfig.Channels) {
+ this.notificationsConfig = notificationsConfig
+ }
+
+ fun createNotificationChannels() {
+ notificationsConfig?.let {
+ val incomingChannel = createNotificationChannel(it.incomingChannel)
+ val ongoingChannel = createNotificationChannel(it.outgoingChannel)
+
+ notificationManager.createNotificationChannelsCompat(
+ listOf(
+ incomingChannel,
+ ongoingChannel,
+ ),
+ )
+ Log.d(TAG, "createNotificationChannels: Notification channels registered")
+ }
+ }
+
+ fun getNotificationStatus(): NotificationStatus {
+ val areNotificationsEnabled = areNotificationsEnabled()
+ val hasPermissions = hasNotificationPermissions()
+ val isIncomingChannelEnabled = isChannelEnabled(notificationsConfig?.incomingChannel?.id)
+ val isOutgoingChannelEnabled = isChannelEnabled(notificationsConfig?.outgoingChannel?.id)
+
+ val canPost =
+ areNotificationsEnabled &&
+ hasPermissions &&
+ isIncomingChannelEnabled &&
+ isOutgoingChannelEnabled
+
+ return NotificationStatus(
+ canPost,
+ hasPermissions,
+ areNotificationsEnabled,
+ isIncomingChannelEnabled,
+ isOutgoingChannelEnabled
+ )
+ }
+
+ private fun createNotificationChannel(
+ config: NotificationsConfig.ChannelParams
+ ): NotificationChannelCompat {
+ return NotificationChannelCompat.Builder(config.id, config.importance)
+ .apply {
+ setName(config.name)
+ setVibrationEnabled(config.vibration)
+ setSound(null, null)
+ }
+ .build()
+ }
+
+ private fun areNotificationsEnabled(): Boolean {
+ return notificationManager.areNotificationsEnabled()
+ }
+
+ private fun hasNotificationPermissions(): Boolean {
+ // POST_NOTIFICATIONS permission is only required on Android 13+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ return true
+ }
+
+ val permission =
+ PermissionChecker.checkSelfPermission(
+ context,
+ Manifest.permission.POST_NOTIFICATIONS,
+ )
+ return permission == PermissionChecker.PERMISSION_GRANTED
+ }
+
+ private fun isChannelEnabled(channelId: String?): Boolean {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ return true
+ }
+
+ if (channelId == null) {
+ return false
+ }
+
+ val channel = notificationManager.getNotificationChannel(channelId)
+ return channel != null && channel.importance != NotificationManagerCompat.IMPORTANCE_NONE
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationIntentFactory.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationIntentFactory.kt
new file mode 100644
index 0000000000..48d06267ca
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationIntentFactory.kt
@@ -0,0 +1,105 @@
+package com.callingx.notifications
+
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import com.callingx.CallingxModule
+
+object NotificationIntentFactory {
+ // Stable request codes for PendingIntents
+ private const val REQUEST_CODE_LAUNCH_ACTIVITY = 1001
+ private const val REQUEST_CODE_RECEIVER_ACTIVITY = 1002
+ private const val REQUEST_CODE_SERVICE = 1003
+
+ fun getPendingNotificationIntent(
+ context: Context,
+ action: String,
+ callId: String,
+ source: String
+ ): PendingIntent {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getReceiverActivityIntent(context, action, callId, source)
+ } else {
+ getPendingServiceIntent(context, action, callId, source)
+ }
+ }
+
+ fun getPendingServiceIntent(context: Context, action: String, callId: String, source: String): PendingIntent {
+ val intent =
+ Intent(context, NotificationReceiverService::class.java).apply {
+ this.action = action
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ putExtra(CallingxModule.EXTRA_SOURCE, source)
+ }
+
+ return PendingIntent.getService(
+ context,
+ REQUEST_CODE_SERVICE,
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
+ )
+ }
+
+ fun getReceiverActivityIntent(context: Context, action: String, callId: String, source: String): PendingIntent {
+ val receiverIntent =
+ Intent(context, NotificationReceiverActivity::class.java).apply {
+ this.action = action
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ putExtra(CallingxModule.EXTRA_SOURCE, source)
+ }
+
+ val launchActivity = context.packageManager.getLaunchIntentForPackage(context.packageName)
+ val launchActivityIntent =
+ Intent(launchActivity).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ }
+
+ return PendingIntent.getActivities(
+ context,
+ REQUEST_CODE_RECEIVER_ACTIVITY,
+ arrayOf(launchActivityIntent, receiverIntent),
+ PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ )
+ }
+
+ fun getLaunchActivityIntent(context: Context, action: String, callId: String, source: String? = null): PendingIntent {
+ val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
+ val callIntent =
+ Intent(launchIntent).apply {
+ this.action = action
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ source?.let { putExtra(CallingxModule.EXTRA_SOURCE, it) }
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ }
+
+ return PendingIntent.getActivity(
+ context,
+ REQUEST_CODE_LAUNCH_ACTIVITY,
+ callIntent,
+ PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
+ )
+ }
+
+ fun getPendingBroadcastIntent(
+ context: Context,
+ action: String,
+ callId: String,
+ addExtras: Intent.() -> Unit = {}
+ ): PendingIntent {
+ val intent =
+ Intent(action).apply {
+ setPackage(context.packageName)
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ addExtras(this)
+ }
+
+ // Use action hashCode for unique request code per action type
+ return PendingIntent.getBroadcast(
+ context,
+ action.hashCode(),
+ intent,
+ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ )
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationReceiverActivity.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationReceiverActivity.kt
new file mode 100644
index 0000000000..1d66ce08af
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationReceiverActivity.kt
@@ -0,0 +1,42 @@
+package com.callingx.notifications
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import com.callingx.CallingxModule
+
+// For Android 12+
+class NotificationReceiverActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ handleIntent(intent)
+ finish()
+ }
+
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+ handleIntent(intent)
+ finish()
+ }
+
+ //re-send intent from notification to the turbo module
+ private fun handleIntent(intent: Intent?) {
+ if (intent == null) {
+ return
+ }
+
+ //we need it only for answered call event, as for cold start case we need to send broadcast event and to launch the app
+ if (intent.action == CallingxModule.CALL_ANSWERED_ACTION) {
+ val callId = intent.getStringExtra(CallingxModule.EXTRA_CALL_ID)
+ val source = intent.getStringExtra(CallingxModule.EXTRA_SOURCE)
+ Intent(CallingxModule.CALL_ANSWERED_ACTION)
+ .apply {
+ setPackage(packageName)
+ putExtra(CallingxModule.EXTRA_CALL_ID, callId)
+ putExtra(CallingxModule.EXTRA_SOURCE, source)
+ }
+ .also { sendBroadcast(it) }
+ }
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationReceiverService.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationReceiverService.kt
new file mode 100644
index 0000000000..13afa95974
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationReceiverService.kt
@@ -0,0 +1,47 @@
+package com.callingx.notifications
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import com.callingx.CallingxModule
+
+class NotificationReceiverService : Service() {
+
+ override fun onBind(intent: Intent?): IBinder? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ val action = intent?.action
+ if (action == null) {
+ stopSelf(startId)
+ return START_NOT_STICKY
+ }
+
+ when (action) {
+ CallingxModule.CALL_ANSWERED_ACTION -> onCallAnswered(intent)
+ }
+
+ stopSelf(startId)
+ return START_NOT_STICKY
+ }
+
+ private fun onCallAnswered(intent: Intent) {
+ val callId = intent.getStringExtra(CallingxModule.EXTRA_CALL_ID)
+ val source = intent.getStringExtra(CallingxModule.EXTRA_SOURCE)
+ callId?.let {
+ NotificationIntentFactory.getPendingBroadcastIntent(
+ applicationContext,
+ CallingxModule.CALL_ANSWERED_ACTION,
+ it
+ ) { putExtra(CallingxModule.EXTRA_SOURCE, source) }
+ .send()
+
+ NotificationIntentFactory.getLaunchActivityIntent(
+ applicationContext,
+ CallingxModule.CALL_ANSWERED_ACTION,
+ it,
+ source
+ )
+ .send()
+ }
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationsConfig.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationsConfig.kt
new file mode 100644
index 0000000000..700923c00c
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationsConfig.kt
@@ -0,0 +1,116 @@
+package com.callingx.notifications
+
+import android.content.Context
+import android.util.Log
+import androidx.core.app.NotificationManagerCompat
+import androidx.core.content.edit
+import com.facebook.react.bridge.ReadableMap
+
+object NotificationsConfig {
+ private const val TAG = "[Callingx] NotificationsConfig"
+ private const val PREFS_NAME = "CallingxPrefs"
+ private const val PREFIX_IN = "incoming_"
+ private const val PREFIX_OUT = "outgoing_"
+ private const val KEY_ID = "id"
+ private const val KEY_NAME = "name"
+ private const val KEY_SOUND = "sound"
+ private const val KEY_VIBRATION = "vibration"
+
+ data class ChannelParams(
+ val id: String,
+ val name: String,
+ val sound: String?,
+ val vibration: Boolean,
+ val importance: Int,
+ )
+
+ data class Channels(
+ val incomingChannel: ChannelParams,
+ val outgoingChannel: ChannelParams,
+ )
+
+ fun saveNotificationsConfig(context: Context, rawConfig: ReadableMap): Channels {
+ Log.d(TAG, "saveNotificationsConfig: Saving notifications config: $rawConfig")
+ val config = extractNotificationsConfig(rawConfig)
+ val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ prefs.edit {
+ // Incoming channel
+ putString(PREFIX_IN + KEY_ID, config.incomingChannel.id)
+ putString(PREFIX_IN + KEY_NAME, config.incomingChannel.name)
+ putString(PREFIX_IN + KEY_SOUND, config.incomingChannel.sound)
+ putBoolean(PREFIX_IN + KEY_VIBRATION, config.incomingChannel.vibration)
+
+ // Outgoing channel
+ putString(PREFIX_OUT + KEY_ID, config.outgoingChannel.id)
+ putString(PREFIX_OUT + KEY_NAME, config.outgoingChannel.name)
+ }
+
+ return config
+ }
+
+ fun loadNotificationsConfig(context: Context): Channels {
+ val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ Log.d(
+ TAG,
+ "loadNotificationsConfig: Loading notifications config ${
+ prefs.getString(
+ PREFIX_IN + KEY_ID,
+ ""
+ )
+ }"
+ )
+ return Channels(
+ incomingChannel =
+ ChannelParams(
+ id = prefs.getString(PREFIX_IN + KEY_ID, "") ?: "",
+ name = prefs.getString(PREFIX_IN + KEY_NAME, "") ?: "",
+ sound = prefs.getString(PREFIX_IN + KEY_SOUND, "") ?: "",
+ vibration = prefs.getBoolean(PREFIX_IN + KEY_VIBRATION, false),
+ importance = NotificationManagerCompat.IMPORTANCE_MAX,
+ ),
+ outgoingChannel =
+ ChannelParams(
+ id = prefs.getString(PREFIX_OUT + KEY_ID, "") ?: "",
+ name = prefs.getString(PREFIX_OUT + KEY_NAME, "") ?: "",
+ importance = NotificationManagerCompat.IMPORTANCE_DEFAULT,
+ vibration = false,
+ sound = null,
+ )
+ )
+ }
+
+ fun extractNotificationsConfig(config: ReadableMap): Channels {
+ return Channels(
+ incomingChannel =
+ extractChannelConfig(
+ config.getMap("incomingChannel"),
+ NotificationManagerCompat.IMPORTANCE_MAX
+ ),
+ outgoingChannel =
+ extractChannelConfig(
+ config.getMap("outgoingChannel"),
+ NotificationManagerCompat.IMPORTANCE_DEFAULT
+ ),
+ )
+ }
+
+ fun extractChannelConfig(channel: ReadableMap?, importance: Int): ChannelParams {
+ if (channel == null) {
+ return ChannelParams(
+ id = "",
+ name = "",
+ sound = "",
+ vibration = false,
+ importance = importance,
+ )
+ }
+
+ return ChannelParams(
+ id = channel.getString("id") ?: "",
+ name = channel.getString("name") ?: "",
+ sound = channel.getString("sound"),
+ vibration = channel.hasKey("vibration") && channel.getBoolean("vibration") ?: false,
+ importance = importance,
+ )
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/repo/CallRepository.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/repo/CallRepository.kt
new file mode 100644
index 0000000000..7d2c380763
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/repo/CallRepository.kt
@@ -0,0 +1,51 @@
+import android.content.Context
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.telecom.DisconnectCause
+import com.callingx.model.Call
+import com.callingx.repo.TelecomCallRepository
+import kotlinx.coroutines.flow.StateFlow
+
+interface CallRepository {
+
+ enum class EventSource {
+ APP, SYS
+ }
+
+ interface Listener {
+ fun onCallStateChanged(call: Call)
+ fun onIsCallAnswered(callId: String, source: EventSource)
+ fun onIsCallDisconnected(callId: String?, cause: DisconnectCause, source: EventSource)
+ fun onIsCallInactive(callId: String)
+ fun onIsCallActive(callId: String)
+ fun onCallRegistered(callId: String)
+ fun onMuteCallChanged(callId: String, isMuted: Boolean)
+ fun onCallEndpointChanged(callId: String, endpoint: String)
+ }
+
+ val currentCall: StateFlow
+
+ fun setListener(listener: Listener)
+ fun release()
+
+ suspend fun registerCall(
+ callId: String,
+ displayName: String,
+ address: Uri,
+ isIncoming: Boolean,
+ isVideo: Boolean,
+ displayOptions: Bundle?,
+ )
+}
+
+object CallRepositoryFactory {
+
+ fun create(context: Context): CallRepository {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ TelecomCallRepository(context) // Your current CallRepository renamed
+ } else {
+ LegacyCallRepository(context) // Fallback implementation
+ }
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/repo/LegacyCallRepository.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/repo/LegacyCallRepository.kt
new file mode 100644
index 0000000000..d27a896c8b
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/repo/LegacyCallRepository.kt
@@ -0,0 +1,163 @@
+import android.content.Context
+import android.net.Uri
+import android.os.Bundle
+import android.util.Log
+import androidx.core.telecom.CallAttributesCompat
+import com.callingx.model.Call
+import com.callingx.model.CallAction
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.consumeAsFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+
+class LegacyCallRepository(private val context: Context) : CallRepository {
+
+ companion object {
+ private const val TAG = "[Callingx] LegacyCallRepository"
+ }
+
+ private val _currentCall: MutableStateFlow = MutableStateFlow(Call.None)
+ override val currentCall = _currentCall.asStateFlow()
+
+ private var listener: CallRepository.Listener? = null
+ private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
+
+ override fun setListener(listener: CallRepository.Listener) {
+ this.listener = listener
+ // Observe call state changes
+ scope.launch { currentCall.collect { listener.onCallStateChanged(it) } }
+ }
+
+ override fun release() {
+ _currentCall.value = Call.None
+
+ listener = null
+
+ scope.cancel()
+ }
+
+ override suspend fun registerCall(
+ callId: String,
+ displayName: String,
+ address: Uri,
+ isIncoming: Boolean,
+ isVideo: Boolean,
+ displayOptions: Bundle?,
+ ) {
+
+ val attributes = createCallAttributes(displayName, address, isIncoming, isVideo)
+ val actionSource = Channel()
+
+ _currentCall.value =
+ Call.Registered(
+ id = callId,
+ isActive = false,
+ isOnHold = false,
+ callAttributes = attributes,
+ displayOptions = displayOptions,
+ isMuted = false,
+ errorCode = null,
+ currentCallEndpoint = null,
+ availableCallEndpoints = emptyList(),
+ actionSource = actionSource,
+ )
+
+ listener?.onCallRegistered(callId)
+
+ // Process actions without telecom SDK
+ scope.launch {
+ actionSource.consumeAsFlow().collect { action -> processActionLegacy(action) }
+ }
+ }
+
+ private fun processActionLegacy(action: CallAction) {
+ when (action) {
+ is CallAction.Answer -> {
+ updateCurrentCall { copy(isActive = true, isOnHold = false) }
+ // In legacy mode, all actions are initiated from the app
+ (currentCall.value as? Call.Registered)?.let {
+ listener?.onIsCallAnswered(it.id, CallRepository.EventSource.APP)
+ }
+ }
+ is CallAction.Disconnect -> {
+ val call = currentCall.value as? Call.Registered
+ if (call != null) {
+ _currentCall.value =
+ Call.Unregistered(call.id, call.callAttributes, action.cause)
+ // In legacy mode, all actions are initiated from the app
+ listener?.onIsCallDisconnected(call.id, action.cause, CallRepository.EventSource.APP)
+ }
+ }
+ is CallAction.ToggleMute -> {
+ updateCurrentCall { copy(isMuted = action.isMute) }
+ }
+ // Handle other actions...
+ else -> {
+ /* No-op for unsupported actions */
+ }
+ }
+ }
+
+ private fun updateCurrentCall(transform: Call.Registered.() -> Call) {
+ val currentState = _currentCall.value
+ Log.d(
+ TAG,
+ "[repository] updateCurrentCall: Current call state: ${currentState::class.simpleName}"
+ )
+
+ _currentCall.update { call ->
+ if (call is Call.Registered) {
+ val updated = call.transform()
+ Log.d(
+ TAG,
+ "[repository] updateCurrentCall: Call state updated to: ${updated::class.simpleName}"
+ )
+ updated
+ } else {
+ Log.w(
+ TAG,
+ "[repository] updateCurrentCall: Call is not Registered, skipping update"
+ )
+ call
+ }
+ }
+ }
+
+ private fun createCallAttributes(
+ displayName: String,
+ address: Uri,
+ isIncoming: Boolean,
+ isVideo: Boolean
+ ): CallAttributesCompat {
+ Log.d(
+ TAG,
+ "createCallAttributes: Creating CallAttributes - Direction: ${if (isIncoming) "Incoming" else "Outgoing"}, Type: ${if (isVideo) "Video" else "Audio"}"
+ )
+ return CallAttributesCompat(
+ displayName = displayName,
+ address = address,
+ direction =
+ if (isIncoming) {
+ CallAttributesCompat.DIRECTION_INCOMING
+ } else {
+ CallAttributesCompat.DIRECTION_OUTGOING
+ },
+ callType =
+ if (isVideo) {
+ CallAttributesCompat.CALL_TYPE_VIDEO_CALL
+ } else {
+ CallAttributesCompat.CALL_TYPE_AUDIO_CALL
+ },
+ callCapabilities =
+ CallAttributesCompat.SUPPORTS_SET_INACTIVE or
+ CallAttributesCompat.SUPPORTS_STREAM or
+ CallAttributesCompat.SUPPORTS_TRANSFER,
+ )
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/java/com/callingx/repo/TelecomCallRepository.kt b/packages/react-native-callingx/android/src/main/java/com/callingx/repo/TelecomCallRepository.kt
new file mode 100644
index 0000000000..2efeb1e226
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/java/com/callingx/repo/TelecomCallRepository.kt
@@ -0,0 +1,469 @@
+package com.callingx.repo
+
+import CallRepository
+import android.content.Context
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.telecom.DisconnectCause
+import android.util.Log
+import androidx.annotation.RequiresApi
+import androidx.core.telecom.CallAttributesCompat
+import androidx.core.telecom.CallControlResult
+import androidx.core.telecom.CallControlScope
+import androidx.core.telecom.CallsManager
+import com.callingx.model.Call
+import com.callingx.model.CallAction
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.consumeAsFlow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.scan
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+
+/**
+ * The central repository that keeps track of the current call and allows to register new calls.
+ *
+ * This class contains the main logic to integrate with Telecom SDK.
+ *
+ * @see registerCall
+ */
+@RequiresApi(Build.VERSION_CODES.O)
+class TelecomCallRepository(private val context: Context) : CallRepository {
+
+ companion object {
+ private const val TAG = "[Callingx] TelecomCallRepository"
+ }
+
+ private var listener: CallRepository.Listener? = null
+ private var observeCallStateJob: Job? = null
+
+ private val callsManager: CallsManager
+ private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
+ private var isSelfAnswered = false
+ private var isSelfDisconnected = false
+
+ // Keeps track of the current TelecomCall state
+ private val _currentCall: MutableStateFlow = MutableStateFlow(Call.None)
+ override val currentCall = _currentCall.asStateFlow()
+
+ init {
+ val capabilities =
+ CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING and
+ CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING
+ callsManager =
+ CallsManager(context.applicationContext).apply {
+ registerAppWithTelecom(capabilities)
+ }
+ Log.d(TAG, "[repository] init: CallsManager created and registered")
+ }
+
+ override fun setListener(listener: CallRepository.Listener) {
+ this.listener = listener
+
+ observeCallStateJob?.cancel()
+ observeCallStateJob = observeCallState()
+ }
+
+ override fun release() {
+ val currentCall = currentCall.value
+ if (currentCall is Call.Registered) {
+ currentCall.processAction(CallAction.Disconnect(DisconnectCause(DisconnectCause.LOCAL)))
+ }
+ _currentCall.value = Call.None
+
+ observeCallStateJob?.cancel()
+ observeCallStateJob = null
+ listener = null
+
+ scope.cancel()
+ }
+
+ /**
+ * Register a new call with the provided attributes. Use the [currentCall] StateFlow to receive
+ * status updates and process call related actions.
+ */
+ override suspend fun registerCall(
+ callId: String,
+ displayName: String,
+ address: Uri,
+ isIncoming: Boolean,
+ isVideo: Boolean,
+ displayOptions: Bundle?,
+ ) {
+ Log.d(
+ TAG,
+ "[repository] registerCall: Starting registration - Name: $displayName, Address: $address, Incoming: $isIncoming"
+ )
+
+ // For simplicity we don't support multiple calls
+ check(_currentCall.value !is Call.Registered) {
+ "There cannot be more than one call at the same time."
+ }
+ Log.d(
+ TAG,
+ "[repository] registerCall: No existing call found, proceeding with registration"
+ )
+
+ val attributes = createCallAttributes(displayName, address, isIncoming, isVideo)
+ val actionSource = Channel()
+
+ // Register the call and handle actions in the scope
+ try {
+ callsManager.addCall(
+ attributes,
+ onIsCallAnswered, // Watch needs to know if it can answer the call
+ onIsCallDisconnected,
+ onIsCallActive,
+ onIsCallInactive
+ ) {
+ Log.d(TAG, "[repository] registerCall: Inside call scope, setting up call handlers")
+
+ // Consume the actions to interact with the call inside the scope
+ launch { processCallActions(actionSource.consumeAsFlow()) }
+
+ // Update the state to registered with default values while waiting for Telecom
+ // updates
+ Log.d(
+ TAG,
+ "[repository] registerCall: Creating Registered call state with ID: $callId"
+ )
+ _currentCall.value =
+ Call.Registered(
+ id = callId,
+ isActive = false, // can we just register the call as active?
+ isOnHold = false,
+ callAttributes = attributes,
+ displayOptions = displayOptions,
+ isMuted = false,
+ errorCode = null,
+ currentCallEndpoint = null,
+ availableCallEndpoints = emptyList(),
+ actionSource = actionSource,
+ )
+ Log.d(TAG, "[repository] registerCall: Call state updated to Registered")
+
+ launch {
+ currentCallEndpoint.collect {
+ updateCurrentCall { copy(currentCallEndpoint = it) }
+ }
+ }
+ launch {
+ availableEndpoints.collect {
+ updateCurrentCall { copy(availableCallEndpoints = it) }
+ }
+ }
+ launch { isMuted.collect { updateCurrentCall { copy(isMuted = it) } } }
+ }
+ Log.d(TAG, "[repository] registerCall: Call successfully registered with Telecom SDK")
+ } catch (e: Exception) {
+ Log.e(TAG, "[repository] registerCall: Error registering call", e)
+ throw e
+ } finally {
+ Log.d(TAG, "[repository] registerCall: Call scope ended, setting state to None")
+ _currentCall.value = Call.None
+ }
+ }
+
+ private fun observeCallState(): Job {
+ return currentCall
+ .scan(Pair(null, currentCall.value)) { (_, prev), next ->
+ Pair(prev, next)
+ }
+ .onEach { (previous, current) ->
+ when {
+ previous is Call.None && current is Call.Registered -> {
+ if (!(current as Call.Registered).isIncoming()) {
+ listener?.onCallRegistered(current.id)
+ }
+ }
+ previous is Call.Registered && current is Call.Registered -> {
+ if (previous.isMuted != current.isMuted) {
+ Log.d(
+ TAG,
+ "[repository] observeCallState: Mute changed: ${current.isMuted}"
+ )
+ listener?.onMuteCallChanged(current.id, current.isMuted)
+ }
+ if (previous.currentCallEndpoint != current.currentCallEndpoint) {
+ current.currentCallEndpoint?.let {
+ listener?.onCallEndpointChanged(current.id, it.name.toString())
+ }
+ }
+ }
+ }
+ listener?.onCallStateChanged(current)
+ }
+ .launchIn(scope)
+ }
+
+ /** Collect the action source to handle client actions inside the call scope */
+ private suspend fun CallControlScope.processCallActions(actionSource: Flow) {
+ actionSource.collect { action ->
+ Log.d(TAG, "[repository] processCallActions: action: ${action::class.simpleName}")
+ when (action) {
+ is CallAction.Answer -> {
+ doAnswer(action.isAudioCall)
+ }
+ is CallAction.Disconnect -> {
+ doDisconnect(action)
+ }
+ is CallAction.SwitchAudioEndpoint -> {
+ doSwitchEndpoint(action)
+ }
+ is CallAction.TransferCall -> {
+ Log.d(
+ TAG,
+ "[repository] processCallActions: Transfer to endpoint: ${action.endpointId}"
+ )
+ val call = _currentCall.value as? Call.Registered
+ val endpoints =
+ call?.availableCallEndpoints?.firstOrNull {
+ it.identifier == action.endpointId
+ }
+ if (endpoints != null) {
+ requestEndpointChange(
+ endpoint = endpoints,
+ )
+ } else {
+ Log.w(
+ TAG,
+ "[repository] processCallActions: Endpoint not found for transfer, ignoring"
+ )
+ }
+ }
+ CallAction.Hold -> {
+ when (val result = setInactive()) {
+ is CallControlResult.Success -> {
+ onIsCallInactive()
+ }
+ is CallControlResult.Error -> {
+ Log.e(
+ TAG,
+ "[repository] processCallActions: Hold action failed with error code: ${result.errorCode}"
+ )
+ updateCurrentCall { copy(errorCode = result.errorCode) }
+ }
+ }
+ }
+ CallAction.Activate -> {
+ when (val result = setActive()) {
+ is CallControlResult.Success -> {
+ onIsCallActive()
+ }
+ is CallControlResult.Error -> {
+ Log.e(
+ TAG,
+ "[repository] processCallActions: Activate action failed with error code: ${result.errorCode}"
+ )
+ updateCurrentCall { copy(errorCode = result.errorCode) }
+ }
+ }
+ }
+ is CallAction.ToggleMute -> {
+ // We cannot programmatically mute the telecom stack. Instead we just update
+ // the state of the call and this will start/stop audio capturing.
+ Log.d(TAG, "[repository] processCallActions: Toggling mute: ${action.isMute}")
+ updateCurrentCall {
+ val newMutedState = action.isMute
+ copy(isMuted = newMutedState)
+ }
+ }
+ }
+ }
+ Log.d(TAG, "[repository] processCallActions: Action collection ended")
+ }
+
+ /**
+ * Update the current state of our call applying the transform lambda only if the call is
+ * registered. Otherwise keep the current state
+ */
+ private fun updateCurrentCall(transform: Call.Registered.() -> Call) {
+ val currentState = _currentCall.value
+ Log.d(
+ TAG,
+ "[repository] updateCurrentCall: Current call state: ${currentState::class.simpleName}"
+ )
+ _currentCall.update { call ->
+ if (call is Call.Registered) {
+ val updated = call.transform()
+ Log.d(
+ TAG,
+ "[repository] updateCurrentCall: Call state updated to: ${updated::class.simpleName}"
+ )
+ updated
+ } else {
+ Log.w(
+ TAG,
+ "[repository] updateCurrentCall: Call is not Registered, skipping update"
+ )
+ call
+ }
+ }
+ }
+
+ private suspend fun CallControlScope.doSwitchEndpoint(action: CallAction.SwitchAudioEndpoint) {
+ Log.d(TAG, "[repository] doSwitchEndpoint: Switching to endpoint: ${action.endpointId}")
+ // TODO once availableCallEndpoints is a state flow we can just get the value
+ val endpoints = (_currentCall.value as Call.Registered).availableCallEndpoints
+
+ // Switch to the given endpoint or fallback to the best possible one.
+ val newEndpoint = endpoints.firstOrNull { it.identifier == action.endpointId }
+
+ if (newEndpoint != null) {
+ Log.d(
+ TAG,
+ "[repository] doSwitchEndpoint: Found endpoint: ${newEndpoint.name}, requesting change"
+ )
+ requestEndpointChange(newEndpoint).also {
+ Log.d(TAG, "[repository] doSwitchEndpoint: Endpoint change result: $it")
+ }
+ } else {
+ Log.w(TAG, "[repository] doSwitchEndpoint: Endpoint not found in available endpoints")
+ }
+ }
+
+ private suspend fun CallControlScope.doDisconnect(action: CallAction.Disconnect) {
+ isSelfDisconnected = true
+ Log.d(TAG, "[repository] doDisconnect: Disconnecting call with cause: ${action.cause}")
+ disconnect(action.cause)
+ Log.d(TAG, "[repository] doDisconnect: Disconnect called, triggering onIsCallDisconnected")
+ onIsCallDisconnected(action.cause)
+ }
+
+ private suspend fun CallControlScope.doAnswer(isAudioCall: Boolean) {
+ isSelfAnswered = true
+ val callType =
+ if (isAudioCall) CallAttributesCompat.CALL_TYPE_AUDIO_CALL
+ else CallAttributesCompat.CALL_TYPE_VIDEO_CALL
+
+ when (val result = answer(callType)) {
+ is CallControlResult.Success -> {
+ onIsCallAnswered(callType)
+ }
+ is CallControlResult.Error -> {
+ Log.e(
+ TAG,
+ "[repository] doAnswer: Answer failed with error code: ${result.errorCode}"
+ )
+ isSelfAnswered = false
+ updateCurrentCall {
+ Call.Unregistered(
+ id = id,
+ callAttributes = callAttributes,
+ disconnectCause = DisconnectCause(DisconnectCause.BUSY),
+ )
+ }
+ }
+ }
+ }
+
+ /**
+ * Can the call be successfully answered?? TIP: We would check the connection/call state to see
+ * if we can answer a call Example you may need to wait for another call to hold.
+ */
+ val onIsCallAnswered: suspend (type: Int) -> Unit = {
+ Log.d(TAG, "[repository] onIsCallAnswered: Call answered, type: $it, isSelfAnswered: $isSelfAnswered")
+ updateCurrentCall { copy(isActive = true, isOnHold = false) }
+
+ val call = _currentCall.value
+ val source = if (isSelfAnswered) CallRepository.EventSource.APP else CallRepository.EventSource.SYS
+ if (call is Call.Registered) {
+ listener?.onIsCallAnswered(call.id, source)
+ }
+ isSelfAnswered = false
+ Log.d(TAG, "[repository] onIsCallAnswered: Call state updated to active")
+ }
+
+ /** Can the call perform a disconnect */
+ val onIsCallDisconnected: suspend (cause: DisconnectCause) -> Unit = {
+ Log.d(
+ TAG,
+ "[repository] onIsCallDisconnected: Call disconnected, cause: ${it.reason}, description: ${it.description}"
+ )
+ val source = if (isSelfDisconnected) CallRepository.EventSource.APP else CallRepository.EventSource.SYS
+ var callId: String? = null
+ if (_currentCall.value is Call.Registered) {
+ callId = (_currentCall.value as Call.Registered).id
+ }
+
+ updateCurrentCall { Call.Unregistered(id, callAttributes, it) }
+ listener?.onIsCallDisconnected(callId, it, source)
+ isSelfDisconnected = false
+ Log.d(TAG, "[repository] onIsCallDisconnected: Call state updated to Unregistered")
+ }
+
+ /**
+ * Check is see if we can make the call active. Other calls and state might stop us from
+ * activating the call
+ */
+ val onIsCallActive: suspend () -> Unit = {
+ Log.d(TAG, "[repository] onIsCallActive: Call became active")
+ updateCurrentCall {
+ copy(
+ errorCode = null,
+ isActive = true,
+ isOnHold = false,
+ )
+ }
+
+ val call = _currentCall.value
+ if (call is Call.Registered) {
+ listener?.onIsCallActive(call.id)
+ }
+ Log.d(TAG, "[repository] onIsCallActive: Call state updated")
+ }
+
+ /** Check to see if we can make the call inactivate */
+ val onIsCallInactive: suspend () -> Unit = {
+ Log.d(TAG, "[repository] onIsCallInactive: Call became inactive (on hold)")
+ updateCurrentCall { copy(errorCode = null, isOnHold = true) }
+
+ val call = _currentCall.value
+ if (call is Call.Registered) {
+ listener?.onIsCallInactive(call.id)
+ }
+ Log.d(TAG, "[repository] onIsCallInactive: Call state updated to on hold")
+ }
+
+ private fun createCallAttributes(
+ displayName: String,
+ address: Uri,
+ isIncoming: Boolean,
+ isVideo: Boolean
+ ): CallAttributesCompat {
+ Log.d(
+ TAG,
+ "createCallAttributes: Creating CallAttributes - Direction: ${if (isIncoming) "Incoming" else "Outgoing"}, Type: ${if (isVideo) "Video" else "Audio"}"
+ )
+ return CallAttributesCompat(
+ displayName = displayName,
+ address = address,
+ direction =
+ if (isIncoming) {
+ CallAttributesCompat.DIRECTION_INCOMING
+ } else {
+ CallAttributesCompat.DIRECTION_OUTGOING
+ },
+ callType =
+ if (isVideo) {
+ CallAttributesCompat.CALL_TYPE_VIDEO_CALL
+ } else {
+ CallAttributesCompat.CALL_TYPE_AUDIO_CALL
+ },
+ callCapabilities =
+ CallAttributesCompat.SUPPORTS_SET_INACTIVE or
+ CallAttributesCompat.SUPPORTS_STREAM or
+ CallAttributesCompat.SUPPORTS_TRANSFER,
+ )
+ }
+}
diff --git a/packages/react-native-callingx/android/src/main/res/drawable/ic_phone_paused_24.xml b/packages/react-native-callingx/android/src/main/res/drawable/ic_phone_paused_24.xml
new file mode 100644
index 0000000000..7773fecd3e
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/res/drawable/ic_phone_paused_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/packages/react-native-callingx/android/src/main/res/drawable/ic_round_call_24.xml b/packages/react-native-callingx/android/src/main/res/drawable/ic_round_call_24.xml
new file mode 100644
index 0000000000..3daf420f62
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/res/drawable/ic_round_call_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/packages/react-native-callingx/android/src/main/res/drawable/ic_user.xml b/packages/react-native-callingx/android/src/main/res/drawable/ic_user.xml
new file mode 100644
index 0000000000..eaaa2941f8
--- /dev/null
+++ b/packages/react-native-callingx/android/src/main/res/drawable/ic_user.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/packages/react-native-callingx/babel.config.js b/packages/react-native-callingx/babel.config.js
new file mode 100644
index 0000000000..0c05fd6963
--- /dev/null
+++ b/packages/react-native-callingx/babel.config.js
@@ -0,0 +1,12 @@
+module.exports = {
+ overrides: [
+ {
+ exclude: /\/node_modules\//,
+ presets: ['module:react-native-builder-bob/babel-preset'],
+ },
+ {
+ include: /\/node_modules\//,
+ presets: ['module:@react-native/babel-preset'],
+ },
+ ],
+};
diff --git a/packages/react-native-callingx/eslint.config.mjs b/packages/react-native-callingx/eslint.config.mjs
new file mode 100644
index 0000000000..16b00bbcd9
--- /dev/null
+++ b/packages/react-native-callingx/eslint.config.mjs
@@ -0,0 +1,29 @@
+import { fixupConfigRules } from '@eslint/compat';
+import { FlatCompat } from '@eslint/eslintrc';
+import js from '@eslint/js';
+import prettier from 'eslint-plugin-prettier';
+import { defineConfig } from 'eslint/config';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all,
+});
+
+export default defineConfig([
+ {
+ extends: fixupConfigRules(compat.extends('@react-native', 'prettier')),
+ plugins: { prettier },
+ rules: {
+ 'react/react-in-jsx-scope': 'off',
+ 'prettier/prettier': 'error',
+ },
+ },
+ {
+ ignores: ['node_modules/', 'lib/'],
+ },
+]);
diff --git a/packages/react-native-callingx/example/.bundle/config b/packages/react-native-callingx/example/.bundle/config
new file mode 100644
index 0000000000..848943bb52
--- /dev/null
+++ b/packages/react-native-callingx/example/.bundle/config
@@ -0,0 +1,2 @@
+BUNDLE_PATH: "vendor/bundle"
+BUNDLE_FORCE_RUBY_PLATFORM: 1
diff --git a/packages/react-native-callingx/example/.watchmanconfig b/packages/react-native-callingx/example/.watchmanconfig
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/packages/react-native-callingx/example/.watchmanconfig
@@ -0,0 +1 @@
+{}
diff --git a/packages/react-native-callingx/example/Gemfile b/packages/react-native-callingx/example/Gemfile
new file mode 100644
index 0000000000..6a4c5f1718
--- /dev/null
+++ b/packages/react-native-callingx/example/Gemfile
@@ -0,0 +1,16 @@
+source 'https://rubygems.org'
+
+# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
+ruby ">= 2.6.10"
+
+# Exclude problematic versions of cocoapods and activesupport that causes build failures.
+gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
+gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
+gem 'xcodeproj', '< 1.26.0'
+gem 'concurrent-ruby', '< 1.3.4'
+
+# Ruby 3.4.0 has removed some libraries from the standard library.
+gem 'bigdecimal'
+gem 'logger'
+gem 'benchmark'
+gem 'mutex_m'
diff --git a/packages/react-native-callingx/example/README.md b/packages/react-native-callingx/example/README.md
new file mode 100644
index 0000000000..3e2c3f8505
--- /dev/null
+++ b/packages/react-native-callingx/example/README.md
@@ -0,0 +1,97 @@
+This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
+
+# Getting Started
+
+> **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.
+
+## Step 1: Start Metro
+
+First, you will need to run **Metro**, the JavaScript build tool for React Native.
+
+To start the Metro dev server, run the following command from the root of your React Native project:
+
+```sh
+# Using npm
+npm start
+
+# OR using Yarn
+yarn start
+```
+
+## Step 2: Build and run your app
+
+With Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:
+
+### Android
+
+```sh
+# Using npm
+npm run android
+
+# OR using Yarn
+yarn android
+```
+
+### iOS
+
+For iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).
+
+The first time you create a new project, run the Ruby bundler to install CocoaPods itself:
+
+```sh
+bundle install
+```
+
+Then, and every time you update your native dependencies, run:
+
+```sh
+bundle exec pod install
+```
+
+For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).
+
+```sh
+# Using npm
+npm run ios
+
+# OR using Yarn
+yarn ios
+```
+
+If everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.
+
+This is one way to run your app — you can also build it directly from Android Studio or Xcode.
+
+## Step 3: Modify your app
+
+Now that you have successfully run the app, let's make changes!
+
+Open `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).
+
+When you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:
+
+- **Android**: Press the R key twice or select **"Reload"** from the **Dev Menu**, accessed via Ctrl + M (Windows/Linux) or Cmd ⌘ + M (macOS).
+- **iOS**: Press R in iOS Simulator.
+
+## Congratulations! :tada:
+
+You've successfully run and modified your React Native App. :partying_face:
+
+### Now what?
+
+- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
+- If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).
+
+# Troubleshooting
+
+If you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
+
+# Learn More
+
+To learn more about React Native, take a look at the following resources:
+
+- [React Native Website](https://reactnative.dev) - learn more about React Native.
+- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
+- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
+- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
+- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
diff --git a/packages/react-native-callingx/example/android/app/build.gradle b/packages/react-native-callingx/example/android/app/build.gradle
new file mode 100644
index 0000000000..48d74066cf
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/build.gradle
@@ -0,0 +1,119 @@
+apply plugin: "com.android.application"
+apply plugin: "org.jetbrains.kotlin.android"
+apply plugin: "com.facebook.react"
+
+/**
+ * This is the configuration block to customize your React Native Android app.
+ * By default you don't need to apply any configuration, just uncomment the lines you need.
+ */
+react {
+ /* Folders */
+ // The root of your project, i.e. where "package.json" lives. Default is '../..'
+ // root = file("../../")
+ // The folder where the react-native NPM package is. Default is ../../node_modules/react-native
+ // reactNativeDir = file("../../node_modules/react-native")
+ // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
+ // codegenDir = file("../../node_modules/@react-native/codegen")
+ // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
+ // cliFile = file("../../node_modules/react-native/cli.js")
+
+ /* Variants */
+ // The list of variants to that are debuggable. For those we're going to
+ // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
+ // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
+ // debuggableVariants = ["liteDebug", "prodDebug"]
+
+ /* Bundling */
+ // A list containing the node command and its flags. Default is just 'node'.
+ // nodeExecutableAndArgs = ["node"]
+ //
+ // The command to run when bundling. By default is 'bundle'
+ // bundleCommand = "ram-bundle"
+ //
+ // The path to the CLI configuration file. Default is empty.
+ // bundleConfig = file(../rn-cli.config.js)
+ //
+ // The name of the generated asset file containing your JS bundle
+ // bundleAssetName = "MyApplication.android.bundle"
+ //
+ // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
+ // entryFile = file("../js/MyApplication.android.js")
+ //
+ // A list of extra flags to pass to the 'bundle' commands.
+ // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
+ // extraPackagerArgs = []
+
+ /* Hermes Commands */
+ // The hermes compiler command to run. By default it is 'hermesc'
+ // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
+ //
+ // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
+ // hermesFlags = ["-O", "-output-source-map"]
+
+ /* Autolinking */
+ autolinkLibrariesWithApp()
+}
+
+/**
+ * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
+ */
+def enableProguardInReleaseBuilds = false
+
+/**
+ * The preferred build flavor of JavaScriptCore (JSC)
+ *
+ * For example, to use the international variant, you can use:
+ * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+`
+ *
+ * The international variant includes ICU i18n library and necessary data
+ * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
+ * give correct results when using with locales other than en-US. Note that
+ * this variant is about 6MiB larger per architecture than default.
+ */
+def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
+
+android {
+ ndkVersion rootProject.ext.ndkVersion
+ buildToolsVersion rootProject.ext.buildToolsVersion
+ compileSdk rootProject.ext.compileSdkVersion
+
+ namespace "callingx.example"
+ defaultConfig {
+ applicationId "callingx.example"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ versionCode 1
+ versionName "1.0"
+ }
+ signingConfigs {
+ debug {
+ storeFile file('debug.keystore')
+ storePassword 'android'
+ keyAlias 'androiddebugkey'
+ keyPassword 'android'
+ }
+ }
+ buildTypes {
+ debug {
+ signingConfig signingConfigs.debug
+ }
+ release {
+ // Caution! In production, you need to generate your own keystore file.
+ // see https://reactnative.dev/docs/signed-apk-android.
+ signingConfig signingConfigs.debug
+ minifyEnabled enableProguardInReleaseBuilds
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ }
+ }
+}
+
+dependencies {
+ // The version of react-native is set by the React Native Gradle Plugin
+ implementation("com.facebook.react:react-android")
+
+ if (hermesEnabled.toBoolean()) {
+ implementation("com.facebook.react:hermes-android")
+ } else {
+ implementation jscFlavor
+ }
+}
diff --git a/packages/react-native-callingx/example/android/app/debug.keystore b/packages/react-native-callingx/example/android/app/debug.keystore
new file mode 100644
index 0000000000..364e105ed3
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/debug.keystore differ
diff --git a/packages/react-native-callingx/example/android/app/proguard-rules.pro b/packages/react-native-callingx/example/android/app/proguard-rules.pro
new file mode 100644
index 0000000000..11b025724a
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/proguard-rules.pro
@@ -0,0 +1,10 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
diff --git a/packages/react-native-callingx/example/android/app/src/debug/AndroidManifest.xml b/packages/react-native-callingx/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000000..eb98c01afd
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/packages/react-native-callingx/example/android/app/src/main/AndroidManifest.xml b/packages/react-native-callingx/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e1892528b8
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-callingx/example/android/app/src/main/java/callingx/example/MainActivity.kt b/packages/react-native-callingx/example/android/app/src/main/java/callingx/example/MainActivity.kt
new file mode 100644
index 0000000000..bfa630a644
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/main/java/callingx/example/MainActivity.kt
@@ -0,0 +1,22 @@
+package callingx.example
+
+import com.facebook.react.ReactActivity
+import com.facebook.react.ReactActivityDelegate
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
+import com.facebook.react.defaults.DefaultReactActivityDelegate
+
+class MainActivity : ReactActivity() {
+
+ /**
+ * Returns the name of the main component registered from JavaScript. This is used to schedule
+ * rendering of the component.
+ */
+ override fun getMainComponentName(): String = "CallingxExample"
+
+ /**
+ * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
+ * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
+ */
+ override fun createReactActivityDelegate(): ReactActivityDelegate =
+ DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
+}
diff --git a/packages/react-native-callingx/example/android/app/src/main/java/callingx/example/MainApplication.kt b/packages/react-native-callingx/example/android/app/src/main/java/callingx/example/MainApplication.kt
new file mode 100644
index 0000000000..c2529473dc
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/main/java/callingx/example/MainApplication.kt
@@ -0,0 +1,38 @@
+package callingx.example
+
+import android.app.Application
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactHost
+import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
+import com.facebook.react.defaults.DefaultReactNativeHost
+
+class MainApplication : Application(), ReactApplication {
+
+ override val reactNativeHost: ReactNativeHost =
+ object : DefaultReactNativeHost(this) {
+ override fun getPackages(): List =
+ PackageList(this).packages.apply {
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // add(MyReactNativePackage())
+ }
+
+ override fun getJSMainModuleName(): String = "index"
+
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
+
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
+ }
+
+ override val reactHost: ReactHost
+ get() = getDefaultReactHost(applicationContext, reactNativeHost)
+
+ override fun onCreate() {
+ super.onCreate()
+ loadReactNative(this)
+ }
+}
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/drawable/rn_edit_text_material.xml b/packages/react-native-callingx/example/android/app/src/main/res/drawable/rn_edit_text_material.xml
new file mode 100644
index 0000000000..5c25e728ea
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/main/res/drawable/rn_edit_text_material.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..a2f5908281
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..1b52399808
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..ff10afd6e1
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..115a4c768a
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..dcd3cd8083
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..459ca609d3
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..8ca12fe024
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..8e19b410a1
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..b824ebdd48
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..4c19a13c23
Binary files /dev/null and b/packages/react-native-callingx/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/values/strings.xml b/packages/react-native-callingx/example/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..79a2a58ede
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ CallingxExample
+
diff --git a/packages/react-native-callingx/example/android/app/src/main/res/values/styles.xml b/packages/react-native-callingx/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..7ba83a2ad5
--- /dev/null
+++ b/packages/react-native-callingx/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/packages/react-native-callingx/example/android/build.gradle b/packages/react-native-callingx/example/android/build.gradle
new file mode 100644
index 0000000000..dad99b022a
--- /dev/null
+++ b/packages/react-native-callingx/example/android/build.gradle
@@ -0,0 +1,21 @@
+buildscript {
+ ext {
+ buildToolsVersion = "36.0.0"
+ minSdkVersion = 24
+ compileSdkVersion = 36
+ targetSdkVersion = 36
+ ndkVersion = "27.1.12297006"
+ kotlinVersion = "2.1.20"
+ }
+ repositories {
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath("com.android.tools.build:gradle")
+ classpath("com.facebook.react:react-native-gradle-plugin")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
+ }
+}
+
+apply plugin: "com.facebook.react.rootproject"
diff --git a/packages/react-native-callingx/example/android/gradle.properties b/packages/react-native-callingx/example/android/gradle.properties
new file mode 100644
index 0000000000..9afe61598f
--- /dev/null
+++ b/packages/react-native-callingx/example/android/gradle.properties
@@ -0,0 +1,44 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
+org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+
+# Use this property to specify which architecture you want to build.
+# You can also override it from the CLI using
+# ./gradlew -PreactNativeArchitectures=x86_64
+reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
+
+# Use this property to enable support to the new architecture.
+# This will allow you to use TurboModules and the Fabric render in
+# your application. You should enable this flag either if you want
+# to write custom TurboModules/Fabric components OR use libraries that
+# are providing them.
+newArchEnabled=true
+
+# Use this property to enable or disable the Hermes JS engine.
+# If set to false, you will be using JSC instead.
+hermesEnabled=true
+
+# Use this property to enable edge-to-edge display support.
+# This allows your app to draw behind system bars for an immersive UI.
+# Note: Only works with ReactActivity and should not be used with custom Activity.
+edgeToEdgeEnabled=false
diff --git a/packages/react-native-callingx/example/android/gradle/wrapper/gradle-wrapper.jar b/packages/react-native-callingx/example/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..1b33c55baa
Binary files /dev/null and b/packages/react-native-callingx/example/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/packages/react-native-callingx/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-callingx/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..d4081da476
--- /dev/null
+++ b/packages/react-native-callingx/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/packages/react-native-callingx/example/android/gradlew b/packages/react-native-callingx/example/android/gradlew
new file mode 100755
index 0000000000..23d15a9367
--- /dev/null
+++ b/packages/react-native-callingx/example/android/gradlew
@@ -0,0 +1,251 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH="\\\"\\\""
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/packages/react-native-callingx/example/android/gradlew.bat b/packages/react-native-callingx/example/android/gradlew.bat
new file mode 100644
index 0000000000..dd2b8eedbd
--- /dev/null
+++ b/packages/react-native-callingx/example/android/gradlew.bat
@@ -0,0 +1,99 @@
+@REM Copyright (c) Meta Platforms, Inc. and affiliates.
+@REM
+@REM This source code is licensed under the MIT license found in the
+@REM LICENSE file in the root directory of this source tree.
+
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/packages/react-native-callingx/example/android/settings.gradle b/packages/react-native-callingx/example/android/settings.gradle
new file mode 100644
index 0000000000..ae60f4c242
--- /dev/null
+++ b/packages/react-native-callingx/example/android/settings.gradle
@@ -0,0 +1,6 @@
+pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
+plugins { id("com.facebook.react.settings") }
+extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
+rootProject.name = 'callingx.example'
+include ':app'
+includeBuild('../node_modules/@react-native/gradle-plugin')
diff --git a/packages/react-native-callingx/example/app.json b/packages/react-native-callingx/example/app.json
new file mode 100644
index 0000000000..cbb977effe
--- /dev/null
+++ b/packages/react-native-callingx/example/app.json
@@ -0,0 +1,4 @@
+{
+ "name": "CallingxExample",
+ "displayName": "CallingxExample"
+}
diff --git a/packages/react-native-callingx/example/babel.config.js b/packages/react-native-callingx/example/babel.config.js
new file mode 100644
index 0000000000..486a09304d
--- /dev/null
+++ b/packages/react-native-callingx/example/babel.config.js
@@ -0,0 +1,12 @@
+const path = require('path');
+const { getConfig } = require('react-native-builder-bob/babel-config');
+const pkg = require('../package.json');
+
+const root = path.resolve(__dirname, '..');
+
+module.exports = getConfig(
+ {
+ presets: ['module:@react-native/babel-preset'],
+ },
+ { root, pkg }
+);
diff --git a/packages/react-native-callingx/example/index.js b/packages/react-native-callingx/example/index.js
new file mode 100644
index 0000000000..117ddcae40
--- /dev/null
+++ b/packages/react-native-callingx/example/index.js
@@ -0,0 +1,5 @@
+import { AppRegistry } from 'react-native';
+import App from './src/App';
+import { name as appName } from './app.json';
+
+AppRegistry.registerComponent(appName, () => App);
diff --git a/packages/react-native-callingx/example/ios/.xcode.env b/packages/react-native-callingx/example/ios/.xcode.env
new file mode 100644
index 0000000000..3d5782c715
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/.xcode.env
@@ -0,0 +1,11 @@
+# This `.xcode.env` file is versioned and is used to source the environment
+# used when running script phases inside Xcode.
+# To customize your local environment, you can create an `.xcode.env.local`
+# file that is not versioned.
+
+# NODE_BINARY variable contains the PATH to the node executable.
+#
+# Customize the NODE_BINARY variable here.
+# For example, to use nvm with brew, add the following line
+# . "$(brew --prefix nvm)/nvm.sh" --no-use
+export NODE_BINARY=$(command -v node)
diff --git a/packages/react-native-callingx/example/ios/CallingxExample.xcodeproj/project.pbxproj b/packages/react-native-callingx/example/ios/CallingxExample.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..1246c566ee
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample.xcodeproj/project.pbxproj
@@ -0,0 +1,471 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 0C80B921A6F3F58F76C31292 /* libPods-CallingxExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-CallingxExample.a */; };
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+ 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
+ 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 13B07F961A680F5B00A75B9A /* CallingxExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CallingxExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = CallingxExample/Images.xcassets; sourceTree = ""; };
+ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = CallingxExample/Info.plist; sourceTree = ""; };
+ 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = CallingxExample/PrivacyInfo.xcprivacy; sourceTree = ""; };
+ 3B4392A12AC88292D35C810B /* Pods-CallingxExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallingxExample.debug.xcconfig"; path = "Target Support Files/Pods-CallingxExample/Pods-CallingxExample.debug.xcconfig"; sourceTree = ""; };
+ 5709B34CF0A7D63546082F79 /* Pods-CallingxExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallingxExample.release.xcconfig"; path = "Target Support Files/Pods-CallingxExample/Pods-CallingxExample.release.xcconfig"; sourceTree = ""; };
+ 5DCACB8F33CDC322A6C60F78 /* libPods-CallingxExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CallingxExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = CallingxExample/AppDelegate.swift; sourceTree = ""; };
+ 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = CallingxExample/LaunchScreen.storyboard; sourceTree = ""; };
+ ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0C80B921A6F3F58F76C31292 /* libPods-CallingxExample.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 13B07FAE1A68108700A75B9A /* CallingxExample */ = {
+ isa = PBXGroup;
+ children = (
+ 13B07FB51A68108700A75B9A /* Images.xcassets */,
+ 761780EC2CA45674006654EE /* AppDelegate.swift */,
+ 13B07FB61A68108700A75B9A /* Info.plist */,
+ 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
+ 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
+ );
+ name = CallingxExample;
+ sourceTree = "";
+ };
+ 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
+ 5DCACB8F33CDC322A6C60F78 /* libPods-CallingxExample.a */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Libraries;
+ sourceTree = "";
+ };
+ 83CBB9F61A601CBA00E9B192 = {
+ isa = PBXGroup;
+ children = (
+ 13B07FAE1A68108700A75B9A /* CallingxExample */,
+ 832341AE1AAA6A7D00B99B32 /* Libraries */,
+ 83CBBA001A601CBA00E9B192 /* Products */,
+ 2D16E6871FA4F8E400B85C8A /* Frameworks */,
+ BBD78D7AC51CEA395F1C20DB /* Pods */,
+ );
+ indentWidth = 2;
+ sourceTree = "";
+ tabWidth = 2;
+ usesTabs = 0;
+ };
+ 83CBBA001A601CBA00E9B192 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 13B07F961A680F5B00A75B9A /* CallingxExample.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ BBD78D7AC51CEA395F1C20DB /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 3B4392A12AC88292D35C810B /* Pods-CallingxExample.debug.xcconfig */,
+ 5709B34CF0A7D63546082F79 /* Pods-CallingxExample.release.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 13B07F861A680F5B00A75B9A /* CallingxExample */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "CallingxExample" */;
+ buildPhases = (
+ C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
+ 13B07F871A680F5B00A75B9A /* Sources */,
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */,
+ 13B07F8E1A680F5B00A75B9A /* Resources */,
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
+ 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
+ E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = CallingxExample;
+ productName = CallingxExample;
+ productReference = 13B07F961A680F5B00A75B9A /* CallingxExample.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 83CBB9F71A601CBA00E9B192 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1210;
+ TargetAttributes = {
+ 13B07F861A680F5B00A75B9A = {
+ LastSwiftMigration = 1120;
+ };
+ };
+ };
+ buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "CallingxExample" */;
+ compatibilityVersion = "Xcode 12.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 83CBB9F61A601CBA00E9B192;
+ productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 13B07F861A680F5B00A75B9A /* CallingxExample */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 13B07F8E1A680F5B00A75B9A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/.xcode.env.local",
+ "$(SRCROOT)/.xcode.env",
+ );
+ name = "Bundle React Native code and images";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
+ };
+ 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-CallingxExample/Pods-CallingxExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-CallingxExample/Pods-CallingxExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CallingxExample/Pods-CallingxExample-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-CallingxExample-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-CallingxExample/Pods-CallingxExample-resources-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-CallingxExample/Pods-CallingxExample-resources-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CallingxExample/Pods-CallingxExample-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 13B07F871A680F5B00A75B9A /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 13B07F941A680F5B00A75B9A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-CallingxExample.debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = CallingxExample/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "callingx.example";
+ PRODUCT_NAME = CallingxExample;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 13B07F951A680F5B00A75B9A /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-CallingxExample.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ INFOPLIST_FILE = CallingxExample/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-ObjC",
+ "-lc++",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "callingx.example";
+ PRODUCT_NAME = CallingxExample;
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+ 83CBBA201A601CBA00E9B192 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++20";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+ LD_RUNPATH_SEARCH_PATHS = (
+ /usr/lib/swift,
+ "$(inherited)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SDKROOT)/usr/lib/swift\"",
+ "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
+ "\"$(inherited)\"",
+ );
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_CPLUSPLUSFLAGS = (
+ "$(OTHER_CFLAGS)",
+ "-DFOLLY_NO_CONFIG",
+ "-DFOLLY_MOBILE=1",
+ "-DFOLLY_USE_LIBCPP=1",
+ "-DFOLLY_CFG_NO_COROUTINES=1",
+ "-DFOLLY_HAVE_CLOCK_GETTIME=1",
+ );
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 83CBBA211A601CBA00E9B192 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++20";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+ LD_RUNPATH_SEARCH_PATHS = (
+ /usr/lib/swift,
+ "$(inherited)",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SDKROOT)/usr/lib/swift\"",
+ "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
+ "\"$(inherited)\"",
+ );
+ MTL_ENABLE_DEBUG_INFO = NO;
+ OTHER_CPLUSPLUSFLAGS = (
+ "$(OTHER_CFLAGS)",
+ "-DFOLLY_NO_CONFIG",
+ "-DFOLLY_MOBILE=1",
+ "-DFOLLY_USE_LIBCPP=1",
+ "-DFOLLY_CFG_NO_COROUTINES=1",
+ "-DFOLLY_HAVE_CLOCK_GETTIME=1",
+ );
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "CallingxExample" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 13B07F941A680F5B00A75B9A /* Debug */,
+ 13B07F951A680F5B00A75B9A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "CallingxExample" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 83CBBA201A601CBA00E9B192 /* Debug */,
+ 83CBBA211A601CBA00E9B192 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
+}
diff --git a/packages/react-native-callingx/example/ios/CallingxExample.xcodeproj/xcshareddata/xcschemes/CallingxExample.xcscheme b/packages/react-native-callingx/example/ios/CallingxExample.xcodeproj/xcshareddata/xcschemes/CallingxExample.xcscheme
new file mode 100644
index 0000000000..c2dd5830ea
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample.xcodeproj/xcshareddata/xcschemes/CallingxExample.xcscheme
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-callingx/example/ios/CallingxExample/AppDelegate.swift b/packages/react-native-callingx/example/ios/CallingxExample/AppDelegate.swift
new file mode 100644
index 0000000000..bd6ee494c1
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample/AppDelegate.swift
@@ -0,0 +1,48 @@
+import UIKit
+import React
+import React_RCTAppDelegate
+import ReactAppDependencyProvider
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ var window: UIWindow?
+
+ var reactNativeDelegate: ReactNativeDelegate?
+ var reactNativeFactory: RCTReactNativeFactory?
+
+ func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
+ ) -> Bool {
+ let delegate = ReactNativeDelegate()
+ let factory = RCTReactNativeFactory(delegate: delegate)
+ delegate.dependencyProvider = RCTAppDependencyProvider()
+
+ reactNativeDelegate = delegate
+ reactNativeFactory = factory
+
+ window = UIWindow(frame: UIScreen.main.bounds)
+
+ factory.startReactNative(
+ withModuleName: "CallingxExample",
+ in: window,
+ launchOptions: launchOptions
+ )
+
+ return true
+ }
+}
+
+class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
+ override func sourceURL(for bridge: RCTBridge) -> URL? {
+ self.bundleURL()
+ }
+
+ override func bundleURL() -> URL? {
+#if DEBUG
+ RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
+#else
+ Bundle.main.url(forResource: "main", withExtension: "jsbundle")
+#endif
+ }
+}
diff --git a/packages/react-native-callingx/example/ios/CallingxExample/Images.xcassets/AppIcon.appiconset/Contents.json b/packages/react-native-callingx/example/ios/CallingxExample/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..ddd7fca89e
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,53 @@
+{
+ "images": [
+ {
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "20x20"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "20x20"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "29x29"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "29x29"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "40x40"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "40x40"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "60x60"
+ },
+ {
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "60x60"
+ },
+ {
+ "idiom": "ios-marketing",
+ "scale": "1x",
+ "size": "1024x1024"
+ }
+ ],
+ "info": {
+ "author": "xcode",
+ "version": 1
+ }
+}
diff --git a/packages/react-native-callingx/example/ios/CallingxExample/Images.xcassets/Contents.json b/packages/react-native-callingx/example/ios/CallingxExample/Images.xcassets/Contents.json
new file mode 100644
index 0000000000..97a8662ebd
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info": {
+ "version": 1,
+ "author": "xcode"
+ }
+}
diff --git a/packages/react-native-callingx/example/ios/CallingxExample/Info.plist b/packages/react-native-callingx/example/ios/CallingxExample/Info.plist
new file mode 100644
index 0000000000..f23ea7e4eb
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample/Info.plist
@@ -0,0 +1,52 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ CallingxExample
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(MARKETING_VERSION)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(CURRENT_PROJECT_VERSION)
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+
+ NSAllowsArbitraryLoads
+
+ NSAllowsLocalNetworking
+
+
+ NSLocationWhenInUseUsageDescription
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/packages/react-native-callingx/example/ios/CallingxExample/LaunchScreen.storyboard b/packages/react-native-callingx/example/ios/CallingxExample/LaunchScreen.storyboard
new file mode 100644
index 0000000000..80913b79e6
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample/LaunchScreen.storyboard
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/react-native-callingx/example/ios/CallingxExample/PrivacyInfo.xcprivacy b/packages/react-native-callingx/example/ios/CallingxExample/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..41b8317f06
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/CallingxExample/PrivacyInfo.xcprivacy
@@ -0,0 +1,37 @@
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryFileTimestamp
+ NSPrivacyAccessedAPITypeReasons
+
+ C617.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryUserDefaults
+ NSPrivacyAccessedAPITypeReasons
+
+ CA92.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategorySystemBootTime
+ NSPrivacyAccessedAPITypeReasons
+
+ 35F9.1
+
+
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyTracking
+
+
+
diff --git a/packages/react-native-callingx/example/ios/Podfile b/packages/react-native-callingx/example/ios/Podfile
new file mode 100644
index 0000000000..e1ac14a934
--- /dev/null
+++ b/packages/react-native-callingx/example/ios/Podfile
@@ -0,0 +1,37 @@
+ENV['RCT_NEW_ARCH_ENABLED'] = '1'
+
+# Resolve react_native_pods.rb with node to allow for hoisting
+require Pod::Executable.execute_command('node', ['-p',
+ 'require.resolve(
+ "react-native/scripts/react_native_pods.rb",
+ {paths: [process.argv[1]]},
+ )', __dir__]).strip
+
+platform :ios, min_ios_version_supported
+prepare_react_native_project!
+
+linkage = ENV['USE_FRAMEWORKS']
+if linkage != nil
+ Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
+ use_frameworks! :linkage => linkage.to_sym
+end
+
+target 'CallingxExample' do
+ config = use_native_modules!
+
+ use_react_native!(
+ :path => config[:reactNativePath],
+ # An absolute path to your application root.
+ :app_path => "#{Pod::Config.instance.installation_root}/.."
+ )
+
+ post_install do |installer|
+ # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
+ react_native_post_install(
+ installer,
+ config[:reactNativePath],
+ :mac_catalyst_enabled => false,
+ # :ccache_enabled => true
+ )
+ end
+end
diff --git a/packages/react-native-callingx/example/jest.config.js b/packages/react-native-callingx/example/jest.config.js
new file mode 100644
index 0000000000..8eb675e9bc
--- /dev/null
+++ b/packages/react-native-callingx/example/jest.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ preset: 'react-native',
+};
diff --git a/packages/react-native-callingx/example/metro.config.js b/packages/react-native-callingx/example/metro.config.js
new file mode 100644
index 0000000000..2da198e82c
--- /dev/null
+++ b/packages/react-native-callingx/example/metro.config.js
@@ -0,0 +1,16 @@
+const path = require('path');
+const { getDefaultConfig } = require('@react-native/metro-config');
+const { withMetroConfig } = require('react-native-monorepo-config');
+
+const root = path.resolve(__dirname, '..');
+
+/**
+ * Metro configuration
+ * https://facebook.github.io/metro/docs/configuration
+ *
+ * @type {import('metro-config').MetroConfig}
+ */
+module.exports = withMetroConfig(getDefaultConfig(__dirname), {
+ root,
+ dirname: __dirname,
+});
diff --git a/packages/react-native-callingx/example/package-lock.json b/packages/react-native-callingx/example/package-lock.json
new file mode 100644
index 0000000000..a43dc4e62a
--- /dev/null
+++ b/packages/react-native-callingx/example/package-lock.json
@@ -0,0 +1,7016 @@
+{
+ "name": "react-native-callingx-example",
+ "version": "0.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "react-native-callingx-example",
+ "version": "0.0.1",
+ "dependencies": {
+ "react": "19.1.0",
+ "react-native": "0.81.1",
+ "react-native-callingx": "file:.."
+ },
+ "devDependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/preset-env": "^7.25.3",
+ "@babel/runtime": "^7.25.0",
+ "@react-native-community/cli": "20.0.0",
+ "@react-native-community/cli-platform-android": "20.0.0",
+ "@react-native-community/cli-platform-ios": "20.0.0",
+ "@react-native/babel-preset": "0.81.1",
+ "@react-native/metro-config": "0.81.1",
+ "@react-native/typescript-config": "0.81.1",
+ "@types/react": "^19.1.0",
+ "react-native-builder-bob": "^0.40.15",
+ "react-native-monorepo-config": "^0.1.9"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "..": {
+ "version": "0.1.0",
+ "license": "MIT",
+ "devDependencies": {
+ "@commitlint/config-conventional": "^19.8.1",
+ "@eslint/compat": "^1.3.2",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "^9.35.0",
+ "@react-native-community/cli": "20.0.1",
+ "@react-native/babel-preset": "0.81.1",
+ "@react-native/eslint-config": "^0.81.1",
+ "@release-it/conventional-changelog": "^10.0.1",
+ "@types/jest": "^29.5.14",
+ "@types/react": "^19.1.0",
+ "commitlint": "^19.8.1",
+ "del-cli": "^6.0.0",
+ "eslint": "^9.35.0",
+ "eslint-config-prettier": "^10.1.8",
+ "eslint-plugin-prettier": "^5.5.4",
+ "jest": "^29.7.0",
+ "lefthook": "^2.0.3",
+ "prettier": "^3.4.2",
+ "react": "19.1.0",
+ "react-native": "0.81.1",
+ "react-native-builder-bob": "^0.40.15",
+ "release-it": "^19.0.4",
+ "turbo": "^2.5.6",
+ "typescript": "^5.9.2"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/@ark/schema": {
+ "version": "0.55.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ark/util": "0.55.0"
+ }
+ },
+ "node_modules/@ark/util": {
+ "version": "0.55.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.27.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.27.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
+ "version": "5.1.1",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@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.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/traverse": "^7.28.5",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "regexpu-core": "^6.3.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.6.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "debug": "^4.4.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.22.10"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-wrap-function": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-member-expression-to-functions": "^7.27.1",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.28.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.3",
+ "@babel/types": "^7.28.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.4",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.5"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
+ "version": "7.28.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/plugin-transform-optional-chaining": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
+ "version": "7.28.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-export-default-from": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.21.0-placeholder-for-preset-env.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-default-from": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-flow": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.27.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
+ "version": "7.18.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.28.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-remap-async-to-generator": "^7.27.1",
+ "@babel/traverse": "^7.28.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-remap-async-to-generator": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-static-block": {
+ "version": "7.28.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.28.3",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.28.4",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1",
+ "@babel/traverse": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/template": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dynamic-import": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-explicit-resource-management": {
+ "version": "7.28.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-transform-destructuring": "^7.28.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.28.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-export-namespace-from": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-flow-strip-types": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-syntax-flow": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-json-strings": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.28.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-numeric-separator": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.28.4",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-transform-destructuring": "^7.28.0",
+ "@babel/plugin-transform-parameters": "^7.27.7",
+ "@babel/traverse": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.27.7",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.28.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.28.4",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regexp-modifiers": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "babel-plugin-polyfill-corejs2": "^0.4.14",
+ "babel-plugin-polyfill-corejs3": "^0.13.0",
+ "babel-plugin-polyfill-regenerator": "^0.6.5",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-strict-mode": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.28.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "@babel/helper-create-class-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/plugin-syntax-typescript": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-property-regex": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.27.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.28.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
+ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+ "@babel/plugin-syntax-import-assertions": "^7.27.1",
+ "@babel/plugin-syntax-import-attributes": "^7.27.1",
+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+ "@babel/plugin-transform-arrow-functions": "^7.27.1",
+ "@babel/plugin-transform-async-generator-functions": "^7.28.0",
+ "@babel/plugin-transform-async-to-generator": "^7.27.1",
+ "@babel/plugin-transform-block-scoped-functions": "^7.27.1",
+ "@babel/plugin-transform-block-scoping": "^7.28.5",
+ "@babel/plugin-transform-class-properties": "^7.27.1",
+ "@babel/plugin-transform-class-static-block": "^7.28.3",
+ "@babel/plugin-transform-classes": "^7.28.4",
+ "@babel/plugin-transform-computed-properties": "^7.27.1",
+ "@babel/plugin-transform-destructuring": "^7.28.5",
+ "@babel/plugin-transform-dotall-regex": "^7.27.1",
+ "@babel/plugin-transform-duplicate-keys": "^7.27.1",
+ "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1",
+ "@babel/plugin-transform-dynamic-import": "^7.27.1",
+ "@babel/plugin-transform-explicit-resource-management": "^7.28.0",
+ "@babel/plugin-transform-exponentiation-operator": "^7.28.5",
+ "@babel/plugin-transform-export-namespace-from": "^7.27.1",
+ "@babel/plugin-transform-for-of": "^7.27.1",
+ "@babel/plugin-transform-function-name": "^7.27.1",
+ "@babel/plugin-transform-json-strings": "^7.27.1",
+ "@babel/plugin-transform-literals": "^7.27.1",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.28.5",
+ "@babel/plugin-transform-member-expression-literals": "^7.27.1",
+ "@babel/plugin-transform-modules-amd": "^7.27.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.27.1",
+ "@babel/plugin-transform-modules-systemjs": "^7.28.5",
+ "@babel/plugin-transform-modules-umd": "^7.27.1",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1",
+ "@babel/plugin-transform-new-target": "^7.27.1",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
+ "@babel/plugin-transform-numeric-separator": "^7.27.1",
+ "@babel/plugin-transform-object-rest-spread": "^7.28.4",
+ "@babel/plugin-transform-object-super": "^7.27.1",
+ "@babel/plugin-transform-optional-catch-binding": "^7.27.1",
+ "@babel/plugin-transform-optional-chaining": "^7.28.5",
+ "@babel/plugin-transform-parameters": "^7.27.7",
+ "@babel/plugin-transform-private-methods": "^7.27.1",
+ "@babel/plugin-transform-private-property-in-object": "^7.27.1",
+ "@babel/plugin-transform-property-literals": "^7.27.1",
+ "@babel/plugin-transform-regenerator": "^7.28.4",
+ "@babel/plugin-transform-regexp-modifiers": "^7.27.1",
+ "@babel/plugin-transform-reserved-words": "^7.27.1",
+ "@babel/plugin-transform-shorthand-properties": "^7.27.1",
+ "@babel/plugin-transform-spread": "^7.27.1",
+ "@babel/plugin-transform-sticky-regex": "^7.27.1",
+ "@babel/plugin-transform-template-literals": "^7.27.1",
+ "@babel/plugin-transform-typeof-symbol": "^7.27.1",
+ "@babel/plugin-transform-unicode-escapes": "^7.27.1",
+ "@babel/plugin-transform-unicode-property-regex": "^7.27.1",
+ "@babel/plugin-transform-unicode-regex": "^7.27.1",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.27.1",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "babel-plugin-polyfill-corejs2": "^0.4.14",
+ "babel-plugin-polyfill-corejs3": "^0.13.0",
+ "babel-plugin-polyfill-regenerator": "^0.6.5",
+ "core-js-compat": "^3.43.0",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.6-no-external-plugins",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/preset-react": {
+ "version": "7.28.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-transform-react-display-name": "^7.28.0",
+ "@babel/plugin-transform-react-jsx": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-development": "^7.27.1",
+ "@babel/plugin-transform-react-pure-annotations": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.28.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.27.1",
+ "@babel/plugin-transform-typescript": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.4",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse--for-generate-function-map": {
+ "name": "@babel/traverse",
+ "version": "7.28.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@hapi/hoek": {
+ "version": "9.3.0",
+ "devOptional": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@hapi/topo": {
+ "version": "5.1.0",
+ "devOptional": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@isaacs/ttlcache": {
+ "version": "1.4.1",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.11",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@react-native-community/cli": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-clean": "20.0.0",
+ "@react-native-community/cli-config": "20.0.0",
+ "@react-native-community/cli-doctor": "20.0.0",
+ "@react-native-community/cli-server-api": "20.0.0",
+ "@react-native-community/cli-tools": "20.0.0",
+ "@react-native-community/cli-types": "20.0.0",
+ "chalk": "^4.1.2",
+ "commander": "^9.4.1",
+ "deepmerge": "^4.3.0",
+ "execa": "^5.0.0",
+ "find-up": "^5.0.0",
+ "fs-extra": "^8.1.0",
+ "graceful-fs": "^4.1.3",
+ "prompts": "^2.4.2",
+ "semver": "^7.5.2"
+ },
+ "bin": {
+ "rnc-cli": "build/bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native-community/cli-clean": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "execa": "^5.0.0",
+ "fast-glob": "^3.3.2"
+ }
+ },
+ "node_modules/@react-native-community/cli-config": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "cosmiconfig": "^9.0.0",
+ "deepmerge": "^4.3.0",
+ "fast-glob": "^3.3.2",
+ "joi": "^17.2.1"
+ }
+ },
+ "node_modules/@react-native-community/cli-config-android": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "fast-glob": "^3.3.2",
+ "fast-xml-parser": "^4.4.1"
+ }
+ },
+ "node_modules/@react-native-community/cli-config-apple": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "execa": "^5.0.0",
+ "fast-glob": "^3.3.2"
+ }
+ },
+ "node_modules/@react-native-community/cli-doctor": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-config": "20.0.0",
+ "@react-native-community/cli-platform-android": "20.0.0",
+ "@react-native-community/cli-platform-apple": "20.0.0",
+ "@react-native-community/cli-platform-ios": "20.0.0",
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "command-exists": "^1.2.8",
+ "deepmerge": "^4.3.0",
+ "envinfo": "^7.13.0",
+ "execa": "^5.0.0",
+ "node-stream-zip": "^1.9.1",
+ "ora": "^5.4.1",
+ "semver": "^7.5.2",
+ "wcwidth": "^1.0.1",
+ "yaml": "^2.2.1"
+ }
+ },
+ "node_modules/@react-native-community/cli-doctor/node_modules/semver": {
+ "version": "7.7.3",
+ "devOptional": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@react-native-community/cli-platform-android": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-config-android": "20.0.0",
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "execa": "^5.0.0",
+ "logkitty": "^0.7.1"
+ }
+ },
+ "node_modules/@react-native-community/cli-platform-apple": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-config-apple": "20.0.0",
+ "@react-native-community/cli-tools": "20.0.0",
+ "chalk": "^4.1.2",
+ "execa": "^5.0.0",
+ "fast-xml-parser": "^4.4.1"
+ }
+ },
+ "node_modules/@react-native-community/cli-platform-ios": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-platform-apple": "20.0.0"
+ }
+ },
+ "node_modules/@react-native-community/cli-server-api": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native-community/cli-tools": "20.0.0",
+ "body-parser": "^1.20.3",
+ "compression": "^1.7.1",
+ "connect": "^3.6.5",
+ "errorhandler": "^1.5.1",
+ "nocache": "^3.0.1",
+ "open": "^6.2.0",
+ "pretty-format": "^29.7.0",
+ "serve-static": "^1.13.1",
+ "ws": "^6.2.3"
+ }
+ },
+ "node_modules/@react-native-community/cli-tools": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vscode/sudo-prompt": "^9.0.0",
+ "appdirsjs": "^1.2.4",
+ "chalk": "^4.1.2",
+ "execa": "^5.0.0",
+ "find-up": "^5.0.0",
+ "launch-editor": "^2.9.1",
+ "mime": "^2.4.1",
+ "ora": "^5.4.1",
+ "prompts": "^2.4.2",
+ "semver": "^7.5.2"
+ }
+ },
+ "node_modules/@react-native-community/cli-tools/node_modules/semver": {
+ "version": "7.7.3",
+ "devOptional": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@react-native-community/cli-types": {
+ "version": "20.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "joi": "^17.2.1"
+ }
+ },
+ "node_modules/@react-native-community/cli/node_modules/semver": {
+ "version": "7.7.3",
+ "devOptional": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@react-native/assets-registry": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/babel-plugin-codegen": {
+ "version": "0.81.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.25.3",
+ "@react-native/codegen": "0.81.1"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/babel-preset": {
+ "version": "0.81.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-proposal-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.24.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.4",
+ "@babel/plugin-transform-async-to-generator": "^7.24.7",
+ "@babel/plugin-transform-block-scoping": "^7.25.0",
+ "@babel/plugin-transform-class-properties": "^7.25.4",
+ "@babel/plugin-transform-classes": "^7.25.4",
+ "@babel/plugin-transform-computed-properties": "^7.24.7",
+ "@babel/plugin-transform-destructuring": "^7.24.8",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.2",
+ "@babel/plugin-transform-for-of": "^7.24.7",
+ "@babel/plugin-transform-function-name": "^7.25.1",
+ "@babel/plugin-transform-literals": "^7.25.2",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.8",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-numeric-separator": "^7.24.7",
+ "@babel/plugin-transform-object-rest-spread": "^7.24.7",
+ "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.8",
+ "@babel/plugin-transform-parameters": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/plugin-transform-private-property-in-object": "^7.24.7",
+ "@babel/plugin-transform-react-display-name": "^7.24.7",
+ "@babel/plugin-transform-react-jsx": "^7.25.2",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.7",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.7",
+ "@babel/plugin-transform-regenerator": "^7.24.7",
+ "@babel/plugin-transform-runtime": "^7.24.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.24.7",
+ "@babel/plugin-transform-spread": "^7.24.7",
+ "@babel/plugin-transform-sticky-regex": "^7.24.7",
+ "@babel/plugin-transform-typescript": "^7.25.2",
+ "@babel/plugin-transform-unicode-regex": "^7.24.7",
+ "@babel/template": "^7.25.0",
+ "@react-native/babel-plugin-codegen": "0.81.1",
+ "babel-plugin-syntax-hermes-parser": "0.29.1",
+ "babel-plugin-transform-flow-enums": "^0.0.2",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/codegen": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/parser": "^7.25.3",
+ "glob": "^7.1.1",
+ "hermes-parser": "0.29.1",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "yargs": "^17.6.2"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "dependencies": {
+ "@react-native/dev-middleware": "0.81.1",
+ "debug": "^4.4.0",
+ "invariant": "^2.2.4",
+ "metro": "^0.83.1",
+ "metro-config": "^0.83.1",
+ "metro-core": "^0.83.1",
+ "semver": "^7.1.3"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@react-native-community/cli": "*",
+ "@react-native/metro-config": "*"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-community/cli": {
+ "optional": true
+ },
+ "@react-native/metro-config": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/semver": {
+ "version": "7.7.3",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@react-native/debugger-frontend": {
+ "version": "0.81.1",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/dev-middleware": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "dependencies": {
+ "@isaacs/ttlcache": "^1.4.1",
+ "@react-native/debugger-frontend": "0.81.1",
+ "chrome-launcher": "^0.15.2",
+ "chromium-edge-launcher": "^0.2.0",
+ "connect": "^3.6.5",
+ "debug": "^4.4.0",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "open": "^7.0.3",
+ "serve-static": "^1.16.2",
+ "ws": "^6.2.3"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/dev-middleware/node_modules/open": {
+ "version": "7.4.2",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@react-native/gradle-plugin": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/js-polyfills": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/metro-babel-transformer": {
+ "version": "0.81.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@react-native/babel-preset": "0.81.1",
+ "hermes-parser": "0.29.1",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/metro-config": {
+ "version": "0.81.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@react-native/js-polyfills": "0.81.1",
+ "@react-native/metro-babel-transformer": "0.81.1",
+ "metro-config": "^0.83.1",
+ "metro-runtime": "^0.83.1"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/normalize-colors": {
+ "version": "0.81.1",
+ "license": "MIT"
+ },
+ "node_modules/@react-native/typescript-config": {
+ "version": "0.81.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@react-native/virtualized-lists": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.1.0",
+ "react": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@sideway/address": {
+ "version": "4.1.5",
+ "devOptional": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@sideway/formula": {
+ "version": "3.0.1",
+ "devOptional": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sideway/pinpoint": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "24.10.1",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.7",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "license": "MIT"
+ },
+ "node_modules/@vscode/sudo-prompt": {
+ "version": "9.3.1",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/accepts/node_modules/negotiator": {
+ "version": "0.6.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/anser": {
+ "version": "1.4.10",
+ "license": "MIT"
+ },
+ "node_modules/ansi-fragments": {
+ "version": "0.2.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "colorette": "^1.0.7",
+ "slice-ansi": "^2.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "node_modules/ansi-fragments/node_modules/ansi-regex": {
+ "version": "4.1.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-fragments/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/appdirsjs": {
+ "version": "1.2.7",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "devOptional": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/arkregex": {
+ "version": "0.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ark/util": "0.55.0"
+ }
+ },
+ "node_modules/arktype": {
+ "version": "2.1.27",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ark/schema": "0.55.0",
+ "@ark/util": "0.55.0",
+ "arkregex": "0.0.3"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "license": "MIT"
+ },
+ "node_modules/astral-regex": {
+ "version": "1.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/async-generator-function": {
+ "version": "1.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/async-limiter": {
+ "version": "1.0.1",
+ "license": "MIT"
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.14",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.7",
+ "@babel/helper-define-polyfill-provider": "^0.6.5",
+ "semver": "^6.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.13.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.5",
+ "core-js-compat": "^3.43.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.6.5",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser": {
+ "version": "0.29.1",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-parser": "0.29.1"
+ }
+ },
+ "node_modules/babel-plugin-transform-flow-enums": {
+ "version": "0.0.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-flow": "^7.12.1"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.31",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.0",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.8.25",
+ "caniuse-lite": "^1.0.30001754",
+ "electron-to-chromium": "^1.5.249",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.1.4"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "license": "MIT"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001757",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chrome-launcher": {
+ "version": "0.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0"
+ },
+ "bin": {
+ "print-chrome-path": "bin/print-chrome-path.js"
+ },
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
+ "node_modules/chromium-edge-launcher": {
+ "version": "0.2.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0",
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "6.0.0",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "license": "MIT"
+ },
+ "node_modules/colorette": {
+ "version": "1.4.0",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/command-exists": {
+ "version": "1.2.9",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "9.5.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compressible/node_modules/mime-db": {
+ "version": "1.54.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.8.1",
+ "devOptional": true,
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/compression/node_modules/debug": {
+ "version": "2.6.9",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/compression/node_modules/ms": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "license": "MIT"
+ },
+ "node_modules/connect": {
+ "version": "3.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/connect/node_modules/debug": {
+ "version": "2.6.9",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/connect/node_modules/ms": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.47.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.19",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "0.7.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/del": {
+ "version": "6.1.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "globby": "^11.0.1",
+ "graceful-fs": "^4.2.4",
+ "is-glob": "^4.0.1",
+ "is-path-cwd": "^2.2.0",
+ "is-path-inside": "^3.0.2",
+ "p-map": "^4.0.0",
+ "rimraf": "^3.0.2",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.259",
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.20.0",
+ "devOptional": true,
+ "license": "MIT",
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/errorhandler": {
+ "version": "1.5.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.7",
+ "escape-html": "~1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exponential-backoff": {
+ "version": "3.1.3",
+ "license": "Apache-2.0"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "license": "MIT"
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "4.5.3",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "strnum": "^1.1.1"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.1.2",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/finalhandler/node_modules/on-finished": {
+ "version": "2.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/statuses": {
+ "version": "1.5.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flow-enums-runtime": {
+ "version": "0.0.6",
+ "license": "MIT"
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "8.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fs-extra/node_modules/universalify": {
+ "version": "0.1.2",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "devOptional": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "async-generator-function": "^1.0.0",
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.29.1",
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.29.1",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.29.1"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/image-size": {
+ "version": "1.2.1",
+ "license": "MIT",
+ "dependencies": {
+ "queue": "6.0.2"
+ },
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "license": "ISC"
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/is-absolute": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-relative": "^1.0.0",
+ "is-windows": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-git-dirty": {
+ "version": "2.0.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^4.0.3",
+ "is-git-repository": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/is-git-dirty/node_modules/execa": {
+ "version": "4.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/is-git-dirty/node_modules/get-stream": {
+ "version": "5.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-git-dirty/node_modules/human-signals": {
+ "version": "1.1.1",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.12.0"
+ }
+ },
+ "node_modules/is-git-repository": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^4.0.3",
+ "is-absolute": "^1.0.0"
+ }
+ },
+ "node_modules/is-git-repository/node_modules/execa": {
+ "version": "4.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/is-git-repository/node_modules/get-stream": {
+ "version": "5.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-git-repository/node_modules/human-signals": {
+ "version": "1.1.1",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.12.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-cwd": {
+ "version": "2.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-relative": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-unc-path": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-unc-path": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "unc-path-regex": "^0.1.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util/node_modules/ci-info": {
+ "version": "3.9.0",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/joi": {
+ "version": "17.13.3",
+ "devOptional": true,
+ "license": "BSD-3-Clause",
+ "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"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsc-safe-url": {
+ "version": "0.2.4",
+ "license": "0BSD"
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/launch-editor": {
+ "version": "2.12.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^1.1.1",
+ "shell-quote": "^1.8.3"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lighthouse-logger": {
+ "version": "1.4.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^2.6.9",
+ "marky": "^1.2.2"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/debug": {
+ "version": "2.6.9",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/ms": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "license": "MIT"
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/logkitty": {
+ "version": "0.7.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-fragments": "^0.2.1",
+ "dayjs": "^1.8.15",
+ "yargs": "^15.1.0"
+ },
+ "bin": {
+ "logkitty": "bin/logkitty.js"
+ }
+ },
+ "node_modules/logkitty/node_modules/find-up": {
+ "version": "4.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/logkitty/node_modules/locate-path": {
+ "version": "5.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/logkitty/node_modules/p-limit": {
+ "version": "2.3.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/logkitty/node_modules/p-locate": {
+ "version": "4.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/logkitty/node_modules/yargs": {
+ "version": "15.4.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/marky": {
+ "version": "1.3.0",
+ "license": "Apache-2.0"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memoize-one": {
+ "version": "5.2.1",
+ "license": "MIT"
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/metro": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.24.7",
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "accepts": "^1.3.7",
+ "chalk": "^4.0.0",
+ "ci-info": "^2.0.0",
+ "connect": "^3.6.5",
+ "debug": "^4.4.0",
+ "error-stack-parser": "^2.0.6",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "hermes-parser": "0.32.0",
+ "image-size": "^1.0.2",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "jsc-safe-url": "^0.2.2",
+ "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.27",
+ "nullthrows": "^1.1.1",
+ "serialize-error": "^2.1.0",
+ "source-map": "^0.5.6",
+ "throat": "^5.0.0",
+ "ws": "^7.5.10",
+ "yargs": "^17.6.2"
+ },
+ "bin": {
+ "metro": "src/cli.js"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-babel-transformer": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "hermes-parser": "0.32.0",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-babel-transformer/node_modules/hermes-estree": {
+ "version": "0.32.0",
+ "license": "MIT"
+ },
+ "node_modules/metro-babel-transformer/node_modules/hermes-parser": {
+ "version": "0.32.0",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.32.0"
+ }
+ },
+ "node_modules/metro-cache": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "exponential-backoff": "^3.1.1",
+ "flow-enums-runtime": "^0.0.6",
+ "https-proxy-agent": "^7.0.5",
+ "metro-core": "0.83.3"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-cache-key": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-config": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "connect": "^3.6.5",
+ "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.6.1"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-core": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "lodash.throttle": "^4.1.1",
+ "metro-resolver": "0.83.3"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-file-map": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "fb-watchman": "^2.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "nullthrows": "^1.1.1",
+ "walker": "^1.0.7"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-minify-terser": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "terser": "^5.15.0"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-resolver": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-runtime": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.25.0",
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-source-map": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.25.3",
+ "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
+ "@babel/types": "^7.25.2",
+ "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.6",
+ "vlq": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-symbolicate": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "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.6",
+ "vlq": "^1.0.0"
+ },
+ "bin": {
+ "metro-symbolicate": "src/index.js"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-transform-plugins": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "flow-enums-runtime": "^0.0.6",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro-transform-worker": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "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"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/metro/node_modules/hermes-estree": {
+ "version": "0.32.0",
+ "license": "MIT"
+ },
+ "node_modules/metro/node_modules/hermes-parser": {
+ "version": "0.32.0",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.32.0"
+ }
+ },
+ "node_modules/metro/node_modules/ws": {
+ "version": "7.5.10",
+ "license": "MIT",
+ "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
+ }
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "devOptional": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.4",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nocache": {
+ "version": "3.0.4",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "license": "MIT"
+ },
+ "node_modules/node-stream-zip": {
+ "version": "1.15.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/antelle"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nullthrows": {
+ "version": "1.1.1",
+ "license": "MIT"
+ },
+ "node_modules/ob1": {
+ "version": "0.83.3",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "6.4.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-wsl": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/open/node_modules/is-wsl": {
+ "version": "1.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/promise": {
+ "version": "8.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "asap": "~2.0.6"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pump": {
+ "version": "3.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.13.0",
+ "devOptional": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue": {
+ "version": "6.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "~2.0.3"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.1.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-devtools-core": {
+ "version": "6.1.5",
+ "license": "MIT",
+ "dependencies": {
+ "shell-quote": "^1.6.1",
+ "ws": "^7"
+ }
+ },
+ "node_modules/react-devtools-core/node_modules/ws": {
+ "version": "7.5.10",
+ "license": "MIT",
+ "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
+ }
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "license": "MIT"
+ },
+ "node_modules/react-native": {
+ "version": "0.81.1",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/create-cache-key-function": "^29.7.0",
+ "@react-native/assets-registry": "0.81.1",
+ "@react-native/codegen": "0.81.1",
+ "@react-native/community-cli-plugin": "0.81.1",
+ "@react-native/gradle-plugin": "0.81.1",
+ "@react-native/js-polyfills": "0.81.1",
+ "@react-native/normalize-colors": "0.81.1",
+ "@react-native/virtualized-lists": "0.81.1",
+ "abort-controller": "^3.0.0",
+ "anser": "^1.4.9",
+ "ansi-regex": "^5.0.0",
+ "babel-jest": "^29.7.0",
+ "babel-plugin-syntax-hermes-parser": "0.29.1",
+ "base64-js": "^1.5.1",
+ "commander": "^12.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "glob": "^7.1.1",
+ "invariant": "^2.2.4",
+ "jest-environment-node": "^29.7.0",
+ "memoize-one": "^5.0.0",
+ "metro-runtime": "^0.83.1",
+ "metro-source-map": "^0.83.1",
+ "nullthrows": "^1.1.1",
+ "pretty-format": "^29.7.0",
+ "promise": "^8.3.0",
+ "react-devtools-core": "^6.1.5",
+ "react-refresh": "^0.14.0",
+ "regenerator-runtime": "^0.13.2",
+ "scheduler": "0.26.0",
+ "semver": "^7.1.3",
+ "stacktrace-parser": "^0.1.10",
+ "whatwg-fetch": "^3.0.0",
+ "ws": "^6.2.3",
+ "yargs": "^17.6.2"
+ },
+ "bin": {
+ "react-native": "cli.js"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.1.0",
+ "react": "^19.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-native-builder-bob": {
+ "version": "0.40.15",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-transform-flow-strip-types": "^7.26.5",
+ "@babel/plugin-transform-strict-mode": "^7.24.7",
+ "@babel/preset-env": "^7.25.2",
+ "@babel/preset-react": "^7.24.7",
+ "@babel/preset-typescript": "^7.24.7",
+ "arktype": "^2.1.15",
+ "babel-plugin-syntax-hermes-parser": "^0.28.0",
+ "browserslist": "^4.20.4",
+ "cross-spawn": "^7.0.3",
+ "dedent": "^0.7.0",
+ "del": "^6.1.1",
+ "escape-string-regexp": "^4.0.0",
+ "fs-extra": "^10.1.0",
+ "glob": "^8.0.3",
+ "is-git-dirty": "^2.0.1",
+ "json5": "^2.2.1",
+ "kleur": "^4.1.4",
+ "prompts": "^2.4.2",
+ "react-native-monorepo-config": "^0.1.8",
+ "which": "^2.0.2",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "bob": "bin/bob"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >= 23.4.0"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/babel-plugin-syntax-hermes-parser": {
+ "version": "0.28.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-parser": "0.28.1"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/glob": {
+ "version": "8.1.0",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/hermes-estree": {
+ "version": "0.28.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/react-native-builder-bob/node_modules/hermes-parser": {
+ "version": "0.28.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.28.1"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/jsonfile": {
+ "version": "6.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/kleur": {
+ "version": "4.1.5",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react-native-builder-bob/node_modules/minimatch": {
+ "version": "5.1.6",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/react-native-callingx": {
+ "resolved": "..",
+ "link": true
+ },
+ "node_modules/react-native-monorepo-config": {
+ "version": "0.1.10",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^5.0.0",
+ "fast-glob": "^3.3.3"
+ }
+ },
+ "node_modules/react-native-monorepo-config/node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/react-native/node_modules/commander": {
+ "version": "12.1.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/react-native/node_modules/semver": {
+ "version": "7.7.3",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.2.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "license": "MIT"
+ },
+ "node_modules/regexpu-core": {
+ "version": "6.4.0",
+ "devOptional": true,
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsgen": {
+ "version": "0.8.0",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/regjsparser": {
+ "version": "0.13.0",
+ "devOptional": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "jsesc": "~3.1.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.11",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/scheduler": {
+ "version": "0.26.0",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.19.0",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/send/node_modules/mime": {
+ "version": "1.6.0",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/serialize-error": {
+ "version": "2.1.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.2",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-static/node_modules/encodeurl": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "license": "ISC"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.8.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "license": "ISC"
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "2.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "astral-regex": "^1.0.0",
+ "is-fullwidth-code-point": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/color-convert": {
+ "version": "1.9.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/color-name": {
+ "version": "1.1.3",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "license": "MIT"
+ },
+ "node_modules/stacktrace-parser": {
+ "version": "0.1.11",
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "1.1.2",
+ "devOptional": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.44.1",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.15.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser/node_modules/commander": {
+ "version": "2.20.3",
+ "license": "MIT"
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/throat": {
+ "version": "5.0.0",
+ "license": "MIT"
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.7.1",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/unc-path-regex": {
+ "version": "0.1.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "license": "MIT"
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.2.1",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.2.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.4",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vlq": {
+ "version": "1.0.1",
+ "license": "MIT"
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/whatwg-fetch": {
+ "version": "3.6.20",
+ "license": "MIT"
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/ws": {
+ "version": "6.2.3",
+ "license": "MIT",
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "4.0.3",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "license": "ISC"
+ },
+ "node_modules/yaml": {
+ "version": "2.8.1",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yargs/node_modules/cliui": {
+ "version": "8.0.1",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/yargs/node_modules/y18n": {
+ "version": "5.0.8",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/packages/react-native-callingx/example/package.json b/packages/react-native-callingx/example/package.json
new file mode 100644
index 0000000000..b8d5ee8f1d
--- /dev/null
+++ b/packages/react-native-callingx/example/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "react-native-callingx-example",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "android": "react-native run-android",
+ "ios": "react-native run-ios",
+ "start": "react-native start",
+ "build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"",
+ "build:ios": "react-native build-ios --mode Debug"
+ },
+ "dependencies": {
+ "react": "19.1.0",
+ "react-native": "0.81.1",
+ "react-native-callingx": "file:.."
+ },
+ "devDependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/preset-env": "^7.25.3",
+ "@babel/runtime": "^7.25.0",
+ "@react-native-community/cli": "20.0.0",
+ "@react-native-community/cli-platform-android": "20.0.0",
+ "@react-native-community/cli-platform-ios": "20.0.0",
+ "@react-native/babel-preset": "0.81.1",
+ "@react-native/metro-config": "0.81.1",
+ "@react-native/typescript-config": "0.81.1",
+ "@types/react": "^19.1.0",
+ "react-native-builder-bob": "^0.40.15",
+ "react-native-monorepo-config": "^0.1.9"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+}
diff --git a/packages/react-native-callingx/example/react-native.config.js b/packages/react-native-callingx/example/react-native.config.js
new file mode 100644
index 0000000000..59d969820e
--- /dev/null
+++ b/packages/react-native-callingx/example/react-native.config.js
@@ -0,0 +1,21 @@
+const path = require('path');
+const pkg = require('../package.json');
+
+module.exports = {
+ project: {
+ ios: {
+ automaticPodsInstallation: true,
+ },
+ },
+ dependencies: {
+ [pkg.name]: {
+ root: path.join(__dirname, '..'),
+ platforms: {
+ // Codegen script incorrectly fails without this
+ // So we explicitly specify the platforms with empty object
+ ios: {},
+ android: {},
+ },
+ },
+ },
+};
diff --git a/packages/react-native-callingx/example/src/App.tsx b/packages/react-native-callingx/example/src/App.tsx
new file mode 100644
index 0000000000..84e1040e26
--- /dev/null
+++ b/packages/react-native-callingx/example/src/App.tsx
@@ -0,0 +1,20 @@
+import { Text, View, StyleSheet } from 'react-native';
+import { multiply } from 'react-native-callingx';
+
+const result = multiply(3, 7);
+
+export default function App() {
+ return (
+
+ Result: {result}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
diff --git a/packages/react-native-callingx/ios/AudioSessionManager.h b/packages/react-native-callingx/ios/AudioSessionManager.h
new file mode 100644
index 0000000000..410ca184bc
--- /dev/null
+++ b/packages/react-native-callingx/ios/AudioSessionManager.h
@@ -0,0 +1,12 @@
+#import
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AudioSessionManager : NSObject
+
++ (void)createAudioSessionIfNeeded;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/packages/react-native-callingx/ios/AudioSessionManager.mm b/packages/react-native-callingx/ios/AudioSessionManager.mm
new file mode 100644
index 0000000000..fc61e7cb89
--- /dev/null
+++ b/packages/react-native-callingx/ios/AudioSessionManager.mm
@@ -0,0 +1,50 @@
+#import "AudioSessionManager.h"
+#import "Settings.h"
+#import
+
+@implementation AudioSessionManager
+
++ (void)createAudioSessionIfNeeded {
+ BOOL autoConfigureAudioSession = [Settings getAutoConfigureAudioSession];
+ if (!autoConfigureAudioSession) {
+#ifdef DEBUG
+ NSLog(@"[Callingx][createAudioSessionIfNeeded] Auto-configuration disabled, user handles audio session");
+#endif
+ return;
+ }
+
+#ifdef DEBUG
+ NSLog(@"[Callingx][createAudioSessionIfNeeded] Activating audio session");
+#endif
+
+ NSUInteger categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth |
+ AVAudioSessionCategoryOptionAllowBluetoothA2DP;
+ NSString *mode = AVAudioSessionModeDefault;
+
+ NSDictionary *settings = [Settings getSettings];
+ if (settings && settings[@"audioSession"]) {
+ if (settings[@"audioSession"][@"categoryOptions"]) {
+ categoryOptions = [settings[@"audioSession"][@"categoryOptions"] integerValue];
+ }
+
+ if (settings[@"audioSession"][@"mode"]) {
+ mode = settings[@"audioSession"][@"mode"];
+ }
+ }
+
+ AVAudioSession *audioSession = [AVAudioSession sharedInstance];
+ [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord
+ withOptions:categoryOptions
+ error:nil];
+
+ [audioSession setMode:mode error:nil];
+
+ double sampleRate = 44100.0;
+ [audioSession setPreferredSampleRate:sampleRate error:nil];
+
+ NSTimeInterval bufferDuration = .005;
+ [audioSession setPreferredIOBufferDuration:bufferDuration error:nil];
+ [audioSession setActive:TRUE error:nil];
+}
+
+@end
diff --git a/packages/react-native-callingx/ios/Callingx.h b/packages/react-native-callingx/ios/Callingx.h
new file mode 100644
index 0000000000..93754f11bc
--- /dev/null
+++ b/packages/react-native-callingx/ios/Callingx.h
@@ -0,0 +1,39 @@
+#import
+#import
+#import
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface Callingx : NativeCallingxSpecBase
+
+@property (nonatomic, strong) CXCallController *callKeepCallController;
+@property (nonatomic, strong) CXProvider *callKeepProvider;
+
+//+ (BOOL)application:(UIApplication *)application
+// openURL:(NSURL *)url
+// options:(NSDictionary *)options NS_AVAILABLE_IOS(9_0);
+//
+//+ (BOOL)application:(UIApplication *)application
+//continueUserActivity:(NSUserActivity *)userActivity
+// restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler;
+
++ (void)reportNewIncomingCall:(NSString *)uuidString
+ handle:(NSString *)handle
+ handleType:(NSString *)handleType
+ hasVideo:(BOOL)hasVideo
+ localizedCallerName:(NSString * _Nullable)localizedCallerName
+ supportsHolding:(BOOL)supportsHolding
+ supportsDTMF:(BOOL)supportsDTMF
+ supportsGrouping:(BOOL)supportsGrouping
+ supportsUngrouping:(BOOL)supportsUngrouping
+ fromPushKit:(BOOL)fromPushKit
+ payload:(NSDictionary * _Nullable)payload
+ withCompletionHandler:(void (^_Nullable)(void))completion;
+
++ (void)endCall:(NSString *)callId
+ reason:(int)reason;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/packages/react-native-callingx/ios/Callingx.mm b/packages/react-native-callingx/ios/Callingx.mm
new file mode 100644
index 0000000000..05b1a695da
--- /dev/null
+++ b/packages/react-native-callingx/ios/Callingx.mm
@@ -0,0 +1,970 @@
+#import "Callingx.h"
+#import
+#import
+
+#import
+#import
+#import "UUIDStorage.h"
+#import "Settings.h"
+#import "AudioSessionManager.h"
+
+#ifdef DEBUG
+static int const OUTGOING_CALL_WAKEUP_DELAY = 10;
+#else
+static int const OUTGOING_CALL_WAKEUP_DELAY = 5;
+#endif
+
+static NSString *const CallingxDidReceiveStartCallAction = @"didReceiveStartCallAction";
+static NSString *const CallingxPerformAnswerCallAction = @"answerCall";
+static NSString *const CallingxPerformEndCallAction = @"endCall";
+static NSString *const CallingxDidToggleHoldAction = @"didToggleHoldCallAction";
+static NSString *const CallingxDidPerformSetMutedCallAction = @"didPerformSetMutedCallAction";
+static NSString *const CallingxDidChangeAudioRoute = @"didChangeAudioRoute";
+static NSString *const CallingxDidLoadWithEvents = @"didLoadWithEvents";
+static NSString *const CallingxDidDisplayIncomingCall = @"didDisplayIncomingCall";
+
+static NSString *const CallingxDidActivateAudioSession = @"didActivateAudioSession";
+static NSString *const CallingxDidDeactivateAudioSession = @"didDeactivateAudioSession";
+static NSString *const CallingxPerformPlayDTMFCallAction = @"didPerformDTMFAction";
+static NSString *const CallingxProviderReset = @"providerReset";
+
+@implementation Callingx {
+ NSOperatingSystemVersion _version;
+ bool _isReachable;
+ bool _isInitialized;
+ bool _isSelfAnswered;
+ bool _isSelfEnded;
+ NSMutableArray *_delayedEvents;
+}
+
+static CXProvider *sharedProvider;
+static UUIDStorage *uuidStorage;
+
+#pragma mark - Class Methods
+
++ (id)allocWithZone:(NSZone *)zone {
+ static Callingx *sharedInstance = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [super allocWithZone:zone];
+ });
+ return sharedInstance;
+}
+
++ (void)initUUIDStorage {
+ if (uuidStorage == nil) {
+ uuidStorage = [[UUIDStorage alloc] init];
+ NSLog(@"[Callingx] initUUIDStorage");
+ }
+}
+
++ (void)initCallKitProvider {
+ if (sharedProvider == nil) {
+ NSDictionary *settings = [Settings getSettings];
+ if (settings != nil) {
+ sharedProvider = [[CXProvider alloc] initWithConfiguration:[Settings getProviderConfiguration:settings]];
+ NSLog(@"[Callingx] initCallKitProvider");
+ }
+ }
+}
+
+
++ (void)reportNewIncomingCall:(NSString *)callId
+ handle:(NSString *)handle
+ handleType:(NSString *)handleType
+ hasVideo:(BOOL)hasVideo
+ localizedCallerName:(NSString *_Nullable)localizedCallerName
+ supportsHolding:(BOOL)supportsHolding
+ supportsDTMF:(BOOL)supportsDTMF
+ supportsGrouping:(BOOL)supportsGrouping
+ supportsUngrouping:(BOOL)supportsUngrouping
+ fromPushKit:(BOOL)fromPushKit
+ payload:(NSDictionary *_Nullable)payload
+ withCompletionHandler:(void (^_Nullable)(void))completion {
+#ifdef DEBUG
+ NSLog(@"[Callingx][reportNewIncomingCall] callId = %@", callId);
+ NSLog(@"[Callingx][reportNewIncomingCall] handle = %@", handle);
+ NSLog(@"[Callingx][reportNewIncomingCall] localizedCallerName = %@", localizedCallerName);
+#endif
+
+ [Callingx initUUIDStorage];
+ [Callingx initCallKitProvider];
+
+ if ([uuidStorage containsCid:callId]) {
+ NSLog(@"[Callingx][reportNewIncomingCall] callId already exists");
+ return;
+ }
+
+ CXHandleType _handleType = [Settings getHandleType:handleType];
+ NSUUID *uuid = [uuidStorage getOrCreateUUIDForCid:callId];
+ CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
+ callUpdate.remoteHandle = [[CXHandle alloc] initWithType:_handleType value:handle];
+ callUpdate.supportsHolding = supportsHolding;
+ callUpdate.supportsDTMF = supportsDTMF;
+ callUpdate.supportsGrouping = supportsGrouping;
+ callUpdate.supportsUngrouping = supportsUngrouping;
+ callUpdate.hasVideo = hasVideo;
+ callUpdate.localizedCallerName = localizedCallerName;
+
+ [sharedProvider
+ reportNewIncomingCallWithUUID:uuid
+ update:callUpdate
+ completion:^(NSError *_Nullable error) {
+ NSLog(@"[Callingx][reportNewIncomingCall] callId = %@, error = %@", callId, error);
+ Callingx *callKeep = [Callingx allocWithZone:nil];
+ [callKeep
+ sendEventWithNameWrapper:
+ CallingxDidDisplayIncomingCall
+ body:@{
+ @"error" : error && error.localizedDescription
+ ? error.localizedDescription
+ : @"",
+ @"errorCode" : error
+ ? [callKeep getIncomingCallErrorCode: error]
+ : @"",
+ @"callId" : callId,
+ @"handle" : handle,
+ @"localizedCallerName" : localizedCallerName
+ ? localizedCallerName
+ : @"",
+ @"hasVideo" : hasVideo
+ ? @"1"
+ : @"0",
+ @"supportsHolding" : supportsHolding
+ ? @"1"
+ : @"0",
+ @"supportsDTMF" : supportsDTMF
+ ? @"1"
+ : @"0",
+ @"supportsGrouping" : supportsGrouping
+ ? @"1"
+ : @"0",
+ @"supportsUngrouping" : supportsUngrouping
+ ? @"1"
+ : @"0",
+ @"fromPushKit" : fromPushKit
+ ? @"1"
+ : @"0",
+ @"payload" : payload
+ ? payload
+ : @"",
+ }];
+ if (error == nil) {
+ NSLog(@"[Callingx][reportNewIncomingCall] success callId = %@", callId);
+ }
+ if (completion != nil) {
+ NSLog(@"[Callingx][reportNewIncomingCall] completion");
+ completion();
+ }
+ }];
+}
+
+//+ (BOOL)application:(UIApplication *)application
+//continueUserActivity:(NSUserActivity *)userActivity
+// restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
+//{
+//#ifdef DEBUG
+// NSLog(@"[Callingx][application:continueUserActivity]");
+//#endif
+// INInteraction *interaction = userActivity.interaction;
+// INPerson *contact;
+// NSString *handle;
+// BOOL isAudioCall;
+// BOOL isVideoCall;
+//
+// // HACK TO AVOID XCODE 10 COMPILE CRASH
+// // REMOVE ON NEXT MAJOR RELEASE OF RNCALLKIT
+//#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
+// //XCode 11
+// // iOS 13 returns an INStartCallIntent userActivity type
+// if (@available(iOS 13, *)) {
+// INStartCallIntent *intent = (INStartCallIntent*)interaction.intent;
+// // callCapability is not available on iOS > 13.2, but it is in 13.1 weirdly...
+// if ([intent respondsToSelector:@selector(callCapability)]) {
+// isAudioCall = intent.callCapability == INCallCapabilityAudioCall;
+// isVideoCall = intent.callCapability == INCallCapabilityVideoCall;
+// } else {
+// isAudioCall = [userActivity.activityType isEqualToString:INStartAudioCallIntentIdentifier];
+// isVideoCall = [userActivity.activityType isEqualToString:INStartVideoCallIntentIdentifier];
+// }
+// } else {
+//#endif
+// // XCode 10 and below
+// isAudioCall = [userActivity.activityType isEqualToString:INStartAudioCallIntentIdentifier];
+// isVideoCall = [userActivity.activityType isEqualToString:INStartVideoCallIntentIdentifier];
+// // HACK TO AVOID XCODE 10 COMPILE CRASH
+// // REMOVE ON NEXT MAJOR RELEASE OF RNCALLKIT
+//#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
+// }
+//#endif
+//
+// if (isAudioCall) {
+// INStartAudioCallIntent *startAudioCallIntent = (INStartAudioCallIntent *)interaction.intent;
+// contact = [startAudioCallIntent.contacts firstObject];
+// } else if (isVideoCall) {
+// INStartVideoCallIntent *startVideoCallIntent = (INStartVideoCallIntent *)interaction.intent;
+// contact = [startVideoCallIntent.contacts firstObject];
+// }
+//
+// if (contact != nil) {
+// handle = contact.personHandle.value;
+// }
+//
+// if (handle != nil && handle.length > 0 ){
+// NSDictionary *userInfo = @{
+// @"handle": handle,
+// @"video": @(isVideoCall)
+// };
+//
+// RNCallKeep *callKeep = [RNCallKeep allocWithZone: nil];
+// [callKeep sendEventWithNameWrapper:CallingxDidReceiveStartCallAction body:userInfo];
+// return YES;
+// }
+// return NO;
+//}
+
+
++ (NSString *)getAudioOutput {
+ @try {
+ NSArray *outputs =
+ [AVAudioSession sharedInstance].currentRoute.outputs;
+ if (outputs != nil && outputs.count > 0) {
+ return outputs[0].portType;
+ }
+ } @catch (NSException *error) {
+ NSLog(@"getAudioOutput error :%@", [error description]);
+ }
+
+ return nil;
+}
+
++ (void)endCall:(NSString *)callId reason:(int)reason {
+#ifdef DEBUG
+ NSLog(@"[Callingx][endCall] callId = %@ reason = %d", callId, reason);
+#endif
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ return;
+ }
+
+ switch (reason) {
+ case 1:
+ [sharedProvider reportCallWithUUID:uuid
+ endedAtDate:[NSDate date]
+ reason:CXCallEndedReasonFailed];
+ break;
+ case 2:
+ [sharedProvider reportCallWithUUID:uuid
+ endedAtDate:[NSDate date]
+ reason:CXCallEndedReasonRemoteEnded];
+ break;
+ case 3:
+ [sharedProvider reportCallWithUUID:uuid
+ endedAtDate:[NSDate date]
+ reason:CXCallEndedReasonUnanswered];
+ break;
+ case 4:
+ [sharedProvider reportCallWithUUID:uuid
+ endedAtDate:[NSDate date]
+ reason:CXCallEndedReasonAnsweredElsewhere];
+ break;
+ case 5:
+ [sharedProvider reportCallWithUUID:uuid
+ endedAtDate:[NSDate date]
+ reason:CXCallEndedReasonDeclinedElsewhere];
+ break;
+ default:
+ break;
+ }
+
+ [uuidStorage removeCid:callId];
+}
+
++ (BOOL)requiresMainQueueSetup {
+ return YES;
+}
+
++ (NSString *)moduleName {
+ return @"Callingx";
+}
+
+#pragma mark - Instance methods
+
+- (instancetype)init {
+#ifdef DEBUG
+ NSLog(@"[Callingx][init]");
+#endif
+ if (self = [super init]) {
+ _isReachable = NO;
+ _isInitialized = NO;
+
+ if (_delayedEvents == nil)
+ _delayedEvents = [NSMutableArray array];
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(onAudioRouteChange:)
+ name:AVAudioSessionRouteChangeNotification
+ object:nil];
+
+ // Init provider directly, in case of an app killed and when we've already
+ // stored our settings
+ [Callingx initCallKitProvider];
+ [Callingx initUUIDStorage];
+
+ self.callKeepProvider = sharedProvider;
+ [self.callKeepProvider setDelegate:nil queue:nil];
+ [self.callKeepProvider setDelegate:self queue:nil];
+ }
+ return self;
+}
+
+- (void)dealloc {
+#ifdef DEBUG
+ NSLog(@"[Callingx][dealloc]");
+#endif
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ if (self.callKeepProvider != nil) {
+ [self.callKeepProvider setDelegate:nil queue:nil];
+ [self.callKeepProvider invalidate];
+ }
+ sharedProvider = nil;
+ _isInitialized = NO;
+ _isReachable = NO;
+}
+
+//- (void)startObserving {
+// NSLog(@"[Callingx][startObserving]");
+// _hasListeners = YES;
+// if ([_delayedEvents count] > 0) {
+//// [self sendEventWithName:CallingxDidLoadWithEvents body:_delayedEvents];
+// NSDictionary *dictionary = [
+// NSDictionary dictionaryWithObjectsAndKeys:
+// CallingxDidLoadWithEvents, @"name",
+// _delayedEvents, @"params",
+// nil
+// ];
+// [self emitOnNewEvent: dictionary];
+// }
+//}
+//
+//- (void)stopObserving {
+// _hasListeners = FALSE;
+//
+// // Fix for
+// // https://github.com/react-native-webrtc/react-native-callkeep/issues/406 We
+// // use Objective-C Key Value Coding(KVC) to sync _RTCEventEmitter_
+// // `_listenerCount`.
+// @try {
+// [self setValue:@0 forKey:@"_listenerCount"];
+// } @catch (NSException *e) {
+// NSLog(@"[Callingx][stopObserving] exception: %@", e);
+// NSLog(@"[Callingx][stopObserving] Callingx parent class "
+// @"RTCEventEmitter might have a broken state.");
+// NSLog(@"[Callingx][stopObserving] Please verify that the parent "
+// @"RTCEventEmitter.m has iVar `_listenerCount`.");
+// }
+//}
+
+- (std::shared_ptr)getTurboModule:
+ (const facebook::react::ObjCTurboModule::InitParams &)params {
+ return std::make_shared(params);
+}
+
+- (void)requestTransaction:(CXTransaction *)transaction {
+#ifdef DEBUG
+ NSLog(@"[Callingx][requestTransaction] transaction = %@", transaction);
+#endif
+ if (self.callKeepCallController == nil) {
+ self.callKeepCallController = [[CXCallController alloc] init];
+ }
+ [self.callKeepCallController
+ requestTransaction:transaction
+ completion:^(NSError *_Nullable error) {
+ if (error != nil) {
+ NSLog(@"[Callingx][requestTransaction] Error requesting "
+ @"transaction (%@): (%@)",
+ transaction.actions, error);
+ } else {
+ NSLog(@"[Callingx][requestTransaction] Requested "
+ @"transaction successfully");
+
+ // CXStartCallAction
+ if ([[transaction.actions firstObject] isKindOfClass:[CXStartCallAction class]]) {
+ CXStartCallAction *startCallAction = [transaction.actions firstObject];
+ CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
+ callUpdate.remoteHandle = startCallAction.handle;
+ callUpdate.hasVideo = startCallAction.video;
+ callUpdate.localizedCallerName = startCallAction.contactIdentifier;
+ callUpdate.supportsDTMF = NO; //configurable?
+ callUpdate.supportsHolding = NO; //configurable?
+ callUpdate.supportsGrouping = NO; //configurable?
+ callUpdate.supportsUngrouping = NO; //configurable?
+ [self.callKeepProvider reportCallWithUUID:startCallAction.callUUID updated:callUpdate];
+ }
+ }
+ }];
+}
+
+- (void)sendEventWithNameWrapper:(NSString *)name body:(id)body {
+ NSLog(@"[Callingx] sendEventWithNameWrapper: %@", name);
+
+ NSDictionary *dictionary = [NSDictionary
+ dictionaryWithObjectsAndKeys:name, @"eventName", body, @"params", nil];
+
+ if (_isInitialized) {
+ [self emitOnNewEvent: dictionary];
+ } else {
+ [_delayedEvents addObject:dictionary];
+ }
+}
+
+- (void)onAudioRouteChange:(NSNotification *)notification {
+ NSDictionary *info = notification.userInfo;
+ NSInteger reason = [[info valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
+ NSString *output = [Callingx getAudioOutput];
+
+ if (output == nil) {
+ return;
+ }
+
+ NSDictionary *params = @{
+ @"output" : output,
+ @"reason" : @(reason),
+ };
+ NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
+ CallingxDidChangeAudioRoute, @"eventName",
+ params, @"params",
+ nil
+ ];
+ // [self emitOnNewEvent: dictionary];
+ // [self sendEventWithNameWrapper:CallingxDidChangeAudioRoute body:params];
+}
+
+- (NSString *)getIncomingCallErrorCode:(NSError *)error {
+ if ([error code] == CXErrorCodeIncomingCallErrorUnentitled) {
+ return @"Unentitled";
+ } else if ([error code] == CXErrorCodeIncomingCallErrorCallUUIDAlreadyExists) {
+ return @"CallUUIDAlreadyExists";
+ } else if ([error code] == CXErrorCodeIncomingCallErrorFilteredByDoNotDisturb) {
+ return @"FilteredByDoNotDisturb";
+ } else if ([error code] == CXErrorCodeIncomingCallErrorFilteredByBlockList) {
+ return @"FilteredByBlockList";
+ } else {
+ return @"Unknown";
+ }
+}
+
+#pragma mark - Turbo module methods
+
+- (void)setupiOS:(JS::NativeCallingx::SpecSetupiOSOptions &)options {
+ NSDictionary *optionsDict = @{
+ @"supportsVideo" : @(options.supportsVideo()),
+ @"maximumCallsPerCallGroup" : @(options.maximumCallsPerCallGroup()),
+ @"maximumCallGroups" : @(options.maximumCallGroups()),
+ @"handleType" : options.handleType(),
+ @"ringtoneSound" : options.sound(),
+ @"imageName" : options.imageName(),
+ @"includesCallsInRecents" : @(options.callsHistory()),
+ @"autoConfigureAudioSession" : @(options.setupAudioSession())
+ };
+
+ _version = [[[NSProcessInfo alloc] init] operatingSystemVersion];
+ self.callKeepCallController = [[CXCallController alloc] init];
+
+ [Settings setSettings:optionsDict];
+ [Callingx initCallKitProvider];
+ [Callingx initUUIDStorage];
+
+ self.callKeepProvider = sharedProvider;
+ [self.callKeepProvider setDelegate:nil queue:nil];
+ [self.callKeepProvider setDelegate:self queue:nil];
+
+ _isInitialized = YES;
+}
+
+- (NSArray *)getInitialEvents {
+#ifdef DEBUG
+ NSLog(@"[Callingx][getInitialEvents] _delayedEvents = %@", _delayedEvents);
+#endif
+ return _delayedEvents;
+}
+
+- (void)clearInitialEvents:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+ _delayedEvents = [NSMutableArray array];
+ resolve(@YES);
+}
+
+- (void)answerIncomingCall:(nonnull NSString *)callId
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(@"[Callingx][answerIncomingCall] callId = %@", callId);
+#endif
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ NSLog(@"[Callingx][answerIncomingCall] callId not found");
+ resolve(@NO);
+ return;
+ }
+
+ _isSelfAnswered = true;
+ CXAnswerCallAction *answerCallAction = [[CXAnswerCallAction alloc] initWithCallUUID:uuid];
+ CXTransaction *transaction = [[CXTransaction alloc] init];
+ [transaction addAction:answerCallAction];
+
+ [self requestTransaction:transaction];
+ resolve(@YES);
+}
+
+- (void)displayIncomingCall:(nonnull NSString *)callId
+ phoneNumber:(nonnull NSString *)phoneNumber
+ callerName:(nonnull NSString *)callerName
+ hasVideo:(BOOL)hasVideo
+ displayOptions:
+ (JS::NativeCallingx::SpecDisplayIncomingCallDisplayOptions &)displayOptions
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+
+ [Callingx reportNewIncomingCall:callId
+ handle:phoneNumber
+ handleType:@"number"
+ hasVideo:hasVideo
+ localizedCallerName:callerName
+ supportsHolding:NO // parametrize?
+ supportsDTMF:NO // parametrize?
+ supportsGrouping:NO // parametrize?
+ supportsUngrouping:NO // parametrize?
+ fromPushKit:NO
+ payload:nil
+ withCompletionHandler:nil];
+
+ NSDictionary *settings = [Settings getSettings];
+ NSNumber *timeout = settings[@"displayCallReachabilityTimeout"];
+
+ if (timeout) {
+ dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)([timeout intValue] * NSEC_PER_MSEC));
+ dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
+ if (!self->_isReachable) {
+#ifdef DEBUG
+ NSLog(@"[Callingx] Displayed a call without a reachable app, ending "
+ @"the call: %@",
+ callId);
+#endif
+ [Callingx endCall:callId reason:CXCallEndedReasonFailed];
+ }
+ });
+ }
+ resolve(@YES);
+}
+
+- (void)endCallWithReason:(nonnull NSString *)callId
+ reason:(double)reason
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(@"[Callingx][endCallWithReason] callId = %@ reason = %f", callId, reason);
+#endif
+ [Callingx endCall:callId reason:reason];
+ resolve(@YES);
+}
+
+- (void)endCall:(nonnull NSString *)callId
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(@"[Callingx][endCall] callId = %@", callId);
+#endif
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ NSLog(@"[Callingx][endCall] callId not found");
+ resolve(@NO);
+ return;
+ }
+
+ _isSelfEnded = true;
+ CXEndCallAction *endCallAction = [[CXEndCallAction alloc] initWithCallUUID:uuid];
+ CXTransaction *transaction = [[CXTransaction alloc] initWithAction:endCallAction];
+
+ [self requestTransaction:transaction];
+ resolve(@YES);
+}
+
+- (NSNumber *)isCallRegistered:(nonnull NSString *)callId {
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) return @NO;
+
+ CXCallObserver *observer = [[CXCallObserver alloc] init];
+ for (CXCall *call in observer.calls) {
+ if ([call.UUID isEqual:uuid]) {
+ return @YES;
+ }
+ }
+
+ return @NO;
+}
+
+- (NSNumber *)hasRegisteredCall {
+ NSArray *appUUIDs = [uuidStorage allUUIDs];
+ if ([appUUIDs count] == 0) return @NO;
+
+ CXCallObserver *observer = [[CXCallObserver alloc] init];
+
+ for (CXCall *call in observer.calls) {
+ for (NSUUID *uuid in appUUIDs) {
+ if ([call.UUID isEqual:uuid]) {
+ return @YES;
+ }
+ }
+ }
+
+ return @NO;
+}
+
+- (void)setCurrentCallActive:(nonnull NSString *)callId
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ NSLog(@"[Callingx][setCurrentCallActive] callId not found");
+ resolve(@NO);
+ return;
+ }
+
+ [self.callKeepProvider reportOutgoingCallWithUUID:uuid startedConnectingAtDate:[NSDate date]];
+ [self.callKeepProvider reportOutgoingCallWithUUID:uuid connectedAtDate:[NSDate date]];
+ resolve(@YES);
+}
+
+- (void)setMutedCall:(nonnull NSString *)callId
+ isMuted:(BOOL)isMuted
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(@"[Callingx][setMutedCall] muted = %i", isMuted);
+#endif
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ NSLog(@"[Callingx][setMutedCall] callId not found");
+ resolve(@NO);
+ return;
+ }
+
+ CXSetMutedCallAction *setMutedAction = [[CXSetMutedCallAction alloc] initWithCallUUID:uuid muted:isMuted];
+ CXTransaction *transaction = [[CXTransaction alloc] init];
+ [transaction addAction:setMutedAction];
+
+ [self requestTransaction:transaction];
+ resolve(@YES);
+}
+
+- (void)setOnHoldCall:(nonnull NSString *)callId
+ isOnHold:(BOOL)isOnHold
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(@"[Callingx][setOnHold] uuidString = %@, shouldHold = %d", callId,
+ isOnHold);
+#endif
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ NSLog(@"[Callingx][setOnHoldCall] callId not found");
+ resolve(@NO);
+ return;
+ }
+
+ CXSetHeldCallAction *setHeldCallAction = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:isOnHold];
+ CXTransaction *transaction = [[CXTransaction alloc] init];
+ [transaction addAction:setHeldCallAction];
+
+ [self requestTransaction:transaction];
+ resolve(@YES);
+}
+
+- (void)startCall:(nonnull NSString *)callId
+ phoneNumber:(nonnull NSString *)phoneNumber
+ callerName:(nonnull NSString *)callerName
+ hasVideo:(BOOL)hasVideo
+ displayOptions:(JS::NativeCallingx::SpecStartCallDisplayOptions &)displayOptions
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(@"[Callingx][startCall] uuidString = %@", callId, phoneNumber);
+#endif
+ CXHandleType _handleType = [Settings getHandleType:@"generic"];
+ NSUUID *uuid = [uuidStorage getOrCreateUUIDForCid:callId];
+ CXHandle *callHandle = [[CXHandle alloc] initWithType:_handleType value:phoneNumber];
+ CXStartCallAction *startCallAction = [[CXStartCallAction alloc] initWithCallUUID:uuid handle:callHandle];
+ [startCallAction setVideo:hasVideo];
+ [startCallAction setContactIdentifier:callerName];
+
+ CXTransaction *transaction = [[CXTransaction alloc] initWithAction:startCallAction];
+
+ [self requestTransaction:transaction];
+}
+
+- (void)updateDisplay:(nonnull NSString *)callId
+ phoneNumber:(nonnull NSString *)phoneNumber
+ callerName:(nonnull NSString *)callerName
+ displayOptions:
+ (JS::NativeCallingx::SpecUpdateDisplayDisplayOptions &)displayOptions
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
+ reject:(nonnull RCTPromiseRejectBlock)reject {
+#ifdef DEBUG
+ NSLog(
+ @"[Callingx][updateDisplay] uuidString = %@ displayName = %@ uri = %@",
+ callId, callerName, phoneNumber);
+#endif
+ NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
+ if (uuid == nil) {
+ return;
+ }
+
+ CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:phoneNumber];
+ CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
+ callUpdate.localizedCallerName = callerName;
+ callUpdate.remoteHandle = callHandle;
+
+ // if ([options valueForKey:@"hasVideo"] != nil) {
+ // callUpdate.hasVideo = [RCTConvert BOOL:options[@"hasVideo"]];
+ // }
+ // if ([options valueForKey:@"supportsHolding"] != nil) {
+ // callUpdate.supportsHolding = [RCTConvert
+ // BOOL:options[@"supportsHolding"]];
+ // }
+ // if ([options valueForKey:@"supportsDTMF"] != nil) {
+ // callUpdate.supportsDTMF = [RCTConvert
+ // BOOL:options[@"supportsDTMF"]];
+ // }
+ // if ([options valueForKey:@"supportsGrouping"] != nil) {
+ // callUpdate.supportsGrouping = [RCTConvert
+ // BOOL:options[@"supportsGrouping"]];
+ // }
+ // if ([options valueForKey:@"supportsUngrouping"] != nil) {
+ // callUpdate.supportsUngrouping = [RCTConvert
+ // BOOL:options[@"supportsUngrouping"]];
+ // }
+
+ [self.callKeepProvider reportCallWithUUID:uuid updated:callUpdate];
+ resolve(@YES);
+}
+
+- (void)log:(NSString *)message level:(NSString *)level {
+ NSLog(@"[Callingx][log] %@, %@", message, level);
+}
+
+- (void)setupAndroid:(JS::NativeCallingx::SpecSetupAndroidOptions &)options {
+ // leave empty
+}
+
+- (void)startBackgroundTask:(NSString *)taskName
+ timeout:(double)timeout
+ resolve:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject {
+ // leave empty
+ resolve(@YES);
+}
+
+- (void)stopBackgroundTask:(NSString *)taskName
+ resolve:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject {
+ // leave empty
+ resolve(@YES);
+}
+
+- (nonnull NSNumber *)canPostNotifications {
+ return @YES;
+}
+
+
+#pragma mark - CXProviderDelegate
+
+- (void)providerDidReset:(CXProvider *)provider {
+#ifdef DEBUG
+ NSLog(@"[Callingx][providerDidReset]");
+#endif
+ // this means something big changed, so tell the JS. The JS should
+ // probably respond by hanging up all calls.
+ [self sendEventWithNameWrapper:CallingxProviderReset body:nil];
+}
+
+- (void)provider:(CXProvider *)provider
+ performStartCallAction:(CXStartCallAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performStartCallAction]");
+#endif
+ NSString *callId = [uuidStorage getCidForUUID:action.callUUID];
+ if (callId == nil) {
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performStartCallAction] callId not found");
+ return;
+ }
+ // do this first, audio sessions are flakey
+ [AudioSessionManager createAudioSessionIfNeeded];
+ // tell the JS to actually make the call
+ [self sendEventWithNameWrapper:CallingxDidReceiveStartCallAction
+ body:@{
+ @"callId" : callId,
+ @"handle" : action.handle.value
+ }];
+ [action fulfill];
+}
+
+// Update call contact info
+// @deprecated
+// RCT_EXPORT_METHOD(reportUpdatedCall : (NSString *)uuidString contactIdentifier : (NSString *)contactIdentifier) {
+// #ifdef DEBUG
+// NSLog(@"[deprecated][Callingx][reportUpdatedCall] contactIdentifier = %@",
+// contactIdentifier);
+// #endif
+// NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidString];
+// CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
+// callUpdate.localizedCallerName = contactIdentifier;
+
+// [self.callKeepProvider reportCallWithUUID:uuid updated:callUpdate];
+// }
+
+- (void)provider:(CXProvider *)provider
+ performAnswerCallAction:(CXAnswerCallAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performAnswerCallAction] isSelfAnswered: %d", _isSelfAnswered);
+#endif
+ NSString *callId = [uuidStorage getCidForUUID:action.callUUID];
+ if (callId == nil) {
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performAnswerCallAction] callId not found");
+ [action fail];
+ return;
+ }
+
+ [AudioSessionManager createAudioSessionIfNeeded];
+
+ NSString *source = _isSelfAnswered ? @"app" : @"sys";
+ [self sendEventWithNameWrapper:CallingxPerformAnswerCallAction
+ body:@{
+ @"callId" : callId,
+ @"source" : source
+ }];
+ _isSelfAnswered = false;
+ [action fulfill];
+}
+
+- (void)provider:(CXProvider *)provider
+ performEndCallAction:(CXEndCallAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performEndCallAction] isSelfEnded: %d", _isSelfEnded);
+#endif
+ NSString *callId = [uuidStorage getCidForUUID:action.callUUID];
+ if (callId == nil) {
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performEndCallAction] callId not found");
+ [action fail];
+ return;
+ }
+
+ NSString *source = _isSelfEnded ? @"app" : @"sys";
+ [self sendEventWithNameWrapper:CallingxPerformEndCallAction
+ body:@{
+ @"callId" : callId,
+ @"source" : source
+ }];
+ _isSelfEnded = false;
+ [uuidStorage removeCid:callId];
+ [action fulfill];
+}
+
+- (void)provider:(CXProvider *)provider
+ performSetHeldCallAction:(CXSetHeldCallAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performSetHeldCallAction]");
+#endif
+ NSString *callId = [uuidStorage getCidForUUID:action.callUUID];
+ if (callId == nil) {
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performSetHeldCallAction] callId not found");
+ [action fail];
+ return;
+ }
+
+ [self sendEventWithNameWrapper:CallingxDidToggleHoldAction
+ body:@{
+ @"hold" : @(action.onHold),
+ @"callId" : callId
+ }];
+ [action fulfill];
+}
+
+- (void)provider:(CXProvider *)provider
+ performPlayDTMFCallAction:(CXPlayDTMFCallAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performPlayDTMFCallAction]");
+#endif
+ NSString *callId = [uuidStorage getCidForUUID:action.callUUID];
+ if (callId == nil) {
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performPlayDTMFCallAction] callId not found");
+ [action fail];
+ return;
+ }
+
+ [self sendEventWithNameWrapper:CallingxPerformPlayDTMFCallAction
+ body:@{
+ @"digits" : action.digits,
+ @"callId" : callId
+ }];
+ [action fulfill];
+}
+
+- (void)provider:(CXProvider *)provider
+ performSetMutedCallAction:(CXSetMutedCallAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performSetMutedCallAction]");
+#endif
+ NSString *callId = [uuidStorage getCidForUUID:action.callUUID];
+ if (callId == nil) {
+ NSLog(@"[Callingx][CXProviderDelegate][provider:performSetMutedCallAction] callId not found");
+ [action fail];
+ return;
+ }
+
+ [self sendEventWithNameWrapper:CallingxDidPerformSetMutedCallAction
+ body:@{
+ @"muted" : @(action.muted),
+ @"callId" : callId
+ }];
+ [action fulfill];
+}
+
+- (void)provider:(CXProvider *)provider
+ timedOutPerformingAction:(CXAction *)action {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:timedOutPerformingAction]");
+#endif
+}
+
+- (void)provider:(CXProvider *)provider
+ didActivateAudioSession:(AVAudioSession *)audioSession {
+#ifdef DEBUG
+ NSLog(@"[Callingx][CXProviderDelegate][provider:didActivateAudioSession]");
+#endif
+ NSDictionary *userInfo = @{
+ AVAudioSessionInterruptionTypeKey :
+ [NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded],
+ AVAudioSessionInterruptionOptionKey :
+ [NSNumber numberWithInt:AVAudioSessionInterruptionOptionShouldResume]
+ };
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:AVAudioSessionInterruptionNotification
+ object:nil
+ userInfo:userInfo];
+
+ [self sendEventWithNameWrapper:CallingxDidActivateAudioSession body:nil];
+}
+
+- (void)provider:(CXProvider *)provider
+ didDeactivateAudioSession:(AVAudioSession *)audioSession {
+#ifdef DEBUG
+ NSLog(
+ @"[Callingx][CXProviderDelegate][provider:didDeactivateAudioSession]");
+#endif
+ [self sendEventWithNameWrapper:CallingxDidDeactivateAudioSession body:nil];
+}
+
+@end
diff --git a/packages/react-native-callingx/ios/CallingxPublic.h b/packages/react-native-callingx/ios/CallingxPublic.h
new file mode 100644
index 0000000000..f5b617f1e9
--- /dev/null
+++ b/packages/react-native-callingx/ios/CallingxPublic.h
@@ -0,0 +1,34 @@
+#import
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface Callingx : NSObject
+
+//+ (BOOL)application:(UIApplication *)application
+// openURL:(NSURL *)url
+// options:(NSDictionary *)options NS_AVAILABLE_IOS(9_0);
+//
+//+ (BOOL)application:(UIApplication *)application
+//continueUserActivity:(NSUserActivity *)userActivity
+// restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler;
+
++ (void)reportNewIncomingCall:(NSString *)uuidString
+ handle:(NSString *)handle
+ handleType:(NSString *)handleType
+ hasVideo:(BOOL)hasVideo
+ localizedCallerName:(NSString * _Nullable)localizedCallerName
+ supportsHolding:(BOOL)supportsHolding
+ supportsDTMF:(BOOL)supportsDTMF
+ supportsGrouping:(BOOL)supportsGrouping
+ supportsUngrouping:(BOOL)supportsUngrouping
+ fromPushKit:(BOOL)fromPushKit
+ payload:(NSDictionary * _Nullable)payload
+ withCompletionHandler:(void (^_Nullable)(void))completion;
+
++ (void)endCall:(NSString *)callId
+ reason:(int)reason;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/packages/react-native-callingx/ios/Settings.h b/packages/react-native-callingx/ios/Settings.h
new file mode 100644
index 0000000000..be642e6d8c
--- /dev/null
+++ b/packages/react-native-callingx/ios/Settings.h
@@ -0,0 +1,17 @@
+#import
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface Settings : NSObject
+
++ (NSDictionary *)getSettings;
++ (void)setSettings:(NSDictionary *)options;
++ (BOOL)getAutoConfigureAudioSession;
++ (CXProviderConfiguration *)getProviderConfiguration:(NSDictionary *)settings;
++ (NSSet *)getSupportedHandleTypes:(id)handleType;
++ (CXHandleType)getHandleType:(NSString *)handleType;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/packages/react-native-callingx/ios/Settings.mm b/packages/react-native-callingx/ios/Settings.mm
new file mode 100644
index 0000000000..b573abae09
--- /dev/null
+++ b/packages/react-native-callingx/ios/Settings.mm
@@ -0,0 +1,97 @@
+#import "Settings.h"
+#import
+
+@implementation Settings
+
++ (NSDictionary *)getSettings {
+ return [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"CallingxSettings"];
+}
+
++ (void)setSettings:(NSDictionary *)options {
+#ifdef DEBUG
+ NSLog(@"[Settings][setSettings] options = %@", options);
+#endif
+ NSDictionary *settings = [[NSMutableDictionary alloc] initWithDictionary:options];
+ // Store settings in NSUserDefault
+ [[NSUserDefaults standardUserDefaults] setObject:settings forKey:@"CallingxSettings"];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+}
+
++ (BOOL)getAutoConfigureAudioSession {
+ NSDictionary *settings = [Settings getSettings];
+ if (settings && settings[@"autoConfigureAudioSession"]) {
+ return [settings[@"autoConfigureAudioSession"] boolValue];
+ }
+ return NO;
+}
+
++ (CXProviderConfiguration *)getProviderConfiguration:(NSDictionary *)settings {
+#ifdef DEBUG
+ NSLog(@"[Settings][getProviderConfiguration]");
+#endif
+ CXProviderConfiguration *providerConfiguration = [[CXProviderConfiguration alloc] init];
+ providerConfiguration.supportsVideo = YES;
+ providerConfiguration.maximumCallGroups = 1;
+ providerConfiguration.maximumCallsPerCallGroup = 1;
+ providerConfiguration.supportedHandleTypes = [Settings getSupportedHandleTypes:settings[@"handleType"]];
+
+ if (settings[@"supportsVideo"]) {
+ providerConfiguration.supportsVideo = [settings[@"supportsVideo"] boolValue];
+ }
+ if (settings[@"maximumCallGroups"]) {
+ providerConfiguration.maximumCallGroups = [settings[@"maximumCallGroups"] integerValue];
+ }
+ if (settings[@"maximumCallsPerCallGroup"]) {
+ providerConfiguration.maximumCallsPerCallGroup = [settings[@"maximumCallsPerCallGroup"] integerValue];
+ }
+ NSString *imageName = settings[@"imageName"];
+ if ([imageName isKindOfClass:[NSString class]] && imageName.length > 0) {
+ providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation([UIImage imageNamed:imageName]);
+ }
+ NSString *ringtoneSound = settings[@"ringtoneSound"];
+ if ([ringtoneSound isKindOfClass:[NSString class]] && ringtoneSound.length > 0) {
+ providerConfiguration.ringtoneSound = ringtoneSound;
+ }
+ if (@available(iOS 11.0, *)) {
+ if (settings[@"includesCallsInRecents"]) {
+ providerConfiguration.includesCallsInRecents = [settings[@"includesCallsInRecents"] boolValue];
+ }
+ }
+ return providerConfiguration;
+}
+
++ (NSSet *)getSupportedHandleTypes:(id)handleType {
+ if (handleType) {
+ if ([handleType isKindOfClass:[NSArray class]]) {
+ NSSet *types = [NSSet set];
+
+ for (NSString *type in handleType) {
+ types = [types setByAddingObject: [NSNumber numberWithInteger:[Settings getHandleType:type]]];
+ }
+
+ return types;
+ } else {
+ CXHandleType _handleType = [Settings getHandleType:handleType];
+
+ return [NSSet setWithObjects:[NSNumber numberWithInteger:_handleType], nil];
+ }
+ } else {
+ return [NSSet setWithObjects:[NSNumber numberWithInteger:CXHandleTypePhoneNumber], nil];
+ }
+}
+
++ (CXHandleType)getHandleType:(NSString *)handleType {
+ if ([handleType isEqualToString:@"generic"]) {
+ return CXHandleTypeGeneric;
+ } else if ([handleType isEqualToString:@"number"]) {
+ return CXHandleTypePhoneNumber;
+ } else if ([handleType isEqualToString:@"phone"]) {
+ return CXHandleTypePhoneNumber;
+ } else if ([handleType isEqualToString:@"email"]) {
+ return CXHandleTypeEmailAddress;
+ } else {
+ return CXHandleTypeGeneric;
+ }
+}
+
+@end
diff --git a/packages/react-native-callingx/ios/UUIDStorage.h b/packages/react-native-callingx/ios/UUIDStorage.h
new file mode 100644
index 0000000000..7b128a08f2
--- /dev/null
+++ b/packages/react-native-callingx/ios/UUIDStorage.h
@@ -0,0 +1,17 @@
+#import
+
+@interface UUIDStorage : NSObject
+
+- (instancetype)init;
+- (NSArray *)allUUIDs;
+- (NSUUID *)getOrCreateUUIDForCid:(NSString *)cid;
+- (NSUUID *)getUUIDForCid:(NSString *)cid;
+- (NSString *)getCidForUUID:(NSUUID *)uuid;
+- (void)removeCidForUUID:(NSUUID *)uuid;
+- (void)removeCid:(NSString *)cid;
+- (void)removeAllObjects;
+- (NSUInteger)count;
+- (BOOL)containsCid:(NSString *)cid;
+- (BOOL)containsUUID:(NSUUID *)uuid;
+
+@end
\ No newline at end of file
diff --git a/packages/react-native-callingx/ios/UUIDStorage.mm b/packages/react-native-callingx/ios/UUIDStorage.mm
new file mode 100644
index 0000000000..cb96d6c35f
--- /dev/null
+++ b/packages/react-native-callingx/ios/UUIDStorage.mm
@@ -0,0 +1,119 @@
+#import "UUIDStorage.h"
+
+@interface UUIDStorage ()
+@property (nonatomic, strong) NSMutableDictionary *uuidDict;
+@property (nonatomic, strong) NSMutableDictionary *cidDict;
+@end
+
+@implementation UUIDStorage
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _uuidDict = [[NSMutableDictionary alloc] init];
+ _cidDict = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (NSArray *)allUUIDs {
+ NSMutableArray *uuids = [NSMutableArray array];
+ for (NSString *uuidString in self.uuidDict.allValues) {
+ [uuids addObject:[[NSUUID alloc] initWithUUIDString:uuidString.lowercaseString]];
+ }
+ return uuids;
+}
+
+- (NSUUID *)getOrCreateUUIDForCid:(NSString *)cid {
+ if ([self containsCid:cid]) {
+ NSString *existingUUID = self.uuidDict[cid];
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] getUUIDForCid: found existing UUID %@ for cid %@", existingUUID, cid);
+#endif
+ return [[NSUUID alloc] initWithUUIDString:existingUUID];
+ }
+
+ NSUUID *uuid = [NSUUID UUID];
+ NSString *uuidString = [uuid.UUIDString lowercaseString];
+ self.uuidDict[cid] = uuidString;
+ self.cidDict[uuidString] = cid;
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] getUUIDForCid: created new UUID %@ for cid %@", uuidString, cid);
+#endif
+ return uuid;
+}
+
+- (NSUUID *)getUUIDForCid:(NSString *)cid {
+ NSString *uuidString = self.uuidDict[cid];
+ if (uuidString) {
+ return [[NSUUID alloc] initWithUUIDString:uuidString];
+ }
+ return nil;
+}
+
+- (NSString *)getCidForUUID:(NSUUID *)uuid {
+ NSString *uuidString = [uuid.UUIDString lowercaseString];
+ NSString *cid = self.cidDict[uuidString];
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] getCidForUUID: UUID %@ -> cid %@", uuidString, cid ?: @"(not found)");
+#endif
+ return cid;
+}
+
+- (void)removeCidForUUID:(NSUUID *)uuid {
+ NSString *uuidString = [uuid.UUIDString lowercaseString];
+ NSString *cid = self.cidDict[uuidString];
+ if (cid) {
+ [self.uuidDict removeObjectForKey:cid];
+ [self.cidDict removeObjectForKey:uuidString];
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] removeCidForUUID: removed cid %@ for UUID %@", cid, uuidString);
+#endif
+ } else {
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] removeCidForUUID: no cid found for UUID %@", uuidString);
+#endif
+ }
+}
+
+- (void)removeCid:(NSString *)cid {
+ NSString *uuidString = self.uuidDict[cid];
+ if (uuidString) {
+ [self.cidDict removeObjectForKey:uuidString];
+ [self.uuidDict removeObjectForKey:cid];
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] removeCid: removed cid %@ with UUID %@", cid, uuidString);
+#endif
+ } else {
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] removeCid: no UUID found for cid %@", cid);
+#endif
+ }
+}
+
+- (void)removeAllObjects {
+ NSUInteger count = [self.uuidDict count];
+ [self.uuidDict removeAllObjects];
+ [self.cidDict removeAllObjects];
+#ifdef DEBUG
+ NSLog(@"[UUIDStorage] removeAllObjects: cleared %lu entries", (unsigned long)count);
+#endif
+}
+
+- (NSUInteger)count {
+ return [self.uuidDict count];
+}
+
+- (BOOL)containsCid:(NSString *)cid {
+ return self.uuidDict[cid] != nil;
+}
+
+- (BOOL)containsUUID:(NSUUID *)uuid {
+ return self.cidDict[[uuid.UUIDString lowercaseString]] != nil;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"UUIDStorage: %@", self.uuidDict];
+}
+
+@end
diff --git a/packages/react-native-callingx/lefthook.yml b/packages/react-native-callingx/lefthook.yml
new file mode 100644
index 0000000000..003bcde2c3
--- /dev/null
+++ b/packages/react-native-callingx/lefthook.yml
@@ -0,0 +1,16 @@
+pre-commit:
+ parallel: true
+ commands:
+
+ lint:
+ glob: "*.{js,ts,jsx,tsx}"
+ run: npx eslint {staged_files}
+
+ types:
+ glob: "*.{js,ts, jsx, tsx}"
+ run: npx tsc
+commit-msg:
+ parallel: true
+ commands:
+ commitlint:
+ run: npx commitlint --edit
diff --git a/packages/react-native-callingx/package.json b/packages/react-native-callingx/package.json
new file mode 100644
index 0000000000..37350e431b
--- /dev/null
+++ b/packages/react-native-callingx/package.json
@@ -0,0 +1,170 @@
+{
+ "name": "react-native-callingx",
+ "version": "0.1.0",
+ "description": "test",
+ "main": "./dist/module/index.js",
+ "types": "./dist/typescript/src/index.d.ts",
+ "exports": {
+ ".": {
+ "source": "./src/index.tsx",
+ "types": "./dist/typescript/src/index.d.ts",
+ "default": "./dist/module/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "files": [
+ "src",
+ "dist",
+ "android",
+ "ios",
+ "cpp",
+ "*.podspec",
+ "react-native.config.js",
+ "!ios/build",
+ "!android/build",
+ "!android/gradle",
+ "!android/gradlew",
+ "!android/gradlew.bat",
+ "!android/local.properties",
+ "!**/__tests__",
+ "!**/__fixtures__",
+ "!**/__mocks__",
+ "!**/.*"
+ ],
+ "scripts": {
+ "example": "yarn workspace react-native-callingx-example",
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build dist",
+ "prepare": "bob build",
+ "build": "bob build",
+ "typecheck": "tsc",
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
+ "release": "release-it --only-version",
+ "test": "jest"
+ },
+ "keywords": [
+ "react-native",
+ "ios",
+ "android"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/GetStream/stream-video-js.git"
+ },
+ "author": "https://getstream.io (https://github.com/GetStream)",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/GetStream/stream-video-js/issues"
+ },
+ "homepage": "https://github.com/GetStream/stream-video-js#readme",
+ "publishConfig": {
+ "registry": "https://registry.npmjs.org/"
+ },
+ "devDependencies": {
+ "@commitlint/config-conventional": "^19.8.1",
+ "@eslint/compat": "^1.3.2",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "^9.35.0",
+ "@react-native-community/cli": "20.0.1",
+ "@react-native/babel-preset": "0.81.1",
+ "@react-native/eslint-config": "^0.81.1",
+ "@release-it/conventional-changelog": "^10.0.1",
+ "@types/jest": "^29.5.14",
+ "@types/react": "^19.1.0",
+ "commitlint": "^19.8.1",
+ "del-cli": "^6.0.0",
+ "eslint": "^9.35.0",
+ "eslint-config-prettier": "^10.1.8",
+ "eslint-plugin-prettier": "^5.5.4",
+ "jest": "^29.7.0",
+ "lefthook": "^2.0.3",
+ "prettier": "^3.4.2",
+ "react": "19.1.0",
+ "react-native": "0.81.1",
+ "react-native-builder-bob": "^0.40.15",
+ "release-it": "^19.0.4",
+ "turbo": "^2.5.6",
+ "typescript": "^5.9.2"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ },
+ "react-native-builder-bob": {
+ "source": "src",
+ "output": "dist",
+ "targets": [
+ [
+ "module",
+ {
+ "esm": true
+ }
+ ],
+ [
+ "typescript",
+ {
+ "project": "tsconfig.build.json"
+ }
+ ]
+ ]
+ },
+ "codegenConfig": {
+ "name": "CallingxSpec",
+ "type": "modules",
+ "jsSrcsDir": "src/spec",
+ "android": {
+ "javaPackageName": "com.callingx"
+ },
+ "ios": {
+ "moduleName": "Callingx"
+ }
+ },
+ "prettier": {
+ "quoteProps": "consistent",
+ "singleQuote": true,
+ "tabWidth": 2,
+ "trailingComma": "es5",
+ "useTabs": false
+ },
+ "commitlint": {
+ "extends": [
+ "@commitlint/config-conventional"
+ ]
+ },
+ "release-it": {
+ "git": {
+ "commitMessage": "chore: release ${version}",
+ "tagName": "v${version}"
+ },
+ "npm": {
+ "publish": true
+ },
+ "github": {
+ "release": true
+ },
+ "plugins": {
+ "@release-it/conventional-changelog": {
+ "preset": {
+ "name": "angular"
+ }
+ }
+ }
+ },
+ "jest": {
+ "preset": "react-native",
+ "modulePathIgnorePatterns": [
+ "/example/node_modules",
+ "/dist/"
+ ]
+ },
+ "create-react-native-library": {
+ "languages": "kotlin-objc",
+ "type": "turbo-module",
+ "tools": [
+ "eslint",
+ "lefthook",
+ "release-it",
+ "jest"
+ ],
+ "version": "0.55.0"
+ }
+}
diff --git a/packages/react-native-callingx/react-native.config.js b/packages/react-native-callingx/react-native.config.js
new file mode 100644
index 0000000000..21b3b68dd7
--- /dev/null
+++ b/packages/react-native-callingx/react-native.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+ dependency: {
+ platforms: {
+ android: {},
+ ios: {},
+ },
+ },
+};
diff --git a/packages/react-native-callingx/src/CallingxModule.ts b/packages/react-native-callingx/src/CallingxModule.ts
new file mode 100644
index 0000000000..e33b0fe27d
--- /dev/null
+++ b/packages/react-native-callingx/src/CallingxModule.ts
@@ -0,0 +1,254 @@
+import { Platform } from 'react-native';
+import NativeCallingModule from './spec/NativeCallingx';
+import {
+ checkCallPermissions,
+ requestCallPermissions,
+} from './utils/permissions';
+import type { PermissionsResult } from './utils/permissions';
+import {
+ HEADLESS_TASK_NAME,
+ registerHeadlessTask,
+ setHeadlessTask,
+} from './utils/headlessTask';
+import type { ManagableTask } from './utils/headlessTask';
+import { EventManager } from './EventManager';
+import type { EventListener, EventName, EventParams } from './EventManager';
+import {
+ type ICallingxModule,
+ type InfoDisplayOptions,
+ type TextTransformer,
+ type EndCallReason,
+ type EventData,
+ type Options,
+} from './types';
+import {
+ androidEndCallReasonMap,
+ defaultAndroidOptions,
+ defaultiOSOptions,
+ defaultTextTransformer,
+ iosEndCallReasonMap,
+} from './utils/constants';
+
+class CallingxModule implements ICallingxModule {
+ private _isNotificationsAllowed = false;
+ private _isOutcomingCallsEnabled = false;
+
+ private titleTransformer: TextTransformer = (text: string) => text;
+ private subtitleTransformer: TextTransformer | undefined = undefined;
+
+ private eventManager: EventManager = new EventManager();
+
+ get isOutcomingCallsEnabled(): boolean {
+ return this._isOutcomingCallsEnabled;
+ }
+
+ get isNotificationsAllowed(): boolean {
+ if (Platform.OS !== 'android') {
+ return true;
+ }
+
+ return (
+ this._isNotificationsAllowed && NativeCallingModule.canPostNotifications()
+ );
+ }
+
+ setup(options: Options): void {
+ this._isOutcomingCallsEnabled = options.enableOutcomingCalls ?? false;
+
+ if (Platform.OS === 'ios') {
+ NativeCallingModule.setupiOS({ ...defaultiOSOptions, ...options.ios });
+ }
+
+ if (Platform.OS === 'android') {
+ const {
+ titleTransformer,
+ subtitleTransformer,
+ incomingChannel,
+ outgoingChannel,
+ } = options.android ?? {};
+
+ this.titleTransformer = titleTransformer ?? defaultTextTransformer;
+ this.subtitleTransformer = subtitleTransformer;
+
+ const notificationsConfig = {
+ incomingChannel: {
+ ...defaultAndroidOptions.incomingChannel,
+ ...(incomingChannel ?? {}),
+ },
+ outgoingChannel: {
+ ...defaultAndroidOptions.outgoingChannel,
+ ...(outgoingChannel ?? {}),
+ },
+ };
+ NativeCallingModule.setupAndroid(notificationsConfig);
+
+ registerHeadlessTask();
+ }
+
+ //by default we will request permissions on setup call
+ if (options.enableAutoPermissions ?? true) {
+ this.requestPermissions()
+ .then((result) => {
+ console.log('Permissions result:', result);
+ })
+ .catch((error) => {
+ console.error('Error requesting permissions:', error);
+ });
+ }
+ }
+
+ async requestPermissions(): Promise {
+ const result: {
+ recordAudio: boolean;
+ postNotifications: boolean;
+ } = await requestCallPermissions();
+
+ this._isNotificationsAllowed = result.postNotifications;
+ return result;
+ }
+
+ async checkPermissions(): Promise {
+ const result: {
+ recordAudio: boolean;
+ postNotifications: boolean;
+ } = await checkCallPermissions();
+
+ this._isNotificationsAllowed = result.postNotifications;
+ return result;
+ }
+
+ getInitialEvents(): EventData[] {
+ return NativeCallingModule.getInitialEvents() as EventData[];
+ }
+
+ clearInitialEvents(): Promise {
+ return NativeCallingModule.clearInitialEvents();
+ }
+
+ //activates call that was registered with the telecom stack
+ setCurrentCallActive(callId: string): Promise {
+ return NativeCallingModule.setCurrentCallActive(callId);
+ }
+
+ displayIncomingCall(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ hasVideo: boolean
+ ): Promise {
+ const displayOptions: InfoDisplayOptions = {
+ displayTitle: this.titleTransformer(callerName, true),
+ displaySubtitle: this.subtitleTransformer?.(phoneNumber, true),
+ };
+ return NativeCallingModule.displayIncomingCall(
+ callId,
+ phoneNumber,
+ callerName,
+ hasVideo,
+ displayOptions
+ );
+ }
+
+ answerIncomingCall(callId: string): Promise {
+ return NativeCallingModule.answerIncomingCall(callId);
+ }
+
+ //registers call with the telecom stack
+ startCall(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ hasVideo: boolean
+ ): Promise {
+ const displayOptions: InfoDisplayOptions = {
+ displayTitle: this.titleTransformer(callerName, false),
+ displaySubtitle: this.subtitleTransformer?.(phoneNumber, false),
+ };
+ return NativeCallingModule.startCall(
+ callId,
+ phoneNumber,
+ callerName,
+ hasVideo,
+ displayOptions
+ );
+ }
+
+ updateDisplay(
+ callId: string,
+ phoneNumber: string,
+ callerName: string
+ ): Promise {
+ const displayOptions: InfoDisplayOptions = {
+ displayTitle: this.titleTransformer(callerName, false),
+ displaySubtitle: this.subtitleTransformer?.(phoneNumber, false),
+ };
+ return NativeCallingModule.updateDisplay(
+ callId,
+ phoneNumber,
+ callerName,
+ displayOptions
+ );
+ }
+
+ endCallWithReason(callId: string, reason: EndCallReason): Promise {
+ const reasons =
+ Platform.OS === 'ios' ? iosEndCallReasonMap : androidEndCallReasonMap;
+
+ if (Platform.OS === 'ios' && reason === 'local') {
+ return NativeCallingModule.endCall(callId);
+ }
+
+ return NativeCallingModule.endCallWithReason(callId, reasons[reason]);
+ }
+
+ isCallRegistered(callId: string): boolean {
+ return NativeCallingModule.isCallRegistered(callId);
+ }
+
+ hasRegisteredCall(): boolean {
+ return NativeCallingModule.hasRegisteredCall();
+ }
+
+ setMutedCall(callId: string, isMuted: boolean): Promise {
+ return NativeCallingModule.setMutedCall(callId, isMuted);
+ }
+
+ setOnHoldCall(callId: string, isOnHold: boolean): Promise {
+ return NativeCallingModule.setOnHoldCall(callId, isOnHold);
+ }
+
+ startBackgroundTask(taskProvider: ManagableTask): Promise {
+ const stopTask = () => {
+ NativeCallingModule.log(`stopBackgroundTask`, 'warn');
+ NativeCallingModule.stopBackgroundTask(HEADLESS_TASK_NAME);
+ };
+
+ setHeadlessTask((taskData: any) => taskProvider(taskData, stopTask));
+
+ return NativeCallingModule.startBackgroundTask(HEADLESS_TASK_NAME, 0);
+ }
+
+ stopBackgroundTask(): Promise {
+ return NativeCallingModule.stopBackgroundTask(HEADLESS_TASK_NAME);
+ }
+
+ addEventListener(
+ eventName: T,
+ callback: EventListener
+ ): { remove: () => void } {
+ this.eventManager.addListener(eventName, callback);
+
+ return {
+ remove: () => {
+ this.eventManager.removeListener(eventName, callback);
+ },
+ };
+ }
+
+ log(message: string, level: 'debug' | 'info' | 'warn' | 'error'): void {
+ NativeCallingModule.log(message, level);
+ }
+}
+
+const module = new CallingxModule();
+export default module;
diff --git a/packages/react-native-callingx/src/EventManager.ts b/packages/react-native-callingx/src/EventManager.ts
new file mode 100644
index 0000000000..73fdac17f8
--- /dev/null
+++ b/packages/react-native-callingx/src/EventManager.ts
@@ -0,0 +1,56 @@
+import type { EventSubscription } from 'react-native';
+import NativeCallingModule from './spec/NativeCallingx';
+import type { EventData, EventName, EventParams } from './types';
+
+type EventListener = (params: T) => void;
+
+class EventManager {
+ private listenersCount: number = 0;
+ private eventListeners: Map<
+ EventName,
+ EventListener[]
+ > = new Map();
+ private subscription: EventSubscription | null = null;
+
+ addListener(
+ eventName: T,
+ callback: EventListener
+ ): void {
+ const listeners = this.eventListeners.get(eventName) || [];
+ listeners.push(callback as EventListener);
+ this.eventListeners.set(eventName, listeners);
+
+ this.listenersCount++;
+
+ if (this.subscription === null) {
+ this.subscription = NativeCallingModule.onNewEvent((event: EventData) => {
+ console.log('[callingx] NativeCallingModule.onNewEvent', event);
+ const eventListeners =
+ this.eventListeners.get(event.eventName as EventName) || [];
+ eventListeners.forEach((listener) =>
+ listener(event.params as EventParams[EventName])
+ );
+ });
+ }
+ }
+
+ removeListener(
+ eventName: T,
+ callback: EventListener
+ ): void {
+ const listeners = this.eventListeners.get(eventName) || [];
+ this.eventListeners.set(
+ eventName,
+ listeners.filter((c) => c !== callback)
+ );
+
+ this.listenersCount--;
+
+ if (this.listenersCount === 0) {
+ this.subscription?.remove();
+ this.subscription = null;
+ }
+ }
+}
+
+export { EventManager, type EventName, type EventParams, type EventListener };
diff --git a/packages/react-native-callingx/src/__tests__/index.test.tsx b/packages/react-native-callingx/src/__tests__/index.test.tsx
new file mode 100644
index 0000000000..bf84291a5e
--- /dev/null
+++ b/packages/react-native-callingx/src/__tests__/index.test.tsx
@@ -0,0 +1 @@
+it.todo('write a test');
diff --git a/packages/react-native-callingx/src/index.tsx b/packages/react-native-callingx/src/index.tsx
new file mode 100644
index 0000000000..0381bf9540
--- /dev/null
+++ b/packages/react-native-callingx/src/index.tsx
@@ -0,0 +1,2 @@
+export { default as CallingxModule } from './CallingxModule';
+export * from './types';
diff --git a/packages/react-native-callingx/src/spec/NativeCallingx.ts b/packages/react-native-callingx/src/spec/NativeCallingx.ts
new file mode 100644
index 0000000000..d39af3cef8
--- /dev/null
+++ b/packages/react-native-callingx/src/spec/NativeCallingx.ts
@@ -0,0 +1,112 @@
+import { TurboModuleRegistry, type TurboModule } from 'react-native';
+
+// @ts-expect-error - CodegenTypes is not properly typed
+import type { EventEmitter } from 'react-native/Libraries/Types/CodegenTypes';
+
+export interface Spec extends TurboModule {
+ setupiOS(options: {
+ supportsVideo: boolean;
+ maximumCallsPerCallGroup: number;
+ maximumCallGroups: number;
+ handleType: string;
+ sound: string | null;
+ imageName: string | null;
+ callsHistory: boolean;
+ setupAudioSession: boolean;
+ }): void;
+
+ setupAndroid(options: {
+ incomingChannel: {
+ id: string;
+ name: string;
+ sound: string;
+ vibration: boolean;
+ };
+ outgoingChannel: {
+ id: string;
+ name: string;
+ };
+ }): void;
+
+ canPostNotifications(): boolean;
+
+ getInitialEvents(): Array<{
+ eventName: string;
+ params: {
+ callId: string;
+ cause?: string;
+ muted?: boolean;
+ hold?: boolean;
+ source?: string;
+ };
+ }>;
+
+ clearInitialEvents(): Promise;
+
+ setCurrentCallActive(callId: string): Promise;
+
+ displayIncomingCall(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ hasVideo: boolean,
+ displayOptions?: {
+ displayTitle?: string;
+ displaySubtitle?: string;
+ }
+ ): Promise;
+
+ //use when need to answer an incoming call withing app UI
+ answerIncomingCall(callId: string): Promise;
+
+ startCall(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ hasVideo: boolean,
+ displayOptions?: {
+ displayTitle?: string;
+ displaySubtitle?: string;
+ }
+ ): Promise;
+
+ updateDisplay(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ displayOptions?: {
+ displayTitle?: string;
+ displaySubtitle?: string;
+ }
+ ): Promise;
+
+ isCallRegistered(callId: string): boolean;
+
+ hasRegisteredCall(): boolean;
+
+ endCallWithReason(callId: string, reason: number): Promise;
+
+ endCall(callId: string): Promise;
+
+ setMutedCall(callId: string, isMuted: boolean): Promise;
+
+ setOnHoldCall(callId: string, isOnHold: boolean): Promise;
+
+ startBackgroundTask(taskName: string, timeout: number): Promise;
+
+ stopBackgroundTask(taskName: string): Promise;
+
+ readonly onNewEvent: EventEmitter<{
+ eventName: string;
+ params: {
+ callId: string;
+ cause?: string;
+ muted?: boolean;
+ hold?: boolean;
+ };
+ }>;
+
+ log(message: string, level: 'debug' | 'info' | 'warn' | 'error'): void;
+}
+
+export default TurboModuleRegistry.getEnforcing('Callingx');
diff --git a/packages/react-native-callingx/src/types.ts b/packages/react-native-callingx/src/types.ts
new file mode 100644
index 0000000000..14008739ef
--- /dev/null
+++ b/packages/react-native-callingx/src/types.ts
@@ -0,0 +1,163 @@
+import type { EventListener } from './EventManager';
+import type { ManagableTask } from './utils/headlessTask';
+import type { PermissionsResult } from './utils/permissions';
+
+export interface ICallingxModule {
+ get isOutcomingCallsEnabled(): boolean;
+
+ get isNotificationsAllowed(): boolean;
+
+ setup(options: Options): void;
+
+ checkPermissions(): Promise;
+
+ requestPermissions(): Promise;
+
+ setCurrentCallActive(callId: string): Promise;
+
+ getInitialEvents(): EventData[];
+
+ displayIncomingCall(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ hasVideo: boolean,
+ displayOptions?: InfoDisplayOptions
+ ): Promise;
+ answerIncomingCall(callId: string): Promise;
+
+ startCall(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ hasVideo: boolean,
+ displayOptions?: InfoDisplayOptions
+ ): Promise;
+
+ updateDisplay(
+ callId: string,
+ phoneNumber: string,
+ callerName: string,
+ displayOptions?: InfoDisplayOptions
+ ): Promise;
+
+ isCallRegistered(callId: string): boolean;
+
+ hasRegisteredCall(): boolean;
+
+ endCallWithReason(callId: string, reason: EndCallReason): Promise;
+
+ setMutedCall(callId: string, isMuted: boolean): Promise;
+
+ setOnHoldCall(callId: string, isOnHold: boolean): Promise;
+
+ startBackgroundTask(taskProvider: ManagableTask): Promise;
+
+ stopBackgroundTask(taskName: string): Promise;
+
+ addEventListener(
+ eventName: T,
+ callback: EventListener
+ ): { remove: () => void };
+
+ log(message: string, level: 'debug' | 'info' | 'warn' | 'error'): void;
+}
+
+export type iOSOptions = {
+ supportsVideo?: boolean;
+ maximumCallsPerCallGroup?: number;
+ maximumCallGroups?: number;
+ handleType?: string; //'generic' | 'number' | 'phone' | 'email';
+ sound?: string;
+ imageName?: string;
+ callsHistory?: boolean;
+ setupAudioSession?: boolean;
+};
+
+export type AndroidOptions = {
+ incomingChannel?: {
+ id?: string;
+ name?: string;
+ sound?: string;
+ vibration?: boolean;
+ };
+ outgoingChannel?: {
+ id?: string;
+ name?: string;
+ };
+};
+
+export type TextTransformer = (text: string, incoming: boolean) => string;
+export type NotificationTransformers = {
+ titleTransformer: TextTransformer;
+ subtitleTransformer?: TextTransformer;
+};
+
+export type Options = {
+ ios?: iOSOptions;
+ android?: AndroidOptions & NotificationTransformers;
+ enableOutcomingCalls?: boolean;
+ enableAutoPermissions?: boolean;
+};
+
+export type InfoDisplayOptions = {
+ displayTitle?: string;
+ displaySubtitle?: string;
+};
+
+export type EventData = {
+ eventName: EventName;
+ params: EventParams[EventName];
+};
+
+export type EventName =
+ | 'answerCall'
+ | 'endCall'
+ | 'didDisplayIncomingCall'
+ | 'didToggleHoldCallAction'
+ | 'didChangeAudioRoute'
+ | 'didReceiveStartCallAction'
+ | 'didPerformSetMutedCallAction'
+ | 'didActivateAudioSession'
+ | 'didDeactivateAudioSession';
+
+export type EventParams = {
+ answerCall: {
+ callId: string;
+ source: 'app' | 'sys';
+ };
+ endCall: {
+ callId: string;
+ cause: string;
+ source: 'app' | 'sys';
+ };
+ didDisplayIncomingCall: {
+ callId: string;
+ };
+ didToggleHoldCallAction: {
+ callId: string;
+ hold: boolean;
+ };
+ didPerformSetMutedCallAction: {
+ callId: string;
+ muted: boolean;
+ };
+ didChangeAudioRoute: {
+ callId: string;
+ output: string;
+ };
+ didReceiveStartCallAction: {
+ callId: string;
+ };
+ didActivateAudioSession: undefined;
+ didDeactivateAudioSession: undefined;
+};
+
+export type EndCallReason =
+ | 'local' // when call is ended by the user
+ | 'remote'
+ | 'rejected'
+ | 'busy'
+ | 'answeredElsewhere'
+ | 'missed'
+ | 'error';
diff --git a/packages/react-native-callingx/src/utils/constants.ts b/packages/react-native-callingx/src/utils/constants.ts
new file mode 100644
index 0000000000..a31ce11830
--- /dev/null
+++ b/packages/react-native-callingx/src/utils/constants.ts
@@ -0,0 +1,55 @@
+import type {
+ AndroidOptions,
+ iOSOptions,
+ EndCallReason,
+ TextTransformer,
+} from '../types';
+import type { DeepRequired } from './types';
+
+export const defaultTextTransformer: TextTransformer = (text: string) => text;
+
+export const defaultiOSOptions: Required = {
+ supportsVideo: true,
+ maximumCallsPerCallGroup: 1,
+ maximumCallGroups: 1,
+ handleType: 'generic',
+ sound: '',
+ imageName: '',
+ callsHistory: false,
+ setupAudioSession: true,
+};
+
+export const defaultAndroidOptions: DeepRequired = {
+ incomingChannel: {
+ id: 'incoming_calls_channel',
+ name: 'Incoming calls',
+ sound: '',
+ vibration: false,
+ },
+ outgoingChannel: {
+ id: 'ongoing_calls_channel',
+ name: 'Ongoing calls',
+ },
+};
+
+// See ios/Callingx.mm for native iOS logic and constants mapping.
+export const iosEndCallReasonMap: Record = {
+ local: -1,
+ remote: 1,
+ rejected: 4,
+ busy: 2,
+ answeredElsewhere: 3,
+ missed: 2,
+ error: 0,
+};
+
+// https://developer.android.com/reference/android/telecom/DisconnectCause
+export const androidEndCallReasonMap: Record = {
+ local: 2,
+ remote: 3,
+ rejected: 6,
+ busy: 7,
+ answeredElsewhere: 11,
+ missed: 5,
+ error: 1,
+};
diff --git a/packages/react-native-callingx/src/utils/headlessTask.ts b/packages/react-native-callingx/src/utils/headlessTask.ts
new file mode 100644
index 0000000000..63c739d520
--- /dev/null
+++ b/packages/react-native-callingx/src/utils/headlessTask.ts
@@ -0,0 +1,52 @@
+import { AppRegistry } from 'react-native';
+
+export const HEADLESS_TASK_NAME = 'HandleIncomingCall';
+
+export type ManagableTask = (
+ taskData: any,
+ stopTask: () => void
+) => Promise;
+
+type HeadlessTask = (taskData: any) => Promise;
+
+export const defaultBackgroundTask: ManagableTask = (
+ taskData: any,
+ stopTask: () => void
+) => {
+ return new Promise((resolve) => {
+ console.log('Default background task data', taskData);
+ let i = 0;
+ const totalIterations = 5;
+
+ function loop() {
+ if (i < totalIterations) {
+ setTimeout(() => {
+ console.log(`Iteration: ${i + 1}`);
+ i++;
+ loop();
+ }, 1000);
+ } else {
+ console.log('Default background task finished');
+ resolve(undefined);
+ stopTask();
+ }
+ }
+
+ loop();
+ });
+};
+
+let headlessTask: HeadlessTask = (taskData: any) =>
+ defaultBackgroundTask(taskData, () => {
+ console.log('Cancel callback called');
+ });
+
+export const setHeadlessTask = (task: HeadlessTask) => {
+ headlessTask = task;
+};
+
+export const registerHeadlessTask = () => {
+ AppRegistry.registerHeadlessTask(HEADLESS_TASK_NAME, () => {
+ return headlessTask;
+ });
+};
diff --git a/packages/react-native-callingx/src/utils/permissions.ts b/packages/react-native-callingx/src/utils/permissions.ts
new file mode 100644
index 0000000000..ef1dbbadd5
--- /dev/null
+++ b/packages/react-native-callingx/src/utils/permissions.ts
@@ -0,0 +1,119 @@
+import { Platform, PermissionsAndroid } from 'react-native';
+import type { Permission } from 'react-native';
+
+export interface PermissionsResult {
+ recordAudio: boolean;
+ postNotifications: boolean;
+}
+
+const allowedPostNotifications =
+ Platform.OS === 'android' && Platform.Version < 33;
+
+export const requestCallPermissions = async (): Promise => {
+ if (Platform.OS !== 'android') {
+ return { recordAudio: true, postNotifications: true }; // iOS handles permissions differently
+ }
+
+ const permissions: string[] = [PermissionsAndroid.PERMISSIONS.RECORD_AUDIO];
+
+ // Add POST_NOTIFICATIONS for Android 13+
+ if (Platform.Version >= 33) {
+ permissions.push(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
+ }
+
+ // Add WRITE_CALL_LOG for call history (required for Android 6.0+)
+ // Note: PermissionsAndroid doesn't have a constant for this, so we use the string directly
+ // permissions.push('android.permission.WRITE_CALL_LOG');
+
+ try {
+ const results = await PermissionsAndroid.requestMultiple(
+ permissions as Permission[]
+ );
+
+ // Check if all permissions are granted
+ const allGranted = Object.values(results).every(
+ (status) => status === PermissionsAndroid.RESULTS.GRANTED
+ );
+
+ if (!allGranted) {
+ const deniedPermissions = Object.entries(results)
+ .filter(([, status]) => status !== PermissionsAndroid.RESULTS.GRANTED)
+ .map(([permission]) => permission);
+
+ console.warn('Denied permissions:', deniedPermissions);
+ }
+
+ return {
+ recordAudio:
+ results[PermissionsAndroid.PERMISSIONS.RECORD_AUDIO] ===
+ PermissionsAndroid.RESULTS.GRANTED,
+ postNotifications:
+ results[PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS] ===
+ PermissionsAndroid.RESULTS.GRANTED || allowedPostNotifications,
+ };
+ } catch (err) {
+ console.warn('Error requesting permissions:', err);
+ return { recordAudio: false, postNotifications: false };
+ }
+};
+
+export const checkCallPermissions = async (): Promise => {
+ if (Platform.OS !== 'android') {
+ return { recordAudio: true, postNotifications: true };
+ }
+
+ const permissions: string[] = [PermissionsAndroid.PERMISSIONS.RECORD_AUDIO];
+
+ // if (Platform.Version >= 26) {
+ // permissions.push(PermissionsAndroid.PERMISSIONS.MANAGE_OWN_CALLS);
+ // }
+
+ if (Platform.Version >= 33) {
+ permissions.push(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
+ }
+
+ // Add WRITE_CALL_LOG for call history (required for Android 6.0+)
+ // Note: PermissionsAndroid doesn't have a constant for this, so we use the string directly
+ // permissions.push('android.permission.WRITE_CALL_LOG');
+
+ try {
+ const results = await Promise.all(
+ permissions.map(async (permission) => ({
+ permission,
+ granted: await PermissionsAndroid.check(permission as Permission),
+ }))
+ );
+
+ const resultsObject = results.reduce(
+ (acc, { permission, granted }) => {
+ acc[permission as Permission] = granted;
+ return acc;
+ },
+ {} as { [key in Permission]: boolean }
+ );
+
+ return {
+ recordAudio: resultsObject[PermissionsAndroid.PERMISSIONS.RECORD_AUDIO],
+ postNotifications:
+ resultsObject[PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS] ||
+ allowedPostNotifications,
+ };
+ } catch (err) {
+ console.warn('Error checking permissions:', err);
+ return { recordAudio: false, postNotifications: false };
+ }
+};
+
+export const requestPostNotificationPermissions =
+ async (): Promise => {
+ if (Platform.OS !== 'android') {
+ return true;
+ }
+
+ const results = await PermissionsAndroid.request(
+ PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
+ );
+ return (
+ results === PermissionsAndroid.RESULTS.GRANTED || allowedPostNotifications
+ );
+ };
diff --git a/packages/react-native-callingx/src/utils/types.ts b/packages/react-native-callingx/src/utils/types.ts
new file mode 100644
index 0000000000..7dd8dee102
--- /dev/null
+++ b/packages/react-native-callingx/src/utils/types.ts
@@ -0,0 +1,5 @@
+export type DeepRequired = {
+ [K in keyof T]-?: NonNullable extends object
+ ? DeepRequired>
+ : NonNullable;
+};
diff --git a/packages/react-native-callingx/tsconfig.build.json b/packages/react-native-callingx/tsconfig.build.json
new file mode 100644
index 0000000000..3c0636adf2
--- /dev/null
+++ b/packages/react-native-callingx/tsconfig.build.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig",
+ "exclude": ["example", "lib"]
+}
diff --git a/packages/react-native-callingx/tsconfig.json b/packages/react-native-callingx/tsconfig.json
new file mode 100644
index 0000000000..6d5506c5f8
--- /dev/null
+++ b/packages/react-native-callingx/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "rootDir": ".",
+ "paths": {
+ "react-native-callingx": ["./src/index"]
+ },
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "customConditions": ["react-native-strict-api"],
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "jsx": "react-jsx",
+ "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": true
+ }
+}
diff --git a/packages/react-native-callingx/turbo.json b/packages/react-native-callingx/turbo.json
new file mode 100644
index 0000000000..c4d78c4961
--- /dev/null
+++ b/packages/react-native-callingx/turbo.json
@@ -0,0 +1,42 @@
+{
+ "$schema": "https://turbo.build/schema.json",
+ "globalDependencies": [".nvmrc", ".yarnrc.yml"],
+ "globalEnv": ["NODE_ENV"],
+ "tasks": {
+ "build:android": {
+ "env": ["ANDROID_HOME", "ORG_GRADLE_PROJECT_newArchEnabled"],
+ "inputs": [
+ "package.json",
+ "android",
+ "!android/build",
+ "src/*.ts",
+ "src/*.tsx",
+ "example/package.json",
+ "example/android",
+ "!example/android/.gradle",
+ "!example/android/build",
+ "!example/android/app/build"
+ ],
+ "outputs": []
+ },
+ "build:ios": {
+ "env": [
+ "RCT_NEW_ARCH_ENABLED",
+ "RCT_USE_RN_DEP",
+ "RCT_USE_PREBUILT_RNCORE"
+ ],
+ "inputs": [
+ "package.json",
+ "*.podspec",
+ "ios",
+ "src/*.ts",
+ "src/*.tsx",
+ "example/package.json",
+ "example/ios",
+ "!example/ios/build",
+ "!example/ios/Pods"
+ ],
+ "outputs": []
+ }
+ }
+}
diff --git a/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidManifest.test.ts b/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidManifest.test.ts
index 9b68104ab2..15cdea767a 100644
--- a/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidManifest.test.ts
+++ b/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidManifest.test.ts
@@ -35,9 +35,7 @@ const getMainActivityOrThrow = AndroidConfig.Manifest.getMainActivityOrThrow;
const sampleManifestPath = getFixturePath('AndroidManifest.xml');
const props: ConfigProps = {
- ringingPushNotifications: {
- disableVideoIos: false,
- },
+ ringing: true,
androidPictureInPicture: true,
androidKeepCallAlive: true,
};
diff --git a/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidPermissions.test.ts b/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidPermissions.test.ts
index 07b9f740bd..6d6537a9c3 100644
--- a/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidPermissions.test.ts
+++ b/packages/react-native-sdk/expo-config-plugin/__tests__/withAndroidPermissions.test.ts
@@ -14,7 +14,7 @@ describe('withStreamVideoReactNativeSDKAndroidPermissions', () => {
};
const props: ConfigProps = {
enableScreenshare: true,
- ringingPushNotifications: { disableVideoIos: false },
+ ringing: true,
androidKeepCallAlive: true,
};
diff --git a/packages/react-native-sdk/expo-config-plugin/__tests__/withAppDelegate.test.ts b/packages/react-native-sdk/expo-config-plugin/__tests__/withAppDelegate.test.ts
index 92b368eba9..06d9a54cb6 100644
--- a/packages/react-native-sdk/expo-config-plugin/__tests__/withAppDelegate.test.ts
+++ b/packages/react-native-sdk/expo-config-plugin/__tests__/withAppDelegate.test.ts
@@ -111,10 +111,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
const props: ConfigProps = {
iOSEnableMultitaskingCameraAccess: true,
addNoiseCancellation: true,
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: true,
- },
+ ringing: true,
};
const updatedConfig = withAppDelegate(config, props) as CustomExpoConfig;
@@ -183,10 +180,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
const props: ConfigProps = {
iOSEnableMultitaskingCameraAccess: true,
addNoiseCancellation: true,
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: true,
- },
+ ringing: true,
};
const updatedConfig = withAppDelegate(config, props) as CustomExpoConfig;
@@ -236,10 +230,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
it('objc - should not modify config if already added', () => {
const props: ConfigProps = {
iOSEnableMultitaskingCameraAccess: true,
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: true,
- },
+ ringing: true,
};
const updatedConfig = withAppDelegate(
@@ -256,10 +247,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
it('swift - should not modify config if already added', () => {
const props: ConfigProps = {
iOSEnableMultitaskingCameraAccess: true,
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: true,
- },
+ ringing: true,
};
const updatedConfig = withAppDelegate(
@@ -288,10 +276,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
},
};
const props: ConfigProps = {
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: false,
- },
+ ringing: true,
};
expect(() => withAppDelegate(config, props)).toThrow();
});
@@ -311,10 +296,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
},
};
const props: ConfigProps = {
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: false,
- },
+ ringing: true,
};
expect(() => withAppDelegate(config, props)).toThrow();
});
diff --git a/packages/react-native-sdk/expo-config-plugin/__tests__/withMainActivity.test.ts b/packages/react-native-sdk/expo-config-plugin/__tests__/withMainActivity.test.ts
index 97281f1049..ef0fcf5abf 100644
--- a/packages/react-native-sdk/expo-config-plugin/__tests__/withMainActivity.test.ts
+++ b/packages/react-native-sdk/expo-config-plugin/__tests__/withMainActivity.test.ts
@@ -43,9 +43,7 @@ describe('withStreamVideoReactNativeSDKAppDelegate', () => {
const props: ConfigProps = {
androidPictureInPicture: true,
enableScreenshare: true,
- ringingPushNotifications: {
- showWhenLockedAndroid: true,
- },
+ ringing: true,
};
const updatedConfig = withMainActivity(config, props) as CustomExpoConfig;
diff --git a/packages/react-native-sdk/expo-config-plugin/__tests__/withiOSInfoPlist.test.ts b/packages/react-native-sdk/expo-config-plugin/__tests__/withiOSInfoPlist.test.ts
index 1fbcda78b5..ee13e91e67 100644
--- a/packages/react-native-sdk/expo-config-plugin/__tests__/withiOSInfoPlist.test.ts
+++ b/packages/react-native-sdk/expo-config-plugin/__tests__/withiOSInfoPlist.test.ts
@@ -129,10 +129,7 @@ describe('withStreamVideoReactNativeSDKiOSInfoPList', () => {
},
};
const props: ConfigProps = {
- ringingPushNotifications: {
- disableVideoIos: true,
- includesCallsInRecentsIos: true,
- },
+ ringing: true,
};
const modifiedConfig = withStreamVideoReactNativeSDKiOSInfoPList(
config,
diff --git a/packages/react-native-sdk/expo-config-plugin/src/common/types.ts b/packages/react-native-sdk/expo-config-plugin/src/common/types.ts
index b6822b0192..b4a4c2b3e1 100644
--- a/packages/react-native-sdk/expo-config-plugin/src/common/types.ts
+++ b/packages/react-native-sdk/expo-config-plugin/src/common/types.ts
@@ -1,12 +1,6 @@
-export type RingingPushNotifications = {
- disableVideoIos?: boolean;
- includesCallsInRecentsIos?: boolean;
- showWhenLockedAndroid?: boolean;
-};
-
export type ConfigProps =
| {
- ringingPushNotifications?: RingingPushNotifications;
+ ringing?: boolean;
enableNonRingingPushNotifications?: boolean;
androidPictureInPicture?: boolean;
androidKeepCallAlive?: boolean;
diff --git a/packages/react-native-sdk/expo-config-plugin/src/withAndroidManifest.ts b/packages/react-native-sdk/expo-config-plugin/src/withAndroidManifest.ts
index 604f71106a..7c457abd8c 100644
--- a/packages/react-native-sdk/expo-config-plugin/src/withAndroidManifest.ts
+++ b/packages/react-native-sdk/expo-config-plugin/src/withAndroidManifest.ts
@@ -50,7 +50,7 @@ const withStreamVideoReactNativeSDKManifest: ConfigPlugin = (
return withAndroidManifest(configuration, (config) => {
const androidManifest = config.modResults;
const mainApplication = getMainApplicationOrThrow(androidManifest);
- if (props?.ringingPushNotifications || props?.androidKeepCallAlive) {
+ if (props?.ringing || props?.androidKeepCallAlive) {
ensureToolsAvailable(androidManifest);
/* Add the notifee foreground Service */
let services = mainApplication.service ?? [];
diff --git a/packages/react-native-sdk/expo-config-plugin/src/withAndroidPermissions.ts b/packages/react-native-sdk/expo-config-plugin/src/withAndroidPermissions.ts
index 1edd3462a0..1dfe642b6c 100644
--- a/packages/react-native-sdk/expo-config-plugin/src/withAndroidPermissions.ts
+++ b/packages/react-native-sdk/expo-config-plugin/src/withAndroidPermissions.ts
@@ -12,7 +12,7 @@ const withStreamVideoReactNativeSDKAndroidPermissions: ConfigPlugin<
];
if (
props?.androidKeepCallAlive ||
- props?.ringingPushNotifications ||
+ props?.ringing ||
props?.enableScreenshare
) {
permissions.push(
@@ -25,7 +25,7 @@ const withStreamVideoReactNativeSDKAndroidPermissions: ConfigPlugin<
);
}
}
- if (props?.androidKeepCallAlive || props?.ringingPushNotifications) {
+ if (props?.androidKeepCallAlive || props?.ringing) {
permissions.push(
'android.permission.FOREGROUND_SERVICE_CAMERA',
'android.permission.FOREGROUND_SERVICE_MICROPHONE',
@@ -33,7 +33,7 @@ const withStreamVideoReactNativeSDKAndroidPermissions: ConfigPlugin<
'android.permission.FOREGROUND_SERVICE_DATA_SYNC',
);
}
- if (props?.ringingPushNotifications?.showWhenLockedAndroid) {
+ if (props?.ringing) {
permissions.push('android.permission.USE_FULL_SCREEN_INTENT');
}
const config = AndroidConfig.Permissions.withPermissions(
diff --git a/packages/react-native-sdk/expo-config-plugin/src/withAppDelegate.ts b/packages/react-native-sdk/expo-config-plugin/src/withAppDelegate.ts
index d12c43dad5..ca08ab9652 100644
--- a/packages/react-native-sdk/expo-config-plugin/src/withAppDelegate.ts
+++ b/packages/react-native-sdk/expo-config-plugin/src/withAppDelegate.ts
@@ -12,17 +12,14 @@ import {
insertContentsInsideObjcFunctionBlock,
} from '@expo/config-plugins/build/ios/codeMod';
-import {
- type ConfigProps,
- type RingingPushNotifications,
-} from './common/types';
+import { type ConfigProps } from './common/types';
import addNewLinesToAppDelegateObjc from './common/addNewLinesToAppDelegateObjc';
import { addToSwiftBridgingHeaderFile } from './common/addToSwiftBridgingHeaderFile';
const withAppDelegate: ConfigPlugin = (configuration, props) => {
return withAppDelegateUtil(configuration, (config) => {
if (
- !props?.ringingPushNotifications &&
+ !props?.ringing &&
!props?.iOSEnableMultitaskingCameraAccess &&
!props?.addNoiseCancellation
) {
@@ -42,22 +39,19 @@ const withAppDelegate: ConfigPlugin = (configuration, props) => {
props.iOSEnableMultitaskingCameraAccess,
props.addNoiseCancellation,
);
- if (props?.ringingPushNotifications) {
+ if (props?.ringing) {
config.modResults.contents = addObjcImports(
config.modResults.contents,
[
- '"RNCallKeep.h"',
'',
'"RNVoipPushNotificationManager.h"',
'"StreamVideoReactNative.h"',
- '',
],
);
config.modResults.contents =
addDidFinishLaunchingWithOptionsRingingObjc(
config.modResults.contents,
- props.ringingPushNotifications,
);
config.modResults.contents = addDidUpdatePushCredentialsObjc(
@@ -67,10 +61,6 @@ const withAppDelegate: ConfigPlugin = (configuration, props) => {
config.modResults.contents = addDidReceiveIncomingPushCallbackObjc(
config.modResults.contents,
);
-
- config.modResults.contents = addAudioSessionMethodsObjc(
- config.modResults.contents,
- );
}
return config;
} catch (error: any) {
@@ -80,7 +70,7 @@ const withAppDelegate: ConfigPlugin = (configuration, props) => {
}
} else {
try {
- if (props?.ringingPushNotifications) {
+ if (props?.ringing) {
// make it public class AppDelegate: ExpoAppDelegate, PKPushRegistryDelegate {
const regex = /(class\s+AppDelegate[^{]*)(\s*\{)/;
config.modResults.contents = config.modResults.contents.replace(
@@ -130,15 +120,14 @@ const withAppDelegate: ConfigPlugin = (configuration, props) => {
props.iOSEnableMultitaskingCameraAccess,
props.addNoiseCancellation,
);
- if (props?.ringingPushNotifications) {
+ if (props?.ringing) {
config.modResults.contents = addSwiftImports(
config.modResults.contents,
- ['RNCallKeep', 'PushKit', 'RNVoipPushNotification'],
+ ['PushKit', 'RNVoipPushNotification'],
);
config.modResults.contents =
addDidFinishLaunchingWithOptionsRingingSwift(
config.modResults.contents,
- props.ringingPushNotifications,
);
config.modResults.contents = addDidUpdatePushCredentialsSwift(
@@ -148,10 +137,6 @@ const withAppDelegate: ConfigPlugin = (configuration, props) => {
config.modResults.contents = addDidReceiveIncomingPushCallbackSwift(
config.modResults.contents,
);
-
- config.modResults.contents = addAudioSessionMethodsSwift(
- config.modResults.contents,
- );
}
return config;
} catch (error: any) {
@@ -231,31 +216,8 @@ function addDidFinishLaunchingWithOptionsObjc(
return contents;
}
-function addDidFinishLaunchingWithOptionsRingingSwift(
- contents: string,
- ringingPushNotifications: RingingPushNotifications,
-) {
+function addDidFinishLaunchingWithOptionsRingingSwift(contents: string) {
const functionSelector = 'application(_:didFinishLaunchingWithOptions:)';
- const supportsVideoString = ringingPushNotifications.disableVideoIos
- ? 'false'
- : 'true';
- const includesCallsInRecents =
- ringingPushNotifications.includesCallsInRecentsIos ? 'false' : 'true';
- const setupCallKeep = ` let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleDisplayName"] as? String
- let appName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String
- RNCallKeep.setup([
- "appName": localizedAppName != nil ? localizedAppName! : appName as Any,
- "supportsVideo": ${supportsVideoString},
- "includesCallsInRecents": ${includesCallsInRecents},
- ])`;
- if (!contents.includes('RNCallKeep.setup')) {
- contents = insertContentsInsideSwiftFunctionBlock(
- contents,
- functionSelector,
- setupCallKeep,
- { position: 'head' },
- );
- }
// call the setup of voip push notification
const voipSetupMethod = 'RNVoipPushNotificationManager.voipRegistration()';
if (!contents.includes(voipSetupMethod)) {
@@ -269,32 +231,8 @@ function addDidFinishLaunchingWithOptionsRingingSwift(
return contents;
}
-function addDidFinishLaunchingWithOptionsRingingObjc(
- contents: string,
- ringingPushNotifications: RingingPushNotifications,
-) {
+function addDidFinishLaunchingWithOptionsRingingObjc(contents: string) {
const functionSelector = 'application:didFinishLaunchingWithOptions:';
- // call the setup RNCallKeep
- const supportsVideoString = ringingPushNotifications.disableVideoIos
- ? '@NO'
- : '@YES';
- const includesCallsInRecents =
- ringingPushNotifications.includesCallsInRecentsIos ? '@YES' : '@NO';
- const setupCallKeep = `NSString *localizedAppName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];
- NSString *appName = [[[NSBundle mainBundle] infoDictionary]objectForKey :@"CFBundleDisplayName"];
- [RNCallKeep setup:@{
- @"appName": localizedAppName != nil ? localizedAppName : appName,
- @"supportsVideo": ${supportsVideoString},
- @"includesCallsInRecents": ${includesCallsInRecents},
- }];`;
- if (!contents.includes('[RNCallKeep setup:@')) {
- contents = insertContentsInsideObjcFunctionBlock(
- contents,
- functionSelector,
- setupCallKeep,
- { position: 'head' },
- );
- }
// call the setup of voip push notification
const voipSetupMethod = '[RNVoipPushNotificationManager voipRegistration];';
if (!contents.includes(voipSetupMethod)) {
@@ -366,108 +304,10 @@ function addDidUpdatePushCredentialsObjc(contents: string) {
return contents;
}
-function addAudioSessionMethodsSwift(contents: string) {
- const audioSessionDidActivateMethod =
- 'RTCAudioSession.sharedInstance().audioSessionDidActivate(AVAudioSession.sharedInstance())';
- if (!contents.includes(audioSessionDidActivateMethod)) {
- const functionSelector = 'provider(_:didActivate:)';
- if (!contents.includes('didActivateAudioSession')) {
- contents = insertContentsInsideSwiftClassBlock(
- contents,
- 'class AppDelegate',
- `
- func provider(_ provider: CXProvider, didActivateAudioSession audioSession: AVAudioSession) {
- ${audioSessionDidActivateMethod}
- }
- `,
- { position: 'tail' },
- );
- } else {
- contents = insertContentsInsideSwiftFunctionBlock(
- contents,
- functionSelector,
- audioSessionDidActivateMethod,
- { position: 'tail' },
- );
- }
- }
- const audioSessionDidDeactivateMethod =
- 'RTCAudioSession.sharedInstance().audioSessionDidDeactivate(AVAudioSession.sharedInstance())';
-
- if (!contents.includes(audioSessionDidDeactivateMethod)) {
- const functionSelector = 'provider(_:didDeactivate:)';
- if (!contents.includes('didDeactivateAudioSession')) {
- contents = insertContentsInsideSwiftClassBlock(
- contents,
- 'class AppDelegate',
- `
- func provider(_ provider: CXProvider, didDeactivateAudioSession audioSession: AVAudioSession) {
- ${audioSessionDidDeactivateMethod}
- }
- `,
- { position: 'tail' },
- );
- } else {
- contents = insertContentsInsideSwiftFunctionBlock(
- contents,
- functionSelector,
- audioSessionDidDeactivateMethod,
- { position: 'tail' },
- );
- }
- }
- return contents;
-}
-
-function addAudioSessionMethodsObjc(contents: string) {
- const audioSessionDidActivateMethod =
- '[[RTCAudioSession sharedInstance] audioSessionDidActivate:[AVAudioSession sharedInstance]];';
- if (!contents.includes(audioSessionDidActivateMethod)) {
- const functionSelector = 'provider:didActivateAudioSession:audioSession:';
- const codeblock = findObjcFunctionCodeBlock(contents, functionSelector);
- if (!codeblock) {
- contents = addNewLinesToAppDelegateObjc(contents, [
- '- (void) provider:(CXProvider *) provider didActivateAudioSession:(AVAudioSession *) audioSession {',
- ' ' /* indentation */ + audioSessionDidActivateMethod,
- '}',
- ]);
- } else {
- contents = insertContentsInsideObjcFunctionBlock(
- contents,
- functionSelector,
- audioSessionDidActivateMethod,
- { position: 'tail' },
- );
- }
- }
- const audioSessionDidDeactivateMethod =
- '[[RTCAudioSession sharedInstance] audioSessionDidDeactivate:[AVAudioSession sharedInstance]];';
-
- if (!contents.includes(audioSessionDidDeactivateMethod)) {
- const functionSelector = 'provider:didDeactivateAudioSession:audioSession:';
- const codeblock = findObjcFunctionCodeBlock(contents, functionSelector);
- if (!codeblock) {
- contents = addNewLinesToAppDelegateObjc(contents, [
- '- (void) provider:(CXProvider *) provider didDeactivateAudioSession:(AVAudioSession *) audioSession {',
- ' ' /* indentation */ + audioSessionDidDeactivateMethod,
- '}',
- ]);
- } else {
- contents = insertContentsInsideObjcFunctionBlock(
- contents,
- functionSelector,
- audioSessionDidDeactivateMethod,
- { position: 'tail' },
- );
- }
- }
- return contents;
-}
-
function addDidReceiveIncomingPushCallbackSwift(contents: string) {
const onIncomingPush = `
guard let stream = payload.dictionaryPayload["stream"] as? [String: Any],
- let createdCallerName = stream["created_by_display_name"] as? String,
+ let _ = stream["created_by_display_name"] as? String,
let cid = stream["call_cid"] as? String else {
completion()
return
@@ -483,28 +323,12 @@ function addDidReceiveIncomingPushCallbackSwift(contents: string) {
return
}
- let uuid = UUID().uuidString
- let videoIncluded = stream["video"] as? String
- let hasVideo = videoIncluded == "false" ? false : true
-
- StreamVideoReactNative.registerIncomingCall(cid, uuid: uuid)
-
- RNVoipPushNotificationManager.addCompletionHandler(uuid, completionHandler: completion)
+ RNVoipPushNotificationManager.addCompletionHandler(cid, completionHandler: completion)
+ // Process the received push // fire 'notification' event to JS
RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue)
- RNCallKeep.reportNewIncomingCall(uuid,
- handle: createdCallerName,
- handleType: "generic",
- hasVideo: hasVideo,
- localizedCallerName: createdCallerName,
- supportsHolding: false,
- supportsDTMF: false,
- supportsGrouping: false,
- supportsUngrouping: false,
- fromPushKit: true,
- payload: stream,
- withCompletionHandler: nil)`;
+ StreamVideoReactNative.didReceiveIncomingPush(payload, completionHandler: nil)`;
if (
!contents.includes('RNVoipPushNotificationManager.didReceiveIncomingPush')
) {
@@ -543,8 +367,6 @@ function addDidReceiveIncomingPushCallbackObjc(contents: string) {
const onIncomingPush = `
// process the payload and store it in the native module's cache
NSDictionary *stream = payload.dictionaryPayload[@"stream"];
- NSString *uuid = [[NSUUID UUID] UUIDString];
- NSString *createdCallerName = stream[@"created_by_display_name"];
NSString *cid = stream[@"call_cid"];
// Check if user is busy BEFORE registering the call
@@ -557,31 +379,13 @@ function addDidReceiveIncomingPushCallbackObjc(contents: string) {
return;
}
- NSString *videoIncluded = stream[@"video"];
- BOOL hasVideo = [videoIncluded isEqualToString:@"false"] ? NO : YES;
-
- // store the call cid and uuid in the native module's cache
- [StreamVideoReactNative registerIncomingCall:cid uuid:uuid];
-
- // set the completion handler - this one is called by the JS SDK
- [RNVoipPushNotificationManager addCompletionHandler:uuid completionHandler:completion];
+ [RNVoipPushNotificationManager addCompletionHandler:cid completionHandler:completion];
// send event to JS - the JS SDK will handle the rest and call the 'completionHandler'
[RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];
// display the incoming call notification
- [RNCallKeep reportNewIncomingCall: uuid
- handle: createdCallerName
- handleType: @"generic"
- hasVideo: hasVideo
- localizedCallerName: createdCallerName
- supportsHolding: NO
- supportsDTMF: NO
- supportsGrouping: NO
- supportsUngrouping: NO
- fromPushKit: YES
- payload: stream
- withCompletionHandler: nil];
+ [StreamVideoReactNative didReceiveIncomingPush:payload completionHandler:nil];
`;
if (
!contents.includes(
diff --git a/packages/react-native-sdk/expo-config-plugin/src/withMainActivity.ts b/packages/react-native-sdk/expo-config-plugin/src/withMainActivity.ts
index d6e14e353f..ff44e5a2e3 100644
--- a/packages/react-native-sdk/expo-config-plugin/src/withMainActivity.ts
+++ b/packages/react-native-sdk/expo-config-plugin/src/withMainActivity.ts
@@ -41,7 +41,7 @@ const withStreamVideoReactNativeSDKMainActivity: ConfigPlugin = (
);
}
- if (props?.ringingPushNotifications?.showWhenLockedAndroid) {
+ if (props?.ringing) {
config.modResults.contents = addInsideOnCreateLockscreen(
config.modResults.contents,
isMainActivityJava,
diff --git a/packages/react-native-sdk/expo-config-plugin/src/withiOSInfoPlist.ts b/packages/react-native-sdk/expo-config-plugin/src/withiOSInfoPlist.ts
index bfbd55a2b9..b2ee1e4728 100644
--- a/packages/react-native-sdk/expo-config-plugin/src/withiOSInfoPlist.ts
+++ b/packages/react-native-sdk/expo-config-plugin/src/withiOSInfoPlist.ts
@@ -15,7 +15,7 @@ const withStreamVideoReactNativeSDKiOSInfoPList: ConfigPlugin = (
}
}
addBackgroundMode('audio');
- if (props?.ringingPushNotifications) {
+ if (props?.ringing) {
addBackgroundMode('voip');
addBackgroundMode('fetch');
addBackgroundMode('processing');
@@ -23,10 +23,7 @@ const withStreamVideoReactNativeSDKiOSInfoPList: ConfigPlugin = (
'$(PRODUCT_BUNDLE_IDENTIFIER)',
];
}
- if (
- props?.enableNonRingingPushNotifications ||
- props?.ringingPushNotifications
- ) {
+ if (props?.enableNonRingingPushNotifications || props?.ringing) {
addBackgroundMode('remote-notification');
}
return config;
diff --git a/packages/react-native-sdk/ios/StreamVideoReactNative.h b/packages/react-native-sdk/ios/StreamVideoReactNative.h
index 9683580f3b..bd0aa76556 100644
--- a/packages/react-native-sdk/ios/StreamVideoReactNative.h
+++ b/packages/react-native-sdk/ios/StreamVideoReactNative.h
@@ -1,11 +1,12 @@
#import
#import
+#import
@interface StreamVideoReactNative : RCTEventEmitter
- (void)screenShareEventReceived:(NSString *)event;
-+ (void)registerIncomingCall:(NSString *)cid uuid:(NSString *)uuid;
++ (void)didReceiveIncomingPush:(PKPushPayload *)payload completionHandler: (void (^_Nullable)(void)) completion;
+ (void)setup DEPRECATED_MSG_ATTRIBUTE("No need to use setup() anymore");
diff --git a/packages/react-native-sdk/ios/StreamVideoReactNative.m b/packages/react-native-sdk/ios/StreamVideoReactNative.m
index 5d2c293dfa..54db9d0994 100644
--- a/packages/react-native-sdk/ios/StreamVideoReactNative.m
+++ b/packages/react-native-sdk/ios/StreamVideoReactNative.m
@@ -4,6 +4,7 @@
#import
#import
#import
+#import
#import "StreamVideoReactNative.h"
#import "WebRTCModule.h"
#import "WebRTCModuleOptions.h"
@@ -14,8 +15,6 @@
NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
-static NSMutableDictionary *_incomingCallUUIDsByCallID = nil;
-static NSMutableDictionary *_incomingCallCidsByUUID = nil;
static dispatch_queue_t _dictionaryQueue = nil;
static BOOL _shouldRejectCallWhenBusy = NO;
@@ -60,11 +59,62 @@ +(void)initializeSharedDictionaries {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_dictionaryQueue = dispatch_queue_create("com.stream.video.dictionary", DISPATCH_QUEUE_SERIAL);
- _incomingCallUUIDsByCallID = [NSMutableDictionary dictionary];
- _incomingCallCidsByUUID = [NSMutableDictionary dictionary];
});
}
++(void)didReceiveIncomingPush:(PKPushPayload *)payload completionHandler: (void (^_Nullable)(void)) completion {
+ NSDictionary *streamPayload = payload.dictionaryPayload[@"stream"];
+ if (!streamPayload) {
+ NSLog(@"[StreamVideoReactNative][didReceiveIncomingPush] Stream payload not found");
+ return;
+ }
+
+ Class callingxClass = NSClassFromString(@"Callingx");
+ if (!callingxClass) {
+ NSLog(@"[StreamVideoReactNative][didReceiveIncomingPush] Callingx not available");
+ return;
+ }
+
+ NSLog(@"[StreamVideoReactNative][didReceiveIncomingPush] Callingx available");
+
+ SEL selector = @selector(reportNewIncomingCall:handle:handleType:hasVideo:localizedCallerName:supportsHolding:supportsDTMF:supportsGrouping:supportsUngrouping:fromPushKit:payload:withCompletionHandler:);
+
+ if (![callingxClass respondsToSelector:selector]) {
+ NSLog(@"[StreamVideoReactNative][didReceiveIncomingPush] Callingx does not respond to selector");
+ return;
+ }
+
+ NSString *callCid = streamPayload[@"call_cid"];
+ NSString *createdCallerName = streamPayload[@"created_by_display_name"];
+ NSString *videoIncluded = streamPayload[@"video"];
+ BOOL hasVideo = [videoIncluded isEqualToString:@"false"] ? NO : YES;
+ NSString *handleType = @"generic";
+ BOOL supportsHolding = NO;
+ BOOL supportsDTMF = NO;
+ BOOL supportsGrouping = NO;
+ BOOL supportsUngrouping = NO;
+ BOOL fromPushKit = YES;
+ void (^completionHandler)(void) = nil;
+
+ NSMethodSignature *signature = [callingxClass methodSignatureForSelector:selector];
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setTarget:callingxClass];
+ [invocation setSelector:selector];
+ [invocation setArgument:&callCid atIndex:2];
+ [invocation setArgument:&createdCallerName atIndex:3];
+ [invocation setArgument:&handleType atIndex:4];
+ [invocation setArgument:&hasVideo atIndex:5];
+ [invocation setArgument:&createdCallerName atIndex:6];
+ [invocation setArgument:&supportsHolding atIndex:7];
+ [invocation setArgument:&supportsDTMF atIndex:8];
+ [invocation setArgument:&supportsGrouping atIndex:9];
+ [invocation setArgument:&supportsUngrouping atIndex:10];
+ [invocation setArgument:&fromPushKit atIndex:11];
+ [invocation setArgument:&streamPayload atIndex:12];
+ [invocation setArgument:&completionHandler atIndex:13];
+ [invocation invoke];
+}
+
-(instancetype)init {
if ((self = [super init])) {
_notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
@@ -191,71 +241,6 @@ -(void)screenShareEventReceived:(NSString*)event {
}
}
-+(void)registerIncomingCall:(NSString *)cid uuid:(NSString *)uuid {
- [StreamVideoReactNative initializeSharedDictionaries];
- dispatch_sync(_dictionaryQueue, ^{
-
-#ifdef DEBUG
- NSLog(@"registerIncomingCall cid:%@ -> uuid:%@",cid,uuid);
-#endif
- NSString *lowercaseUUID = [uuid lowercaseString];
- _incomingCallUUIDsByCallID[cid] = lowercaseUUID;
- _incomingCallCidsByUUID[lowercaseUUID] = cid;
- });
-}
-
-RCT_EXPORT_METHOD(getIncomingCallUUid:(NSString *)cid
- resolver:(RCTPromiseResolveBlock)resolve
- rejecter:(RCTPromiseRejectBlock)reject)
-{
- dispatch_sync(_dictionaryQueue, ^{
- NSString *uuid = _incomingCallUUIDsByCallID[cid];
- if (uuid) {
- resolve(uuid);
- } else {
- NSString *errorString = [NSString stringWithFormat:@"requested incoming call not found for cid: %@", cid];
- reject(@"access_failure", errorString, nil);
- }
- });
-}
-
-RCT_EXPORT_METHOD(getIncomingCallCid:(NSString *)uuid
- resolver:(RCTPromiseResolveBlock)resolve
- rejecter:(RCTPromiseRejectBlock)reject)
-{
- dispatch_sync(_dictionaryQueue, ^{
- NSString *lowercaseUUID = [uuid lowercaseString];
- NSString *foundCid = _incomingCallCidsByUUID[lowercaseUUID];
-
- if (foundCid) {
- resolve(foundCid);
- } else {
- NSString *errorString = [NSString stringWithFormat:@"requested incoming call not found for uuid: %@", uuid];
- reject(@"access_failure", errorString, nil);
- }
- });
-}
-
-RCT_EXPORT_METHOD(removeIncomingCall:(NSString *)cid
- resolver:(RCTPromiseResolveBlock)resolve
- rejecter:(RCTPromiseRejectBlock)reject)
-{
- dispatch_sync(_dictionaryQueue, ^{
- NSString *uuid = _incomingCallUUIDsByCallID[cid];
- if (uuid) {
-#ifdef DEBUG
- NSLog(@"removeIncomingCall cid:%@ -> uuid:%@",cid,uuid);
-#endif
-
- [_incomingCallUUIDsByCallID removeObjectForKey:cid];
- [_incomingCallCidsByUUID removeObjectForKey:uuid];
- resolve(@YES);
- } else {
- resolve(@NO);
- }
- });
-}
-
RCT_EXPORT_METHOD(captureRef:(nonnull NSNumber *)reactTag
options:(NSDictionary *)options
resolver:(RCTPromiseResolveBlock)resolve
diff --git a/packages/react-native-sdk/package.json b/packages/react-native-sdk/package.json
index 5f5f69f7d0..b3fcc514b5 100644
--- a/packages/react-native-sdk/package.json
+++ b/packages/react-native-sdk/package.json
@@ -67,7 +67,7 @@
"expo-notifications": "*",
"react": ">=17.0.0",
"react-native": ">=0.73.0",
- "react-native-callkeep": ">=4.3.11",
+ "react-native-callingx": "workspace:^",
"react-native-gesture-handler": ">=2.8.0",
"react-native-reanimated": ">=2.7.0",
"react-native-svg": ">=13.6.0",
@@ -101,7 +101,7 @@
"expo-notifications": {
"optional": true
},
- "react-native-callkeep": {
+ "react-native-callingx": {
"optional": true
},
"react-native-gesture-handler": {
@@ -143,7 +143,7 @@
"react": "19.1.0",
"react-native": "^0.81.5",
"react-native-builder-bob": "~0.23",
- "react-native-callkeep": "^4.3.16",
+ "react-native-callingx": "workspace:^",
"react-native-gesture-handler": "^2.28.0",
"react-native-reanimated": "~4.1.2",
"react-native-svg": "^15.14.0",
diff --git a/packages/react-native-sdk/src/hooks/push/useCallingExpWithCallingStateEffect.ts b/packages/react-native-sdk/src/hooks/push/useCallingExpWithCallingStateEffect.ts
new file mode 100644
index 0000000000..6160eae289
--- /dev/null
+++ b/packages/react-native-sdk/src/hooks/push/useCallingExpWithCallingStateEffect.ts
@@ -0,0 +1,259 @@
+import {
+ CallingState,
+ MemberResponse,
+ RxUtils,
+ videoLoggerSystem,
+} from '@stream-io/video-client';
+import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
+import { useEffect, useMemo, useRef } from 'react';
+import { getCallingxLibIfAvailable } from '../../utils/push/libs/callingx';
+
+//calling state methods are not exhaustive, so we need to add more methods to cover all the cases
+//for now we can check is state is joined or !joined
+const isAcceptedCallingState = (callingState: CallingState | undefined) => {
+ if (!callingState) {
+ return false;
+ }
+
+ return callingState === CallingState.JOINED;
+};
+
+const logger = videoLoggerSystem.getLogger(
+ 'useCallingExpWithCallingStateEffect',
+);
+
+function getOutcomingDisplayName(
+ members: MemberResponse[] | undefined,
+ currentUserId: string | undefined,
+) {
+ if (!members || !currentUserId) {
+ return 'Unknown';
+ }
+
+ const names = members
+ .filter((member) => member.user_id !== currentUserId)
+ .map((member) => member.user.name)
+ .filter(Boolean);
+
+ return names.length > 0 ? names.join(', ') : 'Unknown';
+}
+
+/**
+ * This hook is used to inform sync call state with CallKit/Telecom (i.e. start call, end call, mute/unmute call).
+ */
+export const useCallingExpWithCallingStateEffect = () => {
+ const { useCallCallingState, useMicrophoneState } = useCallStateHooks();
+
+ const activeCall = useCall();
+ const callingState = useCallCallingState();
+ const { isMute, microphone } = useMicrophoneState();
+
+ const prevState = useRef(undefined);
+
+ const activeCallCid = activeCall?.cid;
+ const isOutcomingCall = activeCall?.isCreatedByMe && activeCall?.ringing; //is this reliable??
+ const currentUserId = activeCall?.currentUserId;
+ const isVideoCall = activeCall?.state.settings?.video?.enabled ?? false;
+
+ const outcomingDisplayName = useMemo(
+ () => getOutcomingDisplayName(activeCall?.state.members, currentUserId),
+ [activeCall?.state.members, currentUserId],
+ );
+
+ useEffect(() => {
+ return () => {
+ const callingx = getCallingxLibIfAvailable();
+ if (!callingx || !activeCallCid) {
+ return;
+ }
+
+ const isCallRegistered = callingx.isCallRegistered(activeCallCid);
+ if (!isCallRegistered) {
+ logger.debug(
+ `No active call cid to end in calling exp: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
+ );
+ return;
+ }
+ //if incoming stream call was unmounted, we need to end the call in CallKit/Telecom
+ logger.debug(`Ending call in calling exp: ${activeCallCid}`);
+ callingx
+ .endCallWithReason(activeCallCid, 'local')
+ .catch((error: unknown) => {
+ logger.error(
+ `Error ending call in calling exp: ${activeCallCid}`,
+ error,
+ );
+ });
+ };
+ }, [activeCallCid]);
+
+ useEffect(() => {
+ const callingx = getCallingxLibIfAvailable();
+ if (!callingx || !activeCallCid || prevState.current === callingState) {
+ return;
+ }
+
+ //tells if call is registered in CallKit/Telecom
+ const isCallRegistered = callingx.isCallRegistered(activeCallCid);
+ logger.debug(
+ `useEffect: ${activeCallCid} isCallRegistered: ${isCallRegistered} isOutcomingCall: ${isOutcomingCall}`,
+ );
+ logger.debug(
+ `prevState.current: ${prevState.current}, current callingState: ${callingState}`,
+ );
+ logger.debug(
+ `isOutcomingCallsEnabled: ${callingx.isOutcomingCallsEnabled}`,
+ );
+
+ if (
+ !isAcceptedCallingState(prevState.current) &&
+ isAcceptedCallingState(callingState)
+ ) {
+ if (
+ isOutcomingCall &&
+ !isCallRegistered &&
+ callingx.isOutcomingCallsEnabled
+ ) {
+ //we request start call action from CallKit/Telecom, next step is to make call active when we receive call started event
+ logger.debug(`Should start call in callkeep: ${activeCallCid}`);
+ callingx
+ .startCall(
+ activeCallCid,
+ activeCallCid,
+ outcomingDisplayName,
+ isVideoCall,
+ )
+ .catch((error: unknown) => {
+ logger.error(
+ `Error starting call in calling exp: ${activeCallCid}`,
+ error,
+ );
+ });
+ } else if (!isOutcomingCall && isCallRegistered) {
+ logger.debug(
+ `Should accept call in callkeep: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
+ );
+ callingx.answerIncomingCall(activeCallCid).catch((error: unknown) => {
+ logger.error(
+ `Error answering call in calling exp: ${activeCallCid}`,
+ error,
+ );
+ });
+ }
+ } else if (
+ isAcceptedCallingState(prevState.current) &&
+ !isAcceptedCallingState(callingState) &&
+ isCallRegistered
+ ) {
+ //in case call was registered as incoming and state changed to "not joined", we need to end the call and clear rxjs subject
+ logger.debug(`Should end call in callkeep: ${activeCallCid}`);
+ //TODO: think about sending appropriate reason for end call
+ callingx
+ .endCallWithReason(activeCallCid, 'local')
+ .catch((error: unknown) => {
+ logger.error(
+ `Error ending call in calling exp: ${activeCallCid}`,
+ error,
+ );
+ });
+ }
+
+ prevState.current = callingState;
+ }, [
+ activeCallCid,
+ callingState,
+ isOutcomingCall,
+ outcomingDisplayName,
+ isVideoCall,
+ ]);
+
+ useEffect(() => {
+ const callingx = getCallingxLibIfAvailable();
+ if (!callingx || !activeCallCid) {
+ return;
+ }
+
+ //listen to start call action from CallKit/Telecom and set the current call active
+ const subscription = callingx.addEventListener(
+ 'didReceiveStartCallAction',
+ ({ callId }: { callId: string }) => {
+ if (callId === activeCallCid) {
+ logger.debug(`Received start call action for call: ${activeCallCid}`);
+ callingx
+ .setCurrentCallActive(activeCallCid)
+ .catch((error: unknown) => {
+ logger.error(
+ `Error answering call in calling exp: ${activeCallCid}`,
+ error,
+ );
+ });
+ }
+ },
+ );
+
+ return () => {
+ subscription.remove();
+ };
+ }, [activeCallCid]);
+
+ useEffect(() => {
+ const callingx = getCallingxLibIfAvailable();
+ if (!callingx || !activeCallCid) {
+ return;
+ }
+
+ const isCallRegistered = callingx.isCallRegistered(activeCallCid);
+ if (!isCallRegistered) {
+ logger.debug(
+ `No active call cid to set muted in calling exp: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
+ );
+ return;
+ }
+
+ callingx.setMutedCall(activeCallCid, isMute);
+ }, [activeCallCid, isMute]);
+
+ useEffect(() => {
+ const callingx = getCallingxLibIfAvailable();
+ if (!callingx || !activeCallCid) {
+ return;
+ }
+
+ //listen to mic toggle events from CallKit/Telecom and update stream call microphone state
+ const subscription = callingx.addEventListener(
+ 'didPerformSetMutedCallAction',
+ async (event: { callId: string; muted: boolean }) => {
+ const { callId, muted } = event;
+
+ if (callId === activeCallCid) {
+ const isCurrentlyMuted =
+ RxUtils.getCurrentValue(microphone.state.status$) === 'disabled';
+ if (isCurrentlyMuted === muted) {
+ logger.debug(
+ `Mic toggle is already in the desired state: ${muted} for call: ${activeCallCid}`,
+ );
+ //this check prevents mic toggle when state change was initiated from client and not from CallKit/Telecom
+ return;
+ }
+
+ try {
+ if (muted) {
+ await microphone.disable();
+ } else {
+ await microphone.enable();
+ }
+ } catch (error: unknown) {
+ logger.error(
+ `Error toggling mic in calling exp: ${activeCallCid}`,
+ error,
+ );
+ }
+ }
+ },
+ );
+
+ return () => {
+ subscription.remove();
+ };
+ }, [activeCallCid, microphone]);
+};
diff --git a/packages/react-native-sdk/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts b/packages/react-native-sdk/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts
deleted file mode 100644
index 24b6de9b4d..0000000000
--- a/packages/react-native-sdk/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts
+++ /dev/null
@@ -1,235 +0,0 @@
-import {
- CallingState,
- RxUtils,
- videoLoggerSystem,
-} from '@stream-io/video-client';
-import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
-import { NativeModules, Platform } from 'react-native';
-import { useEffect, useState } from 'react';
-import { StreamVideoRN } from '../../utils';
-import { getCallKeepLib } from '../../utils/push/libs';
-import {
- voipCallkeepAcceptedCallOnNativeDialerMap$,
- voipCallkeepCallOnForegroundMap$,
- voipPushNotificationCallCId$,
-} from '../../utils/push/internal/rxSubjects';
-
-const isNonActiveCallingState = (callingState: CallingState) => {
- return (
- callingState === CallingState.IDLE ||
- callingState === CallingState.UNKNOWN ||
- callingState === CallingState.LEFT
- );
-};
-
-const isAcceptedCallingState = (callingState: CallingState) => {
- return (
- callingState === CallingState.JOINING ||
- callingState === CallingState.JOINED
- );
-};
-
-const unsubscribeCallkeepEvents = async (activeCallCid: string | undefined) => {
- const voipPushNotificationCallCId = RxUtils.getCurrentValue(
- voipPushNotificationCallCId$,
- );
- if (activeCallCid && activeCallCid === voipPushNotificationCallCId) {
- // callkeep events should not be listened anymore so clear the call cid
- voipPushNotificationCallCId$.next(undefined);
- }
- return await NativeModules.StreamVideoReactNative?.removeIncomingCall(
- activeCallCid,
- );
-};
-
-const logger = videoLoggerSystem.getLogger(
- 'useIosCallkeepWithCallingStateEffect',
-);
-const log = (message: string) => {
- logger.warn(message);
-};
-
-/**
- * This hook is used to inform the callkeep library that the call has been joined or ended.
- */
-export const useIosCallkeepWithCallingStateEffect = () => {
- const activeCall = useCall();
- const { useCallCallingState } = useCallStateHooks();
- const callingState = useCallCallingState();
- const [acceptedForegroundCallkeepMap, setAcceptedForegroundCallkeepMap] =
- useState<{
- uuid: string;
- cid: string;
- }>();
-
- useEffect(() => {
- return () => {
- const pushConfig = StreamVideoRN.getConfig().push;
- if (
- Platform.OS !== 'ios' ||
- !pushConfig ||
- !pushConfig.ios?.pushProviderName
- ) {
- return;
- }
- if (!pushConfig.android.incomingCallChannel) {
- // TODO: remove this check and find a better way once we have telecom integration for android
- return;
- }
-
- const callkeep = getCallKeepLib();
- // if the component is unmounted and the callID was not reported to callkeep, then report it now
- if (acceptedForegroundCallkeepMap) {
- log(
- `Ending call in callkeep: ${acceptedForegroundCallkeepMap.cid}, reason: component unmounted and call was present in acceptedForegroundCallkeepMap`,
- );
- unsubscribeCallkeepEvents(acceptedForegroundCallkeepMap.cid).then(() =>
- callkeep.endCall(acceptedForegroundCallkeepMap.uuid),
- );
- }
- };
- }, [acceptedForegroundCallkeepMap]);
-
- const activeCallCid = activeCall?.cid;
-
- useEffect(() => {
- return () => {
- const pushConfig = StreamVideoRN.getConfig().push;
- if (
- Platform.OS !== 'ios' ||
- !pushConfig ||
- !pushConfig.ios?.pushProviderName ||
- !activeCallCid
- ) {
- return;
- }
- if (!pushConfig.android.incomingCallChannel) {
- // TODO: remove this check and find a better way once we have telecom integration for android
- return;
- }
- const nativeDialerAcceptedCallMap = RxUtils.getCurrentValue(
- voipCallkeepAcceptedCallOnNativeDialerMap$,
- );
- const foregroundIncomingCallkeepMap = RxUtils.getCurrentValue(
- voipCallkeepCallOnForegroundMap$,
- );
- const callkeep = getCallKeepLib();
- if (activeCallCid === nativeDialerAcceptedCallMap?.cid) {
- log(
- `Ending call in callkeep: ${activeCallCid}, reason: activeCallCid changed or was removed and call was present in nativeDialerAcceptedCallMap`,
- );
- unsubscribeCallkeepEvents(activeCallCid).then(() =>
- callkeep.endCall(nativeDialerAcceptedCallMap.uuid),
- );
- // no need to keep this reference anymore
- voipCallkeepAcceptedCallOnNativeDialerMap$.next(undefined);
- } else if (activeCallCid === foregroundIncomingCallkeepMap?.cid) {
- log(
- `Ending call in callkeep: ${activeCallCid}, reason: activeCallCid changed or was removed and call was present in foregroundIncomingCallkeepMap`,
- );
- unsubscribeCallkeepEvents(activeCallCid).then(() =>
- callkeep.endCall(foregroundIncomingCallkeepMap.uuid),
- );
- }
- };
- }, [activeCallCid]);
-
- const pushConfig = StreamVideoRN.getConfig().push;
- if (
- Platform.OS !== 'ios' ||
- !pushConfig ||
- !pushConfig.ios.pushProviderName ||
- !activeCallCid
- ) {
- return;
- }
- if (!pushConfig.android.incomingCallChannel) {
- // TODO: remove this check and find a better way once we have telecom integration for android
- return;
- }
-
- /**
- * Check if current call is still needed to be accepted in callkeep
- */
- if (
- isAcceptedCallingState(callingState) &&
- acceptedForegroundCallkeepMap?.cid !== activeCallCid
- ) {
- const callkeep = getCallKeepLib();
- // push notification was displayed
- // but the call has been accepted through the app and not through the native dialer
- const foregroundCallkeepMap = RxUtils.getCurrentValue(
- voipCallkeepCallOnForegroundMap$,
- );
- if (foregroundCallkeepMap && foregroundCallkeepMap.cid === activeCallCid) {
- log(
- // @ts-expect-error - types issue
- `Accepting call in callkeep: ${activeCallCid}, reason: callingstate went to ${CallingState[callingState]} and call was present in foregroundCallkeepMap`,
- );
- // no need to keep this reference anymore
- voipCallkeepCallOnForegroundMap$.next(undefined);
- NativeModules.StreamVideoReactNative?.removeIncomingCall(
- activeCallCid,
- ).then(() => callkeep.answerIncomingCall(foregroundCallkeepMap.uuid));
- // this call should be accepted in callkeep
- setAcceptedForegroundCallkeepMap(foregroundCallkeepMap);
- }
- }
-
- /**
- * Check if current call is still needed to be ended in callkeep
- */
- if (isNonActiveCallingState(callingState)) {
- const callkeep = getCallKeepLib();
-
- // this was a previously joined call which had push notification displayed
- // the call was accepted through the app and not through native dialer
- // the call was left using the leave button in the app and not through native dialer
- if (activeCallCid === acceptedForegroundCallkeepMap?.cid) {
- log(
- // @ts-expect-error - types issue
- `Ending call in callkeep: ${activeCallCid}, reason: callingstate went to ${CallingState[callingState]} and call was present in acceptedForegroundCallkeepMap`,
- );
- unsubscribeCallkeepEvents(activeCallCid).then(() =>
- callkeep.endCall(acceptedForegroundCallkeepMap.uuid),
- );
- setAcceptedForegroundCallkeepMap(undefined);
- return;
- }
- // this was a call which had push notification displayed but never joined
- // the user rejected in the app and not from native dialer
- const foregroundIncomingCallkeepMap = RxUtils.getCurrentValue(
- voipCallkeepCallOnForegroundMap$,
- );
- if (activeCallCid === foregroundIncomingCallkeepMap?.cid) {
- log(
- // @ts-expect-error - types issue
- `Ending call in callkeep: ${activeCallCid}, reason: callingstate went to ${CallingState[callingState]} and call was present in foregroundIncomingCallkeepMap`,
- );
- unsubscribeCallkeepEvents(activeCallCid).then(() =>
- callkeep.endCall(foregroundIncomingCallkeepMap.uuid),
- );
- // no need to keep this reference anymore
- voipCallkeepCallOnForegroundMap$.next(undefined);
- return;
- }
- // this was a previously joined call
- // it was an accepted call from native dialer and not from the app
- // the user left using the leave button in the app
- const nativeDialerAcceptedCallMap = RxUtils.getCurrentValue(
- voipCallkeepAcceptedCallOnNativeDialerMap$,
- );
- if (activeCallCid === nativeDialerAcceptedCallMap?.cid) {
- log(
- // @ts-expect-error - types issue
- `Ending call in callkeep: ${activeCallCid}, reason: callingstate went to ${CallingState[callingState]} and call was present in nativeDialerAcceptedCallMap`,
- );
- unsubscribeCallkeepEvents(activeCallCid).then(() =>
- callkeep.endCall(nativeDialerAcceptedCallMap.uuid),
- );
- // no need to keep this reference anymore
- voipCallkeepAcceptedCallOnNativeDialerMap$.next(undefined);
- return;
- }
- }
-};
diff --git a/packages/react-native-sdk/src/providers/StreamCall/index.tsx b/packages/react-native-sdk/src/providers/StreamCall/index.tsx
index 6748eaac21..174bf037e4 100644
--- a/packages/react-native-sdk/src/providers/StreamCall/index.tsx
+++ b/packages/react-native-sdk/src/providers/StreamCall/index.tsx
@@ -1,12 +1,12 @@
import { StreamCallProvider } from '@stream-io/video-react-bindings';
import React, { type PropsWithChildren, useEffect } from 'react';
import { Call } from '@stream-io/video-client';
-import { useIosCallkeepWithCallingStateEffect } from '../../hooks/push/useIosCallkeepWithCallingStateEffect';
import { canAddPushWSSubscriptionsRef } from '../../utils/push/internal/utils';
import { useAndroidKeepCallAliveEffect } from '../../hooks/useAndroidKeepCallAliveEffect';
import { AppStateListener } from './AppStateListener';
import { DeviceStats } from './DeviceStats';
import { pushUnsubscriptionCallbacks } from '../../utils/push/internal/constants';
+import { useCallingExpWithCallingStateEffect } from '../../hooks/push/useCallingExpWithCallingStateEffect';
// const PIP_CHANGE_EVENT = 'StreamVideoReactNative_PIP_CHANGE_EVENT';
@@ -34,7 +34,7 @@ export const StreamCall = ({
-
+
{children}
@@ -52,11 +52,11 @@ const AndroidKeepCallAlive = () => {
};
/**
- * This is a renderless component to end the call in callkeep for ios.
- * useAndroidKeepCallAliveEffect needs to called inside a child of StreamCallProvider.
+ * This is a renderless component to sync state between stream call and CallKit/Telecom.
+ * useCallingExpWithCallingStateEffect needs to called inside a child of StreamCallProvider.
*/
-const IosInformCallkeepCallEnd = () => {
- useIosCallkeepWithCallingStateEffect();
+const CallingExpWithCallingState = () => {
+ useCallingExpWithCallingStateEffect();
return null;
};
diff --git a/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts b/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts
index ca45cf4c50..3e5b1e5706 100644
--- a/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts
+++ b/packages/react-native-sdk/src/utils/StreamVideoRN/index.ts
@@ -1,11 +1,14 @@
+import { type Options as CallingxOptions } from 'react-native-callingx';
import type { StreamVideoConfig } from './types';
import pushLogoutCallbacks from '../internal/pushLogoutCallback';
import newNotificationCallbacks, {
type NewCallNotificationCallback,
} from '../internal/newNotificationCallbacks';
-import { setupIosCallKeepEvents } from '../push/setupIosCallKeepEvents';
import { setupIosVoipPushEvents } from '../push/setupIosVoipPushEvents';
+import { setupCallingExpEvents } from '../push/setupCallingExpEvents';
+import { getCallingxLib } from '../push/libs/callingx';
import { NativeModules, Platform } from 'react-native';
+import { videoLoggerSystem } from '@stream-io/video-client';
// Utility type for deep partial
type DeepPartial = {
@@ -123,10 +126,15 @@ export class StreamVideoRN {
this.config.push = pushConfig;
- setupIosCallKeepEvents(pushConfig);
+ setupCallingExpEvents(pushConfig);
setupIosVoipPushEvents(pushConfig);
}
+ static setupCallingExp(options: CallingxOptions) {
+ const callingx = getCallingxLib();
+ callingx.setup(options);
+ }
+
static getConfig() {
return this.config;
}
diff --git a/packages/react-native-sdk/src/utils/push/android.ts b/packages/react-native-sdk/src/utils/push/android.ts
index 0937fd3a26..3333028325 100644
--- a/packages/react-native-sdk/src/utils/push/android.ts
+++ b/packages/react-native-sdk/src/utils/push/android.ts
@@ -1,10 +1,9 @@
import {
- Call,
CallingState,
StreamVideoClient,
videoLoggerSystem,
} from '@stream-io/video-client';
-import { AppState, Platform } from 'react-native';
+import { Platform } from 'react-native';
import type {
NonRingingPushEvent,
StreamVideoConfig,
@@ -15,30 +14,15 @@ import {
getExpoNotificationsLibNoThrow,
getFirebaseMessagingLib,
getFirebaseMessagingLibNoThrow,
- getIncomingCallForegroundServiceTypes,
getNotifeeLibThrowIfNotInstalledForPush,
type NotifeeLib,
} from './libs';
-import {
- pushAcceptedIncomingCallCId$,
- pushAndroidBackgroundDeliveredIncomingCallCId$,
- pushNonRingingCallData$,
- pushRejectedIncomingCallCId$,
- pushTappedIncomingCallCId$,
-} from './internal/rxSubjects';
+import { pushNonRingingCallData$ } from './internal/rxSubjects';
import { pushUnsubscriptionCallbacks } from './internal/constants';
-import {
- canAddPushWSSubscriptionsRef,
- clearPushWSEventSubscriptions,
- processCallFromPushInBackground,
- shouldCallBeEnded,
-} from './internal/utils';
+import { canListenToWS, shouldCallBeClosed } from './internal/utils';
import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
-import { getAndroidDefaultRingtoneUrl } from '../getAndroidDefaultRingtoneUrl';
import { StreamVideoRN } from '../StreamVideoRN';
-
-const ACCEPT_CALL_ACTION_ID = 'accept';
-const DECLINE_CALL_ACTION_ID = 'decline';
+import { getCallingxLib } from './libs/callingx';
type PushConfig = NonNullable;
@@ -127,10 +111,10 @@ export async function initAndroidPushToken(
* Creates notification from the push message data.
* For Ringing and Non-Ringing calls.
*/
+
export const firebaseDataHandler = async (
data: FirebaseMessagingTypes.RemoteMessage['data'],
) => {
- if (Platform.OS !== 'android') return;
/* Example data from firebase
"message": {
"data": {
@@ -146,279 +130,254 @@ export const firebaseDataHandler = async (
// other stuff
}
*/
+ if (Platform.OS !== 'android') return;
+
+ const logger = videoLoggerSystem.getLogger('firebaseDataHandler');
const pushConfig = StreamVideoRN.getConfig().push;
if (!pushConfig || !data || data.sender !== 'stream.video') {
return;
}
- const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
- const notifee = notifeeLib.default;
- const settings = await notifee.getNotificationSettings();
- if (settings.authorizationStatus !== 1) {
- const logger = videoLoggerSystem.getLogger('firebaseDataHandler');
- logger.debug(
- `Notification permission not granted, unable to post ${data.type} notifications`,
- );
- return;
- }
if (data.type === 'call.ring') {
const call_cid = data.call_cid as string;
- const created_by_id = data.created_by_id as string;
- const receiver_id = data.receiver_id as string;
+ if (!call_cid) {
+ logger.debug(
+ `call_cid is not provided, skipping the call.ring notification`,
+ );
+ return;
+ }
- const video_client = await pushConfig.createStreamVideoClient();
- await video_client?.onRingingCall(call_cid);
+ const callingx = getCallingxLib();
- const shouldCallBeClosed = (callToCheck: Call) => {
- const { mustEndCall } = shouldCallBeEnded(
- callToCheck,
- created_by_id,
- receiver_id,
+ if (callingx.hasRegisteredCall()) {
+ logger.debug(
+ `registered call found, skipping the call.ring notification`,
+ );
+ return;
+ }
+
+ await callingx.checkPermissions();
+ if (!callingx.isNotificationsAllowed) {
+ logger.debug(
+ `Notification permission not granted, unable to post ${data.type} notifications`,
);
- return mustEndCall;
- };
+ return;
+ }
+
+ const client = await pushConfig.createStreamVideoClient();
+ if (!client) {
+ logger.debug(
+ `video client not found, skipping the call.ring notification`,
+ );
+ return;
+ }
- const canListenToWS = () =>
- canAddPushWSSubscriptionsRef.current &&
- AppState.currentState !== 'active';
const asForegroundService = canListenToWS();
+ const phoneNumber = data.created_by_display_name as string;
+ const callerName = data.created_by_display_name as string;
+ const hasVideo = data.video === 'true';
+
+ await callingx.displayIncomingCall(
+ call_cid,
+ phoneNumber,
+ callerName,
+ hasVideo,
+ );
+ logger.debug(
+ `Displaying incoming call notification with callCid: ${call_cid} asForegroundService: ${asForegroundService}`,
+ );
+
if (asForegroundService) {
// Listen to call events from WS through fg service
// note: this will replace the current empty fg service runner
- notifee.registerForegroundService(() => {
- return new Promise(async () => {
- const client = await pushConfig.createStreamVideoClient();
- if (!client) {
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Closing fg service as there is no client to create from push config`,
- );
- notifee.stopForegroundService();
+ //we need to start service (e.g. by calling display incoming call) and than launch bg task, consider making those steps independent
+ await callingx.startBackgroundTask((_: unknown, stopTask: () => void) => {
+ return new Promise(async (resolve) => {
+ const finishBackgroundTask = () => {
+ resolve(undefined);
+ stopTask();
+ };
+
+ const _client = await pushConfig.createStreamVideoClient();
+ if (!_client) {
+ logger.debug(
+ `Closing fg service as there is no client to create from push config`,
+ );
+ finishBackgroundTask();
return;
}
- const callFromPush = await client.onRingingCall(call_cid);
- let _shouldCallBeClosed = shouldCallBeClosed(callFromPush);
- if (_shouldCallBeClosed) {
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Closing fg service callCid: ${call_cid} shouldCallBeClosed: ${_shouldCallBeClosed}`,
- );
- notifee.stopForegroundService();
+
+ const callFromPush = await _client.onRingingCall(call_cid);
+ if (shouldCallBeClosed(callFromPush, data)) {
+ logger.debug(
+ `Closing fg service callCid: ${call_cid} shouldCallBeClosed`,
+ );
+
+ finishBackgroundTask();
+ callingx.log(
+ `Ending call with callCid: ${call_cid} shouldCallBeClosed`,
+ 'debug',
+ );
+ //TODO: think about sending appropriate reason for end call
+ callingx.endCallWithReason(call_cid, 'remote');
return;
}
+
const unsubscribeFunctions: Array<() => void> = [];
// check if service needs to be closed if accept/decline event was done on another device
const unsubscribe = callFromPush.on('all', (event) => {
const _canListenToWS = canListenToWS();
if (!_canListenToWS) {
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Closing fg service from event callCid: ${call_cid} canListenToWS: ${_canListenToWS}`,
- { event },
- );
+ logger.debug(
+ `Closing fg service from event callCid: ${call_cid} canListenToWS: ${_canListenToWS}`,
+ { event },
+ );
unsubscribeFunctions.forEach((fn) => fn());
- notifee.stopForegroundService();
+
+ finishBackgroundTask();
return;
}
- _shouldCallBeClosed = shouldCallBeClosed(callFromPush);
- if (_shouldCallBeClosed) {
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Closing fg service from event callCid: ${call_cid} canListenToWS: ${_canListenToWS} shouldCallBeClosed: ${_shouldCallBeClosed}`,
- { event },
- );
+
+ if (shouldCallBeClosed(callFromPush, data)) {
+ logger.debug(
+ `Closing fg service from event callCid: ${call_cid} canListenToWS: ${_canListenToWS} shouldCallBeClosed`,
+ { event },
+ );
unsubscribeFunctions.forEach((fn) => fn());
- notifee.stopForegroundService();
+
+ finishBackgroundTask();
+ //TODO: think about sending appropriate reason for end call
+ callingx.endCallWithReason(call_cid, 'rejected');
}
});
+
// check if service needs to be closed if call was left
- const subscription = callFromPush.state.callingState$.subscribe(
+ const stateSubscription = callFromPush.state.callingState$.subscribe(
(callingState) => {
if (
callingState === CallingState.IDLE ||
callingState === CallingState.LEFT
) {
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Closing fg service from callingState callCid: ${call_cid} callingState: ${callingState}`,
- );
+ logger.debug(
+ `Closing fg service from callingState callCid: ${call_cid} callingState: ${callingState}`,
+ );
unsubscribeFunctions.forEach((fn) => fn());
- notifee.stopForegroundService();
+
+ //TODO: think about sending appropriate reason for end call
+ callingx.log(
+ `Ending call with callCid: ${call_cid} callingState: ${callingState}`,
+ 'debug',
+ );
+ finishBackgroundTask();
+ callingx.endCallWithReason(call_cid, 'remote');
}
},
);
+
+ const endCallSubscription = callingx.addEventListener(
+ 'endCall',
+ async ({ callId }: { callId: string }) => {
+ unsubscribeFunctions.forEach((fn) => fn());
+ try {
+ await callFromPush.leave({ reject: true, reason: 'decline' });
+ } catch (error) {
+ logger.error(
+ `Failed to leave call with callCid: ${call_cid} error: ${error}`,
+ );
+ } finally {
+ callingx.log(
+ `Ending call with callCid: ${call_cid} callId: ${callId}`,
+ 'debug',
+ );
+ finishBackgroundTask();
+ callingx.endCallWithReason(callId, 'rejected');
+ }
+ },
+ );
+
unsubscribeFunctions.push(unsubscribe);
- unsubscribeFunctions.push(() => subscription.unsubscribe());
+ unsubscribeFunctions.push(() => stateSubscription.unsubscribe());
+ unsubscribeFunctions.push(() => endCallSubscription.remove());
pushUnsubscriptionCallbacks.get(call_cid)?.forEach((cb) => cb());
pushUnsubscriptionCallbacks.set(call_cid, unsubscribeFunctions);
});
});
}
- const incomingCallChannel = pushConfig.android.incomingCallChannel;
- const incomingCallNotificationTextGetters =
- pushConfig.android.incomingCallNotificationTextGetters;
- if (!incomingCallChannel || !incomingCallNotificationTextGetters) {
- const logger = videoLoggerSystem.getLogger(
- 'firebaseMessagingOnMessageHandler',
- );
- logger.error(
- "Can't show incoming call notification as either or both incomingCallChannel and incomingCallNotificationTextGetters were not provided",
- );
- return;
- }
- /*
- * Sound has to be set on channel level for android 8 and above and cant be updated later after creation!
- * For android 7 and below, sound should be set on notification level
- */
- // set default ringtone if not provided
- if (!incomingCallChannel.sound) {
- incomingCallChannel.sound = await getAndroidDefaultRingtoneUrl();
- }
- await notifee.createChannel(incomingCallChannel);
- const { getTitle, getBody, getAcceptButtonTitle, getDeclineButtonTitle } =
- incomingCallNotificationTextGetters;
- const createdUserName = data.created_by_display_name as string;
-
- const title = getTitle(createdUserName);
- const body = getBody(createdUserName);
-
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Displaying incoming call notification with callCid: ${call_cid} title: ${title} body: ${body} asForegroundService: ${asForegroundService}`,
- );
-
- const channelId = incomingCallChannel.id;
- await notifee.displayNotification({
- id: call_cid,
- title: getTitle(createdUserName),
- body: getBody(createdUserName),
- data,
- android: {
- channelId,
- smallIcon: pushConfig.android.smallIcon,
- importance: 4, // high importance
- foregroundServiceTypes: getIncomingCallForegroundServiceTypes(),
- asForegroundService,
- ongoing: true,
- sound: incomingCallChannel.sound,
- vibrationPattern: incomingCallChannel.vibrationPattern,
- loopSound: true,
- pressAction: {
- id: 'default',
- launchActivity: 'default', // open the app when the notification is pressed
- },
- actions: [
- {
- title: getDeclineButtonTitle?.() ?? 'Decline',
- pressAction: {
- id: DECLINE_CALL_ACTION_ID,
- },
- },
- {
- title: getAcceptButtonTitle?.() ?? 'Accept',
- pressAction: {
- id: ACCEPT_CALL_ACTION_ID,
- launchActivity: 'default', // open the app when the notification is pressed
- },
- },
- ],
- category: notifeeLib.AndroidCategory.CALL,
- fullScreenAction: {
- id: 'stream_ringing_incoming_call',
- },
- timeoutAfter: 60000, // 60 seconds, after which the notification will be dismissed automatically
- },
- });
if (asForegroundService) {
// no need to check if call has be closed as that will be handled by the fg service
return;
}
- // check if call needs to be closed if accept/decline event was done
- // before the notification was shown
- const client = await pushConfig.createStreamVideoClient();
- if (!client) {
- return;
- }
const callFromPush = await client.onRingingCall(call_cid);
- if (shouldCallBeClosed(callFromPush)) {
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
- `Removing incoming call notification immediately with callCid: ${call_cid} as it should be closed`,
- );
- notifee.cancelDisplayedNotification(call_cid);
+ if (shouldCallBeClosed(callFromPush, data)) {
+ logger.debug(
+ `Removing incoming call notification immediately with callCid: ${call_cid} as it should be closed`,
+ );
+ //TODO: think about sending appropriate reason for end call
+ callingx.endCallWithReason(call_cid, 'remote');
}
} else {
- // the other types are call.live_started and call.notification
- const callChannel = pushConfig.android.callChannel;
- const callNotificationTextGetters =
- pushConfig.android.callNotificationTextGetters;
- if (!callChannel || !callNotificationTextGetters) {
- const logger = videoLoggerSystem.getLogger(
- 'firebaseMessagingOnMessageHandler',
- );
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
+ const notifee = notifeeLib.default;
+ const settings = await notifee.getNotificationSettings();
+ if (settings.authorizationStatus !== 1) {
logger.debug(
- "Can't show call notification as either or both callChannel and callNotificationTextGetters is not provided",
+ `Notification permission not granted, unable to post ${data.type} notifications`,
);
- return;
- }
- await notifee.createChannel(callChannel);
- const channelId = callChannel.id;
- const { getTitle, getBody } = callNotificationTextGetters;
- const createdUserName = data.created_by_display_name as string;
- // we can safely cast to string because the data is from "stream.video"
- const type = data.type as NonRingingPushEvent;
- const title = getTitle(type, createdUserName);
- const body = getBody(type, createdUserName);
+ // the other types are call.live_started and call.notification
+ const callChannel = pushConfig.android.callChannel;
+ const callNotificationTextGetters =
+ pushConfig.android.callNotificationTextGetters;
+ if (!callChannel || !callNotificationTextGetters) {
+ logger.debug(
+ "Can't show call notification as either or both callChannel and callNotificationTextGetters is not provided",
+ );
+ return;
+ }
+ await notifee.createChannel(callChannel);
+ const channelId = callChannel.id;
+ const { getTitle, getBody } = callNotificationTextGetters;
+ const createdUserName = data.created_by_display_name as string;
+ // we can safely cast to string because the data is from "stream.video"
+ const type = data.type as NonRingingPushEvent;
+
+ const title = getTitle(type, createdUserName);
+ const body = getBody(type, createdUserName);
- videoLoggerSystem
- .getLogger('firebaseMessagingOnMessageHandler')
- .debug(
+ logger.debug(
`Displaying NonRingingPushEvent ${type} notification with title: ${title} body: ${body}`,
);
- await notifee.displayNotification({
- title: getTitle(type, createdUserName),
- body: getBody(type, createdUserName),
- data,
- android: {
- sound: callChannel.sound,
- smallIcon: pushConfig.android.smallIcon,
- vibrationPattern: callChannel.vibrationPattern,
- channelId,
- importance: 4, // high importance
- pressAction: {
- id: 'default',
- launchActivity: 'default', // open the app when the notification is pressed
+ await notifee.displayNotification({
+ title: getTitle(type, createdUserName),
+ body: getBody(type, createdUserName),
+ data,
+ android: {
+ sound: callChannel.sound,
+ smallIcon: pushConfig.android.smallIcon,
+ vibrationPattern: callChannel.vibrationPattern,
+ channelId,
+ importance: 4, // high importance
+ pressAction: {
+ id: 'default',
+ launchActivity: 'default', // open the app when the notification is pressed
+ },
+ timeoutAfter: 60000, // 60 seconds, after which the notification will be dismissed automatically
},
- timeoutAfter: 60000, // 60 seconds, after which the notification will be dismissed automatically
- },
- });
- const cid = data.call_cid as string;
- pushNonRingingCallData$.next({ cid, type });
+ });
+ const cid = data.call_cid as string;
+ pushNonRingingCallData$.next({ cid, type });
+ }
}
};
-export const onAndroidNotifeeEvent = async ({
- event,
- isBackground,
-}: {
- event: Event;
- isBackground: boolean;
-}) => {
+export const onAndroidNotifeeEvent = async ({ event }: { event: Event }) => {
if (Platform.OS !== 'android') return;
const { type, detail } = event;
- const { notification, pressAction } = detail;
+ const { notification } = detail;
const notificationId = notification?.id;
const data = notification?.data;
const pushConfig = StreamVideoRN.getConfig().push;
@@ -434,92 +393,14 @@ export const onAndroidNotifeeEvent = async ({
// we can safely cast to string because the data is from "stream.video"
const call_cid = data.call_cid as string;
- if (data.type === 'call.ring') {
- // check if we have observers for the call cid (this means the app is in the foreground state)
- const hasObservers =
- pushAcceptedIncomingCallCId$.observed &&
- pushRejectedIncomingCallCId$.observed;
-
- const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
- const notifee = notifeeLib.default;
- // Check if we need to decline the call
- const didPressDecline =
- type === notifeeLib.EventType.ACTION_PRESS &&
- pressAction?.id === DECLINE_CALL_ACTION_ID;
- const didDismiss = type === notifeeLib.EventType.DISMISSED;
- const mustDecline = didPressDecline || didDismiss;
- // Check if we need to accept the call
- const mustAccept =
- type === notifeeLib.EventType.ACTION_PRESS &&
- pressAction?.id === ACCEPT_CALL_ACTION_ID;
-
- if (
- mustAccept ||
- mustDecline ||
- type === notifeeLib.EventType.ACTION_PRESS
- ) {
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(
- `clearPushWSEventSubscriptions for callCId: ${call_cid} mustAccept: ${mustAccept} mustDecline: ${mustDecline}`,
- );
- clearPushWSEventSubscriptions(call_cid);
- notifee.stopForegroundService();
- }
-
- if (mustAccept) {
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(`pushAcceptedIncomingCallCId$ added with callCId: ${call_cid}`);
- pushAcceptedIncomingCallCId$.next(call_cid);
- // NOTE: accept will be handled by the app with rxjs observers as the app will go to foreground always
- } else if (mustDecline) {
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(`pushRejectedIncomingCallCId$ added with callCId: ${call_cid}`);
- pushRejectedIncomingCallCId$.next(call_cid);
- if (hasObservers) {
- // if we had observers we can return here as the observers will handle the call as the app is in the foreground state
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(
- `Skipped processCallFromPushInBackground for Declining call with callCId: ${call_cid} as the app is in the foreground state`,
- );
- return;
- }
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(
- `start processCallFromPushInBackground - Declining call with callCId: ${call_cid}`,
- );
- await processCallFromPushInBackground(pushConfig, call_cid, 'decline');
- } else {
- if (type === notifeeLib.EventType.PRESS) {
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(`pushTappedIncomingCallCId$ added with callCId: ${call_cid}`);
- pushTappedIncomingCallCId$.next(call_cid);
- // pressed state will be handled by the app with rxjs observers as the app will go to foreground always
- } else if (isBackground && type === notifeeLib.EventType.DELIVERED) {
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(
- `pushAndroidBackgroundDeliveredIncomingCallCId$ added with callCId: ${call_cid}`,
- );
- pushAndroidBackgroundDeliveredIncomingCallCId$.next(call_cid);
- // background delivered state will be handled by the app with rxjs observers as processing needs to happen only when app is opened
- }
- }
- } else {
- const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
- if (type === notifeeLib.EventType.PRESS) {
- videoLoggerSystem
- .getLogger('onAndroidNotifeeEvent')
- .debug(`onTapNonRingingCallNotification with callCId: ${call_cid}`);
- pushConfig.onTapNonRingingCallNotification?.(
- call_cid,
- data.type as NonRingingPushEvent,
- );
- }
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
+ if (type === notifeeLib.EventType.PRESS) {
+ videoLoggerSystem
+ .getLogger('onAndroidNotifeeEvent')
+ .debug(`onTapNonRingingCallNotification with callCId: ${call_cid}`);
+ pushConfig.onTapNonRingingCallNotification?.(
+ call_cid,
+ data.type as NonRingingPushEvent,
+ );
}
};
diff --git a/packages/react-native-sdk/src/utils/push/internal/ios.ts b/packages/react-native-sdk/src/utils/push/internal/ios.ts
index 8801017b45..fdf69d4f13 100644
--- a/packages/react-native-sdk/src/utils/push/internal/ios.ts
+++ b/packages/react-native-sdk/src/utils/push/internal/ios.ts
@@ -1,10 +1,10 @@
-import { AppState, NativeModules, Platform } from 'react-native';
-import { getCallKeepLib, getVoipPushNotificationLib } from '../libs';
-import { voipPushNotificationCallCId$ } from './rxSubjects';
+import { NativeModules, Platform } from 'react-native';
+import { getVoipPushNotificationLib } from '../libs';
import { pushUnsubscriptionCallbacks } from './constants';
-import { canAddPushWSSubscriptionsRef, shouldCallBeEnded } from './utils';
+import { canListenToWS, shouldCallBeClosed } from './utils';
import { StreamVideoConfig } from '../../StreamVideoRN/types';
import { videoLoggerSystem } from '@stream-io/video-client';
+import { getCallingxLib } from '../libs/callingx';
export const onVoipNotificationReceived = async (
notification: any,
@@ -32,6 +32,8 @@ export const onVoipNotificationReceived = async (
"version": "v2"
}
} */
+ const logger = videoLoggerSystem.getLogger('setupIosVoipPushEvents');
+
const sender = notification?.stream?.sender;
const type = notification?.stream?.type;
// do not process any other notifications other than stream.video or ringing
@@ -42,9 +44,14 @@ export const onVoipNotificationReceived = async (
if (!call_cid || Platform.OS !== 'ios' || !pushConfig.ios.pushProviderName) {
return;
}
- const logger = videoLoggerSystem.getLogger('setupIosVoipPushEvents');
- const client = await pushConfig.createStreamVideoClient();
+ const callingx = getCallingxLib();
+ if (callingx.hasRegisteredCall()) {
+ logger.debug(`registered call found, skipping the call.ring notification`);
+ return;
+ }
+
+ const client = await pushConfig.createStreamVideoClient();
if (!client) {
logger.debug(
'client not found, not processing call.ring voip push notification',
@@ -59,44 +66,22 @@ export const onVoipNotificationReceived = async (
);
}
const callFromPush = await client.onRingingCall(call_cid);
- let uuid = '';
- try {
- uuid =
- await NativeModules?.StreamVideoReactNative?.getIncomingCallUUid(
- call_cid,
- );
- } catch (error) {
- logger.error('Error in getting call uuid from native module', error);
- }
- if (!uuid) {
- logger.error(
- `Not processing call.ring push notification, as no uuid found for call_cid: ${call_cid}`,
- );
- return;
- }
- const created_by_id = notification?.stream?.created_by_id;
- const receiver_id = notification?.stream?.receiver_id;
+
function closeCallIfNecessary() {
- const { mustEndCall, callkeepReason } = shouldCallBeEnded(
- callFromPush,
- created_by_id,
- receiver_id,
- );
+ const mustEndCall = shouldCallBeClosed(callFromPush, notification?.stream);
if (mustEndCall) {
- const callkeep = getCallKeepLib();
- logger.debug(
- `callkeep.reportEndCallWithUUID for uuid: ${uuid}, call_cid: ${call_cid}, reason: ${callkeepReason}`,
- );
- callkeep.reportEndCallWithUUID(uuid, callkeepReason);
+ logger.debug(`callkeep.reportEndCallWithUUID for call_cid: ${call_cid}`);
+ //TODO: think about sending appropriate reason for end call
+ callingx.endCallWithReason(call_cid, 'local');
+
const voipPushNotification = getVoipPushNotificationLib();
- voipPushNotification.onVoipNotificationCompleted(uuid);
+ voipPushNotification.onVoipNotificationCompleted(call_cid);
return true;
}
return false;
}
+
const closed = closeCallIfNecessary();
- const canListenToWS = () =>
- canAddPushWSSubscriptionsRef.current && AppState.currentState !== 'active';
if (!closed && canListenToWS()) {
const unsubscribe = callFromPush.on('all', (event) => {
const _canListenToWS = canListenToWS();
@@ -121,10 +106,10 @@ export const onVoipNotificationReceived = async (
pushUnsubscriptionCallbacks.get(call_cid)?.forEach((cb) => cb());
pushUnsubscriptionCallbacks.set(call_cid, [unsubscribe]);
}
+
// send the info to this subject, it is listened by callkeep events
// callkeep events will then accept/reject the call
logger.debug(
- `call_cid:${call_cid} uuid:${uuid} received and processed from call.ring push notification`,
+ `call_cid:${call_cid} received and processed from call.ring push notification`,
);
- voipPushNotificationCallCId$.next(call_cid);
};
diff --git a/packages/react-native-sdk/src/utils/push/internal/rxSubjects.ts b/packages/react-native-sdk/src/utils/push/internal/rxSubjects.ts
index 5b9eab7f58..0e10e40b71 100644
--- a/packages/react-native-sdk/src/utils/push/internal/rxSubjects.ts
+++ b/packages/react-native-sdk/src/utils/push/internal/rxSubjects.ts
@@ -40,32 +40,3 @@ export const pushAndroidBackgroundDeliveredIncomingCallCId$ =
export const pushRejectedIncomingCallCId$ = new BehaviorSubject<
string | undefined
>(undefined);
-
-/**
- * This rxjs subject is used to store the call cid of the incoming call from ios voip pushkit notification
- */
-export const voipPushNotificationCallCId$ = new BehaviorSubject<
- string | undefined
->(undefined);
-
-/** The pair of cid of a call and its corresponding uuid created in the native side */
-type CallkeepMap = {
- uuid: string;
- cid: string;
-};
-
-/*
- * This rxjs subject should only used to store the CallkeepMap
- * for the incoming call when on foreground
- * or in other words, when we get didDisplayIncomingCall from callkeep lib
- */
-export const voipCallkeepCallOnForegroundMap$ = new BehaviorSubject<
- CallkeepMap | undefined
->(undefined);
-
-/*
- * This rxjs subject should only used to store the CallkeepMap when it was accepted in the native dialer
- */
-export const voipCallkeepAcceptedCallOnNativeDialerMap$ = new BehaviorSubject<
- CallkeepMap | undefined
->(undefined);
diff --git a/packages/react-native-sdk/src/utils/push/internal/utils.ts b/packages/react-native-sdk/src/utils/push/internal/utils.ts
index c31ce73c78..48b5d3af2f 100644
--- a/packages/react-native-sdk/src/utils/push/internal/utils.ts
+++ b/packages/react-native-sdk/src/utils/push/internal/utils.ts
@@ -10,6 +10,7 @@ import type {
} from '../../StreamVideoRN/types';
import { onNewCallNotification } from '../../internal/newNotificationCallbacks';
import { pushUnsubscriptionCallbacks } from './constants';
+import { AppState } from 'react-native';
type PushConfig = NonNullable;
@@ -122,6 +123,16 @@ export const processCallFromPush = async (
.debug(
`joining call from push notification with callCid: ${callFromPush.cid}`,
);
+
+ if (callFromPush.state.callingState === CallingState.JOINED) {
+ videoLoggerSystem
+ .getLogger('processCallFromPush')
+ .debug(
+ `call already joined from push notification with callCid: ${callFromPush.cid}`,
+ );
+ return;
+ }
+
await callFromPush.join();
} else if (action === 'decline') {
const canReject =
@@ -191,3 +202,17 @@ export const clearPushWSEventSubscriptions = (call_cid: string) => {
export const canAddPushWSSubscriptionsRef: CanAddPushWSSubscriptionsRef = {
current: true,
};
+
+export const canListenToWS = () =>
+ canAddPushWSSubscriptionsRef.current && AppState.currentState !== 'active';
+
+export const shouldCallBeClosed = (
+ call: Call,
+ pushData: { [key: string]: string | object },
+) => {
+ const created_by_id = pushData?.created_by_id as string;
+ const receiver_id = pushData?.receiver_id as string;
+
+ const { mustEndCall } = shouldCallBeEnded(call, created_by_id, receiver_id);
+ return mustEndCall;
+};
diff --git a/packages/react-native-sdk/src/utils/push/ios.ts b/packages/react-native-sdk/src/utils/push/ios.ts
index 077a6c8c58..f78d7a3941 100644
--- a/packages/react-native-sdk/src/utils/push/ios.ts
+++ b/packages/react-native-sdk/src/utils/push/ios.ts
@@ -62,12 +62,7 @@ export const oniOSExpoNotificationEvent = (event: ExpoNotification) => {
}
};
-export const oniOSNotifeeEvent = ({
- event,
-}: {
- event: Event;
- isBackground: boolean;
-}) => {
+export const oniOSNotifeeEvent = ({ event }: { event: Event }) => {
if (Platform.OS !== 'ios') return;
const pushConfig = StreamVideoRN.getConfig().push;
const { type, detail } = event;
diff --git a/packages/react-native-sdk/src/utils/push/libs/callingx.ts b/packages/react-native-sdk/src/utils/push/libs/callingx.ts
new file mode 100644
index 0000000000..7a3219057a
--- /dev/null
+++ b/packages/react-native-sdk/src/utils/push/libs/callingx.ts
@@ -0,0 +1,19 @@
+export type RNCallingxType = import('react-native-callingx').ICallingxModule;
+export type EventParams = import('react-native-callingx').EventParams;
+
+let callingx: RNCallingxType | undefined;
+
+try {
+ callingx = require('react-native-callingx').CallingxModule;
+} catch {}
+
+export function getCallingxLib() {
+ if (!callingx) {
+ throw Error('react-native-callingx library is not installed.');
+ }
+ return callingx;
+}
+
+export function getCallingxLibIfAvailable() {
+ return callingx ?? undefined;
+}
diff --git a/packages/react-native-sdk/src/utils/push/libs/callkeep.ts b/packages/react-native-sdk/src/utils/push/libs/callkeep.ts
deleted file mode 100644
index fe8a20bf68..0000000000
--- a/packages/react-native-sdk/src/utils/push/libs/callkeep.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export type RNCallKeepType = typeof import('react-native-callkeep').default;
-
-let callkeep: RNCallKeepType | undefined;
-
-try {
- callkeep = require('react-native-callkeep').default;
-} catch {}
-
-export function getCallKeepLib() {
- if (!callkeep) {
- throw Error(
- 'react-native-callkeep library is not installed. Please see https://github.com/react-native-webrtc/react-native-callkeep#Installation for installation instructions',
- );
- }
- return callkeep;
-}
diff --git a/packages/react-native-sdk/src/utils/push/libs/index.ts b/packages/react-native-sdk/src/utils/push/libs/index.ts
index 73a249953b..437da4d834 100644
--- a/packages/react-native-sdk/src/utils/push/libs/index.ts
+++ b/packages/react-native-sdk/src/utils/push/libs/index.ts
@@ -2,8 +2,8 @@ export * from './expoNotifications';
export * from './firebaseMessaging';
export * from './iosPushNotification';
export * from './voipPushNotification';
-export * from './callkeep';
export * from './notifee';
+export * from './callingx';
/*
NOTE: must keep each libs in different files
diff --git a/packages/react-native-sdk/src/utils/push/setupCallingExpEvents.ts b/packages/react-native-sdk/src/utils/push/setupCallingExpEvents.ts
new file mode 100644
index 0000000000..fba4c1cf2a
--- /dev/null
+++ b/packages/react-native-sdk/src/utils/push/setupCallingExpEvents.ts
@@ -0,0 +1,109 @@
+import { pushAcceptedIncomingCallCId$ } from './internal/rxSubjects';
+import { videoLoggerSystem } from '@stream-io/video-client';
+import type { StreamVideoConfig } from '../StreamVideoRN/types';
+import {
+ clearPushWSEventSubscriptions,
+ processCallFromPushInBackground,
+} from './internal/utils';
+import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
+import { getCallingxLib, type EventParams } from './libs/callingx';
+
+type PushConfig = NonNullable;
+
+/**
+ * This hook is used to listen to callkeep events and do the necessary actions
+ */
+export function setupCallingExpEvents(pushConfig: NonNullable) {
+ if (
+ !(pushConfig.android.pushProviderName && pushConfig.ios.pushProviderName)
+ ) {
+ return;
+ }
+
+ const callingx = getCallingxLib();
+ // const logger = videoLoggerSystem.getLogger('setupCallingExpEvents');
+
+ const { remove: removeAnswerCall } = callingx.addEventListener(
+ 'answerCall',
+ onAcceptCall,
+ );
+ const { remove: removeEndCall } = callingx.addEventListener(
+ 'endCall',
+ onEndCall(pushConfig),
+ );
+ const { remove: removeDidActivateAudioSession } = callingx.addEventListener(
+ 'didActivateAudioSession',
+ onDidActivateAudioSession,
+ );
+ const { remove: removeDidDeactivateAudioSession } = callingx.addEventListener(
+ 'didDeactivateAudioSession',
+ onDidDeactivateAudioSession,
+ );
+
+ //TODO: need to find cases where delayed events can appear
+ // const events = callingx.getInitialEvents();
+ // events.forEach((event: EventData) => {
+ // const { eventName, params } = event;
+ // if (eventName === 'didDisplayIncomingCall') {
+ // logger.debug(`[delayed] didDisplayIncomingCall event callId: ${params.callId}`);
+ // } else if (eventName === 'answerCall') {
+ // logger.debug(`[delayed] answerCall event callId: ${params.callId}`);
+ // callingExpAcceptCall(params);
+ // } else if (eventName === 'endCall') {
+ // logger.debug(`[delayed] endCall event callId: ${params.callId}`);
+ // callingExpRejectCall(pushConfig)(params);
+ // }
+ // });
+
+ setPushLogoutCallback(async () => {
+ removeAnswerCall();
+ removeEndCall();
+ removeDidActivateAudioSession();
+ removeDidDeactivateAudioSession();
+ });
+}
+
+const onAcceptCall = ({
+ callId: call_cid,
+ source,
+}: EventParams['answerCall']) => {
+ videoLoggerSystem
+ .getLogger('callingExpAcceptCall')
+ .debug(`callingExpAcceptCall event callId: ${call_cid} source: ${source}`);
+
+ if (source === 'app' || !call_cid) {
+ //we only need to process the call if the call was answered from the system
+ return;
+ }
+
+ clearPushWSEventSubscriptions(call_cid);
+ // to process the call in the app
+ pushAcceptedIncomingCallCId$.next(call_cid);
+};
+
+const onEndCall =
+ (pushConfig: PushConfig) =>
+ async ({ callId: call_cid, source }: EventParams['endCall']) => {
+ videoLoggerSystem
+ .getLogger('callingExpRejectCall')
+ .debug(
+ `callingExpRejectCall event callId: ${call_cid} source: ${source}`,
+ );
+
+ if (source === 'app' || !call_cid) {
+ //we only need to process the call if the call was rejected from the system
+ return;
+ }
+
+ clearPushWSEventSubscriptions(call_cid);
+
+ await processCallFromPushInBackground(pushConfig, call_cid, 'decline');
+ };
+
+const onDidActivateAudioSession = () => {
+ //TODO: start audio session here
+};
+
+const onDidDeactivateAudioSession = () => {
+ //TODO: end audio session here
+};
diff --git a/packages/react-native-sdk/src/utils/push/setupIosCallKeepEvents.ts b/packages/react-native-sdk/src/utils/push/setupIosCallKeepEvents.ts
deleted file mode 100644
index c9d9bcad50..0000000000
--- a/packages/react-native-sdk/src/utils/push/setupIosCallKeepEvents.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-import {
- pushAcceptedIncomingCallCId$,
- voipCallkeepAcceptedCallOnNativeDialerMap$,
- voipCallkeepCallOnForegroundMap$,
- voipPushNotificationCallCId$,
-} from './internal/rxSubjects';
-import { RxUtils, videoLoggerSystem } from '@stream-io/video-client';
-import { getCallKeepLib, getVoipPushNotificationLib } from './libs';
-import type { StreamVideoConfig } from '../StreamVideoRN/types';
-import {
- clearPushWSEventSubscriptions,
- processCallFromPushInBackground,
-} from './internal/utils';
-import { AppState, NativeModules, Platform } from 'react-native';
-import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
-
-type PushConfig = NonNullable;
-
-/**
- * This hook is used to listen to callkeep events and do the necessary actions
- */
-export function setupIosCallKeepEvents(
- pushConfig: NonNullable,
-) {
- if (Platform.OS !== 'ios' || !pushConfig.ios.pushProviderName) {
- return;
- }
- if (!pushConfig.android.incomingCallChannel) {
- // TODO: remove this check and find a better way once we have telecom integration for android
- videoLoggerSystem
- .getLogger('setupIosCallKeepEvents')
- .debug(
- 'android incomingCallChannel is not defined, so skipping the setupIosCallKeepEvents',
- );
- return;
- }
- const logger = videoLoggerSystem.getLogger('setupIosCallKeepEvents');
- const callkeep = getCallKeepLib();
-
- async function getCallCid(callUUID: string): Promise {
- try {
- const call_cid =
- await NativeModules.StreamVideoReactNative.getIncomingCallCid(callUUID);
- // in a case that voipPushNotificationCallCId$ is empty (this should not happen as voipPushNotificationCallCId$ is updated in push reception)]
- // update it with this call_cid
- const voipPushNotificationCallCId = RxUtils.getCurrentValue(
- voipPushNotificationCallCId$,
- );
- if (!voipPushNotificationCallCId) {
- logger.debug(
- `voipPushNotificationCallCId$ is empty, updating it with the call_cid: ${call_cid} for callUUID: ${callUUID}`,
- );
- voipPushNotificationCallCId$.next(call_cid);
- }
- return call_cid;
- } catch {
- logger.debug(
- `Error in getting call cid from native module for callUUID: ${callUUID} - probably the call was already processed, so ignoring this callkeep event`,
- );
- }
- return undefined;
- }
-
- function answerCall(callUUID: string) {
- getCallCid(callUUID).then((call_cid) => {
- logger.debug(`answerCall event with call_cid: ${call_cid}`);
- iosCallkeepAcceptCall(call_cid, callUUID);
- });
- }
-
- function endCall(callUUID: string) {
- getCallCid(callUUID).then((call_cid) => {
- logger.debug(`endCall event with call_cid: ${call_cid}`);
- iosCallkeepRejectCall(call_cid, callUUID, pushConfig!);
- });
- }
-
- function didDisplayIncomingCall(callUUID: string, payload: object) {
- const voipPushNotification = getVoipPushNotificationLib();
- // @ts-expect-error - call_cid is not part of RNCallKeepEventPayload
- const call_cid = payload?.call_cid as string | undefined;
- logger.debug(
- `didDisplayIncomingCall event with callUUID: ${callUUID} call_cid: ${call_cid}`,
- );
- if (call_cid) {
- if (AppState.currentState === 'background') {
- processCallFromPushInBackground(
- pushConfig!,
- call_cid,
- 'backgroundDelivered',
- );
- }
- voipCallkeepCallOnForegroundMap$.next({
- uuid: callUUID,
- cid: call_cid,
- });
- }
- voipPushNotification.onVoipNotificationCompleted(callUUID);
- }
-
- const { remove: removeAnswerCall } = callkeep.addEventListener(
- 'answerCall',
- ({ callUUID }) => {
- answerCall(callUUID);
- },
- );
- const { remove: removeEndCall } = callkeep.addEventListener(
- 'endCall',
- ({ callUUID }) => {
- endCall(callUUID);
- },
- );
-
- const { remove: removeDisplayIncomingCall } = callkeep.addEventListener(
- 'didDisplayIncomingCall',
- ({ callUUID, payload }) => {
- didDisplayIncomingCall(callUUID, payload);
- },
- );
-
- const { remove: removeDidLoadWithEvents } = callkeep.addEventListener(
- 'didLoadWithEvents',
- (events) => {
- if (!events || !Array.isArray(events) || events.length < 1) {
- return;
- }
-
- events.forEach((event) => {
- const { name, data } = event;
- if (name === 'RNCallKeepDidDisplayIncomingCall') {
- didDisplayIncomingCall(data.callUUID, data.payload);
- } else if (name === 'RNCallKeepPerformAnswerCallAction') {
- answerCall(data.callUUID);
- } else if (name === 'RNCallKeepPerformEndCallAction') {
- endCall(data.callUUID);
- }
- });
- },
- );
-
- setPushLogoutCallback(async () => {
- removeAnswerCall();
- removeEndCall();
- removeDisplayIncomingCall();
- removeDidLoadWithEvents();
- });
-}
-
-const iosCallkeepAcceptCall = (
- call_cid: string | undefined,
- callUUIDFromCallkeep: string,
-) => {
- if (!shouldProcessCallFromCallkeep(call_cid, callUUIDFromCallkeep)) {
- return;
- }
- clearPushWSEventSubscriptions(call_cid);
- // to call end callkeep later if ended in app and not through callkeep
- voipCallkeepAcceptedCallOnNativeDialerMap$.next({
- uuid: callUUIDFromCallkeep,
- cid: call_cid,
- });
- // to process the call in the app
- pushAcceptedIncomingCallCId$.next(call_cid);
- // no need to keep these references anymore
- voipCallkeepCallOnForegroundMap$.next(undefined);
-};
-
-const iosCallkeepRejectCall = async (
- call_cid: string | undefined,
- callUUIDFromCallkeep: string,
- pushConfig: PushConfig,
-) => {
- if (!shouldProcessCallFromCallkeep(call_cid, callUUIDFromCallkeep)) {
- return;
- }
- clearPushWSEventSubscriptions(call_cid);
- // remove the references if the call_cid matches
- const voipPushNotificationCallCId = RxUtils.getCurrentValue(
- voipPushNotificationCallCId$,
- );
- if (voipPushNotificationCallCId === call_cid) {
- voipCallkeepAcceptedCallOnNativeDialerMap$.next(undefined);
- voipCallkeepCallOnForegroundMap$.next(undefined);
- voipPushNotificationCallCId$.next(undefined);
- }
-
- await processCallFromPushInBackground(pushConfig, call_cid, 'decline');
- await NativeModules.StreamVideoReactNative?.removeIncomingCall(call_cid);
-};
-
-/**
- * Helper function to determine if the answer/end call event from callkeep must be processed
- * Just checks if we have a valid call_cid and acts as a type guard for call_cid
- */
-const shouldProcessCallFromCallkeep = (
- call_cid: string | undefined,
- callUUIDFromCallkeep: string,
-): call_cid is string => {
- if (!call_cid || !callUUIDFromCallkeep) {
- return false;
- }
- return true;
-};
diff --git a/packages/react-native-sdk/src/utils/push/setupIosVoipPushEvents.ts b/packages/react-native-sdk/src/utils/push/setupIosVoipPushEvents.ts
index 6646e6498b..96256924f9 100644
--- a/packages/react-native-sdk/src/utils/push/setupIosVoipPushEvents.ts
+++ b/packages/react-native-sdk/src/utils/push/setupIosVoipPushEvents.ts
@@ -23,6 +23,15 @@ export function setupIosVoipPushEvents(
const voipPushNotification = getVoipPushNotificationLib();
logger.debug('notification event listener added');
+ voipPushNotification.addEventListener('didLoadWithEvents', (events) => {
+ //we need this for cold start scenario where the app is not running and the events are not processed when the app is launched
+ for (const event of events) {
+ const { name, data } = event;
+ if (name === 'RNVoipPushRemoteNotificationReceivedEvent') {
+ onVoipNotificationReceived(data, pushConfig);
+ }
+ }
+ });
voipPushNotification.addEventListener('notification', (notification) => {
onVoipNotificationReceived(notification, pushConfig);
});
diff --git a/sample-apps/react-native/dogfood/android/app/build.gradle b/sample-apps/react-native/dogfood/android/app/build.gradle
index 708b257ee9..6250da9eca 100644
--- a/sample-apps/react-native/dogfood/android/app/build.gradle
+++ b/sample-apps/react-native/dogfood/android/app/build.gradle
@@ -117,8 +117,6 @@ android {
}
dependencies {
- implementation (project(':react-native-callkeep'))
-
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
diff --git a/sample-apps/react-native/dogfood/android/app/src/main/java/io/getstream/rnvideosample/MainActivity.kt b/sample-apps/react-native/dogfood/android/app/src/main/java/io/getstream/rnvideosample/MainActivity.kt
index 1920222c0a..9af3a7a2c5 100644
--- a/sample-apps/react-native/dogfood/android/app/src/main/java/io/getstream/rnvideosample/MainActivity.kt
+++ b/sample-apps/react-native/dogfood/android/app/src/main/java/io/getstream/rnvideosample/MainActivity.kt
@@ -1,8 +1,10 @@
package io.getstream.rnvideosample
import android.content.res.Configuration
+import android.content.Intent
import android.os.Build
import android.os.Bundle
+import android.util.Log
import androidx.lifecycle.Lifecycle
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
diff --git a/sample-apps/react-native/dogfood/ios/AppDelegate.swift b/sample-apps/react-native/dogfood/ios/AppDelegate.swift
index 010d5e82e8..afffc60e08 100644
--- a/sample-apps/react-native/dogfood/ios/AppDelegate.swift
+++ b/sample-apps/react-native/dogfood/ios/AppDelegate.swift
@@ -11,11 +11,12 @@ import ReactAppDependencyProvider
import UserNotifications
import RNCPushNotificationIOS
-import RNCallKeep
+import Callingx
import PushKit
import WebRTC
import RNVoipPushNotification
import stream_io_noise_cancellation_react_native
+import stream_video_react_native
@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, PKPushRegistryDelegate {
@@ -70,12 +71,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
) {
guard let stream = payload.dictionaryPayload["stream"] as? [String: Any],
- let createdCallerName = stream["created_by_display_name"] as? String,
+ let _ = stream["created_by_display_name"] as? String,
let cid = stream["call_cid"] as? String else {
completion() // Ensure completion handler is called even if parsing fails
return
}
-
+
// Check if user is busy BEFORE registering the call
let shouldReject = StreamVideoReactNative.shouldRejectCallWhenBusy()
let hasAnyActiveCall = StreamVideoReactNative.hasAnyActiveCall()
@@ -86,30 +87,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
return
}
- let uuid = UUID().uuidString
- let videoIncluded = stream["video"] as? String
- let hasVideo = videoIncluded == "false" ? false : true
-
- StreamVideoReactNative.registerIncomingCall(cid, uuid: uuid)
-
// required if you want to call `completion()` on the js side
- RNVoipPushNotificationManager.addCompletionHandler(uuid, completionHandler: completion)
+ RNVoipPushNotificationManager.addCompletionHandler(cid, completionHandler: completion)
// Process the received push // fire 'notification' event to JS
RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) // type is enum, use rawValue
- RNCallKeep.reportNewIncomingCall(uuid,
- handle: createdCallerName,
- handleType: "generic",
- hasVideo: hasVideo,
- localizedCallerName: createdCallerName,
- supportsHolding: false,
- supportsDTMF: false,
- supportsGrouping: false,
- supportsUngrouping: false,
- fromPushKit: true,
- payload: stream,
- withCompletionHandler: nil) // Completion handler is already handled above
+ StreamVideoReactNative.didReceiveIncomingPush(payload, completionHandler: nil) //for now left completion handler empty
}
//Called when a notification is delivered to a foreground app.
@@ -132,14 +116,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// Uncomment the next line to enable verbose WebRTC logs
// WebRTCModuleOptions.sharedInstance().loggingSeverity = .verbose
- let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleDisplayName"] as? String
- let appName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String
- RNCallKeep.setup([
- "appName": localizedAppName != nil ? localizedAppName! : appName as Any, // Forced unwrap is safe here due to nil check
- "supportsVideo": true,
- "includesCallsInRecents": false,
- ])
-
RNVoipPushNotificationManager.voipRegistration()
let center = UNUserNotificationCenter.current()
diff --git a/sample-apps/react-native/dogfood/ios/Podfile.lock b/sample-apps/react-native/dogfood/ios/Podfile.lock
index 1159ebffff..4eaccacbf3 100644
--- a/sample-apps/react-native/dogfood/ios/Podfile.lock
+++ b/sample-apps/react-native/dogfood/ios/Podfile.lock
@@ -1,5 +1,33 @@
PODS:
- boost (1.84.0)
+ - Callingx (0.1.0):
+ - boost
+ - DoubleConversion
+ - fast_float
+ - fmt
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCT-Folly/Fabric
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SocketRocket
+ - Yoga
- DoubleConversion (1.1.6)
- fast_float (8.0.0)
- FBLazyVector (0.81.5)
@@ -2513,8 +2541,6 @@ PODS:
- React-perflogger (= 0.81.5)
- React-utils (= 0.81.5)
- SocketRocket
- - RNCallKeep (4.3.16):
- - React
- RNCClipboard (1.16.3):
- boost
- DoubleConversion
@@ -3028,7 +3054,7 @@ PODS:
- stream-react-native-webrtc (137.0.2):
- React-Core
- StreamWebRTC (~> 137.0.52)
- - stream-video-react-native (1.26.1):
+ - stream-video-react-native (1.26.2):
- boost
- DoubleConversion
- fast_float
@@ -3069,6 +3095,7 @@ PODS:
DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
+ - Callingx (from `../node_modules/react-native-callingx`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
@@ -3145,7 +3172,6 @@ DEPENDENCIES:
- ReactAppDependencyProvider (from `build/generated/ios`)
- ReactCodegen (from `build/generated/ios`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- - RNCallKeep (from `../node_modules/react-native-callkeep`)
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
@@ -3177,6 +3203,8 @@ SPEC REPOS:
EXTERNAL SOURCES:
boost:
:podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
+ Callingx:
+ :path: "../node_modules/react-native-callingx"
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
fast_float:
@@ -3328,8 +3356,6 @@ EXTERNAL SOURCES:
:path: build/generated/ios
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
- RNCallKeep:
- :path: "../node_modules/react-native-callkeep"
RNCClipboard:
:path: "../node_modules/@react-native-clipboard/clipboard"
RNCPushNotificationIOS:
@@ -3371,104 +3397,104 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
+ Callingx: 5f4a8b201c8a7ac415519f67f5c66588209b3b99
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6
FBLazyVector: 5beb8028d5a2e75dd9634917f23e23d3a061d2aa
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: 9f4dfe93326146a1c99eb535b1cb0b857a3cd172
- RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
+ RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f
RCTDeprecation: 5eb1d2eeff5fb91151e8a8eef45b6c7658b6c897
RCTRequired: cebcf9442fc296c9b89ac791dfd463021d9f6f23
RCTTypeSafety: b99aa872829ee18f6e777e0ef55852521c5a6788
React: 914f8695f9bf38e6418228c2ffb70021e559f92f
React-callinvoker: 23cd4e33928608bd0cc35357597568b8b9a5f068
React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a
- React-Core: 6a0a97598e9455348113bfe4c573fe8edac34469
- React-CoreModules: a88a6ca48b668401b9780e272e2a607e70f9f955
- React-cxxreact: 06265fd7e8d5c3b6b49e00d328ef76e5f1ae9c8b
+ React-Core: 895a479e2e0331f48af3ad919bece917926a0b7d
+ React-CoreModules: dfa38212cf3a91f2eb84ccd43d747d006d33449e
+ React-cxxreact: 7a4e2c77e564792252131e63270f6184d93343b3
React-debug: 29aed758c756956a51b4560223edbd15191ca4c5
- React-defaultsnativemodule: c406bf7cd78036efffb7dec9df469257a1bca58c
- React-domnativemodule: 925ea5ff8cb05c68e910057e6349e5898cce00f3
- React-Fabric: 13130d0a70f17e913865b04673ee64603d6c42fe
- React-FabricComponents: 1f01ea24a1314bf9abcac4743bb7ad8791336be6
- React-FabricImage: f364dc54fcf8b0ef77192674a009aa4f65b34d75
- React-featureflags: 32217ac18a8c216fc571044186fb04164af72772
- React-featureflagsnativemodule: 9c552bb908a7434baa846002ee1752a77b1a5520
- React-graphics: 3034a698e46e947f74a443e761f1feef742e9d71
- React-hermes: a852be3ab9e1f515e46ba3ea9f48c31d4a9df437
- React-idlecallbacksnativemodule: c43fe1f2221b0548cc366bf15f88efb3b3221bbf
- React-ImageManager: 7efd7b19cdfaa3a82482e9e6ac0b56606a3ec271
- React-jserrorhandler: 597057d0b9d158c03e02aa376a4a95f64f46a910
- React-jsi: 7b53959aea60909ac6bbe4dd0bdec6c10d7dc597
- React-jsiexecutor: 19938072af05ade148474bac41e0324a2d733f44
- React-jsinspector: eb6bb244a75cbd56f32767daf2efdb344e2ff10c
- React-jsinspectorcdp: 727f37537e9c7ab22b6b86c802d879efae5e2757
- React-jsinspectornetwork: 11d47e644701c58038ef8d7f54a405ddd62b3b16
- React-jsinspectortracing: 8875637e6c65b3b9a3852b006856562e874e7a78
- React-jsitooling: b6e6a2551459a6ef9e1529df2ea981fa27ed3a91
- React-jsitracing: 879e2b2f80dd33d84175989de0a8db5d662505db
- React-logger: a913317214a26565cd4c045347edf1bcacb80a3f
- React-Mapbuffer: 017336879e2e0fb7537bbc08c24f34e2384c9260
- React-microtasksnativemodule: 63ee6730cec233feab9cdcc0c100dc28a12e4165
- react-native-blob-util: 7f71e0af02279ef38a2ba43e8c2fcb79cf927732
- react-native-image-picker: 6051cfd030121b880a58f1cc0e5e33e9887804e4
- react-native-mmkv: 7b9c7469fa0a7e463f9411ad3e4fe273bd5ff030
- react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
- react-native-safe-area-context: ee1e8e2a7abf737a8d4d9d1a5686a7f2e7466236
- react-native-video: d9d12aa2325ae06222e97e8bd801bbc31df2675d
- React-NativeModulesApple: cbceb3c4cb726838c461b13802a76cefa6f3476f
+ React-defaultsnativemodule: ee4e3ca63b29c8b91448a6760d72063196ed0796
+ React-domnativemodule: 4d29aad12ebb2b5aa34043e5bdd191a92821f3aa
+ React-Fabric: 21f78a4856240d39a663a52c452e223c5e412098
+ React-FabricComponents: 13fc0ac39a488cea00c83ffa7b16113f024d66e6
+ React-FabricImage: 8961abe0372d20679ee093d144aaf5fb1227bf41
+ React-featureflags: 018934f958e6b83907e71631599b02144e6b17f4
+ React-featureflagsnativemodule: 89fef5751203b7d3cdde43e1e10407983735a4b4
+ React-graphics: 1c62dd11f47071482ca90238981f0147cce4089d
+ React-hermes: 36704d7354fff9c9e3fbb2490e8eeb2ac027f6f0
+ React-idlecallbacksnativemodule: 5f7cbecc1479b53e665f2cd6c2af2c21a80d2ffd
+ React-ImageManager: 4cb6318bb2bcc947106e29f9297a1c24c85a9233
+ React-jserrorhandler: 4b9344f5794cfe8946f8752d38094649f53dd3f3
+ React-jsi: 3a8c6f94a52033b0cca53c38d9bb568306aa9dc1
+ React-jsiexecutor: d7cf79b1c2771c6b21c46691a96dd2e32d4454c7
+ React-jsinspector: 651483ea1d79859e0ed21b86e9042b2a3f4d2b40
+ React-jsinspectorcdp: c800035023789b8bf32b4f5a4c9003c2dc28ee49
+ React-jsinspectornetwork: 249ee46e9de930d773ff6e4726aa8eeb5854b589
+ React-jsinspectortracing: 80e251e13a6071607f06f0e39e03d3f2ce2645cb
+ React-jsitooling: 6ce395671d0139ec1c4721953a4d3d92172fc06f
+ React-jsitracing: 4a4d89334b14d96de0387876751528433d1d2fbd
+ React-logger: 8bcfaf06f8c536fb9e9760526cf3d17ccd53e4ce
+ React-Mapbuffer: 4649384414066eb77e30a3124dbb48732a3aa173
+ React-microtasksnativemodule: e39f94cc96d61b8174a5cfb2d5862a73fa8c0d35
+ react-native-blob-util: 9027c999d7d2b7d4b087ea40413eddc899af46fe
+ react-native-image-picker: b99d9c1f2ddbef491eb49e1103e5c2ce78b9ab37
+ react-native-mmkv: c70c58437c0f5e5fe6992f1de1e350dcdd236332
+ react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac
+ react-native-safe-area-context: 3e0a25a843c40ad5efdf2bef93fdd95ad7229650
+ react-native-video: 201e71d168053580319a4741e1ef44380cdcb06f
+ React-NativeModulesApple: 8ce162c145e6b9767bb37a090c77d3d28f7d32b5
React-oscompat: eb0626e8ba1a2c61673c991bf9dc21834898475d
- React-perflogger: 509e1f9a3ee28df71b0a66de806ac515ce951246
- React-performancetimeline: 9ce28cce1cded27410c293283f99fe62bebdb920
+ React-perflogger: d0d0d1b884120fa0a13bd38ac5e9c3c8e8bfe82a
+ React-performancetimeline: ae60fb7a7447c44d4d3227fc4eeba606403aaee3
React-RCTActionSheet: 30fe8f9f8d86db4a25ff34595a658ecd837485fc
- React-RCTAnimation: 3126eb1cb8e7a6ca33a52fd833d8018aa9311af1
- React-RCTAppDelegate: b03981c790aa40cf26e0f78cc0f1f2df8287ead4
- React-RCTBlob: 53c35e85c85d6bdaa55dc81a0b290d4e78431095
- React-RCTFabric: 59ad9008775f123019c508efff260594a8509791
- React-RCTFBReactNativeSpec: 82b605ab4f6f8da0a7ad88641161df5a0bafb1fb
- React-RCTImage: 074b2faa71a152a456c974e118b60c9eeda94a64
- React-RCTLinking: e5ca17a4f7ae2ad7b0c0483be77e1b383ecd0a8a
- React-RCTNetwork: c508d7548c9eceac30a8100a846ea00033a03366
- React-RCTRuntime: 6979568c0bc276fe785e085894f954fa15e0ec7e
- React-RCTSettings: dd84c857a4fce42c1e08c1dabcda894e25af4a6e
- React-RCTText: 6e4b177d047f98bccb90d6fb1ebdd3391cf8b299
- React-RCTVibration: 9572d4a06a0c92650bcc62913e50eb2a89f19fb6
+ React-RCTAnimation: e86dacf8a982f42341a44ec87ea8a30964a15f9f
+ React-RCTAppDelegate: d7214067e796732b5d22960270593945f1ab8a14
+ React-RCTBlob: af1fc227a5aa55564afbe84530a8bd28834fda15
+ React-RCTFabric: 8d92e851cc6cdf9771c52a18b144424c92b72082
+ React-RCTFBReactNativeSpec: c9ec2130e3c9366d30a85886e1776210054763f5
+ React-RCTImage: 70a10a5b957ca124b8d0b0fdeec369f11194782c
+ React-RCTLinking: 67f8a024192b4844c40ace955c54bb34f40d47f0
+ React-RCTNetwork: a7679ee67e7d34797a00cefaa879a3f9ea8cee9c
+ React-RCTRuntime: 3d25c69970924b597c339aead60168026d7cbc2c
+ React-RCTSettings: 18d8674195383c4fd51b9fc98ee815b329fba7e4
+ React-RCTText: 125574af8e29d0ceb430cbe2a03381d62ba45a47
+ React-RCTVibration: e96d43017757197d46834c50a0acfb78429c9b30
React-rendererconsistency: a7b47f8b186af64ff8509c8caec4114a2f1ae63f
- React-renderercss: 9845c5063b3a2d0462ed4e4c7fc34219a5d608ed
- React-rendererdebug: 3905e346c06347b86c6e49d427062cdd638a3044
- React-RuntimeApple: 97233caf2b635c40819bf5be38d818777f8229ab
- React-RuntimeCore: dc41f86fcdf1fbb42a5b8388a29bf59dfa56b2f8
- React-runtimeexecutor: d16d045faaf6cd7de8d1aa8e31a51c13d8db84a4
- React-RuntimeHermes: 5a9d132554c8d6b416d794cd4ac7d927b2f88f7b
- React-runtimescheduler: 689d805d43c28b8fb1ab390914e042d10e2ea2ab
- React-timing: c39eeb992274aeaeb9f4666dc97a36a31d33fe94
- React-utils: 2f9ba0088251788ad66aa1855ff99ed2424024d2
- ReactAppDependencyProvider: 1bcd3527ac0390a1c898c114f81ff954be35ed79
- ReactCodegen: 2e921a931c5a4dd1d8ab37ade085fdf58fcfe1dd
- ReactCommon: 6d0fa86a4510730da7c72560e0ced14258292ab9
- RNCallKeep: 1930a01d8caf48f018be4f2db0c9f03405c2f977
- RNCClipboard: e560338bf6cc4656a09ff90610b62ddc0dbdad65
- RNCPushNotificationIOS: 6c4ca3388c7434e4a662b92e4dfeeee858e6f440
- RNDeviceInfo: bcce8752b5043a623fe3c26789679b473f705d3c
- RNGestureHandler: b8d2e75c2e88fc2a1f6be3b3beeeed80b88fa37d
- RNNotifee: 5e3b271e8ea7456a36eec994085543c9adca9168
- RNPermissions: ee88ba7d9fb3f9b3650ff7e5a78e7ee2d1c7e200
- RNReactNativeHapticFeedback: 5f1542065f0b24c9252bd8cf3e83bc9c548182e4
- RNReanimated: 44af5b24b999a70c737df8e407582c32d12b3a87
- RNScreens: 2e9c41cd099b1ca50136af8d57c3594214d0086a
- RNSVG: 65335d69b8e372837ccad79307b1190d5cc1d0a9
- RNVoipPushNotification: 4998fe6724d421da616dca765da7dc421ff54c4e
- RNWorklets: ad0606bee2a8103c14adb412149789c60b72bfb2
+ React-renderercss: 0a5b6b7aefc3f5e46a61b0e41b1179a0750cf077
+ React-rendererdebug: 7da01af21ab31661c3040ef647e6e2bc55575771
+ React-RuntimeApple: 788ca3b8e5485a46654e8a316d4c1e40bf82c5d4
+ React-RuntimeCore: 1730e6e5cba6f0af4e0319f891da6426b491e39f
+ React-runtimeexecutor: 79894322e55268854dc04ff1bee083f24725f6c8
+ React-RuntimeHermes: 86bf03cbf11ef05803a2e32087667c8a3cc45f72
+ React-runtimescheduler: 70601d598a8a71582fa69a9ba488a27c5d12790d
+ React-timing: 5717558f0bea206d7557df53015ee9efe1eb57b2
+ React-utils: 55e54e497e3d3f373ebfcf844eb77e24ed013356
+ ReactAppDependencyProvider: c277c5b231881ad4f00cd59e3aa0671b99d7ebee
+ ReactCodegen: 1e847cf77c1402fe7394dae41b3829c95569e76e
+ ReactCommon: 5cfd842fcd893bb40fc835f98fadc60c42906a20
+ RNCClipboard: 4eea71d801c880175c12f6ab14332ca86fed935f
+ RNCPushNotificationIOS: 64218f3c776c03d7408284a819b2abfda1834bc8
+ RNDeviceInfo: 8b6fa8379062949dd79a009cf3d6b02a9c03ca59
+ RNGestureHandler: 9339994ea5d1ff6ad2679b7d0cc3d49053111369
+ RNNotifee: 4a6ee5c7deaf00e005050052d73ee6315dff7ec9
+ RNPermissions: f16d5f721280a171831d992c5886761f08075926
+ RNReactNativeHapticFeedback: 43c09eb41d8321be2e1375cb87ae734e58f677b0
+ RNReanimated: 91d075aaf0c89d51a0708cd64cd6c77f7fa42cdc
+ RNScreens: 871305075ddf1291411b051d86da9e0d9289de02
+ RNSVG: 596e9946ddc0e023c6e6931038c9e49b553f742d
+ RNVoipPushNotification: a6f7c09e1ca7220e2be1c45e9b6b897c9600024b
+ RNWorklets: 582ee5c59370d483a7a3c3f8a8014d48b1bff6bd
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
- stream-chat-react-native: 2138656043846cd04d5d284605ef07af9a5309bc
- stream-io-noise-cancellation-react-native: 17dfc185dc9b2552f70a1510cf818228dcd2e436
- stream-io-video-filters-react-native: 5f24440c96fda08d50d7e33910a60d354c9771fe
- stream-react-native-webrtc: 1bef09475caf435abbbd8aec8f8c3a9b1ee1fdf0
- stream-video-react-native: e4023430bda1d702a1ce83355db70515ace3f727
+ stream-chat-react-native: 615d9d16c569045da3737a03f54ec3a1d781be81
+ stream-io-noise-cancellation-react-native: 6ba3a3818974c0afc8e39689ba50d65ef5728cb4
+ stream-io-video-filters-react-native: df27d177b2ea10484bfdbb923b577522dbcf77de
+ stream-react-native-webrtc: 3cd9c4c662a196c7cf3faf968c6caab081283ada
+ stream-video-react-native: 185bca35b03ee3531d7c457652bc0e6455942829
StreamVideoNoiseCancellation: 41f5a712aba288f9636b64b17ebfbdff52c61490
StreamWebRTC: 57bd35729bcc46b008de4e741a5b23ac28b8854d
- VisionCamera: 891edb31806dd3a239c8a9d6090d6ec78e11ee80
+ VisionCamera: 05e4bc4783174689a5878a0797015ab32afae9e4
Yoga: cc4a6600d61e4e9276e860d4d68eebb834a050ba
PODFILE CHECKSUM: aa62ba474533b73121c2068a13a8b909b17efbaa
diff --git a/sample-apps/react-native/dogfood/metro.config.js b/sample-apps/react-native/dogfood/metro.config.js
index a414f24daa..0dc43e348f 100644
--- a/sample-apps/react-native/dogfood/metro.config.js
+++ b/sample-apps/react-native/dogfood/metro.config.js
@@ -14,6 +14,7 @@ config.watchFolders = [
path.join(workspaceRoot, 'packages/react-native-sdk'),
path.join(workspaceRoot, 'packages/video-filters-react-native'),
path.join(workspaceRoot, 'packages/noise-cancellation-react-native'),
+ path.join(workspaceRoot, 'packages/react-native-callingx'),
];
// find what all modules need to be unique for the app
diff --git a/sample-apps/react-native/dogfood/package.json b/sample-apps/react-native/dogfood/package.json
index 713178e4a7..c36868689d 100644
--- a/sample-apps/react-native/dogfood/package.json
+++ b/sample-apps/react-native/dogfood/package.json
@@ -28,7 +28,7 @@
"react": "19.1.0",
"react-native": "^0.81.5",
"react-native-blob-util": "^0.22.2",
- "react-native-callkeep": "^4.3.16",
+ "react-native-callingx": "workspace:^",
"react-native-device-info": "^14.1.1",
"react-native-dotenv": "^3.4.11",
"react-native-gesture-handler": "^2.28.0",
diff --git a/sample-apps/react-native/dogfood/src/utils/setPushConfig.ts b/sample-apps/react-native/dogfood/src/utils/setPushConfig.ts
index 58158bd415..7d0c2524f4 100644
--- a/sample-apps/react-native/dogfood/src/utils/setPushConfig.ts
+++ b/sample-apps/react-native/dogfood/src/utils/setPushConfig.ts
@@ -84,18 +84,22 @@ export function setPushConfig() {
},
});
+ StreamVideoRN.setupCallingExp({
+ enableOutcomingCalls: true,
+ });
+
setFirebaseListeners();
if (Platform.OS === 'android') {
// on press handlers of background notifications
notifee.onBackgroundEvent(async (event) => {
if (isNotifeeStreamVideoEvent(event)) {
- await onAndroidNotifeeEvent({ event, isBackground: true });
+ await onAndroidNotifeeEvent({ event });
}
});
// on press handlers of foreground notifications
notifee.onForegroundEvent((event) => {
if (isNotifeeStreamVideoEvent(event)) {
- onAndroidNotifeeEvent({ event, isBackground: false });
+ onAndroidNotifeeEvent({ event });
}
});
}
@@ -104,7 +108,7 @@ export function setPushConfig() {
// note: used only for non-ringing notifications
notifee.onForegroundEvent((event) => {
if (isNotifeeStreamVideoEvent(event)) {
- oniOSNotifeeEvent({ event, isBackground: false });
+ oniOSNotifeeEvent({ event });
}
});
}
diff --git a/sample-apps/react-native/expo-video-sample/app.json b/sample-apps/react-native/expo-video-sample/app.json
index a6c1ceed66..e75a35e4b3 100644
--- a/sample-apps/react-native/expo-video-sample/app.json
+++ b/sample-apps/react-native/expo-video-sample/app.json
@@ -74,11 +74,7 @@
"addNoiseCancellation": true,
"androidKeepCallAlive": true,
"appleTeamId": "EHV7XZLAHA",
- "ringingPushNotifications": {
- "disableVideoIos": false,
- "includesCallsInRecentsIos": false,
- "showWhenLockedAndroid": true
- },
+ "ringing": true,
"enableNonRingingPushNotifications": true,
"androidPictureInPicture": true,
"iOSEnableMultitaskingCameraAccess": true
diff --git a/sample-apps/react-native/expo-video-sample/package.json b/sample-apps/react-native/expo-video-sample/package.json
index f8ed413477..9019c7238e 100644
--- a/sample-apps/react-native/expo-video-sample/package.json
+++ b/sample-apps/react-native/expo-video-sample/package.json
@@ -36,7 +36,7 @@
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "^0.81.5",
- "react-native-callkeep": "^4.3.16",
+ "react-native-callingx": "workspace:^",
"react-native-gesture-handler": "^2.28.0",
"react-native-reanimated": "~4.1.2",
"react-native-safe-area-context": "~5.6.1",
diff --git a/sample-apps/react-native/expo-video-sample/utils/setPushConfig.ts b/sample-apps/react-native/expo-video-sample/utils/setPushConfig.ts
index 3a8b651dd3..117a453a02 100644
--- a/sample-apps/react-native/expo-video-sample/utils/setPushConfig.ts
+++ b/sample-apps/react-native/expo-video-sample/utils/setPushConfig.ts
@@ -68,13 +68,13 @@ export function setPushConfig() {
// on press handlers of background notifications
notifee.onBackgroundEvent(async (event) => {
if (isNotifeeStreamVideoEvent(event)) {
- await onAndroidNotifeeEvent({ event, isBackground: true });
+ await onAndroidNotifeeEvent({ event });
}
});
// on press handlers of foreground notifications
notifee.onForegroundEvent((event) => {
if (isNotifeeStreamVideoEvent(event)) {
- onAndroidNotifeeEvent({ event, isBackground: false });
+ onAndroidNotifeeEvent({ event });
}
});
}
@@ -96,7 +96,7 @@ export function setPushConfig() {
// note: used only for non-ringing notifications
notifee.onForegroundEvent((event) => {
if (isNotifeeStreamVideoEvent(event)) {
- oniOSNotifeeEvent({ event, isBackground: false });
+ oniOSNotifeeEvent({ event });
}
});
}
diff --git a/sample-apps/react-native/ringing-tutorial/app.json b/sample-apps/react-native/ringing-tutorial/app.json
index e0f5055000..fa89effa5a 100644
--- a/sample-apps/react-native/ringing-tutorial/app.json
+++ b/sample-apps/react-native/ringing-tutorial/app.json
@@ -80,11 +80,7 @@
[
"@stream-io/video-react-native-sdk",
{
- "ringingPushNotifications": {
- "disableVideoIos": false,
- "includesCallsInRecentsIos": false,
- "showWhenLockedAndroid": true
- },
+ "ringing": true,
"androidKeepCallAlive": true
}
],
diff --git a/sample-apps/react-native/ringing-tutorial/package.json b/sample-apps/react-native/ringing-tutorial/package.json
index eac251dc1f..53784ef2c4 100644
--- a/sample-apps/react-native/ringing-tutorial/package.json
+++ b/sample-apps/react-native/ringing-tutorial/package.json
@@ -42,7 +42,7 @@
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "^0.81.5",
- "react-native-callkeep": "^4.3.16",
+ "react-native-callingx": "workspace:^",
"react-native-gesture-handler": "^2.28.0",
"react-native-reanimated": "~4.1.2",
"react-native-safe-area-context": "~5.6.1",
diff --git a/sample-apps/react-native/ringing-tutorial/utils/setFirebaseListeners.android.ts b/sample-apps/react-native/ringing-tutorial/utils/setFirebaseListeners.android.ts
index 44486ccde0..a1123779c2 100644
--- a/sample-apps/react-native/ringing-tutorial/utils/setFirebaseListeners.android.ts
+++ b/sample-apps/react-native/ringing-tutorial/utils/setFirebaseListeners.android.ts
@@ -16,7 +16,7 @@ export const setFirebaseListeners = () => {
});
notifee.onBackgroundEvent(async (event) => {
if (isNotifeeStreamVideoEvent(event)) {
- await onAndroidNotifeeEvent({ event, isBackground: true });
+ await onAndroidNotifeeEvent({ event });
}
});
// Set up the foreground message handlers
@@ -27,7 +27,7 @@ export const setFirebaseListeners = () => {
});
notifee.onForegroundEvent((event) => {
if (isNotifeeStreamVideoEvent(event)) {
- onAndroidNotifeeEvent({ event, isBackground: false });
+ onAndroidNotifeeEvent({ event });
}
});
};
diff --git a/yarn.lock b/yarn.lock
index 9619d3474b..9751272685 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -59,6 +59,22 @@ __metadata:
languageName: node
linkType: hard
+"@ark/schema@npm:0.55.0":
+ version: 0.55.0
+ resolution: "@ark/schema@npm:0.55.0"
+ dependencies:
+ "@ark/util": "npm:0.55.0"
+ checksum: 10/18fbfe27f3da911ba38d063ba07b35d3236df124a32bb47ce1ed9cbf25185fe337b37a87f0776831cc698d7295fe4c9ec5547c444c5648ac5205f45c4514aa71
+ languageName: node
+ linkType: hard
+
+"@ark/util@npm:0.55.0":
+ version: 0.55.0
+ resolution: "@ark/util@npm:0.55.0"
+ checksum: 10/a172db34c566e6677f210b6b1fbfab49f86a5c81c7ae6633be43860cac60b67245f7af518b4db92fa9947eb2fb854e1166df3358e60556b2621ecb7547ffd1ef
+ languageName: node
+ linkType: hard
+
"@babel/cli@npm:^7.23.4":
version: 7.26.4
resolution: "@babel/cli@npm:7.26.4"
@@ -136,6 +152,20 @@ __metadata:
languageName: node
linkType: hard
+"@babel/eslint-parser@npm:^7.25.1":
+ version: 7.28.5
+ resolution: "@babel/eslint-parser@npm:7.28.5"
+ dependencies:
+ "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1"
+ eslint-visitor-keys: "npm:^2.1.0"
+ semver: "npm:^6.3.1"
+ peerDependencies:
+ "@babel/core": ^7.11.0
+ eslint: ^7.5.0 || ^8.0.0 || ^9.0.0
+ checksum: 10/ec8eb061f319fe3854f4c720303bf239625e63c5ddc9391a3c00f17339d417dc5482dc043b64d15506b0e87f26820dfec9ff4880a1862f7c05f4cf1bbf6e34be
+ languageName: node
+ linkType: hard
+
"@babel/generator@npm:^7.20.0, @babel/generator@npm:^7.20.5, @babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.7, @babel/generator@npm:^7.28.3, @babel/generator@npm:^7.7.2":
version: 7.28.3
resolution: "@babel/generator@npm:7.28.3"
@@ -565,6 +595,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-syntax-flow@npm:^7.27.1":
+ version: 7.27.1
+ resolution: "@babel/plugin-syntax-flow@npm:7.27.1"
+ dependencies:
+ "@babel/helper-plugin-utils": "npm:^7.27.1"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: 10/7baca3171ed595d04c865b0ce46fca7f21900686df9d7fcd1017036ce78bb5483e33803de810831e68d39cf478953db69f49ae3f3de2e3207bc4ba49a96b6739
+ languageName: node
+ linkType: hard
+
"@babel/plugin-syntax-import-assertions@npm:^7.27.1":
version: 7.27.1
resolution: "@babel/plugin-syntax-import-assertions@npm:7.27.1"
@@ -935,6 +976,18 @@ __metadata:
languageName: node
linkType: hard
+"@babel/plugin-transform-flow-strip-types@npm:^7.26.5":
+ version: 7.27.1
+ resolution: "@babel/plugin-transform-flow-strip-types@npm:7.27.1"
+ dependencies:
+ "@babel/helper-plugin-utils": "npm:^7.27.1"
+ "@babel/plugin-syntax-flow": "npm:^7.27.1"
+ peerDependencies:
+ "@babel/core": ^7.0.0-0
+ checksum: 10/22e260866b122b7d0c35f2c55b2d422b175606b4d14c9ba116b1fbe88e08cc8b024c1c41bb62527cfc5f7ccc0ed06c752e5945cb1ee22465a30aa5623e617940
+ languageName: node
+ linkType: hard
+
"@babel/plugin-transform-for-of@npm:^7.24.7, @babel/plugin-transform-for-of@npm:^7.27.1":
version: 7.27.1
resolution: "@babel/plugin-transform-for-of@npm:7.27.1"
@@ -1669,6 +1722,197 @@ __metadata:
languageName: node
linkType: hard
+"@commitlint/cli@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/cli@npm:19.8.1"
+ dependencies:
+ "@commitlint/format": "npm:^19.8.1"
+ "@commitlint/lint": "npm:^19.8.1"
+ "@commitlint/load": "npm:^19.8.1"
+ "@commitlint/read": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ tinyexec: "npm:^1.0.0"
+ yargs: "npm:^17.0.0"
+ bin:
+ commitlint: ./cli.js
+ checksum: 10/c41f5a42319e38e1da2addd27b32ced461eae2d01c9bbfc75be069d88467974255dfbe4593d3e107a0e3f68350f482490bcda69d9d6a4192cde8084f203e7c8b
+ languageName: node
+ linkType: hard
+
+"@commitlint/config-conventional@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/config-conventional@npm:19.8.1"
+ dependencies:
+ "@commitlint/types": "npm:^19.8.1"
+ conventional-changelog-conventionalcommits: "npm:^7.0.2"
+ checksum: 10/aa61837baaf49e8ccf5eb8fa1bd78656abbea58edb73dacddc64c8915f1d28b27590005d66664c88b9a28a57e9a03ff11cf3b1d913af1ea4e86f3b66678ce630
+ languageName: node
+ linkType: hard
+
+"@commitlint/config-validator@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/config-validator@npm:19.8.1"
+ dependencies:
+ "@commitlint/types": "npm:^19.8.1"
+ ajv: "npm:^8.11.0"
+ checksum: 10/26eee15c1c0564fc8857b4bbc4f06305a32e049a724ede73753f66fc15316eb79a5dde4c8e2765bd75952a27b138cd80cffc49491281f122b834f8467c658d80
+ languageName: node
+ linkType: hard
+
+"@commitlint/ensure@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/ensure@npm:19.8.1"
+ dependencies:
+ "@commitlint/types": "npm:^19.8.1"
+ lodash.camelcase: "npm:^4.3.0"
+ lodash.kebabcase: "npm:^4.1.1"
+ lodash.snakecase: "npm:^4.1.1"
+ lodash.startcase: "npm:^4.4.0"
+ lodash.upperfirst: "npm:^4.3.1"
+ checksum: 10/af342f61b246c301937cc03477c64b86ca6dea47de23f94d237181d346d020ec23c8a458f56aec8bfe9cdcb80a06adcc34964f32c05a2649282a959ce6fae39d
+ languageName: node
+ linkType: hard
+
+"@commitlint/execute-rule@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/execute-rule@npm:19.8.1"
+ checksum: 10/a39d9a87c0962c290e4f7d7438e8fca7642384a5aa97ec84c0b3dbbf91dc048496dd25447ba3dbec37b00006eec1951f8f22f30a98448e90e22d44d585d8a68f
+ languageName: node
+ linkType: hard
+
+"@commitlint/format@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/format@npm:19.8.1"
+ dependencies:
+ "@commitlint/types": "npm:^19.8.1"
+ chalk: "npm:^5.3.0"
+ checksum: 10/5af80e489c1470e20519780867145492c145690bd8e6b0dc049f53d317b045fa39ba012faed2715307e105ca439e6b16bdd4fe9c39c146d38bb5d93f1542fc5f
+ languageName: node
+ linkType: hard
+
+"@commitlint/is-ignored@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/is-ignored@npm:19.8.1"
+ dependencies:
+ "@commitlint/types": "npm:^19.8.1"
+ semver: "npm:^7.6.0"
+ checksum: 10/a70631bb7825ed49f2d6164c7547d025ca184a5e65eb7b1bd63f041ae7aa9189991c2dbef18b1160951aeb59595307b75d5ba151ea10e0de4d36f22709b9c877
+ languageName: node
+ linkType: hard
+
+"@commitlint/lint@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/lint@npm:19.8.1"
+ dependencies:
+ "@commitlint/is-ignored": "npm:^19.8.1"
+ "@commitlint/parse": "npm:^19.8.1"
+ "@commitlint/rules": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ checksum: 10/6206236649b2214c9c81d76e00bb9d010fc5be6c990d14e473a01253e178ad3a4e081b5c458154314291805de843eebfdd35d720d2eff889f86f43269c9d392a
+ languageName: node
+ linkType: hard
+
+"@commitlint/load@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/load@npm:19.8.1"
+ dependencies:
+ "@commitlint/config-validator": "npm:^19.8.1"
+ "@commitlint/execute-rule": "npm:^19.8.1"
+ "@commitlint/resolve-extends": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ chalk: "npm:^5.3.0"
+ cosmiconfig: "npm:^9.0.0"
+ cosmiconfig-typescript-loader: "npm:^6.1.0"
+ lodash.isplainobject: "npm:^4.0.6"
+ lodash.merge: "npm:^4.6.2"
+ lodash.uniq: "npm:^4.5.0"
+ checksum: 10/e78c997ef529f80f8b62f686e553d0f2cb33d88b8b907d2e3890195851cd783fd44bd780addaa49f1cceb12ed073c10bb10e11dc082f51e4fdc54640f5ac1cca
+ languageName: node
+ linkType: hard
+
+"@commitlint/message@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/message@npm:19.8.1"
+ checksum: 10/e365590dd539fe2519a15bd99ee8499c3ffbd80852839783ae6fd0b65feef08b26d2134a4e9ea32e006c2b3aa04447a38b011e73975b4fc3d7c7380a0fbf2377
+ languageName: node
+ linkType: hard
+
+"@commitlint/parse@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/parse@npm:19.8.1"
+ dependencies:
+ "@commitlint/types": "npm:^19.8.1"
+ conventional-changelog-angular: "npm:^7.0.0"
+ conventional-commits-parser: "npm:^5.0.0"
+ checksum: 10/f6264bb30399b420a875532905e18049b4ab6f24d79f42d20fa06e64b9f355649ac18a33874e02643f0a826f3cec69423d6bc96cf852fa692338603ce910a95f
+ languageName: node
+ linkType: hard
+
+"@commitlint/read@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/read@npm:19.8.1"
+ dependencies:
+ "@commitlint/top-level": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ git-raw-commits: "npm:^4.0.0"
+ minimist: "npm:^1.2.8"
+ tinyexec: "npm:^1.0.0"
+ checksum: 10/ee0f42e2e5a3ade673b2d14f3b2056a86804afe7d09b6703d51b41edc099b33b9c09dc715b30d7113879999381a198d78b4fcbc649785ed3beb9c3f7d1dc2bb2
+ languageName: node
+ linkType: hard
+
+"@commitlint/resolve-extends@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/resolve-extends@npm:19.8.1"
+ dependencies:
+ "@commitlint/config-validator": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ global-directory: "npm:^4.0.1"
+ import-meta-resolve: "npm:^4.0.0"
+ lodash.mergewith: "npm:^4.6.2"
+ resolve-from: "npm:^5.0.0"
+ checksum: 10/736e62f5fe819337a95de8ac50b65b04bdd472a652ebe18ac3a92efc3428d62dcf16d9c62b222ef2e8a7e2e8737bd49d13b9c9d3b061a588869a42acdc620bf0
+ languageName: node
+ linkType: hard
+
+"@commitlint/rules@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/rules@npm:19.8.1"
+ dependencies:
+ "@commitlint/ensure": "npm:^19.8.1"
+ "@commitlint/message": "npm:^19.8.1"
+ "@commitlint/to-lines": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ checksum: 10/dc3a90b4561369991b851224c5cc1c0e2297c68ce148e21a7a5893a0556fffced192d59bf491a6c80270da012840fafdb34d991b7048170f4b2e7b0122211cee
+ languageName: node
+ linkType: hard
+
+"@commitlint/to-lines@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/to-lines@npm:19.8.1"
+ checksum: 10/47f33d5e0d77aa0cc2fc14daa3e73661c64c9cffb5fc9c723714ced4fcfc758bf5ba2e084143fa55bc512ad896d115b9983a308a97a005200484f04f2ed0fd90
+ languageName: node
+ linkType: hard
+
+"@commitlint/top-level@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/top-level@npm:19.8.1"
+ dependencies:
+ find-up: "npm:^7.0.0"
+ checksum: 10/c875b6c1be495675c77d86e80419d27fd5eb70fc061ef412d041541219c3222d9c4dbd6f0353247d49e9b2cd6d86a7ffc9df1ba20f96c77726c1f9a0edeeb8fe
+ languageName: node
+ linkType: hard
+
+"@commitlint/types@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "@commitlint/types@npm:19.8.1"
+ dependencies:
+ "@types/conventional-commits-parser": "npm:^5.0.0"
+ chalk: "npm:^5.3.0"
+ checksum: 10/d1943a5789a02c75b0c72755673ab8d50c850b025abb7806b7eef83b373591948f5d1d9cd22022f89302a256546934d797445913c5c495d8e92711cf17b0fbf0
+ languageName: node
+ linkType: hard
+
"@config-plugins/react-native-callkeep@npm:^12.0.0":
version: 12.0.0
resolution: "@config-plugins/react-native-callkeep@npm:12.0.0"
@@ -1687,6 +1931,25 @@ __metadata:
languageName: node
linkType: hard
+"@conventional-changelog/git-client@npm:^2.5.1":
+ version: 2.5.1
+ resolution: "@conventional-changelog/git-client@npm:2.5.1"
+ dependencies:
+ "@simple-libs/child-process-utils": "npm:^1.0.0"
+ "@simple-libs/stream-utils": "npm:^1.1.0"
+ semver: "npm:^7.5.2"
+ peerDependencies:
+ conventional-commits-filter: ^5.0.0
+ conventional-commits-parser: ^6.1.0
+ peerDependenciesMeta:
+ conventional-commits-filter:
+ optional: true
+ conventional-commits-parser:
+ optional: true
+ checksum: 10/39ed505f8b93529ae278f71a75a67c52be54b20a374c7a209918e6c0374e3a4bebd8f8ca7497cbc28c8c062a3923890f54fe8077bca5424c9c42fb7fb4daf71f
+ languageName: node
+ linkType: hard
+
"@egjs/hammerjs@npm:^2.0.17":
version: 2.0.17
resolution: "@egjs/hammerjs@npm:2.0.17"
@@ -2058,7 +2321,7 @@ __metadata:
languageName: node
linkType: hard
-"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0":
+"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0":
version: 4.9.0
resolution: "@eslint-community/eslint-utils@npm:4.9.0"
dependencies:
@@ -2076,6 +2339,20 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/compat@npm:^1.3.2":
+ version: 1.4.1
+ resolution: "@eslint/compat@npm:1.4.1"
+ dependencies:
+ "@eslint/core": "npm:^0.17.0"
+ peerDependencies:
+ eslint: ^8.40 || 9
+ peerDependenciesMeta:
+ eslint:
+ optional: true
+ checksum: 10/2345ba0991aaf57f79feed0417eac61fd0e09fb1d2f5bc3f723d5790a4f0881cca16b7a48c82555ab907a3469dce7d3cb43cc5e5100c22e2a369a561f4b421cd
+ languageName: node
+ linkType: hard
+
"@eslint/config-array@npm:^0.21.0":
version: 0.21.0
resolution: "@eslint/config-array@npm:0.21.0"
@@ -2087,6 +2364,17 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/config-array@npm:^0.21.1":
+ version: 0.21.1
+ resolution: "@eslint/config-array@npm:0.21.1"
+ dependencies:
+ "@eslint/object-schema": "npm:^2.1.7"
+ debug: "npm:^4.3.1"
+ minimatch: "npm:^3.1.2"
+ checksum: 10/6eaa0435972f735ce52d581f355a0b616e50a9b8a73304a7015398096e252798b9b3b968a67b524eefb0fdeacc57c4d960f0ec6432abe1c1e24be815b88c5d18
+ languageName: node
+ linkType: hard
+
"@eslint/config-helpers@npm:^0.4.0":
version: 0.4.0
resolution: "@eslint/config-helpers@npm:0.4.0"
@@ -2096,6 +2384,15 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/config-helpers@npm:^0.4.2":
+ version: 0.4.2
+ resolution: "@eslint/config-helpers@npm:0.4.2"
+ dependencies:
+ "@eslint/core": "npm:^0.17.0"
+ checksum: 10/3f2b4712d8e391c36ec98bc200f7dea423dfe518e42956569666831b89ede83b33120c761dfd3ab6347d8e8894a6d4af47254a18d464a71c6046fd88065f6daf
+ languageName: node
+ linkType: hard
+
"@eslint/core@npm:^0.16.0":
version: 0.16.0
resolution: "@eslint/core@npm:0.16.0"
@@ -2105,6 +2402,15 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/core@npm:^0.17.0":
+ version: 0.17.0
+ resolution: "@eslint/core@npm:0.17.0"
+ dependencies:
+ "@types/json-schema": "npm:^7.0.15"
+ checksum: 10/f9a428cc651ec15fb60d7d60c2a7bacad4666e12508320eafa98258e976fafaa77d7be7be91519e75f801f15f830105420b14a458d4aab121a2b0a59bc43517b
+ languageName: node
+ linkType: hard
+
"@eslint/eslintrc@npm:^3.3.1":
version: 3.3.1
resolution: "@eslint/eslintrc@npm:3.3.1"
@@ -2129,6 +2435,13 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/js@npm:9.39.1, @eslint/js@npm:^9.35.0":
+ version: 9.39.1
+ resolution: "@eslint/js@npm:9.39.1"
+ checksum: 10/b10b9b953212c0f3ffca475159bbe519e9e98847200c7432d1637d444fddcd7b712d2b7710a7dc20510f9cfbe8db330039b2aad09cb55d9545b116d940dbeed2
+ languageName: node
+ linkType: hard
+
"@eslint/object-schema@npm:^2.1.6":
version: 2.1.6
resolution: "@eslint/object-schema@npm:2.1.6"
@@ -2136,6 +2449,13 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/object-schema@npm:^2.1.7":
+ version: 2.1.7
+ resolution: "@eslint/object-schema@npm:2.1.7"
+ checksum: 10/946ef5d6235b4d1c0907c6c6e6429c8895f535380c562b7705c131f63f2e961b06e8785043c86a293da48e0a60c6286d98ba395b8b32ea55561fe6e4417cb7e4
+ languageName: node
+ linkType: hard
+
"@eslint/plugin-kit@npm:^0.4.0":
version: 0.4.0
resolution: "@eslint/plugin-kit@npm:0.4.0"
@@ -2146,6 +2466,16 @@ __metadata:
languageName: node
linkType: hard
+"@eslint/plugin-kit@npm:^0.4.1":
+ version: 0.4.1
+ resolution: "@eslint/plugin-kit@npm:0.4.1"
+ dependencies:
+ "@eslint/core": "npm:^0.17.0"
+ levn: "npm:^0.4.1"
+ checksum: 10/c5947d0ffeddca77d996ac1b886a66060c1a15ed1d5e425d0c7e7d7044a4bd3813fc968892d03950a7831c9b89368a2f7b281e45dd3c74a048962b74bf3a1cb4
+ languageName: node
+ linkType: hard
+
"@expo/cli@npm:54.0.10":
version: 54.0.10
resolution: "@expo/cli@npm:54.0.10"
@@ -3553,93 +3883,340 @@ __metadata:
languageName: node
linkType: hard
-"@inquirer/external-editor@npm:^1.0.0":
+"@inquirer/ansi@npm:^1.0.0, @inquirer/ansi@npm:^1.0.2":
version: 1.0.2
- resolution: "@inquirer/external-editor@npm:1.0.2"
+ resolution: "@inquirer/ansi@npm:1.0.2"
+ checksum: 10/d1496e573a63ee6752bcf3fc93375cdabc55b0d60f0588fe7902282c710b223252ad318ff600ee904e48555634663b53fda517f5b29ce9fbda90bfae18592fbc
+ languageName: node
+ linkType: hard
+
+"@inquirer/checkbox@npm:^4.3.2":
+ version: 4.3.2
+ resolution: "@inquirer/checkbox@npm:4.3.2"
dependencies:
- chardet: "npm:^2.1.0"
- iconv-lite: "npm:^0.7.0"
+ "@inquirer/ansi": "npm:^1.0.2"
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/figures": "npm:^1.0.15"
+ "@inquirer/type": "npm:^3.0.10"
+ yoctocolors-cjs: "npm:^2.1.3"
peerDependencies:
"@types/node": ">=18"
peerDependenciesMeta:
"@types/node":
optional: true
- checksum: 10/d0c5c73249b8153f4cf872c4fba01c57a7653142a4cad496f17ed03ef3769330a4b3c519b68d70af69d4bb33003d2599b66b2242be85411c0b027ff383619666
+ checksum: 10/4ac5dd2679981e23f066c51c605cb1c63ccda9ea6e1ad895e675eb26702aaf6cf961bf5ca3acd832efba5edcf9883b6742002c801673d2b35c123a7fa7db7b23
languageName: node
linkType: hard
-"@isaacs/balanced-match@npm:^4.0.1":
- version: 4.0.1
- resolution: "@isaacs/balanced-match@npm:4.0.1"
- checksum: 10/102fbc6d2c0d5edf8f6dbf2b3feb21695a21bc850f11bc47c4f06aa83bd8884fde3fe9d6d797d619901d96865fdcb4569ac2a54c937992c48885c5e3d9967fe8
+"@inquirer/confirm@npm:^5.1.21":
+ version: 5.1.21
+ resolution: "@inquirer/confirm@npm:5.1.21"
+ dependencies:
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/type": "npm:^3.0.10"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/a107aa0073965ea510affb9e5b55baf40333503d600970c458c07770cd4e0eee01efc4caba66f0409b0fadc9550d127329622efb543cffcabff3ad0e7f865372
languageName: node
linkType: hard
-"@isaacs/brace-expansion@npm:^5.0.0":
- version: 5.0.0
- resolution: "@isaacs/brace-expansion@npm:5.0.0"
+"@inquirer/core@npm:^10.2.2, @inquirer/core@npm:^10.3.2":
+ version: 10.3.2
+ resolution: "@inquirer/core@npm:10.3.2"
dependencies:
- "@isaacs/balanced-match": "npm:^4.0.1"
- checksum: 10/cf3b7f206aff12128214a1df764ac8cdbc517c110db85249b945282407e3dfc5c6e66286383a7c9391a059fc8e6e6a8ca82262fc9d2590bd615376141fbebd2d
+ "@inquirer/ansi": "npm:^1.0.2"
+ "@inquirer/figures": "npm:^1.0.15"
+ "@inquirer/type": "npm:^3.0.10"
+ cli-width: "npm:^4.1.0"
+ mute-stream: "npm:^2.0.0"
+ signal-exit: "npm:^4.1.0"
+ wrap-ansi: "npm:^6.2.0"
+ yoctocolors-cjs: "npm:^2.1.3"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/eb434bdf0ae7d904367003c772bcd80cbf679f79c087c99a4949fd7288e9a2f713ec3ea63381b9a001f52389ab56a77fcd88d64d81a03b1195193410ce8971c2
languageName: node
linkType: hard
-"@isaacs/cliui@npm:^8.0.2":
- version: 8.0.2
- resolution: "@isaacs/cliui@npm:8.0.2"
+"@inquirer/editor@npm:^4.2.23":
+ version: 4.2.23
+ resolution: "@inquirer/editor@npm:4.2.23"
dependencies:
- string-width: "npm:^5.1.2"
- string-width-cjs: "npm:string-width@^4.2.0"
- strip-ansi: "npm:^7.0.1"
- strip-ansi-cjs: "npm:strip-ansi@^6.0.1"
- wrap-ansi: "npm:^8.1.0"
- wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0"
- checksum: 10/e9ed5fd27c3aec1095e3a16e0c0cf148d1fee55a38665c35f7b3f86a9b5d00d042ddaabc98e8a1cb7463b9378c15f22a94eb35e99469c201453eb8375191f243
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/external-editor": "npm:^1.0.3"
+ "@inquirer/type": "npm:^3.0.10"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/f91b9aadba6ea28a0f4ea5f075af421e076262aebbd737e1b9779f086fa9d559d064e9942a581544645d1dcf56d6b685e8063fe46677880fbca73f6de4e4e7c5
languageName: node
linkType: hard
-"@isaacs/fs-minipass@npm:^4.0.0":
- version: 4.0.1
- resolution: "@isaacs/fs-minipass@npm:4.0.1"
+"@inquirer/expand@npm:^4.0.23":
+ version: 4.0.23
+ resolution: "@inquirer/expand@npm:4.0.23"
dependencies:
- minipass: "npm:^7.0.4"
- checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/type": "npm:^3.0.10"
+ yoctocolors-cjs: "npm:^2.1.3"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/73ad1d6376e5efe2a452c33494d6d16ee2670c638ae470a795fdff4acb59a8e032e38e141f87b603b6e96320977519b375dac6471d86d5e3087a9c1db40e3111
languageName: node
linkType: hard
-"@isaacs/ttlcache@npm:^1.4.1":
- version: 1.4.1
- resolution: "@isaacs/ttlcache@npm:1.4.1"
- checksum: 10/57f2b00b58845d48a173c7668c58c27c3e6f91a56c17d6d4c58b38780a475a858ce3b4fc2cd4304469eee9f49818b79a187f0e13120b3617c4f67e4abc475698
+"@inquirer/external-editor@npm:^1.0.0":
+ version: 1.0.2
+ resolution: "@inquirer/external-editor@npm:1.0.2"
+ dependencies:
+ chardet: "npm:^2.1.0"
+ iconv-lite: "npm:^0.7.0"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/d0c5c73249b8153f4cf872c4fba01c57a7653142a4cad496f17ed03ef3769330a4b3c519b68d70af69d4bb33003d2599b66b2242be85411c0b027ff383619666
languageName: node
linkType: hard
-"@istanbuljs/load-nyc-config@npm:^1.0.0":
- version: 1.1.0
- resolution: "@istanbuljs/load-nyc-config@npm:1.1.0"
+"@inquirer/external-editor@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "@inquirer/external-editor@npm:1.0.3"
dependencies:
- camelcase: "npm:^5.3.1"
- find-up: "npm:^4.1.0"
- get-package-type: "npm:^0.1.0"
- js-yaml: "npm:^3.13.1"
- resolve-from: "npm:^5.0.0"
- checksum: 10/b000a5acd8d4fe6e34e25c399c8bdbb5d3a202b4e10416e17bfc25e12bab90bb56d33db6089ae30569b52686f4b35ff28ef26e88e21e69821d2b85884bd055b8
+ chardet: "npm:^2.1.1"
+ iconv-lite: "npm:^0.7.0"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/c95d7237a885b32031715089f92820525731d4d3c2bd7afdb826307dc296cc2b39e7a644b0bb265441963348cca42e7785feb29c3aaf18fd2b63131769bf6587
languageName: node
linkType: hard
-"@istanbuljs/schema@npm:^0.1.2":
- version: 0.1.3
- resolution: "@istanbuljs/schema@npm:0.1.3"
- checksum: 10/a9b1e49acdf5efc2f5b2359f2df7f90c5c725f2656f16099e8b2cd3a000619ecca9fc48cf693ba789cf0fd989f6e0df6a22bc05574be4223ecdbb7997d04384b
+"@inquirer/figures@npm:^1.0.15":
+ version: 1.0.15
+ resolution: "@inquirer/figures@npm:1.0.15"
+ checksum: 10/3f858807f361ca29f41ec1076bbece4098cc140d86a06159d42c6e3f6e4d9bec9e10871ccfcbbaa367d6a8462b01dff89f2b1b157d9de6e8726bec85533f525c
languageName: node
linkType: hard
-"@jest/console@npm:^29.7.0":
- version: 29.7.0
- resolution: "@jest/console@npm:29.7.0"
+"@inquirer/input@npm:^4.3.1":
+ version: 4.3.1
+ resolution: "@inquirer/input@npm:4.3.1"
dependencies:
- "@jest/types": "npm:^29.6.3"
- "@types/node": "npm:*"
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/type": "npm:^3.0.10"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/713aaa4c94263299fbd7adfd65378f788cac1b5047f2b7e1ea349ca669db6c7c91b69ab6e2f6660cdbc28c7f7888c5c77ab4433bd149931597e43976d1ba5f34
+ languageName: node
+ linkType: hard
+
+"@inquirer/number@npm:^3.0.23":
+ version: 3.0.23
+ resolution: "@inquirer/number@npm:3.0.23"
+ dependencies:
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/type": "npm:^3.0.10"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/50694807b71746e15ed69d100aae3c8014d83c90aa660e8a179fe0db1046f26d727947542f64e24cc8b969a61659cb89fe36208cc2b59c1816382b598e686dd2
+ languageName: node
+ linkType: hard
+
+"@inquirer/password@npm:^4.0.23":
+ version: 4.0.23
+ resolution: "@inquirer/password@npm:4.0.23"
+ dependencies:
+ "@inquirer/ansi": "npm:^1.0.2"
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/type": "npm:^3.0.10"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/97364970b01c85946a4a50ad876c53ef0c1857a9144e24fad65e5dfa4b4e5dd42564fbcdfa2b49bb049a25d127efbe0882cb18afcdd47b166ebd01c6c4b5e825
+ languageName: node
+ linkType: hard
+
+"@inquirer/prompts@npm:^7.8.6":
+ version: 7.10.1
+ resolution: "@inquirer/prompts@npm:7.10.1"
+ dependencies:
+ "@inquirer/checkbox": "npm:^4.3.2"
+ "@inquirer/confirm": "npm:^5.1.21"
+ "@inquirer/editor": "npm:^4.2.23"
+ "@inquirer/expand": "npm:^4.0.23"
+ "@inquirer/input": "npm:^4.3.1"
+ "@inquirer/number": "npm:^3.0.23"
+ "@inquirer/password": "npm:^4.0.23"
+ "@inquirer/rawlist": "npm:^4.1.11"
+ "@inquirer/search": "npm:^3.2.2"
+ "@inquirer/select": "npm:^4.4.2"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/b3e3386edd255e4e91c7908050674f8a2e69b043883c00feec2f87d697be37bc6e8cd4a360e7e3233a9825ae7ea044a2ac63d5700926d27f9959013d8566f890
+ languageName: node
+ linkType: hard
+
+"@inquirer/rawlist@npm:^4.1.11":
+ version: 4.1.11
+ resolution: "@inquirer/rawlist@npm:4.1.11"
+ dependencies:
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/type": "npm:^3.0.10"
+ yoctocolors-cjs: "npm:^2.1.3"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/0d8f6484cfc20749190e95eecfb2d034bafb3644ec4907b84b1673646f5dd71730e38e35565ea98dfd240d8851e3cff653edafcc4e0af617054b127b407e3229
+ languageName: node
+ linkType: hard
+
+"@inquirer/search@npm:^3.2.2":
+ version: 3.2.2
+ resolution: "@inquirer/search@npm:3.2.2"
+ dependencies:
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/figures": "npm:^1.0.15"
+ "@inquirer/type": "npm:^3.0.10"
+ yoctocolors-cjs: "npm:^2.1.3"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/abaed2df7763633ff4414b58d1c87233b69ed3cd2ac77629f0d54b72b8b585dc4806c7a2a8261daba58af5b0a2147e586d079fdc82060b6bcf56b75d3d03f3a7
+ languageName: node
+ linkType: hard
+
+"@inquirer/select@npm:^4.4.2":
+ version: 4.4.2
+ resolution: "@inquirer/select@npm:4.4.2"
+ dependencies:
+ "@inquirer/ansi": "npm:^1.0.2"
+ "@inquirer/core": "npm:^10.3.2"
+ "@inquirer/figures": "npm:^1.0.15"
+ "@inquirer/type": "npm:^3.0.10"
+ yoctocolors-cjs: "npm:^2.1.3"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/795ec0ac77d575f20bd6a12fb1c040093e62217ac0c80194829a8d3c3d1e09f70ad738e9a9dd6095cc8358fff4e13882209c09bdf8eb0864a86dcabef5b0a6a6
+ languageName: node
+ linkType: hard
+
+"@inquirer/type@npm:^3.0.10, @inquirer/type@npm:^3.0.8":
+ version: 3.0.10
+ resolution: "@inquirer/type@npm:3.0.10"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/57d113a9db7abc73326491e29bedc88ef362e53779f9f58a1b61225e0be068ce0c54e33cd65f4a13ca46131676fb72c3ef488463c4c9af0aa89680684c55d74c
+ languageName: node
+ linkType: hard
+
+"@isaacs/balanced-match@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "@isaacs/balanced-match@npm:4.0.1"
+ checksum: 10/102fbc6d2c0d5edf8f6dbf2b3feb21695a21bc850f11bc47c4f06aa83bd8884fde3fe9d6d797d619901d96865fdcb4569ac2a54c937992c48885c5e3d9967fe8
+ languageName: node
+ linkType: hard
+
+"@isaacs/brace-expansion@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@isaacs/brace-expansion@npm:5.0.0"
+ dependencies:
+ "@isaacs/balanced-match": "npm:^4.0.1"
+ checksum: 10/cf3b7f206aff12128214a1df764ac8cdbc517c110db85249b945282407e3dfc5c6e66286383a7c9391a059fc8e6e6a8ca82262fc9d2590bd615376141fbebd2d
+ languageName: node
+ linkType: hard
+
+"@isaacs/cliui@npm:^8.0.2":
+ version: 8.0.2
+ resolution: "@isaacs/cliui@npm:8.0.2"
+ dependencies:
+ string-width: "npm:^5.1.2"
+ string-width-cjs: "npm:string-width@^4.2.0"
+ strip-ansi: "npm:^7.0.1"
+ strip-ansi-cjs: "npm:strip-ansi@^6.0.1"
+ wrap-ansi: "npm:^8.1.0"
+ wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0"
+ checksum: 10/e9ed5fd27c3aec1095e3a16e0c0cf148d1fee55a38665c35f7b3f86a9b5d00d042ddaabc98e8a1cb7463b9378c15f22a94eb35e99469c201453eb8375191f243
+ languageName: node
+ linkType: hard
+
+"@isaacs/fs-minipass@npm:^4.0.0":
+ version: 4.0.1
+ resolution: "@isaacs/fs-minipass@npm:4.0.1"
+ dependencies:
+ minipass: "npm:^7.0.4"
+ checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5
+ languageName: node
+ linkType: hard
+
+"@isaacs/ttlcache@npm:^1.4.1":
+ version: 1.4.1
+ resolution: "@isaacs/ttlcache@npm:1.4.1"
+ checksum: 10/57f2b00b58845d48a173c7668c58c27c3e6f91a56c17d6d4c58b38780a475a858ce3b4fc2cd4304469eee9f49818b79a187f0e13120b3617c4f67e4abc475698
+ languageName: node
+ linkType: hard
+
+"@istanbuljs/load-nyc-config@npm:^1.0.0":
+ version: 1.1.0
+ resolution: "@istanbuljs/load-nyc-config@npm:1.1.0"
+ dependencies:
+ camelcase: "npm:^5.3.1"
+ find-up: "npm:^4.1.0"
+ get-package-type: "npm:^0.1.0"
+ js-yaml: "npm:^3.13.1"
+ resolve-from: "npm:^5.0.0"
+ checksum: 10/b000a5acd8d4fe6e34e25c399c8bdbb5d3a202b4e10416e17bfc25e12bab90bb56d33db6089ae30569b52686f4b35ff28ef26e88e21e69821d2b85884bd055b8
+ languageName: node
+ linkType: hard
+
+"@istanbuljs/schema@npm:^0.1.2":
+ version: 0.1.3
+ resolution: "@istanbuljs/schema@npm:0.1.3"
+ checksum: 10/a9b1e49acdf5efc2f5b2359f2df7f90c5c725f2656f16099e8b2cd3a000619ecca9fc48cf693ba789cf0fd989f6e0df6a22bc05574be4223ecdbb7997d04384b
+ languageName: node
+ linkType: hard
+
+"@jest/console@npm:^29.7.0":
+ version: 29.7.0
+ resolution: "@jest/console@npm:29.7.0"
+ dependencies:
+ "@jest/types": "npm:^29.6.3"
+ "@types/node": "npm:*"
chalk: "npm:^4.0.0"
jest-message-util: "npm:^29.7.0"
jest-util: "npm:^29.7.0"
@@ -4375,6 +4952,15 @@ __metadata:
languageName: node
linkType: hard
+"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1":
+ version: 5.1.1-v1
+ resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1"
+ dependencies:
+ eslint-scope: "npm:5.1.1"
+ checksum: 10/f2e3b2d6a6e2d9f163ca22105910c9f850dc4897af0aea3ef0a5886b63d8e1ba6505b71c99cb78a3bba24a09557d601eb21c8dede3f3213753fcfef364eb0e57
+ languageName: node
+ linkType: hard
+
"@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5"
@@ -4402,6 +4988,15 @@ __metadata:
languageName: node
linkType: hard
+"@nodeutils/defaults-deep@npm:1.1.0":
+ version: 1.1.0
+ resolution: "@nodeutils/defaults-deep@npm:1.1.0"
+ dependencies:
+ lodash: "npm:^4.15.0"
+ checksum: 10/4651c6e2179b0207f1a848f1e13eff7f2c24e7b6e52c965a8a5ef5140aea5df1fdafbf714026559e4f1f5828d3723eb35fe1b18dc2c7b0ec2265dc70b577bc34
+ languageName: node
+ linkType: hard
+
"@notifee/react-native@npm:9.1.8":
version: 9.1.8
resolution: "@notifee/react-native@npm:9.1.8"
@@ -4542,6 +5137,146 @@ __metadata:
languageName: node
linkType: hard
+"@octokit/auth-token@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "@octokit/auth-token@npm:6.0.0"
+ checksum: 10/a30f5c4c984964b57193de5b6f67169f74e4779fedbe716157dd3558dd9de3ca5c105cae521b7bd8ce1ae180773a2ef01afe2306ad5a329f4fd291eba2b7c7d1
+ languageName: node
+ linkType: hard
+
+"@octokit/core@npm:^7.0.2":
+ version: 7.0.6
+ resolution: "@octokit/core@npm:7.0.6"
+ dependencies:
+ "@octokit/auth-token": "npm:^6.0.0"
+ "@octokit/graphql": "npm:^9.0.3"
+ "@octokit/request": "npm:^10.0.6"
+ "@octokit/request-error": "npm:^7.0.2"
+ "@octokit/types": "npm:^16.0.0"
+ before-after-hook: "npm:^4.0.0"
+ universal-user-agent: "npm:^7.0.0"
+ checksum: 10/852d41fc3150d2a891156427dd0575c77889f1c7a109894ee541594e3fd47c0d4e0a93fee22966c507dfd6158b522e42846c2ac46b9d896078194c95fa81f4ae
+ languageName: node
+ linkType: hard
+
+"@octokit/endpoint@npm:^11.0.2":
+ version: 11.0.2
+ resolution: "@octokit/endpoint@npm:11.0.2"
+ dependencies:
+ "@octokit/types": "npm:^16.0.0"
+ universal-user-agent: "npm:^7.0.2"
+ checksum: 10/0d088747baf94eafbba69da23ba840b40cd3f5d0bfbc51c692ff9d9d78de6d81f06366e6e30df8c1783355be826c27d38ab9ab0708396af8f430b06cfa29db35
+ languageName: node
+ linkType: hard
+
+"@octokit/graphql@npm:^9.0.3":
+ version: 9.0.3
+ resolution: "@octokit/graphql@npm:9.0.3"
+ dependencies:
+ "@octokit/request": "npm:^10.0.6"
+ "@octokit/types": "npm:^16.0.0"
+ universal-user-agent: "npm:^7.0.0"
+ checksum: 10/7b16f281f8571dce55280b3986fbb8d15465a7236164a5f6497ded7597ff9ee95d5796924555b979903fe8c6706fe6be1b3e140d807297f85ac8edeadc28f9fe
+ languageName: node
+ linkType: hard
+
+"@octokit/openapi-types@npm:^26.0.0":
+ version: 26.0.0
+ resolution: "@octokit/openapi-types@npm:26.0.0"
+ checksum: 10/b9e1b1230b0a3d280b48902a927ce4e7df0d51096c928e2ee929035b0bce779fe7748a1ae58696f1c3080bf8338b6388d5caba5b0dbf254e9713303ed3abf7c2
+ languageName: node
+ linkType: hard
+
+"@octokit/openapi-types@npm:^27.0.0":
+ version: 27.0.0
+ resolution: "@octokit/openapi-types@npm:27.0.0"
+ checksum: 10/5cd2cdf4e41fdf522e15e3d53f3ece8380d98dda9173a6fc905828fb2c33e8733d5f5d2a757ae3a572525f4749748e66cb40e7939372132988d8eb4ba978d54f
+ languageName: node
+ linkType: hard
+
+"@octokit/plugin-paginate-rest@npm:^13.0.1":
+ version: 13.2.1
+ resolution: "@octokit/plugin-paginate-rest@npm:13.2.1"
+ dependencies:
+ "@octokit/types": "npm:^15.0.1"
+ peerDependencies:
+ "@octokit/core": ">=6"
+ checksum: 10/72ad8822594435e766acb968dcdfc3f15779aab9721c51febf078450805cd30c98f5dcaa397f9b20c166b2b75cb1a3b2e3da0354a770fdb502569ef90225e9b1
+ languageName: node
+ linkType: hard
+
+"@octokit/plugin-request-log@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "@octokit/plugin-request-log@npm:6.0.0"
+ peerDependencies:
+ "@octokit/core": ">=6"
+ checksum: 10/8a79973b1429bfead9113c4117f418aaef5ff368795daded3415ba14623d97d5fc08d1e822dbd566ecc9f041119e1a48a11853a9c48d9eb1caa62baa79c17f83
+ languageName: node
+ linkType: hard
+
+"@octokit/plugin-rest-endpoint-methods@npm:^16.0.0":
+ version: 16.1.1
+ resolution: "@octokit/plugin-rest-endpoint-methods@npm:16.1.1"
+ dependencies:
+ "@octokit/types": "npm:^15.0.1"
+ peerDependencies:
+ "@octokit/core": ">=6"
+ checksum: 10/230ad8bd9300e7e4a5e1b1f2c5ebf5f14e0a7e508bcf9355b926e5bcef4b481337ccd912cd3cd5a2498277326615d40805d35176801f7de59336683a3ef0434c
+ languageName: node
+ linkType: hard
+
+"@octokit/request-error@npm:^7.0.2":
+ version: 7.1.0
+ resolution: "@octokit/request-error@npm:7.1.0"
+ dependencies:
+ "@octokit/types": "npm:^16.0.0"
+ checksum: 10/c1d447ff7482382c69f7a4b2eaa44c672906dd111d8a9196a5d07f2adc4ae0f0e12ec4ce0063f14f9b2fb5f0cef4451c95ec961a7a711bd900e5d6441d546570
+ languageName: node
+ linkType: hard
+
+"@octokit/request@npm:^10.0.6":
+ version: 10.0.7
+ resolution: "@octokit/request@npm:10.0.7"
+ dependencies:
+ "@octokit/endpoint": "npm:^11.0.2"
+ "@octokit/request-error": "npm:^7.0.2"
+ "@octokit/types": "npm:^16.0.0"
+ fast-content-type-parse: "npm:^3.0.0"
+ universal-user-agent: "npm:^7.0.2"
+ checksum: 10/eaf6d347340729b47d482b487411e3543384d1c07f9125c4e53c11ece53f22a0245b71be22dd48bd6ad16af48c7c323c7317da49a238206d07fb7cd3ef0c6e74
+ languageName: node
+ linkType: hard
+
+"@octokit/rest@npm:22.0.0":
+ version: 22.0.0
+ resolution: "@octokit/rest@npm:22.0.0"
+ dependencies:
+ "@octokit/core": "npm:^7.0.2"
+ "@octokit/plugin-paginate-rest": "npm:^13.0.1"
+ "@octokit/plugin-request-log": "npm:^6.0.0"
+ "@octokit/plugin-rest-endpoint-methods": "npm:^16.0.0"
+ checksum: 10/d2b80fefd6aed307cb728980cb1d94cb484d48fabf0055198664287a7fb50544d312b005e4fb8dec2a6e97a153ec0ad7654d62f59898e1077a4cfba64e6d5c3e
+ languageName: node
+ linkType: hard
+
+"@octokit/types@npm:^15.0.1":
+ version: 15.0.2
+ resolution: "@octokit/types@npm:15.0.2"
+ dependencies:
+ "@octokit/openapi-types": "npm:^26.0.0"
+ checksum: 10/4f40a3eb65fab1370f8c988e6f8281265238fd1a4d69218eb7b496703c31c652aa27a834b134f6c8679f9029d6f547c61ad588a7a21e3d98fdc57448174ca9f8
+ languageName: node
+ linkType: hard
+
+"@octokit/types@npm:^16.0.0":
+ version: 16.0.0
+ resolution: "@octokit/types@npm:16.0.0"
+ dependencies:
+ "@octokit/openapi-types": "npm:^27.0.0"
+ checksum: 10/03d5cfc29556a9b53eae8beb1bf15c0b704dc722db2c51b53f093f3c3ee6c1d8e20b682be8117a3a17034b458be7746d1b22aaefb959ceb5152ad7589b39e2c9
+ languageName: node
+ linkType: hard
+
"@openapitools/openapi-generator-cli@npm:^2.25.0":
version: 2.25.0
resolution: "@openapitools/openapi-generator-cli@npm:2.25.0"
@@ -5092,6 +5827,13 @@ __metadata:
languageName: node
linkType: hard
+"@phun-ky/typeof@npm:2.0.3":
+ version: 2.0.3
+ resolution: "@phun-ky/typeof@npm:2.0.3"
+ checksum: 10/ca7daa8e520ca3e947c2cd47e25ab1f299acc87c05d5750747665c531a70395b8e4e5e510347bebc98d89d6c65dbe16b8d6604da2327d832aa5abe91703d0598
+ languageName: node
+ linkType: hard
+
"@pkgjs/parseargs@npm:^0.11.0":
version: 0.11.0
resolution: "@pkgjs/parseargs@npm:0.11.0"
@@ -5720,6 +6462,18 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-clean@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-clean@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ execa: "npm:^5.0.0"
+ fast-glob: "npm:^3.3.2"
+ checksum: 10/4389266313a0fe2baf0423b4860117040d91920d29a6430f65f8ab62b779efb3e082fc4d6eefb36180ba3aff2c02b34f2dc2cbf632ad18df749608701c1d1f05
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-config-android@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-config-android@npm:20.0.0"
@@ -5732,6 +6486,18 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-config-android@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-config-android@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ fast-glob: "npm:^3.3.2"
+ fast-xml-parser: "npm:^4.4.1"
+ checksum: 10/6e3f146509ea3f18c2be9e1c626511d9128519aa7e99b584f576257124c33e9d41d51c6e53ea52c1fcf6a06f30eab9eceee4dff37c91f13b273e4b8c5e94e3fe
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-config-apple@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-config-apple@npm:20.0.0"
@@ -5744,6 +6510,18 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-config-apple@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-config-apple@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ execa: "npm:^5.0.0"
+ fast-glob: "npm:^3.3.2"
+ checksum: 10/2cab86e8a156b2a23b31e3064593271d233267a9c746c42075864d9c11bea8de35d0956bf7b01f3f446a299f07d60edbb11da4f3b056b5850a6b35159f37ad52
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-config@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-config@npm:20.0.0"
@@ -5758,6 +6536,20 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-config@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-config@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ cosmiconfig: "npm:^9.0.0"
+ deepmerge: "npm:^4.3.0"
+ fast-glob: "npm:^3.3.2"
+ joi: "npm:^17.2.1"
+ checksum: 10/aac2bb49079585532af854ee3e29b18eba6cc94dcfae831c492379659292a93555dcbf690af14fecadb1ae0f0f9d08a6649e51f6821d3d9baf5983bccdb421da
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-doctor@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-doctor@npm:20.0.0"
@@ -5781,6 +6573,29 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-doctor@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-doctor@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-config": "npm:20.0.1"
+ "@react-native-community/cli-platform-android": "npm:20.0.1"
+ "@react-native-community/cli-platform-apple": "npm:20.0.1"
+ "@react-native-community/cli-platform-ios": "npm:20.0.1"
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ command-exists: "npm:^1.2.8"
+ deepmerge: "npm:^4.3.0"
+ envinfo: "npm:^7.13.0"
+ execa: "npm:^5.0.0"
+ node-stream-zip: "npm:^1.9.1"
+ ora: "npm:^5.4.1"
+ semver: "npm:^7.5.2"
+ wcwidth: "npm:^1.0.1"
+ yaml: "npm:^2.2.1"
+ checksum: 10/3f70f8a9c98f1b4b39ff7073628e595620e24520a744af4c6ca3c453cd3f6df3486132fa344b6a0c2d4ff130de65f38e83498a04b9a8e61b1d6a5d080c0c34bc
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-platform-android@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-platform-android@npm:20.0.0"
@@ -5794,6 +6609,19 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-platform-android@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-platform-android@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-config-android": "npm:20.0.1"
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ execa: "npm:^5.0.0"
+ logkitty: "npm:^0.7.1"
+ checksum: 10/d27eb40b7e7f76cc2f114a9b81600eae19b6bf08791c1e1a0feed6c602792a81e0a749e9e0e008e4eab5cf9b216d476b71de85cad03609343494a516902fb17f
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-platform-apple@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-platform-apple@npm:20.0.0"
@@ -5807,6 +6635,19 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-platform-apple@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-platform-apple@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-config-apple": "npm:20.0.1"
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ execa: "npm:^5.0.0"
+ fast-xml-parser: "npm:^4.4.1"
+ checksum: 10/3f1c2dbfbdf4b89a9403500fbe9c850e8fbe15e3f8869ac063dca2b181f7f21c1d99c984ec517ee682d0163f5347857ecd31ebfff52e63565583fb358850458e
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-platform-ios@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-platform-ios@npm:20.0.0"
@@ -5816,6 +6657,15 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-platform-ios@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-platform-ios@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-platform-apple": "npm:20.0.1"
+ checksum: 10/8abfd1872cecfa6a70790bac831fa3fea6e19e58e3ff9a70475d65b1c17af7426f4a97ea786cfe428dbf1cf2e64bdf1899b9b30eb00445311e54c78163b701b4
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-server-api@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-server-api@npm:20.0.0"
@@ -5834,6 +6684,24 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-server-api@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-server-api@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ body-parser: "npm:^1.20.3"
+ compression: "npm:^1.7.1"
+ connect: "npm:^3.6.5"
+ errorhandler: "npm:^1.5.1"
+ nocache: "npm:^3.0.1"
+ open: "npm:^6.2.0"
+ pretty-format: "npm:^29.7.0"
+ serve-static: "npm:^1.13.1"
+ ws: "npm:^6.2.3"
+ checksum: 10/36bf723828ff03ba86f33489c4296e2d46ba94b04edc3f5c23b680232a68a33547ea3d8b1fc7e8012c105ec97f6704e04d38e412c8e1349ca20157c55ea92616
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-tools@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-tools@npm:20.0.0"
@@ -5852,6 +6720,24 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-tools@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-tools@npm:20.0.1"
+ dependencies:
+ "@vscode/sudo-prompt": "npm:^9.0.0"
+ appdirsjs: "npm:^1.2.4"
+ chalk: "npm:^4.1.2"
+ execa: "npm:^5.0.0"
+ find-up: "npm:^5.0.0"
+ launch-editor: "npm:^2.9.1"
+ mime: "npm:^2.4.1"
+ ora: "npm:^5.4.1"
+ prompts: "npm:^2.4.2"
+ semver: "npm:^7.5.2"
+ checksum: 10/dacb2007419c2428cf7a91aeace8cb342c24bee48e09b9bc77cbef4c5b3c6ff67a60e8934d96e046aa00e4da0e2d0c0e70c761c0ab19e06554bdca6d3939e79f
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-types@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli-types@npm:20.0.0"
@@ -5861,6 +6747,15 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli-types@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli-types@npm:20.0.1"
+ dependencies:
+ joi: "npm:^17.2.1"
+ checksum: 10/8d5153b92b0b2ca409ae31eafa1ad1d5c332ead7a19b896e2be4003a3ae34aac6d999825f1281966e4ed5f88e0479f0b6147d6fb5e6fbb3b7ee378c725889ec1
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli@npm:20.0.0":
version: 20.0.0
resolution: "@react-native-community/cli@npm:20.0.0"
@@ -5886,6 +6781,31 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-community/cli@npm:20.0.1":
+ version: 20.0.1
+ resolution: "@react-native-community/cli@npm:20.0.1"
+ dependencies:
+ "@react-native-community/cli-clean": "npm:20.0.1"
+ "@react-native-community/cli-config": "npm:20.0.1"
+ "@react-native-community/cli-doctor": "npm:20.0.1"
+ "@react-native-community/cli-server-api": "npm:20.0.1"
+ "@react-native-community/cli-tools": "npm:20.0.1"
+ "@react-native-community/cli-types": "npm:20.0.1"
+ chalk: "npm:^4.1.2"
+ commander: "npm:^9.4.1"
+ deepmerge: "npm:^4.3.0"
+ execa: "npm:^5.0.0"
+ find-up: "npm:^5.0.0"
+ fs-extra: "npm:^8.1.0"
+ graceful-fs: "npm:^4.1.3"
+ prompts: "npm:^2.4.2"
+ semver: "npm:^7.5.2"
+ bin:
+ rnc-cli: build/bin.js
+ checksum: 10/63354c1f1b0bd8c69c15596026d8be950f7a8c570c6260d5d73c82e7e43e0f8e57d820ea68ac36140c13841cc54c64db18d1d0c1c6228f2342821f7c021ea393
+ languageName: node
+ linkType: hard
+
"@react-native-community/netinfo@npm:11.4.1, @react-native-community/netinfo@npm:^11.4.1":
version: 11.4.1
resolution: "@react-native-community/netinfo@npm:11.4.1"
@@ -5936,6 +6856,13 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/assets-registry@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/assets-registry@npm:0.81.1"
+ checksum: 10/eb9a69695f6354eb61b68a5ff056ee91f430ae435311f1e8aa72b2c40fdeecd0ad7c7f2334f9b7b6e60e645f6f900353405e4e95145e95fb02aadd13fe867a76
+ languageName: node
+ linkType: hard
+
"@react-native/assets-registry@npm:0.81.5":
version: 0.81.5
resolution: "@react-native/assets-registry@npm:0.81.5"
@@ -5943,6 +6870,16 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/babel-plugin-codegen@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/babel-plugin-codegen@npm:0.81.1"
+ dependencies:
+ "@babel/traverse": "npm:^7.25.3"
+ "@react-native/codegen": "npm:0.81.1"
+ checksum: 10/4321ba81ff440cc2b9bb593c865e660f643054629c6363e8a13c6b8ec678dd3086b3fadf877863676939fc4b32db4c4ce956f2b5d99f0abc946310458bb3d8f4
+ languageName: node
+ linkType: hard
+
"@react-native/babel-plugin-codegen@npm:0.81.4":
version: 0.81.4
resolution: "@react-native/babel-plugin-codegen@npm:0.81.4"
@@ -5963,6 +6900,61 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/babel-preset@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/babel-preset@npm:0.81.1"
+ dependencies:
+ "@babel/core": "npm:^7.25.2"
+ "@babel/plugin-proposal-export-default-from": "npm:^7.24.7"
+ "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3"
+ "@babel/plugin-syntax-export-default-from": "npm:^7.24.7"
+ "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3"
+ "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3"
+ "@babel/plugin-transform-arrow-functions": "npm:^7.24.7"
+ "@babel/plugin-transform-async-generator-functions": "npm:^7.25.4"
+ "@babel/plugin-transform-async-to-generator": "npm:^7.24.7"
+ "@babel/plugin-transform-block-scoping": "npm:^7.25.0"
+ "@babel/plugin-transform-class-properties": "npm:^7.25.4"
+ "@babel/plugin-transform-classes": "npm:^7.25.4"
+ "@babel/plugin-transform-computed-properties": "npm:^7.24.7"
+ "@babel/plugin-transform-destructuring": "npm:^7.24.8"
+ "@babel/plugin-transform-flow-strip-types": "npm:^7.25.2"
+ "@babel/plugin-transform-for-of": "npm:^7.24.7"
+ "@babel/plugin-transform-function-name": "npm:^7.25.1"
+ "@babel/plugin-transform-literals": "npm:^7.25.2"
+ "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.7"
+ "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8"
+ "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.24.7"
+ "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.24.7"
+ "@babel/plugin-transform-numeric-separator": "npm:^7.24.7"
+ "@babel/plugin-transform-object-rest-spread": "npm:^7.24.7"
+ "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.7"
+ "@babel/plugin-transform-optional-chaining": "npm:^7.24.8"
+ "@babel/plugin-transform-parameters": "npm:^7.24.7"
+ "@babel/plugin-transform-private-methods": "npm:^7.24.7"
+ "@babel/plugin-transform-private-property-in-object": "npm:^7.24.7"
+ "@babel/plugin-transform-react-display-name": "npm:^7.24.7"
+ "@babel/plugin-transform-react-jsx": "npm:^7.25.2"
+ "@babel/plugin-transform-react-jsx-self": "npm:^7.24.7"
+ "@babel/plugin-transform-react-jsx-source": "npm:^7.24.7"
+ "@babel/plugin-transform-regenerator": "npm:^7.24.7"
+ "@babel/plugin-transform-runtime": "npm:^7.24.7"
+ "@babel/plugin-transform-shorthand-properties": "npm:^7.24.7"
+ "@babel/plugin-transform-spread": "npm:^7.24.7"
+ "@babel/plugin-transform-sticky-regex": "npm:^7.24.7"
+ "@babel/plugin-transform-typescript": "npm:^7.25.2"
+ "@babel/plugin-transform-unicode-regex": "npm:^7.24.7"
+ "@babel/template": "npm:^7.25.0"
+ "@react-native/babel-plugin-codegen": "npm:0.81.1"
+ babel-plugin-syntax-hermes-parser: "npm:0.29.1"
+ babel-plugin-transform-flow-enums: "npm:^0.0.2"
+ react-refresh: "npm:^0.14.0"
+ peerDependencies:
+ "@babel/core": "*"
+ checksum: 10/fa11e95535233294059f46821173b9c2cba219e03c4d00f110e231728ccd2b2086ba04e9bde352f4c85306859f45ef2213b02f787b8521109f7f416df9f86c30
+ languageName: node
+ linkType: hard
+
"@react-native/babel-preset@npm:0.81.4":
version: 0.81.4
resolution: "@react-native/babel-preset@npm:0.81.4"
@@ -6073,6 +7065,23 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/codegen@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/codegen@npm:0.81.1"
+ dependencies:
+ "@babel/core": "npm:^7.25.2"
+ "@babel/parser": "npm:^7.25.3"
+ glob: "npm:^7.1.1"
+ hermes-parser: "npm:0.29.1"
+ invariant: "npm:^2.2.4"
+ nullthrows: "npm:^1.1.1"
+ yargs: "npm:^17.6.2"
+ peerDependencies:
+ "@babel/core": "*"
+ checksum: 10/9097dbcf9025dd580c2fbf0c0162c63a0b748916fce6afb159a1f3ee4cfd77fda391b8b260396bf2a298d4de8a61b5e7fb2315a4b160997dcfee3c7d2d802d5e
+ languageName: node
+ linkType: hard
+
"@react-native/codegen@npm:0.81.4":
version: 0.81.4
resolution: "@react-native/codegen@npm:0.81.4"
@@ -6107,6 +7116,29 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/community-cli-plugin@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/community-cli-plugin@npm:0.81.1"
+ dependencies:
+ "@react-native/dev-middleware": "npm:0.81.1"
+ debug: "npm:^4.4.0"
+ invariant: "npm:^2.2.4"
+ metro: "npm:^0.83.1"
+ metro-config: "npm:^0.83.1"
+ metro-core: "npm:^0.83.1"
+ semver: "npm:^7.1.3"
+ peerDependencies:
+ "@react-native-community/cli": "*"
+ "@react-native/metro-config": "*"
+ peerDependenciesMeta:
+ "@react-native-community/cli":
+ optional: true
+ "@react-native/metro-config":
+ optional: true
+ checksum: 10/d6dd960010f0cb2be94fbc48b7636af808c36732cc0533a70e69abf6a484ee40e735ca835b0d1ac97809ea9dd28f591c0abe2fb6c7b679a746eae3374a62ee8b
+ languageName: node
+ linkType: hard
+
"@react-native/community-cli-plugin@npm:0.81.5":
version: 0.81.5
resolution: "@react-native/community-cli-plugin@npm:0.81.5"
@@ -6130,6 +7162,13 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/debugger-frontend@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/debugger-frontend@npm:0.81.1"
+ checksum: 10/ce772bf32675234d66c539616e0524e08bfe9165bd2c93496974509d94ebc2b772cd5ed311adaa0f44a6e45e74c156df49063e8ae79b28f9ecd913fbc5318c7d
+ languageName: node
+ linkType: hard
+
"@react-native/debugger-frontend@npm:0.81.4":
version: 0.81.4
resolution: "@react-native/debugger-frontend@npm:0.81.4"
@@ -6144,6 +7183,25 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/dev-middleware@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/dev-middleware@npm:0.81.1"
+ dependencies:
+ "@isaacs/ttlcache": "npm:^1.4.1"
+ "@react-native/debugger-frontend": "npm:0.81.1"
+ chrome-launcher: "npm:^0.15.2"
+ chromium-edge-launcher: "npm:^0.2.0"
+ connect: "npm:^3.6.5"
+ debug: "npm:^4.4.0"
+ invariant: "npm:^2.2.4"
+ nullthrows: "npm:^1.1.1"
+ open: "npm:^7.0.3"
+ serve-static: "npm:^1.16.2"
+ ws: "npm:^6.2.3"
+ checksum: 10/99b06f02d85ddd42d23762fc09b3955d6eb5c03c50cbff897595fdd3504f30a20cfb59fc6a3ef2a7c9c159c5ed254974bede2a28fb08129ece0c03610d154f02
+ languageName: node
+ linkType: hard
+
"@react-native/dev-middleware@npm:0.81.4":
version: 0.81.4
resolution: "@react-native/dev-middleware@npm:0.81.4"
@@ -6182,6 +7240,43 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/eslint-config@npm:^0.81.1":
+ version: 0.81.5
+ resolution: "@react-native/eslint-config@npm:0.81.5"
+ dependencies:
+ "@babel/core": "npm:^7.25.2"
+ "@babel/eslint-parser": "npm:^7.25.1"
+ "@react-native/eslint-plugin": "npm:0.81.5"
+ "@typescript-eslint/eslint-plugin": "npm:^7.1.1"
+ "@typescript-eslint/parser": "npm:^7.1.1"
+ eslint-config-prettier: "npm:^8.5.0"
+ eslint-plugin-eslint-comments: "npm:^3.2.0"
+ eslint-plugin-ft-flow: "npm:^2.0.1"
+ eslint-plugin-jest: "npm:^27.9.0"
+ eslint-plugin-react: "npm:^7.30.1"
+ eslint-plugin-react-hooks: "npm:^5.2.0"
+ eslint-plugin-react-native: "npm:^4.0.0"
+ peerDependencies:
+ eslint: ">=8"
+ prettier: ">=2"
+ checksum: 10/59b017aed747a177caa95672158188d0ce1eee3fb9b60bd73a51841f0f28abab56b4c9d4056bdf8d2469579207d8afab433b60290b8f6a0c3f949505464a316d
+ languageName: node
+ linkType: hard
+
+"@react-native/eslint-plugin@npm:0.81.5":
+ version: 0.81.5
+ resolution: "@react-native/eslint-plugin@npm:0.81.5"
+ checksum: 10/57bea5be68fd90ac6e0b699fc0ce814e5cbda9f9319dfedb36b186e2d022102b44c9db7aed71464f8c631a5efa0af0bfc44d154c26f498a478feb29c4a0141f7
+ languageName: node
+ linkType: hard
+
+"@react-native/gradle-plugin@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/gradle-plugin@npm:0.81.1"
+ checksum: 10/9d75807431bd8671147eb5b2e894de3d1f8a6bd6b20f3478158fb10696e4505d8888934c909b5774aa48a1cfee2c1dcd0e4c6d0b3c88bfa69bba61466b314582
+ languageName: node
+ linkType: hard
+
"@react-native/gradle-plugin@npm:0.81.5":
version: 0.81.5
resolution: "@react-native/gradle-plugin@npm:0.81.5"
@@ -6189,6 +7284,13 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/js-polyfills@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/js-polyfills@npm:0.81.1"
+ checksum: 10/2cd9ccb46bec96c849537087458769d85952a2e9200b7d9a66a2db65dca9a0a3c21d7339e7bd63a8fef21c60f0ab77e6686fbebd277c9e7f708720c720d9a9f4
+ languageName: node
+ linkType: hard
+
"@react-native/js-polyfills@npm:0.81.5":
version: 0.81.5
resolution: "@react-native/js-polyfills@npm:0.81.5"
@@ -6222,6 +7324,13 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/normalize-colors@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/normalize-colors@npm:0.81.1"
+ checksum: 10/c1dae5e6494b7acea6cd40ac70a2f35b10ec09034dfbf504b633b9478ebe75212274302b032cad95073267e96a5658ff35978e718562ce9310afeea0d5009d2f
+ languageName: node
+ linkType: hard
+
"@react-native/normalize-colors@npm:0.81.4":
version: 0.81.4
resolution: "@react-native/normalize-colors@npm:0.81.4"
@@ -6250,6 +7359,23 @@ __metadata:
languageName: node
linkType: hard
+"@react-native/virtualized-lists@npm:0.81.1":
+ version: 0.81.1
+ resolution: "@react-native/virtualized-lists@npm:0.81.1"
+ dependencies:
+ invariant: "npm:^2.2.4"
+ nullthrows: "npm:^1.1.1"
+ peerDependencies:
+ "@types/react": ^19.1.0
+ react: "*"
+ react-native: "*"
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10/3baea44be69d15f94fbd0bcefd92b76ebf5c30e1b402eee3546cc7db306c0fa31cb054c5461bc978a0a5952c59e1ac3be346b067296e81a51da9d95eabb109e4
+ languageName: node
+ linkType: hard
+
"@react-native/virtualized-lists@npm:0.81.5":
version: 0.81.5
resolution: "@react-native/virtualized-lists@npm:0.81.5"
@@ -6390,6 +7516,23 @@ __metadata:
languageName: node
linkType: hard
+"@release-it/conventional-changelog@npm:^10.0.1":
+ version: 10.0.2
+ resolution: "@release-it/conventional-changelog@npm:10.0.2"
+ dependencies:
+ "@conventional-changelog/git-client": "npm:^2.5.1"
+ concat-stream: "npm:^2.0.0"
+ conventional-changelog: "npm:^7.1.1"
+ conventional-changelog-angular: "npm:^8.1.0"
+ conventional-changelog-conventionalcommits: "npm:^9.1.0"
+ conventional-recommended-bump: "npm:^11.2.0"
+ semver: "npm:^7.7.3"
+ peerDependencies:
+ release-it: ^18.0.0 || ^19.0.0
+ checksum: 10/3337224f1f1fe65ba384f4d350996cfeb2241874b870de943ec785404c11dfa92283531767d15923f087820f30c585f8b2b0fba92e5eac7e892a87261a3f378d
+ languageName: node
+ linkType: hard
+
"@remix-run/router@npm:1.23.0":
version: 1.23.0
resolution: "@remix-run/router@npm:1.23.0"
@@ -7111,6 +8254,25 @@ __metadata:
languageName: node
linkType: hard
+"@simple-libs/child-process-utils@npm:^1.0.0":
+ version: 1.0.1
+ resolution: "@simple-libs/child-process-utils@npm:1.0.1"
+ dependencies:
+ "@simple-libs/stream-utils": "npm:^1.1.0"
+ "@types/node": "npm:^22.0.0"
+ checksum: 10/5a8aa820fa635a116027b782fe601ec673a98f302e991e4b84097e007d7d65106caad96d5674d38a673c8fb63e0a737345498e982db5d53562b6cae5a680ee6c
+ languageName: node
+ linkType: hard
+
+"@simple-libs/stream-utils@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "@simple-libs/stream-utils@npm:1.1.0"
+ dependencies:
+ "@types/node": "npm:^22.0.0"
+ checksum: 10/13cb27400fa96c3d212d273ebc501851eaf4b13067be9961cfcc51e19e715e698c12cebd974ffa3135e94c7fd59c5bc857135cc64c1f61f3dd5f38e1a80d88a1
+ languageName: node
+ linkType: hard
+
"@sinclair/typebox@npm:^0.27.8":
version: 0.27.8
resolution: "@sinclair/typebox@npm:0.27.8"
@@ -7125,6 +8287,13 @@ __metadata:
languageName: node
linkType: hard
+"@sindresorhus/merge-streams@npm:^2.1.0":
+ version: 2.3.0
+ resolution: "@sindresorhus/merge-streams@npm:2.3.0"
+ checksum: 10/798bcb53cd1ace9df84fcdd1ba86afdc9e0cd84f5758d26ae9b1eefd8e8887e5fc30051132b9e74daf01bb41fa5a2faf1369361f83d76a3b3d7ee938058fd71c
+ languageName: node
+ linkType: hard
+
"@sinonjs/commons@npm:^2.0.0":
version: 2.0.0
resolution: "@sinonjs/commons@npm:2.0.0"
@@ -7267,7 +8436,7 @@ __metadata:
react: "npm:19.1.0"
react-dom: "npm:19.1.0"
react-native: "npm:^0.81.5"
- react-native-callkeep: "npm:^4.3.16"
+ react-native-callingx: "workspace:^"
react-native-gesture-handler: "npm:^2.28.0"
react-native-reanimated: "npm:~4.1.2"
react-native-safe-area-context: "npm:~5.6.1"
@@ -7601,7 +8770,7 @@ __metadata:
react: "npm:19.1.0"
react-native: "npm:^0.81.5"
react-native-blob-util: "npm:^0.22.2"
- react-native-callkeep: "npm:^4.3.16"
+ react-native-callingx: "workspace:^"
react-native-device-info: "npm:^14.1.1"
react-native-dotenv: "npm:^3.4.11"
react-native-gesture-handler: "npm:^2.28.0"
@@ -7664,7 +8833,7 @@ __metadata:
react: "npm:19.1.0"
react-dom: "npm:19.1.0"
react-native: "npm:^0.81.5"
- react-native-callkeep: "npm:^4.3.16"
+ react-native-callingx: "workspace:^"
react-native-gesture-handler: "npm:^2.28.0"
react-native-reanimated: "npm:~4.1.2"
react-native-safe-area-context: "npm:~5.6.1"
@@ -7714,7 +8883,7 @@ __metadata:
react: "npm:19.1.0"
react-native: "npm:^0.81.5"
react-native-builder-bob: "npm:~0.23"
- react-native-callkeep: "npm:^4.3.16"
+ react-native-callingx: "workspace:^"
react-native-gesture-handler: "npm:^2.28.0"
react-native-reanimated: "npm:~4.1.2"
react-native-svg: "npm:^15.14.0"
@@ -7740,7 +8909,7 @@ __metadata:
expo-notifications: "*"
react: ">=17.0.0"
react-native: ">=0.73.0"
- react-native-callkeep: ">=4.3.11"
+ react-native-callingx: "workspace:^"
react-native-gesture-handler: ">=2.8.0"
react-native-reanimated: ">=2.7.0"
react-native-svg: ">=13.6.0"
@@ -7764,7 +8933,7 @@ __metadata:
optional: true
expo-notifications:
optional: true
- react-native-callkeep:
+ react-native-callingx:
optional: true
react-native-gesture-handler:
optional: true
@@ -8013,6 +9182,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/conventional-commits-parser@npm:^5.0.0":
+ version: 5.0.2
+ resolution: "@types/conventional-commits-parser@npm:5.0.2"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 10/c6f9a47f66dc4f8d0de89ba44f47a1574db010b012c082c43ff1a86856053424e84dd53f59f88ab7cd64b9b20f7ee8957553aba2408768a128a9feb8d0ecfd60
+ languageName: node
+ linkType: hard
+
"@types/css-font-loading-module@npm:0.0.7":
version: 0.0.7
resolution: "@types/css-font-loading-module@npm:0.0.7"
@@ -8153,7 +9331,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/json-schema@npm:^7.0.15":
+"@types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7
@@ -8254,7 +9432,16 @@ __metadata:
languageName: node
linkType: hard
-"@types/normalize-package-data@npm:^2.4.1":
+"@types/node@npm:^22.0.0":
+ version: 22.19.1
+ resolution: "@types/node@npm:22.19.1"
+ dependencies:
+ undici-types: "npm:~6.21.0"
+ checksum: 10/40d5368faa6d9be6c27ebca2362734bc9e035a742e0b5cafee40ba3b355d7cfcaedbc93618c76465451e53f1af0c811b4b85ee9b85e2e942f34a4c5310fa047b
+ languageName: node
+ linkType: hard
+
+"@types/normalize-package-data@npm:^2.4.1, @types/normalize-package-data@npm:^2.4.4":
version: 2.4.4
resolution: "@types/normalize-package-data@npm:2.4.4"
checksum: 10/65dff72b543997b7be8b0265eca7ace0e34b75c3e5fee31de11179d08fa7124a7a5587265d53d0409532ecb7f7fba662c2012807963e1f9b059653ec2c83ee05
@@ -8268,6 +9455,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/parse-path@npm:^7.0.0":
+ version: 7.0.3
+ resolution: "@types/parse-path@npm:7.0.3"
+ checksum: 10/21a12c228d38f5a75659dfd7cb127dc2001ed3f6acbd1b2e0575d1348c735594c0bab06a97fe849c151438384829f20ea5971cb045f7ecd37d53c76a9fcb9de3
+ languageName: node
+ linkType: hard
+
"@types/pg-pool@npm:2.0.6":
version: 2.0.6
resolution: "@types/pg-pool@npm:2.0.6"
@@ -8331,6 +9525,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/react@npm:^19.1.0":
+ version: 19.2.7
+ resolution: "@types/react@npm:19.2.7"
+ dependencies:
+ csstype: "npm:^3.2.2"
+ checksum: 10/dc0b756eee2c9782d282ae47eaa8d537b2a569eb889a6808c4b172d70fb690b2b1d8fe6239db451aa1c90d2a947cc21c9b537ce177ba9e6121468e403e4079c5
+ languageName: node
+ linkType: hard
+
"@types/sdp-transform@npm:^2.15.0":
version: 2.15.0
resolution: "@types/sdp-transform@npm:2.15.0"
@@ -8338,6 +9541,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/semver@npm:^7.3.12":
+ version: 7.7.1
+ resolution: "@types/semver@npm:7.7.1"
+ checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068
+ languageName: node
+ linkType: hard
+
"@types/stack-utils@npm:^2.0.0":
version: 2.0.1
resolution: "@types/stack-utils@npm:2.0.1"
@@ -8435,6 +9645,29 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/eslint-plugin@npm:^7.1.1":
+ version: 7.18.0
+ resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0"
+ dependencies:
+ "@eslint-community/regexpp": "npm:^4.10.0"
+ "@typescript-eslint/scope-manager": "npm:7.18.0"
+ "@typescript-eslint/type-utils": "npm:7.18.0"
+ "@typescript-eslint/utils": "npm:7.18.0"
+ "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ graphemer: "npm:^1.4.0"
+ ignore: "npm:^5.3.1"
+ natural-compare: "npm:^1.4.0"
+ ts-api-utils: "npm:^1.3.0"
+ peerDependencies:
+ "@typescript-eslint/parser": ^7.0.0
+ eslint: ^8.56.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10/6ee4c61f145dc05f0a567b8ac01b5399ef9c75f58bc6e9a3ffca8927b15e2be2d4c3fd32a2c1a7041cc0848fdeadac30d9cb0d3bcd3835d301847a88ffd19c4d
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/parser@npm:8.46.0, @typescript-eslint/parser@npm:^8.29.1":
version: 8.46.0
resolution: "@typescript-eslint/parser@npm:8.46.0"
@@ -8451,6 +9684,24 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/parser@npm:^7.1.1":
+ version: 7.18.0
+ resolution: "@typescript-eslint/parser@npm:7.18.0"
+ dependencies:
+ "@typescript-eslint/scope-manager": "npm:7.18.0"
+ "@typescript-eslint/types": "npm:7.18.0"
+ "@typescript-eslint/typescript-estree": "npm:7.18.0"
+ "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ debug: "npm:^4.3.4"
+ peerDependencies:
+ eslint: ^8.56.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10/36b00e192a96180220ba100fcce3c777fc3e61a6edbdead4e6e75a744d9f0cbe3fabb5f1c94a31cce6b28a4e4d5de148098eec01296026c3c8e16f7f0067cb1e
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/project-service@npm:8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/project-service@npm:8.46.0"
@@ -8464,6 +9715,26 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/scope-manager@npm:5.62.0":
+ version: 5.62.0
+ resolution: "@typescript-eslint/scope-manager@npm:5.62.0"
+ dependencies:
+ "@typescript-eslint/types": "npm:5.62.0"
+ "@typescript-eslint/visitor-keys": "npm:5.62.0"
+ checksum: 10/e827770baa202223bc0387e2fd24f630690809e460435b7dc9af336c77322290a770d62bd5284260fa881c86074d6a9fd6c97b07382520b115f6786b8ed499da
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/scope-manager@npm:7.18.0":
+ version: 7.18.0
+ resolution: "@typescript-eslint/scope-manager@npm:7.18.0"
+ dependencies:
+ "@typescript-eslint/types": "npm:7.18.0"
+ "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ checksum: 10/9eb2ae5d69d9f723e706c16b2b97744fc016996a5473bed596035ac4d12429b3d24e7340a8235d704efa57f8f52e1b3b37925ff7c2e3384859d28b23a99b8bcc
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/scope-manager@npm:8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/scope-manager@npm:8.46.0"
@@ -8483,6 +9754,23 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/type-utils@npm:7.18.0":
+ version: 7.18.0
+ resolution: "@typescript-eslint/type-utils@npm:7.18.0"
+ dependencies:
+ "@typescript-eslint/typescript-estree": "npm:7.18.0"
+ "@typescript-eslint/utils": "npm:7.18.0"
+ debug: "npm:^4.3.4"
+ ts-api-utils: "npm:^1.3.0"
+ peerDependencies:
+ eslint: ^8.56.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10/bcc7958a4ecdddad8c92e17265175773e7dddf416a654c1a391e69cb16e43960b39d37b6ffa349941bf3635e050f0ca7cd8f56ec9dd774168f2bbe7afedc9676
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/type-utils@npm:8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/type-utils@npm:8.46.0"
@@ -8499,6 +9787,20 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/types@npm:5.62.0":
+ version: 5.62.0
+ resolution: "@typescript-eslint/types@npm:5.62.0"
+ checksum: 10/24e8443177be84823242d6729d56af2c4b47bfc664dd411a1d730506abf2150d6c31bdefbbc6d97c8f91043e3a50e0c698239dcb145b79bb6b0c34469aaf6c45
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/types@npm:7.18.0":
+ version: 7.18.0
+ resolution: "@typescript-eslint/types@npm:7.18.0"
+ checksum: 10/0e30c73a3cc3c67dd06360a5a12fd12cee831e4092750eec3d6c031bdc4feafcb0ab1d882910a73e66b451a4f6e1dd015e9e2c4d45bf6bf716a474e5d123ddf0
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/types@npm:8.46.0, @typescript-eslint/types@npm:^8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/types@npm:8.46.0"
@@ -8506,6 +9808,43 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/typescript-estree@npm:5.62.0":
+ version: 5.62.0
+ resolution: "@typescript-eslint/typescript-estree@npm:5.62.0"
+ dependencies:
+ "@typescript-eslint/types": "npm:5.62.0"
+ "@typescript-eslint/visitor-keys": "npm:5.62.0"
+ debug: "npm:^4.3.4"
+ globby: "npm:^11.1.0"
+ is-glob: "npm:^4.0.3"
+ semver: "npm:^7.3.7"
+ tsutils: "npm:^3.21.0"
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10/06c975eb5f44b43bd19fadc2e1023c50cf87038fe4c0dd989d4331c67b3ff509b17fa60a3251896668ab4d7322bdc56162a9926971218d2e1a1874d2bef9a52e
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/typescript-estree@npm:7.18.0":
+ version: 7.18.0
+ resolution: "@typescript-eslint/typescript-estree@npm:7.18.0"
+ dependencies:
+ "@typescript-eslint/types": "npm:7.18.0"
+ "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ debug: "npm:^4.3.4"
+ globby: "npm:^11.1.0"
+ is-glob: "npm:^4.0.3"
+ minimatch: "npm:^9.0.4"
+ semver: "npm:^7.6.0"
+ ts-api-utils: "npm:^1.3.0"
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10/b01e66235a91aa4439d02081d4a5f8b4a7cf9cb24f26b334812f657e3c603493e5f41e5c1e89cf4efae7d64509fa1f73affc16afc5e15cb7f83f724577c82036
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/typescript-estree@npm:8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/typescript-estree@npm:8.46.0"
@@ -8526,6 +9865,20 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/utils@npm:7.18.0":
+ version: 7.18.0
+ resolution: "@typescript-eslint/utils@npm:7.18.0"
+ dependencies:
+ "@eslint-community/eslint-utils": "npm:^4.4.0"
+ "@typescript-eslint/scope-manager": "npm:7.18.0"
+ "@typescript-eslint/types": "npm:7.18.0"
+ "@typescript-eslint/typescript-estree": "npm:7.18.0"
+ peerDependencies:
+ eslint: ^8.56.0
+ checksum: 10/f43fedb4f4d2e3836bdf137889449063a55c0ece74fdb283929cd376197b992313be8ef4df920c1c801b5c3076b92964c84c6c3b9b749d263b648d0011f5926e
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/utils@npm:8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/utils@npm:8.46.0"
@@ -8541,6 +9894,44 @@ __metadata:
languageName: node
linkType: hard
+"@typescript-eslint/utils@npm:^5.10.0":
+ version: 5.62.0
+ resolution: "@typescript-eslint/utils@npm:5.62.0"
+ dependencies:
+ "@eslint-community/eslint-utils": "npm:^4.2.0"
+ "@types/json-schema": "npm:^7.0.9"
+ "@types/semver": "npm:^7.3.12"
+ "@typescript-eslint/scope-manager": "npm:5.62.0"
+ "@typescript-eslint/types": "npm:5.62.0"
+ "@typescript-eslint/typescript-estree": "npm:5.62.0"
+ eslint-scope: "npm:^5.1.1"
+ semver: "npm:^7.3.7"
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ checksum: 10/15ef13e43998a082b15f85db979f8d3ceb1f9ce4467b8016c267b1738d5e7cdb12aa90faf4b4e6dd6486c236cf9d33c463200465cf25ff997dbc0f12358550a1
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/visitor-keys@npm:5.62.0":
+ version: 5.62.0
+ resolution: "@typescript-eslint/visitor-keys@npm:5.62.0"
+ dependencies:
+ "@typescript-eslint/types": "npm:5.62.0"
+ eslint-visitor-keys: "npm:^3.3.0"
+ checksum: 10/dc613ab7569df9bbe0b2ca677635eb91839dfb2ca2c6fa47870a5da4f160db0b436f7ec0764362e756d4164e9445d49d5eb1ff0b87f4c058946ae9d8c92eb388
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/visitor-keys@npm:7.18.0":
+ version: 7.18.0
+ resolution: "@typescript-eslint/visitor-keys@npm:7.18.0"
+ dependencies:
+ "@typescript-eslint/types": "npm:7.18.0"
+ eslint-visitor-keys: "npm:^3.4.3"
+ checksum: 10/b7cfe6fdeae86c507357ac6b2357813c64fb2fbf1aaf844393ba82f73a16e2599b41981b34200d9fc7765d70bc3a8181d76b503051e53f04bcb7c9afef637eab
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/visitor-keys@npm:8.46.0":
version: 8.46.0
resolution: "@typescript-eslint/visitor-keys@npm:8.46.0"
@@ -9133,6 +10524,26 @@ __metadata:
languageName: node
linkType: hard
+"arkregex@npm:0.0.3":
+ version: 0.0.3
+ resolution: "arkregex@npm:0.0.3"
+ dependencies:
+ "@ark/util": "npm:0.55.0"
+ checksum: 10/41969316fa1b134a2b112943bb8d3f236140435cb3bf612add7b6ec982469e0eb0dbc113216e492f71a0c9b8c237c80a22cb82f7226cf9549b8e9112396a4312
+ languageName: node
+ linkType: hard
+
+"arktype@npm:^2.1.15":
+ version: 2.1.27
+ resolution: "arktype@npm:2.1.27"
+ dependencies:
+ "@ark/schema": "npm:0.55.0"
+ "@ark/util": "npm:0.55.0"
+ arkregex: "npm:0.0.3"
+ checksum: 10/89b9c8b8b8441105ab441a40a989e1c84eb930dc2f1e4f1c8304dc84625e51de0da19178e7f425267cbae46007794a38f895e15c0807aa78fe6c3b748d707952
+ languageName: node
+ linkType: hard
+
"array-buffer-byte-length@npm:^1.0.1, array-buffer-byte-length@npm:^1.0.2":
version: 1.0.2
resolution: "array-buffer-byte-length@npm:1.0.2"
@@ -9322,6 +10733,15 @@ __metadata:
languageName: node
linkType: hard
+"async-retry@npm:1.3.3":
+ version: 1.3.3
+ resolution: "async-retry@npm:1.3.3"
+ dependencies:
+ retry: "npm:0.13.1"
+ checksum: 10/38a7152ff7265a9321ea214b9c69e8224ab1febbdec98efbbde6e562f17ff68405569b796b1c5271f354aef8783665d29953f051f68c1fc45306e61aec82fdc4
+ languageName: node
+ linkType: hard
+
"async@npm:^3.2.3":
version: 3.2.6
resolution: "async@npm:3.2.6"
@@ -9542,6 +10962,15 @@ __metadata:
languageName: node
linkType: hard
+"babel-plugin-syntax-hermes-parser@npm:^0.28.0":
+ version: 0.28.1
+ resolution: "babel-plugin-syntax-hermes-parser@npm:0.28.1"
+ dependencies:
+ hermes-parser: "npm:0.28.1"
+ checksum: 10/2cbc921e663463480ead9ccc8bb229a5196032367ba2b5ccb18a44faa3afa84b4dc493297749983b9a837a3d76b0b123664aecc06f9122618c3246f03e076a9d
+ languageName: node
+ linkType: hard
+
"babel-plugin-transform-flow-enums@npm:^0.0.2":
version: 0.0.2
resolution: "babel-plugin-transform-flow-enums@npm:0.0.2"
@@ -9682,6 +11111,13 @@ __metadata:
languageName: node
linkType: hard
+"before-after-hook@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "before-after-hook@npm:4.0.0"
+ checksum: 10/9fd52bc0c3cca0fb115e04dacbeeaacff38fa23e1af725d62392254c31ef433b15da60efcba61552e44d64e26f25ea259f72dba005115924389e88d2fd56e19f
+ languageName: node
+ linkType: hard
+
"better-opn@npm:~3.0.2":
version: 3.0.2
resolution: "better-opn@npm:3.0.2"
@@ -9855,6 +11291,15 @@ __metadata:
languageName: node
linkType: hard
+"bundle-name@npm:^4.1.0":
+ version: 4.1.0
+ resolution: "bundle-name@npm:4.1.0"
+ dependencies:
+ run-applescript: "npm:^7.0.0"
+ checksum: 10/1d966c8d2dbf4d9d394e53b724ac756c2414c45c01340b37743621f59cc565a435024b394ddcb62b9b335d1c9a31f4640eb648c3fec7f97ee74dc0694c9beb6c
+ languageName: node
+ linkType: hard
+
"bytes@npm:3.1.2":
version: 3.1.2
resolution: "bytes@npm:3.1.2"
@@ -9862,6 +11307,31 @@ __metadata:
languageName: node
linkType: hard
+"c12@npm:3.3.1":
+ version: 3.3.1
+ resolution: "c12@npm:3.3.1"
+ dependencies:
+ chokidar: "npm:^4.0.3"
+ confbox: "npm:^0.2.2"
+ defu: "npm:^6.1.4"
+ dotenv: "npm:^17.2.3"
+ exsolve: "npm:^1.0.7"
+ giget: "npm:^2.0.0"
+ jiti: "npm:^2.6.1"
+ ohash: "npm:^2.0.11"
+ pathe: "npm:^2.0.3"
+ perfect-debounce: "npm:^2.0.0"
+ pkg-types: "npm:^2.3.0"
+ rc9: "npm:^2.1.2"
+ peerDependencies:
+ magicast: ^0.3.5
+ peerDependenciesMeta:
+ magicast:
+ optional: true
+ checksum: 10/e736fc498e73cba8d555ea984544127026ff45fe86f5a2dbc7ff8cc971d2e0ecfa213ef7bd0a7b2d2450dfd7798febd98c9fb189dbb6f16f7c78c6ce3a5de040
+ languageName: node
+ linkType: hard
+
"cac@npm:^6.7.14":
version: 6.7.14
resolution: "cac@npm:6.7.14"
@@ -10038,6 +11508,13 @@ __metadata:
languageName: node
linkType: hard
+"chalk@npm:^5.3.0, chalk@npm:^5.6.2":
+ version: 5.6.2
+ resolution: "chalk@npm:5.6.2"
+ checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0
+ languageName: node
+ linkType: hard
+
"char-regex@npm:^1.0.2":
version: 1.0.2
resolution: "char-regex@npm:1.0.2"
@@ -10094,6 +11571,13 @@ __metadata:
languageName: node
linkType: hard
+"chardet@npm:^2.1.1":
+ version: 2.1.1
+ resolution: "chardet@npm:2.1.1"
+ checksum: 10/d56913b65e45c5c86f331988e2ef6264c131bfeadaae098ee719bf6610546c77740e37221ffec802dde56b5e4466613a4c754786f4da6b5f6c5477243454d324
+ languageName: node
+ linkType: hard
+
"chart.js@npm:^4.4.4":
version: 4.4.4
resolution: "chart.js@npm:4.4.4"
@@ -10129,7 +11613,7 @@ __metadata:
languageName: node
linkType: hard
-"chokidar@npm:^4.0.0":
+"chokidar@npm:^4.0.0, chokidar@npm:^4.0.3":
version: 4.0.3
resolution: "chokidar@npm:4.0.3"
dependencies:
@@ -10194,6 +11678,22 @@ __metadata:
languageName: node
linkType: hard
+"ci-info@npm:^4.3.0":
+ version: 4.3.1
+ resolution: "ci-info@npm:4.3.1"
+ checksum: 10/9dc952bef67e665ccde2e7a552d42d5d095529d21829ece060a00925ede2dfa136160c70ef2471ea6ed6c9b133218b47c007f56955c0f1734a2e57f240aa7445
+ languageName: node
+ linkType: hard
+
+"citty@npm:^0.1.6":
+ version: 0.1.6
+ resolution: "citty@npm:0.1.6"
+ dependencies:
+ consola: "npm:^3.2.3"
+ checksum: 10/3208947e73abb699a12578ee2bfee254bf8dd1ce0d5698e8a298411cabf16bd3620d63433aef5bd88cdb2b9da71aef18adefa3b4ffd18273bb62dd1d28c344f5
+ languageName: node
+ linkType: hard
+
"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.2.2":
version: 1.3.1
resolution: "cjs-module-lexer@npm:1.3.1"
@@ -10249,6 +11749,13 @@ __metadata:
languageName: node
linkType: hard
+"cli-spinners@npm:^3.2.0":
+ version: 3.3.0
+ resolution: "cli-spinners@npm:3.3.0"
+ checksum: 10/d95f69f4a6a4efab2104ca5d4723c9f6fae9a4006df7fdcc1f79ea6539324e274b85bf6f5931146d84296b0f71814f4c1ff1acc158f2e1107c0c9797c1291bcc
+ languageName: node
+ linkType: hard
+
"cli-truncate@npm:^5.0.0":
version: 5.1.0
resolution: "cli-truncate@npm:5.1.0"
@@ -10266,6 +11773,13 @@ __metadata:
languageName: node
linkType: hard
+"cli-width@npm:^4.1.0":
+ version: 4.1.0
+ resolution: "cli-width@npm:4.1.0"
+ checksum: 10/b58876fbf0310a8a35c79b72ecfcf579b354e18ad04e6b20588724ea2b522799a758507a37dfe132fafaf93a9922cafd9514d9e1598e6b2cd46694853aed099f
+ languageName: node
+ linkType: hard
+
"client-only@npm:0.0.1, client-only@npm:^0.0.1":
version: 0.0.1
resolution: "client-only@npm:0.0.1"
@@ -10488,6 +12002,18 @@ __metadata:
languageName: node
linkType: hard
+"commitlint@npm:^19.8.1":
+ version: 19.8.1
+ resolution: "commitlint@npm:19.8.1"
+ dependencies:
+ "@commitlint/cli": "npm:^19.8.1"
+ "@commitlint/types": "npm:^19.8.1"
+ bin:
+ commitlint: cli.js
+ checksum: 10/23e9a34b074361ec66c89573b1eba3ab65e7fe8044e22c3f044db87071817d8fe32e9e63313703c65385f5db1ab8e204eb2b3fa5e5a9481bc2fdef56eab478c1
+ languageName: node
+ linkType: hard
+
"commondir@npm:^1.0.1":
version: 1.0.1
resolution: "commondir@npm:1.0.1"
@@ -10543,6 +12069,18 @@ __metadata:
languageName: node
linkType: hard
+"concat-stream@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "concat-stream@npm:2.0.0"
+ dependencies:
+ buffer-from: "npm:^1.0.0"
+ inherits: "npm:^2.0.3"
+ readable-stream: "npm:^3.0.2"
+ typedarray: "npm:^0.0.6"
+ checksum: 10/250e576d0617e7c58e1c4b2dd6fe69560f316d2c962a409f9f3aac794018499ddb31948b1e4296f217008e124cd5d526432097745157fe504b5d9f3dc469eadb
+ languageName: node
+ linkType: hard
+
"concurrently@npm:9.2.1":
version: 9.2.1
resolution: "concurrently@npm:9.2.1"
@@ -10560,6 +12098,13 @@ __metadata:
languageName: node
linkType: hard
+"confbox@npm:^0.2.2":
+ version: 0.2.2
+ resolution: "confbox@npm:0.2.2"
+ checksum: 10/988c7216f9b5aee5d8a8f32153a9164e1b58d92d8335c5daa323fd3fdee91f742ffc25f6c28b059474b6319204085eca985ab14c5a246988dc7ef1fe29414108
+ languageName: node
+ linkType: hard
+
"connect@npm:^3.6.5, connect@npm:^3.7.0":
version: 3.7.0
resolution: "connect@npm:3.7.0"
@@ -10579,7 +12124,7 @@ __metadata:
languageName: node
linkType: hard
-"consola@npm:^3.2.3":
+"consola@npm:^3.2.3, consola@npm:^3.4.0, consola@npm:^3.4.2":
version: 3.4.2
resolution: "consola@npm:3.4.2"
checksum: 10/32192c9f50d7cac27c5d7c4ecd3ff3679aea863e6bf5bd6a9cc2b05d1cd78addf5dae71df08c54330c142be8e7fbd46f051030129b57c6aacdd771efe409c4b2
@@ -10618,6 +12163,15 @@ __metadata:
languageName: node
linkType: hard
+"conventional-changelog-angular@npm:^8.1.0":
+ version: 8.1.0
+ resolution: "conventional-changelog-angular@npm:8.1.0"
+ dependencies:
+ compare-func: "npm:^2.0.0"
+ checksum: 10/2211efa2bebbb00c3976d7b860979d3c04c2bcbb661cfc0c61445986dd3efa391f6e56636482cda83dfb3da3e2327a05c80f647a9147072627046bcbe0de7d39
+ languageName: node
+ linkType: hard
+
"conventional-changelog-atom@npm:^4.0.0":
version: 4.0.0
resolution: "conventional-changelog-atom@npm:4.0.0"
@@ -10641,6 +12195,15 @@ __metadata:
languageName: node
linkType: hard
+"conventional-changelog-conventionalcommits@npm:^9.1.0":
+ version: 9.1.0
+ resolution: "conventional-changelog-conventionalcommits@npm:9.1.0"
+ dependencies:
+ compare-func: "npm:^2.0.0"
+ checksum: 10/932522a9eb2f19f8b6efc05f1de0b8d4775842e2156c2c58358d25069bfc43ca1a6198fb07666d7abc83695a10591787c23b7ff2e1e2d73ac484cfb2f57f5f7f
+ languageName: node
+ linkType: hard
+
"conventional-changelog-core@npm:^7.0.0":
version: 7.0.0
resolution: "conventional-changelog-core@npm:7.0.0"
@@ -10703,6 +12266,13 @@ __metadata:
languageName: node
linkType: hard
+"conventional-changelog-preset-loader@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "conventional-changelog-preset-loader@npm:5.0.0"
+ checksum: 10/7630c2826b43f8f546f0575b46d3eb8c2ac2b5bcfae60b7d1186e9a87f07b7a689d9463afc125a40ab84a030574c9ce7965dd96e6506323e5a7d1ac2b9f2df19
+ languageName: node
+ linkType: hard
+
"conventional-changelog-writer@npm:^7.0.0":
version: 7.0.1
resolution: "conventional-changelog-writer@npm:7.0.1"
@@ -10719,6 +12289,20 @@ __metadata:
languageName: node
linkType: hard
+"conventional-changelog-writer@npm:^8.2.0":
+ version: 8.2.0
+ resolution: "conventional-changelog-writer@npm:8.2.0"
+ dependencies:
+ conventional-commits-filter: "npm:^5.0.0"
+ handlebars: "npm:^4.7.7"
+ meow: "npm:^13.0.0"
+ semver: "npm:^7.5.2"
+ bin:
+ conventional-changelog-writer: dist/cli/index.js
+ checksum: 10/050387a37a295bf8d0f91733432ea1e3959478d5b7d71f19654b83943503f2a37f24d69cf7688d9bb371c537693da024bc4e7c72a7029df8d121a44035ff7949
+ languageName: node
+ linkType: hard
+
"conventional-changelog@npm:^5.1.0":
version: 5.1.0
resolution: "conventional-changelog@npm:5.1.0"
@@ -10738,6 +12322,24 @@ __metadata:
languageName: node
linkType: hard
+"conventional-changelog@npm:^7.1.1":
+ version: 7.1.1
+ resolution: "conventional-changelog@npm:7.1.1"
+ dependencies:
+ "@conventional-changelog/git-client": "npm:^2.5.1"
+ "@types/normalize-package-data": "npm:^2.4.4"
+ conventional-changelog-preset-loader: "npm:^5.0.0"
+ conventional-changelog-writer: "npm:^8.2.0"
+ conventional-commits-parser: "npm:^6.2.0"
+ fd-package-json: "npm:^2.0.0"
+ meow: "npm:^13.0.0"
+ normalize-package-data: "npm:^7.0.0"
+ bin:
+ conventional-changelog: dist/cli/index.js
+ checksum: 10/983ce0498fa9e6103c602342f93b3a9b13dd414be594cd1ec4f7715916253caca1f42a98df7646a8ee629108e0f9bb33b1e45c58f2e689918097063c783cb0d9
+ languageName: node
+ linkType: hard
+
"conventional-commits-filter@npm:^4.0.0":
version: 4.0.0
resolution: "conventional-commits-filter@npm:4.0.0"
@@ -10745,6 +12347,13 @@ __metadata:
languageName: node
linkType: hard
+"conventional-commits-filter@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "conventional-commits-filter@npm:5.0.0"
+ checksum: 10/2345546ea9e40412558d508311d7729b38f8d4c0fd554837c10721a432e8598ec1152320f6b601a9c11c023a31bccbb5a12067736b2227de8591f4de707e11a7
+ languageName: node
+ linkType: hard
+
"conventional-commits-parser@npm:^5.0.0":
version: 5.0.0
resolution: "conventional-commits-parser@npm:5.0.0"
@@ -10759,6 +12368,32 @@ __metadata:
languageName: node
linkType: hard
+"conventional-commits-parser@npm:^6.1.0, conventional-commits-parser@npm:^6.2.0":
+ version: 6.2.1
+ resolution: "conventional-commits-parser@npm:6.2.1"
+ dependencies:
+ meow: "npm:^13.0.0"
+ bin:
+ conventional-commits-parser: dist/cli/index.js
+ checksum: 10/342764ac7c8114e3030d9d86968eafa3023ed887bc66412f89891fb55f09179d151a02342142a4039ca3375a7e39553d29789e022afd08edddbd995a1d5d9c24
+ languageName: node
+ linkType: hard
+
+"conventional-recommended-bump@npm:^11.2.0":
+ version: 11.2.0
+ resolution: "conventional-recommended-bump@npm:11.2.0"
+ dependencies:
+ "@conventional-changelog/git-client": "npm:^2.5.1"
+ conventional-changelog-preset-loader: "npm:^5.0.0"
+ conventional-commits-filter: "npm:^5.0.0"
+ conventional-commits-parser: "npm:^6.1.0"
+ meow: "npm:^13.0.0"
+ bin:
+ conventional-recommended-bump: dist/cli/index.js
+ checksum: 10/b6330542675399d1053c9092c5ddcc4ab0904046b5f767478f9434ada2cb1e9adbd9555e6952e1ad5a3bae6775cf67a14062b0be3b5c61b93c22abc702b00175
+ languageName: node
+ linkType: hard
+
"conventional-recommended-bump@npm:^9.0.0":
version: 9.0.0
resolution: "conventional-recommended-bump@npm:9.0.0"
@@ -10812,6 +12447,19 @@ __metadata:
languageName: node
linkType: hard
+"cosmiconfig-typescript-loader@npm:^6.1.0":
+ version: 6.2.0
+ resolution: "cosmiconfig-typescript-loader@npm:6.2.0"
+ dependencies:
+ jiti: "npm:^2.6.1"
+ peerDependencies:
+ "@types/node": "*"
+ cosmiconfig: ">=9"
+ typescript: ">=5"
+ checksum: 10/f905077c7233e561810b030342e6b85a2a58ddcfdaaad7d7b0a52f6376581957826e3aa64238d80d1aaf4d24013342d7c780888cffb36ba445d728d6e12588f3
+ languageName: node
+ linkType: hard
+
"cosmiconfig@npm:^5.0.5":
version: 5.2.1
resolution: "cosmiconfig@npm:5.2.1"
@@ -10983,6 +12631,13 @@ __metadata:
languageName: node
linkType: hard
+"csstype@npm:^3.2.2":
+ version: 3.2.3
+ resolution: "csstype@npm:3.2.3"
+ checksum: 10/ad41baf7e2ffac65ab544d79107bf7cd1a4bb9bab9ac3302f59ab4ba655d5e30942a8ae46e10ba160c6f4ecea464cc95b975ca2fefbdeeacd6ac63f12f99fe1f
+ languageName: node
+ linkType: hard
+
"d@npm:1, d@npm:^1.0.1":
version: 1.0.1
resolution: "d@npm:1.0.1"
@@ -11177,6 +12832,23 @@ __metadata:
languageName: node
linkType: hard
+"default-browser-id@npm:^5.0.0":
+ version: 5.0.1
+ resolution: "default-browser-id@npm:5.0.1"
+ checksum: 10/52c637637bcd76bfe974462a2f1dd75cb04784c2852935575760f82e1fd338e5e80d3c45a9b01fdbb1e450553a830bb163b004d2eca223c5573989f82232a072
+ languageName: node
+ linkType: hard
+
+"default-browser@npm:^5.2.1":
+ version: 5.4.0
+ resolution: "default-browser@npm:5.4.0"
+ dependencies:
+ bundle-name: "npm:^4.1.0"
+ default-browser-id: "npm:^5.0.0"
+ checksum: 10/cac0222ca5c9a3387d25337228689652ab33679a6566995c7194a75af7e554e91ec9ac92a70bfaa8e8089eae9f466ae99267bb38601282aade89b200f50a765c
+ languageName: node
+ linkType: hard
+
"defaults@npm:^1.0.3":
version: 1.0.4
resolution: "defaults@npm:1.0.4"
@@ -11204,6 +12876,13 @@ __metadata:
languageName: node
linkType: hard
+"define-lazy-prop@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "define-lazy-prop@npm:3.0.0"
+ checksum: 10/f28421cf9ee86eecaf5f3b8fe875f13d7009c2625e97645bfff7a2a49aca678270b86c39f9c32939e5ca7ab96b551377ed4139558c795e076774287ad3af1aa4
+ languageName: node
+ linkType: hard
+
"define-properties@npm:^1.1.3, define-properties@npm:^1.2.1":
version: 1.2.1
resolution: "define-properties@npm:1.2.1"
@@ -11215,6 +12894,13 @@ __metadata:
languageName: node
linkType: hard
+"defu@npm:^6.1.4":
+ version: 6.1.4
+ resolution: "defu@npm:6.1.4"
+ checksum: 10/aeffdb47300f45b4fdef1c5bd3880ac18ea7a1fd5b8a8faf8df29350ff03bf16dd34f9800205cab513d476e4c0a3783aa0cff0a433aff0ac84a67ddc4c8a2d64
+ languageName: node
+ linkType: hard
+
"degenerator@npm:^5.0.0":
version: 5.0.1
resolution: "degenerator@npm:5.0.1"
@@ -11226,6 +12912,19 @@ __metadata:
languageName: node
linkType: hard
+"del-cli@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "del-cli@npm:6.0.0"
+ dependencies:
+ del: "npm:^8.0.0"
+ meow: "npm:^13.2.0"
+ bin:
+ del: cli.js
+ del-cli: cli.js
+ checksum: 10/5441e55c9181f364e84a1d211e53a03476a806e795f6b7d576673f164a9f76e0dc846413a47730f6224913974ba54dabb1884f854a9cf4d418084872bdaaa229
+ languageName: node
+ linkType: hard
+
"del@npm:^6.1.1":
version: 6.1.1
resolution: "del@npm:6.1.1"
@@ -11242,6 +12941,21 @@ __metadata:
languageName: node
linkType: hard
+"del@npm:^8.0.0":
+ version: 8.0.1
+ resolution: "del@npm:8.0.1"
+ dependencies:
+ globby: "npm:^14.0.2"
+ is-glob: "npm:^4.0.3"
+ is-path-cwd: "npm:^3.0.0"
+ is-path-inside: "npm:^4.0.0"
+ p-map: "npm:^7.0.2"
+ presentable-error: "npm:^0.0.1"
+ slash: "npm:^5.1.0"
+ checksum: 10/53ed4a379a68c90e7d6d3bcce09c49229e77de9a946d0a5fc25f45b16c950cb8665986b7d0d0423416c03bfd43e0f31e528c5a19c558fe47449be9d6fae7f846
+ languageName: node
+ linkType: hard
+
"delayed-stream@npm:~1.0.0":
version: 1.0.0
resolution: "delayed-stream@npm:1.0.0"
@@ -11277,6 +12991,13 @@ __metadata:
languageName: node
linkType: hard
+"destr@npm:^2.0.3":
+ version: 2.0.5
+ resolution: "destr@npm:2.0.5"
+ checksum: 10/0e4fba62a55a4188c7ab13eed5ebeeda037ead1ab21cf6be40ca39828b258475ad9eb1e7de50a5ea8041705d454a4d090caf9f92b89f03b04d2e229716f7da0a
+ languageName: node
+ linkType: hard
+
"destroy@npm:1.2.0":
version: 1.2.0
resolution: "destroy@npm:1.2.0"
@@ -11451,6 +13172,13 @@ __metadata:
languageName: node
linkType: hard
+"dotenv@npm:^17.2.3":
+ version: 17.2.3
+ resolution: "dotenv@npm:17.2.3"
+ checksum: 10/f8b78626ebfff6e44420f634773375c9651808b3e1a33df6d4cc19120968eea53e100f59f04ec35f2a20b2beb334b6aba4f24040b2f8ad61773f158ac042a636
+ languageName: node
+ linkType: hard
+
"dotenv@npm:~16.4.5":
version: 16.4.7
resolution: "dotenv@npm:16.4.7"
@@ -12024,6 +13752,28 @@ __metadata:
languageName: node
linkType: hard
+"eslint-config-prettier@npm:^10.1.8":
+ version: 10.1.8
+ resolution: "eslint-config-prettier@npm:10.1.8"
+ peerDependencies:
+ eslint: ">=7.0.0"
+ bin:
+ eslint-config-prettier: bin/cli.js
+ checksum: 10/03f8e6ea1a6a9b8f9eeaf7c8c52a96499ec4b275b9ded33331a6cc738ed1d56de734097dbd0091f136f0e84bc197388bd8ec22a52a4658105883f8c8b7d8921a
+ languageName: node
+ linkType: hard
+
+"eslint-config-prettier@npm:^8.5.0":
+ version: 8.10.2
+ resolution: "eslint-config-prettier@npm:8.10.2"
+ peerDependencies:
+ eslint: ">=7.0.0"
+ bin:
+ eslint-config-prettier: bin/cli.js
+ checksum: 10/9818f26eebf32c5698bcc68d9b05e985ccaa6862488a32305681f9f025248c4b9192e587969594b3e79a814f965f808f513f63921dbb14639501fa61d6e6560d
+ languageName: node
+ linkType: hard
+
"eslint-config-prettier@npm:^9.1.0":
version: 9.1.0
resolution: "eslint-config-prettier@npm:9.1.0"
@@ -12107,6 +13857,31 @@ __metadata:
languageName: node
linkType: hard
+"eslint-plugin-eslint-comments@npm:^3.2.0":
+ version: 3.2.0
+ resolution: "eslint-plugin-eslint-comments@npm:3.2.0"
+ dependencies:
+ escape-string-regexp: "npm:^1.0.5"
+ ignore: "npm:^5.0.5"
+ peerDependencies:
+ eslint: ">=4.19.1"
+ checksum: 10/4aa0d31a78ac7746002e37ca0cb436f3e5b481a97d28be07bad831e161a2ffcc4dedff44820edef9a1e80f6a0ab1ef44ed9a46e3a4c4a050350438451908972b
+ languageName: node
+ linkType: hard
+
+"eslint-plugin-ft-flow@npm:^2.0.1":
+ version: 2.0.3
+ resolution: "eslint-plugin-ft-flow@npm:2.0.3"
+ dependencies:
+ lodash: "npm:^4.17.21"
+ string-natural-compare: "npm:^3.0.1"
+ peerDependencies:
+ "@babel/eslint-parser": ^7.12.0
+ eslint: ^8.1.0
+ checksum: 10/ea03496d247b9de915f0c5cee3724d4cbec8c0ab22029e4c06301c524bd8a7cbc20598971bed792304c5b3a17c1a1004a1bf7c7f59b55d3887aa7581e00ad0e1
+ languageName: node
+ linkType: hard
+
"eslint-plugin-import@npm:^2.31.0, eslint-plugin-import@npm:^2.32.0":
version: 2.32.0
resolution: "eslint-plugin-import@npm:2.32.0"
@@ -12136,6 +13911,24 @@ __metadata:
languageName: node
linkType: hard
+"eslint-plugin-jest@npm:^27.9.0":
+ version: 27.9.0
+ resolution: "eslint-plugin-jest@npm:27.9.0"
+ dependencies:
+ "@typescript-eslint/utils": "npm:^5.10.0"
+ peerDependencies:
+ "@typescript-eslint/eslint-plugin": ^5.0.0 || ^6.0.0 || ^7.0.0
+ eslint: ^7.0.0 || ^8.0.0
+ jest: "*"
+ peerDependenciesMeta:
+ "@typescript-eslint/eslint-plugin":
+ optional: true
+ jest:
+ optional: true
+ checksum: 10/bca54347280c06c56516faea76042134dd74355c2de6c23361ba0e8736ecc01c62b144eea7eda7570ea4f4ee511c583bb8dab00d7153a1bd1740eb77b0038fd4
+ languageName: node
+ linkType: hard
+
"eslint-plugin-n@npm:^17.17.0":
version: 17.23.1
resolution: "eslint-plugin-n@npm:17.23.1"
@@ -12171,7 +13964,7 @@ __metadata:
languageName: node
linkType: hard
-"eslint-plugin-prettier@npm:^5.2.6":
+"eslint-plugin-prettier@npm:^5.2.6, eslint-plugin-prettier@npm:^5.5.4":
version: 5.5.4
resolution: "eslint-plugin-prettier@npm:5.5.4"
dependencies:
@@ -12215,7 +14008,25 @@ __metadata:
languageName: node
linkType: hard
-"eslint-plugin-react@npm:^7.37.5":
+"eslint-plugin-react-native-globals@npm:^0.1.1":
+ version: 0.1.2
+ resolution: "eslint-plugin-react-native-globals@npm:0.1.2"
+ checksum: 10/ab91e8ecbb51718fb0763f29226b1c2d402251ab2c4730a8bf85f38b805e32d4243da46d07ccdb12cb9dcce9e7514364a1706142cf970f58dcc9a820bcf4b732
+ languageName: node
+ linkType: hard
+
+"eslint-plugin-react-native@npm:^4.0.0":
+ version: 4.1.0
+ resolution: "eslint-plugin-react-native@npm:4.1.0"
+ dependencies:
+ eslint-plugin-react-native-globals: "npm:^0.1.1"
+ peerDependencies:
+ eslint: ^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8
+ checksum: 10/fb2d65a3faca9bf775a0fa430eb7e86b7c27d0b256916d4f79a94def9ad353c8a10605f1f0dc9a5fb10e446b003341d53af9d8cbca4dd7ba394350355efa30c6
+ languageName: node
+ linkType: hard
+
+"eslint-plugin-react@npm:^7.30.1, eslint-plugin-react@npm:^7.37.5":
version: 7.37.5
resolution: "eslint-plugin-react@npm:7.37.5"
dependencies:
@@ -12243,6 +14054,16 @@ __metadata:
languageName: node
linkType: hard
+"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1":
+ version: 5.1.1
+ resolution: "eslint-scope@npm:5.1.1"
+ dependencies:
+ esrecurse: "npm:^4.3.0"
+ estraverse: "npm:^4.1.1"
+ checksum: 10/c541ef384c92eb5c999b7d3443d80195fcafb3da335500946f6db76539b87d5826c8f2e1d23bf6afc3154ba8cd7c8e566f8dc00f1eea25fdf3afc8fb9c87b238
+ languageName: node
+ linkType: hard
+
"eslint-scope@npm:^8.4.0":
version: 8.4.0
resolution: "eslint-scope@npm:8.4.0"
@@ -12269,7 +14090,14 @@ __metadata:
languageName: node
linkType: hard
-"eslint-visitor-keys@npm:^3.4.3":
+"eslint-visitor-keys@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "eslint-visitor-keys@npm:2.1.0"
+ checksum: 10/db4547eef5039122d518fa307e938ceb8589da5f6e8f5222efaf14dd62f748ce82e2d2becd3ff9412a50350b726bda95dbea8515a471074547daefa58aee8735
+ languageName: node
+ linkType: hard
+
+"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.3":
version: 3.4.3
resolution: "eslint-visitor-keys@npm:3.4.3"
checksum: 10/3f357c554a9ea794b094a09bd4187e5eacd1bc0d0653c3adeb87962c548e6a1ab8f982b86963ae1337f5d976004146536dcee5d0e2806665b193fbfbf1a9231b
@@ -12283,6 +14111,55 @@ __metadata:
languageName: node
linkType: hard
+"eslint@npm:^9.35.0":
+ version: 9.39.1
+ resolution: "eslint@npm:9.39.1"
+ dependencies:
+ "@eslint-community/eslint-utils": "npm:^4.8.0"
+ "@eslint-community/regexpp": "npm:^4.12.1"
+ "@eslint/config-array": "npm:^0.21.1"
+ "@eslint/config-helpers": "npm:^0.4.2"
+ "@eslint/core": "npm:^0.17.0"
+ "@eslint/eslintrc": "npm:^3.3.1"
+ "@eslint/js": "npm:9.39.1"
+ "@eslint/plugin-kit": "npm:^0.4.1"
+ "@humanfs/node": "npm:^0.16.6"
+ "@humanwhocodes/module-importer": "npm:^1.0.1"
+ "@humanwhocodes/retry": "npm:^0.4.2"
+ "@types/estree": "npm:^1.0.6"
+ ajv: "npm:^6.12.4"
+ chalk: "npm:^4.0.0"
+ cross-spawn: "npm:^7.0.6"
+ debug: "npm:^4.3.2"
+ escape-string-regexp: "npm:^4.0.0"
+ eslint-scope: "npm:^8.4.0"
+ eslint-visitor-keys: "npm:^4.2.1"
+ espree: "npm:^10.4.0"
+ esquery: "npm:^1.5.0"
+ esutils: "npm:^2.0.2"
+ fast-deep-equal: "npm:^3.1.3"
+ file-entry-cache: "npm:^8.0.0"
+ find-up: "npm:^5.0.0"
+ glob-parent: "npm:^6.0.2"
+ ignore: "npm:^5.2.0"
+ imurmurhash: "npm:^0.1.4"
+ is-glob: "npm:^4.0.0"
+ json-stable-stringify-without-jsonify: "npm:^1.0.1"
+ lodash.merge: "npm:^4.6.2"
+ minimatch: "npm:^3.1.2"
+ natural-compare: "npm:^1.4.0"
+ optionator: "npm:^0.9.3"
+ peerDependencies:
+ jiti: "*"
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+ bin:
+ eslint: bin/eslint.js
+ checksum: 10/c85fefe4a81a1a476e62087366907af830b62a6565ac153f6d50a100a42a946aeb049c3af8f06c0e091105ba0fe97ac109f379f32755a67f66ecb7d4d1e4dca3
+ languageName: node
+ linkType: hard
+
"eslint@npm:^9.37.0":
version: 9.37.0
resolution: "eslint@npm:9.37.0"
@@ -12372,6 +14249,13 @@ __metadata:
languageName: node
linkType: hard
+"estraverse@npm:^4.1.1":
+ version: 4.3.0
+ resolution: "estraverse@npm:4.3.0"
+ checksum: 10/3f67ad02b6dbfaddd9ea459cf2b6ef4ecff9a6082a7af9d22e445b9abc082ad9ca47e1825557b293fcdae477f4714e561123e30bb6a5b2f184fb2bad4a9497eb
+ languageName: node
+ linkType: hard
+
"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0":
version: 5.3.0
resolution: "estraverse@npm:5.3.0"
@@ -12409,6 +14293,13 @@ __metadata:
languageName: node
linkType: hard
+"eta@npm:4.0.1":
+ version: 4.0.1
+ resolution: "eta@npm:4.0.1"
+ checksum: 10/390f69d1213d640026e51c993f6c35fa39cbb21c242e1328210329af959844b5b22a5284f9560b8e9be044272ed606dca1053a49656de1eebc5a1d0884e1f171
+ languageName: node
+ linkType: hard
+
"etag@npm:~1.8.1":
version: 1.8.1
resolution: "etag@npm:1.8.1"
@@ -12478,6 +14369,23 @@ __metadata:
languageName: node
linkType: hard
+"execa@npm:^8.0.1":
+ version: 8.0.1
+ resolution: "execa@npm:8.0.1"
+ dependencies:
+ cross-spawn: "npm:^7.0.3"
+ get-stream: "npm:^8.0.1"
+ human-signals: "npm:^5.0.0"
+ is-stream: "npm:^3.0.0"
+ merge-stream: "npm:^2.0.0"
+ npm-run-path: "npm:^5.1.0"
+ onetime: "npm:^6.0.0"
+ signal-exit: "npm:^4.1.0"
+ strip-final-newline: "npm:^3.0.0"
+ checksum: 10/d2ab5fe1e2bb92b9788864d0713f1fce9a07c4594e272c0c97bc18c90569897ab262e4ea58d27a694d288227a2e24f16f5e2575b44224ad9983b799dc7f1098d
+ languageName: node
+ linkType: hard
+
"exit@npm:^0.1.2":
version: 0.1.2
resolution: "exit@npm:0.1.2"
@@ -12954,6 +14862,13 @@ __metadata:
languageName: node
linkType: hard
+"exsolve@npm:^1.0.7":
+ version: 1.0.8
+ resolution: "exsolve@npm:1.0.8"
+ checksum: 10/e7e8eac048af9f6856628a46df15529ab37428bdb5f7bc5b7824614383223de1aff60ebe85f44d9c8d4ee218d98c71df1a3e2d336f7d022a4dccd97a0651ec5b
+ languageName: node
+ linkType: hard
+
"ext@npm:^1.1.2":
version: 1.7.0
resolution: "ext@npm:1.7.0"
@@ -12981,6 +14896,13 @@ __metadata:
languageName: node
linkType: hard
+"fast-content-type-parse@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "fast-content-type-parse@npm:3.0.0"
+ checksum: 10/8616a8aa6c9b4f8f4f3c90eaa4e7bfc2240cfa6f41f0eef5b5aa2b2c8b38bd9ad435f1488b6d817ffd725c54651e2777b882ae9dd59366e71e7896f1ec11d473
+ languageName: node
+ linkType: hard
+
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
version: 3.1.3
resolution: "fast-deep-equal@npm:3.1.3"
@@ -13008,6 +14930,19 @@ __metadata:
languageName: node
linkType: hard
+"fast-glob@npm:^3.3.3":
+ version: 3.3.3
+ resolution: "fast-glob@npm:3.3.3"
+ dependencies:
+ "@nodelib/fs.stat": "npm:^2.0.2"
+ "@nodelib/fs.walk": "npm:^1.2.3"
+ glob-parent: "npm:^5.1.2"
+ merge2: "npm:^1.3.0"
+ micromatch: "npm:^4.0.8"
+ checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad
+ languageName: node
+ linkType: hard
+
"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0":
version: 2.1.0
resolution: "fast-json-stable-stringify@npm:2.1.0"
@@ -13089,6 +15024,15 @@ __metadata:
languageName: node
linkType: hard
+"fd-package-json@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "fd-package-json@npm:2.0.0"
+ dependencies:
+ walk-up-path: "npm:^4.0.0"
+ checksum: 10/e595a1a23f8e208815cdcf26c92218240da00acce80468324408dc4a5cb6c26b6efb5076f0458a02f044562a1e60253731187a627d5416b4961468ddfc0ae426
+ languageName: node
+ linkType: hard
+
"fdir@npm:^6.2.0, fdir@npm:^6.5.0":
version: 6.5.0
resolution: "fdir@npm:6.5.0"
@@ -13242,6 +15186,17 @@ __metadata:
languageName: node
linkType: hard
+"find-up@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "find-up@npm:7.0.0"
+ dependencies:
+ locate-path: "npm:^7.2.0"
+ path-exists: "npm:^5.0.0"
+ unicorn-magic: "npm:^0.1.0"
+ checksum: 10/7e6b08fbc05a10677e25e74bb0a020054a86b31d1806c5e6a9e32e75472bbf177210bc16e5f97453be8bda7ae2e3d97669dbb2901f8c30b39ce53929cbea6746
+ languageName: node
+ linkType: hard
+
"firebase@npm:12.2.1":
version: 12.2.1
resolution: "firebase@npm:12.2.1"
@@ -13671,6 +15626,13 @@ __metadata:
languageName: node
linkType: hard
+"get-stream@npm:^8.0.1":
+ version: 8.0.1
+ resolution: "get-stream@npm:8.0.1"
+ checksum: 10/dde5511e2e65a48e9af80fea64aff11b4921b14b6e874c6f8294c50975095af08f41bfb0b680c887f28b566dd6ec2cb2f960f9d36a323359be324ce98b766e9e
+ languageName: node
+ linkType: hard
+
"get-symbol-description@npm:^1.1.0":
version: 1.1.0
resolution: "get-symbol-description@npm:1.1.0"
@@ -13709,6 +15671,22 @@ __metadata:
languageName: node
linkType: hard
+"giget@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "giget@npm:2.0.0"
+ dependencies:
+ citty: "npm:^0.1.6"
+ consola: "npm:^3.4.0"
+ defu: "npm:^6.1.4"
+ node-fetch-native: "npm:^1.6.6"
+ nypm: "npm:^0.6.0"
+ pathe: "npm:^2.0.3"
+ bin:
+ giget: dist/cli.mjs
+ checksum: 10/3ee0f4aa06bdaeda9d4d31791d6a1e4349f15e20ff1dbe60535c709d3acc03f29f36a648cd047851a332fc1a0e9997ab6c5036410cc1629c09ad45ee155ee6dd
+ languageName: node
+ linkType: hard
+
"git-raw-commits@npm:^4.0.0":
version: 4.0.0
resolution: "git-raw-commits@npm:4.0.0"
@@ -13734,6 +15712,25 @@ __metadata:
languageName: node
linkType: hard
+"git-up@npm:^8.1.0":
+ version: 8.1.1
+ resolution: "git-up@npm:8.1.1"
+ dependencies:
+ is-ssh: "npm:^1.4.0"
+ parse-url: "npm:^9.2.0"
+ checksum: 10/475bfb816ee6003c505f25f2d6859148eedf684b2381f59774a8b4baf279d603710b888ecd1c5f5619fd7a582b131c2c52f8d247d59c7cc10bb7f7edffc704f7
+ languageName: node
+ linkType: hard
+
+"git-url-parse@npm:16.1.0":
+ version: 16.1.0
+ resolution: "git-url-parse@npm:16.1.0"
+ dependencies:
+ git-up: "npm:^8.1.0"
+ checksum: 10/1522e86ce89bb854ac5eaab13e71f9a72e93c4eb9897559d9731e03b700a7e2d38d16a77dddede9f79c8dac6f50633e2e420702bb1677580e797312e9b55379d
+ languageName: node
+ linkType: hard
+
"gl-matrix@npm:^3.4.3":
version: 3.4.3
resolution: "gl-matrix@npm:3.4.3"
@@ -13841,6 +15838,15 @@ __metadata:
languageName: node
linkType: hard
+"global-directory@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "global-directory@npm:4.0.1"
+ dependencies:
+ ini: "npm:4.1.1"
+ checksum: 10/5b4df24438a4e5f21e43fbdd9e54f5e12bb48dce01a0a83b415d8052ce91be2d3a97e0c8f98a535e69649b2190036155e9f0f7d3c62f9318f31bdc3fd4f235f5
+ languageName: node
+ linkType: hard
+
"global-dirs@npm:^0.1.1":
version: 0.1.1
resolution: "global-dirs@npm:0.1.1"
@@ -13888,7 +15894,7 @@ __metadata:
languageName: node
linkType: hard
-"globby@npm:^11.0.1":
+"globby@npm:^11.0.1, globby@npm:^11.1.0":
version: 11.1.0
resolution: "globby@npm:11.1.0"
dependencies:
@@ -13902,6 +15908,20 @@ __metadata:
languageName: node
linkType: hard
+"globby@npm:^14.0.2":
+ version: 14.1.0
+ resolution: "globby@npm:14.1.0"
+ dependencies:
+ "@sindresorhus/merge-streams": "npm:^2.1.0"
+ fast-glob: "npm:^3.3.3"
+ ignore: "npm:^7.0.3"
+ path-type: "npm:^6.0.0"
+ slash: "npm:^5.1.0"
+ unicorn-magic: "npm:^0.3.0"
+ checksum: 10/e527ff54f0dddf60abfabd0d9e799768619d957feecd8b13ef60481f270bfdce0d28f6b09267c60f8064798fb3003b8ec991375f7fe0233fbce5304e1741368c
+ languageName: node
+ linkType: hard
+
"globrex@npm:^0.1.2":
version: 0.1.2
resolution: "globrex@npm:0.1.2"
@@ -14104,6 +16124,13 @@ __metadata:
languageName: node
linkType: hard
+"hermes-estree@npm:0.28.1":
+ version: 0.28.1
+ resolution: "hermes-estree@npm:0.28.1"
+ checksum: 10/3195a1aa7035d96b77839e6bfd6832b51830518aaf8dabfca11248b84d6fb6abd27e21c8caa84229954a76b4f8a1e346b65d421a4daecd3053bd2ea08fe6abc9
+ languageName: node
+ linkType: hard
+
"hermes-estree@npm:0.29.1":
version: 0.29.1
resolution: "hermes-estree@npm:0.29.1"
@@ -14127,6 +16154,15 @@ __metadata:
languageName: node
linkType: hard
+"hermes-parser@npm:0.28.1":
+ version: 0.28.1
+ resolution: "hermes-parser@npm:0.28.1"
+ dependencies:
+ hermes-estree: "npm:0.28.1"
+ checksum: 10/cb2aa4d386929825c3bd8184eeb4e3dcf34892c1f850624d09a80aee0674bc2eb135eccaeb7ac33675552130229ee6160025c4e4f351d6a61b503bd8bfdf63f5
+ languageName: node
+ linkType: hard
+
"hermes-parser@npm:0.29.1, hermes-parser@npm:^0.29.1":
version: 0.29.1
resolution: "hermes-parser@npm:0.29.1"
@@ -14179,6 +16215,15 @@ __metadata:
languageName: node
linkType: hard
+"hosted-git-info@npm:^8.0.0":
+ version: 8.1.0
+ resolution: "hosted-git-info@npm:8.1.0"
+ dependencies:
+ lru-cache: "npm:^10.0.1"
+ checksum: 10/872a1f3b5da6bff9d99410b96cf7ecb6415ef7d8c8842579cfb690144f40be4581cc4ea50d978829a5fc1ef0b1097151a722d14f905beaf3f09330e8ca40fa4c
+ languageName: node
+ linkType: hard
+
"hotkeys-js@npm:^3.13.15":
version: 3.13.15
resolution: "hotkeys-js@npm:3.13.15"
@@ -14291,6 +16336,13 @@ __metadata:
languageName: node
linkType: hard
+"human-signals@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "human-signals@npm:5.0.0"
+ checksum: 10/30f8870d831cdcd2d6ec0486a7d35d49384996742052cee792854273fa9dd9e7d5db06bb7985d4953e337e10714e994e0302e90dc6848069171b05ec836d65b0
+ languageName: node
+ linkType: hard
+
"humanize-ms@npm:^1.2.1":
version: 1.2.1
resolution: "humanize-ms@npm:1.2.1"
@@ -14371,14 +16423,14 @@ __metadata:
languageName: node
linkType: hard
-"ignore@npm:^5.0.4, ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.3.1, ignore@npm:^5.3.2":
+"ignore@npm:^5.0.4, ignore@npm:^5.0.5, ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.3.1, ignore@npm:^5.3.2":
version: 5.3.2
resolution: "ignore@npm:5.3.2"
checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98
languageName: node
linkType: hard
-"ignore@npm:^7.0.0":
+"ignore@npm:^7.0.0, ignore@npm:^7.0.3":
version: 7.0.5
resolution: "ignore@npm:7.0.5"
checksum: 10/f134b96a4de0af419196f52c529d5c6120c4456ff8a6b5a14ceaaa399f883e15d58d2ce651c9b69b9388491d4669dda47285d307e827de9304a53a1824801bc6
@@ -14454,6 +16506,13 @@ __metadata:
languageName: node
linkType: hard
+"import-meta-resolve@npm:^4.0.0":
+ version: 4.2.0
+ resolution: "import-meta-resolve@npm:4.2.0"
+ checksum: 10/3499ee8b7eddb79be77067b368bcdf39e6f144306dea4686d08071ae7e65a2e3bdca3f98f2a0f4babdcd4ba9d9e7d379ae7e27c4b9bf8b08c1e812a28c674bf3
+ languageName: node
+ linkType: hard
+
"imurmurhash@npm:^0.1.4":
version: 0.1.4
resolution: "imurmurhash@npm:0.1.4"
@@ -14499,6 +16558,13 @@ __metadata:
languageName: node
linkType: hard
+"ini@npm:4.1.1":
+ version: 4.1.1
+ resolution: "ini@npm:4.1.1"
+ checksum: 10/64c7102301742a7527bb17257d18451410eacf63b4b5648a20e108816c355c21c4e8a1761bbcbf3fe8c4ded3297f1b832b885d5e3e485d781e293ebfaf56fea6
+ languageName: node
+ linkType: hard
+
"ini@npm:^1.3.4, ini@npm:~1.3.0":
version: 1.3.8
resolution: "ini@npm:1.3.8"
@@ -14522,6 +16588,26 @@ __metadata:
languageName: node
linkType: hard
+"inquirer@npm:12.9.6":
+ version: 12.9.6
+ resolution: "inquirer@npm:12.9.6"
+ dependencies:
+ "@inquirer/ansi": "npm:^1.0.0"
+ "@inquirer/core": "npm:^10.2.2"
+ "@inquirer/prompts": "npm:^7.8.6"
+ "@inquirer/type": "npm:^3.0.8"
+ mute-stream: "npm:^2.0.0"
+ run-async: "npm:^4.0.5"
+ rxjs: "npm:^7.8.2"
+ peerDependencies:
+ "@types/node": ">=18"
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ checksum: 10/bcac231b3eba055aa16dbdb60ba6d7bfe66109be654bfb19f92095f703af07fc01528f716e86ec62f7bf7bd17b4e21ad4bb32b677cf42075dee04568afe9686b
+ languageName: node
+ linkType: hard
+
"inquirer@npm:8.2.6":
version: 8.2.6
resolution: "inquirer@npm:8.2.6"
@@ -14765,6 +16851,15 @@ __metadata:
languageName: node
linkType: hard
+"is-docker@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "is-docker@npm:3.0.0"
+ bin:
+ is-docker: cli.js
+ checksum: 10/b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90
+ languageName: node
+ linkType: hard
+
"is-extglob@npm:^2.1.1":
version: 2.1.1
resolution: "is-extglob@npm:2.1.1"
@@ -14859,6 +16954,17 @@ __metadata:
languageName: node
linkType: hard
+"is-inside-container@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "is-inside-container@npm:1.0.0"
+ dependencies:
+ is-docker: "npm:^3.0.0"
+ bin:
+ is-inside-container: cli.js
+ checksum: 10/c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03
+ languageName: node
+ linkType: hard
+
"is-interactive@npm:^1.0.0":
version: 1.0.0
resolution: "is-interactive@npm:1.0.0"
@@ -14866,6 +16972,13 @@ __metadata:
languageName: node
linkType: hard
+"is-interactive@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "is-interactive@npm:2.0.0"
+ checksum: 10/e8d52ad490bed7ae665032c7675ec07732bbfe25808b0efbc4d5a76b1a1f01c165f332775c63e25e9a03d319ebb6b24f571a9e902669fc1e40b0a60b5be6e26c
+ languageName: node
+ linkType: hard
+
"is-lambda@npm:^1.0.1":
version: 1.0.1
resolution: "is-lambda@npm:1.0.1"
@@ -14928,6 +17041,13 @@ __metadata:
languageName: node
linkType: hard
+"is-path-cwd@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "is-path-cwd@npm:3.0.0"
+ checksum: 10/bc34d13b6a03dfca4a3ab6a8a5ba78ae4b24f4f1db4b2b031d2760c60d0913bd16a4b980dcb4e590adfc906649d5f5132684079a3972bd219da49deebb9adea8
+ languageName: node
+ linkType: hard
+
"is-path-inside@npm:^3.0.2":
version: 3.0.3
resolution: "is-path-inside@npm:3.0.3"
@@ -14935,6 +17055,13 @@ __metadata:
languageName: node
linkType: hard
+"is-path-inside@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "is-path-inside@npm:4.0.0"
+ checksum: 10/8810fa11c58e6360b82c3e0d6cd7d9c7d0392d3ac9eb10f980b81f9839f40ac6d1d6d6f05d069db0d227759801228f0b072e1b6c343e4469b065ab5fe0b68fe5
+ languageName: node
+ linkType: hard
+
"is-plain-obj@npm:^2.1.0":
version: 2.1.0
resolution: "is-plain-obj@npm:2.1.0"
@@ -15002,6 +17129,15 @@ __metadata:
languageName: node
linkType: hard
+"is-ssh@npm:^1.4.0":
+ version: 1.4.1
+ resolution: "is-ssh@npm:1.4.1"
+ dependencies:
+ protocols: "npm:^2.0.1"
+ checksum: 10/f60910cd83fa94e9874655a672c3849312c12af83c0fe3dbff9945755fe838a73985d8f94e32ebf5626ba4148ee10eef51b7240b0218dbb6e9a43a06899b0529
+ languageName: node
+ linkType: hard
+
"is-stream@npm:^2.0.0":
version: 2.0.1
resolution: "is-stream@npm:2.0.1"
@@ -15009,6 +17145,13 @@ __metadata:
languageName: node
linkType: hard
+"is-stream@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "is-stream@npm:3.0.0"
+ checksum: 10/172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16
+ languageName: node
+ linkType: hard
+
"is-string@npm:^1.1.1":
version: 1.1.1
resolution: "is-string@npm:1.1.1"
@@ -15064,6 +17207,13 @@ __metadata:
languageName: node
linkType: hard
+"is-unicode-supported@npm:^2.0.0, is-unicode-supported@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "is-unicode-supported@npm:2.1.0"
+ checksum: 10/f254e3da6b0ab1a57a94f7273a7798dd35d1d45b227759f600d0fa9d5649f9c07fa8d3c8a6360b0e376adf916d151ec24fc9a50c5295c58bae7ca54a76a063f9
+ languageName: node
+ linkType: hard
+
"is-weakmap@npm:^2.0.2":
version: 2.0.2
resolution: "is-weakmap@npm:2.0.2"
@@ -15113,6 +17263,15 @@ __metadata:
languageName: node
linkType: hard
+"is-wsl@npm:^3.1.0":
+ version: 3.1.0
+ resolution: "is-wsl@npm:3.1.0"
+ dependencies:
+ is-inside-container: "npm:^1.0.0"
+ checksum: 10/f9734c81f2f9cf9877c5db8356bfe1ff61680f1f4c1011e91278a9c0564b395ae796addb4bf33956871041476ec82c3e5260ed57b22ac91794d4ae70a1d2f0a9
+ languageName: node
+ linkType: hard
+
"isarray@npm:^2.0.5":
version: 2.0.5
resolution: "isarray@npm:2.0.5"
@@ -15143,6 +17302,19 @@ __metadata:
languageName: node
linkType: hard
+"issue-parser@npm:7.0.1":
+ version: 7.0.1
+ resolution: "issue-parser@npm:7.0.1"
+ dependencies:
+ lodash.capitalize: "npm:^4.2.1"
+ lodash.escaperegexp: "npm:^4.1.2"
+ lodash.isplainobject: "npm:^4.0.6"
+ lodash.isstring: "npm:^4.0.1"
+ lodash.uniqby: "npm:^4.7.0"
+ checksum: 10/04d14d987567008a270f5ed165e9464e131faf9c1d373b13c53bc7a1fe78b4e3aa91fcf2a1be2bac73983624084260b72957926fa35a1df4d60afbb61b645c95
+ languageName: node
+ linkType: hard
+
"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0, istanbul-lib-coverage@npm:^3.2.2":
version: 3.2.2
resolution: "istanbul-lib-coverage@npm:3.2.2"
@@ -15841,6 +18013,15 @@ __metadata:
languageName: node
linkType: hard
+"jiti@npm:^2.6.1":
+ version: 2.6.1
+ resolution: "jiti@npm:2.6.1"
+ bin:
+ jiti: lib/jiti-cli.mjs
+ checksum: 10/8cd72c5fd03a0502564c3f46c49761090f6dadead21fa191b73535724f095ad86c2fa89ee6fe4bc3515337e8d406cc8fb2d37b73fa0c99a34584bac35cd4a4de
+ languageName: node
+ linkType: hard
+
"joi@npm:^17.2.1":
version: 17.9.1
resolution: "joi@npm:17.9.1"
@@ -16173,6 +18354,117 @@ __metadata:
languageName: node
linkType: hard
+"lefthook-darwin-arm64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-darwin-arm64@npm:2.0.4"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"lefthook-darwin-x64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-darwin-x64@npm:2.0.4"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"lefthook-freebsd-arm64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-freebsd-arm64@npm:2.0.4"
+ conditions: os=freebsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"lefthook-freebsd-x64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-freebsd-x64@npm:2.0.4"
+ conditions: os=freebsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"lefthook-linux-arm64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-linux-arm64@npm:2.0.4"
+ conditions: os=linux & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"lefthook-linux-x64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-linux-x64@npm:2.0.4"
+ conditions: os=linux & cpu=x64
+ languageName: node
+ linkType: hard
+
+"lefthook-openbsd-arm64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-openbsd-arm64@npm:2.0.4"
+ conditions: os=openbsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"lefthook-openbsd-x64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-openbsd-x64@npm:2.0.4"
+ conditions: os=openbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
+"lefthook-windows-arm64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-windows-arm64@npm:2.0.4"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"lefthook-windows-x64@npm:2.0.4":
+ version: 2.0.4
+ resolution: "lefthook-windows-x64@npm:2.0.4"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
+"lefthook@npm:^2.0.3":
+ version: 2.0.4
+ resolution: "lefthook@npm:2.0.4"
+ dependencies:
+ lefthook-darwin-arm64: "npm:2.0.4"
+ lefthook-darwin-x64: "npm:2.0.4"
+ lefthook-freebsd-arm64: "npm:2.0.4"
+ lefthook-freebsd-x64: "npm:2.0.4"
+ lefthook-linux-arm64: "npm:2.0.4"
+ lefthook-linux-x64: "npm:2.0.4"
+ lefthook-openbsd-arm64: "npm:2.0.4"
+ lefthook-openbsd-x64: "npm:2.0.4"
+ lefthook-windows-arm64: "npm:2.0.4"
+ lefthook-windows-x64: "npm:2.0.4"
+ dependenciesMeta:
+ lefthook-darwin-arm64:
+ optional: true
+ lefthook-darwin-x64:
+ optional: true
+ lefthook-freebsd-arm64:
+ optional: true
+ lefthook-freebsd-x64:
+ optional: true
+ lefthook-linux-arm64:
+ optional: true
+ lefthook-linux-x64:
+ optional: true
+ lefthook-openbsd-arm64:
+ optional: true
+ lefthook-openbsd-x64:
+ optional: true
+ lefthook-windows-arm64:
+ optional: true
+ lefthook-windows-x64:
+ optional: true
+ bin:
+ lefthook: bin/index.js
+ checksum: 10/dd0eb5737c50a386dbe9a877613ee21f495d86458f96a7ffae6335425232efa400d205c57f205cdba66a454d370557de20dcbda72818bb0e9a45608062c1b38e
+ languageName: node
+ linkType: hard
+
"leven@npm:^3.1.0":
version: 3.1.0
resolution: "leven@npm:3.1.0"
@@ -16418,7 +18710,7 @@ __metadata:
languageName: node
linkType: hard
-"locate-path@npm:^7.1.0":
+"locate-path@npm:^7.1.0, locate-path@npm:^7.2.0":
version: 7.2.0
resolution: "locate-path@npm:7.2.0"
dependencies:
@@ -16441,6 +18733,13 @@ __metadata:
languageName: node
linkType: hard
+"lodash.capitalize@npm:^4.2.1":
+ version: 4.2.1
+ resolution: "lodash.capitalize@npm:4.2.1"
+ checksum: 10/54d61121bd040212954faee94703a999282987a104fab4ea6a85027d5fb2ce482a737478b76d292d07753da1c15911541adf0f6db840abf121c4cab85b92e962
+ languageName: node
+ linkType: hard
+
"lodash.debounce@npm:^4.0.8":
version: 4.0.8
resolution: "lodash.debounce@npm:4.0.8"
@@ -16462,6 +18761,13 @@ __metadata:
languageName: node
linkType: hard
+"lodash.escaperegexp@npm:^4.1.2":
+ version: 4.1.2
+ resolution: "lodash.escaperegexp@npm:4.1.2"
+ checksum: 10/6d99452b1cfd6073175a9b741a9b09ece159eac463f86f02ea3bee2e2092923fce812c8d2bf446309cc52d1d61bf9af51c8118b0d7421388e6cead7bd3798f0f
+ languageName: node
+ linkType: hard
+
"lodash.includes@npm:^4.3.0":
version: 4.3.0
resolution: "lodash.includes@npm:4.3.0"
@@ -16504,6 +18810,13 @@ __metadata:
languageName: node
linkType: hard
+"lodash.kebabcase@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "lodash.kebabcase@npm:4.1.1"
+ checksum: 10/d84ec5441ef8e5c718c50315f35b0a045a77c7e8ee3e54472c06dc31f6f3602e95551a16c0923d689198b51deb8902c4bbc54fc9b965b26c1f86e21df3a05f34
+ languageName: node
+ linkType: hard
+
"lodash.memoize@npm:4.x":
version: 4.1.2
resolution: "lodash.memoize@npm:4.1.2"
@@ -16511,7 +18824,7 @@ __metadata:
languageName: node
linkType: hard
-"lodash.merge@npm:^4.6.2":
+"lodash.merge@npm:4.6.2, lodash.merge@npm:^4.6.2":
version: 4.6.2
resolution: "lodash.merge@npm:4.6.2"
checksum: 10/d0ea2dd0097e6201be083865d50c3fb54fbfbdb247d9cc5950e086c991f448b7ab0cdab0d57eacccb43473d3f2acd21e134db39f22dac2d6c9ba6bf26978e3d6
@@ -16532,6 +18845,20 @@ __metadata:
languageName: node
linkType: hard
+"lodash.snakecase@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "lodash.snakecase@npm:4.1.1"
+ checksum: 10/82ed40935d840477ef8fee64f9f263f75989c6cde36b84aae817246d95826228e1b5a7f6093c51de324084f86433634c7af244cb89496633cacfe443071450d0
+ languageName: node
+ linkType: hard
+
+"lodash.startcase@npm:^4.4.0":
+ version: 4.4.0
+ resolution: "lodash.startcase@npm:4.4.0"
+ checksum: 10/3091048a54a2f92bcf2c6441d2bd9a706fb133d5f461ae7c310d6dca1530338a06c91e9e42a5b14b12e875ddae1814d448050dc02afe2cec09b3995d8e836837
+ languageName: node
+ linkType: hard
+
"lodash.throttle@npm:^4.1.1":
version: 4.1.1
resolution: "lodash.throttle@npm:4.1.1"
@@ -16539,6 +18866,13 @@ __metadata:
languageName: node
linkType: hard
+"lodash.uniq@npm:^4.5.0":
+ version: 4.5.0
+ resolution: "lodash.uniq@npm:4.5.0"
+ checksum: 10/86246ca64ac0755c612e5df6d93cfe92f9ecac2e5ff054b965efbbb1d9a647b6310969e78545006f70f52760554b03233ad0103324121ae31474c20d5f7a2812
+ languageName: node
+ linkType: hard
+
"lodash.uniqby@npm:^4.7.0":
version: 4.7.0
resolution: "lodash.uniqby@npm:4.7.0"
@@ -16546,7 +18880,14 @@ __metadata:
languageName: node
linkType: hard
-"lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21":
+"lodash.upperfirst@npm:^4.3.1":
+ version: 4.3.1
+ resolution: "lodash.upperfirst@npm:4.3.1"
+ checksum: 10/3e849d4eb4dbf26faee6435edda8e707b65a5dbd2f10f8def5a16a57bbbf38d3b7506950f0dd455e9c46ba73af35f1de75df4ef83952106949413d64eed59333
+ languageName: node
+ linkType: hard
+
+"lodash@npm:^4.15.0, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
checksum: 10/c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532
@@ -16572,6 +18913,16 @@ __metadata:
languageName: node
linkType: hard
+"log-symbols@npm:^7.0.1":
+ version: 7.0.1
+ resolution: "log-symbols@npm:7.0.1"
+ dependencies:
+ is-unicode-supported: "npm:^2.0.0"
+ yoctocolors: "npm:^2.1.1"
+ checksum: 10/0862313d84826b551582e39659b8586c56b65130c5f4f976420e2c23985228334f2a26fc4251ac22bf0a5b415d9430e86bf332557d934c10b036f9a549d63a09
+ languageName: node
+ linkType: hard
+
"log-update@npm:^6.1.0":
version: 6.1.0
resolution: "log-update@npm:6.1.0"
@@ -16669,6 +19020,13 @@ __metadata:
languageName: node
linkType: hard
+"macos-release@npm:^3.3.0":
+ version: 3.4.0
+ resolution: "macos-release@npm:3.4.0"
+ checksum: 10/f4c0cb8b3f93b05d73c502b4bbe2b811c44facfc9bd072c13a30ff2a8ba1cad5d9de517d10be8b31e2b917643245a81587a2eec8300e66a7364419d11402ab02
+ languageName: node
+ linkType: hard
+
"magic-string@npm:0.30.8":
version: 0.30.8
resolution: "magic-string@npm:0.30.8"
@@ -17053,6 +19411,13 @@ __metadata:
languageName: node
linkType: hard
+"meow@npm:^13.0.0, meow@npm:^13.2.0":
+ version: 13.2.0
+ resolution: "meow@npm:13.2.0"
+ checksum: 10/4eff5bc921fed0b8a471ad79069d741a0210036d717547d0c7f36fdaf84ef7a3036225f38b6a53830d84dc9cbf8b944b097fde62381b8b5b215119e735ce1063
+ languageName: node
+ linkType: hard
+
"merge-options@npm:^3.0.4":
version: 3.0.4
resolution: "merge-options@npm:3.0.4"
@@ -18104,13 +20469,22 @@ __metadata:
languageName: node
linkType: hard
-"mime-db@npm:>= 1.43.0 < 2":
+"mime-db@npm:>= 1.43.0 < 2, mime-db@npm:^1.54.0":
version: 1.54.0
resolution: "mime-db@npm:1.54.0"
checksum: 10/9e7834be3d66ae7f10eaa69215732c6d389692b194f876198dca79b2b90cbf96688d9d5d05ef7987b20f749b769b11c01766564264ea5f919c88b32a29011311
languageName: node
linkType: hard
+"mime-types@npm:3.0.1":
+ version: 3.0.1
+ resolution: "mime-types@npm:3.0.1"
+ dependencies:
+ mime-db: "npm:^1.54.0"
+ checksum: 10/fa1d3a928363723a8046c346d87bf85d35014dae4285ad70a3ff92bd35957992b3094f8417973cfe677330916c6ef30885109624f1fb3b1e61a78af509dba120
+ languageName: node
+ linkType: hard
+
"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
version: 2.1.35
resolution: "mime-types@npm:2.1.35"
@@ -18161,6 +20535,13 @@ __metadata:
languageName: node
linkType: hard
+"mimic-fn@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "mimic-fn@npm:4.0.0"
+ checksum: 10/995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56
+ languageName: node
+ linkType: hard
+
"mimic-function@npm:^5.0.0":
version: 5.0.1
resolution: "mimic-function@npm:5.0.1"
@@ -18229,7 +20610,7 @@ __metadata:
languageName: node
linkType: hard
-"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6":
+"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8":
version: 1.2.8
resolution: "minimist@npm:1.2.8"
checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f
@@ -18437,6 +20818,13 @@ __metadata:
languageName: node
linkType: hard
+"mute-stream@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "mute-stream@npm:2.0.0"
+ checksum: 10/d2e4fd2f5aa342b89b98134a8d899d8ef9b0a6d69274c4af9df46faa2d97aeb1f2ce83d867880d6de63643c52386579b99139801e24e7526c3b9b0a6d1e18d6c
+ languageName: node
+ linkType: hard
+
"mz@npm:^2.7.0":
version: 2.7.0
resolution: "mz@npm:2.7.0"
@@ -18515,6 +20903,15 @@ __metadata:
languageName: node
linkType: hard
+"new-github-release-url@npm:2.0.0":
+ version: 2.0.0
+ resolution: "new-github-release-url@npm:2.0.0"
+ dependencies:
+ type-fest: "npm:^2.5.1"
+ checksum: 10/3d4ae0f3b775623ceed8e558b6f9850e897aea981a9c937d3ad4e018669c829beccb2c4b5a6af996726ebf86c5b7638368dfc01f3ac2e395d1df29309bc0c5ca
+ languageName: node
+ linkType: hard
+
"next-auth@npm:^4.24.11":
version: 4.24.11
resolution: "next-auth@npm:4.24.11"
@@ -18632,6 +21029,13 @@ __metadata:
languageName: node
linkType: hard
+"node-fetch-native@npm:^1.6.6":
+ version: 1.6.7
+ resolution: "node-fetch-native@npm:1.6.7"
+ checksum: 10/b8a99e6adafbdbdd9373a6784c467ca5c7b95eeed4896ee2d604f0729962fda8d07cf7a85edd1e8bb3ee51e791dc55c30cbebeb46cbd1f086d74141b3769a680
+ languageName: node
+ linkType: hard
+
"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.7":
version: 2.6.13
resolution: "node-fetch@npm:2.6.13"
@@ -18723,6 +21127,17 @@ __metadata:
languageName: node
linkType: hard
+"normalize-package-data@npm:^7.0.0":
+ version: 7.0.1
+ resolution: "normalize-package-data@npm:7.0.1"
+ dependencies:
+ hosted-git-info: "npm:^8.0.0"
+ semver: "npm:^7.3.5"
+ validate-npm-package-license: "npm:^3.0.4"
+ checksum: 10/8150d7e663303fb5b06b616416b512812c5805a7a2ed34272448beb000bc8fdfdb0aeea0c997f875a326bc0b8fa263819f765902dc67dd0f5c6b4350ebc22821
+ languageName: node
+ linkType: hard
+
"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0":
version: 3.0.0
resolution: "normalize-path@npm:3.0.0"
@@ -18758,6 +21173,15 @@ __metadata:
languageName: node
linkType: hard
+"npm-run-path@npm:^5.1.0":
+ version: 5.3.0
+ resolution: "npm-run-path@npm:5.3.0"
+ dependencies:
+ path-key: "npm:^4.0.0"
+ checksum: 10/ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25
+ languageName: node
+ linkType: hard
+
"npmlog@npm:^6.0.0":
version: 6.0.2
resolution: "npmlog@npm:6.0.2"
@@ -18878,6 +21302,21 @@ __metadata:
languageName: node
linkType: hard
+"nypm@npm:^0.6.0":
+ version: 0.6.2
+ resolution: "nypm@npm:0.6.2"
+ dependencies:
+ citty: "npm:^0.1.6"
+ consola: "npm:^3.4.2"
+ pathe: "npm:^2.0.3"
+ pkg-types: "npm:^2.3.0"
+ tinyexec: "npm:^1.0.1"
+ bin:
+ nypm: dist/cli.mjs
+ checksum: 10/3bbf25b02b9eab5565a9a11c1f0946d0065cc6a9028e8f438ebf5256f3139cfac0763a3852984a7ae92c761ab1c2ce881272f9b1a863107e195e7f7cae05b598
+ languageName: node
+ linkType: hard
+
"oauth@npm:^0.9.15":
version: 0.9.15
resolution: "oauth@npm:0.9.15"
@@ -19018,6 +21457,13 @@ __metadata:
languageName: node
linkType: hard
+"ohash@npm:^2.0.11":
+ version: 2.0.11
+ resolution: "ohash@npm:2.0.11"
+ checksum: 10/6b0423f42cc95c3d643f390a88364aac824178b7788dccb4e8c64e2124463d0069e60d4d90bad88ed9823808368d051e088aa27058ca4722b1397a201ffbfa4b
+ languageName: node
+ linkType: hard
+
"oidc-token-hash@npm:^5.0.1":
version: 5.0.1
resolution: "oidc-token-hash@npm:5.0.1"
@@ -19077,6 +21523,15 @@ __metadata:
languageName: node
linkType: hard
+"onetime@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "onetime@npm:6.0.0"
+ dependencies:
+ mimic-fn: "npm:^4.0.0"
+ checksum: 10/0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788
+ languageName: node
+ linkType: hard
+
"onetime@npm:^7.0.0":
version: 7.0.0
resolution: "onetime@npm:7.0.0"
@@ -19086,6 +21541,18 @@ __metadata:
languageName: node
linkType: hard
+"open@npm:10.2.0":
+ version: 10.2.0
+ resolution: "open@npm:10.2.0"
+ dependencies:
+ default-browser: "npm:^5.2.1"
+ define-lazy-prop: "npm:^3.0.0"
+ is-inside-container: "npm:^1.0.0"
+ wsl-utils: "npm:^0.1.0"
+ checksum: 10/e6ad9474734eac3549dcc7d85e952394856ccaee48107c453bd6a725b82e3b8ed5f427658935df27efa76b411aeef62888edea8a9e347e8e7c82632ec966b30e
+ languageName: node
+ linkType: hard
+
"open@npm:^6.2.0":
version: 6.4.0
resolution: "open@npm:6.4.0"
@@ -19158,6 +21625,23 @@ __metadata:
languageName: node
linkType: hard
+"ora@npm:9.0.0":
+ version: 9.0.0
+ resolution: "ora@npm:9.0.0"
+ dependencies:
+ chalk: "npm:^5.6.2"
+ cli-cursor: "npm:^5.0.0"
+ cli-spinners: "npm:^3.2.0"
+ is-interactive: "npm:^2.0.0"
+ is-unicode-supported: "npm:^2.1.0"
+ log-symbols: "npm:^7.0.1"
+ stdin-discarder: "npm:^0.2.2"
+ string-width: "npm:^8.1.0"
+ strip-ansi: "npm:^7.1.2"
+ checksum: 10/b6074c9cec4a39c1b4f41c2ce2741982a99c53c86bd6f07a28fb6274857263af7fe1a340136629939934b553af35b03fc62ca2a88baa6803b2f9bfdf269fb850
+ languageName: node
+ linkType: hard
+
"ora@npm:^3.4.0":
version: 3.4.0
resolution: "ora@npm:3.4.0"
@@ -19189,6 +21673,16 @@ __metadata:
languageName: node
linkType: hard
+"os-name@npm:6.1.0":
+ version: 6.1.0
+ resolution: "os-name@npm:6.1.0"
+ dependencies:
+ macos-release: "npm:^3.3.0"
+ windows-release: "npm:^6.1.0"
+ checksum: 10/d69a2060bea01dc502bd9a08802f43bebce85e95adde7740d0629a8522c16a92c05e0ee052819cac49f82aa61324ff038a3b79e015e26f122bbc08b40aa4ead3
+ languageName: node
+ linkType: hard
+
"os-tmpdir@npm:~1.0.2":
version: 1.0.2
resolution: "os-tmpdir@npm:1.0.2"
@@ -19279,6 +21773,13 @@ __metadata:
languageName: node
linkType: hard
+"p-map@npm:^7.0.2":
+ version: 7.0.4
+ resolution: "p-map@npm:7.0.4"
+ checksum: 10/ef48c3b2e488f31c693c9fcc0df0ef76518cf6426a495cf9486ebbb0fd7f31aef7f90e96f72e0070c0ff6e3177c9318f644b512e2c29e3feee8d7153fcb6782e
+ languageName: node
+ linkType: hard
+
"p-try@npm:^2.0.0":
version: 2.2.0
resolution: "p-try@npm:2.2.0"
@@ -19378,6 +21879,15 @@ __metadata:
languageName: node
linkType: hard
+"parse-path@npm:^7.0.0":
+ version: 7.1.0
+ resolution: "parse-path@npm:7.1.0"
+ dependencies:
+ protocols: "npm:^2.0.0"
+ checksum: 10/6da6c6803fa73bacfee98e694c6c95fa55caae632c765369e4fd917f1043ef71f35ecaae420ef0e39e933bd1f939c4bc1e01522b62145191cdbe72e58d37a8ab
+ languageName: node
+ linkType: hard
+
"parse-png@npm:^2.1.0":
version: 2.1.0
resolution: "parse-png@npm:2.1.0"
@@ -19387,6 +21897,16 @@ __metadata:
languageName: node
linkType: hard
+"parse-url@npm:^9.2.0":
+ version: 9.2.0
+ resolution: "parse-url@npm:9.2.0"
+ dependencies:
+ "@types/parse-path": "npm:^7.0.0"
+ parse-path: "npm:^7.0.0"
+ checksum: 10/d2746f0dbcd34d39df966a0726c00ede272aa34d825513baca721ad95480786c664f91ab22cf4e79cdb130468056e41834f6c9cc912b9180539f73aa5bafa982
+ languageName: node
+ linkType: hard
+
"parse5@npm:^7.0.0, parse5@npm:^7.1.1":
version: 7.2.1
resolution: "parse5@npm:7.2.1"
@@ -19448,6 +21968,13 @@ __metadata:
languageName: node
linkType: hard
+"path-key@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "path-key@npm:4.0.0"
+ checksum: 10/8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7
+ languageName: node
+ linkType: hard
+
"path-parse@npm:^1.0.5, path-parse@npm:^1.0.7":
version: 1.0.7
resolution: "path-parse@npm:1.0.7"
@@ -19489,6 +22016,13 @@ __metadata:
languageName: node
linkType: hard
+"path-type@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "path-type@npm:6.0.0"
+ checksum: 10/b9f6eaf7795c48d5c9bc4c6bc3ac61315b8d36975a73497ab2e02b764c0836b71fb267ea541863153f633a069a1c2ed3c247cb781633842fc571c655ac57c00e
+ languageName: node
+ linkType: hard
+
"path@npm:0.12.7":
version: 0.12.7
resolution: "path@npm:0.12.7"
@@ -19525,6 +22059,13 @@ __metadata:
languageName: node
linkType: hard
+"perfect-debounce@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "perfect-debounce@npm:2.0.0"
+ checksum: 10/3f889ab0fe22d84daf49564d4a0b5e823f67beeb1974a2ea26f139b3d90f56a8f81eabc8d317b56caa05c5ee1bf06d2ae6c0aac4bab8f266c6db2aa89ae16ed8
+ languageName: node
+ linkType: hard
+
"pg-int8@npm:1.0.1":
version: 1.0.1
resolution: "pg-int8@npm:1.0.1"
@@ -19619,6 +22160,17 @@ __metadata:
languageName: node
linkType: hard
+"pkg-types@npm:^2.3.0":
+ version: 2.3.0
+ resolution: "pkg-types@npm:2.3.0"
+ dependencies:
+ confbox: "npm:^0.2.2"
+ exsolve: "npm:^1.0.7"
+ pathe: "npm:^2.0.3"
+ checksum: 10/4b36e4eb12693a1beb145573c564ec6fb74b1008d3b457eaa1f0072331edf05cb7c479c47fe0c4bfdec76c2caff5b68215ff270e5fe49634c07984a7a0197118
+ languageName: node
+ linkType: hard
+
"pkg-up@npm:^3.1.0":
version: 3.1.0
resolution: "pkg-up@npm:3.1.0"
@@ -19847,6 +22399,13 @@ __metadata:
languageName: node
linkType: hard
+"presentable-error@npm:^0.0.1":
+ version: 0.0.1
+ resolution: "presentable-error@npm:0.0.1"
+ checksum: 10/013809ee7a47ced847a8d860e9b89a56cdd8c4f1ad04ad8da1e58fd60843f77f497d204146bb15aaa9793d3b94ad8626eed01256fc9eb5839a545af2000a5fa4
+ languageName: node
+ linkType: hard
+
"prettier-linter-helpers@npm:^1.0.0":
version: 1.0.0
resolution: "prettier-linter-helpers@npm:1.0.0"
@@ -19856,7 +22415,7 @@ __metadata:
languageName: node
linkType: hard
-"prettier@npm:^3.6.2":
+"prettier@npm:^3.4.2, prettier@npm:^3.6.2":
version: 3.6.2
resolution: "prettier@npm:3.6.2"
bin:
@@ -20019,6 +22578,13 @@ __metadata:
languageName: node
linkType: hard
+"protocols@npm:^2.0.0, protocols@npm:^2.0.1":
+ version: 2.0.2
+ resolution: "protocols@npm:2.0.2"
+ checksum: 10/031cc068eb800468a50eb7c1e1c528bf142fb8314f5df9b9ea3c3f9df1697a19f97b9915b1229cef694d156812393172d9c3051ef7878d26eaa8c6faa5cccec4
+ languageName: node
+ linkType: hard
+
"proxy-agent@npm:6.5.0":
version: 6.5.0
resolution: "proxy-agent@npm:6.5.0"
@@ -20175,6 +22741,16 @@ __metadata:
languageName: node
linkType: hard
+"rc9@npm:^2.1.2":
+ version: 2.1.2
+ resolution: "rc9@npm:2.1.2"
+ dependencies:
+ defu: "npm:^6.1.4"
+ destr: "npm:^2.0.3"
+ checksum: 10/0694d2a80579983a5e4f0452092d9f6a06b785b104b32f48f3d6bb263f637e53d9ebd1fd77a41b157b84c1c7e8e4ecc87c3824907738653a296e6d2faf3d1844
+ languageName: node
+ linkType: hard
+
"rc@npm:~1.2.7":
version: 1.2.8
resolution: "rc@npm:1.2.8"
@@ -20346,6 +22922,38 @@ __metadata:
languageName: node
linkType: hard
+"react-native-builder-bob@npm:^0.40.15":
+ version: 0.40.16
+ resolution: "react-native-builder-bob@npm:0.40.16"
+ dependencies:
+ "@babel/core": "npm:^7.25.2"
+ "@babel/plugin-transform-flow-strip-types": "npm:^7.26.5"
+ "@babel/plugin-transform-strict-mode": "npm:^7.24.7"
+ "@babel/preset-env": "npm:^7.25.2"
+ "@babel/preset-react": "npm:^7.24.7"
+ "@babel/preset-typescript": "npm:^7.24.7"
+ arktype: "npm:^2.1.15"
+ babel-plugin-syntax-hermes-parser: "npm:^0.28.0"
+ browserslist: "npm:^4.20.4"
+ cross-spawn: "npm:^7.0.3"
+ dedent: "npm:^0.7.0"
+ del: "npm:^6.1.1"
+ escape-string-regexp: "npm:^4.0.0"
+ fs-extra: "npm:^10.1.0"
+ glob: "npm:^10.5.0"
+ is-git-dirty: "npm:^2.0.1"
+ json5: "npm:^2.2.1"
+ kleur: "npm:^4.1.4"
+ prompts: "npm:^2.4.2"
+ react-native-monorepo-config: "npm:^0.1.8"
+ which: "npm:^2.0.2"
+ yargs: "npm:^17.5.1"
+ bin:
+ bob: bin/bob
+ checksum: 10/7f9c6e02131a833d68df92e6338f86e2880c7404116c5104c7eaa1cb8517ed559f2de591306b6d67e0af39f4f4fef9894b69b3fd624dce35822fb7d4b752776b
+ languageName: node
+ linkType: hard
+
"react-native-builder-bob@npm:~0.23":
version: 0.23.2
resolution: "react-native-builder-bob@npm:0.23.2"
@@ -20375,14 +22983,39 @@ __metadata:
languageName: node
linkType: hard
-"react-native-callkeep@npm:^4.3.16":
- version: 4.3.16
- resolution: "react-native-callkeep@npm:4.3.16"
+"react-native-callingx@workspace:^, react-native-callingx@workspace:packages/react-native-callingx":
+ version: 0.0.0-use.local
+ resolution: "react-native-callingx@workspace:packages/react-native-callingx"
+ dependencies:
+ "@commitlint/config-conventional": "npm:^19.8.1"
+ "@eslint/compat": "npm:^1.3.2"
+ "@eslint/eslintrc": "npm:^3.3.1"
+ "@eslint/js": "npm:^9.35.0"
+ "@react-native-community/cli": "npm:20.0.1"
+ "@react-native/babel-preset": "npm:0.81.1"
+ "@react-native/eslint-config": "npm:^0.81.1"
+ "@release-it/conventional-changelog": "npm:^10.0.1"
+ "@types/jest": "npm:^29.5.14"
+ "@types/react": "npm:^19.1.0"
+ commitlint: "npm:^19.8.1"
+ del-cli: "npm:^6.0.0"
+ eslint: "npm:^9.35.0"
+ eslint-config-prettier: "npm:^10.1.8"
+ eslint-plugin-prettier: "npm:^5.5.4"
+ jest: "npm:^29.7.0"
+ lefthook: "npm:^2.0.3"
+ prettier: "npm:^3.4.2"
+ react: "npm:19.1.0"
+ react-native: "npm:0.81.1"
+ react-native-builder-bob: "npm:^0.40.15"
+ release-it: "npm:^19.0.4"
+ turbo: "npm:^2.5.6"
+ typescript: "npm:^5.9.2"
peerDependencies:
- react-native: ">=0.40.0"
- checksum: 10/db1ece74c2272b72625fc6240464452aca6d8541a3682e051f72de1f1c52ee5b8295b247e30fe9a325f9ecc60d728b18ae4b46e6ac590151b4b33c351b67f4e7
- languageName: node
- linkType: hard
+ react: "*"
+ react-native: "*"
+ languageName: unknown
+ linkType: soft
"react-native-device-info@npm:^14.1.1":
version: 14.1.1
@@ -20477,6 +23110,16 @@ __metadata:
languageName: node
linkType: hard
+"react-native-monorepo-config@npm:^0.1.8":
+ version: 0.1.10
+ resolution: "react-native-monorepo-config@npm:0.1.10"
+ dependencies:
+ escape-string-regexp: "npm:^5.0.0"
+ fast-glob: "npm:^3.3.3"
+ checksum: 10/36611eca9cbda6647111e659d5c466fdba002c608172b9d25880b6e3ac95c51f41d15520e06d9d3188c096b0c9182caeba7b9340c64f6b45f1fee331c08b877b
+ languageName: node
+ linkType: hard
+
"react-native-permissions@npm:^5.4.2":
version: 5.4.2
resolution: "react-native-permissions@npm:5.4.2"
@@ -20670,6 +23313,56 @@ __metadata:
languageName: node
linkType: hard
+"react-native@npm:0.81.1":
+ version: 0.81.1
+ resolution: "react-native@npm:0.81.1"
+ dependencies:
+ "@jest/create-cache-key-function": "npm:^29.7.0"
+ "@react-native/assets-registry": "npm:0.81.1"
+ "@react-native/codegen": "npm:0.81.1"
+ "@react-native/community-cli-plugin": "npm:0.81.1"
+ "@react-native/gradle-plugin": "npm:0.81.1"
+ "@react-native/js-polyfills": "npm:0.81.1"
+ "@react-native/normalize-colors": "npm:0.81.1"
+ "@react-native/virtualized-lists": "npm:0.81.1"
+ abort-controller: "npm:^3.0.0"
+ anser: "npm:^1.4.9"
+ ansi-regex: "npm:^5.0.0"
+ babel-jest: "npm:^29.7.0"
+ babel-plugin-syntax-hermes-parser: "npm:0.29.1"
+ base64-js: "npm:^1.5.1"
+ commander: "npm:^12.0.0"
+ flow-enums-runtime: "npm:^0.0.6"
+ glob: "npm:^7.1.1"
+ invariant: "npm:^2.2.4"
+ jest-environment-node: "npm:^29.7.0"
+ memoize-one: "npm:^5.0.0"
+ metro-runtime: "npm:^0.83.1"
+ metro-source-map: "npm:^0.83.1"
+ nullthrows: "npm:^1.1.1"
+ pretty-format: "npm:^29.7.0"
+ promise: "npm:^8.3.0"
+ react-devtools-core: "npm:^6.1.5"
+ react-refresh: "npm:^0.14.0"
+ regenerator-runtime: "npm:^0.13.2"
+ scheduler: "npm:0.26.0"
+ semver: "npm:^7.1.3"
+ stacktrace-parser: "npm:^0.1.10"
+ whatwg-fetch: "npm:^3.0.0"
+ ws: "npm:^6.2.3"
+ yargs: "npm:^17.6.2"
+ peerDependencies:
+ "@types/react": ^19.1.0
+ react: ^19.1.0
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ bin:
+ react-native: cli.js
+ checksum: 10/f6b99f5225ddb2ffa8e10d24e56b3fc47e96fc217c2e1682de6f7fd2728be6d1172f2be21442ca31b34ec552317cb5813288d3921821d1eda22631ecefe1c891
+ languageName: node
+ linkType: hard
+
"react-native@npm:^0.81.5":
version: 0.81.5
resolution: "react-native@npm:0.81.5"
@@ -20941,7 +23634,7 @@ __metadata:
languageName: node
linkType: hard
-"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0":
+"readable-stream@npm:^3.0.2, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0":
version: 3.6.2
resolution: "readable-stream@npm:3.6.2"
dependencies:
@@ -21092,6 +23785,39 @@ __metadata:
languageName: node
linkType: hard
+"release-it@npm:^19.0.4":
+ version: 19.0.6
+ resolution: "release-it@npm:19.0.6"
+ dependencies:
+ "@nodeutils/defaults-deep": "npm:1.1.0"
+ "@octokit/rest": "npm:22.0.0"
+ "@phun-ky/typeof": "npm:2.0.3"
+ async-retry: "npm:1.3.3"
+ c12: "npm:3.3.1"
+ ci-info: "npm:^4.3.0"
+ eta: "npm:4.0.1"
+ git-url-parse: "npm:16.1.0"
+ inquirer: "npm:12.9.6"
+ issue-parser: "npm:7.0.1"
+ lodash.merge: "npm:4.6.2"
+ mime-types: "npm:3.0.1"
+ new-github-release-url: "npm:2.0.0"
+ open: "npm:10.2.0"
+ ora: "npm:9.0.0"
+ os-name: "npm:6.1.0"
+ proxy-agent: "npm:6.5.0"
+ semver: "npm:7.7.2"
+ tinyglobby: "npm:0.2.15"
+ undici: "npm:6.21.3"
+ url-join: "npm:5.0.0"
+ wildcard-match: "npm:5.1.4"
+ yargs-parser: "npm:21.1.1"
+ bin:
+ release-it: bin/release-it.js
+ checksum: 10/99eca72bc55f1dbe6a03e1365f27013d81f502ecc9b74962bafa8524a7ce2d74812441c1deb123ce22fbc77367d5dadc76a0da84a2974ddcc1b17d3e295f45df
+ languageName: node
+ linkType: hard
+
"remark-gfm@npm:^4.0.1":
version: 4.0.1
resolution: "remark-gfm@npm:4.0.1"
@@ -21393,6 +24119,13 @@ __metadata:
languageName: node
linkType: hard
+"retry@npm:0.13.1":
+ version: 0.13.1
+ resolution: "retry@npm:0.13.1"
+ checksum: 10/6125ec2e06d6e47e9201539c887defba4e47f63471db304c59e4b82fc63c8e89ca06a77e9d34939a9a42a76f00774b2f46c0d4a4cbb3e287268bd018ed69426d
+ languageName: node
+ linkType: hard
+
"retry@npm:^0.12.0":
version: 0.12.0
resolution: "retry@npm:0.12.0"
@@ -21552,6 +24285,13 @@ __metadata:
languageName: node
linkType: hard
+"run-applescript@npm:^7.0.0":
+ version: 7.1.0
+ resolution: "run-applescript@npm:7.1.0"
+ checksum: 10/8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a
+ languageName: node
+ linkType: hard
+
"run-async@npm:^2.4.0":
version: 2.4.1
resolution: "run-async@npm:2.4.1"
@@ -21559,6 +24299,13 @@ __metadata:
languageName: node
linkType: hard
+"run-async@npm:^4.0.5":
+ version: 4.0.6
+ resolution: "run-async@npm:4.0.6"
+ checksum: 10/d23929e36d0422b871a8964d5cfcb1b88295950ea5f72e1dfed458d4c3f3a33a7395e08167d8a4446f2110cfaac7d7653d9c804d2becab8afa8a63e16b97da81
+ languageName: node
+ linkType: hard
+
"run-parallel@npm:^1.1.9":
version: 1.2.0
resolution: "run-parallel@npm:1.2.0"
@@ -21575,7 +24322,7 @@ __metadata:
languageName: node
linkType: hard
-"rxjs@npm:7.8.2, rxjs@npm:^7.5.5, rxjs@npm:~7.8.2":
+"rxjs@npm:7.8.2, rxjs@npm:^7.5.5, rxjs@npm:^7.8.2, rxjs@npm:~7.8.2":
version: 7.8.2
resolution: "rxjs@npm:7.8.2"
dependencies:
@@ -21722,6 +24469,15 @@ __metadata:
languageName: node
linkType: hard
+"semver@npm:^7.3.7, semver@npm:^7.7.3":
+ version: 7.7.3
+ resolution: "semver@npm:7.7.3"
+ bin:
+ semver: bin/semver.js
+ checksum: 10/8dbc3168e057a38fc322af909c7f5617483c50caddba135439ff09a754b20bdd6482a5123ff543dad4affa488ecf46ec5fb56d61312ad20bb140199b88dfaea9
+ languageName: node
+ linkType: hard
+
"semver@npm:~7.6.3":
version: 7.6.3
resolution: "semver@npm:7.6.3"
@@ -22091,7 +24847,7 @@ __metadata:
languageName: node
linkType: hard
-"slash@npm:^5.0.0":
+"slash@npm:^5.0.0, slash@npm:^5.1.0":
version: 5.1.0
resolution: "slash@npm:5.1.0"
checksum: 10/2c41ec6fb1414cd9bba0fa6b1dd00e8be739e3fe85d079c69d4b09ca5f2f86eafd18d9ce611c0c0f686428638a36c272a6ac14799146a8295f259c10cc45cde4
@@ -22379,6 +25135,13 @@ __metadata:
languageName: node
linkType: hard
+"stdin-discarder@npm:^0.2.2":
+ version: 0.2.2
+ resolution: "stdin-discarder@npm:0.2.2"
+ checksum: 10/642ffd05bd5b100819d6b24a613d83c6e3857c6de74eb02fc51506fa61dc1b0034665163831873868157c4538d71e31762bcf319be86cea04c3aba5336470478
+ languageName: node
+ linkType: hard
+
"stop-iteration-iterator@npm:^1.1.0":
version: 1.1.0
resolution: "stop-iteration-iterator@npm:1.1.0"
@@ -22593,6 +25356,13 @@ __metadata:
languageName: node
linkType: hard
+"string-natural-compare@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "string-natural-compare@npm:3.0.1"
+ checksum: 10/bc1fd0ee196466489e121bbe11844094ddcdee5a687dca9dbb18ba2ace73b1f6c96c9b448df2dfed0879b781b6b12e329ca1c1fc0a86d70b00c7823b76109b1e
+ languageName: node
+ linkType: hard
+
"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
version: 4.2.3
resolution: "string-width@npm:4.2.3"
@@ -22626,7 +25396,7 @@ __metadata:
languageName: node
linkType: hard
-"string-width@npm:^8.0.0":
+"string-width@npm:^8.0.0, string-width@npm:^8.1.0":
version: 8.1.0
resolution: "string-width@npm:8.1.0"
dependencies:
@@ -22760,6 +25530,15 @@ __metadata:
languageName: node
linkType: hard
+"strip-ansi@npm:^7.1.2":
+ version: 7.1.2
+ resolution: "strip-ansi@npm:7.1.2"
+ dependencies:
+ ansi-regex: "npm:^6.0.1"
+ checksum: 10/db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b
+ languageName: node
+ linkType: hard
+
"strip-bom@npm:^3.0.0":
version: 3.0.0
resolution: "strip-bom@npm:3.0.0"
@@ -22781,6 +25560,13 @@ __metadata:
languageName: node
linkType: hard
+"strip-final-newline@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "strip-final-newline@npm:3.0.0"
+ checksum: 10/23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050
+ languageName: node
+ linkType: hard
+
"strip-indent@npm:^3.0.0":
version: 3.0.0
resolution: "strip-indent@npm:3.0.0"
@@ -23208,7 +25994,14 @@ __metadata:
languageName: node
linkType: hard
-"tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15":
+"tinyexec@npm:^1.0.0, tinyexec@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "tinyexec@npm:1.0.2"
+ checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405
+ languageName: node
+ linkType: hard
+
+"tinyglobby@npm:0.2.15, tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15":
version: 0.2.15
resolution: "tinyglobby@npm:0.2.15"
dependencies:
@@ -23349,6 +26142,15 @@ __metadata:
languageName: node
linkType: hard
+"ts-api-utils@npm:^1.3.0":
+ version: 1.4.3
+ resolution: "ts-api-utils@npm:1.4.3"
+ peerDependencies:
+ typescript: ">=4.2.0"
+ checksum: 10/713c51e7392323305bd4867422ba130fbf70873ef6edbf80ea6d7e9c8f41eeeb13e40e8e7fe7cd321d74e4864777329797077268c9f570464303a1723f1eed39
+ languageName: node
+ linkType: hard
+
"ts-api-utils@npm:^2.1.0":
version: 2.1.0
resolution: "ts-api-utils@npm:2.1.0"
@@ -23451,6 +26253,95 @@ __metadata:
languageName: node
linkType: hard
+"tslib@npm:^1.8.1":
+ version: 1.14.1
+ resolution: "tslib@npm:1.14.1"
+ checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb
+ languageName: node
+ linkType: hard
+
+"tsutils@npm:^3.21.0":
+ version: 3.21.0
+ resolution: "tsutils@npm:3.21.0"
+ dependencies:
+ tslib: "npm:^1.8.1"
+ peerDependencies:
+ typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ checksum: 10/ea036bec1dd024e309939ffd49fda7a351c0e87a1b8eb049570dd119d447250e2c56e0e6c00554e8205760e7417793fdebff752a46e573fbe07d4f375502a5b2
+ languageName: node
+ linkType: hard
+
+"turbo-darwin-64@npm:2.6.1":
+ version: 2.6.1
+ resolution: "turbo-darwin-64@npm:2.6.1"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"turbo-darwin-arm64@npm:2.6.1":
+ version: 2.6.1
+ resolution: "turbo-darwin-arm64@npm:2.6.1"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"turbo-linux-64@npm:2.6.1":
+ version: 2.6.1
+ resolution: "turbo-linux-64@npm:2.6.1"
+ conditions: os=linux & cpu=x64
+ languageName: node
+ linkType: hard
+
+"turbo-linux-arm64@npm:2.6.1":
+ version: 2.6.1
+ resolution: "turbo-linux-arm64@npm:2.6.1"
+ conditions: os=linux & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"turbo-windows-64@npm:2.6.1":
+ version: 2.6.1
+ resolution: "turbo-windows-64@npm:2.6.1"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
+"turbo-windows-arm64@npm:2.6.1":
+ version: 2.6.1
+ resolution: "turbo-windows-arm64@npm:2.6.1"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"turbo@npm:^2.5.6":
+ version: 2.6.1
+ resolution: "turbo@npm:2.6.1"
+ dependencies:
+ turbo-darwin-64: "npm:2.6.1"
+ turbo-darwin-arm64: "npm:2.6.1"
+ turbo-linux-64: "npm:2.6.1"
+ turbo-linux-arm64: "npm:2.6.1"
+ turbo-windows-64: "npm:2.6.1"
+ turbo-windows-arm64: "npm:2.6.1"
+ dependenciesMeta:
+ turbo-darwin-64:
+ optional: true
+ turbo-darwin-arm64:
+ optional: true
+ turbo-linux-64:
+ optional: true
+ turbo-linux-arm64:
+ optional: true
+ turbo-windows-64:
+ optional: true
+ turbo-windows-arm64:
+ optional: true
+ bin:
+ turbo: bin/turbo
+ checksum: 10/7bbd7cd3d36ba4d9061c32b07f1d86de946add71d29b5d9098841c195d2d6d60128db2da8b4fa1ed9c69959e544d0e4b063ecf47fdbfb70d7248bfb4dac8f30a
+ languageName: node
+ linkType: hard
+
"type-check@npm:^0.4.0, type-check@npm:~0.4.0":
version: 0.4.0
resolution: "type-check@npm:0.4.0"
@@ -23481,6 +26372,13 @@ __metadata:
languageName: node
linkType: hard
+"type-fest@npm:^2.5.1":
+ version: 2.19.0
+ resolution: "type-fest@npm:2.19.0"
+ checksum: 10/7bf9e8fdf34f92c8bb364c0af14ca875fac7e0183f2985498b77be129dc1b3b1ad0a6b3281580f19e48c6105c037fb966ad9934520c69c6434d17fd0af4eed78
+ languageName: node
+ linkType: hard
+
"type-fest@npm:^3.8.0":
version: 3.13.1
resolution: "type-fest@npm:3.13.1"
@@ -23572,6 +26470,13 @@ __metadata:
languageName: node
linkType: hard
+"typedarray@npm:^0.0.6":
+ version: 0.0.6
+ resolution: "typedarray@npm:0.0.6"
+ checksum: 10/2cc1bcf7d8c1237f6a16c04efc06637b2c5f2d74e58e84665445cf87668b85a21ab18dd751fa49eee6ae024b70326635d7b79ad37b1c370ed2fec6aeeeb52714
+ languageName: node
+ linkType: hard
+
"typescript-eslint@npm:^8.46.0":
version: 8.46.0
resolution: "typescript-eslint@npm:8.46.0"
@@ -23681,6 +26586,13 @@ __metadata:
languageName: node
linkType: hard
+"undici@npm:6.21.3":
+ version: 6.21.3
+ resolution: "undici@npm:6.21.3"
+ checksum: 10/b6b8f4a90e294c11fabbb174b471a310840695ed0154a44b81e9bb4a08867ed738c8a7eac4eb46c7902d502fbccf03fa2cf2e5f18d9a2218d82e4294e3f74a2b
+ languageName: node
+ linkType: hard
+
"undici@npm:^6.18.2":
version: 6.21.0
resolution: "undici@npm:6.21.0"
@@ -23719,6 +26631,20 @@ __metadata:
languageName: node
linkType: hard
+"unicorn-magic@npm:^0.1.0":
+ version: 0.1.0
+ resolution: "unicorn-magic@npm:0.1.0"
+ checksum: 10/9b4d0e9809807823dc91d0920a4a4c0cff2de3ebc54ee87ac1ee9bc75eafd609b09d1f14495e0173aef26e01118706196b6ab06a75fe0841028b3983a8af313f
+ languageName: node
+ linkType: hard
+
+"unicorn-magic@npm:^0.3.0":
+ version: 0.3.0
+ resolution: "unicorn-magic@npm:0.3.0"
+ checksum: 10/bdd7d7c522f9456f32a0b77af23f8854f9a7db846088c3868ec213f9550683ab6a2bdf3803577eacbafddb4e06900974385841ccb75338d17346ccef45f9cb01
+ languageName: node
+ linkType: hard
+
"unified@npm:^11.0.0":
version: 11.0.5
resolution: "unified@npm:11.0.5"
@@ -23825,6 +26751,13 @@ __metadata:
languageName: node
linkType: hard
+"universal-user-agent@npm:^7.0.0, universal-user-agent@npm:^7.0.2":
+ version: 7.0.3
+ resolution: "universal-user-agent@npm:7.0.3"
+ checksum: 10/c497e85f8b11eb8fa4dce584d7a39cc98710164959f494cafc3c269b51abb20fff269951838efd7424d15f6b3d001507f3cb8b52bb5676fdb642019dfd17e63e
+ languageName: node
+ linkType: hard
+
"universalify@npm:^0.1.0":
version: 0.1.2
resolution: "universalify@npm:0.1.2"
@@ -23888,6 +26821,13 @@ __metadata:
languageName: node
linkType: hard
+"url-join@npm:5.0.0":
+ version: 5.0.0
+ resolution: "url-join@npm:5.0.0"
+ checksum: 10/5921384a8ad4395b49ce4b50aa26efbc429cebe0bc8b3660ad693dd12fd859747b5369be0443e60e53a7850b2bc9d7d0687bcb94386662b40e743596bbf38101
+ languageName: node
+ linkType: hard
+
"url-parse@npm:^1.5.3":
version: 1.5.10
resolution: "url-parse@npm:1.5.10"
@@ -24280,6 +27220,13 @@ __metadata:
languageName: node
linkType: hard
+"walk-up-path@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "walk-up-path@npm:4.0.0"
+ checksum: 10/6a230b20e5de296895116dc12b09dafaec1f72b8060c089533d296e241aff059dfaebe0d015c77467f857e4b40c78e08f7481add76f340233a1f34fa8af9ed63
+ languageName: node
+ linkType: hard
+
"walker@npm:^1.0.7, walker@npm:^1.0.8":
version: 1.0.8
resolution: "walker@npm:1.0.8"
@@ -24535,6 +27482,22 @@ __metadata:
languageName: node
linkType: hard
+"wildcard-match@npm:5.1.4":
+ version: 5.1.4
+ resolution: "wildcard-match@npm:5.1.4"
+ checksum: 10/4a6821e91def808a38aa7c7c2e774c5b6dc8c6eb37743f18fae182802af52f19f19375de1bc1d465ff1e6b188489eab2716bf3eba1789b25b3f495f55e10fc57
+ languageName: node
+ linkType: hard
+
+"windows-release@npm:^6.1.0":
+ version: 6.1.0
+ resolution: "windows-release@npm:6.1.0"
+ dependencies:
+ execa: "npm:^8.0.1"
+ checksum: 10/2af39c94d5e4e250c3239e70177f3a97291c505e364b85a7ae63ca9d06c91496e8bd3a75c55e03184d9c27e58c0a0fa21a4a8457ac72cc560d8796a75f12d0a3
+ languageName: node
+ linkType: hard
+
"wonka@npm:^6.3.2":
version: 6.3.4
resolution: "wonka@npm:6.3.4"
@@ -24649,6 +27612,15 @@ __metadata:
languageName: node
linkType: hard
+"wsl-utils@npm:^0.1.0":
+ version: 0.1.0
+ resolution: "wsl-utils@npm:0.1.0"
+ dependencies:
+ is-wsl: "npm:^3.1.0"
+ checksum: 10/de4c92187e04c3c27b4478f410a02e81c351dc85efa3447bf1666f34fc80baacd890a6698ec91995631714086992036013286aea3d77e6974020d40a08e00aec
+ languageName: node
+ linkType: hard
+
"xcode@npm:^3.0.1":
version: 3.0.1
resolution: "xcode@npm:3.0.1"
@@ -24779,7 +27751,7 @@ __metadata:
languageName: node
linkType: hard
-"yargs@npm:17.7.2, yargs@npm:^17.3.1, yargs@npm:^17.5.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2":
+"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.3.1, yargs@npm:^17.5.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2":
version: 17.7.2
resolution: "yargs@npm:17.7.2"
dependencies:
@@ -24841,6 +27813,20 @@ __metadata:
languageName: node
linkType: hard
+"yoctocolors-cjs@npm:^2.1.3":
+ version: 2.1.3
+ resolution: "yoctocolors-cjs@npm:2.1.3"
+ checksum: 10/b2144b38807673a4254dae06fe1a212729550609e606289c305e45c585b36fab1dbba44fe6cde90db9b28be465ec63f4c2a50867aeec6672f6bc36b6c9a361a0
+ languageName: node
+ linkType: hard
+
+"yoctocolors@npm:^2.1.1":
+ version: 2.1.2
+ resolution: "yoctocolors@npm:2.1.2"
+ checksum: 10/6ee42d665a4cc161c7de3f015b2a65d6c65d2808bfe3b99e228bd2b1b784ef1e54d1907415c025fc12b400f26f372bfc1b71966c6c738d998325ca422eb39363
+ languageName: node
+ linkType: hard
+
"zod-to-json-schema@npm:^3.24.6":
version: 3.24.6
resolution: "zod-to-json-schema@npm:3.24.6"