@npaw/forge-react-native 9.6.1
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 +10 -0
- package/NPAWForgeReactNative.podspec +44 -0
- package/README.md +51 -0
- package/android/build.gradle +77 -0
- package/android/src/main/AndroidManifest.xml +14 -0
- package/android/src/main/java/com/npaw/forge/reactnative/ForgeDtoMapper.java +295 -0
- package/android/src/main/java/com/npaw/forge/reactnative/ForgeInstanceRegistry.java +61 -0
- package/android/src/main/java/com/npaw/forge/reactnative/NPAWForgeModule.java +735 -0
- package/android/src/main/java/com/npaw/forge/reactnative/NPAWForgePackage.java +53 -0
- package/android/src/test/java/com/npaw/forge/reactnative/ForgeDtoMapperTest.java +133 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/Info.plist +82 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernel.swift +3931 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernelFFI.modulemap +7 -0
- package/ios/ForgeApple/Sources/NPAWForgeAVPlayerAdapter/AVPlayerAccessLogFacts.swift +152 -0
- package/ios/ForgeApple/Sources/NPAWForgeAVPlayerAdapter/AVPlayerAdapter.swift +877 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/AttributionCapture.swift +158 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/CapturePlanGate.swift +189 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/CrashCapture.swift +120 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/ForgeAutomaticCapture.swift +639 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsCapture.swift +1176 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsEngine.swift +674 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsMarkers.swift +105 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsSwiftUI.swift +284 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SwiftUICapture.swift +44 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/AdAdapter.swift +199 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/AdSemantics.swift +136 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeApple.swift +596 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeCapturePlan.swift +297 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeClock.swift +29 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeLogging.swift +109 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeOutcome.swift +89 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeRuntime.swift +291 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeStorage.swift +70 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ManualAdReporter.swift +180 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NPAWForge.swift +453 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NativeUniFFIRuntime.swift +594 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NetworkRequestRecord.swift +191 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ObjectiveCWrappers.swift +191 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PlayerAdapter.swift +299 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PlayerSemantics.swift +266 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PrivacySanitizer.swift +59 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/VideoAdapter.swift +478 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/VideoOptions.swift +431 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCapture/ForgeNetworkCapture.swift +116 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCaptureObjC/NPAWForgeNetworkSwizzler.m +293 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCaptureObjC/include/NPAWForgeNetworkSwizzler.h +33 -0
- package/ios/ForgeModuleImpl.swift +1131 -0
- package/ios/NPAWForgeTurboModule.mm +399 -0
- package/package.json +33 -0
- package/src/ForgeAdReporter.ts +101 -0
- package/src/ForgeVideo.ts +169 -0
- package/src/NPAWForge.ts +177 -0
- package/src/capture.ts +192 -0
- package/src/events.ts +40 -0
- package/src/index.ts +37 -0
- package/src/specs/NativeNPAWForge.ts +168 -0
- package/src/types.ts +114 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Copyright (C) NPAW - All Rights Reserved
|
|
2
|
+
|
|
3
|
+
This software is protected under international copyright law. All rights
|
|
4
|
+
reserved and protected by the copyright holders. This software is confidential
|
|
5
|
+
and only available to authorized individuals with the permission of the
|
|
6
|
+
copyright holders. If you obtained this software and do not have permission,
|
|
7
|
+
please contact the copyright holders and delete it.
|
|
8
|
+
|
|
9
|
+
Use of this software requires an active NPAW commercial agreement. See
|
|
10
|
+
https://npaw.com for licensing and support.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Copyright (C) NPAW - All Rights Reserved
|
|
2
|
+
#
|
|
3
|
+
# This source code is protected under international copyright law. All rights
|
|
4
|
+
# reserved and protected by the copyright holders. This file is confidential and
|
|
5
|
+
# only available to authorized individuals with the permission of the copyright
|
|
6
|
+
# holders. If you encounter this file and do not have permission, please contact
|
|
7
|
+
# the copyright holders and delete this file.
|
|
8
|
+
#
|
|
9
|
+
#
|
|
10
|
+
# @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
11
|
+
# @description: CocoaPods spec for the @npaw/forge-react-native core TurboModule over the Forge Apple SDK.
|
|
12
|
+
|
|
13
|
+
require "json"
|
|
14
|
+
|
|
15
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
16
|
+
|
|
17
|
+
Pod::Spec.new do |s|
|
|
18
|
+
s.name = "NPAWForgeReactNative"
|
|
19
|
+
s.version = package["version"]
|
|
20
|
+
s.summary = package["description"]
|
|
21
|
+
s.homepage = "https://npaw.com"
|
|
22
|
+
s.license = { :type => "Commercial", :text => "Copyright (C) NPAW - All Rights Reserved" }
|
|
23
|
+
s.authors = { "Victor Soto" => "victor.soto@nicepeopleatwork.com" }
|
|
24
|
+
s.platforms = { :ios => "13.0" }
|
|
25
|
+
s.source = { :path => "." }
|
|
26
|
+
|
|
27
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
28
|
+
s.swift_version = "5.9"
|
|
29
|
+
|
|
30
|
+
# FORGE_APPLE_CONSUMPTION BEGIN (staged: hydrated self-contained variant)
|
|
31
|
+
s.vendored_frameworks = "ios/ForgeApple/ForgeKernelFFI.xcframework"
|
|
32
|
+
s.preserve_paths = "ios/ForgeApple/**"
|
|
33
|
+
s.pod_target_xcconfig = {
|
|
34
|
+
"DEFINES_MODULE" => "YES",
|
|
35
|
+
"OTHER_SWIFT_FLAGS" => "$(inherited) -DFORGE_HAS_UNIFFI -DFORGE_RN_HYDRATED",
|
|
36
|
+
}
|
|
37
|
+
# FORGE_APPLE_CONSUMPTION END
|
|
38
|
+
|
|
39
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
40
|
+
install_modules_dependencies(s)
|
|
41
|
+
else
|
|
42
|
+
s.dependency "React-Core"
|
|
43
|
+
end
|
|
44
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# @npaw/forge-react-native
|
|
2
|
+
|
|
3
|
+
NPAW Forge analytics for React Native: application sessions, user identity,
|
|
4
|
+
video and ad analytics, capture, and network observation, powered by the shared
|
|
5
|
+
Forge analytics core through the native Android and Apple SDKs.
|
|
6
|
+
|
|
7
|
+
Use of this package requires an active NPAW commercial agreement. See
|
|
8
|
+
[LICENSE](./LICENSE).
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm install @npaw/forge-react-native
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires React Native 0.75+ with the New Architecture enabled (TurboModules).
|
|
17
|
+
|
|
18
|
+
### iOS
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
cd ios && pod install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Android
|
|
25
|
+
|
|
26
|
+
No extra steps: the module resolves the published Forge Android coordinates.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
import { NPAWForge } from '@npaw/forge-react-native';
|
|
32
|
+
|
|
33
|
+
const forge = await NPAWForge.create({
|
|
34
|
+
accountCode: '<account-code>',
|
|
35
|
+
appName: 'My App',
|
|
36
|
+
appReleaseVersion: '1.0.0',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await forge.startSession({ screen: 'Home' });
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Player adapters
|
|
43
|
+
|
|
44
|
+
This package reports application sessions and manual video/ad events. For
|
|
45
|
+
automatic playback reporting with `react-native-video`, add
|
|
46
|
+
[`@npaw/forge-react-native-video`](https://www.npmjs.com/package/@npaw/forge-react-native-video).
|
|
47
|
+
|
|
48
|
+
## Documentation
|
|
49
|
+
|
|
50
|
+
Integration guides and the API reference are published at
|
|
51
|
+
[npaw.com](https://npaw.com).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Copyright (C) NPAW - All Rights Reserved
|
|
2
|
+
//
|
|
3
|
+
// This source code is protected under international copyright law. All rights
|
|
4
|
+
// reserved and protected by the copyright holders. This file is confidential and
|
|
5
|
+
// only available to authorized individuals with the permission of the copyright
|
|
6
|
+
// holders. If you encounter this file and do not have permission, please contact
|
|
7
|
+
// the copyright holders and delete this file.
|
|
8
|
+
//
|
|
9
|
+
//
|
|
10
|
+
// @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
11
|
+
// @description: Android library build for the @npaw/forge-react-native TurboModule wrapping the published Forge Android SDK. Pure-Java module so the Kotlin-2.3-built Forge AAR imposes no Kotlin floor on host apps.
|
|
12
|
+
|
|
13
|
+
def isNewArchitectureEnabled() {
|
|
14
|
+
return project.hasProperty('newArchEnabled') && project.newArchEnabled == 'true'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
apply plugin: 'com.android.library'
|
|
18
|
+
if (isNewArchitectureEnabled()) {
|
|
19
|
+
apply plugin: 'com.facebook.react'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
def safeExtGet(prop, fallback) {
|
|
23
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Committed default stays 0.0.0; release staging rewrites it and the dev loop
|
|
27
|
+
// injects the locally published version via NpawForge_forgeCoreVersion or
|
|
28
|
+
// FORGE_CORE_VERSION (see scripts/react-native/hydrate-natives.sh).
|
|
29
|
+
def forgeCoreVersion = project.hasProperty('NpawForge_forgeCoreVersion')
|
|
30
|
+
? project.property('NpawForge_forgeCoreVersion')
|
|
31
|
+
: (System.getenv('FORGE_CORE_VERSION') ?: '9.6.1')
|
|
32
|
+
|
|
33
|
+
android {
|
|
34
|
+
namespace 'com.npaw.forge.reactnative'
|
|
35
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
36
|
+
|
|
37
|
+
defaultConfig {
|
|
38
|
+
minSdkVersion safeExtGet('minSdkVersion', 23)
|
|
39
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 34)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
compileOptions {
|
|
43
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
44
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
testOptions {
|
|
48
|
+
// android.util.Log in JVM unit tests (warn-and-ignore config paths).
|
|
49
|
+
unitTests.returnDefaultValues = true
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
repositories {
|
|
54
|
+
mavenCentral()
|
|
55
|
+
google()
|
|
56
|
+
def localMavenRepo = System.getenv('FORGE_LOCAL_MAVEN_REPO')
|
|
57
|
+
if (localMavenRepo != null && !localMavenRepo.isEmpty()) {
|
|
58
|
+
maven { url uri(localMavenRepo) }
|
|
59
|
+
}
|
|
60
|
+
maven { url 'https://artifact.plugin.npaw.com/artifactory/plugins/android' }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
dependencies {
|
|
64
|
+
implementation 'com.facebook.react:react-native:+'
|
|
65
|
+
// compileOnly + runtimeOnly split: this module's javac compiles against
|
|
66
|
+
// the Forge classes (javac ignores Kotlin metadata), while nothing from
|
|
67
|
+
// the Kotlin-2.3-built Forge graph — including its kotlin-stdlib —
|
|
68
|
+
// reaches the host app's Kotlin COMPILE classpath. The full graph still
|
|
69
|
+
// flows to every runtime classpath, where newer stdlib is binary-safe.
|
|
70
|
+
compileOnly "com.npaw.forge:forge-android-core:${forgeCoreVersion}"
|
|
71
|
+
runtimeOnly "com.npaw.forge:forge-android-core:${forgeCoreVersion}"
|
|
72
|
+
compileOnly "com.npaw.forge:forge-android-network-capture:${forgeCoreVersion}"
|
|
73
|
+
runtimeOnly "com.npaw.forge:forge-android-network-capture:${forgeCoreVersion}"
|
|
74
|
+
|
|
75
|
+
testImplementation 'junit:junit:4.13.2'
|
|
76
|
+
testImplementation "com.npaw.forge:forge-android-core:${forgeCoreVersion}"
|
|
77
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!--
|
|
3
|
+
Copyright (C) NPAW - All Rights Reserved
|
|
4
|
+
|
|
5
|
+
This source code is protected under international copyright law. All rights
|
|
6
|
+
reserved and protected by the copyright holders. This file is confidential and
|
|
7
|
+
only available to authorized individuals with the permission of the copyright
|
|
8
|
+
holders. If you encounter this file and do not have permission, please contact
|
|
9
|
+
the copyright holders and delete this file.
|
|
10
|
+
|
|
11
|
+
@author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
@description: Manifest stub for the @npaw/forge-react-native Android library module.
|
|
13
|
+
-->
|
|
14
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) NPAW - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This source code is protected under international copyright law. All rights
|
|
5
|
+
* reserved and protected by the copyright holders.
|
|
6
|
+
* This file is confidential and only available to authorized individuals with the
|
|
7
|
+
* permission of the copyright holders. If you encounter this file and do not have
|
|
8
|
+
* permission, please contact the copyright holders and delete this file.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
* @description: DTO conversions between React Native bridge maps and the Forge Android facade types (configs, params, outcomes, recorded events, network records).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
package com.npaw.forge.reactnative;
|
|
16
|
+
|
|
17
|
+
import androidx.annotation.Nullable;
|
|
18
|
+
import com.facebook.react.bridge.Arguments;
|
|
19
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
20
|
+
import com.facebook.react.bridge.WritableArray;
|
|
21
|
+
import com.facebook.react.bridge.WritableMap;
|
|
22
|
+
import com.npaw.forge.android.NPAWForge;
|
|
23
|
+
import com.npaw.forge.android.core.ForgeOutcome;
|
|
24
|
+
import com.npaw.forge.android.core.ForgeRecordedEvent;
|
|
25
|
+
import com.npaw.forge.android.network.NetworkRequestOutcome;
|
|
26
|
+
import com.npaw.forge.android.network.NetworkRequestRecord;
|
|
27
|
+
import com.npaw.forge.android.network.NetworkRequestSource;
|
|
28
|
+
import java.util.Collections;
|
|
29
|
+
import java.util.HashMap;
|
|
30
|
+
import java.util.List;
|
|
31
|
+
import java.util.Map;
|
|
32
|
+
import java.util.UUID;
|
|
33
|
+
|
|
34
|
+
public final class ForgeDtoMapper {
|
|
35
|
+
|
|
36
|
+
private ForgeDtoMapper() {}
|
|
37
|
+
|
|
38
|
+
// ---- inputs ----
|
|
39
|
+
|
|
40
|
+
public static Map<String, Object> toObjectMap(@Nullable ReadableMap map) {
|
|
41
|
+
if (map == null) {
|
|
42
|
+
return Collections.emptyMap();
|
|
43
|
+
}
|
|
44
|
+
return new HashMap<>(map.toHashMap());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Stringifies every value; the Forge params surfaces are string maps. */
|
|
48
|
+
public static HashMap<String, String> toStringMap(@Nullable ReadableMap map) {
|
|
49
|
+
HashMap<String, String> result = new HashMap<>();
|
|
50
|
+
if (map == null) {
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
for (Map.Entry<String, Object> entry : map.toHashMap().entrySet()) {
|
|
54
|
+
Object value = entry.getValue();
|
|
55
|
+
if (value == null) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (value instanceof Double) {
|
|
59
|
+
double d = (Double) value;
|
|
60
|
+
if (d == Math.rint(d) && !Double.isInfinite(d) && Math.abs(d) < 9.007199254740992E15) {
|
|
61
|
+
long asLong = (long) d;
|
|
62
|
+
result.put(entry.getKey(), String.valueOf(asLong));
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (value instanceof Boolean) {
|
|
67
|
+
result.put(entry.getKey(), ((Boolean) value) ? "true" : "false");
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
result.put(entry.getKey(), String.valueOf(value));
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public static HashMap<String, Double> toDoubleMap(@Nullable ReadableMap map) {
|
|
76
|
+
HashMap<String, Double> result = new HashMap<>();
|
|
77
|
+
if (map == null) {
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
for (Map.Entry<String, Object> entry : map.toHashMap().entrySet()) {
|
|
81
|
+
Object value = entry.getValue();
|
|
82
|
+
if (value instanceof Number) {
|
|
83
|
+
result.put(entry.getKey(), ((Number) value).doubleValue());
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@Nullable
|
|
90
|
+
public static String emptyToNull(@Nullable String value) {
|
|
91
|
+
return value == null || value.isEmpty() ? null : value;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public static void applyConfig(NPAWForge.Builder builder, @Nullable ReadableMap config) {
|
|
95
|
+
if (config == null) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
for (Map.Entry<String, Object> entry : config.toHashMap().entrySet()) {
|
|
99
|
+
String key = entry.getKey();
|
|
100
|
+
Object value = entry.getValue();
|
|
101
|
+
if (value == null) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
switch (key) {
|
|
105
|
+
case "appName":
|
|
106
|
+
builder.setAppName(String.valueOf(value));
|
|
107
|
+
break;
|
|
108
|
+
case "appReleaseVersion":
|
|
109
|
+
builder.setAppReleaseVersion(String.valueOf(value));
|
|
110
|
+
break;
|
|
111
|
+
case "buildVariant":
|
|
112
|
+
builder.setBuildVariant(String.valueOf(value));
|
|
113
|
+
break;
|
|
114
|
+
case "lmaEndpoint":
|
|
115
|
+
builder.setLmaEndpoint(String.valueOf(value));
|
|
116
|
+
break;
|
|
117
|
+
case "analyticsUserAgent":
|
|
118
|
+
builder.setAnalyticsUserAgent(String.valueOf(value));
|
|
119
|
+
break;
|
|
120
|
+
case "logLevel":
|
|
121
|
+
builder.setLogLevel(value);
|
|
122
|
+
break;
|
|
123
|
+
case "startSessionOnInitialize":
|
|
124
|
+
builder.setStartSessionOnInitialize(asBoolean(value));
|
|
125
|
+
break;
|
|
126
|
+
case "processEventsBeforeSessionStart":
|
|
127
|
+
builder.setProcessEventsBeforeSessionStart(asBoolean(value));
|
|
128
|
+
break;
|
|
129
|
+
case "preSessionEventQueueLimitEvents":
|
|
130
|
+
builder.setPreSessionEventQueueLimitEvents((int) asLong(value));
|
|
131
|
+
break;
|
|
132
|
+
case "preSessionEventQueueMaxAgeMs":
|
|
133
|
+
builder.setPreSessionEventQueueMaxAgeMs(asLong(value));
|
|
134
|
+
break;
|
|
135
|
+
case "allowLocalHttpForTesting":
|
|
136
|
+
builder.setLocalPlaintextTransportForTesting(asBoolean(value));
|
|
137
|
+
break;
|
|
138
|
+
case "deviceUuid":
|
|
139
|
+
builder.setDeviceUuid(String.valueOf(value));
|
|
140
|
+
break;
|
|
141
|
+
case "autoDeviceIdentityEnabled":
|
|
142
|
+
builder.setAutoDeviceIdentityEnabled(asBoolean(value));
|
|
143
|
+
break;
|
|
144
|
+
default:
|
|
145
|
+
android.util.Log.w(
|
|
146
|
+
"NPAWForgeRN", "Unknown ForgeConfig key '" + key + "' ignored (forward compatibility)");
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public static NetworkRequestRecord toNetworkRequestRecord(ReadableMap record) {
|
|
153
|
+
Map<String, Object> map = record.toHashMap();
|
|
154
|
+
String targetUrl = stringOr(map, "targetUrl", "");
|
|
155
|
+
String method = stringOr(map, "method", "GET");
|
|
156
|
+
int responseStatusCode = (int) longOr(map, "responseStatusCode", 0L);
|
|
157
|
+
long durationMs = longOr(map, "durationMs", 0L);
|
|
158
|
+
NetworkRequestOutcome outcome = parseOutcome(stringOr(map, "outcome", "unknown"));
|
|
159
|
+
return new NetworkRequestRecord(
|
|
160
|
+
targetUrl,
|
|
161
|
+
method,
|
|
162
|
+
responseStatusCode,
|
|
163
|
+
durationMs,
|
|
164
|
+
outcome,
|
|
165
|
+
0L,
|
|
166
|
+
UUID.randomUUID().toString(),
|
|
167
|
+
NetworkRequestSource.Manual,
|
|
168
|
+
null,
|
|
169
|
+
null,
|
|
170
|
+
nullableString(map, "responseStatusText"),
|
|
171
|
+
nullableString(map, "errorMessage"),
|
|
172
|
+
nullableString(map, "traceparent"),
|
|
173
|
+
nullableLong(map, "dnsDurationMs"),
|
|
174
|
+
nullableLong(map, "connectDurationMs"),
|
|
175
|
+
nullableLong(map, "sslDurationMs"),
|
|
176
|
+
nullableLong(map, "requestDurationMs"),
|
|
177
|
+
nullableLong(map, "timeToFirstByteMs"),
|
|
178
|
+
nullableLong(map, "responseDownloadDurationMs"),
|
|
179
|
+
nullableLong(map, "redirectDurationMs"),
|
|
180
|
+
nullableInt(map, "redirectCount"),
|
|
181
|
+
nullableString(map, "protocol"),
|
|
182
|
+
nullableLong(map, "requestBytes"),
|
|
183
|
+
nullableLong(map, "responseBytes"),
|
|
184
|
+
Collections.emptyMap(),
|
|
185
|
+
Collections.emptyMap());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ---- outputs ----
|
|
189
|
+
|
|
190
|
+
public static WritableMap outcomeToMap(ForgeOutcome outcome) {
|
|
191
|
+
WritableMap result = Arguments.createMap();
|
|
192
|
+
result.putString("code", outcome.getCode());
|
|
193
|
+
result.putBoolean("isAccepted", outcome.isAccepted());
|
|
194
|
+
if (outcome instanceof ForgeOutcome.FailedWithDiagnostic) {
|
|
195
|
+
ForgeOutcome.FailedWithDiagnostic failed = (ForgeOutcome.FailedWithDiagnostic) outcome;
|
|
196
|
+
result.putString("reason", failed.getReason());
|
|
197
|
+
WritableMap details = Arguments.createMap();
|
|
198
|
+
for (Map.Entry<String, String> entry : failed.getDetails().entrySet()) {
|
|
199
|
+
details.putString(entry.getKey(), entry.getValue());
|
|
200
|
+
}
|
|
201
|
+
result.putMap("details", details);
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public static WritableMap recordedEventToMap(String instanceId, ForgeRecordedEvent event) {
|
|
207
|
+
WritableMap result = Arguments.createMap();
|
|
208
|
+
result.putString("instanceId", instanceId);
|
|
209
|
+
result.putString("eventName", event.getEventName());
|
|
210
|
+
result.putDouble("timestampMs", (double) event.getTimestampMs());
|
|
211
|
+
WritableMap payload = Arguments.createMap();
|
|
212
|
+
for (Map.Entry<String, String> entry : event.getPayload().entrySet()) {
|
|
213
|
+
payload.putString(entry.getKey(), entry.getValue());
|
|
214
|
+
}
|
|
215
|
+
result.putMap("payload", payload);
|
|
216
|
+
result.putBoolean("urgent", event.getUrgent());
|
|
217
|
+
if (event.getViewKey() != null) {
|
|
218
|
+
result.putString("viewKey", event.getViewKey());
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
public static WritableMap snapshotToMap(String instanceId, List<ForgeRecordedEvent> events) {
|
|
224
|
+
WritableArray items = Arguments.createArray();
|
|
225
|
+
for (ForgeRecordedEvent event : events) {
|
|
226
|
+
items.pushMap(recordedEventToMap(instanceId, event));
|
|
227
|
+
}
|
|
228
|
+
WritableMap result = Arguments.createMap();
|
|
229
|
+
result.putArray("items", items);
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---- helpers ----
|
|
234
|
+
|
|
235
|
+
private static boolean asBoolean(Object value) {
|
|
236
|
+
if (value instanceof Boolean) {
|
|
237
|
+
return (Boolean) value;
|
|
238
|
+
}
|
|
239
|
+
return Boolean.parseBoolean(String.valueOf(value));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private static long asLong(Object value) {
|
|
243
|
+
if (value instanceof Number) {
|
|
244
|
+
return ((Number) value).longValue();
|
|
245
|
+
}
|
|
246
|
+
return Long.parseLong(String.valueOf(value));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private static String stringOr(Map<String, Object> map, String key, String fallback) {
|
|
250
|
+
Object value = map.get(key);
|
|
251
|
+
return value == null ? fallback : String.valueOf(value);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private static long longOr(Map<String, Object> map, String key, long fallback) {
|
|
255
|
+
Object value = map.get(key);
|
|
256
|
+
return value instanceof Number ? ((Number) value).longValue() : fallback;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@Nullable
|
|
260
|
+
private static String nullableString(Map<String, Object> map, String key) {
|
|
261
|
+
Object value = map.get(key);
|
|
262
|
+
return value == null ? null : String.valueOf(value);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@Nullable
|
|
266
|
+
private static Long nullableLong(Map<String, Object> map, String key) {
|
|
267
|
+
Object value = map.get(key);
|
|
268
|
+
return value instanceof Number ? ((Number) value).longValue() : null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@Nullable
|
|
272
|
+
private static Integer nullableInt(Map<String, Object> map, String key) {
|
|
273
|
+
Object value = map.get(key);
|
|
274
|
+
return value instanceof Number ? ((Number) value).intValue() : null;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private static NetworkRequestOutcome parseOutcome(String wireName) {
|
|
278
|
+
switch (wireName) {
|
|
279
|
+
case "success":
|
|
280
|
+
return NetworkRequestOutcome.Success;
|
|
281
|
+
case "http_error":
|
|
282
|
+
return NetworkRequestOutcome.HttpError;
|
|
283
|
+
case "network_error":
|
|
284
|
+
return NetworkRequestOutcome.NetworkError;
|
|
285
|
+
case "cancelled":
|
|
286
|
+
return NetworkRequestOutcome.Cancelled;
|
|
287
|
+
case "timeout":
|
|
288
|
+
return NetworkRequestOutcome.Timeout;
|
|
289
|
+
case "blocked":
|
|
290
|
+
return NetworkRequestOutcome.Blocked;
|
|
291
|
+
default:
|
|
292
|
+
return NetworkRequestOutcome.Unknown;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) NPAW - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This source code is protected under international copyright law. All rights
|
|
5
|
+
* reserved and protected by the copyright holders.
|
|
6
|
+
* This file is confidential and only available to authorized individuals with the
|
|
7
|
+
* permission of the copyright holders. If you encounter this file and do not have
|
|
8
|
+
* permission, please contact the copyright holders and delete this file.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
* @description: Process-wide registry mapping React Native instance ids to live NPAWForge facades; the compile-time seam the video package uses to reach core instances. Written in Java so the module compiles under any host-app Kotlin version despite the Kotlin-2.3-built Forge AAR.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
package com.npaw.forge.reactnative;
|
|
16
|
+
|
|
17
|
+
import com.npaw.forge.android.NPAWForge;
|
|
18
|
+
import com.npaw.forge.android.video.VideoAdapter;
|
|
19
|
+
import java.util.ArrayList;
|
|
20
|
+
import java.util.HashMap;
|
|
21
|
+
import java.util.List;
|
|
22
|
+
import java.util.Map;
|
|
23
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
24
|
+
import androidx.annotation.Nullable;
|
|
25
|
+
|
|
26
|
+
public final class ForgeInstanceRegistry {
|
|
27
|
+
|
|
28
|
+
private static final ConcurrentHashMap<String, NPAWForge> INSTANCES = new ConcurrentHashMap<>();
|
|
29
|
+
|
|
30
|
+
private ForgeInstanceRegistry() {}
|
|
31
|
+
|
|
32
|
+
public static void register(String instanceId, NPAWForge forge) {
|
|
33
|
+
INSTANCES.put(instanceId, forge);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Nullable
|
|
37
|
+
public static NPAWForge remove(String instanceId) {
|
|
38
|
+
return INSTANCES.remove(instanceId);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Nullable
|
|
42
|
+
public static NPAWForge resolve(String instanceId) {
|
|
43
|
+
return INSTANCES.get(instanceId);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Nullable
|
|
47
|
+
public static VideoAdapter resolveVideoAdapter(String instanceId, @Nullable String identifier) {
|
|
48
|
+
NPAWForge forge = INSTANCES.get(instanceId);
|
|
49
|
+
return forge == null ? null : forge.getVideoAdapter(identifier);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public static Map<String, NPAWForge> snapshot() {
|
|
53
|
+
return new HashMap<>(INSTANCES);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public static List<NPAWForge> clear() {
|
|
57
|
+
List<NPAWForge> live = new ArrayList<>(INSTANCES.values());
|
|
58
|
+
INSTANCES.clear();
|
|
59
|
+
return live;
|
|
60
|
+
}
|
|
61
|
+
}
|