@posthog/react-native-plugin 0.0.1 → 2.0.0
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.
- package/LICENSE +326 -0
- package/README.md +21 -35
- package/android/build.gradle +90 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/posthogreactnativeplugin/PosthogReactNativePluginModule.kt +301 -0
- package/android/src/main/java/com/posthogreactnativeplugin/PosthogReactNativePluginPackage.kt +13 -0
- package/ios/PosthogReactNativePlugin-Bridging-Header.h +2 -0
- package/ios/PosthogReactNativePlugin.mm +45 -0
- package/ios/PosthogReactNativePlugin.swift +217 -0
- package/lib/commonjs/index.js +60 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/index.js +48 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +39 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/index.d.ts +39 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +112 -7
- package/posthog-react-native-plugin.podspec +68 -0
- package/src/index.tsx +119 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
package com.posthogreactnativeplugin
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
7
|
+
import com.facebook.react.bridge.ReactMethod
|
|
8
|
+
import com.facebook.react.bridge.ReadableMap
|
|
9
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
10
|
+
import com.posthog.PostHog
|
|
11
|
+
import com.posthog.PostHogConfig
|
|
12
|
+
import com.posthog.android.PostHogAndroid
|
|
13
|
+
import com.posthog.android.PostHogAndroidConfig
|
|
14
|
+
import com.posthog.internal.PostHogPreferences
|
|
15
|
+
import com.posthog.internal.PostHogPreferences.Companion.ANONYMOUS_ID
|
|
16
|
+
import com.posthog.internal.PostHogPreferences.Companion.DISTINCT_ID
|
|
17
|
+
import com.posthog.internal.PostHogSessionManager
|
|
18
|
+
import java.util.UUID
|
|
19
|
+
|
|
20
|
+
class PosthogReactNativePluginModule(
|
|
21
|
+
reactContext: ReactApplicationContext,
|
|
22
|
+
) : ReactContextBaseJavaModule(reactContext) {
|
|
23
|
+
override fun getName(): String = NAME
|
|
24
|
+
|
|
25
|
+
@ReactMethod
|
|
26
|
+
fun setup(
|
|
27
|
+
sessionId: String,
|
|
28
|
+
sdkOptions: ReadableMap,
|
|
29
|
+
pluginConfig: ReadableMap,
|
|
30
|
+
promise: Promise,
|
|
31
|
+
) {
|
|
32
|
+
val sessionReplayConfig = getMap(pluginConfig, "sessionReplay")
|
|
33
|
+
val errorTrackingConfig = getMap(pluginConfig, "errorTracking")
|
|
34
|
+
|
|
35
|
+
setupNativeSdk(
|
|
36
|
+
method = "setup",
|
|
37
|
+
sessionId = sessionId,
|
|
38
|
+
sdkOptions = sdkOptions,
|
|
39
|
+
sessionReplayEnabled = getBoolean(sessionReplayConfig, "enabled", false),
|
|
40
|
+
sdkReplayConfig = getMap(sessionReplayConfig, "sdkReplayConfig"),
|
|
41
|
+
decideReplayConfig = getMap(sessionReplayConfig, "decideReplayConfig"),
|
|
42
|
+
nativeErrorTrackingAutocapture = getBoolean(errorTrackingConfig, "nativeAutocapture", false),
|
|
43
|
+
promise = promise,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@ReactMethod
|
|
48
|
+
fun start(
|
|
49
|
+
sessionId: String,
|
|
50
|
+
sdkOptions: ReadableMap,
|
|
51
|
+
sdkReplayConfig: ReadableMap,
|
|
52
|
+
decideReplayConfig: ReadableMap,
|
|
53
|
+
promise: Promise,
|
|
54
|
+
) {
|
|
55
|
+
setupNativeSdk(
|
|
56
|
+
method = "start",
|
|
57
|
+
sessionId = sessionId,
|
|
58
|
+
sdkOptions = sdkOptions,
|
|
59
|
+
sessionReplayEnabled = true,
|
|
60
|
+
sdkReplayConfig = sdkReplayConfig,
|
|
61
|
+
decideReplayConfig = decideReplayConfig,
|
|
62
|
+
nativeErrorTrackingAutocapture = false,
|
|
63
|
+
promise = promise,
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private fun setupNativeSdk(
|
|
68
|
+
method: String,
|
|
69
|
+
sessionId: String,
|
|
70
|
+
sdkOptions: ReadableMap,
|
|
71
|
+
sessionReplayEnabled: Boolean,
|
|
72
|
+
sdkReplayConfig: ReadableMap?,
|
|
73
|
+
decideReplayConfig: ReadableMap?,
|
|
74
|
+
nativeErrorTrackingAutocapture: Boolean,
|
|
75
|
+
promise: Promise,
|
|
76
|
+
) {
|
|
77
|
+
val initRunnable =
|
|
78
|
+
Runnable {
|
|
79
|
+
try {
|
|
80
|
+
val uuid = UUID.fromString(sessionId)
|
|
81
|
+
PostHogSessionManager.setSessionId(uuid)
|
|
82
|
+
|
|
83
|
+
val context = this.reactApplicationContext
|
|
84
|
+
val apiKey = getString(sdkOptions, "apiKey", "")
|
|
85
|
+
val host = getString(sdkOptions, "host", PostHogConfig.DEFAULT_HOST)
|
|
86
|
+
val debugValue = getBoolean(sdkOptions, "debug", false)
|
|
87
|
+
val distinctId = getString(sdkOptions, "distinctId", "")
|
|
88
|
+
val anonymousId = getString(sdkOptions, "anonymousId", "")
|
|
89
|
+
val theSdkVersion = getString(sdkOptions, "sdkVersion", "")
|
|
90
|
+
val theFlushAt = getInt(sdkOptions, "flushAt", DEFAULT_FLUSH_AT)
|
|
91
|
+
|
|
92
|
+
val config =
|
|
93
|
+
PostHogAndroidConfig(apiKey, host).apply {
|
|
94
|
+
debug = debugValue
|
|
95
|
+
captureDeepLinks = false
|
|
96
|
+
captureApplicationLifecycleEvents = false
|
|
97
|
+
captureScreenViews = false
|
|
98
|
+
flushAt = theFlushAt
|
|
99
|
+
errorTrackingConfig.autoCapture = nativeErrorTrackingAutocapture
|
|
100
|
+
|
|
101
|
+
if (sessionReplayEnabled) {
|
|
102
|
+
val maskAllTextInputs = getBoolean(sdkReplayConfig, "maskAllTextInputs", DEFAULT_MASK_ALL_TEXT_INPUTS)
|
|
103
|
+
val maskAllImages = getBoolean(sdkReplayConfig, "maskAllImages", DEFAULT_MASK_ALL_IMAGES)
|
|
104
|
+
val captureLog = getBoolean(sdkReplayConfig, "captureLog", DEFAULT_CAPTURE_LOG)
|
|
105
|
+
|
|
106
|
+
// read throttleDelayMs and use androidDebouncerDelayMs as a fallback for back compatibility
|
|
107
|
+
val throttleDelayMs =
|
|
108
|
+
when {
|
|
109
|
+
hasKey(sdkReplayConfig, "throttleDelayMs") -> getInt(sdkReplayConfig, "throttleDelayMs", DEFAULT_THROTTLE_DELAY_MS)
|
|
110
|
+
hasKey(sdkReplayConfig, "androidDebouncerDelayMs") -> getInt(sdkReplayConfig, "androidDebouncerDelayMs", DEFAULT_THROTTLE_DELAY_MS)
|
|
111
|
+
else -> DEFAULT_THROTTLE_DELAY_MS
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
sessionReplay = true
|
|
115
|
+
sessionReplayConfig.screenshot = true
|
|
116
|
+
sessionReplayConfig.captureLogcat = captureLog
|
|
117
|
+
sessionReplayConfig.throttleDelayMs = throttleDelayMs.toLong()
|
|
118
|
+
sessionReplayConfig.maskAllImages = maskAllImages
|
|
119
|
+
sessionReplayConfig.maskAllTextInputs = maskAllTextInputs
|
|
120
|
+
sessionReplayConfig.sampleRate = getDoubleOrNull(sdkReplayConfig, "sampleRate")
|
|
121
|
+
|
|
122
|
+
val endpoint = getString(decideReplayConfig, "endpoint", "")
|
|
123
|
+
if (endpoint.isNotEmpty()) {
|
|
124
|
+
snapshotEndpoint = endpoint
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (theSdkVersion.isNotEmpty()) {
|
|
129
|
+
sdkName = "posthog-react-native"
|
|
130
|
+
sdkVersion = theSdkVersion
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
PostHogAndroid.setup(context, config)
|
|
134
|
+
|
|
135
|
+
setIdentify(config.cachePreferences, distinctId, anonymousId)
|
|
136
|
+
} catch (e: Throwable) {
|
|
137
|
+
logError(method, e)
|
|
138
|
+
} finally {
|
|
139
|
+
promise.resolve(null)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// forces the SDK to be initialized on the main thread
|
|
144
|
+
if (UiThreadUtil.isOnUiThread()) {
|
|
145
|
+
initRunnable.run()
|
|
146
|
+
} else {
|
|
147
|
+
UiThreadUtil.runOnUiThread(initRunnable)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@ReactMethod
|
|
152
|
+
fun startSession(
|
|
153
|
+
sessionId: String,
|
|
154
|
+
promise: Promise,
|
|
155
|
+
) {
|
|
156
|
+
try {
|
|
157
|
+
val uuid = UUID.fromString(sessionId)
|
|
158
|
+
PostHogSessionManager.setSessionId(uuid)
|
|
159
|
+
PostHog.startSession()
|
|
160
|
+
} catch (e: Throwable) {
|
|
161
|
+
logError("startSession", e)
|
|
162
|
+
} finally {
|
|
163
|
+
promise.resolve(null)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@ReactMethod
|
|
168
|
+
fun isEnabled(promise: Promise) {
|
|
169
|
+
try {
|
|
170
|
+
promise.resolve(PostHog.isSessionReplayActive())
|
|
171
|
+
} catch (e: Throwable) {
|
|
172
|
+
logError("isEnabled", e)
|
|
173
|
+
promise.resolve(false)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@ReactMethod
|
|
178
|
+
fun endSession(promise: Promise) {
|
|
179
|
+
try {
|
|
180
|
+
PostHog.endSession()
|
|
181
|
+
} catch (e: Throwable) {
|
|
182
|
+
logError("endSession", e)
|
|
183
|
+
} finally {
|
|
184
|
+
promise.resolve(null)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@ReactMethod
|
|
189
|
+
fun identify(
|
|
190
|
+
distinctId: String,
|
|
191
|
+
anonymousId: String,
|
|
192
|
+
promise: Promise,
|
|
193
|
+
) {
|
|
194
|
+
try {
|
|
195
|
+
setIdentify(PostHog.getConfig<PostHogConfig>()?.cachePreferences, distinctId, anonymousId)
|
|
196
|
+
} catch (e: Throwable) {
|
|
197
|
+
logError("identify", e)
|
|
198
|
+
} finally {
|
|
199
|
+
promise.resolve(null)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private fun setIdentify(
|
|
204
|
+
cachePreferences: PostHogPreferences?,
|
|
205
|
+
distinctId: String,
|
|
206
|
+
anonymousId: String,
|
|
207
|
+
) {
|
|
208
|
+
cachePreferences?.let { preferences ->
|
|
209
|
+
if (anonymousId.isNotEmpty()) {
|
|
210
|
+
preferences.setValue(ANONYMOUS_ID, anonymousId)
|
|
211
|
+
}
|
|
212
|
+
if (distinctId.isNotEmpty()) {
|
|
213
|
+
preferences.setValue(DISTINCT_ID, distinctId)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@ReactMethod
|
|
219
|
+
fun startRecording(
|
|
220
|
+
resumeCurrent: Boolean,
|
|
221
|
+
promise: Promise,
|
|
222
|
+
) {
|
|
223
|
+
try {
|
|
224
|
+
PostHog.startSessionReplay(resumeCurrent)
|
|
225
|
+
} catch (e: Throwable) {
|
|
226
|
+
logError("startRecording", e)
|
|
227
|
+
} finally {
|
|
228
|
+
promise.resolve(null)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@ReactMethod
|
|
233
|
+
fun stopRecording(promise: Promise) {
|
|
234
|
+
try {
|
|
235
|
+
PostHog.stopSessionReplay()
|
|
236
|
+
} catch (e: Throwable) {
|
|
237
|
+
logError("stopRecording", e)
|
|
238
|
+
} finally {
|
|
239
|
+
promise.resolve(null)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private fun getMap(
|
|
244
|
+
map: ReadableMap?,
|
|
245
|
+
key: String,
|
|
246
|
+
): ReadableMap? =
|
|
247
|
+
runCatching {
|
|
248
|
+
if (map != null && map.hasKey(key) && !map.isNull(key)) {
|
|
249
|
+
map.getMap(key)
|
|
250
|
+
} else {
|
|
251
|
+
null
|
|
252
|
+
}
|
|
253
|
+
}.getOrNull()
|
|
254
|
+
|
|
255
|
+
private fun hasKey(
|
|
256
|
+
map: ReadableMap?,
|
|
257
|
+
key: String,
|
|
258
|
+
): Boolean = runCatching { map != null && map.hasKey(key) && !map.isNull(key) }.getOrDefault(false)
|
|
259
|
+
|
|
260
|
+
private fun getBoolean(
|
|
261
|
+
map: ReadableMap?,
|
|
262
|
+
key: String,
|
|
263
|
+
default: Boolean,
|
|
264
|
+
): Boolean = runCatching { if (hasKey(map, key)) map?.getBoolean(key) ?: default else default }.getOrDefault(default)
|
|
265
|
+
|
|
266
|
+
private fun getString(
|
|
267
|
+
map: ReadableMap?,
|
|
268
|
+
key: String,
|
|
269
|
+
default: String,
|
|
270
|
+
): String = runCatching { if (hasKey(map, key)) map?.getString(key) ?: default else default }.getOrDefault(default)
|
|
271
|
+
|
|
272
|
+
private fun getInt(
|
|
273
|
+
map: ReadableMap?,
|
|
274
|
+
key: String,
|
|
275
|
+
default: Int,
|
|
276
|
+
): Int = runCatching { if (hasKey(map, key)) map?.getInt(key) ?: default else default }.getOrDefault(default)
|
|
277
|
+
|
|
278
|
+
private fun getDoubleOrNull(
|
|
279
|
+
map: ReadableMap?,
|
|
280
|
+
key: String,
|
|
281
|
+
): Double? = runCatching { if (hasKey(map, key)) map?.getDouble(key) else null }.getOrNull()
|
|
282
|
+
|
|
283
|
+
private fun logError(
|
|
284
|
+
method: String,
|
|
285
|
+
error: Throwable,
|
|
286
|
+
) {
|
|
287
|
+
Log.println(Log.ERROR, POSTHOG_TAG, "Method $method, error: $error")
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
companion object {
|
|
291
|
+
const val NAME = "PosthogReactNativePlugin"
|
|
292
|
+
const val POSTHOG_TAG = "PostHog"
|
|
293
|
+
|
|
294
|
+
// Default session replay configuration values
|
|
295
|
+
const val DEFAULT_MASK_ALL_TEXT_INPUTS = true
|
|
296
|
+
const val DEFAULT_MASK_ALL_IMAGES = true
|
|
297
|
+
const val DEFAULT_CAPTURE_LOG = true
|
|
298
|
+
const val DEFAULT_FLUSH_AT = 20
|
|
299
|
+
const val DEFAULT_THROTTLE_DELAY_MS = 1000
|
|
300
|
+
}
|
|
301
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.posthogreactnativeplugin
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class PosthogReactNativePluginPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
|
|
10
|
+
listOf(PosthogReactNativePluginModule(reactContext))
|
|
11
|
+
|
|
12
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_MODULE(PosthogReactNativePlugin, NSObject)
|
|
4
|
+
|
|
5
|
+
RCT_EXTERN_METHOD(setup:(NSString)sessionId
|
|
6
|
+
withSdkOptions:(NSDictionary)sdkOptions
|
|
7
|
+
withPluginConfig:(NSDictionary)pluginConfig
|
|
8
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
10
|
+
|
|
11
|
+
RCT_EXTERN_METHOD(start:(NSString)sessionId
|
|
12
|
+
withSdkOptions:(NSDictionary)sdkOptions
|
|
13
|
+
withSdkReplayConfig:(NSDictionary)sdkReplayConfig
|
|
14
|
+
withDecideReplayConfig:(NSDictionary)decideReplayConfig
|
|
15
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
16
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
17
|
+
|
|
18
|
+
RCT_EXTERN_METHOD(startSession:(NSString)sessionId
|
|
19
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
20
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
21
|
+
|
|
22
|
+
RCT_EXTERN_METHOD(isEnabled:(RCTPromiseResolveBlock)resolve
|
|
23
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
24
|
+
|
|
25
|
+
RCT_EXTERN_METHOD(endSession:(RCTPromiseResolveBlock)resolve
|
|
26
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
27
|
+
|
|
28
|
+
RCT_EXTERN_METHOD(identify:(NSString)distinctId
|
|
29
|
+
withAnonymousId:(NSString)anonymousId
|
|
30
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
31
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
32
|
+
|
|
33
|
+
RCT_EXTERN_METHOD(startRecording:(BOOL)resumeCurrent
|
|
34
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
36
|
+
|
|
37
|
+
RCT_EXTERN_METHOD(stopRecording:(RCTPromiseResolveBlock)resolve
|
|
38
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
39
|
+
|
|
40
|
+
+ (BOOL)requiresMainQueueSetup
|
|
41
|
+
{
|
|
42
|
+
return NO;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@end
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import PostHog
|
|
2
|
+
|
|
3
|
+
/// Meant for internally logging PostHog related things
|
|
4
|
+
private func hedgeLog(_ message: String) {
|
|
5
|
+
print("[PostHog] \(message)")
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@objc(PosthogReactNativePlugin)
|
|
9
|
+
class PosthogReactNativePlugin: NSObject {
|
|
10
|
+
private var config: PostHogConfig?
|
|
11
|
+
|
|
12
|
+
@objc(setup:withSdkOptions:withPluginConfig:withResolver:withRejecter:)
|
|
13
|
+
func setup(
|
|
14
|
+
sessionId: String, sdkOptions: [String: Any], pluginConfig: [String: Any],
|
|
15
|
+
resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock
|
|
16
|
+
) {
|
|
17
|
+
let sessionReplayConfig = pluginConfig["sessionReplay"] as? [String: Any] ?? [:]
|
|
18
|
+
let errorTrackingConfig = pluginConfig["errorTracking"] as? [String: Any] ?? [:]
|
|
19
|
+
|
|
20
|
+
setupNativeSdk(
|
|
21
|
+
method: "setup",
|
|
22
|
+
sessionId: sessionId,
|
|
23
|
+
sdkOptions: sdkOptions,
|
|
24
|
+
sessionReplayEnabled: sessionReplayConfig["enabled"] as? Bool ?? false,
|
|
25
|
+
sdkReplayConfig: sessionReplayConfig["sdkReplayConfig"] as? [String: Any] ?? [:],
|
|
26
|
+
decideReplayConfig: sessionReplayConfig["decideReplayConfig"] as? [String: Any] ?? [:],
|
|
27
|
+
nativeErrorTrackingAutocapture: errorTrackingConfig["nativeAutocapture"] as? Bool ?? false,
|
|
28
|
+
resolve: resolve
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@objc(start:withSdkOptions:withSdkReplayConfig:withDecideReplayConfig:withResolver:withRejecter:)
|
|
33
|
+
func start(
|
|
34
|
+
sessionId: String, sdkOptions: [String: Any], sdkReplayConfig: [String: Any],
|
|
35
|
+
decideReplayConfig: [String: Any], resolve: RCTPromiseResolveBlock,
|
|
36
|
+
reject _: RCTPromiseRejectBlock
|
|
37
|
+
) {
|
|
38
|
+
setupNativeSdk(
|
|
39
|
+
method: "start",
|
|
40
|
+
sessionId: sessionId,
|
|
41
|
+
sdkOptions: sdkOptions,
|
|
42
|
+
sessionReplayEnabled: true,
|
|
43
|
+
sdkReplayConfig: sdkReplayConfig,
|
|
44
|
+
decideReplayConfig: decideReplayConfig,
|
|
45
|
+
nativeErrorTrackingAutocapture: false,
|
|
46
|
+
resolve: resolve
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private func setupNativeSdk(
|
|
51
|
+
method _: String,
|
|
52
|
+
sessionId: String,
|
|
53
|
+
sdkOptions: [String: Any],
|
|
54
|
+
sessionReplayEnabled: Bool,
|
|
55
|
+
sdkReplayConfig: [String: Any],
|
|
56
|
+
decideReplayConfig: [String: Any],
|
|
57
|
+
nativeErrorTrackingAutocapture: Bool,
|
|
58
|
+
resolve: RCTPromiseResolveBlock
|
|
59
|
+
) {
|
|
60
|
+
if sessionId.isEmpty {
|
|
61
|
+
hedgeLog("Invalid empty sessionId provided.")
|
|
62
|
+
resolve(nil)
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let projectToken =
|
|
67
|
+
(sdkOptions["projectToken"] as? String)
|
|
68
|
+
?? (sdkOptions["apiKey"] as? String)
|
|
69
|
+
?? ""
|
|
70
|
+
let host = sdkOptions["host"] as? String ?? PostHogConfig.defaultHost
|
|
71
|
+
let debug = sdkOptions["debug"] as? Bool ?? false
|
|
72
|
+
|
|
73
|
+
PostHogSessionManager.shared.setSessionId(sessionId)
|
|
74
|
+
|
|
75
|
+
let config = PostHogConfig(projectToken: projectToken, host: host)
|
|
76
|
+
config.captureApplicationLifecycleEvents = false
|
|
77
|
+
config.captureScreenViews = false
|
|
78
|
+
config.debug = debug
|
|
79
|
+
config.errorTrackingConfig.autoCapture = nativeErrorTrackingAutocapture
|
|
80
|
+
|
|
81
|
+
if #available(iOS 15.0, *) {
|
|
82
|
+
config.surveys = false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if sessionReplayEnabled {
|
|
86
|
+
config.sessionReplay = true
|
|
87
|
+
config.sessionReplayConfig.screenshotMode = true
|
|
88
|
+
|
|
89
|
+
let maskAllTextInputs = sdkReplayConfig["maskAllTextInputs"] as? Bool ?? true
|
|
90
|
+
config.sessionReplayConfig.maskAllTextInputs = maskAllTextInputs
|
|
91
|
+
|
|
92
|
+
let maskAllImages = sdkReplayConfig["maskAllImages"] as? Bool ?? true
|
|
93
|
+
config.sessionReplayConfig.maskAllImages = maskAllImages
|
|
94
|
+
|
|
95
|
+
let maskAllSandboxedViews = sdkReplayConfig["maskAllSandboxedViews"] as? Bool ?? true
|
|
96
|
+
config.sessionReplayConfig.maskAllSandboxedViews = maskAllSandboxedViews
|
|
97
|
+
|
|
98
|
+
// read throttleDelayMs and use iOSdebouncerDelayMs as a fallback for back compatibility
|
|
99
|
+
let throttleDelayMs =
|
|
100
|
+
(sdkReplayConfig["throttleDelayMs"] as? Int)
|
|
101
|
+
?? (sdkReplayConfig["iOSdebouncerDelayMs"] as? Int)
|
|
102
|
+
?? 1000
|
|
103
|
+
|
|
104
|
+
let timeInterval: TimeInterval = Double(throttleDelayMs) / 1000.0
|
|
105
|
+
config.sessionReplayConfig.throttleDelay = timeInterval
|
|
106
|
+
|
|
107
|
+
let captureNetworkTelemetry = sdkReplayConfig["captureNetworkTelemetry"] as? Bool ?? true
|
|
108
|
+
config.sessionReplayConfig.captureNetworkTelemetry = captureNetworkTelemetry
|
|
109
|
+
|
|
110
|
+
let captureLog = sdkReplayConfig["captureLog"] as? Bool ?? true
|
|
111
|
+
config.sessionReplayConfig.captureLogs = captureLog
|
|
112
|
+
|
|
113
|
+
config.sessionReplayConfig.sampleRate = sdkReplayConfig["sampleRate"] as? NSNumber
|
|
114
|
+
|
|
115
|
+
let screenshotModeBackgroundCapture = sdkReplayConfig["screenshotModeBackgroundCapture"] as? Bool ?? false
|
|
116
|
+
config.sessionReplayConfig.screenshotModeBackgroundCapture = screenshotModeBackgroundCapture
|
|
117
|
+
|
|
118
|
+
let endpoint = decideReplayConfig["endpoint"] as? String ?? ""
|
|
119
|
+
if !endpoint.isEmpty {
|
|
120
|
+
config.snapshotEndpoint = endpoint
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let distinctId = sdkOptions["distinctId"] as? String ?? ""
|
|
125
|
+
let anonymousId = sdkOptions["anonymousId"] as? String ?? ""
|
|
126
|
+
|
|
127
|
+
let sdkVersion = sdkOptions["sdkVersion"] as? String ?? ""
|
|
128
|
+
|
|
129
|
+
let flushAt = sdkOptions["flushAt"] as? Int ?? 20
|
|
130
|
+
config.flushAt = flushAt
|
|
131
|
+
|
|
132
|
+
if !sdkVersion.isEmpty {
|
|
133
|
+
postHogSdkName = "posthog-react-native"
|
|
134
|
+
postHogVersion = sdkVersion
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
PostHogSDK.shared.setup(config)
|
|
138
|
+
|
|
139
|
+
self.config = config
|
|
140
|
+
|
|
141
|
+
guard let storageManager = self.config?.storageManager else {
|
|
142
|
+
hedgeLog("Storage manager is not available in the config.")
|
|
143
|
+
resolve(nil)
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
setIdentify(storageManager, distinctId: distinctId, anonymousId: anonymousId)
|
|
148
|
+
|
|
149
|
+
resolve(nil)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@objc(startSession:withResolver:withRejecter:)
|
|
153
|
+
func startSession(
|
|
154
|
+
sessionId: String, resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock
|
|
155
|
+
) {
|
|
156
|
+
if sessionId.isEmpty {
|
|
157
|
+
hedgeLog("Invalid empty sessionId provided.")
|
|
158
|
+
resolve(nil)
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
PostHogSessionManager.shared.setSessionId(sessionId)
|
|
162
|
+
PostHogSDK.shared.startSession()
|
|
163
|
+
resolve(nil)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@objc(isEnabled:withRejecter:)
|
|
167
|
+
func isEnabled(resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock) {
|
|
168
|
+
let isEnabled = PostHogSDK.shared.isSessionReplayActive()
|
|
169
|
+
resolve(isEnabled)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@objc(endSession:withRejecter:)
|
|
173
|
+
func endSession(resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock) {
|
|
174
|
+
PostHogSDK.shared.endSession()
|
|
175
|
+
resolve(nil)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@objc(identify:withAnonymousId:withResolver:withRejecter:)
|
|
179
|
+
func identify(
|
|
180
|
+
distinctId: String, anonymousId: String, resolve: RCTPromiseResolveBlock,
|
|
181
|
+
reject _: RCTPromiseRejectBlock
|
|
182
|
+
) {
|
|
183
|
+
guard let storageManager = config?.storageManager else {
|
|
184
|
+
hedgeLog("Storage manager is not available in the config.")
|
|
185
|
+
resolve(nil)
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
setIdentify(storageManager, distinctId: distinctId, anonymousId: anonymousId)
|
|
189
|
+
|
|
190
|
+
resolve(nil)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private func setIdentify(
|
|
194
|
+
_ storageManager: PostHogStorageManager, distinctId: String, anonymousId: String
|
|
195
|
+
) {
|
|
196
|
+
if !anonymousId.isEmpty {
|
|
197
|
+
storageManager.setAnonymousId(anonymousId)
|
|
198
|
+
}
|
|
199
|
+
if !distinctId.isEmpty {
|
|
200
|
+
storageManager.setDistinctId(distinctId)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@objc(startRecording:withResolver:withRejecter:)
|
|
205
|
+
func startRecording(
|
|
206
|
+
resumeCurrent: Bool, resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock
|
|
207
|
+
) {
|
|
208
|
+
PostHogSDK.shared.startSessionRecording(resumeCurrent: resumeCurrent)
|
|
209
|
+
resolve(nil)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@objc(stopRecording:withRejecter:)
|
|
213
|
+
func stopRecording(resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock) {
|
|
214
|
+
PostHogSDK.shared.stopSessionRecording()
|
|
215
|
+
resolve(nil)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
exports.endSession = endSession;
|
|
8
|
+
exports.identify = identify;
|
|
9
|
+
exports.isEnabled = isEnabled;
|
|
10
|
+
exports.setup = setup;
|
|
11
|
+
exports.start = start;
|
|
12
|
+
exports.startRecording = startRecording;
|
|
13
|
+
exports.startSession = startSession;
|
|
14
|
+
exports.stopRecording = stopRecording;
|
|
15
|
+
var _reactNative = require("react-native");
|
|
16
|
+
const LINKING_ERROR = `The package '@posthog/react-native-plugin' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
|
|
17
|
+
ios: "- You have run 'pod install'\n",
|
|
18
|
+
default: ''
|
|
19
|
+
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
20
|
+
const PosthogReactNativePlugin = _reactNative.NativeModules.PosthogReactNativePlugin ? _reactNative.NativeModules.PosthogReactNativePlugin : new Proxy({}, {
|
|
21
|
+
get() {
|
|
22
|
+
throw new Error(LINKING_ERROR);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
function setup(sessionId, sdkOptions, pluginConfig = {}) {
|
|
26
|
+
return PosthogReactNativePlugin.setup(sessionId, sdkOptions, pluginConfig);
|
|
27
|
+
}
|
|
28
|
+
function start(sessionId, sdkOptions, sdkReplayConfig, decideReplayConfig) {
|
|
29
|
+
return PosthogReactNativePlugin.start(sessionId, sdkOptions, sdkReplayConfig, decideReplayConfig);
|
|
30
|
+
}
|
|
31
|
+
function startSession(sessionId) {
|
|
32
|
+
return PosthogReactNativePlugin.startSession(sessionId);
|
|
33
|
+
}
|
|
34
|
+
function endSession() {
|
|
35
|
+
return PosthogReactNativePlugin.endSession();
|
|
36
|
+
}
|
|
37
|
+
function isEnabled() {
|
|
38
|
+
return PosthogReactNativePlugin.isEnabled();
|
|
39
|
+
}
|
|
40
|
+
function identify(distinctId, anonymousId) {
|
|
41
|
+
return PosthogReactNativePlugin.identify(distinctId, anonymousId);
|
|
42
|
+
}
|
|
43
|
+
function startRecording(resumeCurrent) {
|
|
44
|
+
return PosthogReactNativePlugin.startRecording(resumeCurrent);
|
|
45
|
+
}
|
|
46
|
+
function stopRecording() {
|
|
47
|
+
return PosthogReactNativePlugin.stopRecording();
|
|
48
|
+
}
|
|
49
|
+
const PostHogReactNativePlugin = {
|
|
50
|
+
setup,
|
|
51
|
+
start,
|
|
52
|
+
startSession,
|
|
53
|
+
endSession,
|
|
54
|
+
isEnabled,
|
|
55
|
+
identify,
|
|
56
|
+
startRecording,
|
|
57
|
+
stopRecording
|
|
58
|
+
};
|
|
59
|
+
var _default = exports.default = PostHogReactNativePlugin;
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","PosthogReactNativePlugin","NativeModules","Proxy","get","Error","setup","sessionId","sdkOptions","pluginConfig","start","sdkReplayConfig","decideReplayConfig","startSession","endSession","isEnabled","identify","distinctId","anonymousId","startRecording","resumeCurrent","stopRecording","PostHogReactNativePlugin","_default","exports"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,aAAa,GACjB,uFAAuF,GACvFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,wBAAwB,GAAGC,0BAAa,CAACD,wBAAwB,GACnEC,0BAAa,CAACD,wBAAwB,GACtC,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAmBE,SAASU,KAAKA,CACnBC,SAAiB,EACjBC,UAAuC,EACvCC,YAA4C,GAAG,CAAC,CAAC,EAClC;EACf,OAAOR,wBAAwB,CAACK,KAAK,CAACC,SAAS,EAAEC,UAAU,EAAEC,YAAY,CAAC;AAC5E;AAEO,SAASC,KAAKA,CACnBH,SAAiB,EACjBC,UAAuC,EACvCG,eAA4C,EAC5CC,kBAA+C,EAChC;EACf,OAAOX,wBAAwB,CAACS,KAAK,CAACH,SAAS,EAAEC,UAAU,EAAEG,eAAe,EAAEC,kBAAkB,CAAC;AACnG;AAEO,SAASC,YAAYA,CAACN,SAAiB,EAAiB;EAC7D,OAAON,wBAAwB,CAACY,YAAY,CAACN,SAAS,CAAC;AACzD;AAEO,SAASO,UAAUA,CAAA,EAAkB;EAC1C,OAAOb,wBAAwB,CAACa,UAAU,CAAC,CAAC;AAC9C;AAEO,SAASC,SAASA,CAAA,EAAqB;EAC5C,OAAOd,wBAAwB,CAACc,SAAS,CAAC,CAAC;AAC7C;AAEO,SAASC,QAAQA,CAACC,UAAkB,EAAEC,WAAmB,EAAiB;EAC/E,OAAOjB,wBAAwB,CAACe,QAAQ,CAACC,UAAU,EAAEC,WAAW,CAAC;AACnE;AAEO,SAASC,cAAcA,CAACC,aAAsB,EAAiB;EACpE,OAAOnB,wBAAwB,CAACkB,cAAc,CAACC,aAAa,CAAC;AAC/D;AAEO,SAASC,aAAaA,CAAA,EAAkB;EAC7C,OAAOpB,wBAAwB,CAACoB,aAAa,CAAC,CAAC;AACjD;AAgCA,MAAMC,wBAAwD,GAAG;EAC/DhB,KAAK;EACLI,KAAK;EACLG,YAAY;EACZC,UAAU;EACVC,SAAS;EACTC,QAAQ;EACRG,cAAc;EACdE;AACF,CAAC;AAAA,IAAAE,QAAA,GAAAC,OAAA,CAAAxB,OAAA,GAEcsB,wBAAwB","ignoreList":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeModules, Platform } from 'react-native';
|
|
4
|
+
const LINKING_ERROR = `The package '@posthog/react-native-plugin' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
|
|
5
|
+
ios: "- You have run 'pod install'\n",
|
|
6
|
+
default: ''
|
|
7
|
+
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
8
|
+
const PosthogReactNativePlugin = NativeModules.PosthogReactNativePlugin ? NativeModules.PosthogReactNativePlugin : new Proxy({}, {
|
|
9
|
+
get() {
|
|
10
|
+
throw new Error(LINKING_ERROR);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export function setup(sessionId, sdkOptions, pluginConfig = {}) {
|
|
14
|
+
return PosthogReactNativePlugin.setup(sessionId, sdkOptions, pluginConfig);
|
|
15
|
+
}
|
|
16
|
+
export function start(sessionId, sdkOptions, sdkReplayConfig, decideReplayConfig) {
|
|
17
|
+
return PosthogReactNativePlugin.start(sessionId, sdkOptions, sdkReplayConfig, decideReplayConfig);
|
|
18
|
+
}
|
|
19
|
+
export function startSession(sessionId) {
|
|
20
|
+
return PosthogReactNativePlugin.startSession(sessionId);
|
|
21
|
+
}
|
|
22
|
+
export function endSession() {
|
|
23
|
+
return PosthogReactNativePlugin.endSession();
|
|
24
|
+
}
|
|
25
|
+
export function isEnabled() {
|
|
26
|
+
return PosthogReactNativePlugin.isEnabled();
|
|
27
|
+
}
|
|
28
|
+
export function identify(distinctId, anonymousId) {
|
|
29
|
+
return PosthogReactNativePlugin.identify(distinctId, anonymousId);
|
|
30
|
+
}
|
|
31
|
+
export function startRecording(resumeCurrent) {
|
|
32
|
+
return PosthogReactNativePlugin.startRecording(resumeCurrent);
|
|
33
|
+
}
|
|
34
|
+
export function stopRecording() {
|
|
35
|
+
return PosthogReactNativePlugin.stopRecording();
|
|
36
|
+
}
|
|
37
|
+
const PostHogReactNativePlugin = {
|
|
38
|
+
setup,
|
|
39
|
+
start,
|
|
40
|
+
startSession,
|
|
41
|
+
endSession,
|
|
42
|
+
isEnabled,
|
|
43
|
+
identify,
|
|
44
|
+
startRecording,
|
|
45
|
+
stopRecording
|
|
46
|
+
};
|
|
47
|
+
export default PostHogReactNativePlugin;
|
|
48
|
+
//# sourceMappingURL=index.js.map
|