From 568d8078cd95e22e39717936056f40763fb87b28 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 18 Mar 2026 14:14:46 -0700 Subject: [PATCH 01/25] chore(demo): add clean scripts for Android and iOS --- examples/demo/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo/package.json b/examples/demo/package.json index 00f3cf43..c33cd498 100644 --- a/examples/demo/package.json +++ b/examples/demo/package.json @@ -9,7 +9,7 @@ "android": "bash ../run-android.sh", "ios": "bash ../run-ios.sh", "clean:android": "cd android && ./gradlew clean && cd ..", - "clean:ios": "rm -rf ios/build ios/Pods", + "clean:ios": "cd ios && xcodebuild clean && cd ..", "lint": "eslint .", "start": "react-native start", "test": "jest" From a0693f6c9aa1900c99fa9be24c8504ee9b120beb Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 17:27:18 -0700 Subject: [PATCH 02/25] feat: add React Native New Architecture support --- __mocks__/react-native.ts | 4 + android/build.gradle | 1 + .../rnonesignalandroid/RNOneSignal.java | 246 +++++++++--------- .../ReactNativeOneSignalPackage.java | 45 ++-- ios/RCTOneSignal/RCTOneSignalEventEmitter.h | 8 + ...tEmitter.m => RCTOneSignalEventEmitter.mm} | 32 ++- package.json | 14 +- react-native-onesignal.podspec | 13 +- src/NativeOneSignal.ts | 106 ++++++++ src/OSNotification.ts | 5 +- src/events/EventManager.ts | 11 +- src/events/NotificationWillDisplayEvent.ts | 4 +- src/helpers.ts | 3 +- src/index.test.ts | 2 +- src/index.ts | 24 +- 15 files changed, 332 insertions(+), 186 deletions(-) rename ios/RCTOneSignal/{RCTOneSignalEventEmitter.m => RCTOneSignalEventEmitter.mm} (97%) create mode 100644 src/NativeOneSignal.ts diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index 4170f2ee..c28ca5f1 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -97,6 +97,10 @@ export const NativeModules = { OneSignal: mockRNOneSignal, }; +export const TurboModuleRegistry = { + getEnforcing: (_name: string) => mockRNOneSignal, +}; + export const Platform = mockPlatform; export { mockPlatform, mockRNOneSignal }; diff --git a/android/build.gradle b/android/build.gradle index 85cfc0dd..07933cb9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.library' +apply plugin: 'com.facebook.react' def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java index 8c59d882..aeb191ac 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -38,11 +38,11 @@ of this software and associated documentation files (the "Software"), to deal import android.content.Context; import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; @@ -75,12 +75,14 @@ of this software and associated documentation files (the "Software"), to deal import java.util.Map; import org.json.JSONException; -public class RNOneSignal extends ReactContextBaseJavaModule +public class RNOneSignal extends NativeOneSignalSpec implements IPushSubscriptionObserver, IPermissionObserver, IUserStateObserver, LifecycleEventListener, INotificationLifecycleListener { + public static final String NAME = "OneSignal"; + private ReactApplicationContext mReactApplicationContext; private ReactContext mReactContext; @@ -221,10 +223,9 @@ public RNOneSignal(ReactApplicationContext reactContext) { currentInstance = this; } - /** Native Module Overrides */ @Override public String getName() { - return "OneSignal"; + return NAME; } @Override @@ -243,8 +244,7 @@ public void onCatalystInstanceDestroy() { removeObservers(); } - // OneSignal namespace methods - @ReactMethod + @Override public void initialize(String appId) { Context context = mReactApplicationContext.getCurrentActivity(); OneSignalWrapper.setSdkType("reactnative"); @@ -265,29 +265,27 @@ public void initialize(String appId) { oneSignalInitDone = true; } - @ReactMethod - public void setPrivacyConsentGiven(Boolean value) { + @Override + public void setPrivacyConsentGiven(boolean value) { OneSignal.setConsentGiven(value); } - @ReactMethod - public void setPrivacyConsentRequired(Boolean required) { + @Override + public void setPrivacyConsentRequired(boolean required) { OneSignal.setConsentRequired(required); } - // OneSignal.Debug namespace methods - @ReactMethod - public void setLogLevel(int logLevel) { - OneSignal.getDebug().setLogLevel(LogLevel.fromInt(logLevel)); + @Override + public void setLogLevel(double logLevel) { + OneSignal.getDebug().setLogLevel(LogLevel.fromInt((int) logLevel)); } - @ReactMethod - public void setAlertLevel(int logLevel) { - OneSignal.getDebug().setAlertLevel(LogLevel.fromInt(logLevel)); + @Override + public void setAlertLevel(double logLevel) { + OneSignal.getDebug().setAlertLevel(LogLevel.fromInt((int) logLevel)); } - // OneSignal.InAppMessages namespace methods - @ReactMethod + @Override public void addInAppMessageClickListener() { if (!hasAddedInAppMessageClickListener) { OneSignal.getInAppMessages().addClickListener(rnInAppClickListener); @@ -295,7 +293,7 @@ public void addInAppMessageClickListener() { } } - @ReactMethod + @Override public void addInAppMessagesLifecycleListener() { if (!hasAddedInAppMessageLifecycleListener) { OneSignal.getInAppMessages().addLifecycleListener(rnInAppLifecycleListener); @@ -303,13 +301,13 @@ public void addInAppMessagesLifecycleListener() { } } - @ReactMethod + @Override public void getPaused(Promise promise) { promise.resolve(OneSignal.getInAppMessages().getPaused()); } - @ReactMethod - public void paused(Boolean pause) { + @Override + public void paused(boolean pause) { OneSignal.getInAppMessages().setPaused(pause); } @@ -318,44 +316,42 @@ public void addTrigger(String key, String value) { OneSignal.getInAppMessages().addTrigger(key, value); } - @ReactMethod + @Override public void addTriggers(ReadableMap triggers) { OneSignal.getInAppMessages().addTriggers(RNUtils.convertReadableMapIntoStringMap(triggers)); } - @ReactMethod + @Override public void removeTrigger(String key) { OneSignal.getInAppMessages().removeTrigger(key); } - @ReactMethod + @Override public void removeTriggers(ReadableArray keys) { OneSignal.getInAppMessages().removeTriggers(RNUtils.convertReadableArrayIntoStringCollection(keys)); } - @ReactMethod + @Override public void clearTriggers() { OneSignal.getInAppMessages().clearTriggers(); } - // OneSignal.Location namespace methods - @ReactMethod + @Override public void requestLocationPermission() { OneSignal.getLocation().requestPermission(Continue.none()); } - @ReactMethod + @Override public void isLocationShared(Promise promise) { promise.resolve(OneSignal.getLocation().isShared()); } - @ReactMethod - public void setLocationShared(Boolean shared) { + @Override + public void setLocationShared(boolean shared) { OneSignal.getLocation().setShared(shared); } - // OneSignal.Notifications namespace methods - @ReactMethod + @Override public void addNotificationClickListener() { if (this.hasAddedNotificationClickListener) { return; @@ -365,7 +361,7 @@ public void addNotificationClickListener() { hasAddedNotificationClickListener = true; } - @ReactMethod + @Override public void addNotificationForegroundLifecycleListener() { if (this.hasAddedNotificationForegroundListener) { return; @@ -405,8 +401,8 @@ public void onWillDisplay(INotificationWillDisplayEvent event) { } } - @ReactMethod - private void displayNotification(String notificationId) { + @Override + public void displayNotification(String notificationId) { INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId); if (event == null) { Logging.error( @@ -416,8 +412,8 @@ private void displayNotification(String notificationId) { event.getNotification().display(); } - @ReactMethod - private void preventDefault(String notificationId) { + @Override + public void preventDefault(String notificationId) { INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId); if (event == null) { Logging.error( @@ -428,7 +424,7 @@ private void preventDefault(String notificationId) { this.preventDefaultCache.put(notificationId, event); } - @ReactMethod + @Override public void addPermissionObserver() { if (!hasSetPermissionObserver) { OneSignal.getNotifications().addPermissionObserver(this); @@ -436,7 +432,6 @@ public void addPermissionObserver() { } } - @ReactMethod public void removePermissionObserver() { if (hasSetPermissionObserver) { OneSignal.getNotifications().removePermissionObserver(this); @@ -456,9 +451,8 @@ public void onNotificationPermissionChange(boolean permission) { } } - @ReactMethod - public void requestNotificationPermission(final boolean fallbackToSettings, Promise promise) { - // if permission already exists, return early as the method call will not resolve + @Override + public void requestNotificationPermission(boolean fallbackToSettings, Promise promise) { if (OneSignal.getNotifications().getPermission()) { promise.resolve(true); return; @@ -473,12 +467,12 @@ public void requestNotificationPermission(final boolean fallbackToSettings, Prom })); } - @ReactMethod + @Override public void hasNotificationPermission(Promise promise) { promise.resolve(OneSignal.getNotifications().getPermission()); } - @ReactMethod + @Override public void permissionNative(Promise promise) { if (OneSignal.getNotifications().getPermission()) { promise.resolve(2); @@ -487,28 +481,63 @@ public void permissionNative(Promise promise) { } } - @ReactMethod + @Override public void canRequestNotificationPermission(Promise promise) { promise.resolve(OneSignal.getNotifications().getCanRequestPermission()); } - @ReactMethod + @Override + public void registerForProvisionalAuthorization(Callback callback) { + // iOS only, no-op on Android + } + + @Override public void clearAllNotifications() { OneSignal.getNotifications().clearAllNotifications(); } - @ReactMethod - public void removeNotification(int id) { - OneSignal.getNotifications().removeNotification(id); + @Override + public void removeNotification(double id) { + OneSignal.getNotifications().removeNotification((int) id); } - @ReactMethod + @Override public void removeGroupedNotifications(String id) { OneSignal.getNotifications().removeGroupedNotifications(id); } - // OneSignal.User.pushSubscription namespace methods - @ReactMethod + // Live Activities stubs (iOS only) + @Override + public void enterLiveActivity(String activityId, String token, Callback callback) { + // iOS only, no-op on Android + } + + @Override + public void exitLiveActivity(String activityId, Callback callback) { + // iOS only, no-op on Android + } + + @Override + public void setPushToStartToken(String activityType, String token) { + // iOS only, no-op on Android + } + + @Override + public void removePushToStartToken(String activityType) { + // iOS only, no-op on Android + } + + @Override + public void setupDefaultLiveActivity(@Nullable ReadableMap options) { + // iOS only, no-op on Android + } + + @Override + public void startDefaultLiveActivity(String activityId, ReadableMap attributes, ReadableMap content) { + // iOS only, no-op on Android + } + + @Override public void getPushSubscriptionId(Promise promise) { IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); String pushId = pushSubscription.getId(); @@ -519,7 +548,7 @@ public void getPushSubscriptionId(Promise promise) { } } - @ReactMethod + @Override public void getPushSubscriptionToken(Promise promise) { IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); String pushToken = pushSubscription.getToken(); @@ -530,25 +559,25 @@ public void getPushSubscriptionToken(Promise promise) { } } - @ReactMethod + @Override public void getOptedIn(Promise promise) { IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); promise.resolve(pushSubscription.getOptedIn()); } - @ReactMethod + @Override public void optIn() { IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); pushSubscription.optIn(); } - @ReactMethod + @Override public void optOut() { IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); pushSubscription.optOut(); } - @ReactMethod + @Override public void addPushSubscriptionObserver() { if (!hasSetPushSubscriptionObserver) { OneSignal.getUser().getPushSubscription().addObserver(this); @@ -569,7 +598,6 @@ public void onPushSubscriptionChange(PushSubscriptionChangedState pushSubscripti } } - @ReactMethod public void removePushSubscriptionObserver() { if (hasSetPushSubscriptionObserver) { OneSignal.getUser().getPushSubscription().removeObserver(this); @@ -577,39 +605,37 @@ public void removePushSubscriptionObserver() { } } - // OneSignal.Session namespace methods - @ReactMethod + @Override public void addOutcome(String name) { OneSignal.getSession().addOutcome(name); } - @ReactMethod + @Override public void addUniqueOutcome(String name) { OneSignal.getSession().addUniqueOutcome(name); } - @ReactMethod - public void addOutcomeWithValue(String name, float value) { - OneSignal.getSession().addOutcomeWithValue(name, value); + @Override + public void addOutcomeWithValue(String name, double value) { + OneSignal.getSession().addOutcomeWithValue(name, (float) value); } - // OneSignal.User namespace methods - @ReactMethod + @Override public void login(String externalUserId) { OneSignal.login(externalUserId); } - @ReactMethod + @Override public void logout() { OneSignal.logout(); } - @ReactMethod + @Override public void setLanguage(String language) { OneSignal.getUser().setLanguage(language); } - @ReactMethod + @Override public void addTag(String key, String value) { OneSignal.getUser().addTag(key, value); } @@ -619,17 +645,17 @@ public void removeTag(String key) { OneSignal.getUser().removeTag(key); } - @ReactMethod + @Override public void addTags(ReadableMap tags) { OneSignal.getUser().addTags(RNUtils.convertReadableMapIntoStringMap(tags)); } - @ReactMethod + @Override public void removeTags(ReadableArray tagKeys) { OneSignal.getUser().removeTags(RNUtils.convertReadableArrayIntoStringCollection(tagKeys)); } - @ReactMethod + @Override public void getTags(Promise promise) { Map tags = OneSignal.getUser().getTags(); WritableMap writableTags = Arguments.createMap(); @@ -639,67 +665,47 @@ public void getTags(Promise promise) { promise.resolve(writableTags); } - @ReactMethod - public void addEmail(String email, Promise promise) { - try { - OneSignal.getUser().addEmail(email); - promise.resolve(null); - } catch (Throwable t) { - promise.reject(t.getMessage()); - } + @Override + public void addEmail(String email) { + OneSignal.getUser().addEmail(email); } - @ReactMethod - public void removeEmail(String email, Promise promise) { - try { - OneSignal.getUser().removeEmail(email); - promise.resolve(null); - } catch (Throwable t) { - promise.reject(t.getMessage()); - } + @Override + public void removeEmail(String email) { + OneSignal.getUser().removeEmail(email); } - @ReactMethod - public void addSms(String smsNumber, Promise promise) { - try { - OneSignal.getUser().addSms(smsNumber); - promise.resolve(null); - } catch (Throwable t) { - promise.reject(t.getMessage()); - } + @Override + public void addSms(String smsNumber) { + OneSignal.getUser().addSms(smsNumber); } - @ReactMethod - public void removeSms(String smsNumber, Promise promise) { - try { - OneSignal.getUser().removeSms(smsNumber); - promise.resolve(null); - } catch (Throwable t) { - promise.reject(t.getMessage()); - } + @Override + public void removeSms(String smsNumber) { + OneSignal.getUser().removeSms(smsNumber); } - @ReactMethod + @Override public void addAlias(String label, String id) { OneSignal.getUser().addAlias(label, id); } - @ReactMethod + @Override public void removeAlias(String label) { OneSignal.getUser().removeAlias(label); } - @ReactMethod + @Override public void addAliases(ReadableMap aliases) { OneSignal.getUser().addAliases(RNUtils.convertReadableMapIntoStringMap(aliases)); } - @ReactMethod + @Override public void removeAliases(ReadableArray aliasLabels) { OneSignal.getUser().removeAliases(RNUtils.convertReadableArrayIntoStringCollection(aliasLabels)); } - @ReactMethod + @Override public void getOnesignalId(Promise promise) { String onesignalId = OneSignal.getUser().getOnesignalId(); if (onesignalId.isEmpty()) { @@ -708,7 +714,7 @@ public void getOnesignalId(Promise promise) { promise.resolve(onesignalId); } - @ReactMethod + @Override public void getExternalId(Promise promise) { String externalId = OneSignal.getUser().getExternalId(); if (externalId.isEmpty()) { @@ -717,7 +723,7 @@ public void getExternalId(Promise promise) { promise.resolve(externalId); } - @ReactMethod + @Override public void addUserStateObserver() { if (!hasSetUserStateObserver) { OneSignal.getUser().addObserver(this); @@ -737,7 +743,6 @@ public void onUserStateChange(UserChangedState state) { } } - @ReactMethod public void removeUserStateObserver() { if (hasSetUserStateObserver) { OneSignal.getUser().removeObserver(this); @@ -745,18 +750,17 @@ public void removeUserStateObserver() { } } - /** Added for NativeEventEmitter */ - @ReactMethod + @Override public void addListener(String eventName) { - // Keep: Required for RN built in Event Emitter Calls. + // Required for RN built in Event Emitter Calls. } - @ReactMethod - public void removeListeners(int count) { - // Keep: Required for RN built in Event Emitter Calls. + @Override + public void removeListeners(double count) { + // Required for RN built in Event Emitter Calls. } - @ReactMethod + @Override public void trackEvent(String name, @Nullable ReadableMap properties) { OneSignal.getUser().trackEvent(name, properties != null ? properties.toHashMap() : new HashMap<>()); } diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java b/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java index 73a8daa9..921525c4 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java @@ -1,28 +1,39 @@ package com.onesignal.rnonesignalandroid; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.BaseReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import java.util.HashMap; +import java.util.Map; -public class ReactNativeOneSignalPackage implements ReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new RNOneSignal(reactContext)); - } +public class ReactNativeOneSignalPackage extends BaseReactPackage { - // Deprecated RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(RNOneSignal.NAME)) { + return new RNOneSignal(reactContext); + } + return null; } @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return new ArrayList<>(); + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return new ReactModuleInfoProvider() { + @Override + public Map getReactModuleInfos() { + Map map = new HashMap<>(); + map.put(RNOneSignal.NAME, new ReactModuleInfo( + RNOneSignal.NAME, + RNOneSignal.NAME, + false, + false, + false, + true + )); + return map; + } + }; } } diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h index 5e4a8f2a..81b949ab 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h @@ -12,6 +12,10 @@ #import "RCTUtils.h" #endif +#ifdef RCT_NEW_ARCH_ENABLED +#import +#endif + typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { PermissionChanged, SubscriptionChanged, @@ -37,7 +41,11 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { #define OSEventString(enum) [OSNotificationEventTypesArray objectAtIndex:enum] +#ifdef RCT_NEW_ARCH_ENABLED +@interface RCTOneSignalEventEmitter : RCTEventEmitter +#else @interface RCTOneSignalEventEmitter : RCTEventEmitter +#endif + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body; + (BOOL)hasSetBridge; diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.m b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm similarity index 97% rename from ios/RCTOneSignal/RCTOneSignalEventEmitter.m rename to ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 46b13810..1a3d1002 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.m +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -30,13 +30,7 @@ + (BOOL)requiresMainQueueSetup { return YES; } -/* - This class acts as the module & event emitter - It is initialized automatically by React-Native - This subclass handles communication between the SDK and JavaScript -*/ - -RCT_EXPORT_MODULE(RCTOneSignal) +RCT_EXPORT_MODULE(OneSignal) #pragma mark RCTEventEmitter Subclass Methods @@ -418,6 +412,15 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { RCT_EXPORT_METHOD(clearAllNotifications) { [OneSignal.Notifications clearAll]; } +// Android-only stubs +RCT_EXPORT_METHOD(removeNotification : (double)notificationId) { + // Android only, no-op on iOS +} + +RCT_EXPORT_METHOD(removeGroupedNotifications : (NSString *)groupId) { + // Android only, no-op on iOS +} + // OneSignal.Session namespace methods RCT_EXPORT_METHOD(addOutcome : (NSString *)name) { [OneSignal.Session addOutcome:name]; @@ -503,7 +506,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { NSString *onesignalId = OneSignal.User.onesignalId; if (onesignalId == nil || [onesignalId length] == 0) { - resolve([NSNull null]); // Resolve with null if nil or empty + resolve([NSNull null]); } else { resolve(onesignalId); } @@ -515,7 +518,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { NSString *externalId = OneSignal.User.externalId; if (externalId == nil || [externalId length] == 0) { - resolve([NSNull null]); // Resolve with null if nil or empty + resolve([NSNull null]); } else { resolve(externalId); } @@ -591,10 +594,6 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { [_notificationWillDisplayCache removeObjectForKey:notificationId]; } -RCT_EXPORT_METHOD(initInAppMessageClickHandlerParams) { - // iOS Stub -} - - (void)removeObservers { [self removePermissionObserver]; [self removePushSubscriptionObserver]; @@ -633,4 +632,11 @@ - (void)removeUserStateObserver { [OneSignal.User trackEventWithName:name properties:properties]; } +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); +} +#endif + @end diff --git a/package.json b/package.json index 08ec262f..ce23a1ef 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "React Native OneSignal SDK", "files": [ "dist", + "src/NativeOneSignal.ts", "android", "ios", "react-native-onesignal.podspec" @@ -59,5 +60,16 @@ "url": "https://github.com/OneSignal/react-native-onesignal" }, "author": "OneSignal , Geektime ", - "license": "MIT" + "license": "MIT", + "codegenConfig": { + "name": "RNOneSignalSpec", + "type": "modules", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.onesignal.rnonesignalandroid" + } + }, + "peerDependencies": { + "react-native": ">=0.71.0" + } } diff --git a/react-native-onesignal.podspec b/react-native-onesignal.podspec index d0827f74..d2acd3f5 100644 --- a/react-native-onesignal.podspec +++ b/react-native-onesignal.podspec @@ -10,17 +10,10 @@ Pod::Spec.new do |s| s.author = { package_json["author"] => package_json["author"] } s.platform = :ios, "11.0" s.source = { :git => "#{package_json["repository"]["url"]}.git", :tag => "#{s.version}" } - s.source_files = 'ios/RCTOneSignal/*.{h,m}' + s.source_files = 'ios/RCTOneSignal/*.{h,m,mm}' s.static_framework = true - # The "React" pod is required due to the use of RCTBridgeModule, RCTEventEmitter, etc - # Ensuring we have version 0.13.0 or greater to avoid a cocoapods issue noted in React Native's release notes - # https://github.com/facebook/react-native/releases/tag/v0.13.0 - # The last stable version on Cocapod's repo is 0.11.0 as we want to ignore it to always use the local copy. - s.dependency 'React', '>= 0.13.0', '< 1.0.0' - # REQUIRED: Ensure you have the following in your project's Podfile - # pod 'React', :path => '../node_modules/react-native/' + install_modules_dependencies(s) - # The Native OneSignal-iOS-SDK XCFramework from cocoapods. - s.dependency 'OneSignalXCFramework', '5.5.0' + s.dependency 'OneSignalXCFramework', '5.4.2' end diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts new file mode 100644 index 00000000..22f0ba7d --- /dev/null +++ b/src/NativeOneSignal.ts @@ -0,0 +1,106 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + // OneSignal root + initialize(appId: string): void; + login(externalId: string): void; + logout(): void; + setPrivacyConsentRequired(required: boolean): void; + setPrivacyConsentGiven(granted: boolean): void; + + // Debug + setLogLevel(logLevel: number): void; + setAlertLevel(logLevel: number): void; + + // Live Activities (iOS only, stubs on Android) + enterLiveActivity( + activityId: string, + token: string, + callback: (result: Object) => void, + ): void; + exitLiveActivity( + activityId: string, + callback: (result: Object) => void, + ): void; + setPushToStartToken(activityType: string, token: string): void; + removePushToStartToken(activityType: string): void; + setupDefaultLiveActivity(options: Object | null): void; + startDefaultLiveActivity( + activityId: string, + attributes: Object, + content: Object, + ): void; + + // Push Subscription + addPushSubscriptionObserver(): void; + getPushSubscriptionId(): Promise; + getPushSubscriptionToken(): Promise; + getOptedIn(): Promise; + optIn(): void; + optOut(): void; + + // User + addUserStateObserver(): void; + getOnesignalId(): Promise; + getExternalId(): Promise; + setLanguage(language: string): void; + addAlias(label: string, id: string): void; + addAliases(aliases: Object): void; + removeAlias(label: string): void; + removeAliases(labels: string[]): void; + addEmail(email: string): void; + removeEmail(email: string): void; + addSms(smsNumber: string): void; + removeSms(smsNumber: string): void; + addTag(key: string, value: string): void; + addTags(tags: Object): void; + removeTags(keys: string[]): void; + getTags(): Promise; + trackEvent(name: string, properties: Object): void; + + // Notifications + hasNotificationPermission(): Promise; + requestNotificationPermission( + fallbackToSettings: boolean, + ): Promise; + canRequestNotificationPermission(): Promise; + registerForProvisionalAuthorization( + callback: (accepted: boolean) => void, + ): void; + permissionNative(): Promise; + addNotificationClickListener(): void; + addNotificationForegroundLifecycleListener(): void; + addPermissionObserver(): void; + clearAllNotifications(): void; + removeNotification(id: number): void; + removeGroupedNotifications(id: string): void; + displayNotification(notificationId: string): void; + preventDefault(notificationId: string): void; + + // In-App Messages + addInAppMessageClickListener(): void; + addInAppMessagesLifecycleListener(): void; + addTriggers(triggers: Object): void; + removeTrigger(key: string): void; + removeTriggers(keys: string[]): void; + clearTriggers(): void; + paused(pause: boolean): void; + getPaused(): Promise; + + // Location + requestLocationPermission(): void; + setLocationShared(shared: boolean): void; + isLocationShared(): Promise; + + // Session + addOutcome(name: string): void; + addUniqueOutcome(name: string): void; + addOutcomeWithValue(name: string, value: number): void; + + // Events (required for NativeEventEmitter) + addListener(eventName: string): void; + removeListeners(count: number): void; +} + +export default TurboModuleRegistry.getEnforcing('OneSignal'); diff --git a/src/OSNotification.ts b/src/OSNotification.ts index 7e7cf5c9..1a630f23 100644 --- a/src/OSNotification.ts +++ b/src/OSNotification.ts @@ -1,5 +1,6 @@ -import { NativeModules, Platform } from 'react-native'; -const RNOneSignal = NativeModules.OneSignal; +import { Platform } from 'react-native'; +import NativeOneSignal from './NativeOneSignal'; +const RNOneSignal = NativeOneSignal; export interface BaseNotificationData { body: string; diff --git a/src/events/EventManager.ts b/src/events/EventManager.ts index 5d5b2edd..ad1855cc 100644 --- a/src/events/EventManager.ts +++ b/src/events/EventManager.ts @@ -1,8 +1,5 @@ -import { - type EmitterSubscription, - NativeEventEmitter, - type NativeModule, -} from 'react-native'; +import { type EmitterSubscription, NativeEventEmitter } from 'react-native'; +import type { Spec } from '../NativeOneSignal'; import { IN_APP_MESSAGE_CLICKED, IN_APP_MESSAGE_DID_DISMISS, @@ -67,12 +64,12 @@ const eventList = [ ] as const; export default class EventManager { - private RNOneSignal: NativeModule; + private RNOneSignal: Spec; private oneSignalEventEmitter: NativeEventEmitter; private eventListenerArrayMap: Map void>>; private listeners: { [key: string]: EmitterSubscription }; - constructor(RNOneSignal: NativeModule) { + constructor(RNOneSignal: Spec) { this.RNOneSignal = RNOneSignal; this.oneSignalEventEmitter = new NativeEventEmitter(RNOneSignal); this.eventListenerArrayMap = new Map(); // used for adders (multiple callbacks possible) diff --git a/src/events/NotificationWillDisplayEvent.ts b/src/events/NotificationWillDisplayEvent.ts index c042b5df..e8ab9caf 100644 --- a/src/events/NotificationWillDisplayEvent.ts +++ b/src/events/NotificationWillDisplayEvent.ts @@ -1,6 +1,6 @@ -import { NativeModules } from 'react-native'; +import NativeOneSignal from '../NativeOneSignal'; import OSNotification from '../OSNotification'; -const RNOneSignal = NativeModules.OneSignal; +const RNOneSignal = NativeOneSignal; export default class NotificationWillDisplayEvent { public notification: OSNotification; diff --git a/src/helpers.ts b/src/helpers.ts index 4bd3c22f..e811357a 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,11 +1,10 @@ import invariant from 'invariant'; -import type { NativeModule } from 'react-native'; export function isValidCallback(handler: Function) { invariant(typeof handler === 'function', 'Must provide a valid callback'); } -export function isNativeModuleLoaded(module: NativeModule): boolean { +export function isNativeModuleLoaded(module: object | null | undefined): boolean { if (module == null) { console.error( 'Could not load RNOneSignal native module. Make sure native dependencies are properly linked.', diff --git a/src/index.test.ts b/src/index.test.ts index 4d877938..f96941c6 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -319,7 +319,7 @@ describe('OneSignal', () => { test('should setup default without options', () => { OneSignal.LiveActivities.setupDefault(); expect(mockRNOneSignal.setupDefaultLiveActivity).toHaveBeenCalledWith( - undefined, + null, ); }); diff --git a/src/index.ts b/src/index.ts index 7bced605..bef1473b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ -import { NativeModules, Platform } from 'react-native'; +import { Platform } from 'react-native'; +import NativeOneSignal from './NativeOneSignal'; import { IN_APP_MESSAGE_CLICKED, IN_APP_MESSAGE_DID_DISMISS, @@ -39,7 +40,7 @@ import type { } from './types/subscription'; import type { UserChangedState, UserState } from './types/user'; -const RNOneSignal = NativeModules.OneSignal; +const RNOneSignal = NativeOneSignal; const eventManager = new EventManager(RNOneSignal); /// An enum that declares different types of log levels you can use with the OneSignal SDK, going from the least verbose (none) to verbose (print all comments). @@ -82,8 +83,8 @@ async function _addPushSubscriptionObserver() { }, ); - pushSub.id = await RNOneSignal.getPushSubscriptionId(); - pushSub.token = await RNOneSignal.getPushSubscriptionToken(); + pushSub.id = (await RNOneSignal.getPushSubscriptionId()) ?? ''; + pushSub.token = (await RNOneSignal.getPushSubscriptionToken()) ?? ''; pushSub.optedIn = await RNOneSignal.getOptedIn(); } @@ -170,11 +171,10 @@ export namespace OneSignal { export function enter( activityId: string, token: string, - handler: Function = () => {}, + handler: (result: Object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; - // Only Available on iOS if (Platform.OS === 'ios') { RNOneSignal.enterLiveActivity(activityId, token, handler); } @@ -187,7 +187,10 @@ export namespace OneSignal { * * @param activityId: The activity identifier the live activity on this device will no longer receive updates for. **/ - export function exit(activityId: string, handler: Function = () => {}) { + export function exit( + activityId: string, + handler: (result: Object) => void = () => {}, + ) { if (!isNativeModuleLoaded(RNOneSignal)) return; if (Platform.OS === 'ios') { @@ -250,7 +253,7 @@ export namespace OneSignal { if (!isNativeModuleLoaded(RNOneSignal)) return; if (Platform.OS === 'ios') { - RNOneSignal.setupDefaultLiveActivity(options); + RNOneSignal.setupDefaultLiveActivity(options ?? null); } } @@ -587,12 +590,13 @@ export namespace OneSignal { } /** Returns the local tags for the current user. */ - export function getTags(): Promise<{ [key: string]: string }> { + export async function getTags(): Promise<{ [key: string]: string }> { if (!isNativeModuleLoaded(RNOneSignal)) { return Promise.reject(new Error('OneSignal native module not loaded')); } - return RNOneSignal.getTags(); + const tags = await RNOneSignal.getTags(); + return tags as { [key: string]: string }; } /** From 5f24e3295de527b2a42e239b97d05535198f58a7 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 17:42:06 -0700 Subject: [PATCH 03/25] refactor(ios): standardize RCT method s ignatures --- .../ReactNativeOneSignalPackage.java | 11 +- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 103 +++++++++--------- src/NativeOneSignal.ts | 24 ++-- src/helpers.ts | 4 +- src/index.ts | 4 +- 5 files changed, 69 insertions(+), 77 deletions(-) diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java b/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java index 921525c4..b689a7ab 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java @@ -24,14 +24,9 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { @Override public Map getReactModuleInfos() { Map map = new HashMap<>(); - map.put(RNOneSignal.NAME, new ReactModuleInfo( - RNOneSignal.NAME, - RNOneSignal.NAME, - false, - false, - false, - true - )); + map.put( + RNOneSignal.NAME, + new ReactModuleInfo(RNOneSignal.NAME, RNOneSignal.NAME, false, false, false, true)); return map; } }; diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 1a3d1002..5869ac44 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -119,8 +119,9 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { RCT_EXPORT_METHOD(logout) { [OneSignal logout]; } -RCT_EXPORT_METHOD(enterLiveActivity : (NSString *)activityId withToken : ( - NSString *)token withResponse : (RCTResponseSenderBlock)callback) { +RCT_EXPORT_METHOD(enterLiveActivity : (NSString *)activityId + token : (NSString *)token + callback : (RCTResponseSenderBlock)callback) { [OneSignal.LiveActivities enter:activityId withToken:token withSuccess:^(NSDictionary *result) { @@ -131,8 +132,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { }]; } -RCT_EXPORT_METHOD(exitLiveActivity : (NSString *)activityId withResponse : ( - RCTResponseSenderBlock)callback) { +RCT_EXPORT_METHOD(exitLiveActivity : (NSString *)activityId + callback : (RCTResponseSenderBlock)callback) { [OneSignal.LiveActivities exit:activityId withSuccess:^(NSDictionary *result) { callback(@[ result ]); @@ -142,8 +143,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { }]; } -RCT_EXPORT_METHOD(setPushToStartToken : (NSString *) - activityType withToken : (NSString *)token) { +RCT_EXPORT_METHOD(setPushToStartToken : (NSString *)activityType + token : (NSString *)token) { #if !TARGET_OS_MACCATALYST NSError *err = nil; if (@available(iOS 17.2, *)) { @@ -211,9 +212,9 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { #endif } -RCT_EXPORT_METHOD(startDefaultLiveActivity : ( - NSString *)activityId withAttributes : (NSDictionary *_Nonnull)attributes - withContent : (NSDictionary *_Nonnull)content) { +RCT_EXPORT_METHOD(startDefaultLiveActivity : (NSString *)activityId + attributes : (NSDictionary *_Nonnull)attributes + content : (NSDictionary *_Nonnull)content) { #if !TARGET_OS_MACCATALYST if (@available(iOS 16.1, *)) { [OneSignalLiveActivitiesManagerImpl startDefault:activityId @@ -248,9 +249,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } // OneSignal.InAppMessages namespace methods -RCT_REMAP_METHOD(getPaused, - getPausedResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getPaused : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { resolve(@([OneSignal.InAppMessages paused])); } @@ -292,9 +292,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } // OneSignal.Location namespace methods -RCT_REMAP_METHOD(isLocationShared, - isLocationSharedResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(isLocationShared : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { resolve(@([OneSignal.Location isShared])); } @@ -307,29 +306,25 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } // OneSignal.Notifications namespace methods -RCT_REMAP_METHOD(hasNotificationPermission, - hasNotificationPermissionResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(hasNotificationPermission : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { resolve(@([OneSignal.Notifications permission])); } -RCT_REMAP_METHOD( - canRequestNotificationPermission, - canRequestNotificationPermissionResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(canRequestNotificationPermission : (RCTPromiseResolveBlock) + resolve + reject : (RCTPromiseRejectBlock)reject) { resolve(@([OneSignal.Notifications canRequestPermission])); } -RCT_REMAP_METHOD( - requestNotificationPermission, - withFallBackSettings : fallbackToSettings - requestNotificationPermissionResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(requestNotificationPermission : (BOOL)fallbackToSettings + resolve : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { [OneSignal.Notifications requestPermission:^(BOOL accepted) { resolve(@(accepted)); } - fallbackToSettings:[fallbackToSettings boolValue]]; + fallbackToSettings:fallbackToSettings]; } RCT_EXPORT_METHOD(registerForProvisionalAuthorization : (RCTResponseSenderBlock) @@ -356,9 +351,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } } -RCT_REMAP_METHOD(permissionNative, - getPermissionNativeResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(permissionNative : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { resolve(@([OneSignal.Notifications permissionNative])); } @@ -430,8 +424,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { [OneSignal.Session addUniqueOutcome:name]; } -RCT_EXPORT_METHOD(addOutcomeWithValue : (NSString *)name : (NSNumber *_Nonnull) - value) { +RCT_EXPORT_METHOD(addOutcomeWithValue : (NSString *)name + value : (NSNumber *_Nonnull)value) { [OneSignal.Session addOutcomeWithValue:name value:value]; } @@ -494,15 +488,14 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { [OneSignal.User removeTags:keys]; } -RCT_EXPORT_METHOD(getTags : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getTags : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { NSDictionary *tags = [OneSignal.User getTags]; resolve(tags); } -RCT_REMAP_METHOD(getOnesignalId, - getOnesignalIdResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getOnesignalId : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { NSString *onesignalId = OneSignal.User.onesignalId; if (onesignalId == nil || [onesignalId length] == 0) { @@ -512,9 +505,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } } -RCT_REMAP_METHOD(getExternalId, - getExternalIdResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getExternalId : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { NSString *externalId = OneSignal.User.externalId; if (externalId == nil || [externalId length] == 0) { @@ -524,7 +516,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } } -RCT_EXPORT_METHOD(addAlias : (NSString *)label : (NSString *)id) { +RCT_EXPORT_METHOD(addAlias : (NSString *)label id : (NSString *)id) { [OneSignal.User addAliasWithLabel:label id:id]; } @@ -541,15 +533,13 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } // OneSignal.User.pushSubscription namespace methods -RCT_REMAP_METHOD(getOptedIn, - getOptedInResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getOptedIn : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { resolve(@(OneSignal.User.pushSubscription.optedIn)); } -RCT_REMAP_METHOD(getPushSubscriptionId, - getPushSubscriptionIdResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getPushSubscriptionId : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { NSString *pushId = OneSignal.User.pushSubscription.id; if (pushId && ![pushId isEqualToString:@""]) { resolve(pushId); @@ -558,9 +548,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } } -RCT_REMAP_METHOD(getPushSubscriptionToken, - getPushSubscriptionTokenResolver : (RCTPromiseResolveBlock) - resolve rejecter : (RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getPushSubscriptionToken : (RCTPromiseResolveBlock)resolve + reject : (RCTPromiseRejectBlock)reject) { NSString *token = OneSignal.User.pushSubscription.token; if (token && ![token isEqualToString:@""]) { resolve(token); @@ -627,11 +616,19 @@ - (void)removeUserStateObserver { } } -RCT_EXPORT_METHOD(trackEvent : (NSString *)name withProperties : ( - NSDictionary *_Nullable)properties) { +RCT_EXPORT_METHOD(trackEvent : (NSString *)name + properties : (NSDictionary *_Nullable)properties) { [OneSignal.User trackEventWithName:name properties:properties]; } +RCT_EXPORT_METHOD(addListener : (NSString *)eventName) { + // Required for NativeEventEmitter under the New Architecture. +} + +RCT_EXPORT_METHOD(removeListeners : (double)count) { + // Required for NativeEventEmitter under the New Architecture. +} + #ifdef RCT_NEW_ARCH_ENABLED - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts index 22f0ba7d..b482bfd9 100644 --- a/src/NativeOneSignal.ts +++ b/src/NativeOneSignal.ts @@ -17,19 +17,19 @@ export interface Spec extends TurboModule { enterLiveActivity( activityId: string, token: string, - callback: (result: Object) => void, + callback: (result: object) => void, ): void; exitLiveActivity( activityId: string, - callback: (result: Object) => void, + callback: (result: object) => void, ): void; setPushToStartToken(activityType: string, token: string): void; removePushToStartToken(activityType: string): void; - setupDefaultLiveActivity(options: Object | null): void; + setupDefaultLiveActivity(options: object | null): void; startDefaultLiveActivity( activityId: string, - attributes: Object, - content: Object, + attributes: object, + content: object, ): void; // Push Subscription @@ -46,7 +46,7 @@ export interface Spec extends TurboModule { getExternalId(): Promise; setLanguage(language: string): void; addAlias(label: string, id: string): void; - addAliases(aliases: Object): void; + addAliases(aliases: object): void; removeAlias(label: string): void; removeAliases(labels: string[]): void; addEmail(email: string): void; @@ -54,16 +54,14 @@ export interface Spec extends TurboModule { addSms(smsNumber: string): void; removeSms(smsNumber: string): void; addTag(key: string, value: string): void; - addTags(tags: Object): void; + addTags(tags: object): void; removeTags(keys: string[]): void; - getTags(): Promise; - trackEvent(name: string, properties: Object): void; + getTags(): Promise; + trackEvent(name: string, properties: object): void; // Notifications hasNotificationPermission(): Promise; - requestNotificationPermission( - fallbackToSettings: boolean, - ): Promise; + requestNotificationPermission(fallbackToSettings: boolean): Promise; canRequestNotificationPermission(): Promise; registerForProvisionalAuthorization( callback: (accepted: boolean) => void, @@ -81,7 +79,7 @@ export interface Spec extends TurboModule { // In-App Messages addInAppMessageClickListener(): void; addInAppMessagesLifecycleListener(): void; - addTriggers(triggers: Object): void; + addTriggers(triggers: object): void; removeTrigger(key: string): void; removeTriggers(keys: string[]): void; clearTriggers(): void; diff --git a/src/helpers.ts b/src/helpers.ts index e811357a..604b62b6 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -4,7 +4,9 @@ export function isValidCallback(handler: Function) { invariant(typeof handler === 'function', 'Must provide a valid callback'); } -export function isNativeModuleLoaded(module: object | null | undefined): boolean { +export function isNativeModuleLoaded( + module: object | null | undefined, +): boolean { if (module == null) { console.error( 'Could not load RNOneSignal native module. Make sure native dependencies are properly linked.', diff --git a/src/index.ts b/src/index.ts index bef1473b..61b968dd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -171,7 +171,7 @@ export namespace OneSignal { export function enter( activityId: string, token: string, - handler: (result: Object) => void = () => {}, + handler: (result: object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; @@ -189,7 +189,7 @@ export namespace OneSignal { **/ export function exit( activityId: string, - handler: (result: Object) => void = () => {}, + handler: (result: object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; From 984816914a3faf3bf831b273a0cff5ec2838f11a Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 17:52:52 -0700 Subject: [PATCH 04/25] refactor: standardize object types to Object --- src/NativeOneSignal.ts | 20 ++++++++++---------- src/index.ts | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts index b482bfd9..485a29b8 100644 --- a/src/NativeOneSignal.ts +++ b/src/NativeOneSignal.ts @@ -17,19 +17,19 @@ export interface Spec extends TurboModule { enterLiveActivity( activityId: string, token: string, - callback: (result: object) => void, + callback: (result: Object) => void, ): void; exitLiveActivity( activityId: string, - callback: (result: object) => void, + callback: (result: Object) => void, ): void; setPushToStartToken(activityType: string, token: string): void; removePushToStartToken(activityType: string): void; - setupDefaultLiveActivity(options: object | null): void; + setupDefaultLiveActivity(options: Object | null): void; startDefaultLiveActivity( activityId: string, - attributes: object, - content: object, + attributes: Object, + content: Object, ): void; // Push Subscription @@ -46,7 +46,7 @@ export interface Spec extends TurboModule { getExternalId(): Promise; setLanguage(language: string): void; addAlias(label: string, id: string): void; - addAliases(aliases: object): void; + addAliases(aliases: Object): void; removeAlias(label: string): void; removeAliases(labels: string[]): void; addEmail(email: string): void; @@ -54,10 +54,10 @@ export interface Spec extends TurboModule { addSms(smsNumber: string): void; removeSms(smsNumber: string): void; addTag(key: string, value: string): void; - addTags(tags: object): void; + addTags(tags: Object): void; removeTags(keys: string[]): void; - getTags(): Promise; - trackEvent(name: string, properties: object): void; + getTags(): Promise; + trackEvent(name: string, properties: Object): void; // Notifications hasNotificationPermission(): Promise; @@ -79,7 +79,7 @@ export interface Spec extends TurboModule { // In-App Messages addInAppMessageClickListener(): void; addInAppMessagesLifecycleListener(): void; - addTriggers(triggers: object): void; + addTriggers(triggers: Object): void; removeTrigger(key: string): void; removeTriggers(keys: string[]): void; clearTriggers(): void; diff --git a/src/index.ts b/src/index.ts index 61b968dd..bef1473b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -171,7 +171,7 @@ export namespace OneSignal { export function enter( activityId: string, token: string, - handler: (result: object) => void = () => {}, + handler: (result: Object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; @@ -189,7 +189,7 @@ export namespace OneSignal { **/ export function exit( activityId: string, - handler: (result: object) => void = () => {}, + handler: (result: Object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; From 409be4a358a387466e55a7838e4be919f3d9c11c Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 18:40:24 -0700 Subject: [PATCH 05/25] refactor: migrate from NativeEventEmitter to TurboModule events --- __mocks__/react-native.ts | 50 +--- .../rnonesignalandroid/RNOneSignal.java | 52 +---- ios/RCTOneSignal/RCTOneSignalEventEmitter.h | 2 +- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 45 ++-- package.json | 2 +- src/NativeOneSignal.ts | 16 +- src/events/EventManager.test.ts | 218 ++++++++---------- src/events/EventManager.ts | 141 +++++------ 8 files changed, 215 insertions(+), 311 deletions(-) diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index c28ca5f1..2af0ea96 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -1,27 +1,7 @@ import { vi } from 'vitest'; -export const createEmitterSubscriptionMock = ( - eventName: string, - callback: (payload: unknown) => void, -) => ({ - remove: vi.fn(), - emitter: { - addListener: vi.fn(), - removeAllListeners: vi.fn(), - listenerCount: vi.fn(() => 1), - emit: vi.fn(), - }, - listener: () => callback, - context: undefined, - eventType: eventName, - key: 0, - subscriber: { - addSubscription: vi.fn(), - removeSubscription: vi.fn(), - removeAllSubscriptions: vi.fn(), - getSubscriptionsForType: vi.fn(), - }, -}); +const createEventEmitterMock = () => + vi.fn(() => ({ remove: vi.fn() })); const mockRNOneSignal = { initialize: vi.fn(), @@ -87,6 +67,16 @@ const mockRNOneSignal = { displayNotification: vi.fn(), preventDefault: vi.fn(), trackEvent: vi.fn(), + onPermissionChanged: createEventEmitterMock(), + onSubscriptionChanged: createEventEmitterMock(), + onUserStateChanged: createEventEmitterMock(), + onNotificationWillDisplay: createEventEmitterMock(), + onNotificationClicked: createEventEmitterMock(), + onInAppMessageClicked: createEventEmitterMock(), + onInAppMessageWillDisplay: createEventEmitterMock(), + onInAppMessageDidDisplay: createEventEmitterMock(), + onInAppMessageWillDismiss: createEventEmitterMock(), + onInAppMessageDidDismiss: createEventEmitterMock(), }; const mockPlatform = { @@ -104,19 +94,3 @@ export const TurboModuleRegistry = { export const Platform = mockPlatform; export { mockPlatform, mockRNOneSignal }; - -export class NativeEventEmitter { - constructor(_nativeModule: typeof mockRNOneSignal) {} - - addListener(eventName: string, callback: (payload: unknown) => void) { - return createEmitterSubscriptionMock(eventName, callback); - } - - removeListener(_eventName: string, _callback: (payload: unknown) => void) { - // Mock implementation - } - - removeAllListeners(_eventName: string) { - // Mock implementation - } -} diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java index aeb191ac..97e5efc8 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -42,12 +42,10 @@ of this software and associated documentation files (the "Software"), to deal import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.modules.core.DeviceEventManagerModule; import com.onesignal.Continue; import com.onesignal.OneSignal; import com.onesignal.common.OneSignalWrapper; @@ -84,7 +82,6 @@ public class RNOneSignal extends NativeOneSignalSpec public static final String NAME = "OneSignal"; private ReactApplicationContext mReactApplicationContext; - private ReactContext mReactContext; private boolean oneSignalInitDone; private boolean hasSetPermissionObserver = false; @@ -106,8 +103,7 @@ public class RNOneSignal extends NativeOneSignalSpec @Override public void onClick(IInAppMessageClickEvent event) { try { - sendEvent( - "OneSignal-inAppMessageClicked", + emitOnInAppMessageClicked( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageClickEventToMap(event))); } catch (JSONException e) { e.printStackTrace(); @@ -119,8 +115,7 @@ public void onClick(IInAppMessageClickEvent event) { @Override public void onWillDisplay(IInAppMessageWillDisplayEvent event) { try { - sendEvent( - "OneSignal-inAppMessageWillDisplay", + emitOnInAppMessageWillDisplay( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageWillDisplayEventToMap(event))); } catch (JSONException e) { e.printStackTrace(); @@ -130,8 +125,7 @@ public void onWillDisplay(IInAppMessageWillDisplayEvent event) { @Override public void onDidDisplay(IInAppMessageDidDisplayEvent event) { try { - sendEvent( - "OneSignal-inAppMessageDidDisplay", + emitOnInAppMessageDidDisplay( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageDidDisplayEventToMap(event))); } catch (JSONException e) { e.printStackTrace(); @@ -141,8 +135,7 @@ public void onDidDisplay(IInAppMessageDidDisplayEvent event) { @Override public void onWillDismiss(IInAppMessageWillDismissEvent event) { try { - sendEvent( - "OneSignal-inAppMessageWillDismiss", + emitOnInAppMessageWillDismiss( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageWillDismissEventToMap(event))); } catch (JSONException e) { e.printStackTrace(); @@ -152,8 +145,7 @@ public void onWillDismiss(IInAppMessageWillDismissEvent event) { @Override public void onDidDismiss(IInAppMessageDidDismissEvent event) { try { - sendEvent( - "OneSignal-inAppMessageDidDismiss", + emitOnInAppMessageDidDismiss( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageDidDismissEventToMap(event))); } catch (JSONException e) { e.printStackTrace(); @@ -165,8 +157,7 @@ public void onDidDismiss(IInAppMessageDidDismissEvent event) { @Override public void onClick(INotificationClickEvent event) { try { - sendEvent( - "OneSignal-notificationClicked", + emitOnNotificationClicked( RNUtils.convertHashMapToWritableMap(RNUtils.convertNotificationClickEventToMap(event))); } catch (JSONException e) { e.printStackTrace(); @@ -202,17 +193,10 @@ private void removeObservers() { } } - private void sendEvent(String eventName, Object params) { - mReactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } - public RNOneSignal(ReactApplicationContext reactContext) { super(reactContext); mReactApplicationContext = reactContext; - mReactContext = reactContext; - mReactContext.addLifecycleEventListener(this); + mReactApplicationContext.addLifecycleEventListener(this); notificationWillDisplayCache = new HashMap(); preventDefaultCache = new HashMap(); @@ -383,8 +367,7 @@ public void onWillDisplay(INotificationWillDisplayEvent event) { event.preventDefault(); try { - sendEvent( - "OneSignal-notificationWillDisplayInForeground", + emitOnNotificationWillDisplay( RNUtils.convertHashMapToWritableMap(RNUtils.convertNotificationToMap(notification))); try { @@ -442,8 +425,7 @@ public void removePermissionObserver() { @Override public void onNotificationPermissionChange(boolean permission) { try { - sendEvent( - "OneSignal-permissionChanged", + emitOnPermissionChanged( RNUtils.convertHashMapToWritableMap(RNUtils.convertPermissionToMap(permission))); Logging.debug("Sending permission change event", null); } catch (JSONException e) { @@ -588,8 +570,7 @@ public void addPushSubscriptionObserver() { @Override public void onPushSubscriptionChange(PushSubscriptionChangedState pushSubscriptionChangedState) { try { - sendEvent( - "OneSignal-subscriptionChanged", + emitOnSubscriptionChanged( RNUtils.convertHashMapToWritableMap( RNUtils.convertPushSubscriptionChangedStateToMap(pushSubscriptionChangedState))); Logging.debug("Sending subscription change event", null); @@ -734,8 +715,7 @@ public void addUserStateObserver() { @Override public void onUserStateChange(UserChangedState state) { try { - sendEvent( - "OneSignal-userStateChanged", + emitOnUserStateChanged( RNUtils.convertHashMapToWritableMap(RNUtils.convertUserChangedStateToMap(state))); Logging.debug("Sending user state change event", null); } catch (JSONException e) { @@ -750,16 +730,6 @@ public void removeUserStateObserver() { } } - @Override - public void addListener(String eventName) { - // Required for RN built in Event Emitter Calls. - } - - @Override - public void removeListeners(double count) { - // Required for RN built in Event Emitter Calls. - } - @Override public void trackEvent(String name, @Nullable ReadableMap properties) { OneSignal.getUser().trackEvent(name, properties != null ? properties.toHashMap() : new HashMap<>()); diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h index 81b949ab..2c1f0cb6 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h @@ -42,7 +42,7 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { #define OSEventString(enum) [OSNotificationEventTypesArray objectAtIndex:enum] #ifdef RCT_NEW_ARCH_ENABLED -@interface RCTOneSignalEventEmitter : RCTEventEmitter +@interface RCTOneSignalEventEmitter : NativeOneSignalSpecBase #else @interface RCTOneSignalEventEmitter : RCTEventEmitter #endif diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 5869ac44..d02968a6 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -97,7 +97,35 @@ - (void)emitEvent:(NSNotification *)notification { if (!_hasListeners) return; - [self sendEventWithName:notification.name body:notification.userInfo]; + NSString *name = notification.name; + NSDictionary *body = notification.userInfo; + +#ifdef RCT_NEW_ARCH_ENABLED + if ([name isEqualToString:OSEventString(PermissionChanged)]) { + [self emitOnPermissionChanged:body]; + } else if ([name isEqualToString:OSEventString(SubscriptionChanged)]) { + [self emitOnSubscriptionChanged:body]; + } else if ([name isEqualToString:OSEventString(UserStateChanged)]) { + [self emitOnUserStateChanged:body]; + } else if ([name isEqualToString: + OSEventString(NotificationWillDisplayInForeground)]) { + [self emitOnNotificationWillDisplay:body]; + } else if ([name isEqualToString:OSEventString(NotificationClicked)]) { + [self emitOnNotificationClicked:body]; + } else if ([name isEqualToString:OSEventString(InAppMessageClicked)]) { + [self emitOnInAppMessageClicked:body]; + } else if ([name isEqualToString:OSEventString(InAppMessageWillDisplay)]) { + [self emitOnInAppMessageWillDisplay:body]; + } else if ([name isEqualToString:OSEventString(InAppMessageDidDisplay)]) { + [self emitOnInAppMessageDidDisplay:body]; + } else if ([name isEqualToString:OSEventString(InAppMessageWillDismiss)]) { + [self emitOnInAppMessageWillDismiss:body]; + } else if ([name isEqualToString:OSEventString(InAppMessageDidDismiss)]) { + [self emitOnInAppMessageDidDismiss:body]; + } +#else + [self sendEventWithName:name body:body]; +#endif } + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { @@ -621,19 +649,4 @@ - (void)removeUserStateObserver { [OneSignal.User trackEventWithName:name properties:properties]; } -RCT_EXPORT_METHOD(addListener : (NSString *)eventName) { - // Required for NativeEventEmitter under the New Architecture. -} - -RCT_EXPORT_METHOD(removeListeners : (double)count) { - // Required for NativeEventEmitter under the New Architecture. -} - -#ifdef RCT_NEW_ARCH_ENABLED -- (std::shared_ptr)getTurboModule: - (const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); -} -#endif - @end diff --git a/package.json b/package.json index ce23a1ef..4e420acd 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,6 @@ } }, "peerDependencies": { - "react-native": ">=0.71.0" + "react-native": ">=0.76.0" } } diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts index 485a29b8..75349277 100644 --- a/src/NativeOneSignal.ts +++ b/src/NativeOneSignal.ts @@ -1,4 +1,4 @@ -import type { TurboModule } from 'react-native'; +import type { TurboModule, CodegenTypes } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { @@ -96,9 +96,17 @@ export interface Spec extends TurboModule { addUniqueOutcome(name: string): void; addOutcomeWithValue(name: string, value: number): void; - // Events (required for NativeEventEmitter) - addListener(eventName: string): void; - removeListeners(count: number): void; + // Events + readonly onPermissionChanged: CodegenTypes.EventEmitter; + readonly onSubscriptionChanged: CodegenTypes.EventEmitter; + readonly onUserStateChanged: CodegenTypes.EventEmitter; + readonly onNotificationWillDisplay: CodegenTypes.EventEmitter; + readonly onNotificationClicked: CodegenTypes.EventEmitter; + readonly onInAppMessageClicked: CodegenTypes.EventEmitter; + readonly onInAppMessageWillDisplay: CodegenTypes.EventEmitter; + readonly onInAppMessageDidDisplay: CodegenTypes.EventEmitter; + readonly onInAppMessageWillDismiss: CodegenTypes.EventEmitter; + readonly onInAppMessageDidDismiss: CodegenTypes.EventEmitter; } export default TurboModuleRegistry.getEnforcing('OneSignal'); diff --git a/src/events/EventManager.test.ts b/src/events/EventManager.test.ts index c307bc2b..93bf12be 100644 --- a/src/events/EventManager.test.ts +++ b/src/events/EventManager.test.ts @@ -1,5 +1,3 @@ -import { NativeEventEmitter } from 'react-native'; -import { createEmitterSubscriptionMock } from '../../__mocks__/react-native'; import { IN_APP_MESSAGE_CLICKED, IN_APP_MESSAGE_DID_DISMISS, @@ -16,92 +14,82 @@ import OSNotification from '../OSNotification'; import type { NotificationClickEvent } from '../types/notificationEvents'; import type { PushSubscriptionChangedState } from '../types/subscription'; import type { UserChangedState } from '../types/user'; -import EventManager, { type RawEventListenerMap } from './EventManager'; +import EventManager from './EventManager'; import NotificationWillDisplayEvent from './NotificationWillDisplayEvent'; -describe('EventManager', () => { - let eventManager: EventManager; - let mockNativeModule: any; - let eventCallbacks: Map void>; +function createMockNativeModule() { + const callbacks = new Map void>(); - const getCallback = ( - eventName: K, - ): RawEventListenerMap[K] | undefined => { - return eventCallbacks.get(eventName) as RawEventListenerMap[K] | undefined; + const makeEmitter = (name: string) => + vi.fn((cb: (payload: unknown) => void) => { + callbacks.set(name, cb); + return { remove: vi.fn() }; + }); + + const module = { + onPermissionChanged: makeEmitter('onPermissionChanged'), + onSubscriptionChanged: makeEmitter('onSubscriptionChanged'), + onUserStateChanged: makeEmitter('onUserStateChanged'), + onNotificationWillDisplay: makeEmitter('onNotificationWillDisplay'), + onNotificationClicked: makeEmitter('onNotificationClicked'), + onInAppMessageClicked: makeEmitter('onInAppMessageClicked'), + onInAppMessageWillDisplay: makeEmitter('onInAppMessageWillDisplay'), + onInAppMessageDidDisplay: makeEmitter('onInAppMessageDidDisplay'), + onInAppMessageWillDismiss: makeEmitter('onInAppMessageWillDismiss'), + onInAppMessageDidDismiss: makeEmitter('onInAppMessageDidDismiss'), }; + return { module, callbacks }; +} + +describe('EventManager', () => { + let eventManager: EventManager; + let mockModule: ReturnType['module']; + let callbacks: Map void>; + beforeEach(() => { - eventCallbacks = new Map(); - - mockNativeModule = { - addListener: vi.fn(), - removeListener: vi.fn(), - }; - - // Spy on NativeEventEmitter.prototype.addListener to capture callbacks - vi.spyOn(NativeEventEmitter.prototype, 'addListener').mockImplementation( - (eventName: string, callback: (payload: any) => void) => { - eventCallbacks.set(eventName, callback); - return createEmitterSubscriptionMock(eventName, callback) as never; - }, - ); - - eventManager = new EventManager(mockNativeModule); + const mock = createMockNativeModule(); + mockModule = mock.module; + callbacks = mock.callbacks; + eventManager = new EventManager(mockModule as never); }); describe('constructor', () => { - test('should initialize with all required properties and listeners', () => { + test('should initialize with all required properties', () => { expect(eventManager).toBeDefined(); - expect(eventManager['RNOneSignal']).toBe(mockNativeModule); - expect(eventManager['oneSignalEventEmitter']).toBeDefined(); + expect(eventManager['RNOneSignal']).toBe(mockModule); expect(eventManager['eventListenerArrayMap']).toBeInstanceOf(Map); - - const listeners = eventManager['listeners']; - const expectedEvents = [ - PERMISSION_CHANGED, - SUBSCRIPTION_CHANGED, - USER_STATE_CHANGED, - NOTIFICATION_WILL_DISPLAY, - NOTIFICATION_CLICKED, - IN_APP_MESSAGE_CLICKED, - IN_APP_MESSAGE_WILL_DISPLAY, - IN_APP_MESSAGE_WILL_DISMISS, - IN_APP_MESSAGE_DID_DISMISS, - IN_APP_MESSAGE_DID_DISPLAY, - ]; - - expectedEvents.forEach((eventName) => { - expect(listeners[eventName]).toBeDefined(); - }); - - // Verify that eventCallbacks were populated during setup - expect(eventCallbacks.size).toBe(10); }); }); describe('setupListeners', () => { - test('should register all event listeners with NativeEventEmitter', () => { - const eventList = [ - PERMISSION_CHANGED, - SUBSCRIPTION_CHANGED, - USER_STATE_CHANGED, - NOTIFICATION_WILL_DISPLAY, - NOTIFICATION_CLICKED, - IN_APP_MESSAGE_CLICKED, - IN_APP_MESSAGE_WILL_DISPLAY, - IN_APP_MESSAGE_WILL_DISMISS, - IN_APP_MESSAGE_DID_DISMISS, - IN_APP_MESSAGE_DID_DISPLAY, - ]; - - eventList.forEach((eventName) => { - expect(eventCallbacks.has(eventName)).toBe(true); + test('should subscribe to all 10 event emitters', () => { + expect(mockModule.onPermissionChanged).toHaveBeenCalledOnce(); + expect(mockModule.onSubscriptionChanged).toHaveBeenCalledOnce(); + expect(mockModule.onUserStateChanged).toHaveBeenCalledOnce(); + expect(mockModule.onNotificationWillDisplay).toHaveBeenCalledOnce(); + expect(mockModule.onNotificationClicked).toHaveBeenCalledOnce(); + expect(mockModule.onInAppMessageClicked).toHaveBeenCalledOnce(); + expect(mockModule.onInAppMessageWillDisplay).toHaveBeenCalledOnce(); + expect(mockModule.onInAppMessageDidDisplay).toHaveBeenCalledOnce(); + expect(mockModule.onInAppMessageWillDismiss).toHaveBeenCalledOnce(); + expect(mockModule.onInAppMessageDidDismiss).toHaveBeenCalledOnce(); + + expect(callbacks.size).toBe(10); + }); + + test('should store native subscriptions', () => { + const subscriptions = eventManager['nativeSubscriptions']; + expect(subscriptions.length).toBe(10); + subscriptions.forEach((sub) => { + expect(sub.remove).toBeDefined(); }); }); test('should not setup listeners if RNOneSignal is null', () => { - new EventManager(null as any); - expect(mockNativeModule.addListener).not.toHaveBeenCalled(); + const { module: freshModule } = createMockNativeModule(); + new EventManager(null as never); + expect(freshModule.onPermissionChanged).not.toHaveBeenCalled(); }); }); @@ -178,7 +166,8 @@ describe('EventManager', () => { test('should do nothing if event does not exist', () => { const handler = vi.fn(); expect(() => { - eventManager.removeEventListener('non-existent-event' as any, handler); + // @ts-expect-error testing invalid event name + eventManager.removeEventListener('non-existent-event', handler); }).not.toThrow(); }); @@ -199,20 +188,13 @@ describe('EventManager', () => { }); }); - describe('generateEventListener', () => { - test('should return an EmitterSubscription', () => { - const listener = - eventManager['generateEventListener'](PERMISSION_CHANGED); - expect(listener).toBeDefined(); - expect(listener.remove).toBeDefined(); - }); - + describe('event dispatching', () => { test('should handle NOTIFICATION_WILL_DISPLAY events', () => { const handler = vi.fn(); eventManager.addEventListener(NOTIFICATION_WILL_DISPLAY, handler); - const callback = getCallback(NOTIFICATION_WILL_DISPLAY); - callback!(rawWillDisplayPayload); + const emitCallback = callbacks.get('onNotificationWillDisplay')!; + emitCallback(rawWillDisplayPayload); expect(handler).toHaveBeenCalled(); const receivedEvent = handler.mock.calls[0][0]; @@ -223,20 +205,18 @@ describe('EventManager', () => { const handler = vi.fn(); eventManager.addEventListener(PERMISSION_CHANGED, handler); - const payload = getRawPermissionChangedPayload(true); - const callback = getCallback(PERMISSION_CHANGED); - callback!(payload); + const emitCallback = callbacks.get('onPermissionChanged')!; + emitCallback(getRawPermissionChangedPayload(true)); expect(handler).toHaveBeenCalledWith(true); }); test('should handle generic events with object payload', () => { const handler = vi.fn(); - eventManager.addEventListener(SUBSCRIPTION_CHANGED, handler); - const callback = getCallback(SUBSCRIPTION_CHANGED); - callback!(pushChangedPayload); + const emitCallback = callbacks.get('onSubscriptionChanged')!; + emitCallback(pushChangedPayload); expect(handler).toHaveBeenCalledWith(pushChangedPayload); }); @@ -250,11 +230,11 @@ describe('EventManager', () => { eventManager.addEventListener(USER_STATE_CHANGED, handler2); eventManager.addEventListener(USER_STATE_CHANGED, handler3); - const callback = getCallback(USER_STATE_CHANGED); + const emitCallback = callbacks.get('onUserStateChanged')!; const payload = { current: { onesignalId: '123', externalId: '456' }, } satisfies UserChangedState; - callback!(payload); + emitCallback(payload); expect(handler1).toHaveBeenCalledWith(payload); expect(handler2).toHaveBeenCalledWith(payload); @@ -262,10 +242,10 @@ describe('EventManager', () => { }); test('should do nothing if no handlers are registered', () => { - const callback = getCallback(IN_APP_MESSAGE_WILL_DISPLAY); + const emitCallback = callbacks.get('onInAppMessageWillDisplay')!; expect(() => { - callback!({ message: { messageId: 'msg-123' } }); + emitCallback({ message: { messageId: 'msg-123' } }); }).not.toThrow(); }); @@ -278,8 +258,8 @@ describe('EventManager', () => { eventManager.addEventListener(IN_APP_MESSAGE_CLICKED, handler); - const callback = getCallback(IN_APP_MESSAGE_CLICKED); - callback!(payload); + const emitCallback = callbacks.get('onInAppMessageClicked')!; + emitCallback(payload); expect(handler).toHaveBeenCalledWith(payload); }); @@ -290,8 +270,8 @@ describe('EventManager', () => { eventManager.addEventListener(IN_APP_MESSAGE_WILL_DISPLAY, handler); - const callback = getCallback(IN_APP_MESSAGE_WILL_DISPLAY); - callback!(payload); + const emitCallback = callbacks.get('onInAppMessageWillDisplay')!; + emitCallback(payload); expect(handler).toHaveBeenCalledWith(payload); }); @@ -302,8 +282,8 @@ describe('EventManager', () => { eventManager.addEventListener(IN_APP_MESSAGE_DID_DISPLAY, handler); - const callback = getCallback(IN_APP_MESSAGE_DID_DISPLAY); - callback!(payload); + const emitCallback = callbacks.get('onInAppMessageDidDisplay')!; + emitCallback(payload); expect(handler).toHaveBeenCalledWith(payload); }); @@ -314,8 +294,8 @@ describe('EventManager', () => { eventManager.addEventListener(IN_APP_MESSAGE_WILL_DISMISS, handler); - const callback = getCallback(IN_APP_MESSAGE_WILL_DISMISS); - callback!(payload); + const emitCallback = callbacks.get('onInAppMessageWillDismiss')!; + emitCallback(payload); expect(handler).toHaveBeenCalledWith(payload); }); @@ -326,8 +306,8 @@ describe('EventManager', () => { eventManager.addEventListener(IN_APP_MESSAGE_DID_DISMISS, handler); - const callback = getCallback(IN_APP_MESSAGE_DID_DISMISS); - callback!(payload); + const emitCallback = callbacks.get('onInAppMessageDidDismiss')!; + emitCallback(payload); expect(handler).toHaveBeenCalledWith(payload); }); @@ -345,8 +325,8 @@ describe('EventManager', () => { eventManager.addEventListener(NOTIFICATION_CLICKED, handler); - const callback = getCallback(NOTIFICATION_CLICKED); - callback!(payload); + const emitCallback = callbacks.get('onNotificationClicked')!; + emitCallback(payload); expect(handler).toHaveBeenCalledWith(payload); }); @@ -357,27 +337,21 @@ describe('EventManager', () => { const handler1 = vi.fn(); const handler2 = vi.fn(); - // Add handlers eventManager.addEventListener(PERMISSION_CHANGED, handler1); eventManager.addEventListener(PERMISSION_CHANGED, handler2); - // Trigger event - const callback = getCallback(PERMISSION_CHANGED); - const payload = getRawPermissionChangedPayload(true); - callback!(payload); + const emitCallback = callbacks.get('onPermissionChanged')!; + emitCallback(getRawPermissionChangedPayload(true)); expect(handler1).toHaveBeenCalledWith(true); expect(handler2).toHaveBeenCalledWith(true); - // Remove one handler eventManager.removeEventListener(PERMISSION_CHANGED, handler1); - // Reset mocks handler1.mockClear(); handler2.mockClear(); - // Trigger event again - callback!(getRawPermissionChangedPayload(false)); + emitCallback(getRawPermissionChangedPayload(false)); expect(handler1).not.toHaveBeenCalled(); expect(handler2).toHaveBeenCalledWith(false); @@ -395,16 +369,11 @@ describe('EventManager', () => { notificationWillDisplayHandler, ); - // Get callbacks - const permissionCallback = getCallback(PERMISSION_CHANGED); - const subscriptionCallback = getCallback(SUBSCRIPTION_CHANGED); - const notificationCallback = getCallback(NOTIFICATION_WILL_DISPLAY); - - // Trigger different event types - const permissionPayload = getRawPermissionChangedPayload(true); - permissionCallback!(permissionPayload); - subscriptionCallback!(pushChangedPayload); - notificationCallback!(rawWillDisplayPayload); + callbacks.get('onPermissionChanged')!( + getRawPermissionChangedPayload(true), + ); + callbacks.get('onSubscriptionChanged')!(pushChangedPayload); + callbacks.get('onNotificationWillDisplay')!(rawWillDisplayPayload); expect(permissionHandler).toHaveBeenCalledWith(true); expect(subscriptionHandler).toHaveBeenCalledWith(pushChangedPayload); @@ -444,9 +413,9 @@ describe('EventManager', () => { eventManager.addEventListener(SUBSCRIPTION_CHANGED, handler2); eventManager.addEventListener(SUBSCRIPTION_CHANGED, handler3); - const callback = getCallback(SUBSCRIPTION_CHANGED); + const emitCallback = callbacks.get('onSubscriptionChanged')!; - callback!(pushChangedPayload); + emitCallback(pushChangedPayload); expect(handler1).toHaveBeenCalledWith(pushChangedPayload); expect(handler2).toHaveBeenCalledWith(pushChangedPayload); expect(handler3).toHaveBeenCalledWith(pushChangedPayload); @@ -456,7 +425,7 @@ describe('EventManager', () => { handler2.mockClear(); handler3.mockClear(); - callback!(pushChangedPayload); + emitCallback(pushChangedPayload); expect(handler1).toHaveBeenCalledWith(pushChangedPayload); expect(handler2).not.toHaveBeenCalled(); expect(handler3).toHaveBeenCalledWith(pushChangedPayload); @@ -464,7 +433,6 @@ describe('EventManager', () => { }); }); -// helper payloads const getRawPermissionChangedPayload = (permission: boolean) => ({ permission: permission, }); diff --git a/src/events/EventManager.ts b/src/events/EventManager.ts index ad1855cc..04b514dc 100644 --- a/src/events/EventManager.ts +++ b/src/events/EventManager.ts @@ -1,4 +1,4 @@ -import { type EmitterSubscription, NativeEventEmitter } from 'react-native'; +import type { EventSubscription } from 'react-native'; import type { Spec } from '../NativeOneSignal'; import { IN_APP_MESSAGE_CLICKED, @@ -38,79 +38,73 @@ export interface EventListenerMap { [IN_APP_MESSAGE_DID_DISPLAY]: (event: InAppMessageDidDisplayEvent) => void; } -// Internal event listeners that connect to the native modules then get -// transformed (via generateEventListener) into the EventListenerMap types -type RawNotificationOverrides = { - [PERMISSION_CHANGED]: (payload: { permission: boolean }) => void; - [NOTIFICATION_WILL_DISPLAY]: (payload: OSNotification) => void; -}; -export type RawEventListenerMap = Omit< - EventListenerMap, - keyof RawNotificationOverrides -> & - RawNotificationOverrides; - -const eventList = [ - PERMISSION_CHANGED, - SUBSCRIPTION_CHANGED, - USER_STATE_CHANGED, - NOTIFICATION_WILL_DISPLAY, - NOTIFICATION_CLICKED, - IN_APP_MESSAGE_CLICKED, - IN_APP_MESSAGE_WILL_DISPLAY, - IN_APP_MESSAGE_WILL_DISMISS, - IN_APP_MESSAGE_DID_DISMISS, - IN_APP_MESSAGE_DID_DISPLAY, -] as const; - export default class EventManager { private RNOneSignal: Spec; - private oneSignalEventEmitter: NativeEventEmitter; - private eventListenerArrayMap: Map void>>; - private listeners: { [key: string]: EmitterSubscription }; + private eventListenerArrayMap: Map void>>; + private nativeSubscriptions: EventSubscription[]; constructor(RNOneSignal: Spec) { this.RNOneSignal = RNOneSignal; - this.oneSignalEventEmitter = new NativeEventEmitter(RNOneSignal); - this.eventListenerArrayMap = new Map(); // used for adders (multiple callbacks possible) - this.listeners = {}; + this.eventListenerArrayMap = new Map(); + this.nativeSubscriptions = []; this.setupListeners(); } setupListeners() { - // set up the event emitter and listeners - if (this.RNOneSignal != null) { - for (let i = 0; i < eventList.length; i++) { - let eventName = eventList[i]; - this.listeners[eventName] = this.generateEventListener(eventName); - } - } + if (this.RNOneSignal == null) return; + + this.nativeSubscriptions.push( + this.RNOneSignal.onPermissionChanged((payload) => { + const typed = payload as { permission: boolean }; + this.dispatchHandlers(PERMISSION_CHANGED, typed.permission); + }), + this.RNOneSignal.onSubscriptionChanged((payload) => { + this.dispatchHandlers(SUBSCRIPTION_CHANGED, payload); + }), + this.RNOneSignal.onUserStateChanged((payload) => { + this.dispatchHandlers(USER_STATE_CHANGED, payload); + }), + this.RNOneSignal.onNotificationWillDisplay((payload) => { + this.dispatchHandlers( + NOTIFICATION_WILL_DISPLAY, + new NotificationWillDisplayEvent(payload as OSNotification), + ); + }), + this.RNOneSignal.onNotificationClicked((payload) => { + this.dispatchHandlers(NOTIFICATION_CLICKED, payload); + }), + this.RNOneSignal.onInAppMessageClicked((payload) => { + this.dispatchHandlers(IN_APP_MESSAGE_CLICKED, payload); + }), + this.RNOneSignal.onInAppMessageWillDisplay((payload) => { + this.dispatchHandlers(IN_APP_MESSAGE_WILL_DISPLAY, payload); + }), + this.RNOneSignal.onInAppMessageDidDisplay((payload) => { + this.dispatchHandlers(IN_APP_MESSAGE_DID_DISPLAY, payload); + }), + this.RNOneSignal.onInAppMessageWillDismiss((payload) => { + this.dispatchHandlers(IN_APP_MESSAGE_WILL_DISMISS, payload); + }), + this.RNOneSignal.onInAppMessageDidDismiss((payload) => { + this.dispatchHandlers(IN_APP_MESSAGE_DID_DISMISS, payload); + }), + ); } - /** - * Adds the event handler to the corresponding handler array on the JS side of the bridge - * @param {string} eventName - * @param {function} handler - * @returns void - */ addEventListener( eventName: K, handler: EventListenerMap[K], ) { - let handlerArray = this.eventListenerArrayMap.get(eventName); + const handlerArray = this.eventListenerArrayMap.get(eventName); if (handlerArray && handlerArray.length > 0) { - handlerArray.push(handler); + handlerArray.push(handler as (event: unknown) => void); } else { - this.eventListenerArrayMap.set(eventName, [handler]); + this.eventListenerArrayMap.set(eventName, [ + handler as (event: unknown) => void, + ]); } } - /** - * clears the event handler(s) for the event name - * @param {string} eventName - * @param {function} handler - * @returns void - */ removeEventListener( eventName: K, handler: EventListenerMap[K], @@ -119,7 +113,7 @@ export default class EventManager { if (!handlerArray) { return; } - const index = handlerArray.indexOf(handler); + const index = handlerArray.indexOf(handler as (event: unknown) => void); if (index !== -1) { handlerArray.splice(index, 1); } @@ -128,35 +122,12 @@ export default class EventManager { } } - // returns an event listener with the js to native mapping - generateEventListener( - eventName: K, - ): EmitterSubscription { - const addListenerCallback: RawEventListenerMap[K] = (payload: unknown) => { - let handlerArray = this.eventListenerArrayMap.get(eventName); - if (handlerArray) { - if (eventName === NOTIFICATION_WILL_DISPLAY) { - handlerArray.forEach((handler) => { - handler( - new NotificationWillDisplayEvent(payload as OSNotification), - ); - }); - } else if (eventName === PERMISSION_CHANGED) { - const typedPayload = payload as { permission: boolean }; - handlerArray.forEach((handler) => { - handler(typedPayload.permission); - }); - } else { - handlerArray.forEach((handler) => { - handler(payload as EventListenerMap[K]); - }); - } - } - }; - - return this.oneSignalEventEmitter.addListener( - eventName, - addListenerCallback, - ); + private dispatchHandlers(eventName: string, payload: unknown) { + const handlerArray = this.eventListenerArrayMap.get(eventName); + if (handlerArray) { + handlerArray.forEach((handler) => { + handler(payload); + }); + } } } From 6780cf712ea1a335ced92791eb2fbcfffb606595 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 18:47:53 -0700 Subject: [PATCH 06/25] feat(ios): add TurboModule support for new arch --- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index d02968a6..7bd23f90 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -94,8 +94,10 @@ - (void)stopObserving { #pragma mark Send Event Methods - (void)emitEvent:(NSNotification *)notification { +#ifndef RCT_NEW_ARCH_ENABLED if (!_hasListeners) return; +#endif NSString *name = notification.name; NSDictionary *body = notification.userInfo; @@ -649,4 +651,11 @@ - (void)removeUserStateObserver { [OneSignal.User trackEventWithName:name properties:properties]; } +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); +} +#endif + @end From f546f1126aa7b3293520bd8105a111e9df65441b Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 19:12:00 -0700 Subject: [PATCH 07/25] refactor(ios): remove legacy arch support code --- ios/RCTOneSignal/RCTOneSignalEventEmitter.h | 9 ---- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 46 ++------------------ 2 files changed, 4 insertions(+), 51 deletions(-) diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h index 2c1f0cb6..e62506c1 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h @@ -2,19 +2,15 @@ #import #import #import -#import #import #elif __has_include("RCTBridgeModule.h") #import "RCTBridgeModule.h" #import "RCTConvert.h" #import "RCTEventDispatcher.h" -#import "RCTEventEmitter.h" #import "RCTUtils.h" #endif -#ifdef RCT_NEW_ARCH_ENABLED #import -#endif typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { PermissionChanged, @@ -41,13 +37,8 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { #define OSEventString(enum) [OSNotificationEventTypesArray objectAtIndex:enum] -#ifdef RCT_NEW_ARCH_ENABLED @interface RCTOneSignalEventEmitter : NativeOneSignalSpecBase -#else -@interface RCTOneSignalEventEmitter : RCTEventEmitter -#endif + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body; -+ (BOOL)hasSetBridge; @end diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 7bd23f90..075fc65f 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -6,7 +6,6 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @implementation RCTOneSignalEventEmitter { - BOOL _hasListeners; BOOL _hasSetSubscriptionObserver; BOOL _hasSetPermissionObserver; BOOL _hasSetUserStateObserver; @@ -18,28 +17,20 @@ @implementation RCTOneSignalEventEmitter { NSMutableDictionary *_notificationWillDisplayCache; } -static BOOL _didStartObserving = false; -// Static reference to track current instance for cleanup on reload static RCTOneSignalEventEmitter *_currentInstance = nil; -+ (BOOL)hasSetBridge { - return _didStartObserving; -} - + (BOOL)requiresMainQueueSetup { return YES; } RCT_EXPORT_MODULE(OneSignal) -#pragma mark RCTEventEmitter Subclass Methods - - (instancetype)init { if (self = [super init]) { _preventDefaultCache = [NSMutableDictionary new]; _notificationWillDisplayCache = [NSMutableDictionary new]; - for (NSString *eventName in [self supportedEvents]) + for (NSString *eventName in OSNotificationEventTypesArray) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(emitEvent:) name:eventName @@ -56,29 +47,11 @@ - (instancetype)init { return self; } -- (void)startObserving { - _hasListeners = true; - - [[NSNotificationCenter defaultCenter] postNotificationName:@"didSetBridge" - object:nil]; - - _didStartObserving = true; -} - -- (void)stopObserving { - _hasListeners = false; +- (void)invalidate { [self removeHandlers]; [self removeObservers]; -} - -- (NSArray *)supportedEvents { - NSMutableArray *events = [NSMutableArray new]; - - for (int i = 0; i < OSNotificationEventTypesArray.count; i++) { - [events addObject:OSEventString(i)]; - } - - return events; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super invalidate]; } - (NSArray *)processNSError:(NSError *)error { @@ -94,15 +67,9 @@ - (void)stopObserving { #pragma mark Send Event Methods - (void)emitEvent:(NSNotification *)notification { -#ifndef RCT_NEW_ARCH_ENABLED - if (!_hasListeners) - return; -#endif - NSString *name = notification.name; NSDictionary *body = notification.userInfo; -#ifdef RCT_NEW_ARCH_ENABLED if ([name isEqualToString:OSEventString(PermissionChanged)]) { [self emitOnPermissionChanged:body]; } else if ([name isEqualToString:OSEventString(SubscriptionChanged)]) { @@ -125,9 +92,6 @@ - (void)emitEvent:(NSNotification *)notification { } else if ([name isEqualToString:OSEventString(InAppMessageDidDismiss)]) { [self emitOnInAppMessageDidDismiss:body]; } -#else - [self sendEventWithName:name body:body]; -#endif } + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { @@ -651,11 +615,9 @@ - (void)removeUserStateObserver { [OneSignal.User trackEventWithName:name properties:properties]; } -#ifdef RCT_NEW_ARCH_ENABLED - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { return std::make_shared(params); } -#endif @end From 87cb1f63a452a4dcc9ce6dbf18d7862d028821e9 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 19:29:54 -0700 Subject: [PATCH 08/25] refactor: use direct native methods over JS wrappers --- .../java/com/onesignal/rnonesignalandroid/RNOneSignal.java | 4 ++-- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 2 +- src/NativeOneSignal.ts | 2 ++ src/index.ts | 6 ++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java index 97e5efc8..53f4ca3d 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -295,7 +295,7 @@ public void paused(boolean pause) { OneSignal.getInAppMessages().setPaused(pause); } - @ReactMethod + @Override public void addTrigger(String key, String value) { OneSignal.getInAppMessages().addTrigger(key, value); } @@ -621,7 +621,7 @@ public void addTag(String key, String value) { OneSignal.getUser().addTag(key, value); } - @ReactMethod + @Override public void removeTag(String key) { OneSignal.getUser().removeTag(key); } diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 075fc65f..8898eaf3 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -252,7 +252,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { [OneSignal.InAppMessages paused:pause]; } -RCT_EXPORT_METHOD(addTrigger : (NSString *)key withValue : (NSString *)value) { +RCT_EXPORT_METHOD(addTrigger : (NSString *)key value : (NSString *)value) { [OneSignal.InAppMessages addTrigger:key withValue:value]; } diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts index 75349277..faee870b 100644 --- a/src/NativeOneSignal.ts +++ b/src/NativeOneSignal.ts @@ -54,6 +54,7 @@ export interface Spec extends TurboModule { addSms(smsNumber: string): void; removeSms(smsNumber: string): void; addTag(key: string, value: string): void; + removeTag(key: string): void; addTags(tags: Object): void; removeTags(keys: string[]): void; getTags(): Promise; @@ -79,6 +80,7 @@ export interface Spec extends TurboModule { // In-App Messages addInAppMessageClickListener(): void; addInAppMessagesLifecycleListener(): void; + addTrigger(key: string, value: string): void; addTriggers(triggers: Object): void; removeTrigger(key: string): void; removeTriggers(keys: string[]): void; diff --git a/src/index.ts b/src/index.ts index bef1473b..420e1ad8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -574,7 +574,7 @@ export namespace OneSignal { return; } - RNOneSignal.removeTags([key]); + RNOneSignal.removeTag(key); } /** Remove multiple tags with the provided keys from the current user. */ @@ -844,9 +844,7 @@ export namespace OneSignal { console.error('OneSignal: addTrigger: must include a key and a value'); } - let trigger: { [key: string]: string } = {}; - trigger[key] = value; - RNOneSignal.addTriggers(trigger); + RNOneSignal.addTrigger(key, value); } /** From 5c56fdc9ba96b2c709767a08ab7f90e8723d43a1 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 19:36:08 -0700 Subject: [PATCH 09/25] refactor: use direct native methods and fix event cleanup --- __mocks__/react-native.ts | 2 ++ src/events/EventManager.ts | 6 ++++++ src/index.test.ts | 20 +++++++------------- src/index.ts | 7 +++++++ 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index 2af0ea96..f0bdb2a4 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -36,6 +36,7 @@ const mockRNOneSignal = { addSms: vi.fn(), removeSms: vi.fn(), addTag: vi.fn(), + removeTag: vi.fn(), addTags: vi.fn(), removeTags: vi.fn(), getTags: vi.fn(), @@ -52,6 +53,7 @@ const mockRNOneSignal = { removeGroupedNotifications: vi.fn(), addInAppMessageClickListener: vi.fn(), addInAppMessagesLifecycleListener: vi.fn(), + addTrigger: vi.fn(), addTriggers: vi.fn(), removeTrigger: vi.fn(), removeTriggers: vi.fn(), diff --git a/src/events/EventManager.ts b/src/events/EventManager.ts index 04b514dc..6a23428a 100644 --- a/src/events/EventManager.ts +++ b/src/events/EventManager.ts @@ -50,6 +50,12 @@ export default class EventManager { this.setupListeners(); } + clearListeners() { + this.nativeSubscriptions.forEach((sub) => sub.remove()); + this.nativeSubscriptions = []; + this.eventListenerArrayMap.clear(); + } + setupListeners() { if (this.RNOneSignal == null) return; diff --git a/src/index.test.ts b/src/index.test.ts index f96941c6..59db5517 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -840,19 +840,19 @@ describe('OneSignal', () => { describe('removeTag', () => { test('should remove tag', () => { OneSignal.User.removeTag('key'); - expect(mockRNOneSignal.removeTags).toHaveBeenCalledWith(['key']); + expect(mockRNOneSignal.removeTag).toHaveBeenCalledWith('key'); }); test('should not remove tag if key is not a string', () => { OneSignal.User.removeTag(123 as unknown as string); expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.removeTags).not.toHaveBeenCalled(); + expect(mockRNOneSignal.removeTag).not.toHaveBeenCalled(); }); test('should not remove tag if native module is not loaded', () => { isNativeLoadedSpy.mockReturnValue(false); OneSignal.User.removeTag('key'); - expect(mockRNOneSignal.removeTags).not.toHaveBeenCalled(); + expect(mockRNOneSignal.removeTag).not.toHaveBeenCalled(); }); }); @@ -1338,31 +1338,25 @@ describe('OneSignal', () => { describe('addTrigger', () => { test('should add trigger', () => { OneSignal.InAppMessages.addTrigger('key', 'value'); - expect(mockRNOneSignal.addTriggers).toHaveBeenCalledWith({ - key: 'value', - }); + expect(mockRNOneSignal.addTrigger).toHaveBeenCalledWith('key', 'value'); }); test('should log error but still call native method if key is missing', () => { OneSignal.InAppMessages.addTrigger('', 'value'); expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.addTriggers).toHaveBeenCalledWith({ - '': 'value', - }); + expect(mockRNOneSignal.addTrigger).toHaveBeenCalledWith('', 'value'); }); test('should log error but still call native method if value is null', () => { OneSignal.InAppMessages.addTrigger('key', null as unknown as string); expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.addTriggers).toHaveBeenCalledWith({ - key: null, - }); + expect(mockRNOneSignal.addTrigger).toHaveBeenCalledWith('key', null); }); test('should not add trigger if native module is not loaded', () => { isNativeLoadedSpy.mockReturnValue(false); OneSignal.InAppMessages.addTrigger('key', 'value'); - expect(mockRNOneSignal.addTriggers).not.toHaveBeenCalled(); + expect(mockRNOneSignal.addTrigger).not.toHaveBeenCalled(); }); }); diff --git a/src/index.ts b/src/index.ts index 420e1ad8..0e9e0439 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,7 +41,14 @@ import type { import type { UserChangedState, UserState } from './types/user'; const RNOneSignal = NativeOneSignal; + +const GLOBAL_KEY = '__oneSignalEventManager'; +const prev = (globalThis as Record)[GLOBAL_KEY]; +if (prev instanceof EventManager) { + prev.clearListeners(); +} const eventManager = new EventManager(RNOneSignal); +(globalThis as Record)[GLOBAL_KEY] = eventManager; /// An enum that declares different types of log levels you can use with the OneSignal SDK, going from the least verbose (none) to verbose (print all comments). export enum LogLevel { From b4f59247698cb461af32f79ea33ff2ee0db93332 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 19:48:09 -0700 Subject: [PATCH 10/25] refactor: remove runtime type validation for tags/triggers --- src/index.test.ts | 47 ++--------------------------------------- src/index.ts | 53 +++-------------------------------------------- 2 files changed, 5 insertions(+), 95 deletions(-) diff --git a/src/index.test.ts b/src/index.test.ts index 59db5517..e373b33e 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,5 +1,5 @@ import { NativeModules, Platform } from 'react-native'; -import type { MockInstance } from 'vitest'; + import { IN_APP_MESSAGE_CLICKED, IN_APP_MESSAGE_DID_DISMISS, @@ -25,7 +25,6 @@ const PUSH_TOKEN = 'push-token'; // spies const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); -let warnSpy: MockInstance; const isNativeLoadedSpy = vi.spyOn(helpers, 'isNativeModuleLoaded'); const isValidCallbackSpy = vi.spyOn(helpers, 'isValidCallback'); @@ -51,7 +50,7 @@ describe('OneSignal', () => { mockPlatform.OS = 'ios'; isNativeLoadedSpy.mockReturnValue(true); isValidCallbackSpy.mockImplementation(() => {}); - warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); + vi.spyOn(console, 'warn').mockImplementation(() => {}); }); describe('LogLevel enum', () => { @@ -780,14 +779,6 @@ describe('OneSignal', () => { expect(mockRNOneSignal.addTag).toHaveBeenCalledWith('key', 'value'); }); - test('should convert non-string values to string', () => { - OneSignal.User.addTag('key', 123 as unknown as string); - expect(console.warn).toHaveBeenCalledWith( - 'OneSignal: addTag: tag value must be of type string; attempting to convert', - ); - expect(mockRNOneSignal.addTag).toHaveBeenCalledWith('key', '123'); - }); - test('should not add tag if key is missing', () => { OneSignal.User.addTag('', 'value'); expect(errorSpy).toHaveBeenCalled(); @@ -814,22 +805,6 @@ describe('OneSignal', () => { expect(mockRNOneSignal.addTags).toHaveBeenCalledWith(tags); }); - test('should convert non-string values to string', () => { - const tags = { key1: 'value1', key2: 123 }; - OneSignal.User.addTags(tags); - expect(warnSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.addTags).toHaveBeenCalledWith({ - key1: 'value1', - key2: '123', - }); - }); - - test('should not add tags if tags object is empty', () => { - OneSignal.User.addTags({}); - expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.addTags).not.toHaveBeenCalled(); - }); - test('should not add tags if native module is not loaded', () => { isNativeLoadedSpy.mockReturnValue(false); OneSignal.User.addTags({ key: 'value' }); @@ -843,12 +818,6 @@ describe('OneSignal', () => { expect(mockRNOneSignal.removeTag).toHaveBeenCalledWith('key'); }); - test('should not remove tag if key is not a string', () => { - OneSignal.User.removeTag(123 as unknown as string); - expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.removeTag).not.toHaveBeenCalled(); - }); - test('should not remove tag if native module is not loaded', () => { isNativeLoadedSpy.mockReturnValue(false); OneSignal.User.removeTag('key'); @@ -863,12 +832,6 @@ describe('OneSignal', () => { expect(mockRNOneSignal.removeTags).toHaveBeenCalledWith(keys); }); - test('should not remove tags if keys is not an array', () => { - OneSignal.User.removeTags('key' as unknown as string[]); - expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.removeTags).not.toHaveBeenCalled(); - }); - test('should not remove tags if native module is not loaded', () => { isNativeLoadedSpy.mockReturnValue(false); OneSignal.User.removeTags(['key']); @@ -1367,12 +1330,6 @@ describe('OneSignal', () => { expect(mockRNOneSignal.addTriggers).toHaveBeenCalledWith(triggers); }); - test('should log error but still call native method if empty', () => { - OneSignal.InAppMessages.addTriggers({}); - expect(errorSpy).toHaveBeenCalled(); - expect(mockRNOneSignal.addTriggers).toHaveBeenCalled(); - }); - test('should not add triggers if native module is not loaded', () => { isNativeLoadedSpy.mockReturnValue(false); OneSignal.InAppMessages.addTriggers({ key: 'value' }); diff --git a/src/index.ts b/src/index.ts index 0e9e0439..b3ed2b2b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -463,7 +463,7 @@ export namespace OneSignal { } /** Set aliases for the current user. If any alias already exists, it will be overwritten to the new values. */ - export function addAliases(aliases: object) { + export function addAliases(aliases: Record) { if (!isNativeModuleLoaded(RNOneSignal)) return; RNOneSignal.addAliases(aliases); @@ -529,14 +529,6 @@ export namespace OneSignal { return; } - // forces values to be string types - if (typeof value !== 'string') { - console.warn( - 'OneSignal: addTag: tag value must be of type string; attempting to convert', - ); - value = String(value); - } - RNOneSignal.addTag(key, value); } @@ -545,28 +537,9 @@ export namespace OneSignal { * specific users and/or personalizing messages. If the tag key already exists, it will be replaced with * the value provided here. */ - export function addTags(tags: object) { + export function addTags(tags: Record) { if (!isNativeModuleLoaded(RNOneSignal)) return; - if (!tags || Object.keys(tags).length === 0) { - console.error( - 'OneSignal: addTags: argument must be of type object of the form { key : "value" }', - ); - return; - } - - const convertedTags = tags as { [key: string]: any }; - Object.keys(tags).forEach(function (key) { - if (typeof convertedTags[key] !== 'string') { - console.warn( - 'OneSignal: addTags: tag value for key ' + - key + - ' must be of type string; attempting to convert', - ); - convertedTags[key] = String(convertedTags[key]); - } - }); - RNOneSignal.addTags(tags); } @@ -574,13 +547,6 @@ export namespace OneSignal { export function removeTag(key: string) { if (!isNativeModuleLoaded(RNOneSignal)) return; - if (typeof key !== 'string') { - console.error( - 'OneSignal: removeTag: key argument must be of type string', - ); - return; - } - RNOneSignal.removeTag(key); } @@ -588,11 +554,6 @@ export namespace OneSignal { export function removeTags(keys: string[]) { if (!isNativeModuleLoaded(RNOneSignal)) return; - if (!Array.isArray(keys)) { - console.error('OneSignal: removeTags: argument must be of array type'); - return; - } - RNOneSignal.removeTags(keys); } @@ -858,17 +819,9 @@ export namespace OneSignal { * Add multiple triggers for the current user. Triggers are currently explicitly used to determine whether a specific IAM should * be displayed to the user. */ - export function addTriggers(triggers: { [key: string]: string }) { + export function addTriggers(triggers: Record) { if (!isNativeModuleLoaded(RNOneSignal)) return; - let keys = Object.keys(triggers); - - if (keys.length === 0) { - console.error( - "OneSignal: addTriggers: argument must be an object of the form { key : 'value' }", - ); - } - RNOneSignal.addTriggers(triggers); } From 1c949a017541205710e89d3d5e3dd61e6dc45a61 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 19:52:47 -0700 Subject: [PATCH 11/25] test: replace NativeModules with direct mock imports --- __mocks__/react-native.ts | 4 ---- src/OSNotification.test.ts | 5 +++-- src/events/NotificationWillDisplayEvent.test.ts | 4 +--- src/index.test.ts | 4 ++-- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index f0bdb2a4..43ad78b6 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -85,10 +85,6 @@ const mockPlatform = { OS: 'ios', }; -export const NativeModules = { - OneSignal: mockRNOneSignal, -}; - export const TurboModuleRegistry = { getEnforcing: (_name: string) => mockRNOneSignal, }; diff --git a/src/OSNotification.test.ts b/src/OSNotification.test.ts index 0dee397e..bb080404 100644 --- a/src/OSNotification.test.ts +++ b/src/OSNotification.test.ts @@ -1,7 +1,8 @@ -import { NativeModules, Platform } from 'react-native'; +import { Platform } from 'react-native'; + +import { mockRNOneSignal } from '../__mocks__/react-native'; import OSNotification, { type BaseNotificationData } from './OSNotification'; -const mockRNOneSignal = NativeModules.OneSignal; const mockPlatform = Platform; describe('OSNotification', () => { diff --git a/src/events/NotificationWillDisplayEvent.test.ts b/src/events/NotificationWillDisplayEvent.test.ts index 217ffb83..5d759f4d 100644 --- a/src/events/NotificationWillDisplayEvent.test.ts +++ b/src/events/NotificationWillDisplayEvent.test.ts @@ -1,9 +1,7 @@ -import { NativeModules } from 'react-native'; +import { mockRNOneSignal } from '../../__mocks__/react-native'; import OSNotification, { type BaseNotificationData } from '../OSNotification'; import NotificationWillDisplayEvent from './NotificationWillDisplayEvent'; -const mockRNOneSignal = NativeModules.OneSignal; - describe('NotificationWillDisplayEvent', () => { const notificationId = 'test-notification-id'; const baseNotificationData: BaseNotificationData = { diff --git a/src/index.test.ts b/src/index.test.ts index e373b33e..b705adf5 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,5 +1,6 @@ -import { NativeModules, Platform } from 'react-native'; +import { Platform } from 'react-native'; +import { mockRNOneSignal } from '../__mocks__/react-native'; import { IN_APP_MESSAGE_CLICKED, IN_APP_MESSAGE_DID_DISMISS, @@ -16,7 +17,6 @@ import EventManager, { type EventListenerMap } from './events/EventManager'; import * as helpers from './helpers'; import { LogLevel, OneSignal, OSNotificationPermission } from './index'; -const mockRNOneSignal = NativeModules.OneSignal; const mockPlatform = Platform; const APP_ID = 'test-app-id'; From a1ac922e2302713059ac9dbea589bf64f0cd53e7 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 11 Mar 2026 20:20:52 -0700 Subject: [PATCH 12/25] refactor: remove deprecated sync methods --- examples/build.md | 6 +- examples/demo/src/context/AppContext.tsx | 8 +- .../src/repositories/OneSignalRepository.ts | 13 +- src/index.test.ts | 133 +----------------- src/index.ts | 93 +----------- 5 files changed, 11 insertions(+), 242 deletions(-) diff --git a/examples/build.md b/examples/build.md index 8560c2ae..3b2ae96d 100644 --- a/examples/build.md +++ b/examples/build.md @@ -128,12 +128,12 @@ Use the `OneSignal` object from `react-native-onesignal`: | SendUniqueOutcome(name) | `OneSignal.Session.addUniqueOutcome(name)` | | SendOutcomeWithValue(name, value) | `OneSignal.Session.addOutcomeWithValue(name, value)` | | TrackEvent(name, properties) | `OneSignal.User.trackEvent(name, properties)` | -| GetPushSubscriptionId() | `OneSignal.User.pushSubscription.getPushSubscriptionId()` | -| IsPushOptedIn() | `OneSignal.User.pushSubscription.getOptedIn()` | +| GetPushSubscriptionId() | `await OneSignal.User.pushSubscription.getIdAsync()` | +| IsPushOptedIn() | `await OneSignal.User.pushSubscription.getOptedInAsync()` | | OptInPush() | `OneSignal.User.pushSubscription.optIn()` | | OptOutPush() | `OneSignal.User.pushSubscription.optOut()` | | ClearAllNotifications() | `OneSignal.Notifications.clearAll()` | -| HasPermission() | `OneSignal.Notifications.hasPermission()` | +| HasPermission() | `await OneSignal.Notifications.getPermissionAsync()` | | RequestPermission(fallback) | `OneSignal.Notifications.requestPermission(fallback)` | | SetPaused(paused) | `OneSignal.InAppMessages.setPaused(paused)` | | SetLocationShared(shared) | `OneSignal.Location.setShared(shared)` | diff --git a/examples/demo/src/context/AppContext.tsx b/examples/demo/src/context/AppContext.tsx index f751b193..48379955 100644 --- a/examples/demo/src/context/AppContext.tsx +++ b/examples/demo/src/context/AppContext.tsx @@ -357,11 +357,11 @@ export function AppContextProvider({ children }: Props) { OneSignalApiService.getInstance().setAppId(appId); const externalId = await repository.getExternalId(); - const [pushId, pushOptedIn] = await Promise.all([ + const [pushId, pushOptedIn, hasPerm] = await Promise.all([ repository.getPushSubscriptionIdAsync(), repository.isPushOptedInAsync(), + repository.hasPermission(), ]); - const hasPerm = repository.hasPermission(); if (!mountedRef.current) { return; @@ -422,13 +422,13 @@ export function AppContextProvider({ children }: Props) { }); }; - const permissionHandler = () => { + const permissionHandler = async () => { if (!mountedRef.current) { return; } dispatch({ type: 'SET_HAS_NOTIFICATION_PERMISSION', - payload: repository.hasPermission(), + payload: await repository.hasPermission(), }); }; diff --git a/examples/demo/src/repositories/OneSignalRepository.ts b/examples/demo/src/repositories/OneSignalRepository.ts index 559a6681..87dc92f9 100644 --- a/examples/demo/src/repositories/OneSignalRepository.ts +++ b/examples/demo/src/repositories/OneSignalRepository.ts @@ -95,20 +95,11 @@ class OneSignalRepository { } // Push Subscription - getPushSubscriptionId(): string | undefined { - const id = OneSignal.User.pushSubscription.getPushSubscriptionId(); - return id || undefined; - } - async getPushSubscriptionIdAsync(): Promise { const id = await OneSignal.User.pushSubscription.getIdAsync(); return id ?? undefined; } - isPushOptedIn(): boolean { - return OneSignal.User.pushSubscription.getOptedIn(); - } - async isPushOptedInAsync(): Promise { return OneSignal.User.pushSubscription.getOptedInAsync(); } @@ -122,8 +113,8 @@ class OneSignalRepository { } // Notifications - hasPermission(): boolean { - return OneSignal.Notifications.hasPermission(); + async hasPermission(): Promise { + return OneSignal.Notifications.getPermissionAsync(); } async requestPermission(fallbackToSettings: boolean): Promise { diff --git a/src/index.test.ts b/src/index.test.ts index b705adf5..5956985f 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -13,7 +13,7 @@ import { SUBSCRIPTION_CHANGED, USER_STATE_CHANGED, } from './constants/events'; -import EventManager, { type EventListenerMap } from './events/EventManager'; +import EventManager from './events/EventManager'; import * as helpers from './helpers'; import { LogLevel, OneSignal, OSNotificationPermission } from './index'; @@ -37,14 +37,6 @@ const removeEventManagerListenerSpy = vi.spyOn( 'removeEventListener', ); -const filterEventListener = ( - eventName: K, -): EventListenerMap[K] => { - return addEventManagerListenerSpy.mock.calls.filter( - (call) => call[0] === eventName, - )[0][1] as EventListenerMap[K]; -}; - describe('OneSignal', () => { beforeEach(() => { mockPlatform.OS = 'ios'; @@ -71,37 +63,6 @@ describe('OneSignal', () => { test('should initialize OneSignal with appId', () => { OneSignal.initialize(APP_ID); expect(mockRNOneSignal.initialize).toHaveBeenCalledWith(APP_ID); - - // test permission change listener - const changeFn = filterEventListener(PERMISSION_CHANGED); - changeFn(true); - const permission = OneSignal.Notifications.hasPermission(); - expect(permission).toBe(true); - - // test push subscription change listener - const pushData = { - previous: { - id: '', - token: '', - optedIn: false, - }, - current: { - id: 'subscription-id', - token: 'push-token', - optedIn: true, - }, - }; - const subscriptionChangeFn = filterEventListener(SUBSCRIPTION_CHANGED); - subscriptionChangeFn(pushData); - const pushSubscription = - OneSignal.User.pushSubscription.getPushSubscriptionId(); - expect(pushSubscription).toBe('subscription-id'); - - // reset push subscription - subscriptionChangeFn({ - ...pushData, - current: { id: '', token: '', optedIn: false }, - }); }); test('should not initialize if native module is not loaded', () => { @@ -413,32 +374,6 @@ describe('OneSignal', () => { }); }); - describe('getPushSubscriptionId (deprecated)', () => { - test('should return empty string if native module not loaded', () => { - isNativeLoadedSpy.mockReturnValue(false); - const result = OneSignal.User.pushSubscription.getPushSubscriptionId(); - expect(result).toBe(''); - }); - - test('should log deprecation warning and return the push id', async () => { - // with no push id - const result = OneSignal.User.pushSubscription.getPushSubscriptionId(); - expect(result).toBe(''); - expect(console.warn).toHaveBeenCalledWith( - 'OneSignal: This method has been deprecated. Use getIdAsync instead for getting push subscription id.', - ); - - // with a push id - mockRNOneSignal.getPushSubscriptionId.mockResolvedValue(PUSH_ID); - OneSignal.initialize(APP_ID); - await vi.waitFor(() => { - const result2 = - OneSignal.User.pushSubscription.getPushSubscriptionId(); - expect(result2).toBe(PUSH_ID); - }); - }); - }); - describe('getIdAsync', () => { test('should get push subscription id', async () => { mockRNOneSignal.getPushSubscriptionId.mockResolvedValue(PUSH_ID); @@ -455,36 +390,6 @@ describe('OneSignal', () => { }); }); - describe('getPushSubscriptionToken (deprecated)', () => { - test('should return empty string if native module not loaded', () => { - isNativeLoadedSpy.mockReturnValue(false); - const result = - OneSignal.User.pushSubscription.getPushSubscriptionToken(); - expect(result).toBe(''); - }); - - test('should log deprecation warning and return the push token', async () => { - // with no push token - const result = - OneSignal.User.pushSubscription.getPushSubscriptionToken(); - expect(result).toBe(''); - expect(console.warn).toHaveBeenCalledWith( - 'OneSignal: This method has been deprecated. Use getTokenAsync instead for getting push subscription token.', - ); - - // with a push token - vi.mocked(mockRNOneSignal.getPushSubscriptionToken).mockResolvedValue( - PUSH_TOKEN, - ); - OneSignal.initialize(APP_ID); - await vi.waitFor(() => { - const result2 = - OneSignal.User.pushSubscription.getPushSubscriptionToken(); - expect(result2).toBe(PUSH_TOKEN); - }); - }); - }); - describe('getTokenAsync', () => { test('should get push subscription token', async () => { vi.mocked(mockRNOneSignal.getPushSubscriptionToken).mockResolvedValue( @@ -503,31 +408,6 @@ describe('OneSignal', () => { }); }); - describe('getOptedIn (deprecated)', () => { - test('should return false if native module not loaded', () => { - isNativeLoadedSpy.mockReturnValue(false); - const result = OneSignal.User.pushSubscription.getOptedIn(); - expect(result).toBe(false); - }); - - test('should log deprecation warning and return the opted in status', async () => { - // with no opted in status - const result = OneSignal.User.pushSubscription.getOptedIn(); - expect(result).toBe(false); - expect(console.warn).toHaveBeenCalledWith( - 'OneSignal: This method has been deprecated. Use getOptedInAsync instead for getting push subscription opted in status.', - ); - - // with a opted in status - vi.mocked(mockRNOneSignal.getOptedIn).mockResolvedValue(true); - OneSignal.initialize(APP_ID); - await vi.waitFor(() => { - const result2 = OneSignal.User.pushSubscription.getOptedIn(); - expect(result2).toBe(true); - }); - }); - }); - describe('getOptedInAsync', () => { test('should get opted in status', async () => { vi.mocked(mockRNOneSignal.getOptedIn).mockResolvedValue(true); @@ -904,17 +784,6 @@ describe('OneSignal', () => { }); describe('Notifications', () => { - describe('hasPermission (deprecated)', () => { - test('should log deprecation warning', () => { - const consoleSpy = vi - .spyOn(console, 'warn') - .mockImplementation(() => {}); - OneSignal.Notifications.hasPermission(); - expect(consoleSpy).toHaveBeenCalled(); - consoleSpy.mockRestore(); - }); - }); - describe('getPermissionAsync', () => { test('should get permission status', async () => { vi.mocked( diff --git a/src/index.ts b/src/index.ts index b3ed2b2b..b7a5db92 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,7 +36,6 @@ import type { } from './types/notificationEvents'; import type { PushSubscriptionChangedState, - PushSubscriptionState, } from './types/subscription'; import type { UserChangedState, UserState } from './types/user'; @@ -61,49 +60,12 @@ export enum LogLevel { Verbose, } -// Internal wrapper notification permission state that is being updated by the permission change handler. -let notificationPermission = false; - -// Internal wrapper push subscription state that is being updated by the subscription change handler. -let pushSub: PushSubscriptionState = { - id: '', - token: '', - optedIn: false, -}; - -async function _addPermissionObserver() { - OneSignal.Notifications.addEventListener( - 'permissionChange', - (granted: boolean) => { - notificationPermission = granted; - }, - ); - - notificationPermission = await RNOneSignal.hasNotificationPermission(); -} - -async function _addPushSubscriptionObserver() { - OneSignal.User.pushSubscription.addEventListener( - 'change', - (subscriptionChange) => { - pushSub = subscriptionChange.current; - }, - ); - - pushSub.id = (await RNOneSignal.getPushSubscriptionId()) ?? ''; - pushSub.token = (await RNOneSignal.getPushSubscriptionToken()) ?? ''; - pushSub.optedIn = await RNOneSignal.getOptedIn(); -} - export namespace OneSignal { /** Initializes the OneSignal SDK. This should be called during startup of the application. */ export function initialize(appId: string) { if (!isNativeModuleLoaded(RNOneSignal)) return; RNOneSignal.initialize(appId); - - _addPermissionObserver(); - _addPushSubscriptionObserver(); } /** @@ -313,20 +275,6 @@ export namespace OneSignal { eventManager.removeEventListener(SUBSCRIPTION_CHANGED, listener); } - /** - * @deprecated This method is deprecated. It has been replaced by {@link getIdAsync}. - */ - export function getPushSubscriptionId(): string { - if (!isNativeModuleLoaded(RNOneSignal)) { - return ''; - } - console.warn( - 'OneSignal: This method has been deprecated. Use getIdAsync instead for getting push subscription id.', - ); - - return pushSub.id ? pushSub.id : ''; - } - export async function getIdAsync(): Promise { if (!isNativeModuleLoaded(RNOneSignal)) { return Promise.reject( @@ -337,20 +285,6 @@ export namespace OneSignal { return await RNOneSignal.getPushSubscriptionId(); } - /** - * @deprecated This method is deprecated. It has been replaced by {@link getTokenAsync}. - */ - export function getPushSubscriptionToken(): string { - if (!isNativeModuleLoaded(RNOneSignal)) { - return ''; - } - console.warn( - 'OneSignal: This method has been deprecated. Use getTokenAsync instead for getting push subscription token.', - ); - - return pushSub.token ? pushSub.token : ''; - } - /** The readonly push subscription token */ export async function getTokenAsync(): Promise { if (!isNativeModuleLoaded(RNOneSignal)) { @@ -362,20 +296,6 @@ export namespace OneSignal { return await RNOneSignal.getPushSubscriptionToken(); } - /** - * @deprecated This method is deprecated. It has been replaced by {@link getOptedInAsync}. - */ - export function getOptedIn(): boolean { - if (!isNativeModuleLoaded(RNOneSignal)) { - return false; - } - console.warn( - 'OneSignal: This method has been deprecated. Use getOptedInAsync instead for getting push subscription opted in status.', - ); - - return pushSub.optedIn ?? false; - } - /** * Gets a boolean value indicating whether the current user is opted in to push notifications. * This returns true when the app has notifications permission and optOut is not called. @@ -587,17 +507,6 @@ export namespace OneSignal { } export namespace Notifications { - /** - * @deprecated This method is deprecated. It has been replaced by {@link getPermissionAsync}. - */ - export function hasPermission(): boolean { - console.warn( - 'OneSignal: This method has been deprecated. Use getPermissionAsync instead for getting notification permission status.', - ); - - return notificationPermission; - } - /** * Whether this app has push notification permission. Returns true if the user has accepted permissions, * or if the app has ephemeral or provisional permission. @@ -933,7 +842,6 @@ export { type InAppMessageWillDisplayEvent, type NotificationClickEvent, type PushSubscriptionChangedState, - type PushSubscriptionState, type UserChangedState, type UserState, }; @@ -941,3 +849,4 @@ export { export { default as OSNotification } from './OSNotification'; export type { InAppMessageClickResult } from './types/inAppMessage'; export type { NotificationClickResult } from './types/notificationEvents'; +export type { PushSubscriptionState } from './types/subscription'; From 21a92dd2f9e431fb0d8bbe1b9d872a761a59062d Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 09:18:43 -0700 Subject: [PATCH 13/25] docs: add v5 to v6 migration guide --- MIGRATION_GUIDE.md | 85 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 3df54d73..4c81d74a 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,3 +1,76 @@ +# React Native Migration Guide + +# Migration Guide (v5 to v6) + +## Requirements + +- **React Native 0.76.0 or higher** is now required. The SDK exclusively uses the New Architecture (TurboModules, Fabric, Bridgeless Mode). The legacy Bridge architecture is no longer supported. + +## Removed Deprecated Methods + +The following synchronous methods have been removed. Replace them with their async equivalents: + +| Removed (v5) | Replacement (v6) | +|---|---| +| `pushSubscription.getPushSubscriptionId()` | `await pushSubscription.getIdAsync()` | +| `pushSubscription.getPushSubscriptionToken()` | `await pushSubscription.getTokenAsync()` | +| `pushSubscription.getOptedIn()` | `await pushSubscription.getOptedInAsync()` | +| `Notifications.hasPermission()` | `await Notifications.getPermissionAsync()` | + +Since the replacements are async, update call sites to use `await`: + +```typescript +// v5 (removed) +const id = OneSignal.User.pushSubscription.getPushSubscriptionId(); +const hasPermission = OneSignal.Notifications.hasPermission(); + +// v6 +const id = await OneSignal.User.pushSubscription.getIdAsync(); +const hasPermission = await OneSignal.Notifications.getPermissionAsync(); +``` + +## Stricter TypeScript Types + +Methods that accept key-value objects now use `Record` instead of a loosely typed object. This applies to: + +- `OneSignal.User.addTags(tags)` +- `OneSignal.User.addAliases(aliases)` +- `OneSignal.InAppMessages.addTriggers(triggers)` + +If you were passing non-string values (e.g. numbers), convert them to strings: + +```typescript +// v5 (allowed at runtime, coerced to strings) +OneSignal.User.addTags({ score: 100 }); + +// v6 (TypeScript enforces string values) +OneSignal.User.addTags({ score: '100' }); +``` + +## iOS + +The podspec now uses `install_modules_dependencies(s)` instead of an explicit `React` dependency. This is handled automatically and requires no action. + +The iOS implementation file has been renamed from `.m` to `.mm` (Objective-C++). If you have any custom build phase scripts that reference this file, update them accordingly. + +## Android + +No additional Android configuration is required. The SDK uses React Native's codegen to generate the TurboModule spec automatically during the app build. + +### OkHttp Version Conflict + +The OneSignal Android SDK transitively pulls in OkHttp 5.x via its OpenTelemetry dependency, which conflicts with React Native's OkHttp 4.x. If you see a `NoClassDefFoundError` for `okhttp3.internal.Util`, add this to your app's `build.gradle`: + +```groovy +configurations.all { + resolutionStrategy { + force 'com.squareup.okhttp3:okhttp:4.12.0' + } +} +``` + +--- + # React Native v5.0.0 Migration Guide #### ⚠️ Migration Advisory for current OneSignal customers @@ -123,9 +196,9 @@ In previous versions of the SDK, a “player” could have up to one email addre The current device’s push subscription can be retrieved via: ```typescript -const id: string = OneSignal.User.pushSubscription.getPushSubscriptionId(); -const token: string = OneSignal.User.pushSubscription.getPushSubscriptionToken(); -const optedIn: boolean = OneSignal.User.pushSubscription.getOptedIn(); +const id = await OneSignal.User.pushSubscription.getIdAsync(); +const token = await OneSignal.User.pushSubscription.getTokenAsync(); +const optedIn = await OneSignal.User.pushSubscription.getOptedInAsync(); ``` ### **Opting In and Out of Push Notifications** @@ -245,9 +318,6 @@ The Push Subscription namespace is accessible via `OneSignal.User.pushSubscripti | **React Native** | **Description** | | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `OneSignal.User.pushSubscription.getPushSubscriptionId()` | _**DEPRECATED**
use `getIdAsync`._ | -| `OneSignal.User.pushSubscription.getPushSubscriptionToken()` | _**DEPRECATED**
use `getTokenAsync`_ | -| `OneSignal.User.pushSubscription.getOptedIn()` | _**DEPRECATED**
use `getOptedInAsync`_ | | `await OneSignal.User.pushSubscription.getIdAsync()` | _The readonly push subscription ID._ | | `await OneSignal.User.pushSubscription.getTokenAsync()` | _The readonly push token._ | | `await OneSignal.User.pushSubscription.getOptedInAsync()` | _Gets a boolean value indicating whether the current user is opted in to push notifications. This returns `true` when the app has notifications permission and `optOut()` is **not** called. **_Note:_** Does not take into account the existence of the subscription ID and push token. This boolean may return `true` but push notifications may still not be received by the user._ | @@ -284,8 +354,7 @@ The Notifications namespace is accessible via `OneSignal.Notifications` and prov | **React Native** | **Description** | |--------------------------------------- | --------------- | -| `OneSignal.Notifications.hasPermission()` | _**DEPRECATED**
use `getPermissionAsync()`_ | -| `OneSignal.Notifications.getPermissionAsync()` | _Whether this app has push notification permission._ | +| `await OneSignal.Notifications.getPermissionAsync()` | _Whether this app has push notification permission._ | | `await OneSignal.Notifications.canRequestPermission()` | _Whether attempting to request notification permission will show a prompt. Returns `true` if the device has not been prompted for push notification permission already._ | | `await OneSignal.Notifications.permissionNative()` | _(ios only) Returns the enum for the native permission of the device. It will be one of: NotDetermined, Denied, Authorized, Provisional (only available in iOS 12), Ephemeral (only available in iOS 14)_ | | `OneSignal.Notifications.clearAll();` | _Removes all OneSignal notifications._ | From ae3d4a01eb72380f05f81a7374c0e36ea4aeb1c9 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 12:06:58 -0700 Subject: [PATCH 14/25] style: format code and remove unused imports --- __mocks__/react-native.ts | 3 +- .../rnonesignalandroid/RNOneSignal.java | 12 ++---- ios/RCTOneSignal/RCTOneSignalEventEmitter.h | 3 +- src/NativeOneSignal.ts | 40 +++++++++---------- src/index.test.ts | 5 ++- src/index.ts | 8 ++-- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index 43ad78b6..432d65de 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -1,7 +1,6 @@ import { vi } from 'vitest'; -const createEventEmitterMock = () => - vi.fn(() => ({ remove: vi.fn() })); +const createEventEmitterMock = () => vi.fn(() => ({ remove: vi.fn() })); const mockRNOneSignal = { initialize: vi.fn(), diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java index 53f4ca3d..06610dac 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -42,7 +42,6 @@ of this software and associated documentation files (the "Software"), to deal import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; @@ -425,8 +424,7 @@ public void removePermissionObserver() { @Override public void onNotificationPermissionChange(boolean permission) { try { - emitOnPermissionChanged( - RNUtils.convertHashMapToWritableMap(RNUtils.convertPermissionToMap(permission))); + emitOnPermissionChanged(RNUtils.convertHashMapToWritableMap(RNUtils.convertPermissionToMap(permission))); Logging.debug("Sending permission change event", null); } catch (JSONException e) { e.printStackTrace(); @@ -570,9 +568,8 @@ public void addPushSubscriptionObserver() { @Override public void onPushSubscriptionChange(PushSubscriptionChangedState pushSubscriptionChangedState) { try { - emitOnSubscriptionChanged( - RNUtils.convertHashMapToWritableMap( - RNUtils.convertPushSubscriptionChangedStateToMap(pushSubscriptionChangedState))); + emitOnSubscriptionChanged(RNUtils.convertHashMapToWritableMap( + RNUtils.convertPushSubscriptionChangedStateToMap(pushSubscriptionChangedState))); Logging.debug("Sending subscription change event", null); } catch (JSONException e) { e.printStackTrace(); @@ -715,8 +712,7 @@ public void addUserStateObserver() { @Override public void onUserStateChange(UserChangedState state) { try { - emitOnUserStateChanged( - RNUtils.convertHashMapToWritableMap(RNUtils.convertUserChangedStateToMap(state))); + emitOnUserStateChanged(RNUtils.convertHashMapToWritableMap(RNUtils.convertUserChangedStateToMap(state))); Logging.debug("Sending user state change event", null); } catch (JSONException e) { e.printStackTrace(); diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h index e62506c1..0bc07bf1 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h @@ -37,7 +37,8 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { #define OSEventString(enum) [OSNotificationEventTypesArray objectAtIndex:enum] -@interface RCTOneSignalEventEmitter : NativeOneSignalSpecBase +@interface RCTOneSignalEventEmitter + : NativeOneSignalSpecBase + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body; diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts index faee870b..04b9cc6c 100644 --- a/src/NativeOneSignal.ts +++ b/src/NativeOneSignal.ts @@ -17,19 +17,19 @@ export interface Spec extends TurboModule { enterLiveActivity( activityId: string, token: string, - callback: (result: Object) => void, + callback: (result: object) => void, ): void; exitLiveActivity( activityId: string, - callback: (result: Object) => void, + callback: (result: object) => void, ): void; setPushToStartToken(activityType: string, token: string): void; removePushToStartToken(activityType: string): void; - setupDefaultLiveActivity(options: Object | null): void; + setupDefaultLiveActivity(options: object | null): void; startDefaultLiveActivity( activityId: string, - attributes: Object, - content: Object, + attributes: object, + content: object, ): void; // Push Subscription @@ -46,7 +46,7 @@ export interface Spec extends TurboModule { getExternalId(): Promise; setLanguage(language: string): void; addAlias(label: string, id: string): void; - addAliases(aliases: Object): void; + addAliases(aliases: object): void; removeAlias(label: string): void; removeAliases(labels: string[]): void; addEmail(email: string): void; @@ -55,10 +55,10 @@ export interface Spec extends TurboModule { removeSms(smsNumber: string): void; addTag(key: string, value: string): void; removeTag(key: string): void; - addTags(tags: Object): void; + addTags(tags: object): void; removeTags(keys: string[]): void; - getTags(): Promise; - trackEvent(name: string, properties: Object): void; + getTags(): Promise; + trackEvent(name: string, properties: object): void; // Notifications hasNotificationPermission(): Promise; @@ -81,7 +81,7 @@ export interface Spec extends TurboModule { addInAppMessageClickListener(): void; addInAppMessagesLifecycleListener(): void; addTrigger(key: string, value: string): void; - addTriggers(triggers: Object): void; + addTriggers(triggers: object): void; removeTrigger(key: string): void; removeTriggers(keys: string[]): void; clearTriggers(): void; @@ -99,16 +99,16 @@ export interface Spec extends TurboModule { addOutcomeWithValue(name: string, value: number): void; // Events - readonly onPermissionChanged: CodegenTypes.EventEmitter; - readonly onSubscriptionChanged: CodegenTypes.EventEmitter; - readonly onUserStateChanged: CodegenTypes.EventEmitter; - readonly onNotificationWillDisplay: CodegenTypes.EventEmitter; - readonly onNotificationClicked: CodegenTypes.EventEmitter; - readonly onInAppMessageClicked: CodegenTypes.EventEmitter; - readonly onInAppMessageWillDisplay: CodegenTypes.EventEmitter; - readonly onInAppMessageDidDisplay: CodegenTypes.EventEmitter; - readonly onInAppMessageWillDismiss: CodegenTypes.EventEmitter; - readonly onInAppMessageDidDismiss: CodegenTypes.EventEmitter; + readonly onPermissionChanged: CodegenTypes.EventEmitter; + readonly onSubscriptionChanged: CodegenTypes.EventEmitter; + readonly onUserStateChanged: CodegenTypes.EventEmitter; + readonly onNotificationWillDisplay: CodegenTypes.EventEmitter; + readonly onNotificationClicked: CodegenTypes.EventEmitter; + readonly onInAppMessageClicked: CodegenTypes.EventEmitter; + readonly onInAppMessageWillDisplay: CodegenTypes.EventEmitter; + readonly onInAppMessageDidDisplay: CodegenTypes.EventEmitter; + readonly onInAppMessageWillDismiss: CodegenTypes.EventEmitter; + readonly onInAppMessageDidDismiss: CodegenTypes.EventEmitter; } export default TurboModuleRegistry.getEnforcing('OneSignal'); diff --git a/src/index.test.ts b/src/index.test.ts index 5956985f..61aa016a 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1170,7 +1170,10 @@ describe('OneSignal', () => { describe('addTrigger', () => { test('should add trigger', () => { OneSignal.InAppMessages.addTrigger('key', 'value'); - expect(mockRNOneSignal.addTrigger).toHaveBeenCalledWith('key', 'value'); + expect(mockRNOneSignal.addTrigger).toHaveBeenCalledWith( + 'key', + 'value', + ); }); test('should log error but still call native method if key is missing', () => { diff --git a/src/index.ts b/src/index.ts index b7a5db92..5b1ade1e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,9 +34,7 @@ import type { NotificationClickEvent, NotificationListeners, } from './types/notificationEvents'; -import type { - PushSubscriptionChangedState, -} from './types/subscription'; +import type { PushSubscriptionChangedState } from './types/subscription'; import type { UserChangedState, UserState } from './types/user'; const RNOneSignal = NativeOneSignal; @@ -140,7 +138,7 @@ export namespace OneSignal { export function enter( activityId: string, token: string, - handler: (result: Object) => void = () => {}, + handler: (result: object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; @@ -158,7 +156,7 @@ export namespace OneSignal { **/ export function exit( activityId: string, - handler: (result: Object) => void = () => {}, + handler: (result: object) => void = () => {}, ) { if (!isNativeModuleLoaded(RNOneSignal)) return; From 830981f83651c7e3f289ad47f63ed7c1406a2a22 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 13:56:11 -0700 Subject: [PATCH 15/25] refactor(demo): add AppInputProps to TextInputs --- .../src/components/modals/CustomNotificationModal.tsx | 4 +++- examples/demo/src/components/modals/LoginModal.tsx | 3 ++- .../demo/src/components/modals/MultiPairInputModal.tsx | 4 +++- examples/demo/src/components/modals/OutcomeModal.tsx | 9 ++++++++- examples/demo/src/components/modals/PairInputModal.tsx | 4 +++- examples/demo/src/components/modals/SingleInputModal.tsx | 3 ++- examples/demo/src/components/modals/TrackEventModal.tsx | 3 +++ examples/demo/src/theme.ts | 8 +++++++- 8 files changed, 31 insertions(+), 7 deletions(-) diff --git a/examples/demo/src/components/modals/CustomNotificationModal.tsx b/examples/demo/src/components/modals/CustomNotificationModal.tsx index 2b48239e..d3c98472 100644 --- a/examples/demo/src/components/modals/CustomNotificationModal.tsx +++ b/examples/demo/src/components/modals/CustomNotificationModal.tsx @@ -9,7 +9,7 @@ import { KeyboardAvoidingView, Platform, } from 'react-native'; -import { AppColors, AppDialogStyles } from '../../theme'; +import { AppColors, AppDialogStyles, AppInputProps } from '../../theme'; interface Props { visible: boolean; @@ -61,6 +61,7 @@ export default function CustomNotificationModal({ value={title} onChangeText={setTitle} autoFocus + {...AppInputProps} testID="custom_notification_title_input" /> diff --git a/examples/demo/src/components/modals/LoginModal.tsx b/examples/demo/src/components/modals/LoginModal.tsx index dcddf25d..e1321d05 100644 --- a/examples/demo/src/components/modals/LoginModal.tsx +++ b/examples/demo/src/components/modals/LoginModal.tsx @@ -9,7 +9,7 @@ import { TouchableOpacity, View, } from 'react-native'; -import { AppColors, AppDialogStyles } from '../../theme'; +import { AppColors, AppDialogStyles, AppInputProps } from '../../theme'; interface Props { visible: boolean; @@ -55,6 +55,7 @@ export default function LoginModal({ visible, onConfirm, onClose }: Props) { value={userId} onChangeText={setUserId} autoFocus + {...AppInputProps} testID="login_user_id_input" /> diff --git a/examples/demo/src/components/modals/MultiPairInputModal.tsx b/examples/demo/src/components/modals/MultiPairInputModal.tsx index 104356a1..3eab94ec 100644 --- a/examples/demo/src/components/modals/MultiPairInputModal.tsx +++ b/examples/demo/src/components/modals/MultiPairInputModal.tsx @@ -11,7 +11,7 @@ import { Platform, } from 'react-native'; import Icon from 'react-native-vector-icons/MaterialIcons'; -import { AppColors, AppDialogStyles } from '../../theme'; +import { AppColors, AppDialogStyles, AppInputProps } from '../../theme'; interface Row { id: number; @@ -107,6 +107,7 @@ export default function MultiPairInputModal({ value={row.key} onChangeText={t => updateRow(row.id, 'key', t)} autoFocus={idx === 0} + {...AppInputProps} testID={idx === 0 ? 'multi_pair_key_0' : undefined} /> updateRow(row.id, 'value', t)} + {...AppInputProps} testID={idx === 0 ? 'multi_pair_value_0' : undefined} /> {rows.length > 1 && ( diff --git a/examples/demo/src/components/modals/OutcomeModal.tsx b/examples/demo/src/components/modals/OutcomeModal.tsx index d3f7695a..7f3ede97 100644 --- a/examples/demo/src/components/modals/OutcomeModal.tsx +++ b/examples/demo/src/components/modals/OutcomeModal.tsx @@ -9,7 +9,12 @@ import { KeyboardAvoidingView, Platform, } from 'react-native'; -import { AppColors, AppTextStyles, AppDialogStyles } from '../../theme'; +import { + AppColors, + AppTextStyles, + AppDialogStyles, + AppInputProps, +} from '../../theme'; type OutcomeType = 'normal' | 'unique' | 'withValue'; @@ -103,6 +108,7 @@ export default function OutcomeModal({ value={name} onChangeText={setName} autoFocus + {...AppInputProps} testID="outcome_name_input" /> {outcomeType === 'withValue' && ( @@ -113,6 +119,7 @@ export default function OutcomeModal({ value={value} onChangeText={setValue} keyboardType="numeric" + {...AppInputProps} testID="outcome_value_input" /> )} diff --git a/examples/demo/src/components/modals/PairInputModal.tsx b/examples/demo/src/components/modals/PairInputModal.tsx index 064ad731..14f205ac 100644 --- a/examples/demo/src/components/modals/PairInputModal.tsx +++ b/examples/demo/src/components/modals/PairInputModal.tsx @@ -9,7 +9,7 @@ import { KeyboardAvoidingView, Platform, } from 'react-native'; -import { AppColors, AppDialogStyles } from '../../theme'; +import { AppColors, AppDialogStyles, AppInputProps } from '../../theme'; interface Props { visible: boolean; @@ -78,6 +78,7 @@ export default function PairInputModal({ value={keyValue} onChangeText={setKeyValue} autoFocus + {...AppInputProps} testID={keyTestID} /> diff --git a/examples/demo/src/components/modals/SingleInputModal.tsx b/examples/demo/src/components/modals/SingleInputModal.tsx index 1a4de37b..a92e989b 100644 --- a/examples/demo/src/components/modals/SingleInputModal.tsx +++ b/examples/demo/src/components/modals/SingleInputModal.tsx @@ -9,7 +9,7 @@ import { KeyboardAvoidingView, Platform, } from 'react-native'; -import { AppColors, AppDialogStyles } from '../../theme'; +import { AppColors, AppDialogStyles, AppInputProps } from '../../theme'; interface Props { visible: boolean; @@ -67,6 +67,7 @@ export default function SingleInputModal({ onChangeText={setValue} keyboardType={keyboardType} autoFocus + {...AppInputProps} testID={testID} /> diff --git a/examples/demo/src/components/modals/TrackEventModal.tsx b/examples/demo/src/components/modals/TrackEventModal.tsx index 8cc25828..619d01fb 100644 --- a/examples/demo/src/components/modals/TrackEventModal.tsx +++ b/examples/demo/src/components/modals/TrackEventModal.tsx @@ -14,6 +14,7 @@ import { AppTextStyles, AppSpacing, AppDialogStyles, + AppInputProps, } from '../../theme'; interface Props { @@ -103,6 +104,7 @@ export default function TrackEventModal({ value={name} onChangeText={setName} autoFocus + {...AppInputProps} testID="track_event_name_input" /> Properties (optional, JSON) @@ -117,6 +119,7 @@ export default function TrackEventModal({ value={propertiesText} onChangeText={handlePropertiesChange} multiline + {...AppInputProps} testID="track_event_properties_input" /> {!!jsonError && {jsonError}} diff --git a/examples/demo/src/theme.ts b/examples/demo/src/theme.ts index deb25df7..5e2977c6 100644 --- a/examples/demo/src/theme.ts +++ b/examples/demo/src/theme.ts @@ -1,4 +1,4 @@ -import { StyleSheet } from 'react-native'; +import { StyleSheet, type TextInputProps } from 'react-native'; export const AppColors = { osPrimary: '#E54B4D', @@ -49,6 +49,12 @@ export const AppTheme = StyleSheet.create({ }, }); +export const AppInputProps: TextInputProps = { + autoCorrect: false, + autoCapitalize: 'none', + autoComplete: 'off', +}; + export const AppDialogStyles = StyleSheet.create({ backdrop: { flex: 1, From 60d800ebd46821d45c7d758b9b5a913c3e52635e Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 17:52:33 -0700 Subject: [PATCH 16/25] refactor: update TurboModule types from object to Object --- examples/demo/bun.lock | 2 +- examples/demo/ios/Podfile.lock | 28 ++++++++++++++++++---- src/NativeOneSignal.ts | 43 +++++++++++++++++----------------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index 265c6c69..516955ec 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" } }, "sha512-mPeoX34XBXwXpy8ocluG7jJJNBtLv258AYc9lH0TAyAAyUIh/6JAl1JITv+U2ZOtUpXM9Cc+vAyJAWjfE9LjhQ=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-e1VOWZLx4vo3Ih9a7ar39PXyx6s4ktiOSSyTmyfKaLHWlHx93KbSPHD8kcitqQQaQJX7DiwfZs9s6DswuaTdAg=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/examples/demo/ios/Podfile.lock b/examples/demo/ios/Podfile.lock index 20aee29e..3782374e 100644 --- a/examples/demo/ios/Podfile.lock +++ b/examples/demo/ios/Podfile.lock @@ -1446,9 +1446,29 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - ReactNativeDependencies - - react-native-onesignal (5.3.6): - - OneSignalXCFramework (= 5.5.0) - - React (< 1.0.0, >= 0.13.0) + - react-native-onesignal (5.3.4): + - hermes-engine + - OneSignalXCFramework (= 5.4.2) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-Core-prebuilt + - 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 + - ReactNativeDependencies + - Yoga - react-native-safe-area-context (5.6.2): - hermes-engine - RCTRequired @@ -2329,7 +2349,7 @@ SPEC CHECKSUMS: React-logger: 9e51e01455f15cb3ef87a09a1ec773cdb22d56c1 React-Mapbuffer: 92b99e450e8ff598b27d6e4db3a75e04fd45e9a9 React-microtasksnativemodule: 2fe0f2bd2840dedbd66c0ac249c64f977f39cc18 - react-native-onesignal: 43e278433205c5cf4c3c0dc64ec3e8390a2a7b6f + react-native-onesignal: 3ad7ccd00e4ea2b4f433e579f897b356747ae548 react-native-safe-area-context: 37e680fc4cace3c0030ee46e8987d24f5d3bdab2 React-NativeModulesApple: 44a9474594566cd03659f92e38f42599c6b9dee4 React-networking: db73d91466cb134fcbdaaa579fb2de14e2c2ea01 diff --git a/src/NativeOneSignal.ts b/src/NativeOneSignal.ts index 04b9cc6c..4414f2db 100644 --- a/src/NativeOneSignal.ts +++ b/src/NativeOneSignal.ts @@ -1,4 +1,5 @@ -import type { TurboModule, CodegenTypes } from 'react-native'; +/* eslint-disable @typescript-eslint/no-wrapper-object-types */ +import type { CodegenTypes, TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { @@ -17,19 +18,19 @@ export interface Spec extends TurboModule { enterLiveActivity( activityId: string, token: string, - callback: (result: object) => void, + callback: (result: Object) => void, ): void; exitLiveActivity( activityId: string, - callback: (result: object) => void, + callback: (result: Object) => void, ): void; setPushToStartToken(activityType: string, token: string): void; removePushToStartToken(activityType: string): void; - setupDefaultLiveActivity(options: object | null): void; + setupDefaultLiveActivity(options: Object | null): void; startDefaultLiveActivity( activityId: string, - attributes: object, - content: object, + attributes: Object, + content: Object, ): void; // Push Subscription @@ -46,7 +47,7 @@ export interface Spec extends TurboModule { getExternalId(): Promise; setLanguage(language: string): void; addAlias(label: string, id: string): void; - addAliases(aliases: object): void; + addAliases(aliases: Object): void; removeAlias(label: string): void; removeAliases(labels: string[]): void; addEmail(email: string): void; @@ -55,10 +56,10 @@ export interface Spec extends TurboModule { removeSms(smsNumber: string): void; addTag(key: string, value: string): void; removeTag(key: string): void; - addTags(tags: object): void; + addTags(tags: Object): void; removeTags(keys: string[]): void; - getTags(): Promise; - trackEvent(name: string, properties: object): void; + getTags(): Promise; + trackEvent(name: string, properties: Object | null): void; // Notifications hasNotificationPermission(): Promise; @@ -81,7 +82,7 @@ export interface Spec extends TurboModule { addInAppMessageClickListener(): void; addInAppMessagesLifecycleListener(): void; addTrigger(key: string, value: string): void; - addTriggers(triggers: object): void; + addTriggers(triggers: Object): void; removeTrigger(key: string): void; removeTriggers(keys: string[]): void; clearTriggers(): void; @@ -99,16 +100,16 @@ export interface Spec extends TurboModule { addOutcomeWithValue(name: string, value: number): void; // Events - readonly onPermissionChanged: CodegenTypes.EventEmitter; - readonly onSubscriptionChanged: CodegenTypes.EventEmitter; - readonly onUserStateChanged: CodegenTypes.EventEmitter; - readonly onNotificationWillDisplay: CodegenTypes.EventEmitter; - readonly onNotificationClicked: CodegenTypes.EventEmitter; - readonly onInAppMessageClicked: CodegenTypes.EventEmitter; - readonly onInAppMessageWillDisplay: CodegenTypes.EventEmitter; - readonly onInAppMessageDidDisplay: CodegenTypes.EventEmitter; - readonly onInAppMessageWillDismiss: CodegenTypes.EventEmitter; - readonly onInAppMessageDidDismiss: CodegenTypes.EventEmitter; + readonly onPermissionChanged: CodegenTypes.EventEmitter; + readonly onSubscriptionChanged: CodegenTypes.EventEmitter; + readonly onUserStateChanged: CodegenTypes.EventEmitter; + readonly onNotificationWillDisplay: CodegenTypes.EventEmitter; + readonly onNotificationClicked: CodegenTypes.EventEmitter; + readonly onInAppMessageClicked: CodegenTypes.EventEmitter; + readonly onInAppMessageWillDisplay: CodegenTypes.EventEmitter; + readonly onInAppMessageDidDisplay: CodegenTypes.EventEmitter; + readonly onInAppMessageWillDismiss: CodegenTypes.EventEmitter; + readonly onInAppMessageDidDismiss: CodegenTypes.EventEmitter; } export default TurboModuleRegistry.getEnforcing('OneSignal'); From fddafdb4434a5ae5bfadb6f1946b9fb0579a5d40 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 18:16:26 -0700 Subject: [PATCH 17/25] refactor: rename RCTOneSignal.m to .mm for new arch --- examples/demo/bun.lock | 2 +- examples/run-android.sh | 1 + examples/run-ios.sh | 1 + ios/RCTOneSignal.xcodeproj/project.pbxproj | 8 ++++---- ios/RCTOneSignal/{RCTOneSignal.m => RCTOneSignal.mm} | 0 5 files changed, 7 insertions(+), 5 deletions(-) rename ios/RCTOneSignal/{RCTOneSignal.m => RCTOneSignal.mm} (100%) diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index 516955ec..04c5b895 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-e1VOWZLx4vo3Ih9a7ar39PXyx6s4ktiOSSyTmyfKaLHWlHx93KbSPHD8kcitqQQaQJX7DiwfZs9s6DswuaTdAg=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-7AfEs5BOHr/x7Sj3C1wvTs1WlPdX6Vma8jBrT0cGTvU3v9wKvgBN1oqOqvr5s0jBLf8bmOUrwT/OQS5Lqm0YRQ=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/examples/run-android.sh b/examples/run-android.sh index 92095182..8d12f034 100755 --- a/examples/run-android.sh +++ b/examples/run-android.sh @@ -1,3 +1,4 @@ +# DON'T RUN THIS FILE DIRECTLY, USE THE run-ios.sh FILE IN THE DEMO APP #!/bin/bash set -e diff --git a/examples/run-ios.sh b/examples/run-ios.sh index 32d6d062..0d2af134 100755 --- a/examples/run-ios.sh +++ b/examples/run-ios.sh @@ -1,3 +1,4 @@ +# DON'T RUN THIS FILE DIRECTLY, USE THE run-ios.sh FILE IN THE DEMO APP #!/bin/bash set -e diff --git a/ios/RCTOneSignal.xcodeproj/project.pbxproj b/ios/RCTOneSignal.xcodeproj/project.pbxproj index 1942ea57..6a607cde 100644 --- a/ios/RCTOneSignal.xcodeproj/project.pbxproj +++ b/ios/RCTOneSignal.xcodeproj/project.pbxproj @@ -18,7 +18,7 @@ CAADD42720B3791A0089D086 /* OneSignal.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = CAADD42520B379060089D086 /* OneSignal.h */; }; CACB39D6202D232A00D86CD1 /* RCTOneSignalEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = CACB39D5202D232A00D86CD1 /* RCTOneSignalEventEmitter.m */; }; FD2CCC851C772B4200B2B24E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2CCC841C772B4200B2B24E /* SystemConfiguration.framework */; }; - FDB40CC41C5E4E5500CBF09B /* RCTOneSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.m */; }; + FDB40CC41C5E4E5500CBF09B /* RCTOneSignal.mm in Sources */ = {isa = PBXBuildFile; fileRef = FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.mm */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -48,7 +48,7 @@ CACB39D5202D232A00D86CD1 /* RCTOneSignalEventEmitter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTOneSignalEventEmitter.m; sourceTree = ""; }; FD2CCC841C772B4200B2B24E /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; FDB40CC21C5E4E5500CBF09B /* RCTOneSignal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTOneSignal.h; sourceTree = ""; }; - FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTOneSignal.m; sourceTree = ""; }; + FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTOneSignal.mm; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -86,7 +86,7 @@ isa = PBXGroup; children = ( FDB40CC21C5E4E5500CBF09B /* RCTOneSignal.h */, - FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.m */, + FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.mm */, CACB39D4202D232A00D86CD1 /* RCTOneSignalEventEmitter.h */, CACB39D5202D232A00D86CD1 /* RCTOneSignalEventEmitter.m */, CA1CC866200FE3C3005B66AA /* RCTOneSignalExtensionService.h */, @@ -178,7 +178,7 @@ CACB39D6202D232A00D86CD1 /* RCTOneSignalEventEmitter.m in Sources */, CA63F32E20ACFD60009AE90F /* UIApplication+RCTOnesignal.m in Sources */, CA1CC868200FE3C3005B66AA /* RCTOneSignalExtensionService.m in Sources */, - FDB40CC41C5E4E5500CBF09B /* RCTOneSignal.m in Sources */, + FDB40CC41C5E4E5500CBF09B /* RCTOneSignal.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/RCTOneSignal/RCTOneSignal.m b/ios/RCTOneSignal/RCTOneSignal.mm similarity index 100% rename from ios/RCTOneSignal/RCTOneSignal.m rename to ios/RCTOneSignal/RCTOneSignal.mm From fa1bf98f6e4cad0f68f0eec0df3fe0853b754413 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 18:20:30 -0700 Subject: [PATCH 18/25] refactor: import OneSignalUser Swift module --- examples/demo/bun.lock | 2 +- ios/RCTOneSignal.xcodeproj/project.pbxproj | 346 ------------------ .../contents.xcworkspacedata | 7 - ios/RCTOneSignal/RCTOneSignal.h | 1 + ios/RCTOneSignal/RCTOneSignalEventEmitter.h | 4 +- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 22 +- package.json | 5 + 7 files changed, 23 insertions(+), 364 deletions(-) delete mode 100644 ios/RCTOneSignal.xcodeproj/project.pbxproj delete mode 100644 ios/RCTOneSignal.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index 04c5b895..cfaee04c 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-7AfEs5BOHr/x7Sj3C1wvTs1WlPdX6Vma8jBrT0cGTvU3v9wKvgBN1oqOqvr5s0jBLf8bmOUrwT/OQS5Lqm0YRQ=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-TNLDqNz7CaQayuuwDia3uMt9qybeMdxMUCzYdRCz4xz4QN4SDk8MNeHntsfm8FNhUidcujDiqDUXUNJ549CODQ=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/ios/RCTOneSignal.xcodeproj/project.pbxproj b/ios/RCTOneSignal.xcodeproj/project.pbxproj deleted file mode 100644 index 6a607cde..00000000 --- a/ios/RCTOneSignal.xcodeproj/project.pbxproj +++ /dev/null @@ -1,346 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - CA1CC868200FE3C3005B66AA /* RCTOneSignalExtensionService.m in Sources */ = {isa = PBXBuildFile; fileRef = CA1CC867200FE3C3005B66AA /* RCTOneSignalExtensionService.m */; }; - CA3D8B582076D83C006F3572 /* RCTOneSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = FDB40CC21C5E4E5500CBF09B /* RCTOneSignal.h */; }; - CA3D8B592076D83C006F3572 /* RCTOneSignalExtensionService.h in Headers */ = {isa = PBXBuildFile; fileRef = CA1CC866200FE3C3005B66AA /* RCTOneSignalExtensionService.h */; }; - CA3D8B5A2076D84E006F3572 /* RCTOneSignal.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = FDB40CC21C5E4E5500CBF09B /* RCTOneSignal.h */; }; - CA3D8B5B2076D84E006F3572 /* RCTOneSignalExtensionService.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = CA1CC866200FE3C3005B66AA /* RCTOneSignalExtensionService.h */; }; - CA63F32E20ACFD60009AE90F /* UIApplication+RCTOnesignal.m in Sources */ = {isa = PBXBuildFile; fileRef = CA63F32C20ACFD60009AE90F /* UIApplication+RCTOnesignal.m */; }; - CAADD42420B378FE0089D086 /* libOneSignal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAADD42320B378FD0089D086 /* libOneSignal.a */; }; - CAADD42620B379070089D086 /* OneSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = CAADD42520B379060089D086 /* OneSignal.h */; }; - CAADD42720B3791A0089D086 /* OneSignal.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = CAADD42520B379060089D086 /* OneSignal.h */; }; - CACB39D6202D232A00D86CD1 /* RCTOneSignalEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = CACB39D5202D232A00D86CD1 /* RCTOneSignalEventEmitter.m */; }; - FD2CCC851C772B4200B2B24E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2CCC841C772B4200B2B24E /* SystemConfiguration.framework */; }; - FDB40CC41C5E4E5500CBF09B /* RCTOneSignal.mm in Sources */ = {isa = PBXBuildFile; fileRef = FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.mm */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 3245CDEB1BFEE35C00EABF68 /* Copy Headers */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; - files = ( - CAADD42720B3791A0089D086 /* OneSignal.h in Copy Headers */, - CA3D8B5A2076D84E006F3572 /* RCTOneSignal.h in Copy Headers */, - CA3D8B5B2076D84E006F3572 /* RCTOneSignalExtensionService.h in Copy Headers */, - ); - name = "Copy Headers"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 3245CDED1BFEE35C00EABF68 /* libRCTOneSignal.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTOneSignal.a; sourceTree = BUILT_PRODUCTS_DIR; }; - CA1CC866200FE3C3005B66AA /* RCTOneSignalExtensionService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTOneSignalExtensionService.h; sourceTree = ""; }; - CA1CC867200FE3C3005B66AA /* RCTOneSignalExtensionService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTOneSignalExtensionService.m; sourceTree = ""; }; - CA63F32C20ACFD60009AE90F /* UIApplication+RCTOnesignal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIApplication+RCTOnesignal.m"; sourceTree = ""; }; - CAADD42320B378FD0089D086 /* libOneSignal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOneSignal.a; sourceTree = ""; }; - CAADD42520B379060089D086 /* OneSignal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OneSignal.h; sourceTree = ""; }; - CACB39D4202D232A00D86CD1 /* RCTOneSignalEventEmitter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTOneSignalEventEmitter.h; sourceTree = ""; }; - CACB39D5202D232A00D86CD1 /* RCTOneSignalEventEmitter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTOneSignalEventEmitter.m; sourceTree = ""; }; - FD2CCC841C772B4200B2B24E /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; - FDB40CC21C5E4E5500CBF09B /* RCTOneSignal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTOneSignal.h; sourceTree = ""; }; - FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTOneSignal.mm; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 3245CDEA1BFEE35C00EABF68 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - CAADD42420B378FE0089D086 /* libOneSignal.a in Frameworks */, - FD2CCC851C772B4200B2B24E /* SystemConfiguration.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 3245CDE41BFEE35C00EABF68 = { - isa = PBXGroup; - children = ( - FD2CCC841C772B4200B2B24E /* SystemConfiguration.framework */, - 3245CDEF1BFEE35C00EABF68 /* RCTOneSignal */, - 3245CDEE1BFEE35C00EABF68 /* Products */, - CA1CC858200FDEFC005B66AA /* Frameworks */, - ); - sourceTree = ""; - }; - 3245CDEE1BFEE35C00EABF68 /* Products */ = { - isa = PBXGroup; - children = ( - 3245CDED1BFEE35C00EABF68 /* libRCTOneSignal.a */, - ); - name = Products; - sourceTree = ""; - }; - 3245CDEF1BFEE35C00EABF68 /* RCTOneSignal */ = { - isa = PBXGroup; - children = ( - FDB40CC21C5E4E5500CBF09B /* RCTOneSignal.h */, - FDB40CC31C5E4E5500CBF09B /* RCTOneSignal.mm */, - CACB39D4202D232A00D86CD1 /* RCTOneSignalEventEmitter.h */, - CACB39D5202D232A00D86CD1 /* RCTOneSignalEventEmitter.m */, - CA1CC866200FE3C3005B66AA /* RCTOneSignalExtensionService.h */, - CA1CC867200FE3C3005B66AA /* RCTOneSignalExtensionService.m */, - CA63F32C20ACFD60009AE90F /* UIApplication+RCTOnesignal.m */, - ); - path = RCTOneSignal; - sourceTree = ""; - }; - CA1CC858200FDEFC005B66AA /* Frameworks */ = { - isa = PBXGroup; - children = ( - CAADD42520B379060089D086 /* OneSignal.h */, - CAADD42320B378FD0089D086 /* libOneSignal.a */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - CA3D8B572076D824006F3572 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CA3D8B582076D83C006F3572 /* RCTOneSignal.h in Headers */, - CAADD42620B379070089D086 /* OneSignal.h in Headers */, - CA3D8B592076D83C006F3572 /* RCTOneSignalExtensionService.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 3245CDEC1BFEE35C00EABF68 /* RCTOneSignal */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3245CE011BFEE35C00EABF68 /* Build configuration list for PBXNativeTarget "RCTOneSignal" */; - buildPhases = ( - 3245CDE91BFEE35C00EABF68 /* Sources */, - 3245CDEA1BFEE35C00EABF68 /* Frameworks */, - 3245CDEB1BFEE35C00EABF68 /* Copy Headers */, - CA3D8B572076D824006F3572 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RCTOneSignal; - productName = RCTOneSignal; - productReference = 3245CDED1BFEE35C00EABF68 /* libRCTOneSignal.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 3245CDE51BFEE35C00EABF68 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0730; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 3245CDEC1BFEE35C00EABF68 = { - CreatedOnToolsVersion = 6.4; - }; - }; - }; - buildConfigurationList = 3245CDE81BFEE35C00EABF68 /* Build configuration list for PBXProject "RCTOneSignal" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 3245CDE41BFEE35C00EABF68; - productRefGroup = 3245CDEE1BFEE35C00EABF68 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 3245CDEC1BFEE35C00EABF68 /* RCTOneSignal */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 3245CDE91BFEE35C00EABF68 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CACB39D6202D232A00D86CD1 /* RCTOneSignalEventEmitter.m in Sources */, - CA63F32E20ACFD60009AE90F /* UIApplication+RCTOnesignal.m in Sources */, - CA1CC868200FE3C3005B66AA /* RCTOneSignalExtensionService.m in Sources */, - FDB40CC41C5E4E5500CBF09B /* RCTOneSignal.mm in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 3245CDFF1BFEE35C00EABF68 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/Frameworks"; - 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; - HEADER_SEARCH_PATHS = ""; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 3245CE001BFEE35C00EABF68 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/Frameworks"; - 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; - HEADER_SEARCH_PATHS = ""; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 3245CE021BFEE35C00EABF68 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Frameworks/**", - "$(PROJECT_DIR)/**", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/**", - "$(PROJECT_DIR)/RCTOneSignal", - "$(PROJECT_DIR)", - ); - ONLY_ACTIVE_ARCH = NO; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 3245CE031BFEE35C00EABF68 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Frameworks/**", - "$(PROJECT_DIR)/**", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/**", - "$(PROJECT_DIR)/RCTOneSignal", - "$(PROJECT_DIR)", - ); - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 3245CDE81BFEE35C00EABF68 /* Build configuration list for PBXProject "RCTOneSignal" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3245CDFF1BFEE35C00EABF68 /* Debug */, - 3245CE001BFEE35C00EABF68 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3245CE011BFEE35C00EABF68 /* Build configuration list for PBXNativeTarget "RCTOneSignal" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3245CE021BFEE35C00EABF68 /* Debug */, - 3245CE031BFEE35C00EABF68 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 3245CDE51BFEE35C00EABF68 /* Project object */; -} diff --git a/ios/RCTOneSignal.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/RCTOneSignal.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/ios/RCTOneSignal.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ios/RCTOneSignal/RCTOneSignal.h b/ios/RCTOneSignal/RCTOneSignal.h index c470f1a3..3d9716a6 100644 --- a/ios/RCTOneSignal/RCTOneSignal.h +++ b/ios/RCTOneSignal/RCTOneSignal.h @@ -1,6 +1,7 @@ #if __has_include() #import +#import #else #import "../OneSignalFramework.h" #endif diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h index 0bc07bf1..fdc2a0ff 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h @@ -37,8 +37,10 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { #define OSEventString(enum) [OSNotificationEventTypesArray objectAtIndex:enum] +@protocol OSNotificationLifecycleListener; + @interface RCTOneSignalEventEmitter - : NativeOneSignalSpecBase + : NativeOneSignalSpecBase + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body; diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 8898eaf3..fbe40de2 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -1,7 +1,8 @@ #import "RCTOneSignalEventEmitter.h" -#import "OneSignalLiveActivities/OneSignalLiveActivities-Swift.h" -#import "RCTOneSignal.h" #import +#import +#import +#import "RCTOneSignal.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -51,7 +52,6 @@ - (void)invalidate { [self removeHandlers]; [self removeObservers]; [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super invalidate]; } - (NSArray *)processNSError:(NSError *)error { @@ -67,6 +67,10 @@ - (void)invalidate { #pragma mark Send Event Methods - (void)emitEvent:(NSNotification *)notification { + if (!_eventEmitterCallback) { + return; + } + NSString *name = notification.name; NSDictionary *body = notification.userInfo; @@ -234,12 +238,12 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } // OneSignal.Debug namespace methods -RCT_EXPORT_METHOD(setLogLevel : (int)logLevel) { - [OneSignal.Debug setLogLevel:logLevel]; +RCT_EXPORT_METHOD(setLogLevel : (double)logLevel) { + [OneSignal.Debug setLogLevel:(ONE_S_LOG_LEVEL)(int)logLevel]; } -RCT_EXPORT_METHOD(setAlertLevel : (int)logLevel) { - [OneSignal.Debug setAlertLevel:logLevel]; +RCT_EXPORT_METHOD(setAlertLevel : (double)logLevel) { + [OneSignal.Debug setAlertLevel:(ONE_S_LOG_LEVEL)(int)logLevel]; } // OneSignal.InAppMessages namespace methods @@ -419,8 +423,8 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } RCT_EXPORT_METHOD(addOutcomeWithValue : (NSString *)name - value : (NSNumber *_Nonnull)value) { - [OneSignal.Session addOutcomeWithValue:name value:value]; + value : (double)value) { + [OneSignal.Session addOutcomeWithValue:name value:@(value)]; } // OneSignal.User namespace methods diff --git a/package.json b/package.json index 4e420acd..ca391099 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,11 @@ "jsSrcsDir": "src", "android": { "javaPackageName": "com.onesignal.rnonesignalandroid" + }, + "ios": { + "modulesProvider": { + "OneSignal": "RCTOneSignalEventEmitter" + } } }, "peerDependencies": { From 776822d591992d4f4382cdd93bb30e2bdff0840a Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 18:49:08 -0700 Subject: [PATCH 19/25] refactor(ios): remove legacy Xcode project and update imports --- examples/demo/bun.lock | 2 +- ios/RCTOneSignal/RCTOneSignal.mm | 51 ------------------- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 43 +++++++--------- ios/RCTOneSignal/UIApplication+RCTOnesignal.m | 2 - 4 files changed, 18 insertions(+), 80 deletions(-) diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index cfaee04c..138b2200 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-TNLDqNz7CaQayuuwDia3uMt9qybeMdxMUCzYdRCz4xz4QN4SDk8MNeHntsfm8FNhUidcujDiqDUXUNJ549CODQ=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-LKq3nsUYlCy9AQ/9kp0WuchjjnuowXPlx0aLBobrp1BNLkA+IqoJnLjx8+St3vBaKTHSEsp65LvkRnmHRlzxlA=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/ios/RCTOneSignal/RCTOneSignal.mm b/ios/RCTOneSignal/RCTOneSignal.mm index dd49fa06..6138781a 100644 --- a/ios/RCTOneSignal/RCTOneSignal.mm +++ b/ios/RCTOneSignal/RCTOneSignal.mm @@ -1,28 +1,6 @@ -#if __has_include() -#import -#import -#import -#import -#else -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTUtils.h" -#endif - #import "RCTOneSignal.h" #import "RCTOneSignalEventEmitter.h" -#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 - -#define UIUserNotificationTypeAlert UIRemoteNotificationTypeAlert -#define UIUserNotificationTypeBadge UIRemoteNotificationTypeBadge -#define UIUserNotificationTypeSound UIRemoteNotificationTypeSound -#define UIUserNotificationTypeNone UIRemoteNotificationTypeNone -#define UIUserNotificationType UIRemoteNotificationType - -#endif - @interface RCTOneSignal () @end @@ -30,8 +8,6 @@ @implementation RCTOneSignal { BOOL didInitialize; } -OSNotificationClickResult *coldStartOSNotificationClickResult; - + (RCTOneSignal *)sharedInstance { static dispatch_once_t token = 0; static id _sharedInstance = nil; @@ -54,29 +30,6 @@ - (void)initOneSignal:(NSDictionary *)launchOptions { didInitialize = true; } -- (void)handleRemoteNotificationOpened:(NSString *)result { - NSDictionary *json = [self jsonObjectWithString:result]; - - if (json) { - [self sendEvent:OSEventString(NotificationClicked) withBody:json]; - } -} - -- (NSDictionary *)jsonObjectWithString:(NSString *)jsonString { - NSError *jsonError; - NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *json = - [NSJSONSerialization JSONObjectWithData:data - options:NSJSONReadingMutableContainers - error:&jsonError]; - - if (jsonError) { - return nil; - } - - return json; -} - - (void)sendEvent:(NSString *)eventName withBody:(NSDictionary *)body { [RCTOneSignalEventEmitter sendEventWithName:eventName withBody:body]; } @@ -176,8 +129,4 @@ - (void)onDidDismissInAppMessage: withBody:[event jsonRepresentation]]; } -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - @end diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index fbe40de2..5f8ff3cd 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -6,6 +6,10 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +@interface RCTOneSignalEventEmitter () +- (void)emitEventWithName:(NSString *)name body:(NSDictionary *)body; +@end + @implementation RCTOneSignalEventEmitter { BOOL _hasSetSubscriptionObserver; BOOL _hasSetPermissionObserver; @@ -31,12 +35,6 @@ - (instancetype)init { _preventDefaultCache = [NSMutableDictionary new]; _notificationWillDisplayCache = [NSMutableDictionary new]; - for (NSString *eventName in OSNotificationEventTypesArray) - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(emitEvent:) - name:eventName - object:nil]; - // Clean up previous instance if it exists (handles reload scenario) if (_currentInstance != nil && _currentInstance != self) { [_currentInstance removeHandlers]; @@ -51,7 +49,11 @@ - (instancetype)init { - (void)invalidate { [self removeHandlers]; [self removeObservers]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [_preventDefaultCache removeAllObjects]; + [_notificationWillDisplayCache removeAllObjects]; + if (_currentInstance == self) { + _currentInstance = nil; + } } - (NSArray *)processNSError:(NSError *)error { @@ -66,14 +68,11 @@ - (void)invalidate { #pragma mark Send Event Methods -- (void)emitEvent:(NSNotification *)notification { +- (void)emitEventWithName:(NSString *)name body:(NSDictionary *)body { if (!_eventEmitterCallback) { return; } - NSString *name = notification.name; - NSDictionary *body = notification.userInfo; - if ([name isEqualToString:OSEventString(PermissionChanged)]) { [self emitOnPermissionChanged:body]; } else if ([name isEqualToString:OSEventString(SubscriptionChanged)]) { @@ -99,9 +98,7 @@ - (void)emitEvent:(NSNotification *)notification { } + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { - [[NSNotificationCenter defaultCenter] postNotificationName:name - object:nil - userInfo:body]; + [_currentInstance emitEventWithName:name body:body]; } #pragma mark Exported Methods @@ -341,7 +338,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } } -RCT_EXPORT_METHOD(removePermissionObserver) { +- (void)removePermissionObserver { if (_hasSetPermissionObserver) { [OneSignal.Notifications removePermissionObserver:[RCTOneSignal sharedInstance]]; @@ -370,13 +367,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { RCT_EXPORT_METHOD(onWillDisplayNotification : (OSNotificationWillDisplayEvent *) event) { - __weak RCTOneSignalEventEmitter *weakSelf = self; - RCTOneSignalEventEmitter *strongSelf = weakSelf; - if (!strongSelf) - return; - - strongSelf->_notificationWillDisplayCache[event.notification.notificationId] = - event; + _notificationWillDisplayCache[event.notification.notificationId] = event; [event preventDefault]; [RCTOneSignalEventEmitter sendEventWithName:@"OneSignal-notificationWillDisplayInForeground" @@ -384,8 +375,6 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } RCT_EXPORT_METHOD(preventDefault : (NSString *)notificationId) { - __weak RCTOneSignalEventEmitter *weakSelf = self; - RCTOneSignalEventEmitter *strongSelf = weakSelf; OSNotificationWillDisplayEvent *event = _notificationWillDisplayCache[notificationId]; if (!event) { @@ -398,7 +387,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { notificationId]]; return; } - strongSelf->_preventDefaultCache[event.notification.notificationId] = event; + _preventDefaultCache[event.notification.notificationId] = event; [event preventDefault]; } @@ -442,7 +431,7 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body { } } -RCT_EXPORT_METHOD(removePushSubscriptionObserver) { +- (void)removePushSubscriptionObserver { if (_hasSetSubscriptionObserver) { [OneSignal.User.pushSubscription removeObserver:[RCTOneSignal sharedInstance]]; @@ -625,3 +614,5 @@ - (void)removeUserStateObserver { } @end + +#pragma GCC diagnostic pop diff --git a/ios/RCTOneSignal/UIApplication+RCTOnesignal.m b/ios/RCTOneSignal/UIApplication+RCTOnesignal.m index e2abbc56..d7353ba3 100644 --- a/ios/RCTOneSignal/UIApplication+RCTOnesignal.m +++ b/ios/RCTOneSignal/UIApplication+RCTOnesignal.m @@ -3,8 +3,6 @@ @interface RCTOneSignal + (RCTOneSignal *)sharedInstance; -- (void)initialize:(nonnull NSString *)newAppId - withLaunchOptions:(nullable NSDictionary *)launchOptions; - (void)initOneSignal:(NSDictionary *)launchOptions; @end From 42031e96b9acbf8f9ffeee99b528c188d3d29b4b Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 18:55:18 -0700 Subject: [PATCH 20/25] refactor(android): update SDK versions and dependencies --- android/build.gradle | 12 +++----- android/proguard-rules.pro | 19 ++----------- .../rnonesignalandroid/RNOneSignal.java | 28 +++++++++---------- .../onesignal/rnonesignalandroid/RNUtils.java | 4 +-- android/src/main/res/values/strings.xml | 3 -- 5 files changed, 21 insertions(+), 45 deletions(-) delete mode 100644 android/src/main/res/values/strings.xml diff --git a/android/build.gradle b/android/build.gradle index 07933cb9..50d51322 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,11 +7,10 @@ def safeExtGet(prop, fallback) { android { namespace "com.onesignal.rnonesignalandroid" - compileSdkVersion safeExtGet('compileSdkVersion', 28) - buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') + compileSdkVersion safeExtGet('compileSdkVersion', 34) defaultConfig { - minSdkVersion safeExtGet('minSdkVersion', 16) + minSdkVersion safeExtGet('minSdkVersion', 21) } buildTypes { release { @@ -20,16 +19,13 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } } dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" // api is used instead of implementation so the parent :app project can access any of the OneSignal Java // classes if needed. Such as com.onesignal.NotificationExtenderService diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro index 38140b70..4bf98e1d 100644 --- a/android/proguard-rules.pro +++ b/android/proguard-rules.pro @@ -1,17 +1,2 @@ -# 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.4.1_1/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: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} +# OneSignal SDK ships its own consumer proguard rules. +# Add project-specific rules here if needed. diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java index 06610dac..7b3c395d 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -80,8 +80,6 @@ public class RNOneSignal extends NativeOneSignalSpec INotificationLifecycleListener { public static final String NAME = "OneSignal"; - private ReactApplicationContext mReactApplicationContext; - private boolean oneSignalInitDone; private boolean hasSetPermissionObserver = false; private boolean hasSetPushSubscriptionObserver = false; @@ -194,8 +192,7 @@ private void removeObservers() { public RNOneSignal(ReactApplicationContext reactContext) { super(reactContext); - mReactApplicationContext = reactContext; - mReactApplicationContext.addLifecycleEventListener(this); + reactContext.addLifecycleEventListener(this); notificationWillDisplayCache = new HashMap(); preventDefaultCache = new HashMap(); @@ -229,7 +226,6 @@ public void onCatalystInstanceDestroy() { @Override public void initialize(String appId) { - Context context = mReactApplicationContext.getCurrentActivity(); OneSignalWrapper.setSdkType("reactnative"); OneSignalWrapper.setSdkVersion("050213"); @@ -238,10 +234,10 @@ public void initialize(String appId) { return; } + ReactApplicationContext reactContext = getReactApplicationContext(); + Context context = reactContext.getCurrentActivity(); if (context == null) { - // in some cases, especially when react-native-navigation is installed, - // the activity can be null, so we can initialize with the context instead - context = mReactApplicationContext.getApplicationContext(); + context = reactContext.getApplicationContext(); } OneSignal.initWithContext(context, appId); @@ -362,7 +358,7 @@ public void onWillDisplay(INotificationWillDisplayEvent event) { INotification notification = event.getNotification(); String notificationId = notification.getNotificationId(); - notificationWillDisplayCache.put(notificationId, (INotificationWillDisplayEvent) event); + notificationWillDisplayCache.put(notificationId, event); event.preventDefault(); try { @@ -686,19 +682,21 @@ public void removeAliases(ReadableArray aliasLabels) { @Override public void getOnesignalId(Promise promise) { String onesignalId = OneSignal.getUser().getOnesignalId(); - if (onesignalId.isEmpty()) { - onesignalId = null; + if (onesignalId == null || onesignalId.isEmpty()) { + promise.resolve(null); + } else { + promise.resolve(onesignalId); } - promise.resolve(onesignalId); } @Override public void getExternalId(Promise promise) { String externalId = OneSignal.getUser().getExternalId(); - if (externalId.isEmpty()) { - externalId = null; + if (externalId == null || externalId.isEmpty()) { + promise.resolve(null); + } else { + promise.resolve(externalId); } - promise.resolve(externalId); } @Override diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java index 29d1f722..639d5ba0 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java @@ -171,7 +171,7 @@ public static HashMap convertInAppMessageClickEventToMap(IInAppM return hash; } - public static HashMap convertPushSubscriptionStateToMap(PushSubscriptionState state) { + private static HashMap convertPushSubscriptionStateToMap(PushSubscriptionState state) { HashMap hash = new HashMap<>(); if (state.getToken() != null && !state.getToken().isEmpty()) { hash.put("token", state.getToken()); @@ -188,7 +188,7 @@ public static HashMap convertPushSubscriptionStateToMap(PushSubs return hash; } - public static HashMap convertUserStateToMap(UserState user) { + private static HashMap convertUserStateToMap(UserState user) { HashMap hash = new HashMap<>(); if (user.getExternalId() != null && !user.getExternalId().isEmpty()) { diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml deleted file mode 100644 index dbb95e8b..00000000 --- a/android/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - RNOneSignalAndroid - From ea1d5678947dbc7ce56b50912e14dd87f1451c2a Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 12 Mar 2026 19:01:17 -0700 Subject: [PATCH 21/25] more clean up --- .../rnonesignalandroid/RNOneSignal.java | 45 +- bun.lock | 439 ++++++++++-------- bun.lockb | Bin 192588 -> 0 bytes examples/demo/App.tsx | 121 +++-- examples/demo/bun.lock | 2 +- examples/run-android.sh | 2 +- examples/run-ios.sh | 2 +- ios/RCTOneSignal/RCTOneSignalEventEmitter.h | 9 +- ios/RCTOneSignal/RCTOneSignalEventEmitter.mm | 7 +- package.json | 4 +- 10 files changed, 351 insertions(+), 280 deletions(-) delete mode 100755 bun.lockb diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java index 7b3c395d..148c3cb9 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -85,8 +85,8 @@ public class RNOneSignal extends NativeOneSignalSpec private boolean hasSetPushSubscriptionObserver = false; private boolean hasSetUserStateObserver = false; - private HashMap notificationWillDisplayCache; - private HashMap preventDefaultCache; + private final HashMap notificationWillDisplayCache = new HashMap<>(); + private final HashMap preventDefaultCache = new HashMap<>(); private boolean hasAddedNotificationForegroundListener = false; private boolean hasAddedInAppMessageLifecycleListener = false; @@ -96,26 +96,26 @@ public class RNOneSignal extends NativeOneSignalSpec // Static reference to track current instance for cleanup on reload private static RNOneSignal currentInstance = null; - private IInAppMessageClickListener rnInAppClickListener = new IInAppMessageClickListener() { + private final IInAppMessageClickListener rnInAppClickListener = new IInAppMessageClickListener() { @Override public void onClick(IInAppMessageClickEvent event) { try { emitOnInAppMessageClicked( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageClickEventToMap(event))); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onInAppMessageClicked", e); } } }; - private IInAppMessageLifecycleListener rnInAppLifecycleListener = new IInAppMessageLifecycleListener() { + private final IInAppMessageLifecycleListener rnInAppLifecycleListener = new IInAppMessageLifecycleListener() { @Override public void onWillDisplay(IInAppMessageWillDisplayEvent event) { try { emitOnInAppMessageWillDisplay( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageWillDisplayEventToMap(event))); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onInAppMessageWillDisplay", e); } } @@ -125,7 +125,7 @@ public void onDidDisplay(IInAppMessageDidDisplayEvent event) { emitOnInAppMessageDidDisplay( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageDidDisplayEventToMap(event))); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onInAppMessageDidDisplay", e); } } @@ -135,7 +135,7 @@ public void onWillDismiss(IInAppMessageWillDismissEvent event) { emitOnInAppMessageWillDismiss( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageWillDismissEventToMap(event))); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onInAppMessageWillDismiss", e); } } @@ -145,23 +145,27 @@ public void onDidDismiss(IInAppMessageDidDismissEvent event) { emitOnInAppMessageDidDismiss( RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageDidDismissEventToMap(event))); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onInAppMessageDidDismiss", e); } } }; - private INotificationClickListener rnNotificationClickListener = new INotificationClickListener() { + private final INotificationClickListener rnNotificationClickListener = new INotificationClickListener() { @Override public void onClick(INotificationClickEvent event) { try { emitOnNotificationClicked( RNUtils.convertHashMapToWritableMap(RNUtils.convertNotificationClickEventToMap(event))); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onNotificationClicked", e); } } }; + private void logJSONException(String eventName, JSONException exception) { + Logging.error("Failed to serialize payload for " + eventName, exception); + } + private void removeObservers() { if (!oneSignalInitDone) { Logging.debug("OneSignal React-Native SDK not initialized yet. Could not remove observers.", null); @@ -193,8 +197,6 @@ private void removeObservers() { public RNOneSignal(ReactApplicationContext reactContext) { super(reactContext); reactContext.addLifecycleEventListener(this); - notificationWillDisplayCache = new HashMap(); - preventDefaultCache = new HashMap(); // Clean up previous instance if it exists (handles reload scenario) if (currentInstance != null && currentInstance != this) { @@ -220,8 +222,9 @@ public void onHostPause() {} public void onHostResume() {} @Override - public void onCatalystInstanceDestroy() { + public void invalidate() { removeObservers(); + super.invalidate(); } @Override @@ -375,7 +378,7 @@ public void onWillDisplay(INotificationWillDisplayEvent event) { Logging.error("InterruptedException: " + e.toString(), null); } } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onNotificationWillDisplay", e); } } @@ -410,7 +413,7 @@ public void addPermissionObserver() { } } - public void removePermissionObserver() { + private void removePermissionObserver() { if (hasSetPermissionObserver) { OneSignal.getNotifications().removePermissionObserver(this); hasSetPermissionObserver = false; @@ -423,7 +426,7 @@ public void onNotificationPermissionChange(boolean permission) { emitOnPermissionChanged(RNUtils.convertHashMapToWritableMap(RNUtils.convertPermissionToMap(permission))); Logging.debug("Sending permission change event", null); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onPermissionChanged", e); } } @@ -568,11 +571,11 @@ public void onPushSubscriptionChange(PushSubscriptionChangedState pushSubscripti RNUtils.convertPushSubscriptionChangedStateToMap(pushSubscriptionChangedState))); Logging.debug("Sending subscription change event", null); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onSubscriptionChanged", e); } } - public void removePushSubscriptionObserver() { + private void removePushSubscriptionObserver() { if (hasSetPushSubscriptionObserver) { OneSignal.getUser().getPushSubscription().removeObserver(this); hasSetPushSubscriptionObserver = false; @@ -713,11 +716,11 @@ public void onUserStateChange(UserChangedState state) { emitOnUserStateChanged(RNUtils.convertHashMapToWritableMap(RNUtils.convertUserChangedStateToMap(state))); Logging.debug("Sending user state change event", null); } catch (JSONException e) { - e.printStackTrace(); + logJSONException("onUserStateChanged", e); } } - public void removeUserStateObserver() { + private void removeUserStateObserver() { if (hasSetUserStateObserver) { OneSignal.getUser().removeObserver(this); hasSetUserStateObserver = false; diff --git a/bun.lock b/bun.lock index 87862bfe..081472cb 100644 --- a/bun.lock +++ b/bun.lock @@ -1,6 +1,6 @@ { "lockfileVersion": 1, - "configVersion": 0, + "configVersion": 1, "workspaces": { "": { "name": "react-native-onesignal", @@ -19,26 +19,29 @@ "vite-plugin-dts": "^4.5.4", "vitest": "^4.0.8", }, + "peerDependencies": { + "react-native": ">=0.76.0", + }, }, }, "packages": { - "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], - "@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="], + "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], - "@babel/core": ["@babel/core@7.28.5", "", { "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" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="], + "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@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" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], - "@babel/generator": ["@babel/generator@7.28.5", "", { "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" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="], + "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "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" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="], + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="], + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="], + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], @@ -46,9 +49,9 @@ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], - "@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="], + "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], - "@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="], + "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], "@babel/plugin-syntax-async-generators": ["@babel/plugin-syntax-async-generators@7.8.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw=="], @@ -58,7 +61,7 @@ "@babel/plugin-syntax-class-static-block": ["@babel/plugin-syntax-class-static-block@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw=="], - "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww=="], + "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw=="], "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="], @@ -80,73 +83,67 @@ "@babel/plugin-syntax-top-level-await": ["@babel/plugin-syntax-top-level-await@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw=="], - "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], - - "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], - "@babel/traverse": ["@babel/traverse@7.28.5", "", { "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" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="], + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], - "@babel/traverse--for-generate-function-map": ["@babel/traverse@7.28.5", "", { "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" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="], + "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], - "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="], - "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], - - "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="], "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], @@ -178,113 +175,141 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - "@microsoft/api-extractor": ["@microsoft/api-extractor@7.54.0", "", { "dependencies": { "@microsoft/api-extractor-model": "7.31.3", "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", "@rushstack/node-core-library": "5.18.0", "@rushstack/rig-package": "0.6.0", "@rushstack/terminal": "0.19.3", "@rushstack/ts-command-line": "5.1.3", "diff": "~8.0.2", "lodash": "~4.17.15", "minimatch": "10.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", "typescript": "5.8.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "sha512-t0SEcbVUPy4yAVykPafTNWktBg728X6p9t8qCuGDsYr1/lz2VQFihYDP2CnBFSArP5vwJPcvxktoKVSqH326cA=="], + "@microsoft/api-extractor": ["@microsoft/api-extractor@7.57.7", "", { "dependencies": { "@microsoft/api-extractor-model": "7.33.4", "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.1", "@rushstack/node-core-library": "5.20.3", "@rushstack/rig-package": "0.7.2", "@rushstack/terminal": "0.22.3", "@rushstack/ts-command-line": "5.3.3", "diff": "~8.0.2", "lodash": "~4.17.23", "minimatch": "10.2.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", "typescript": "5.8.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "sha512-kmnmVs32MFWbV5X6BInC1/TfCs7y1ugwxv1xHsAIj/DyUfoe7vtO0alRUgbQa57+yRGHBBjlNcEk33SCAt5/dA=="], + + "@microsoft/api-extractor-model": ["@microsoft/api-extractor-model@7.33.4", "", { "dependencies": { "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.1", "@rushstack/node-core-library": "5.20.3" } }, "sha512-u1LTaNTikZAQ9uK6KG1Ms7nvNedsnODnspq/gH2dcyETWvH4hVNGNDvRAEutH66kAmxA4/necElqGNs1FggC8w=="], + + "@microsoft/tsdoc": ["@microsoft/tsdoc@0.16.0", "", {}, "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA=="], + + "@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.18.1", "", { "dependencies": { "@microsoft/tsdoc": "0.16.0", "ajv": "~8.18.0", "jju": "~1.4.0", "resolve": "~1.22.2" } }, "sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg=="], + + "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.55.0", "", { "os": "android", "cpu": "arm" }, "sha512-NhvgAhncTSOhRahQSCnkK/4YIGPjTmhPurQQ2dwt2IvwCMTvZRW5vF2K10UBOxFve4GZDMw6LtXZdC2qeuYIVQ=="], + + "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.55.0", "", { "os": "android", "cpu": "arm64" }, "sha512-P9iWRh+Ugqhg+D7rkc7boHX8o3H2h7YPcZHQIgvVBgnua5tk4LR2L+IBlreZs58/95cd2x3/004p5VsQM9z4SA=="], + + "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.55.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-esakkJIt7WFAhT30P/Qzn96ehFpzdZ1mNuzpOb8SCW7lI4oB8VsyQnkSHREM671jfpuBb/o2ppzBCx5l0jpgMA=="], - "@microsoft/api-extractor-model": ["@microsoft/api-extractor-model@7.31.3", "", { "dependencies": { "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", "@rushstack/node-core-library": "5.18.0" } }, "sha512-dv4quQI46p0U03TCEpasUf6JrJL3qjMN7JUAobsPElxBv4xayYYvWW9aPpfYV+Jx6hqUcVaLVOeV7+5hxsyoFQ=="], + "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.55.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-xDMFRCCAEK9fOH6As2z8ELsC+VDGSFRHwIKVSilw+xhgLwTDFu37rtmRbmUlx8rRGS6cWKQPTc47AVxAZEVVPQ=="], - "@microsoft/tsdoc": ["@microsoft/tsdoc@0.15.1", "", {}, "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw=="], + "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.55.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mYZqnwUD7ALCRxGenyLd1uuG+rHCL+OTT6S8FcAbVm/ZT2AZMGjvibp3F6k1SKOb2aeqFATmwRykrE41Q0GWVw=="], - "@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.17.1", "", { "dependencies": { "@microsoft/tsdoc": "0.15.1", "ajv": "~8.12.0", "jju": "~1.4.0", "resolve": "~1.22.2" } }, "sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw=="], + "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.55.0", "", { "os": "linux", "cpu": "arm" }, "sha512-LcX6RYcF9vL9ESGwJW3yyIZ/d/ouzdOKXxCdey1q0XJOW1asrHsIg5MmyKdEBR4plQx+shvYeQne7AzW5f3T1w=="], - "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.26.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kTmm1opqyn7iZopWHO3Ml4D/44pA5eknZBepgxCnTaPrW8XgCEUI85Q5AvOOvoNve8NziTYb8ax+CyuGJIgn/Q=="], + "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.55.0", "", { "os": "linux", "cpu": "arm" }, "sha512-C+8GS1rPtK+dI7mJFkqoRBkDuqbrNihnyYQsJPS9ez+8zF9JzfvU19lawqt4l/Y23o5uQswE/DORa8aiXUih3w=="], - "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.26.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-/hMfZ9j7ZzVPRmMm02PHNc6MIMk0QYv5VowZJRIp40YLqLPvFfGNGZBj8e1fDVgZMFEGWDQK3yrt1uBKxXAK4Q=="], + "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.55.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ErLE4XbmcCopA4/CIDiH6J1IAaDOMnf/KSx/aFObs4/OjAAM3sFKWGZ57pNOMxhhyBdcmcXwYymph9GwcpcqgQ=="], - "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.26.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-iv4wdrwdCa8bhJxOpKlvfxqTs0LgW5tKBUMvH9B13zREHm1xT9JRZ8cQbbKiyC6LNdggwu5S6TSvODgAu7/DlA=="], + "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.55.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-/kp65avi6zZfqEng56TTuhiy3P/3pgklKIdf38yvYeJ9/PgEeRA2A2AqKAKbZBNAqUzrzHhz9jF6j/PZvhJzTQ=="], - "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.26.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-a3gTbnN1JzedxqYeGTkg38BAs/r3Krd2DPNs/MF7nnHthT3RzkPUk47isMePLuNc4e/Weljn7m2m/Onx22tiNg=="], + "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.55.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-A6pTdXwcEEwL/nmz0eUJ6WxmxcoIS+97GbH96gikAyre3s5deC7sts38ZVVowjS2QQFuSWkpA4ZmQC0jZSNvJQ=="], - "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.26.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cCAyqyuKpFImjlgiBuuwSF+aDBW2h19/aCmHMTMSp6KXwhoQK7/Xx7/EhZKP5wiQJzVUYq5fXr0D8WmpLGsjRg=="], + "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.55.0", "", { "os": "linux", "cpu": "none" }, "sha512-clj0lnIN+V52G9tdtZl0LbdTSurnZ1NZj92Je5X4lC7gP5jiCSW+Y/oiDiSauBAD4wrHt2S7nN3pA0zfKYK/6Q=="], - "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.26.0", "", { "os": "linux", "cpu": "x64" }, "sha512-8VOJ4vQo0G1tNdaghxrWKjKZGg73tv+FoMDrtNYuUesqBHZN68FkYCsgPwEsacLhCmtoZrkF3ePDWDuWEpDyAg=="], + "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.55.0", "", { "os": "linux", "cpu": "none" }, "sha512-NNu08pllN5x/O94/sgR3DA8lbrGBnTHsINZZR0hcav1sj79ksTiKKm1mRzvZvacwQ0hUnGinFo+JO75ok2PxYg=="], - "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.26.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-N8KUtzP6gfEHKvaIBZCS9g8wRfqV5v55a/B8iJjIEhtMehcEM+UX+aYRsQ4dy5oBCrK3FEp4Yy/jHgb0moLm3Q=="], + "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.55.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-BvfQz3PRlWZRoEZ17dZCqgQsMRdpzGZomJkVATwCIGhHVVeHJMQdmdXPSjcT1DCNUrOjXnVyj1RGDj5+/Je2+Q=="], - "@oxlint/win32-x64": ["@oxlint/win32-x64@1.26.0", "", { "os": "win32", "cpu": "x64" }, "sha512-7tCyG0laduNQ45vzB9blVEGq/6DOvh7AFmiUAana8mTp0zIKQQmwJ21RqhazH0Rk7O6lL7JYzKcu+zaJHGpRLA=="], + "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.55.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ngSOoFCSBMKVQd24H8zkbcBNc7EHhjnF1sv3mC9NNXQ/4rRjI/4Dj9+9XoDZeFEkF1SX1COSBXF1b2Pr9rqdEw=="], - "@react-native/assets-registry": ["@react-native/assets-registry@0.82.1", "", {}, "sha512-B1SRwpntaAcckiatxbjzylvNK562Ayza05gdJCjDQHTiDafa1OABmyB5LHt7qWDOpNkaluD+w11vHF7pBmTpzQ=="], + "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.55.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BDpP7W8GlaG7BR6QjGZAleYzxoyKc/D24spZIF2mB3XsfALQJJT/OBmP8YpeTb1rveFSBHzl8T7l0aqwkWNdGA=="], - "@react-native/codegen": ["@react-native/codegen@0.82.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.32.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-ezXTN70ygVm9l2m0i+pAlct0RntoV4afftWMGUIeAWLgaca9qItQ54uOt32I/9dBJvzBibT33luIR/pBG0dQvg=="], + "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.55.0", "", { "os": "none", "cpu": "arm64" }, "sha512-PS6GFvmde/pc3fCA2Srt51glr8Lcxhpf6WIBFfLphndjRrD34NEcses4TSxQrEcxYo6qVywGfylM0ZhSCF2gGA=="], - "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.82.1", "", { "dependencies": { "@react-native/dev-middleware": "0.82.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" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "*" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-H/eMdtOy9nEeX7YVeEG1N2vyCoifw3dr9OV8++xfUElNYV7LtSmJ6AqxZUUfxGJRDFPQvaU/8enmJlM/l11VxQ=="], + "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.55.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-P6JcLJGs/q1UOvDLzN8otd9JsH4tsuuPDv+p7aHqHM3PrKmYdmUvkNj4K327PTd35AYcznOCN+l4ZOaq76QzSw=="], - "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.82.1", "", {}, "sha512-a2O6M7/OZ2V9rdavOHyCQ+10z54JX8+B+apYKCQ6a9zoEChGTxUMG2YzzJ8zZJVvYf1ByWSNxv9Se0dca1hO9A=="], + "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.55.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-gzkk4zE2zsE+WmRxFOiAZHpCpUNDFytEakqNXoNHW+PnYEOTPKDdW6nrzgSeTbGKVPXNAKQnRnMgrh7+n3Xueg=="], - "@react-native/debugger-shell": ["@react-native/debugger-shell@0.82.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "fb-dotslash": "0.5.8" } }, "sha512-fdRHAeqqPT93bSrxfX+JHPpCXHApfDUdrXMXhoxlPgSzgXQXJDykIViKhtpu0M6slX6xU/+duq+AtP/qWJRpBw=="], + "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.55.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZFALNow2/og75gvYzNP7qe+rREQ5xunktwA+lgykoozHZ6hw9bqg4fn5j2UvG4gIn1FXqrZHkOAXuPf5+GOYTQ=="], - "@react-native/dev-middleware": ["@react-native/dev-middleware@0.82.1", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.82.1", "@react-native/debugger-shell": "0.82.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" } }, "sha512-wuOIzms/Qg5raBV6Ctf2LmgzEOCqdP3p1AYN4zdhMT110c39TVMbunpBaJxm0Kbt2HQ762MQViF9naxk7SBo4w=="], + "@react-native/assets-registry": ["@react-native/assets-registry@0.84.1", "", {}, "sha512-lAJ6PDZv95FdT9s9uhc9ivhikW1Zwh4j9XdXM7J2l4oUA3t37qfoBmTSDLuPyE3Bi+Xtwa11hJm0BUTT2sc/gg=="], - "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.82.1", "", {}, "sha512-KkF/2T1NSn6EJ5ALNT/gx0MHlrntFHv8YdooH9OOGl9HQn5NM0ZmQSr86o5utJsGc7ME3R6p3SaQuzlsFDrn8Q=="], + "@react-native/codegen": ["@react-native/codegen@0.84.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "hermes-parser": "0.32.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-n1RIU0QAavgCg1uC5+s53arL7/mpM+16IBhJ3nCFSd/iK5tUmCwxQDcIDC703fuXfpub/ZygeSjVN8bcOWn0gA=="], - "@react-native/js-polyfills": ["@react-native/js-polyfills@0.82.1", "", {}, "sha512-tf70X7pUodslOBdLN37J57JmDPB/yiZcNDzS2m+4bbQzo8fhx3eG9QEBv5n4fmzqfGAgSB4BWRHgDMXmmlDSVA=="], + "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.84.1", "", { "dependencies": { "@react-native/dev-middleware": "0.84.1", "debug": "^4.4.0", "invariant": "^2.2.4", "metro": "^0.83.3", "metro-config": "^0.83.3", "metro-core": "^0.83.3", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "*" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-f6a+mJEJ6Joxlt/050TqYUr7uRRbeKnz8lnpL7JajhpsgZLEbkJRjH8HY5QiLcRdUwWFtizml4V+vcO3P4RxoQ=="], - "@react-native/normalize-colors": ["@react-native/normalize-colors@0.82.1", "", {}, "sha512-CCfTR1uX+Z7zJTdt3DNX9LUXr2zWXsNOyLbwupW2wmRzrxlHRYfmLgTABzRL/cKhh0Ubuwn15o72MQChvCRaHw=="], + "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.84.1", "", {}, "sha512-rUU/Pyh3R5zT0WkVgB+yA6VwOp7HM5Hz4NYE97ajFS07OUIcv8JzBL3MXVdSSjLfldfqOuPEuKUaZcAOwPgabw=="], - "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.82.1", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-f5zpJg9gzh7JtCbsIwV+4kP3eI0QBuA93JGmwFRd4onQ3DnCjV2J5pYqdWtM95sjSKK1dyik59Gj01lLeKqs1Q=="], + "@react-native/debugger-shell": ["@react-native/debugger-shell@0.84.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "debug": "^4.4.0", "fb-dotslash": "0.5.8" } }, "sha512-LIGhh4q4ette3yW5OzmukNMYwmINYrRGDZqKyTYc/VZyNpblZPw72coXVHXdfpPT6+YlxHqXzn3UjFZpNODGCQ=="], + + "@react-native/dev-middleware": ["@react-native/dev-middleware@0.84.1", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.84.1", "@react-native/debugger-shell": "0.84.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": "^7.5.10" } }, "sha512-Z83ra+Gk6ElAhH3XRrv3vwbwCPTb04sPPlNpotxcFZb5LtRQZwT91ZQEXw3GOJCVIFp9EQ/gj8AQbVvtHKOUlQ=="], + + "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.84.1", "", {}, "sha512-7uVlPBE3uluRNRX4MW7PUJIO1LDBTpAqStKHU7LHH+GRrdZbHsWtOEAX8PiY4GFfBEvG8hEjiuTOqAxMjV+hDg=="], + + "@react-native/js-polyfills": ["@react-native/js-polyfills@0.84.1", "", {}, "sha512-UsTe2AbUugsfyI7XIHMQq4E7xeC8a6GrYwuK+NohMMMJMxmyM3JkzIk+GB9e2il6ScEQNMJNaj+q+i5za8itxQ=="], + + "@react-native/normalize-colors": ["@react-native/normalize-colors@0.84.1", "", {}, "sha512-/UPaQ4jl95soXnLDEJ6Cs6lnRXhwbxtT4KbZz+AFDees7prMV2NOLcHfCnzmTabf5Y3oxENMVBL666n4GMLcTA=="], + + "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.84.1", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.2.0", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-sJoDunzhci8ZsqxlUiKoLut4xQeQcmbIgvDHGQKeBz6uEq9HgU+hCWOijMRr6sLP0slQVfBAza34Rq7IbXZZOA=="], "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="], - "@rushstack/node-core-library": ["@rushstack/node-core-library@5.18.0", "", { "dependencies": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.5.4" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-XDebtBdw5S3SuZIt+Ra2NieT8kQ3D2Ow1HxhDQ/2soinswnOu9e7S69VSwTOLlQnx5mpWbONu+5JJjDxMAb6Fw=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="], - "@rushstack/problem-matcher": ["@rushstack/problem-matcher@0.1.1", "", { "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="], - "@rushstack/rig-package": ["@rushstack/rig-package@0.6.0", "", { "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" } }, "sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="], - "@rushstack/terminal": ["@rushstack/terminal@0.19.3", "", { "dependencies": { "@rushstack/node-core-library": "5.18.0", "@rushstack/problem-matcher": "0.1.1", "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-0P8G18gK9STyO+CNBvkKPnWGMxESxecTYqOcikHOVIHXa9uAuTK+Fw8TJq2Gng1w7W6wTC9uPX6hGNvrMll2wA=="], + "@rushstack/node-core-library": ["@rushstack/node-core-library@5.20.3", "", { "dependencies": { "ajv": "~8.18.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.5.4" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-95JgEPq2k7tHxhF9/OJnnyHDXfC9cLhhta0An/6MlkDsX2A6dTzDrTUG18vx4vjc280V0fi0xDH9iQczpSuWsw=="], - "@rushstack/ts-command-line": ["@rushstack/ts-command-line@5.1.3", "", { "dependencies": { "@rushstack/terminal": "0.19.3", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "sha512-Kdv0k/BnnxIYFlMVC1IxrIS0oGQd4T4b7vKfx52Y2+wk2WZSDFIvedr7JrhenzSlm3ou5KwtoTGTGd5nbODRug=="], + "@rushstack/problem-matcher": ["@rushstack/problem-matcher@0.2.1", "", { "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog=="], - "@sinclair/typebox": ["@sinclair/typebox@0.27.8", "", {}, "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="], + "@rushstack/rig-package": ["@rushstack/rig-package@0.7.2", "", { "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" } }, "sha512-9XbFWuqMYcHUso4mnETfhGVUSaADBRj6HUAAEYk50nMPn8WRICmBuCphycQGNB3duIR6EEZX3Xj3SYc2XiP+9A=="], + + "@rushstack/terminal": ["@rushstack/terminal@0.22.3", "", { "dependencies": { "@rushstack/node-core-library": "5.20.3", "@rushstack/problem-matcher": "0.2.1", "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-gHC9pIMrUPzAbBiI4VZMU7Q+rsCzb8hJl36lFIulIzoceKotyKL3Rd76AZ2CryCTKEg+0bnTj406HE5YY5OQvw=="], + + "@rushstack/ts-command-line": ["@rushstack/ts-command-line@5.3.3", "", { "dependencies": { "@rushstack/terminal": "0.22.3", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "sha512-c+ltdcvC7ym+10lhwR/vWiOhsrm/bP3By2VsFcs5qTKv+6tTmxgbVrtJ5NdNjANiV5TcmOZgUN+5KYQ4llsvEw=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.27.10", "", {}, "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA=="], "@sinonjs/commons": ["@sinonjs/commons@3.0.1", "", { "dependencies": { "type-detect": "4.0.8" } }, "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ=="], "@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.3.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA=="], - "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], @@ -312,57 +337,57 @@ "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="], - "@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="], + "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], "@types/react-native": ["@types/react-native@0.73.0", "", { "dependencies": { "react-native": "*" } }, "sha512-6ZRPQrYM72qYKGWidEttRe6M5DZBEV5F+MHMHqd4TTYx0tfkcdrUFGdef6CCxY0jXU7wldvd/zA/b0A/kTeJmA=="], "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], - "@types/yargs": ["@types/yargs@17.0.34", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A=="], + "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="], "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], "@vitest/coverage-v8": ["@vitest/coverage-v8@4.0.8", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.0.8", "ast-v8-to-istanbul": "^0.3.8", "debug": "^4.4.3", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.2.0", "magicast": "^0.5.1", "std-env": "^3.10.0", "tinyrainbow": "^3.0.3" }, "peerDependencies": { "@vitest/browser": "4.0.8", "vitest": "4.0.8" }, "optionalPeers": ["@vitest/browser"] }, "sha512-wQgmtW6FtPNn4lWUXi8ZSYLpOIb92j3QCujxX3sQ81NTfQ/ORnE0HtK7Kqf2+7J9jeveMGyGyc4NWc5qy3rC4A=="], - "@vitest/expect": ["@vitest/expect@4.0.8", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.8", "@vitest/utils": "4.0.8", "chai": "^6.2.0", "tinyrainbow": "^3.0.3" } }, "sha512-Rv0eabdP/xjAHQGr8cjBm+NnLHNoL268lMDK85w2aAGLFoVKLd8QGnVon5lLtkXQCoYaNL0wg04EGnyKkkKhPA=="], + "@vitest/expect": ["@vitest/expect@4.1.0", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.0", "@vitest/utils": "4.1.0", "chai": "^6.2.2", "tinyrainbow": "^3.0.3" } }, "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA=="], - "@vitest/mocker": ["@vitest/mocker@4.0.8", "", { "dependencies": { "@vitest/spy": "4.0.8", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-9FRM3MZCedXH3+pIh+ME5Up2NBBHDq0wqwhOKkN4VnvCiKbVxddqH9mSGPZeawjd12pCOGnl+lo/ZGHt0/dQSg=="], + "@vitest/mocker": ["@vitest/mocker@4.1.0", "", { "dependencies": { "@vitest/spy": "4.1.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.0.8", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-qRrjdRkINi9DaZHAimV+8ia9Gq6LeGz2CgIEmMLz3sBDYV53EsnLZbJMR1q84z1HZCMsf7s0orDgZn7ScXsZKg=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.0", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A=="], - "@vitest/runner": ["@vitest/runner@4.0.8", "", { "dependencies": { "@vitest/utils": "4.0.8", "pathe": "^2.0.3" } }, "sha512-mdY8Sf1gsM8hKJUQfiPT3pn1n8RF4QBcJYFslgWh41JTfrK1cbqY8whpGCFzBl45LN028g0njLCYm0d7XxSaQQ=="], + "@vitest/runner": ["@vitest/runner@4.1.0", "", { "dependencies": { "@vitest/utils": "4.1.0", "pathe": "^2.0.3" } }, "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ=="], - "@vitest/snapshot": ["@vitest/snapshot@4.0.8", "", { "dependencies": { "@vitest/pretty-format": "4.0.8", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-Nar9OTU03KGiubrIOFhcfHg8FYaRaNT+bh5VUlNz8stFhCZPNrJvmZkhsr1jtaYvuefYFwK2Hwrq026u4uPWCw=="], + "@vitest/snapshot": ["@vitest/snapshot@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "@vitest/utils": "4.1.0", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg=="], - "@vitest/spy": ["@vitest/spy@4.0.8", "", {}, "sha512-nvGVqUunyCgZH7kmo+Ord4WgZ7lN0sOULYXUOYuHr55dvg9YvMz3izfB189Pgp28w0vWFbEEfNc/c3VTrqrXeA=="], + "@vitest/spy": ["@vitest/spy@4.1.0", "", {}, "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw=="], "@vitest/utils": ["@vitest/utils@4.0.8", "", { "dependencies": { "@vitest/pretty-format": "4.0.8", "tinyrainbow": "^3.0.3" } }, "sha512-pdk2phO5NDvEFfUTxcTP8RFYjVj/kfLSPIN5ebP2Mu9kcIMeAQTbknqcFEyBcC4z2pJlJI9aS5UQjcYfhmKAow=="], - "@volar/language-core": ["@volar/language-core@2.4.23", "", { "dependencies": { "@volar/source-map": "2.4.23" } }, "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ=="], + "@volar/language-core": ["@volar/language-core@2.4.28", "", { "dependencies": { "@volar/source-map": "2.4.28" } }, "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ=="], - "@volar/source-map": ["@volar/source-map@2.4.23", "", {}, "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q=="], + "@volar/source-map": ["@volar/source-map@2.4.28", "", {}, "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ=="], - "@volar/typescript": ["@volar/typescript@2.4.23", "", { "dependencies": { "@volar/language-core": "2.4.23", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag=="], + "@volar/typescript": ["@volar/typescript@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw=="], - "@vue/compiler-core": ["@vue/compiler-core@3.5.22", "", { "dependencies": { "@babel/parser": "^7.28.4", "@vue/shared": "3.5.22", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ=="], + "@vue/compiler-core": ["@vue/compiler-core@3.5.30", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/shared": "3.5.30", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw=="], - "@vue/compiler-dom": ["@vue/compiler-dom@3.5.22", "", { "dependencies": { "@vue/compiler-core": "3.5.22", "@vue/shared": "3.5.22" } }, "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA=="], + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.30", "", { "dependencies": { "@vue/compiler-core": "3.5.30", "@vue/shared": "3.5.30" } }, "sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g=="], "@vue/compiler-vue2": ["@vue/compiler-vue2@2.7.16", "", { "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A=="], "@vue/language-core": ["@vue/language-core@2.2.0", "", { "dependencies": { "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^0.4.9", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw=="], - "@vue/shared": ["@vue/shared@3.5.22", "", {}, "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w=="], + "@vue/shared": ["@vue/shared@3.5.30", "", {}, "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ=="], "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], - "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - "ajv": ["ajv@8.12.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA=="], + "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="], @@ -384,9 +409,7 @@ "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], - "ast-v8-to-istanbul": ["ast-v8-to-istanbul@0.3.8", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", "js-tokens": "^9.0.1" } }, "sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ=="], - - "async-limiter": ["async-limiter@1.0.1", "", {}, "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="], + "ast-v8-to-istanbul": ["ast-v8-to-istanbul@0.3.12", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", "js-tokens": "^10.0.0" } }, "sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g=="], "babel-jest": ["babel-jest@29.7.0", "", { "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" }, "peerDependencies": { "@babel/core": "^7.8.0" } }, "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg=="], @@ -400,17 +423,17 @@ "babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="], - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.8.25", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.7", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-1ghYO3HnxGec0TCGBXiDLVns4eCSx4zJpxnHrlqFQajmhfKMQBzUGDdkMK7fUW7PTHTeLf+j87aTuKuuwWzMGw=="], - "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "browserslist": ["browserslist@4.27.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", "electron-to-chromium": "^1.5.238", "node-releases": "^2.0.26", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw=="], + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], "bser": ["bser@2.1.1", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ=="], @@ -418,9 +441,9 @@ "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001753", "", {}, "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw=="], + "caniuse-lite": ["caniuse-lite@1.0.30001778", "", {}, "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg=="], - "chai": ["chai@6.2.0", "", {}, "sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -444,7 +467,7 @@ "concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="], - "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], + "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="], "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], @@ -460,23 +483,23 @@ "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], - "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + "diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "electron-to-chromium": ["electron-to-chromium@1.5.245", "", {}, "sha512-rdmGfW47ZhL/oWEJAY4qxRtdly2B98ooTJ0pdEI4jhVLZ6tNf8fPtov2wS1IRKwFJT92le3x4Knxiwzl7cPPpQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.313", "", {}, "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + "es-module-lexer": ["es-module-lexer@2.0.0", "", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="], - "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -492,16 +515,18 @@ "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], - "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], + "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], - "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], + "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], + "fb-dotslash": ["fb-dotslash@0.5.8", "", { "bin": { "dotslash": "bin/dotslash" } }, "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA=="], "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="], @@ -518,7 +543,7 @@ "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - "fs-extra": ["fs-extra@11.3.2", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A=="], + "fs-extra": ["fs-extra@11.3.4", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="], "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], @@ -542,7 +567,7 @@ "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - "hermes-compiler": ["hermes-compiler@0.0.0", "", {}, "sha512-boVFutx6ME/Km2mB6vvsQcdnazEYYI/jV1pomx1wcFUG/EVqTkr5CU0CW9bKipOA/8Hyu3NYwW3THg2Q1kNCfA=="], + "hermes-compiler": ["hermes-compiler@250829098.0.9", "", {}, "sha512-hZ5O7PDz1vQ99TS7HD3FJ9zVynfU1y+VWId6U1Pldvd8hmAYrNec/XLPYJKD3dLOW6NXak6aAQAuMuSo3ji0tQ=="], "hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="], @@ -550,7 +575,7 @@ "html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], - "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], @@ -608,9 +633,9 @@ "jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="], - "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], + "js-tokens": ["js-tokens@10.0.0", "", {}, "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q=="], - "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + "js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "jsc-safe-url": ["jsc-safe-url@0.2.4", "", {}, "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q=="], @@ -632,7 +657,7 @@ "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="], @@ -642,7 +667,7 @@ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - "magicast": ["magicast@0.5.1", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "source-map-js": "^1.2.1" } }, "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw=="], + "magicast": ["magicast@0.5.2", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ=="], "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], @@ -654,47 +679,47 @@ "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], - "metro": ["metro@0.83.3", "", { "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" } }, "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q=="], + "metro": ["metro@0.83.5", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "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.33.3", "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.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-config": "0.83.5", "metro-core": "0.83.5", "metro-file-map": "0.83.5", "metro-resolver": "0.83.5", "metro-runtime": "0.83.5", "metro-source-map": "0.83.5", "metro-symbolicate": "0.83.5", "metro-transform-plugins": "0.83.5", "metro-transform-worker": "0.83.5", "mime-types": "^3.0.1", "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" } }, "sha512-BgsXevY1MBac/3ZYv/RfNFf/4iuW9X7f4H8ZNkiH+r667HD9sVujxcmu4jvEzGCAm4/WyKdZCuyhAcyhTHOucQ=="], - "metro-babel-transformer": ["metro-babel-transformer@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" } }, "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g=="], + "metro-babel-transformer": ["metro-babel-transformer@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.33.3", "nullthrows": "^1.1.1" } }, "sha512-d9FfmgUEVejTiSb7bkQeLRGl6aeno2UpuPm3bo3rCYwxewj03ymvOn8s8vnS4fBqAPQ+cE9iQM40wh7nGXR+eA=="], - "metro-cache": ["metro-cache@0.83.3", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.3" } }, "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q=="], + "metro-cache": ["metro-cache@0.83.5", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.5" } }, "sha512-oH+s4U+IfZyg8J42bne2Skc90rcuESIYf86dYittcdWQtPfcaFXWpByPyTuWk3rR1Zz3Eh5HOrcVImfEhhJLng=="], - "metro-cache-key": ["metro-cache-key@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw=="], + "metro-cache-key": ["metro-cache-key@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-Ycl8PBajB7bhbAI7Rt0xEyiF8oJ0RWX8EKkolV1KfCUlC++V/GStMSGpPLwnnBZXZWkCC5edBPzv1Hz1Yi0Euw=="], - "metro-config": ["metro-config@0.83.3", "", { "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" } }, "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA=="], + "metro-config": ["metro-config@0.83.5", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.5", "metro-cache": "0.83.5", "metro-core": "0.83.5", "metro-runtime": "0.83.5", "yaml": "^2.6.1" } }, "sha512-JQ/PAASXH7yczgV6OCUSRhZYME+NU8NYjI2RcaG5ga4QfQ3T/XdiLzpSb3awWZYlDCcQb36l4Vl7i0Zw7/Tf9w=="], - "metro-core": ["metro-core@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.3" } }, "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw=="], + "metro-core": ["metro-core@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.5" } }, "sha512-YcVcLCrf0ed4mdLa82Qob0VxYqfhmlRxUS8+TO4gosZo/gLwSvtdeOjc/Vt0pe/lvMNrBap9LlmvZM8FIsMgJQ=="], - "metro-file-map": ["metro-file-map@0.83.3", "", { "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" } }, "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA=="], + "metro-file-map": ["metro-file-map@0.83.5", "", { "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" } }, "sha512-ZEt8s3a1cnYbn40nyCD+CsZdYSlwtFh2kFym4lo+uvfM+UMMH+r/BsrC6rbNClSrt+B7rU9T+Te/sh/NL8ZZKQ=="], - "metro-minify-terser": ["metro-minify-terser@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ=="], + "metro-minify-terser": ["metro-minify-terser@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Toe4Md1wS1PBqbvB0cFxBzKEVyyuYTUb0sgifAZh/mSvLH84qA1NAWik9sISWatzvfWf3rOGoUoO5E3f193a3Q=="], - "metro-resolver": ["metro-resolver@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ=="], + "metro-resolver": ["metro-resolver@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-7p3GtzVUpbAweJeCcUJihJeOQl1bDuimO5ueo1K0BUpUtR41q5EilbQ3klt16UTPPMpA+tISWBtsrqU556mY1A=="], - "metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="], + "metro-runtime": ["metro-runtime@0.83.5", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-f+b3ue9AWTVlZe2Xrki6TAoFtKIqw30jwfk7GQ1rDUBQaE0ZQ+NkiMEtb9uwH7uAjJ87U7Tdx1Jg1OJqUfEVlA=="], - "metro-source-map": ["metro-source-map@0.83.3", "", { "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" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="], + "metro-source-map": ["metro-source-map@0.83.5", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.5", "nullthrows": "^1.1.1", "ob1": "0.83.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ=="], - "metro-symbolicate": ["metro-symbolicate@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.3", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw=="], + "metro-symbolicate": ["metro-symbolicate@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA=="], - "metro-transform-plugins": ["metro-transform-plugins@0.83.3", "", { "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" } }, "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A=="], + "metro-transform-plugins": ["metro-transform-plugins@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-KxYKzZL+lt3Os5H2nx7YkbkWVduLZL5kPrE/Yq+Prm/DE1VLhpfnO6HtPs8vimYFKOa58ncl60GpoX0h7Wm0Vw=="], - "metro-transform-worker": ["metro-transform-worker@0.83.3", "", { "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" } }, "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA=="], + "metro-transform-worker": ["metro-transform-worker@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "metro": "0.83.5", "metro-babel-transformer": "0.83.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-minify-terser": "0.83.5", "metro-source-map": "0.83.5", "metro-transform-plugins": "0.83.5", "nullthrows": "^1.1.1" } }, "sha512-8N4pjkNXc6ytlP9oAM6MwqkvUepNSW39LKYl9NjUMpRDazBQ7oBpQDc8Sz4aI8jnH6AGhF7s1m/ayxkN1t04yA=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], - "minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], + "minimatch": ["minimatch@10.2.3", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg=="], "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], - "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], + "mlly": ["mlly@1.8.1", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], @@ -702,17 +727,19 @@ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="], - "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], + "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], "nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="], - "ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], + "ob1": ["ob1@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg=="], + + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], "on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], @@ -720,7 +747,7 @@ "open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], - "oxlint": ["oxlint@1.26.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.26.0", "@oxlint/darwin-x64": "1.26.0", "@oxlint/linux-arm64-gnu": "1.26.0", "@oxlint/linux-arm64-musl": "1.26.0", "@oxlint/linux-x64-gnu": "1.26.0", "@oxlint/linux-x64-musl": "1.26.0", "@oxlint/win32-arm64": "1.26.0", "@oxlint/win32-x64": "1.26.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.4.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-KRpL+SMi07JQyggv5ldIF+wt2pnrKm8NLW0B+8bK+0HZsLmH9/qGA+qMWie5Vf7lnlMBllJmsuzHaKFEGY3rIA=="], + "oxlint": ["oxlint@1.55.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.55.0", "@oxlint/binding-android-arm64": "1.55.0", "@oxlint/binding-darwin-arm64": "1.55.0", "@oxlint/binding-darwin-x64": "1.55.0", "@oxlint/binding-freebsd-x64": "1.55.0", "@oxlint/binding-linux-arm-gnueabihf": "1.55.0", "@oxlint/binding-linux-arm-musleabihf": "1.55.0", "@oxlint/binding-linux-arm64-gnu": "1.55.0", "@oxlint/binding-linux-arm64-musl": "1.55.0", "@oxlint/binding-linux-ppc64-gnu": "1.55.0", "@oxlint/binding-linux-riscv64-gnu": "1.55.0", "@oxlint/binding-linux-riscv64-musl": "1.55.0", "@oxlint/binding-linux-s390x-gnu": "1.55.0", "@oxlint/binding-linux-x64-gnu": "1.55.0", "@oxlint/binding-linux-x64-musl": "1.55.0", "@oxlint/binding-openharmony-arm64": "1.55.0", "@oxlint/binding-win32-arm64-msvc": "1.55.0", "@oxlint/binding-win32-ia32-msvc": "1.55.0", "@oxlint/binding-win32-x64-msvc": "1.55.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-T+FjepiyWpaZMhekqRpH8Z3I4vNM610p6w+Vjfqgj5TZUxHXl7N8N5IPvmOU8U4XdTRxqtNNTh9Y4hLtr7yvFg=="], "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -750,29 +777,27 @@ "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], - "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="], "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="], "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], - "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="], + "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], "react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="], "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], - "react-native": ["react-native@0.82.1", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.82.1", "@react-native/codegen": "0.82.1", "@react-native/community-cli-plugin": "0.82.1", "@react-native/gradle-plugin": "0.82.1", "@react-native/js-polyfills": "0.82.1", "@react-native/normalize-colors": "0.82.1", "@react-native/virtualized-lists": "0.82.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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "hermes-compiler": "0.0.0", "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" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.1.1" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-tFAqcU7Z4g49xf/KnyCEzI4nRTu1Opcx05Ov2helr8ZTg1z7AJR/3sr2rZ+AAVlAs2IXk+B0WOxXGmdD3+4czA=="], + "react-native": ["react-native@0.84.1", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.1", "@react-native/codegen": "0.84.1", "@react-native/community-cli-plugin": "0.84.1", "@react-native/gradle-plugin": "0.84.1", "@react-native/js-polyfills": "0.84.1", "@react-native/normalize-colors": "0.84.1", "@react-native/virtualized-lists": "0.84.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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.9", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-0PjxOyXRu3tZ8EobabxSukvhKje2HJbsZikR0U+pvS0pYZza2hXKjcSBiBdFN4h9D0S3v6a8kkrDK6WTRKMwzg=="], "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], @@ -788,19 +813,19 @@ "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - "rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="], + "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], - "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], - "send": ["send@0.19.0", "", { "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" } }, "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw=="], + "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], - "serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="], + "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], @@ -848,7 +873,7 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "terser": ["terser@5.44.1", "", { "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" } }, "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw=="], + "terser": ["terser@5.46.0", "", { "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" } }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], "test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="], @@ -856,11 +881,11 @@ "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - "tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="], + "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="], "tmpl": ["tmpl@1.0.5", "", {}, "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="], @@ -878,25 +903,23 @@ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], + "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="], - "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - "vite": ["vite@7.2.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-C/Naxf8H0pBx1PA4BdpT+c/5wdqI9ILMdwjSMILw7tVIh3JsxzZqdeTLmmdaoh5MYUEOyBnM9K3o0DzoZ/fe+w=="], + "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], "vite-plugin-dts": ["vite-plugin-dts@4.5.4", "", { "dependencies": { "@microsoft/api-extractor": "^7.50.1", "@rollup/pluginutils": "^5.1.4", "@volar/typescript": "^2.4.11", "@vue/language-core": "2.2.0", "compare-versions": "^6.1.1", "debug": "^4.4.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "magic-string": "^0.30.17" }, "peerDependencies": { "typescript": "*", "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg=="], - "vitest": ["vitest@4.0.8", "", { "dependencies": { "@vitest/expect": "4.0.8", "@vitest/mocker": "4.0.8", "@vitest/pretty-format": "4.0.8", "@vitest/runner": "4.0.8", "@vitest/snapshot": "4.0.8", "@vitest/spy": "4.0.8", "@vitest/utils": "4.0.8", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.8", "@vitest/browser-preview": "4.0.8", "@vitest/browser-webdriverio": "4.0.8", "@vitest/ui": "4.0.8", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-urzu3NCEV0Qa0Y2PwvBtRgmNtxhj5t5ULw7cuKhIHh3OrkKTLlut0lnBOv9qe5OvbkMH2g38G7KPDCTpIytBVg=="], + "vitest": ["vitest@4.1.0", "", { "dependencies": { "@vitest/expect": "4.1.0", "@vitest/mocker": "4.1.0", "@vitest/pretty-format": "4.1.0", "@vitest/runner": "4.1.0", "@vitest/snapshot": "4.1.0", "@vitest/spy": "4.1.0", "@vitest/utils": "4.1.0", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.0", "@vitest/browser-preview": "4.1.0", "@vitest/browser-webdriverio": "4.1.0", "@vitest/ui": "4.1.0", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw=="], "vlq": ["vlq@1.0.1", "", {}, "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="], @@ -916,13 +939,13 @@ "write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="], - "ws": ["ws@6.2.3", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA=="], + "ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], + "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], "yargs": ["yargs@17.7.2", "", { "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" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], @@ -938,21 +961,21 @@ "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], - "@microsoft/api-extractor/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], - "@microsoft/api-extractor/typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "@rushstack/node-core-library/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], + "@vitest/expect/@vitest/utils": ["@vitest/utils@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" } }, "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw=="], - "@rushstack/node-core-library/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], + "@vitest/runner/@vitest/utils": ["@vitest/utils@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" } }, "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw=="], - "@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "@vitest/snapshot/@vitest/utils": ["@vitest/utils@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" } }, "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw=="], + + "@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@4.0.8", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-qRrjdRkINi9DaZHAimV+8ia9Gq6LeGz2CgIEmMLz3sBDYV53EsnLZbJMR1q84z1HZCMsf7s0orDgZn7ScXsZKg=="], - "@vue/language-core/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "ajv-formats/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], + "@vue/language-core/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -964,9 +987,9 @@ "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - "glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - "http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + "http-errors/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "istanbul-lib-instrument/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -980,9 +1003,11 @@ "loose-envify/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "metro/hermes-parser": ["hermes-parser@0.33.3", "", { "dependencies": { "hermes-estree": "0.33.3" } }, "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA=="], + "metro/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], - "metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "metro-babel-transformer/hermes-parser": ["hermes-parser@0.33.3", "", { "dependencies": { "hermes-estree": "0.33.3" } }, "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA=="], "metro-source-map/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], @@ -994,24 +1019,26 @@ "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], - "react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - "send/on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], - "send/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + "send/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - "test-exclude/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "test-exclude/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "vitest/@vitest/utils": ["@vitest/utils@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" } }, "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw=="], + + "vitest/std-env": ["std-env@4.0.0", "", {}, "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ=="], "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "@vue/language-core/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -1020,10 +1047,20 @@ "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.33.3", "", {}, "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg=="], + + "metro/hermes-parser/hermes-estree": ["hermes-estree@0.33.3", "", {}, "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg=="], + "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "@vue/language-core/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "test-exclude/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], } } diff --git a/bun.lockb b/bun.lockb deleted file mode 100755 index d47900dae040ac805d9799fe9488d904dc08e6dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192588 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 >VWippP>%E z|EDVHA4r!`zx3chKiJTA`hVB=|A8$3Ls3b2J%i{$&bXh$SpJW$i~o_#ki6`6|Ic$R z2^;Q7qv0s=uYSk!x28+%UGx|j_m+A6eP<{n?!U^KhUCRF$j?_B_nFw#{G)pfVowc? zfSk3tqVbdOv=H=%i@X<14-6vbSNxbC|Iu{+kN`V??SX%i2T0p}<}}b|`6B+k&Xxa3 zE@PWzd*ENj1El|Y22EuwJxlQ`J>vx-5`RHP1$ZE+tdV9F}`nlqVc*xb)KX8%fyD℘WwQa7wa?m9R;0%WN7!8?+ioObY@sN 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 diff --git a/examples/demo/App.tsx b/examples/demo/App.tsx index eccc3a97..23f5c9d9 100644 --- a/examples/demo/App.tsx +++ b/examples/demo/App.tsx @@ -32,6 +32,44 @@ const TAG = 'App'; function App() { useEffect(() => { + const handleIamWillDisplay = (e: InAppMessageWillDisplayEvent) => { + log.i(TAG, `IAM willDisplay: ${e.message.messageId}`); + }; + + const handleIamDidDisplay = (e: InAppMessageDidDisplayEvent) => { + log.i(TAG, `IAM didDisplay: ${e.message.messageId}`); + }; + + const handleIamWillDismiss = (e: InAppMessageWillDismissEvent) => { + log.i(TAG, `IAM willDismiss: ${e.message.messageId}`); + }; + + const handleIamDidDismiss = (e: InAppMessageDidDismissEvent) => { + log.i(TAG, `IAM didDismiss: ${e.message.messageId}`); + }; + + const handleIamClick = (e: InAppMessageClickEvent) => { + log.i(TAG, `IAM click: ${e.result.actionId ?? 'unknown'}`); + }; + + const handleNotificationClick = (e: NotificationClickEvent) => { + log.i(TAG, `Notification click: ${e.notification.title ?? ''}`); + }; + + const handlePermissionChange = (granted: boolean) => { + log.i(TAG, `Permission changed: ${granted}`); + }; + + const handleForegroundWillDisplay = (e: NotificationWillDisplayEvent) => { + log.i( + TAG, + `Notification foregroundWillDisplay: ${ + e.getNotification().title ?? '' + }`, + ); + e.getNotification().display(); + }; + const init = async () => { try { const prefs = PreferencesService.getInstance(); @@ -59,66 +97,35 @@ function App() { OneSignal.InAppMessages.setPaused(iamPaused); OneSignal.Location.setShared(locationShared); - console.log( - 'OneSignal.Notifications.getPermissionAsync: ', - await OneSignal.Notifications.getPermissionAsync(), - ); - // Register SDK event listeners for logging OneSignal.InAppMessages.addEventListener( 'willDisplay', - (e: InAppMessageWillDisplayEvent) => { - log.i(TAG, `IAM willDisplay: ${e.message.messageId}`); - }, + handleIamWillDisplay, ); OneSignal.InAppMessages.addEventListener( 'didDisplay', - (e: InAppMessageDidDisplayEvent) => { - log.i(TAG, `IAM didDisplay: ${e.message.messageId}`); - }, + handleIamDidDisplay, ); OneSignal.InAppMessages.addEventListener( 'willDismiss', - (e: InAppMessageWillDismissEvent) => { - log.i(TAG, `IAM willDismiss: ${e.message.messageId}`); - }, + handleIamWillDismiss, ); OneSignal.InAppMessages.addEventListener( 'didDismiss', - (e: InAppMessageDidDismissEvent) => { - log.i(TAG, `IAM didDismiss: ${e.message.messageId}`); - }, - ); - OneSignal.InAppMessages.addEventListener( - 'click', - (e: InAppMessageClickEvent) => { - log.i(TAG, `IAM click: ${e.result.actionId ?? 'unknown'}`); - }, + handleIamDidDismiss, ); + OneSignal.InAppMessages.addEventListener('click', handleIamClick); OneSignal.Notifications.addEventListener( 'click', - (e: NotificationClickEvent) => { - log.i(TAG, `Notification click: ${e.notification.title ?? ''}`); - }, + handleNotificationClick, ); OneSignal.Notifications.addEventListener( 'permissionChange', - (granted: boolean) => { - log.i(TAG, `Permission changed: ${granted}`); - }, + handlePermissionChange, ); OneSignal.Notifications.addEventListener( 'foregroundWillDisplay', - (e: NotificationWillDisplayEvent) => { - log.i( - TAG, - `Notification foregroundWillDisplay: ${ - e.getNotification().title ?? '' - }`, - ); - e.preventDefault(); - e.getNotification().display(); - }, + handleForegroundWillDisplay, ); log.i(TAG, `OneSignal initialized with app ID: ${appId}`); @@ -127,10 +134,42 @@ function App() { } }; - init(); + void init(); // Fetch tooltips in background - TooltipHelper.getInstance().init(); + void TooltipHelper.getInstance().init(); + + return () => { + OneSignal.InAppMessages.removeEventListener( + 'willDisplay', + handleIamWillDisplay, + ); + OneSignal.InAppMessages.removeEventListener( + 'didDisplay', + handleIamDidDisplay, + ); + OneSignal.InAppMessages.removeEventListener( + 'willDismiss', + handleIamWillDismiss, + ); + OneSignal.InAppMessages.removeEventListener( + 'didDismiss', + handleIamDidDismiss, + ); + OneSignal.InAppMessages.removeEventListener('click', handleIamClick); + OneSignal.Notifications.removeEventListener( + 'click', + handleNotificationClick, + ); + OneSignal.Notifications.removeEventListener( + 'permissionChange', + handlePermissionChange, + ); + OneSignal.Notifications.removeEventListener( + 'foregroundWillDisplay', + handleForegroundWillDisplay, + ); + }; }, []); return ( diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index 138b2200..b3e570a9 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-LKq3nsUYlCy9AQ/9kp0WuchjjnuowXPlx0aLBobrp1BNLkA+IqoJnLjx8+St3vBaKTHSEsp65LvkRnmHRlzxlA=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-tN4xtiPwGhQmnuqxNAGSc8ht1pHE0a0qw+Mg0OJfs4im/D7j2QWjiDAlpv/vpjSXliWTXGgEkDqcTKfQ/GIZ7w=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/examples/run-android.sh b/examples/run-android.sh index 8d12f034..e751c210 100755 --- a/examples/run-android.sh +++ b/examples/run-android.sh @@ -1,4 +1,4 @@ -# DON'T RUN THIS FILE DIRECTLY, USE THE run-ios.sh FILE IN THE DEMO APP +# DON'T RUN THIS FILE DIRECTLY, USE PACKAGE.JSON SCRIPTS #!/bin/bash set -e diff --git a/examples/run-ios.sh b/examples/run-ios.sh index 0d2af134..24ab04e8 100755 --- a/examples/run-ios.sh +++ b/examples/run-ios.sh @@ -1,4 +1,4 @@ -# DON'T RUN THIS FILE DIRECTLY, USE THE run-ios.sh FILE IN THE DEMO APP +# DON'T RUN THIS FILE DIRECTLY, USE PACKAGE.JSON SCRIPTS #!/bin/bash set -e diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h index fdc2a0ff..6be0c892 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.h +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.h @@ -1,13 +1,7 @@ #if __has_include() #import -#import -#import -#import #elif __has_include("RCTBridgeModule.h") #import "RCTBridgeModule.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTUtils.h" #endif #import @@ -40,7 +34,8 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) { @protocol OSNotificationLifecycleListener; @interface RCTOneSignalEventEmitter - : NativeOneSignalSpecBase + : NativeOneSignalSpecBase + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body; diff --git a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm index 5f8ff3cd..92ad3010 100644 --- a/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm +++ b/ios/RCTOneSignal/RCTOneSignalEventEmitter.mm @@ -69,10 +69,6 @@ - (void)invalidate { #pragma mark Send Event Methods - (void)emitEventWithName:(NSString *)name body:(NSDictionary *)body { - if (!_eventEmitterCallback) { - return; - } - if ([name isEqualToString:OSEventString(PermissionChanged)]) { [self emitOnPermissionChanged:body]; } else if ([name isEqualToString:OSEventString(SubscriptionChanged)]) { @@ -365,8 +361,7 @@ - (void)removePermissionObserver { } } -RCT_EXPORT_METHOD(onWillDisplayNotification : (OSNotificationWillDisplayEvent *) - event) { +- (void)onWillDisplayNotification:(OSNotificationWillDisplayEvent *)event { _notificationWillDisplayCache[event.notification.notificationId] = event; [event preventDefault]; [RCTOneSignalEventEmitter diff --git a/package.json b/package.json index ca391099..98264abe 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "files": [ "dist", "src/NativeOneSignal.ts", - "android", + "android/src", + "android/build.gradle", + "android/proguard-rules.pro", "ios", "react-native-onesignal.podspec" ], From 6358fb7a7f9152a33cbf0c79df3b7cd5aa0d6114 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 18 Mar 2026 12:35:23 -0700 Subject: [PATCH 22/25] feat: restore deprecated sync methods for backwards compatibility --- MIGRATION_GUIDE.md | 85 +++-------------------------- src/index.test.ts | 133 ++++++++++++++++++++++++++++++++++++++++++++- src/index.ts | 93 ++++++++++++++++++++++++++++++- 3 files changed, 232 insertions(+), 79 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 4c81d74a..3df54d73 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,76 +1,3 @@ -# React Native Migration Guide - -# Migration Guide (v5 to v6) - -## Requirements - -- **React Native 0.76.0 or higher** is now required. The SDK exclusively uses the New Architecture (TurboModules, Fabric, Bridgeless Mode). The legacy Bridge architecture is no longer supported. - -## Removed Deprecated Methods - -The following synchronous methods have been removed. Replace them with their async equivalents: - -| Removed (v5) | Replacement (v6) | -|---|---| -| `pushSubscription.getPushSubscriptionId()` | `await pushSubscription.getIdAsync()` | -| `pushSubscription.getPushSubscriptionToken()` | `await pushSubscription.getTokenAsync()` | -| `pushSubscription.getOptedIn()` | `await pushSubscription.getOptedInAsync()` | -| `Notifications.hasPermission()` | `await Notifications.getPermissionAsync()` | - -Since the replacements are async, update call sites to use `await`: - -```typescript -// v5 (removed) -const id = OneSignal.User.pushSubscription.getPushSubscriptionId(); -const hasPermission = OneSignal.Notifications.hasPermission(); - -// v6 -const id = await OneSignal.User.pushSubscription.getIdAsync(); -const hasPermission = await OneSignal.Notifications.getPermissionAsync(); -``` - -## Stricter TypeScript Types - -Methods that accept key-value objects now use `Record` instead of a loosely typed object. This applies to: - -- `OneSignal.User.addTags(tags)` -- `OneSignal.User.addAliases(aliases)` -- `OneSignal.InAppMessages.addTriggers(triggers)` - -If you were passing non-string values (e.g. numbers), convert them to strings: - -```typescript -// v5 (allowed at runtime, coerced to strings) -OneSignal.User.addTags({ score: 100 }); - -// v6 (TypeScript enforces string values) -OneSignal.User.addTags({ score: '100' }); -``` - -## iOS - -The podspec now uses `install_modules_dependencies(s)` instead of an explicit `React` dependency. This is handled automatically and requires no action. - -The iOS implementation file has been renamed from `.m` to `.mm` (Objective-C++). If you have any custom build phase scripts that reference this file, update them accordingly. - -## Android - -No additional Android configuration is required. The SDK uses React Native's codegen to generate the TurboModule spec automatically during the app build. - -### OkHttp Version Conflict - -The OneSignal Android SDK transitively pulls in OkHttp 5.x via its OpenTelemetry dependency, which conflicts with React Native's OkHttp 4.x. If you see a `NoClassDefFoundError` for `okhttp3.internal.Util`, add this to your app's `build.gradle`: - -```groovy -configurations.all { - resolutionStrategy { - force 'com.squareup.okhttp3:okhttp:4.12.0' - } -} -``` - ---- - # React Native v5.0.0 Migration Guide #### ⚠️ Migration Advisory for current OneSignal customers @@ -196,9 +123,9 @@ In previous versions of the SDK, a “player” could have up to one email addre The current device’s push subscription can be retrieved via: ```typescript -const id = await OneSignal.User.pushSubscription.getIdAsync(); -const token = await OneSignal.User.pushSubscription.getTokenAsync(); -const optedIn = await OneSignal.User.pushSubscription.getOptedInAsync(); +const id: string = OneSignal.User.pushSubscription.getPushSubscriptionId(); +const token: string = OneSignal.User.pushSubscription.getPushSubscriptionToken(); +const optedIn: boolean = OneSignal.User.pushSubscription.getOptedIn(); ``` ### **Opting In and Out of Push Notifications** @@ -318,6 +245,9 @@ The Push Subscription namespace is accessible via `OneSignal.User.pushSubscripti | **React Native** | **Description** | | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OneSignal.User.pushSubscription.getPushSubscriptionId()` | _**DEPRECATED**
use `getIdAsync`._ | +| `OneSignal.User.pushSubscription.getPushSubscriptionToken()` | _**DEPRECATED**
use `getTokenAsync`_ | +| `OneSignal.User.pushSubscription.getOptedIn()` | _**DEPRECATED**
use `getOptedInAsync`_ | | `await OneSignal.User.pushSubscription.getIdAsync()` | _The readonly push subscription ID._ | | `await OneSignal.User.pushSubscription.getTokenAsync()` | _The readonly push token._ | | `await OneSignal.User.pushSubscription.getOptedInAsync()` | _Gets a boolean value indicating whether the current user is opted in to push notifications. This returns `true` when the app has notifications permission and `optOut()` is **not** called. **_Note:_** Does not take into account the existence of the subscription ID and push token. This boolean may return `true` but push notifications may still not be received by the user._ | @@ -354,7 +284,8 @@ The Notifications namespace is accessible via `OneSignal.Notifications` and prov | **React Native** | **Description** | |--------------------------------------- | --------------- | -| `await OneSignal.Notifications.getPermissionAsync()` | _Whether this app has push notification permission._ | +| `OneSignal.Notifications.hasPermission()` | _**DEPRECATED**
use `getPermissionAsync()`_ | +| `OneSignal.Notifications.getPermissionAsync()` | _Whether this app has push notification permission._ | | `await OneSignal.Notifications.canRequestPermission()` | _Whether attempting to request notification permission will show a prompt. Returns `true` if the device has not been prompted for push notification permission already._ | | `await OneSignal.Notifications.permissionNative()` | _(ios only) Returns the enum for the native permission of the device. It will be one of: NotDetermined, Denied, Authorized, Provisional (only available in iOS 12), Ephemeral (only available in iOS 14)_ | | `OneSignal.Notifications.clearAll();` | _Removes all OneSignal notifications._ | diff --git a/src/index.test.ts b/src/index.test.ts index 61aa016a..fb6c90d2 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -13,7 +13,7 @@ import { SUBSCRIPTION_CHANGED, USER_STATE_CHANGED, } from './constants/events'; -import EventManager from './events/EventManager'; +import EventManager, { type EventListenerMap } from './events/EventManager'; import * as helpers from './helpers'; import { LogLevel, OneSignal, OSNotificationPermission } from './index'; @@ -37,6 +37,14 @@ const removeEventManagerListenerSpy = vi.spyOn( 'removeEventListener', ); +const filterEventListener = ( + eventName: K, +): EventListenerMap[K] => { + return addEventManagerListenerSpy.mock.calls.filter( + (call) => call[0] === eventName, + )[0][1] as EventListenerMap[K]; +}; + describe('OneSignal', () => { beforeEach(() => { mockPlatform.OS = 'ios'; @@ -63,6 +71,37 @@ describe('OneSignal', () => { test('should initialize OneSignal with appId', () => { OneSignal.initialize(APP_ID); expect(mockRNOneSignal.initialize).toHaveBeenCalledWith(APP_ID); + + // test permission change listener + const changeFn = filterEventListener(PERMISSION_CHANGED); + changeFn(true); + const permission = OneSignal.Notifications.hasPermission(); + expect(permission).toBe(true); + + // test push subscription change listener + const pushData = { + previous: { + id: '', + token: '', + optedIn: false, + }, + current: { + id: 'subscription-id', + token: 'push-token', + optedIn: true, + }, + }; + const subscriptionChangeFn = filterEventListener(SUBSCRIPTION_CHANGED); + subscriptionChangeFn(pushData); + const pushSubscription = + OneSignal.User.pushSubscription.getPushSubscriptionId(); + expect(pushSubscription).toBe('subscription-id'); + + // reset push subscription + subscriptionChangeFn({ + ...pushData, + current: { id: '', token: '', optedIn: false }, + }); }); test('should not initialize if native module is not loaded', () => { @@ -374,6 +413,32 @@ describe('OneSignal', () => { }); }); + describe('getPushSubscriptionId (deprecated)', () => { + test('should return empty string if native module not loaded', () => { + isNativeLoadedSpy.mockReturnValue(false); + const result = OneSignal.User.pushSubscription.getPushSubscriptionId(); + expect(result).toBe(''); + }); + + test('should log deprecation warning and return the push id', async () => { + // with no push id + const result = OneSignal.User.pushSubscription.getPushSubscriptionId(); + expect(result).toBe(''); + expect(console.warn).toHaveBeenCalledWith( + 'OneSignal: This method has been deprecated. Use getIdAsync instead for getting push subscription id.', + ); + + // with a push id + mockRNOneSignal.getPushSubscriptionId.mockResolvedValue(PUSH_ID); + OneSignal.initialize(APP_ID); + await vi.waitFor(() => { + const result2 = + OneSignal.User.pushSubscription.getPushSubscriptionId(); + expect(result2).toBe(PUSH_ID); + }); + }); + }); + describe('getIdAsync', () => { test('should get push subscription id', async () => { mockRNOneSignal.getPushSubscriptionId.mockResolvedValue(PUSH_ID); @@ -390,6 +455,36 @@ describe('OneSignal', () => { }); }); + describe('getPushSubscriptionToken (deprecated)', () => { + test('should return empty string if native module not loaded', () => { + isNativeLoadedSpy.mockReturnValue(false); + const result = + OneSignal.User.pushSubscription.getPushSubscriptionToken(); + expect(result).toBe(''); + }); + + test('should log deprecation warning and return the push token', async () => { + // with no push token + const result = + OneSignal.User.pushSubscription.getPushSubscriptionToken(); + expect(result).toBe(''); + expect(console.warn).toHaveBeenCalledWith( + 'OneSignal: This method has been deprecated. Use getTokenAsync instead for getting push subscription token.', + ); + + // with a push token + vi.mocked(mockRNOneSignal.getPushSubscriptionToken).mockResolvedValue( + PUSH_TOKEN, + ); + OneSignal.initialize(APP_ID); + await vi.waitFor(() => { + const result2 = + OneSignal.User.pushSubscription.getPushSubscriptionToken(); + expect(result2).toBe(PUSH_TOKEN); + }); + }); + }); + describe('getTokenAsync', () => { test('should get push subscription token', async () => { vi.mocked(mockRNOneSignal.getPushSubscriptionToken).mockResolvedValue( @@ -408,6 +503,31 @@ describe('OneSignal', () => { }); }); + describe('getOptedIn (deprecated)', () => { + test('should return false if native module not loaded', () => { + isNativeLoadedSpy.mockReturnValue(false); + const result = OneSignal.User.pushSubscription.getOptedIn(); + expect(result).toBe(false); + }); + + test('should log deprecation warning and return the opted in status', async () => { + // with no opted in status + const result = OneSignal.User.pushSubscription.getOptedIn(); + expect(result).toBe(false); + expect(console.warn).toHaveBeenCalledWith( + 'OneSignal: This method has been deprecated. Use getOptedInAsync instead for getting push subscription opted in status.', + ); + + // with a opted in status + vi.mocked(mockRNOneSignal.getOptedIn).mockResolvedValue(true); + OneSignal.initialize(APP_ID); + await vi.waitFor(() => { + const result2 = OneSignal.User.pushSubscription.getOptedIn(); + expect(result2).toBe(true); + }); + }); + }); + describe('getOptedInAsync', () => { test('should get opted in status', async () => { vi.mocked(mockRNOneSignal.getOptedIn).mockResolvedValue(true); @@ -784,6 +904,17 @@ describe('OneSignal', () => { }); describe('Notifications', () => { + describe('hasPermission (deprecated)', () => { + test('should log deprecation warning', () => { + const consoleSpy = vi + .spyOn(console, 'warn') + .mockImplementation(() => {}); + OneSignal.Notifications.hasPermission(); + expect(consoleSpy).toHaveBeenCalled(); + consoleSpy.mockRestore(); + }); + }); + describe('getPermissionAsync', () => { test('should get permission status', async () => { vi.mocked( diff --git a/src/index.ts b/src/index.ts index 5b1ade1e..013dd716 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,7 +34,10 @@ import type { NotificationClickEvent, NotificationListeners, } from './types/notificationEvents'; -import type { PushSubscriptionChangedState } from './types/subscription'; +import type { + PushSubscriptionChangedState, + PushSubscriptionState, +} from './types/subscription'; import type { UserChangedState, UserState } from './types/user'; const RNOneSignal = NativeOneSignal; @@ -58,12 +61,47 @@ export enum LogLevel { Verbose, } +let notificationPermission = false; + +let pushSub: PushSubscriptionState = { + id: '', + token: '', + optedIn: false, +}; + +async function _addPermissionObserver() { + OneSignal.Notifications.addEventListener( + 'permissionChange', + (granted: boolean) => { + notificationPermission = granted; + }, + ); + + notificationPermission = await RNOneSignal.hasNotificationPermission(); +} + +async function _addPushSubscriptionObserver() { + OneSignal.User.pushSubscription.addEventListener( + 'change', + (subscriptionChange) => { + pushSub = subscriptionChange.current; + }, + ); + + pushSub.id = (await RNOneSignal.getPushSubscriptionId()) ?? undefined; + pushSub.token = (await RNOneSignal.getPushSubscriptionToken()) ?? undefined; + pushSub.optedIn = await RNOneSignal.getOptedIn(); +} + export namespace OneSignal { /** Initializes the OneSignal SDK. This should be called during startup of the application. */ export function initialize(appId: string) { if (!isNativeModuleLoaded(RNOneSignal)) return; RNOneSignal.initialize(appId); + + _addPermissionObserver(); + _addPushSubscriptionObserver(); } /** @@ -273,6 +311,20 @@ export namespace OneSignal { eventManager.removeEventListener(SUBSCRIPTION_CHANGED, listener); } + /** + * @deprecated This method is deprecated. It has been replaced by {@link getIdAsync}. + */ + export function getPushSubscriptionId(): string { + if (!isNativeModuleLoaded(RNOneSignal)) { + return ''; + } + console.warn( + 'OneSignal: This method has been deprecated. Use getIdAsync instead for getting push subscription id.', + ); + + return pushSub.id ? pushSub.id : ''; + } + export async function getIdAsync(): Promise { if (!isNativeModuleLoaded(RNOneSignal)) { return Promise.reject( @@ -283,6 +335,20 @@ export namespace OneSignal { return await RNOneSignal.getPushSubscriptionId(); } + /** + * @deprecated This method is deprecated. It has been replaced by {@link getTokenAsync}. + */ + export function getPushSubscriptionToken(): string { + if (!isNativeModuleLoaded(RNOneSignal)) { + return ''; + } + console.warn( + 'OneSignal: This method has been deprecated. Use getTokenAsync instead for getting push subscription token.', + ); + + return pushSub.token ? pushSub.token : ''; + } + /** The readonly push subscription token */ export async function getTokenAsync(): Promise { if (!isNativeModuleLoaded(RNOneSignal)) { @@ -294,6 +360,20 @@ export namespace OneSignal { return await RNOneSignal.getPushSubscriptionToken(); } + /** + * @deprecated This method is deprecated. It has been replaced by {@link getOptedInAsync}. + */ + export function getOptedIn(): boolean { + if (!isNativeModuleLoaded(RNOneSignal)) { + return false; + } + console.warn( + 'OneSignal: This method has been deprecated. Use getOptedInAsync instead for getting push subscription opted in status.', + ); + + return pushSub.optedIn ?? false; + } + /** * Gets a boolean value indicating whether the current user is opted in to push notifications. * This returns true when the app has notifications permission and optOut is not called. @@ -505,6 +585,17 @@ export namespace OneSignal { } export namespace Notifications { + /** + * @deprecated This method is deprecated. It has been replaced by {@link getPermissionAsync}. + */ + export function hasPermission(): boolean { + console.warn( + 'OneSignal: This method has been deprecated. Use getPermissionAsync instead for getting notification permission status.', + ); + + return notificationPermission; + } + /** * Whether this app has push notification permission. Returns true if the user has accepted permissions, * or if the app has ephemeral or provisional permission. From 74f729779dc74f679c320931c8efc1dc7d06e100 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 18 Mar 2026 12:55:11 -0700 Subject: [PATCH 23/25] chore: update OneSignalXCFramework to 5.5.0 --- examples/demo/bun.lock | 2 +- examples/demo/ios/Podfile.lock | 6 +++--- react-native-onesignal.podspec | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index b3e570a9..06b8aa8c 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-tN4xtiPwGhQmnuqxNAGSc8ht1pHE0a0qw+Mg0OJfs4im/D7j2QWjiDAlpv/vpjSXliWTXGgEkDqcTKfQ/GIZ7w=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-Igkuz2Ab5ZlxkW/4sFOBJQ1+V6P+Tm833emn+zJiGfkwxWfo+Bw0Jw/xTS3UIuE6Uz0n8gfa5C+Xv/fW4TlJwg=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/examples/demo/ios/Podfile.lock b/examples/demo/ios/Podfile.lock index 3782374e..b93ef32a 100644 --- a/examples/demo/ios/Podfile.lock +++ b/examples/demo/ios/Podfile.lock @@ -1446,9 +1446,9 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - ReactNativeDependencies - - react-native-onesignal (5.3.4): + - react-native-onesignal (5.3.6): - hermes-engine - - OneSignalXCFramework (= 5.4.2) + - OneSignalXCFramework (= 5.5.0) - RCTRequired - RCTTypeSafety - React-Core @@ -2349,7 +2349,7 @@ SPEC CHECKSUMS: React-logger: 9e51e01455f15cb3ef87a09a1ec773cdb22d56c1 React-Mapbuffer: 92b99e450e8ff598b27d6e4db3a75e04fd45e9a9 React-microtasksnativemodule: 2fe0f2bd2840dedbd66c0ac249c64f977f39cc18 - react-native-onesignal: 3ad7ccd00e4ea2b4f433e579f897b356747ae548 + react-native-onesignal: 6f530ad3cac113ad36491dddc455fec600776158 react-native-safe-area-context: 37e680fc4cace3c0030ee46e8987d24f5d3bdab2 React-NativeModulesApple: 44a9474594566cd03659f92e38f42599c6b9dee4 React-networking: db73d91466cb134fcbdaaa579fb2de14e2c2ea01 diff --git a/react-native-onesignal.podspec b/react-native-onesignal.podspec index d2acd3f5..d92089c5 100644 --- a/react-native-onesignal.podspec +++ b/react-native-onesignal.podspec @@ -15,5 +15,5 @@ Pod::Spec.new do |s| install_modules_dependencies(s) - s.dependency 'OneSignalXCFramework', '5.4.2' + s.dependency 'OneSignalXCFramework', '5.5.0' end From 4660c4694d863694f13acb16e9d25d4e88b50d47 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 18 Mar 2026 14:27:58 -0700 Subject: [PATCH 24/25] build(ios): bump minimum platform to iOS 15.1 --- examples/demo/bun.lock | 2 +- examples/demo/ios/Podfile.lock | 2 +- react-native-onesignal.podspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock index 06b8aa8c..17cce7dd 100644 --- a/examples/demo/bun.lock +++ b/examples/demo/bun.lock @@ -1368,7 +1368,7 @@ "react-native": ["react-native@0.84.0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.84.0", "@react-native/codegen": "0.84.0", "@react-native/community-cli-plugin": "0.84.0", "@react-native/gradle-plugin": "0.84.0", "@react-native/js-polyfills": "0.84.0", "@react-native/normalize-colors": "0.84.0", "@react-native/virtualized-lists": "0.84.0", "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.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.7", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "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.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-CcBfucLDHz8MAjQx9kFXasYtpcn8zP1YapUgGtAy0psRZTLShwF9yeh5+ErSgEK2gXV1CCSz7hqCZqx1eMyBLA=="], - "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-Igkuz2Ab5ZlxkW/4sFOBJQ1+V6P+Tm833emn+zJiGfkwxWfo+Bw0Jw/xTS3UIuE6Uz0n8gfa5C+Xv/fW4TlJwg=="], + "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.76.0" } }, "sha512-CfyXgxsDx0Nw1GYBDDwR8LDgZ0nWbyBlZIOiDpCeJydR1nThwWuKH0F1FRbbpI+MisZuCPqHLZ1IBnZf8qfrCA=="], "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], diff --git a/examples/demo/ios/Podfile.lock b/examples/demo/ios/Podfile.lock index b93ef32a..715de224 100644 --- a/examples/demo/ios/Podfile.lock +++ b/examples/demo/ios/Podfile.lock @@ -2349,7 +2349,7 @@ SPEC CHECKSUMS: React-logger: 9e51e01455f15cb3ef87a09a1ec773cdb22d56c1 React-Mapbuffer: 92b99e450e8ff598b27d6e4db3a75e04fd45e9a9 React-microtasksnativemodule: 2fe0f2bd2840dedbd66c0ac249c64f977f39cc18 - react-native-onesignal: 6f530ad3cac113ad36491dddc455fec600776158 + react-native-onesignal: eb0b07478feb04abfc7a2504d34fec0df6317140 react-native-safe-area-context: 37e680fc4cace3c0030ee46e8987d24f5d3bdab2 React-NativeModulesApple: 44a9474594566cd03659f92e38f42599c6b9dee4 React-networking: db73d91466cb134fcbdaaa579fb2de14e2c2ea01 diff --git a/react-native-onesignal.podspec b/react-native-onesignal.podspec index d92089c5..ddc946f8 100644 --- a/react-native-onesignal.podspec +++ b/react-native-onesignal.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/OneSignal/react-native-onesignal" s.license = package_json["license"] s.author = { package_json["author"] => package_json["author"] } - s.platform = :ios, "11.0" + s.platform = :ios, "15.1" s.source = { :git => "#{package_json["repository"]["url"]}.git", :tag => "#{s.version}" } s.source_files = 'ios/RCTOneSignal/*.{h,m,mm}' s.static_framework = true From cf81d929bc6de06cdba75aea758323c93b7f6ab9 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 18 Mar 2026 14:58:19 -0700 Subject: [PATCH 25/25] chore(demo): simplify Android and iOS clean scripts --- examples/demo/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/demo/package.json b/examples/demo/package.json index c33cd498..3561a5c1 100644 --- a/examples/demo/package.json +++ b/examples/demo/package.json @@ -8,8 +8,8 @@ "preios": "bun run setup", "android": "bash ../run-android.sh", "ios": "bash ../run-ios.sh", - "clean:android": "cd android && ./gradlew clean && cd ..", - "clean:ios": "cd ios && xcodebuild clean && cd ..", + "clean:android": "rm -rf android/app/build android/app/.cxx android/build", + "clean:ios": "rm -rf ios/build ios/Pods", "lint": "eslint .", "start": "react-native start", "test": "jest"