@npaw/forge-react-native 9.6.1 → 9.7.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/android/build.gradle +1 -1
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/Info.plist +11 -11
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernel.swift +9 -1
- package/ios/ForgeApple/Sources/NPAWForgeCore/DeviceIdentity.swift +194 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeApple.swift +7 -1
- package/ios/ForgeApple/Sources/NPAWForgeCore/NPAWForge.swift +40 -3
- package/ios/ForgeApple/Sources/NPAWForgeCore/NativeUniFFIRuntime.swift +2 -0
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -28,7 +28,7 @@ def safeExtGet(prop, fallback) {
|
|
|
28
28
|
// FORGE_CORE_VERSION (see scripts/react-native/hydrate-natives.sh).
|
|
29
29
|
def forgeCoreVersion = project.hasProperty('NpawForge_forgeCoreVersion')
|
|
30
30
|
? project.property('NpawForge_forgeCoreVersion')
|
|
31
|
-
: (System.getenv('FORGE_CORE_VERSION') ?: '9.
|
|
31
|
+
: (System.getenv('FORGE_CORE_VERSION') ?: '9.7.0')
|
|
32
32
|
|
|
33
33
|
android {
|
|
34
34
|
namespace 'com.npaw.forge.reactnative'
|
|
@@ -10,15 +10,18 @@
|
|
|
10
10
|
<key>HeadersPath</key>
|
|
11
11
|
<string>Headers</string>
|
|
12
12
|
<key>LibraryIdentifier</key>
|
|
13
|
-
<string>
|
|
13
|
+
<string>ios-arm64_x86_64-simulator</string>
|
|
14
14
|
<key>LibraryPath</key>
|
|
15
15
|
<string>libForgeKernelFFI.a</string>
|
|
16
16
|
<key>SupportedArchitectures</key>
|
|
17
17
|
<array>
|
|
18
18
|
<string>arm64</string>
|
|
19
|
+
<string>x86_64</string>
|
|
19
20
|
</array>
|
|
20
21
|
<key>SupportedPlatform</key>
|
|
21
|
-
<string>
|
|
22
|
+
<string>ios</string>
|
|
23
|
+
<key>SupportedPlatformVariant</key>
|
|
24
|
+
<string>simulator</string>
|
|
22
25
|
</dict>
|
|
23
26
|
<dict>
|
|
24
27
|
<key>BinaryPath</key>
|
|
@@ -26,7 +29,7 @@
|
|
|
26
29
|
<key>HeadersPath</key>
|
|
27
30
|
<string>Headers</string>
|
|
28
31
|
<key>LibraryIdentifier</key>
|
|
29
|
-
<string>
|
|
32
|
+
<string>tvos-arm64</string>
|
|
30
33
|
<key>LibraryPath</key>
|
|
31
34
|
<string>libForgeKernelFFI.a</string>
|
|
32
35
|
<key>SupportedArchitectures</key>
|
|
@@ -34,7 +37,7 @@
|
|
|
34
37
|
<string>arm64</string>
|
|
35
38
|
</array>
|
|
36
39
|
<key>SupportedPlatform</key>
|
|
37
|
-
<string>
|
|
40
|
+
<string>tvos</string>
|
|
38
41
|
</dict>
|
|
39
42
|
<dict>
|
|
40
43
|
<key>BinaryPath</key>
|
|
@@ -42,16 +45,15 @@
|
|
|
42
45
|
<key>HeadersPath</key>
|
|
43
46
|
<string>Headers</string>
|
|
44
47
|
<key>LibraryIdentifier</key>
|
|
45
|
-
<string>
|
|
48
|
+
<string>tvos-arm64-simulator</string>
|
|
46
49
|
<key>LibraryPath</key>
|
|
47
50
|
<string>libForgeKernelFFI.a</string>
|
|
48
51
|
<key>SupportedArchitectures</key>
|
|
49
52
|
<array>
|
|
50
53
|
<string>arm64</string>
|
|
51
|
-
<string>x86_64</string>
|
|
52
54
|
</array>
|
|
53
55
|
<key>SupportedPlatform</key>
|
|
54
|
-
<string>
|
|
56
|
+
<string>tvos</string>
|
|
55
57
|
<key>SupportedPlatformVariant</key>
|
|
56
58
|
<string>simulator</string>
|
|
57
59
|
</dict>
|
|
@@ -61,7 +63,7 @@
|
|
|
61
63
|
<key>HeadersPath</key>
|
|
62
64
|
<string>Headers</string>
|
|
63
65
|
<key>LibraryIdentifier</key>
|
|
64
|
-
<string>
|
|
66
|
+
<string>ios-arm64</string>
|
|
65
67
|
<key>LibraryPath</key>
|
|
66
68
|
<string>libForgeKernelFFI.a</string>
|
|
67
69
|
<key>SupportedArchitectures</key>
|
|
@@ -69,9 +71,7 @@
|
|
|
69
71
|
<string>arm64</string>
|
|
70
72
|
</array>
|
|
71
73
|
<key>SupportedPlatform</key>
|
|
72
|
-
<string>
|
|
73
|
-
<key>SupportedPlatformVariant</key>
|
|
74
|
-
<string>simulator</string>
|
|
74
|
+
<string>ios</string>
|
|
75
75
|
</dict>
|
|
76
76
|
</array>
|
|
77
77
|
<key>CFBundlePackageType</key>
|
|
Binary file
|
package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/libForgeKernelFFI.a
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1891,11 +1891,13 @@ public struct AppleRuntimeConfig: Equatable, Hashable {
|
|
|
1891
1891
|
public var analyticsUserAgent: String?
|
|
1892
1892
|
public var allowLocalHttp: Bool
|
|
1893
1893
|
public var logLevel: String
|
|
1894
|
+
public var deviceUuid: String?
|
|
1895
|
+
public var deviceInfoJson: String?
|
|
1894
1896
|
public var preSessionEventPolicy: ApplePreSessionEventPolicy
|
|
1895
1897
|
|
|
1896
1898
|
// Default memberwise initializers are never public by default, so we
|
|
1897
1899
|
// declare one manually.
|
|
1898
|
-
public init(accountCode: String, pluginVersion: String, appName: String, buildVariant: String, appReleaseVersion: String?, lmaEndpoint: String, analyticsUserAgent: String?, allowLocalHttp: Bool, logLevel: String, preSessionEventPolicy: ApplePreSessionEventPolicy) {
|
|
1900
|
+
public init(accountCode: String, pluginVersion: String, appName: String, buildVariant: String, appReleaseVersion: String?, lmaEndpoint: String, analyticsUserAgent: String?, allowLocalHttp: Bool, logLevel: String, deviceUuid: String?, deviceInfoJson: String?, preSessionEventPolicy: ApplePreSessionEventPolicy) {
|
|
1899
1901
|
self.accountCode = accountCode
|
|
1900
1902
|
self.pluginVersion = pluginVersion
|
|
1901
1903
|
self.appName = appName
|
|
@@ -1905,6 +1907,8 @@ public struct AppleRuntimeConfig: Equatable, Hashable {
|
|
|
1905
1907
|
self.analyticsUserAgent = analyticsUserAgent
|
|
1906
1908
|
self.allowLocalHttp = allowLocalHttp
|
|
1907
1909
|
self.logLevel = logLevel
|
|
1910
|
+
self.deviceUuid = deviceUuid
|
|
1911
|
+
self.deviceInfoJson = deviceInfoJson
|
|
1908
1912
|
self.preSessionEventPolicy = preSessionEventPolicy
|
|
1909
1913
|
}
|
|
1910
1914
|
|
|
@@ -1933,6 +1937,8 @@ public struct FfiConverterTypeAppleRuntimeConfig: FfiConverterRustBuffer {
|
|
|
1933
1937
|
analyticsUserAgent: FfiConverterOptionString.read(from: &buf),
|
|
1934
1938
|
allowLocalHttp: FfiConverterBool.read(from: &buf),
|
|
1935
1939
|
logLevel: FfiConverterString.read(from: &buf),
|
|
1940
|
+
deviceUuid: FfiConverterOptionString.read(from: &buf),
|
|
1941
|
+
deviceInfoJson: FfiConverterOptionString.read(from: &buf),
|
|
1936
1942
|
preSessionEventPolicy: FfiConverterTypeApplePreSessionEventPolicy.read(from: &buf)
|
|
1937
1943
|
)
|
|
1938
1944
|
}
|
|
@@ -1947,6 +1953,8 @@ public struct FfiConverterTypeAppleRuntimeConfig: FfiConverterRustBuffer {
|
|
|
1947
1953
|
FfiConverterOptionString.write(value.analyticsUserAgent, into: &buf)
|
|
1948
1954
|
FfiConverterBool.write(value.allowLocalHttp, into: &buf)
|
|
1949
1955
|
FfiConverterString.write(value.logLevel, into: &buf)
|
|
1956
|
+
FfiConverterOptionString.write(value.deviceUuid, into: &buf)
|
|
1957
|
+
FfiConverterOptionString.write(value.deviceInfoJson, into: &buf)
|
|
1950
1958
|
FfiConverterTypeApplePreSessionEventPolicy.write(value.preSessionEventPolicy, into: &buf)
|
|
1951
1959
|
}
|
|
1952
1960
|
}
|
|
@@ -0,0 +1,194 @@
|
|
|
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: Automatic Apple device identity (deviceInfo fields and persistent deviceUUID) for Forge analytics.
|
|
13
|
+
*/
|
|
14
|
+
import Foundation
|
|
15
|
+
|
|
16
|
+
#if canImport(UIKit)
|
|
17
|
+
import UIKit
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
/// Device identity facts reported through the `deviceInfo` analytics parameter.
|
|
21
|
+
///
|
|
22
|
+
/// The JSON key names are a wire contract fixed by the v7 plugins, because the
|
|
23
|
+
/// NQS device resolver reads those exact names. Note `deviceType`/`deviceCode`
|
|
24
|
+
/// keep their prefix while `model`/`brand`/`osName`/`osVersion` do not, and
|
|
25
|
+
/// vendor is `brand` — `deviceVendor` is the backend's column name and has
|
|
26
|
+
/// never been a wire key.
|
|
27
|
+
public struct ForgeDeviceInfo: Equatable {
|
|
28
|
+
public var brand: String?
|
|
29
|
+
public var code: String?
|
|
30
|
+
public var model: String?
|
|
31
|
+
public var type: String?
|
|
32
|
+
public var name: String?
|
|
33
|
+
public var osName: String?
|
|
34
|
+
public var osVersion: String?
|
|
35
|
+
|
|
36
|
+
public init(
|
|
37
|
+
brand: String? = nil,
|
|
38
|
+
code: String? = nil,
|
|
39
|
+
model: String? = nil,
|
|
40
|
+
type: String? = nil,
|
|
41
|
+
name: String? = nil,
|
|
42
|
+
osName: String? = nil,
|
|
43
|
+
osVersion: String? = nil
|
|
44
|
+
) {
|
|
45
|
+
self.brand = brand
|
|
46
|
+
self.code = code
|
|
47
|
+
self.model = model
|
|
48
|
+
self.type = type
|
|
49
|
+
self.name = name
|
|
50
|
+
self.osName = osName
|
|
51
|
+
self.osVersion = osVersion
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// Ordered non-blank fields keyed by the `deviceInfo` JSON key names.
|
|
55
|
+
/// Blank values are omitted rather than sent empty, matching v7.
|
|
56
|
+
public func orderedFields() -> [(String, String)] {
|
|
57
|
+
var fields: [(String, String)] = []
|
|
58
|
+
func append(_ key: String, _ value: String?) {
|
|
59
|
+
guard let value, !value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
fields.append((key, value))
|
|
63
|
+
}
|
|
64
|
+
append("model", model)
|
|
65
|
+
append("osVersion", osVersion)
|
|
66
|
+
append("brand", brand)
|
|
67
|
+
append("deviceType", type)
|
|
68
|
+
append("deviceCode", code)
|
|
69
|
+
append("deviceName", name)
|
|
70
|
+
append("osName", osName)
|
|
71
|
+
return fields
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public var isEmpty: Bool { orderedFields().isEmpty }
|
|
75
|
+
|
|
76
|
+
/// Serializes to the JSON object string the kernel expects. Returns `nil`
|
|
77
|
+
/// when no fact is known, so the param stays off the wire entirely.
|
|
78
|
+
public func toRuntimeJson() -> String? {
|
|
79
|
+
let fields = orderedFields()
|
|
80
|
+
guard !fields.isEmpty else { return nil }
|
|
81
|
+
let body = fields
|
|
82
|
+
.map { "\(Self.quoted($0.0)):\(Self.quoted($0.1))" }
|
|
83
|
+
.joined(separator: ",")
|
|
84
|
+
return "{\(body)}"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private static func quoted(_ value: String) -> String {
|
|
88
|
+
var escaped = ""
|
|
89
|
+
for character in value.unicodeScalars {
|
|
90
|
+
switch character {
|
|
91
|
+
case "\"": escaped.append("\\\"")
|
|
92
|
+
case "\\": escaped.append("\\\\")
|
|
93
|
+
case "\n": escaped.append("\\n")
|
|
94
|
+
case "\r": escaped.append("\\r")
|
|
95
|
+
case "\t": escaped.append("\\t")
|
|
96
|
+
default:
|
|
97
|
+
if character.value < 0x20 {
|
|
98
|
+
escaped.append(String(format: "\\u%04x", character.value))
|
|
99
|
+
} else {
|
|
100
|
+
escaped.unicodeScalars.append(character)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return "\"\(escaped)\""
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public enum DeviceIdentity {
|
|
109
|
+
public static let deviceUuidStorageKey = "npaw_forge_device_uuid"
|
|
110
|
+
|
|
111
|
+
/// Collects the automatic device facts available on this platform.
|
|
112
|
+
///
|
|
113
|
+
/// Matches the v7 iOS plugin where it reports at all — `brand` is the
|
|
114
|
+
/// literal `Apple` and `osVersion` comes from the system — and adds the
|
|
115
|
+
/// two facts v7 left to the backend's User-Agent parsing: `osName` and the
|
|
116
|
+
/// hardware `model`. That addition is deliberate. Forge's analytics
|
|
117
|
+
/// User-Agent is `NPAWForgeApple/<version> (<app>; <variant>)`, which
|
|
118
|
+
/// carries no device identity at all, unlike v7's
|
|
119
|
+
/// `<app>/<version>/<UIDevice.model>/<hw.machine>/<systemVersion>`. Without
|
|
120
|
+
/// these two fields NPAW would have no way to resolve an Apple device.
|
|
121
|
+
///
|
|
122
|
+
/// `deviceType` is deliberately not inferred: v7 iOS emits no type literal
|
|
123
|
+
/// and the backend vocabulary is not ours to invent. Integrators can still
|
|
124
|
+
/// set it explicitly.
|
|
125
|
+
public static func collectDeviceInfo() -> ForgeDeviceInfo {
|
|
126
|
+
ForgeDeviceInfo(
|
|
127
|
+
brand: "Apple",
|
|
128
|
+
model: hardwareModel(),
|
|
129
|
+
osName: systemName(),
|
|
130
|
+
osVersion: systemVersion()
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// The hardware identifier, e.g. `iPhone16,1` or `AppleTV11,1`. This is the
|
|
135
|
+
/// same value v7 embedded in its User-Agent via `sysctlbyname("hw.machine")`.
|
|
136
|
+
/// On the simulator it reports the host architecture, which is expected.
|
|
137
|
+
public static func hardwareModel() -> String? {
|
|
138
|
+
var systemInfo = utsname()
|
|
139
|
+
uname(&systemInfo)
|
|
140
|
+
let machine = withUnsafePointer(to: &systemInfo.machine) { pointer in
|
|
141
|
+
pointer.withMemoryRebound(to: CChar.self, capacity: MemoryLayout.size(ofValue: pointer.pointee)) {
|
|
142
|
+
String(validatingUTF8: $0)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
guard let machine, !machine.isEmpty else { return nil }
|
|
146
|
+
return machine
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private static func systemName() -> String? {
|
|
150
|
+
#if os(tvOS)
|
|
151
|
+
return "tvOS"
|
|
152
|
+
#elseif os(visionOS)
|
|
153
|
+
return "visionOS"
|
|
154
|
+
#elseif os(watchOS)
|
|
155
|
+
return "watchOS"
|
|
156
|
+
#elseif os(macOS)
|
|
157
|
+
return "macOS"
|
|
158
|
+
#else
|
|
159
|
+
return "iOS"
|
|
160
|
+
#endif
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private static func systemVersion() -> String? {
|
|
164
|
+
#if canImport(UIKit)
|
|
165
|
+
let version = UIDevice.current.systemVersion
|
|
166
|
+
return version.isEmpty ? nil : version
|
|
167
|
+
#else
|
|
168
|
+
let version = ProcessInfo.processInfo.operatingSystemVersion
|
|
169
|
+
return "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
|
|
170
|
+
#endif
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// Returns a stable device identifier.
|
|
174
|
+
///
|
|
175
|
+
/// Prefers `identifierForVendor`, which is what v7 sends and what NPAW
|
|
176
|
+
/// already associates with Apple installs. When it is unavailable — it can
|
|
177
|
+
/// be `nil` before first unlock, and does not exist off UIKit — falls back
|
|
178
|
+
/// to a random UUID persisted in [storage], so a device is never left
|
|
179
|
+
/// without an identifier.
|
|
180
|
+
public static func persistentDeviceUuid(storage: ForgeStorage) -> String {
|
|
181
|
+
#if canImport(UIKit)
|
|
182
|
+
if let vendorId = UIDevice.current.identifierForVendor?.uuidString, !vendorId.isEmpty {
|
|
183
|
+
return vendorId
|
|
184
|
+
}
|
|
185
|
+
#endif
|
|
186
|
+
if let stored = storage.read(deviceUuidStorageKey),
|
|
187
|
+
!stored.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
188
|
+
return stored
|
|
189
|
+
}
|
|
190
|
+
let generated = UUID().uuidString
|
|
191
|
+
_ = storage.write(deviceUuidStorageKey, value: generated)
|
|
192
|
+
return generated
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -28,6 +28,8 @@ public struct ForgeAppleConfig: Equatable {
|
|
|
28
28
|
public var preSessionEventQueueLimitEvents: Int
|
|
29
29
|
public var preSessionEventQueueMaxAgeMs: Int64
|
|
30
30
|
public var logLevel: ForgeLogLevel
|
|
31
|
+
public var deviceUuid: String?
|
|
32
|
+
public var deviceInfo: ForgeDeviceInfo?
|
|
31
33
|
|
|
32
34
|
public init(
|
|
33
35
|
accountCode: String,
|
|
@@ -42,7 +44,9 @@ public struct ForgeAppleConfig: Equatable {
|
|
|
42
44
|
processEventsBeforeSessionStart: Bool = false,
|
|
43
45
|
preSessionEventQueueLimitEvents: Int = 100,
|
|
44
46
|
preSessionEventQueueMaxAgeMs: Int64 = 30_000,
|
|
45
|
-
logLevel: ForgeLogLevel = .warning
|
|
47
|
+
logLevel: ForgeLogLevel = .warning,
|
|
48
|
+
deviceUuid: String? = nil,
|
|
49
|
+
deviceInfo: ForgeDeviceInfo? = nil
|
|
46
50
|
) {
|
|
47
51
|
self.accountCode = accountCode
|
|
48
52
|
self.pluginVersion = pluginVersion
|
|
@@ -57,6 +61,8 @@ public struct ForgeAppleConfig: Equatable {
|
|
|
57
61
|
self.preSessionEventQueueLimitEvents = preSessionEventQueueLimitEvents
|
|
58
62
|
self.preSessionEventQueueMaxAgeMs = preSessionEventQueueMaxAgeMs
|
|
59
63
|
self.logLevel = logLevel
|
|
64
|
+
self.deviceUuid = deviceUuid
|
|
65
|
+
self.deviceInfo = deviceInfo
|
|
60
66
|
}
|
|
61
67
|
}
|
|
62
68
|
|
|
@@ -40,7 +40,7 @@ public final class NPAWForge: NSObject {
|
|
|
40
40
|
/// `scripts/apple/publish-local-shipped.sh` rewrites this literal to the
|
|
41
41
|
/// release version when staging the shipped package, and fails loudly if
|
|
42
42
|
/// it cannot find it. Keep it a plain stored literal for that reason.
|
|
43
|
-
public static let defaultPluginVersion = "9.
|
|
43
|
+
public static let defaultPluginVersion = "9.7.0"
|
|
44
44
|
public static let defaultAppName = "apple"
|
|
45
45
|
public static let defaultBuildVariant = "release"
|
|
46
46
|
public static let defaultLmaEndpoint = "https://lma.npaw.com"
|
|
@@ -298,6 +298,9 @@ public final class NPAWForge: NSObject {
|
|
|
298
298
|
private var preSessionEventQueueLimitEvents = 100
|
|
299
299
|
private var preSessionEventQueueMaxAgeMs: Int64 = 30_000
|
|
300
300
|
private var logLevel: ForgeLogLevel = .warning
|
|
301
|
+
private var autoDeviceIdentityEnabled = true
|
|
302
|
+
private var deviceUuid: String?
|
|
303
|
+
private var deviceInfo: ForgeDeviceInfo?
|
|
301
304
|
private var services: ForgeAppleServices?
|
|
302
305
|
|
|
303
306
|
public init(accountCode: String) {
|
|
@@ -378,7 +381,40 @@ public final class NPAWForge: NSObject {
|
|
|
378
381
|
return self
|
|
379
382
|
}
|
|
380
383
|
|
|
384
|
+
/// Disables the automatic device identity collection (`deviceInfo` from
|
|
385
|
+
/// the system plus the `deviceUUID`). `deviceUUID` is a persistent
|
|
386
|
+
/// identifier, so integrators can opt out; an explicit
|
|
387
|
+
/// ``setDeviceUuid(_:)`` value is still honored when disabled.
|
|
388
|
+
@discardableResult
|
|
389
|
+
public func setAutoDeviceIdentityEnabled(_ enabled: Bool) -> Builder {
|
|
390
|
+
autoDeviceIdentityEnabled = enabled
|
|
391
|
+
return self
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/// Overrides the automatically collected device identifier.
|
|
395
|
+
@discardableResult
|
|
396
|
+
public func setDeviceUuid(_ value: String?) -> Builder {
|
|
397
|
+
deviceUuid = value
|
|
398
|
+
return self
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/// Overrides the automatically collected `deviceInfo` facts wholesale.
|
|
402
|
+
@discardableResult
|
|
403
|
+
public func setDeviceInfo(_ value: ForgeDeviceInfo?) -> Builder {
|
|
404
|
+
deviceInfo = value
|
|
405
|
+
return self
|
|
406
|
+
}
|
|
407
|
+
|
|
381
408
|
public func build() -> NPAWForge {
|
|
409
|
+
// Services first: resolving the device UUID needs the storage the
|
|
410
|
+
// integrator supplied, so it cannot wait until after the config.
|
|
411
|
+
let resolvedServices = services ?? ForgeAppleServices(storage: UserDefaultsStorage())
|
|
412
|
+
let resolvedDeviceUuid = deviceUuid ?? (autoDeviceIdentityEnabled
|
|
413
|
+
? DeviceIdentity.persistentDeviceUuid(storage: resolvedServices.storage)
|
|
414
|
+
: nil)
|
|
415
|
+
let resolvedDeviceInfo = deviceInfo ?? (autoDeviceIdentityEnabled
|
|
416
|
+
? DeviceIdentity.collectDeviceInfo()
|
|
417
|
+
: nil)
|
|
382
418
|
let config = ForgeAppleConfig(
|
|
383
419
|
accountCode: accountCode,
|
|
384
420
|
pluginVersion: NPAWForge.defaultPluginVersion,
|
|
@@ -392,9 +428,10 @@ public final class NPAWForge: NSObject {
|
|
|
392
428
|
processEventsBeforeSessionStart: processEventsBeforeSessionStart,
|
|
393
429
|
preSessionEventQueueLimitEvents: preSessionEventQueueLimitEvents,
|
|
394
430
|
preSessionEventQueueMaxAgeMs: preSessionEventQueueMaxAgeMs,
|
|
395
|
-
logLevel: logLevel
|
|
431
|
+
logLevel: logLevel,
|
|
432
|
+
deviceUuid: resolvedDeviceUuid,
|
|
433
|
+
deviceInfo: resolvedDeviceInfo?.isEmpty == true ? nil : resolvedDeviceInfo
|
|
396
434
|
)
|
|
397
|
-
let resolvedServices = services ?? ForgeAppleServices(storage: UserDefaultsStorage())
|
|
398
435
|
let forge = NPAWForge(kernel: ForgeApple(config: config, services: resolvedServices))
|
|
399
436
|
ForgeAutomaticCaptureRegistry.installIfAvailable(forge)
|
|
400
437
|
return forge
|
|
@@ -38,6 +38,8 @@ final class UniFFIForgeRuntime: ForgeRuntime {
|
|
|
38
38
|
analyticsUserAgent: config.analyticsUserAgent,
|
|
39
39
|
allowLocalHttp: config.allowLocalHttp,
|
|
40
40
|
logLevel: config.logLevel.wireName,
|
|
41
|
+
deviceUuid: config.deviceUuid,
|
|
42
|
+
deviceInfoJson: config.deviceInfo?.toRuntimeJson(),
|
|
41
43
|
preSessionEventPolicy: ApplePreSessionEventPolicy(
|
|
42
44
|
processEventsBeforeSessionStart: config.processEventsBeforeSessionStart,
|
|
43
45
|
queueLimitEvents: UInt64(max(0, config.preSessionEventQueueLimitEvents)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npaw/forge-react-native",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.7.0",
|
|
4
4
|
"description": "NPAW Forge analytics for React Native: New Architecture TurboModule facade over the native Forge Android/Apple SDKs.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Victor Soto <victor.soto@nicepeopleatwork.com>",
|