@rejourneyco/react-native 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +29 -0
  2. package/android/build.gradle.kts +135 -0
  3. package/android/consumer-rules.pro +10 -0
  4. package/android/proguard-rules.pro +1 -0
  5. package/android/src/main/AndroidManifest.xml +15 -0
  6. package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +860 -0
  7. package/android/src/main/java/com/rejourney/engine/DeviceRegistrar.kt +290 -0
  8. package/android/src/main/java/com/rejourney/engine/DiagnosticLog.kt +385 -0
  9. package/android/src/main/java/com/rejourney/engine/RejourneyImpl.kt +512 -0
  10. package/android/src/main/java/com/rejourney/platform/OEMDetector.kt +173 -0
  11. package/android/src/main/java/com/rejourney/platform/PerfTiming.kt +384 -0
  12. package/android/src/main/java/com/rejourney/platform/SessionLifecycleService.kt +160 -0
  13. package/android/src/main/java/com/rejourney/platform/Telemetry.kt +301 -0
  14. package/android/src/main/java/com/rejourney/platform/WindowUtils.kt +100 -0
  15. package/android/src/main/java/com/rejourney/recording/AnrSentinel.kt +129 -0
  16. package/android/src/main/java/com/rejourney/recording/EventBuffer.kt +330 -0
  17. package/android/src/main/java/com/rejourney/recording/InteractionRecorder.kt +519 -0
  18. package/android/src/main/java/com/rejourney/recording/ReplayOrchestrator.kt +740 -0
  19. package/android/src/main/java/com/rejourney/recording/SegmentDispatcher.kt +559 -0
  20. package/android/src/main/java/com/rejourney/recording/StabilityMonitor.kt +238 -0
  21. package/android/src/main/java/com/rejourney/recording/TelemetryPipeline.kt +633 -0
  22. package/android/src/main/java/com/rejourney/recording/ViewHierarchyScanner.kt +232 -0
  23. package/android/src/main/java/com/rejourney/recording/VisualCapture.kt +474 -0
  24. package/android/src/main/java/com/rejourney/utility/DataCompression.kt +63 -0
  25. package/android/src/main/java/com/rejourney/utility/ImageBlur.kt +412 -0
  26. package/android/src/main/java/com/rejourney/utility/ViewIdentifier.kt +169 -0
  27. package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +232 -0
  28. package/android/src/newarch/java/com/rejourney/RejourneyPackage.kt +40 -0
  29. package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +268 -0
  30. package/android/src/oldarch/java/com/rejourney/RejourneyPackage.kt +23 -0
  31. package/ios/Engine/DeviceRegistrar.swift +288 -0
  32. package/ios/Engine/DiagnosticLog.swift +387 -0
  33. package/ios/Engine/RejourneyImpl.swift +719 -0
  34. package/ios/Recording/AnrSentinel.swift +142 -0
  35. package/ios/Recording/EventBuffer.swift +326 -0
  36. package/ios/Recording/InteractionRecorder.swift +428 -0
  37. package/ios/Recording/ReplayOrchestrator.swift +624 -0
  38. package/ios/Recording/SegmentDispatcher.swift +492 -0
  39. package/ios/Recording/StabilityMonitor.swift +223 -0
  40. package/ios/Recording/TelemetryPipeline.swift +547 -0
  41. package/ios/Recording/ViewHierarchyScanner.swift +156 -0
  42. package/ios/Recording/VisualCapture.swift +675 -0
  43. package/ios/Rejourney.h +38 -0
  44. package/ios/Rejourney.mm +375 -0
  45. package/ios/Utility/DataCompression.swift +55 -0
  46. package/ios/Utility/ImageBlur.swift +89 -0
  47. package/ios/Utility/RuntimeMethodSwap.swift +41 -0
  48. package/ios/Utility/ViewIdentifier.swift +37 -0
  49. package/lib/commonjs/NativeRejourney.js +40 -0
  50. package/lib/commonjs/components/Mask.js +88 -0
  51. package/lib/commonjs/index.js +1443 -0
  52. package/lib/commonjs/sdk/autoTracking.js +1087 -0
  53. package/lib/commonjs/sdk/constants.js +166 -0
  54. package/lib/commonjs/sdk/errorTracking.js +187 -0
  55. package/lib/commonjs/sdk/index.js +50 -0
  56. package/lib/commonjs/sdk/metricsTracking.js +205 -0
  57. package/lib/commonjs/sdk/navigation.js +128 -0
  58. package/lib/commonjs/sdk/networkInterceptor.js +375 -0
  59. package/lib/commonjs/sdk/utils.js +433 -0
  60. package/lib/commonjs/sdk/version.js +13 -0
  61. package/lib/commonjs/types/expo-router.d.js +2 -0
  62. package/lib/commonjs/types/index.js +2 -0
  63. package/lib/module/NativeRejourney.js +38 -0
  64. package/lib/module/components/Mask.js +83 -0
  65. package/lib/module/index.js +1341 -0
  66. package/lib/module/sdk/autoTracking.js +1059 -0
  67. package/lib/module/sdk/constants.js +154 -0
  68. package/lib/module/sdk/errorTracking.js +177 -0
  69. package/lib/module/sdk/index.js +26 -0
  70. package/lib/module/sdk/metricsTracking.js +187 -0
  71. package/lib/module/sdk/navigation.js +120 -0
  72. package/lib/module/sdk/networkInterceptor.js +364 -0
  73. package/lib/module/sdk/utils.js +412 -0
  74. package/lib/module/sdk/version.js +7 -0
  75. package/lib/module/types/expo-router.d.js +2 -0
  76. package/lib/module/types/index.js +2 -0
  77. package/lib/typescript/NativeRejourney.d.ts +160 -0
  78. package/lib/typescript/components/Mask.d.ts +54 -0
  79. package/lib/typescript/index.d.ts +117 -0
  80. package/lib/typescript/sdk/autoTracking.d.ts +226 -0
  81. package/lib/typescript/sdk/constants.d.ts +138 -0
  82. package/lib/typescript/sdk/errorTracking.d.ts +47 -0
  83. package/lib/typescript/sdk/index.d.ts +24 -0
  84. package/lib/typescript/sdk/metricsTracking.d.ts +75 -0
  85. package/lib/typescript/sdk/navigation.d.ts +48 -0
  86. package/lib/typescript/sdk/networkInterceptor.d.ts +62 -0
  87. package/lib/typescript/sdk/utils.d.ts +193 -0
  88. package/lib/typescript/sdk/version.d.ts +6 -0
  89. package/lib/typescript/types/index.d.ts +618 -0
  90. package/package.json +122 -0
  91. package/rejourney.podspec +23 -0
  92. package/src/NativeRejourney.ts +185 -0
  93. package/src/components/Mask.tsx +93 -0
  94. package/src/index.ts +1555 -0
  95. package/src/sdk/autoTracking.ts +1245 -0
  96. package/src/sdk/constants.ts +155 -0
  97. package/src/sdk/errorTracking.ts +231 -0
  98. package/src/sdk/index.ts +25 -0
  99. package/src/sdk/metricsTracking.ts +227 -0
  100. package/src/sdk/navigation.ts +152 -0
  101. package/src/sdk/networkInterceptor.ts +423 -0
  102. package/src/sdk/utils.ts +442 -0
  103. package/src/sdk/version.ts +6 -0
  104. package/src/types/expo-router.d.ts +7 -0
  105. package/src/types/index.ts +709 -0
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright 2026 Rejourney
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef Rejourney_h
18
+ #define Rejourney_h
19
+
20
+ #import <Foundation/Foundation.h>
21
+ #import <React/RCTBridgeModule.h>
22
+
23
+ #ifdef RCT_NEW_ARCH_ENABLED
24
+ #import <ReactCommon/RCTTurboModule.h>
25
+ #if __has_include(<RejourneySpec/RejourneySpec.h>)
26
+ #import <RejourneySpec/RejourneySpec.h>
27
+ #elif __has_include("RejourneySpec.h")
28
+ #import "RejourneySpec.h"
29
+ #endif
30
+
31
+ @interface Rejourney : NSObject <NativeRejourneySpec>
32
+ #else
33
+ @interface Rejourney : NSObject <RCTBridgeModule>
34
+ #endif
35
+
36
+ @end
37
+
38
+ #endif /* Rejourney_h */
@@ -0,0 +1,375 @@
1
+ /**
2
+ * Copyright 2026 Rejourney
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #import "Rejourney.h"
18
+ #import <React/RCTBridgeModule.h>
19
+ #import <React/RCTLog.h>
20
+
21
+ // Import the Swift-generated header - this is created at build time
22
+ // The header name follows the pattern: <ProductModuleName>-Swift.h
23
+ #if __has_include(<Rejourney/Rejourney-Swift.h>)
24
+ #import <Rejourney/Rejourney-Swift.h>
25
+ #elif __has_include("Rejourney-Swift.h")
26
+ #import "Rejourney-Swift.h"
27
+ #else
28
+ // Fallback: forward declare the Swift class for runtime resolution
29
+ @class RejourneyImpl;
30
+ #endif
31
+
32
+ #ifdef RCT_NEW_ARCH_ENABLED
33
+ #import <ReactCommon/RCTTurboModule.h>
34
+ #if __has_include(<RejourneySpec/RejourneySpec.h>)
35
+ #import <RejourneySpec/RejourneySpec.h>
36
+ #elif __has_include("RejourneySpec.h")
37
+ #import "RejourneySpec.h"
38
+ #endif
39
+ #endif
40
+
41
+ #pragma mark - Private Interface
42
+
43
+ @interface Rejourney ()
44
+ @property(nonatomic, strong) RejourneyImpl *impl;
45
+ @end
46
+
47
+ #pragma mark - Implementation
48
+
49
+ @implementation Rejourney
50
+
51
+ @synthesize bridge = _bridge;
52
+
53
+ RCT_EXPORT_MODULE()
54
+
55
+ + (BOOL)requiresMainQueueSetup {
56
+ return YES;
57
+ }
58
+
59
+ - (instancetype)init {
60
+ self = [super init];
61
+ if (self) {
62
+ _impl = [self resolveSwiftImpl];
63
+ if (!_impl) {
64
+ RCTLogWarn(@"[Rejourney] Swift implementation not found - will retry at "
65
+ @"method call time");
66
+ }
67
+ }
68
+ return self;
69
+ }
70
+
71
+ #pragma mark - Tap Event Emission (no-ops, dead tap detection is native-side)
72
+
73
+ RCT_EXPORT_METHOD(addListener:(NSString *)eventName) {
74
+ // No-op: dead tap detection is handled natively in TelemetryPipeline
75
+ }
76
+
77
+ RCT_EXPORT_METHOD(removeListeners:(double)count) {
78
+ // No-op: dead tap detection is handled natively in TelemetryPipeline
79
+ }
80
+
81
+ - (RejourneyImpl *)resolveSwiftImpl {
82
+ // First try direct class access (works when Swift header is properly
83
+ // imported)
84
+ Class implClass = NSClassFromString(@"RejourneyImpl");
85
+ if (!implClass) {
86
+ // Try module-prefixed names
87
+ implClass = NSClassFromString(@"Rejourney.RejourneyImpl");
88
+ }
89
+ if (!implClass) {
90
+ implClass = NSClassFromString(@"rejourney.RejourneyImpl");
91
+ }
92
+
93
+ if (implClass) {
94
+ SEL sharedSel = NSSelectorFromString(@"shared");
95
+ if ([implClass respondsToSelector:sharedSel]) {
96
+ #pragma clang diagnostic push
97
+ #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
98
+ return [implClass performSelector:sharedSel];
99
+ #pragma clang diagnostic pop
100
+ }
101
+ }
102
+
103
+ return nil;
104
+ }
105
+
106
+ - (RejourneyImpl *)ensureImpl {
107
+ if (!_impl) {
108
+ _impl = [self resolveSwiftImpl];
109
+ }
110
+ return _impl;
111
+ }
112
+
113
+ #ifdef RCT_NEW_ARCH_ENABLED
114
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
115
+ (const facebook::react::ObjCTurboModule::InitParams &)params {
116
+ return std::make_shared<facebook::react::NativeRejourneySpecJSI>(params);
117
+ }
118
+ #endif
119
+
120
+ #pragma mark - Session Lifecycle
121
+
122
+ RCT_EXPORT_METHOD(startSession : (NSString *)userId apiUrl : (NSString *)
123
+ apiUrl publicKey : (NSString *)
124
+ publicKey resolve : (RCTPromiseResolveBlock)
125
+ resolve reject : (RCTPromiseRejectBlock)reject) {
126
+ RejourneyImpl *impl = [self ensureImpl];
127
+ if (!impl) {
128
+ resolve(@{
129
+ @"success" : @NO,
130
+ @"sessionId" : @"",
131
+ @"error" : @"Native module not available - cannot start recording"
132
+ });
133
+ return;
134
+ }
135
+ [impl startSession:userId
136
+ apiUrl:apiUrl
137
+ publicKey:publicKey
138
+ resolve:resolve
139
+ reject:reject];
140
+ }
141
+
142
+ RCT_EXPORT_METHOD(startSessionWithOptions : (NSDictionary *)options resolve : (
143
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
144
+ RejourneyImpl *impl = [self ensureImpl];
145
+ if (!impl) {
146
+ resolve(@{
147
+ @"success" : @NO,
148
+ @"sessionId" : @"",
149
+ @"error" : @"Native module not available"
150
+ });
151
+ return;
152
+ }
153
+ [impl startSessionWithOptions:options resolve:resolve reject:reject];
154
+ }
155
+
156
+ RCT_EXPORT_METHOD(stopSession : (RCTPromiseResolveBlock)
157
+ resolve reject : (RCTPromiseRejectBlock)reject) {
158
+ RejourneyImpl *impl = [self ensureImpl];
159
+ if (!impl) {
160
+ resolve(@{@"success" : @YES, @"sessionId" : @""});
161
+ return;
162
+ }
163
+ [impl stopSession:resolve reject:reject];
164
+ }
165
+
166
+ RCT_EXPORT_METHOD(getSessionId : (RCTPromiseResolveBlock)
167
+ resolve reject : (RCTPromiseRejectBlock)reject) {
168
+ RejourneyImpl *impl = [self ensureImpl];
169
+ if (!impl) {
170
+ resolve([NSNull null]);
171
+ return;
172
+ }
173
+ [impl getSessionId:resolve reject:reject];
174
+ }
175
+
176
+ #pragma mark - User Identity
177
+
178
+ RCT_EXPORT_METHOD(setUserIdentity : (NSString *)userId resolve : (
179
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
180
+ RejourneyImpl *impl = [self ensureImpl];
181
+ if (!impl) {
182
+ resolve(@{@"success" : @NO});
183
+ return;
184
+ }
185
+ [impl setUserIdentity:userId resolve:resolve reject:reject];
186
+ }
187
+
188
+ RCT_EXPORT_METHOD(getUserIdentity : (RCTPromiseResolveBlock)
189
+ resolve reject : (RCTPromiseRejectBlock)reject) {
190
+ RejourneyImpl *impl = [self ensureImpl];
191
+ if (!impl) {
192
+ resolve([NSNull null]);
193
+ return;
194
+ }
195
+ [impl getUserIdentity:resolve reject:reject];
196
+ }
197
+
198
+ #pragma mark - Events and Tracking
199
+
200
+ RCT_EXPORT_METHOD(logEvent : (NSString *)eventType details : (NSDictionary *)
201
+ details resolve : (RCTPromiseResolveBlock)
202
+ resolve reject : (RCTPromiseRejectBlock)reject) {
203
+ RejourneyImpl *impl = [self ensureImpl];
204
+ if (!impl) {
205
+ resolve(@{@"success" : @YES}); // Silent success - don't break the app
206
+ return;
207
+ }
208
+ [impl logEvent:eventType details:details resolve:resolve reject:reject];
209
+ }
210
+
211
+ RCT_EXPORT_METHOD(screenChanged : (NSString *)screenName resolve : (
212
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
213
+ RejourneyImpl *impl = [self ensureImpl];
214
+ if (!impl) {
215
+ resolve(@{@"success" : @YES});
216
+ return;
217
+ }
218
+ [impl screenChanged:screenName resolve:resolve reject:reject];
219
+ }
220
+
221
+ RCT_EXPORT_METHOD(onScroll : (double)offsetY resolve : (RCTPromiseResolveBlock)
222
+ resolve reject : (RCTPromiseRejectBlock)reject) {
223
+ RejourneyImpl *impl = [self ensureImpl];
224
+ if (!impl) {
225
+ resolve(@{@"success" : @YES});
226
+ return;
227
+ }
228
+ [impl onScroll:offsetY resolve:resolve reject:reject];
229
+ }
230
+
231
+ RCT_EXPORT_METHOD(markVisualChange : (NSString *)reason importance : (
232
+ NSString *)importance resolve : (RCTPromiseResolveBlock)
233
+ resolve reject : (RCTPromiseRejectBlock)reject) {
234
+ RejourneyImpl *impl = [self ensureImpl];
235
+ if (!impl) {
236
+ resolve(@YES);
237
+ return;
238
+ }
239
+ [impl markVisualChange:reason
240
+ importance:importance
241
+ resolve:resolve
242
+ reject:reject];
243
+ }
244
+
245
+ #pragma mark - External Events
246
+
247
+ RCT_EXPORT_METHOD(onExternalURLOpened : (NSString *)urlScheme resolve : (
248
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
249
+ RejourneyImpl *impl = [self ensureImpl];
250
+ if (!impl) {
251
+ resolve(@{@"success" : @YES});
252
+ return;
253
+ }
254
+ [impl onExternalURLOpened:urlScheme resolve:resolve reject:reject];
255
+ }
256
+
257
+ RCT_EXPORT_METHOD(onOAuthStarted : (NSString *)provider resolve : (
258
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
259
+ RejourneyImpl *impl = [self ensureImpl];
260
+ if (!impl) {
261
+ resolve(@{@"success" : @YES});
262
+ return;
263
+ }
264
+ [impl onOAuthStarted:provider resolve:resolve reject:reject];
265
+ }
266
+
267
+ RCT_EXPORT_METHOD(onOAuthCompleted : (NSString *)provider success : (BOOL)
268
+ success resolve : (RCTPromiseResolveBlock)
269
+ resolve reject : (RCTPromiseRejectBlock)reject) {
270
+ RejourneyImpl *impl = [self ensureImpl];
271
+ if (!impl) {
272
+ resolve(@{@"success" : @YES});
273
+ return;
274
+ }
275
+ [impl onOAuthCompleted:provider
276
+ success:success
277
+ resolve:resolve
278
+ reject:reject];
279
+ }
280
+
281
+ #pragma mark - View Masking
282
+
283
+ RCT_EXPORT_METHOD(maskViewByNativeID : (NSString *)nativeID resolve : (
284
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
285
+ RejourneyImpl *impl = [self ensureImpl];
286
+ if (!impl) {
287
+ resolve(@{@"success" : @NO});
288
+ return;
289
+ }
290
+ [impl maskViewByNativeID:nativeID resolve:resolve reject:reject];
291
+ }
292
+
293
+ RCT_EXPORT_METHOD(unmaskViewByNativeID : (NSString *)nativeID resolve : (
294
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
295
+ RejourneyImpl *impl = [self ensureImpl];
296
+ if (!impl) {
297
+ resolve(@{@"success" : @NO});
298
+ return;
299
+ }
300
+ [impl unmaskViewByNativeID:nativeID resolve:resolve reject:reject];
301
+ }
302
+
303
+ #pragma mark - Debug and Info
304
+
305
+ RCT_EXPORT_METHOD(setDebugMode : (BOOL)enabled resolve : (
306
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
307
+ RejourneyImpl *impl = [self ensureImpl];
308
+ if (!impl) {
309
+ resolve(@{@"success" : @NO});
310
+ return;
311
+ }
312
+ [impl setDebugMode:enabled resolve:resolve reject:reject];
313
+ }
314
+
315
+ RCT_EXPORT_METHOD(setRemoteConfig : (BOOL)rejourneyEnabled
316
+ recordingEnabled : (BOOL)recordingEnabled
317
+ sampleRate : (double)sampleRate
318
+ maxRecordingMinutes : (double)maxRecordingMinutes
319
+ resolve : (RCTPromiseResolveBlock)resolve
320
+ reject : (RCTPromiseRejectBlock)reject) {
321
+ RejourneyImpl *impl = [self ensureImpl];
322
+ if (!impl) {
323
+ resolve(@{@"success" : @NO});
324
+ return;
325
+ }
326
+ [impl setRemoteConfigWithRejourneyEnabled:rejourneyEnabled
327
+ recordingEnabled:recordingEnabled
328
+ sampleRate:(NSInteger)sampleRate
329
+ maxRecordingMinutes:(NSInteger)maxRecordingMinutes
330
+ resolve:resolve
331
+ reject:reject];
332
+ }
333
+
334
+ RCT_EXPORT_METHOD(getSDKMetrics : (RCTPromiseResolveBlock)
335
+ resolve reject : (RCTPromiseRejectBlock)reject) {
336
+ RejourneyImpl *impl = [self ensureImpl];
337
+ if (!impl) {
338
+ resolve(@{});
339
+ return;
340
+ }
341
+ [impl getSDKMetrics:resolve reject:reject];
342
+ }
343
+
344
+ RCT_EXPORT_METHOD(getDeviceInfo : (RCTPromiseResolveBlock)
345
+ resolve reject : (RCTPromiseRejectBlock)reject) {
346
+ RejourneyImpl *impl = [self ensureImpl];
347
+ if (!impl) {
348
+ resolve(@{});
349
+ return;
350
+ }
351
+ [impl getDeviceInfo:resolve reject:reject];
352
+ }
353
+
354
+ RCT_EXPORT_METHOD(setSDKVersion : (NSString *)version) {
355
+ RejourneyImpl *impl = [self ensureImpl];
356
+ if (impl) {
357
+ [impl setSDKVersion:version];
358
+ }
359
+ }
360
+
361
+ RCT_EXPORT_METHOD(debugCrash) {
362
+ RejourneyImpl *impl = [self ensureImpl];
363
+ if (impl) {
364
+ [impl debugCrash];
365
+ }
366
+ }
367
+
368
+ RCT_EXPORT_METHOD(debugTriggerANR : (double)durationMs) {
369
+ RejourneyImpl *impl = [self ensureImpl];
370
+ if (impl) {
371
+ [impl debugTriggerANR:durationMs];
372
+ }
373
+ }
374
+
375
+ @end
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Copyright 2026 Rejourney
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import Foundation
18
+ import zlib
19
+
20
+ extension Data {
21
+ /// Compress data using gzip
22
+ func gzipCompress() -> Data? {
23
+ return self.withUnsafeBytes { (sourceBytes: UnsafeRawBufferPointer) -> Data? in
24
+ var stream = z_stream()
25
+ stream.next_in = UnsafeMutablePointer<Bytef>(mutating: sourceBytes.bindMemory(to: Bytef.self).baseAddress)
26
+ stream.avail_in = uint(self.count)
27
+ stream.total_out = 0
28
+
29
+ // MAX_WBITS + 16 = gzip format
30
+ if deflateInit2_(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY, ZLIB_VERSION, Int32(MemoryLayout<z_stream>.size)) != Z_OK {
31
+ return nil
32
+ }
33
+
34
+ var output = Data(capacity: self.count / 2)
35
+ let chunk = 16384
36
+
37
+ repeat {
38
+ if Int(stream.total_out) >= output.count {
39
+ output.count += chunk
40
+ }
41
+
42
+ output.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in
43
+ stream.next_out = outputBytes.bindMemory(to: Bytef.self).baseAddress!.advanced(by: Int(stream.total_out))
44
+ stream.avail_out = uint(outputBytes.count - Int(stream.total_out))
45
+
46
+ deflate(&stream, Z_FINISH)
47
+ }
48
+ } while stream.avail_out == 0
49
+
50
+ deflateEnd(&stream)
51
+ output.count = Int(stream.total_out)
52
+ return output
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Copyright 2026 Rejourney
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import UIKit
18
+ import Accelerate
19
+
20
+ extension UIImage {
21
+ /// Apply Gaussian blur to the image
22
+ func gaussianBlur(radius: CGFloat) -> UIImage? {
23
+ guard let cgImage = cgImage else { return nil }
24
+
25
+ let inputRadius: CGFloat = radius * scale
26
+ let sqrtPi: CGFloat = sqrt(2.0 * CGFloat.pi)
27
+ let radiusCalc: CGFloat = inputRadius * 3.0 * sqrtPi / 4.0 + 0.5
28
+ var kernelRadius: UInt32 = UInt32(floor(radiusCalc))
29
+ if kernelRadius % 2 != 1 { kernelRadius += 1 }
30
+
31
+ var inputBuffer = vImage_Buffer()
32
+ var outputBuffer = vImage_Buffer()
33
+
34
+ let width = vImagePixelCount(cgImage.width)
35
+ let height = vImagePixelCount(cgImage.height)
36
+ let rowBytes = cgImage.bytesPerRow
37
+
38
+ let inputData = UnsafeMutableRawPointer.allocate(byteCount: Int(height) * rowBytes, alignment: MemoryLayout<UInt8>.alignment)
39
+ defer { inputData.deallocate() }
40
+
41
+ let colorSpace = CGColorSpaceCreateDeviceRGB()
42
+ guard let ctx = CGContext(
43
+ data: inputData,
44
+ width: Int(width),
45
+ height: Int(height),
46
+ bitsPerComponent: 8,
47
+ bytesPerRow: rowBytes,
48
+ space: colorSpace,
49
+ bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
50
+ ) else { return nil }
51
+
52
+ ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height)))
53
+
54
+ inputBuffer.data = inputData
55
+ inputBuffer.width = width
56
+ inputBuffer.height = height
57
+ inputBuffer.rowBytes = rowBytes
58
+
59
+ let outputData = UnsafeMutableRawPointer.allocate(byteCount: Int(height) * rowBytes, alignment: MemoryLayout<UInt8>.alignment)
60
+ defer { outputData.deallocate() }
61
+
62
+ outputBuffer.data = outputData
63
+ outputBuffer.width = width
64
+ outputBuffer.height = height
65
+ outputBuffer.rowBytes = rowBytes
66
+
67
+ var err = vImageBoxConvolve_ARGB8888(&inputBuffer, &outputBuffer, nil, 0, 0, kernelRadius, kernelRadius, nil, vImage_Flags(kvImageEdgeExtend))
68
+ guard err == kvImageNoError else { return nil }
69
+
70
+ err = vImageBoxConvolve_ARGB8888(&outputBuffer, &inputBuffer, nil, 0, 0, kernelRadius, kernelRadius, nil, vImage_Flags(kvImageEdgeExtend))
71
+ guard err == kvImageNoError else { return nil }
72
+
73
+ err = vImageBoxConvolve_ARGB8888(&inputBuffer, &outputBuffer, nil, 0, 0, kernelRadius, kernelRadius, nil, vImage_Flags(kvImageEdgeExtend))
74
+ guard err == kvImageNoError else { return nil }
75
+
76
+ guard let outputCtx = CGContext(
77
+ data: outputData,
78
+ width: Int(width),
79
+ height: Int(height),
80
+ bitsPerComponent: 8,
81
+ bytesPerRow: rowBytes,
82
+ space: colorSpace,
83
+ bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
84
+ ) else { return nil }
85
+
86
+ guard let blurredCGImage = outputCtx.makeImage() else { return nil }
87
+ return UIImage(cgImage: blurredCGImage, scale: scale, orientation: imageOrientation)
88
+ }
89
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright 2026 Rejourney
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import UIKit
18
+ import ObjectiveC
19
+
20
+ @objc(ObjCRuntimeUtils)
21
+ public final class ObjCRuntimeUtils: NSObject {
22
+
23
+ @objc public static func hotswap(cls: AnyClass, original: Selector, replacement: Selector) {
24
+ guard let m1 = class_getInstanceMethod(cls, original),
25
+ let m2 = class_getInstanceMethod(cls, replacement) else { return }
26
+ method_exchangeImplementations(m1, m2)
27
+ }
28
+
29
+ @objc public static func hotswapSafely(cls: AnyClass, original: Selector, replacement: Selector) {
30
+ guard let m1 = class_getInstanceMethod(cls, original),
31
+ let m2 = class_getInstanceMethod(cls, replacement) else { return }
32
+
33
+ let added = class_addMethod(cls, original, method_getImplementation(m2), method_getTypeEncoding(m2))
34
+
35
+ if added {
36
+ class_replaceMethod(cls, replacement, method_getImplementation(m1), method_getTypeEncoding(m1))
37
+ } else {
38
+ method_exchangeImplementations(m1, m2)
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright 2026 Rejourney
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import UIKit
18
+ import ObjectiveC
19
+
20
+ private var _rjViewIdentifierKey: UInt8 = 0
21
+
22
+ public extension UIView {
23
+ var rjViewIdentifier: String? {
24
+ if let rnNativeID = value(forKey: "nativeID") as? String, !rnNativeID.isEmpty {
25
+ return rnNativeID
26
+ }
27
+ return objc_getAssociatedObject(self, &_rjViewIdentifierKey) as? String
28
+ }
29
+
30
+ func setRjViewIdentifier(_ identifier: String?) {
31
+ objc_setAssociatedObject(self, &_rjViewIdentifierKey, identifier, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
32
+ }
33
+
34
+ var nativeID: String? {
35
+ value(forKey: "nativeID") as? String
36
+ }
37
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _reactNative = require("react-native");
8
+ /**
9
+ * TurboModule spec for Rejourney SDK
10
+ *
11
+ * This file defines the native module interface for React Native's New Architecture.
12
+ * It follows the official React Native TurboModules pattern for Codegen compatibility.
13
+ *
14
+ * IMPORTANT: This spec file is used by Codegen to generate native bindings.
15
+ * The default export MUST be a direct TurboModuleRegistry.get() call.
16
+ *
17
+ * @see https://reactnative.dev/docs/turbo-native-modules-introduction
18
+ */
19
+ /**
20
+ * SDK telemetry metrics for observability
21
+ */
22
+ /**
23
+ * Native Rejourney module specification for TurboModules (New Architecture)
24
+ *
25
+ * This interface defines all methods exposed by the native module.
26
+ * Codegen uses this to generate:
27
+ * - iOS: RejourneySpec.h (protocol) and RejourneySpec-generated.mm (JSI bindings)
28
+ * - Android: NativeRejourneySpec.java (interface)
29
+ */
30
+ /**
31
+ * Default export for Codegen.
32
+ *
33
+ * CRITICAL: This MUST be a direct TurboModuleRegistry.get() call.
34
+ * Codegen parses this file statically and requires this exact pattern.
35
+ *
36
+ * Using getEnforcing() would throw if module not found.
37
+ * Using get() returns null, which is safer during development/testing.
38
+ */
39
+ var _default = exports.default = _reactNative.TurboModuleRegistry.get('Rejourney');
40
+ //# sourceMappingURL=NativeRejourney.js.map