@logbrew/react-native 0.1.11 → 0.1.13

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 (61) hide show
  1. package/LogBrewReactNative.podspec +25 -3
  2. package/README.md +106 -3
  3. package/apple-native-diagnostics.d.ts +52 -0
  4. package/apple-native-diagnostics.js +286 -0
  5. package/expo.cjs +46 -0
  6. package/expo.d.ts +16 -0
  7. package/expo.js +5 -0
  8. package/fatal-replay.cjs +12 -1
  9. package/global-errors.cjs +3 -1
  10. package/index.cjs +84 -2
  11. package/index.d.cts +4 -0
  12. package/index.d.ts +4 -0
  13. package/index.js +84 -2
  14. package/index.native.d.ts +4 -0
  15. package/index.native.js +14 -1
  16. package/ios/AppleDiagnostics/LBRNAppleDiagnosticsModule.h +4 -0
  17. package/ios/AppleDiagnostics/LBRNAppleDiagnosticsModule.mm +56 -0
  18. package/ios/AppleDiagnostics/LBRNAppleNativeDiagnostics.swift +293 -0
  19. package/ios/GeneratedAppleDiagnostics/LogBrew/AutomaticTelemetryContext.swift +72 -0
  20. package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngine.swift +270 -0
  21. package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngineAutomatic.swift +331 -0
  22. package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngineDurable.swift +148 -0
  23. package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngineQueue.swift +343 -0
  24. package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryLifecycle.swift +70 -0
  25. package/ios/GeneratedAppleDiagnostics/LogBrew/DurableDeliveryStore.swift +258 -0
  26. package/ios/GeneratedAppleDiagnostics/LogBrew/DurableDeliveryStoreRecovery.swift +330 -0
  27. package/ios/GeneratedAppleDiagnostics/LogBrew/EventEncoding.swift +114 -0
  28. package/ios/GeneratedAppleDiagnostics/LogBrew/IssueDiagnostics.swift +385 -0
  29. package/ios/GeneratedAppleDiagnostics/LogBrew/LifecycleTrace.swift +138 -0
  30. package/ios/GeneratedAppleDiagnostics/LogBrew/LogBrewClient.swift +358 -0
  31. package/ios/GeneratedAppleDiagnostics/LogBrew/LogBrewLogger.swift +262 -0
  32. package/ios/GeneratedAppleDiagnostics/LogBrew/LogBrewTrace.swift +357 -0
  33. package/ios/GeneratedAppleDiagnostics/LogBrew/Metadata.swift +86 -0
  34. package/ios/GeneratedAppleDiagnostics/LogBrew/NativeStackFrame.swift +27 -0
  35. package/ios/GeneratedAppleDiagnostics/LogBrew/ProductTimeline.swift +228 -0
  36. package/ios/GeneratedAppleDiagnostics/LogBrew/PublicTypes.swift +334 -0
  37. package/ios/GeneratedAppleDiagnostics/LogBrew/TelemetryContext.swift +197 -0
  38. package/ios/GeneratedAppleDiagnostics/LogBrew/TelemetryContextValidation.swift +337 -0
  39. package/ios/GeneratedAppleDiagnostics/LogBrew/TraceEvidence.swift +79 -0
  40. package/ios/GeneratedAppleDiagnostics/LogBrew/Transport.swift +204 -0
  41. package/ios/GeneratedAppleDiagnostics/LogBrew/URLSessionTrace.swift +277 -0
  42. package/ios/GeneratedAppleDiagnostics/LogBrew/URLSessionTracer.swift +151 -0
  43. package/ios/GeneratedAppleDiagnostics/LogBrew/Validation.swift +165 -0
  44. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/CrashEngine.swift +125 -0
  45. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/CrashReportSanitizer.swift +139 -0
  46. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/CrashStorageDirectory.swift +124 -0
  47. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeArtifactIdentity.swift +137 -0
  48. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeCrashCapture.swift +229 -0
  49. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeCrashPublic.swift +386 -0
  50. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeCrashReplay.swift +317 -0
  51. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangIncidentStore.swift +321 -0
  52. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangWatchdog.swift +386 -0
  53. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangWatchdogContracts.swift +84 -0
  54. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangWatchdogSystem.swift +139 -0
  55. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeMainThreadStackCapture.swift +84 -0
  56. package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeStackFrameSanitizer.swift +170 -0
  57. package/ios/GeneratedAppleDiagnostics/SOURCE-MANIFEST.json +43 -0
  58. package/package.json +43 -5
  59. package/promise-rejections.cjs +3 -1
  60. package/scripts/sync-apple-native-sources.mjs +93 -0
  61. package/src/NativeLogBrewAppleDiagnostics.ts +12 -0
@@ -0,0 +1,170 @@
1
+ // Generated by scripts/sync-apple-native-sources.mjs.
2
+ // Edit the canonical Swift source, then regenerate this package boundary.
3
+ import CoreFoundation
4
+ import Foundation
5
+
6
+ struct NativeStackFrameSanitizer {
7
+ private static let maxFrames = 32
8
+ private static let cpuTypeArm64: Int32 = 0x0100_000C
9
+ private static let cpuTypeX8664: Int32 = 0x0100_0007
10
+ private static let cpuSubtypeMask: UInt32 = 0x00FF_FFFF
11
+
12
+ func frames(from rawReport: [String: Any]) -> [NativeStackFrame]? {
13
+ guard let crash = rawReport["crash"] as? [String: Any],
14
+ let threads = crash["threads"] as? [Any]
15
+ else {
16
+ return nil
17
+ }
18
+ let crashedThreads = threads.compactMap { value -> [String: Any]? in
19
+ guard let thread = value as? [String: Any], strictBool(thread["crashed"]) == true else {
20
+ return nil
21
+ }
22
+ return thread
23
+ }
24
+ guard crashedThreads.count == 1,
25
+ let backtrace = crashedThreads[0]["backtrace"] as? [String: Any],
26
+ let rawFrames = backtrace["contents"] as? [Any],
27
+ let rawImages = rawReport["binary_images"] as? [Any]
28
+ else {
29
+ return nil
30
+ }
31
+
32
+ let images = rawImages.compactMap(parseImage)
33
+ return mapFrames(rawFrames, to: images)
34
+ }
35
+
36
+ private func mapFrames(_ rawFrames: [Any], to images: [BinaryImage]) -> [NativeStackFrame]? {
37
+ let identityCounts = Dictionary(
38
+ images.map { ($0.identity, 1) },
39
+ uniquingKeysWith: +,
40
+ )
41
+
42
+ var result: [NativeStackFrame] = []
43
+ result.reserveCapacity(min(rawFrames.count, Self.maxFrames))
44
+ for rawFrame in rawFrames {
45
+ guard let frame = rawFrame as? [String: Any],
46
+ let instructionAddress = unsignedInteger(frame["instruction_addr"])
47
+ else {
48
+ continue
49
+ }
50
+ let matchingImages = images.filter { $0.contains(instructionAddress) }
51
+ guard matchingImages.count <= 1 else {
52
+ return nil
53
+ }
54
+ guard let image = matchingImages.first else {
55
+ continue
56
+ }
57
+ guard identityCounts[image.identity] == 1 else {
58
+ return nil
59
+ }
60
+ guard result.count < Self.maxFrames else {
61
+ continue
62
+ }
63
+ result.append(
64
+ NativeStackFrame(
65
+ imageUuid: image.uuid,
66
+ architecture: image.architecture,
67
+ instructionOffset: String(format: "%016llx", instructionAddress - image.start),
68
+ ),
69
+ )
70
+ }
71
+ return result.isEmpty ? nil : result
72
+ }
73
+
74
+ private func parseImage(_ value: Any) -> BinaryImage? {
75
+ guard let image = value as? [String: Any],
76
+ let start = unsignedInteger(image["image_addr"]),
77
+ let size = unsignedInteger(image["image_size"]),
78
+ size > 0,
79
+ let rawUUID = image["uuid"] as? String,
80
+ let uuid = UUID(uuidString: rawUUID)?.uuidString.lowercased(),
81
+ let cpuType = signedInt32(image["cpu_type"]),
82
+ let cpuSubtype = signedInt32(image["cpu_subtype"]),
83
+ let architecture = architecture(cpuType: cpuType, cpuSubtype: cpuSubtype)
84
+ else {
85
+ return nil
86
+ }
87
+ let (end, overflow) = start.addingReportingOverflow(size)
88
+ guard !overflow else {
89
+ return nil
90
+ }
91
+ return BinaryImage(start: start, end: end, uuid: uuid, architecture: architecture)
92
+ }
93
+
94
+ private func architecture(cpuType: Int32, cpuSubtype: Int32) -> NativeStackArchitecture? {
95
+ let subtype = UInt32(bitPattern: cpuSubtype) & Self.cpuSubtypeMask
96
+ switch (cpuType, subtype) {
97
+ case (Self.cpuTypeArm64, 0), (Self.cpuTypeArm64, 1):
98
+ return .arm64
99
+ case (Self.cpuTypeArm64, 2):
100
+ return .arm64e
101
+ case (Self.cpuTypeX8664, 3):
102
+ return .x8664
103
+ default:
104
+ return nil
105
+ }
106
+ }
107
+
108
+ private func strictBool(_ value: Any?) -> Bool? {
109
+ guard let number = value as? NSNumber,
110
+ CFGetTypeID(number) == CFBooleanGetTypeID()
111
+ else {
112
+ return nil
113
+ }
114
+ return number.boolValue
115
+ }
116
+
117
+ private func unsignedInteger(_ value: Any?) -> UInt64? {
118
+ guard let number = integralNumber(value) else {
119
+ return nil
120
+ }
121
+ switch String(cString: number.objCType) {
122
+ case "C", "S", "I", "L", "Q":
123
+ return number.uint64Value
124
+ default:
125
+ let signed = number.int64Value
126
+ return signed < 0 ? nil : UInt64(signed)
127
+ }
128
+ }
129
+
130
+ private func signedInt32(_ value: Any?) -> Int32? {
131
+ guard let number = integralNumber(value) else {
132
+ return nil
133
+ }
134
+ return Int32(exactly: number.int64Value)
135
+ }
136
+
137
+ private func integralNumber(_ value: Any?) -> NSNumber? {
138
+ guard let number = value as? NSNumber,
139
+ CFGetTypeID(number) != CFBooleanGetTypeID()
140
+ else {
141
+ return nil
142
+ }
143
+ switch String(cString: number.objCType) {
144
+ case "c", "C", "s", "S", "i", "I", "l", "L", "q", "Q":
145
+ return number
146
+ default:
147
+ return nil
148
+ }
149
+ }
150
+ }
151
+
152
+ private struct BinaryImage {
153
+ let start: UInt64
154
+ let end: UInt64
155
+ let uuid: String
156
+ let architecture: NativeStackArchitecture
157
+
158
+ var identity: ImageIdentity {
159
+ ImageIdentity(uuid: uuid, architecture: architecture)
160
+ }
161
+
162
+ func contains(_ address: UInt64) -> Bool {
163
+ address >= start && address < end
164
+ }
165
+ }
166
+
167
+ private struct ImageIdentity: Hashable {
168
+ let uuid: String
169
+ let architecture: NativeStackArchitecture
170
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "sources": {
4
+ "swift/logbrew-swift/Sources/LogBrew/AutomaticTelemetryContext.swift": "76ab7f8a7c79db1d54ba13da8d61d96af62c509116b7df0f9d220d5c88364c00",
5
+ "swift/logbrew-swift/Sources/LogBrew/DeliveryEngine.swift": "f98ef86db1a5e5144cd9ab30df325a3602823167c784a22a63904a593725e814",
6
+ "swift/logbrew-swift/Sources/LogBrew/DeliveryEngineAutomatic.swift": "5ca25a8dc626d33c2b9fa85242acc4715c736024324008897deac906212b65ae",
7
+ "swift/logbrew-swift/Sources/LogBrew/DeliveryEngineDurable.swift": "b0d2ca07cce7fe01fc110238c7d10aa9c8ada0d28509e4c022e7fa950a4c79b9",
8
+ "swift/logbrew-swift/Sources/LogBrew/DeliveryEngineQueue.swift": "9c8503da4023368922b8b73dd989213685a64312806ecd73d0513958ad85f883",
9
+ "swift/logbrew-swift/Sources/LogBrew/DeliveryLifecycle.swift": "7b76541c2659cecf6614d9d6dcf9b61dc85b7a562d44fda03a026076afa02fcd",
10
+ "swift/logbrew-swift/Sources/LogBrew/DurableDeliveryStore.swift": "2de6a08473722ebd99b2d1762ed3356fefc0181f5cd886367fbfd52c75c6644b",
11
+ "swift/logbrew-swift/Sources/LogBrew/DurableDeliveryStoreRecovery.swift": "a843f784e7645f916bb0f401e88fa7d49fa8c4351dc2f26c1fbf32be3f4aaa40",
12
+ "swift/logbrew-swift/Sources/LogBrew/EventEncoding.swift": "b88b6b2d17f7d0cee9ac1a1f34ef35b192cd33d213ef3c9e1c2d21cbcc304a97",
13
+ "swift/logbrew-swift/Sources/LogBrew/IssueDiagnostics.swift": "797e6e25f203930e85f827bf211b58c73e6b10938b9f0943f2fe6f6757186ba9",
14
+ "swift/logbrew-swift/Sources/LogBrew/LifecycleTrace.swift": "738cd3f129fac821a892404d1d42ee92bd806b6583d3dbb5379e88b14ab23c16",
15
+ "swift/logbrew-swift/Sources/LogBrew/LogBrewClient.swift": "2e6dd7c9ef07f181a2798c36a820338e3f81369b1b9c7b85c5c3b6f44103732c",
16
+ "swift/logbrew-swift/Sources/LogBrew/LogBrewLogger.swift": "d3266353a5f5139a2a1ca1a86bacce793518eb1489bf67ed9e3720b57b1c29b2",
17
+ "swift/logbrew-swift/Sources/LogBrew/LogBrewTrace.swift": "f67edf4ca464e6a6eb1c7a22cd4997928cd27b6c2d07535855a18a053d8de924",
18
+ "swift/logbrew-swift/Sources/LogBrew/Metadata.swift": "65840ebb3f3b79fbfc1f5faa3026c2583319e89ff26061676dc552c03ee15dbe",
19
+ "swift/logbrew-swift/Sources/LogBrew/NativeStackFrame.swift": "ecbd418969ec4a31503d9916a8bf27f22e6863356c6fabe457c1e61027a8d805",
20
+ "swift/logbrew-swift/Sources/LogBrew/ProductTimeline.swift": "209906aa0e8f096a347e35832840522710eadfb530053253cd73c748518e362d",
21
+ "swift/logbrew-swift/Sources/LogBrew/PublicTypes.swift": "d64de009cd9f8f43fc059cd8fefc2a282c781ba8543be2f56cb48cb757dbe924",
22
+ "swift/logbrew-swift/Sources/LogBrew/TelemetryContext.swift": "ce3ac93a62a345f8c9a8f4c69ce84efc991bf02a688f49bad5e68edcff2f6e08",
23
+ "swift/logbrew-swift/Sources/LogBrew/TelemetryContextValidation.swift": "f631beef20a8a86f975787b4092a9798fedbe2c9e3f0d2740f81831b4adef287",
24
+ "swift/logbrew-swift/Sources/LogBrew/TraceEvidence.swift": "40aaa42976164c53d9f4d9e9e30d236534238da43bbe90832a673c8809ad54b6",
25
+ "swift/logbrew-swift/Sources/LogBrew/Transport.swift": "73eec81aaebec4bc922b2a372429c88fcd3e85606a7862cd08e1795eb2a8e6cd",
26
+ "swift/logbrew-swift/Sources/LogBrew/URLSessionTrace.swift": "d0076c72671716c41bd7498d0509e453b8182c418156e169196fee9f26fc66b1",
27
+ "swift/logbrew-swift/Sources/LogBrew/URLSessionTracer.swift": "0cdf08f92d6111c0dc2883b87837b81f69b5c2f9a8e5501780a114c23a741af7",
28
+ "swift/logbrew-swift/Sources/LogBrew/Validation.swift": "5551ee5237cbdf1c9ed4ee93025f95313e4dd84f31ce7cb774d1dc01175213c7",
29
+ "swift/logbrew-swift/Sources/LogBrewCrash/CrashEngine.swift": "7a46035fcaa72dd7504b4e274a92070d73dd1c45fe20e008474340d6d7c44ede",
30
+ "swift/logbrew-swift/Sources/LogBrewCrash/CrashReportSanitizer.swift": "a872ad63532999e74af1e9685a9382d0e02b93c6f9b942b371d47f56f8b961c0",
31
+ "swift/logbrew-swift/Sources/LogBrewCrash/CrashStorageDirectory.swift": "7cd566703cbf704dc99155451ee93dcace12c35c805abc09a6dcf23975cf43f9",
32
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeArtifactIdentity.swift": "3d785ad717dcf7302451531c18b5e1183983270a6cd78dd543a407e3facc6ae0",
33
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeCrashCapture.swift": "e9ab5f1850a096f40592a025d16c5ffa2fdff0222004a37056898cf1cb4b0dd9",
34
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeCrashPublic.swift": "ee209aa25b1c6bcadf84604f145fc55c251c8697e745c87283703dbdd5bbf5ba",
35
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeCrashReplay.swift": "3eb3d93b32cf14de416f56fa30d6d65e6f268b5ec9d1a67081d7525c4efd4f80",
36
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeHangIncidentStore.swift": "02413ca7e003917faadcc9aa612b5d98897c75b39f67c3c845948dd9349a9d8f",
37
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeHangWatchdog.swift": "37b25904cd6576e20c40500be2c153156403b57ad7b4186a1b6b35b414145ecb",
38
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeHangWatchdogContracts.swift": "59f51554d86c326122bb2bdce47c5a7e01996bd61f2b371eba23855032487b9f",
39
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeHangWatchdogSystem.swift": "b87e3db246691d5b0719898cdc02ba068836647b1ac9339a73cf866eabe235ae",
40
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeMainThreadStackCapture.swift": "66f4a53faabf1cc0d65983689e86bc2a9334649b8bb9726a8104822c988693db",
41
+ "swift/logbrew-swift/Sources/LogBrewCrash/NativeStackFrameSanitizer.swift": "31570c08f182f709ef898ece15dcdc7624b5d8f77e6fb7db3f94d4f14d93585f"
42
+ }
43
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@logbrew/react-native",
3
- "version": "0.1.11",
4
- "description": "React Native offline delivery, screen, error, trace, action, and network timeline helpers for LogBrew.",
3
+ "version": "0.1.13",
4
+ "description": "React Native offline delivery, Apple native diagnostics, screen, error, trace, action, and network timeline helpers for LogBrew.",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",
7
7
  "module": "./index.js",
@@ -114,6 +114,28 @@
114
114
  "default": "./metro.cjs"
115
115
  },
116
116
  "default": "./metro.js"
117
+ },
118
+ "./apple-native-diagnostics": {
119
+ "react-native": {
120
+ "types": "./apple-native-diagnostics.d.ts",
121
+ "default": "./apple-native-diagnostics.js"
122
+ },
123
+ "import": {
124
+ "types": "./apple-native-diagnostics.d.ts",
125
+ "default": "./apple-native-diagnostics.js"
126
+ },
127
+ "default": "./apple-native-diagnostics.js"
128
+ },
129
+ "./expo": {
130
+ "import": {
131
+ "types": "./expo.d.ts",
132
+ "default": "./expo.js"
133
+ },
134
+ "require": {
135
+ "types": "./expo.d.ts",
136
+ "default": "./expo.cjs"
137
+ },
138
+ "default": "./expo.cjs"
117
139
  }
118
140
  },
119
141
  "files": [
@@ -161,6 +183,11 @@
161
183
  "metro.js",
162
184
  "metro.d.ts",
163
185
  "metro.d.cts",
186
+ "apple-native-diagnostics.js",
187
+ "apple-native-diagnostics.d.ts",
188
+ "expo.cjs",
189
+ "expo.js",
190
+ "expo.d.ts",
164
191
  "LogBrewReactNative.podspec",
165
192
  "android/build.gradle",
166
193
  "android/src/main",
@@ -174,8 +201,11 @@
174
201
  "ios/LBRNPrivateStorage.m",
175
202
  "ios/LBRNEventRecordStore.h",
176
203
  "ios/LBRNEventRecordStore.m",
204
+ "ios/AppleDiagnostics",
205
+ "ios/GeneratedAppleDiagnostics",
177
206
  "react-native.config.js",
178
207
  "src",
208
+ "scripts/sync-apple-native-sources.mjs",
179
209
  "README.md",
180
210
  "examples"
181
211
  ],
@@ -188,7 +218,9 @@
188
218
  "logs",
189
219
  "traces",
190
220
  "events",
191
- "source-maps"
221
+ "source-maps",
222
+ "crash-reporting",
223
+ "app-hangs"
192
224
  ],
193
225
  "sideEffects": false,
194
226
  "codegenConfig": {
@@ -208,11 +240,17 @@
208
240
  "url": "git+https://github.com/LogBrewCo/sdk.git"
209
241
  },
210
242
  "peerDependencies": {
211
- "@logbrew/sdk": "^0.1.5",
243
+ "@logbrew/sdk": "^0.1.7",
244
+ "expo": ">=49",
212
245
  "react": ">=18",
213
246
  "react-native": ">=0.72"
214
247
  },
248
+ "peerDependenciesMeta": {
249
+ "expo": {
250
+ "optional": true
251
+ }
252
+ },
215
253
  "scripts": {
216
- "test": "node --check index.js && node --check index.cjs && node --check index.native.js && node --check apollo.js && node --check apollo.cjs && node --check instrumentation.js && node --check instrumentation.cjs && node --check lifecycle.js && node --check lifecycle.cjs && node --check global-errors.js && node --check global-errors.native.js && node --check global-errors.cjs && node --check promise-rejections.cjs && node --check fatal-replay.cjs && node --check metadata.js && node --check metadata.cjs && node --check native-bridge.js && node --check native-bridge.cjs && node --check resource-fetch.js && node --check resource-fetch.cjs && node --check release-artifacts.js && node --check release-artifacts.cjs && node --check metro.js && node --check metro.cjs && node --check examples/index.mjs && node --check examples/apollo-link-spans.mjs && node --check examples/instrumentation-kit.mjs && node --check examples/lifecycle-spans.mjs && node --check examples/native-bridge-scope.mjs && node --check examples/navigation-resource-spans.mjs && node --check examples/readme-example.mjs && node --check examples/real-user-smoke.mjs && node --check examples/resource-fetch-spans.mjs && node --check examples/trace-correlation.mjs && node --test"
254
+ "test": "node scripts/sync-apple-native-sources.mjs --check && node --check index.js && node --check index.cjs && node --check index.native.js && node --check apple-native-diagnostics.js && node --check expo.js && node --check expo.cjs && node --check apollo.js && node --check apollo.cjs && node --check instrumentation.js && node --check instrumentation.cjs && node --check lifecycle.js && node --check lifecycle.cjs && node --check global-errors.js && node --check global-errors.native.js && node --check global-errors.cjs && node --check promise-rejections.cjs && node --check fatal-replay.cjs && node --check metadata.js && node --check metadata.cjs && node --check native-bridge.js && node --check native-bridge.cjs && node --check resource-fetch.js && node --check resource-fetch.cjs && node --check release-artifacts.js && node --check release-artifacts.cjs && node --check metro.js && node --check metro.cjs && node --check examples/index.mjs && node --check examples/apollo-link-spans.mjs && node --check examples/instrumentation-kit.mjs && node --check examples/lifecycle-spans.mjs && node --check examples/native-bridge-scope.mjs && node --check examples/navigation-resource-spans.mjs && node --check examples/readme-example.mjs && node --check examples/real-user-smoke.mjs && node --check examples/resource-fetch-spans.mjs && node --check examples/trace-correlation.mjs && node --test"
217
255
  }
218
256
  }
@@ -223,7 +223,9 @@ function createEvent(mechanism) {
223
223
  delete error.stack;
224
224
  const event = createReactNativeErrorEvent(error, {
225
225
  id: nextEventId(),
226
- includeStack: false
226
+ handled: false,
227
+ includeStack: false,
228
+ mechanism
227
229
  });
228
230
  return {
229
231
  ...event,
@@ -0,0 +1,93 @@
1
+ import assert from "node:assert/strict";
2
+ import crypto from "node:crypto";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
8
+ const packageRoot = path.resolve(scriptDirectory, "..");
9
+ const repositoryRoot = path.resolve(packageRoot, "../..");
10
+ const generatedRoot = path.join(packageRoot, "ios", "GeneratedAppleDiagnostics");
11
+ const sourceRoot = path.join(repositoryRoot, "swift", "logbrew-swift", "Sources");
12
+ const sourceModules = ["LogBrew", "LogBrewCrash"];
13
+ const generatedHeader = [
14
+ "// Generated by scripts/sync-apple-native-sources.mjs.",
15
+ "// Edit the canonical Swift source, then regenerate this package boundary.",
16
+ ""
17
+ ].join("\n");
18
+ const mode = process.argv[2] ?? "--check";
19
+
20
+ assert.ok(
21
+ generatedRoot.startsWith(`${packageRoot}${path.sep}`)
22
+ && path.basename(generatedRoot) === "GeneratedAppleDiagnostics",
23
+ "refusing to operate outside the package-generated source directory"
24
+ );
25
+
26
+ const expected = expectedFiles();
27
+ if (mode === "--write") {
28
+ fs.rmSync(generatedRoot, { force: true, recursive: true });
29
+ for (const [relativePath, contents] of expected) {
30
+ const destination = path.join(generatedRoot, relativePath);
31
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
32
+ fs.writeFileSync(destination, contents, "utf8");
33
+ }
34
+ process.stdout.write(`generated ${expected.size} Apple diagnostics source files\n`);
35
+ } else if (mode === "--check") {
36
+ const actualPaths = listFiles(generatedRoot).map((filePath) =>
37
+ path.relative(generatedRoot, filePath)
38
+ );
39
+ assert.deepEqual(actualPaths, [...expected.keys()]);
40
+ for (const [relativePath, contents] of expected) {
41
+ assert.equal(
42
+ fs.readFileSync(path.join(generatedRoot, relativePath), "utf8"),
43
+ contents,
44
+ `${relativePath} is stale; run the source sync with --write`
45
+ );
46
+ }
47
+ process.stdout.write(`verified ${expected.size} Apple diagnostics source files\n`);
48
+ } else {
49
+ throw new Error("usage: sync-apple-native-sources.mjs [--check|--write]");
50
+ }
51
+
52
+ function expectedFiles() {
53
+ const files = new Map();
54
+ const manifest = {};
55
+ for (const moduleName of sourceModules) {
56
+ const moduleRoot = path.join(sourceRoot, moduleName);
57
+ for (const sourcePath of listFiles(moduleRoot).filter((filePath) => filePath.endsWith(".swift"))) {
58
+ const moduleRelativePath = path.relative(moduleRoot, sourcePath);
59
+ const relativePath = path.join(moduleName, moduleRelativePath);
60
+ const canonical = fs.readFileSync(sourcePath, "utf8");
61
+ const transformed = transformCanonicalSource(canonical);
62
+ const contents = `${generatedHeader}${transformed}`;
63
+ files.set(relativePath, contents);
64
+ manifest[path.join("swift", "logbrew-swift", "Sources", relativePath)] =
65
+ crypto.createHash("sha256").update(canonical).digest("hex");
66
+ }
67
+ }
68
+ files.set(
69
+ "SOURCE-MANIFEST.json",
70
+ `${JSON.stringify({ schemaVersion: 1, sources: manifest }, null, 2)}\n`
71
+ );
72
+ return new Map([...files].sort(([left], [right]) => left.localeCompare(right)));
73
+ }
74
+
75
+ function transformCanonicalSource(canonical) {
76
+ return canonical
77
+ .replaceAll("@_spi(CrashReplay) import LogBrew\n", "")
78
+ .replaceAll("@objc(LBW", "@objc(LBRNApple")
79
+ .replaceAll("@preconcurrency import KSCrashRecording\n", "@preconcurrency import KSCrash\n")
80
+ .replaceAll("@preconcurrency import KSCrashRecordingCore\n", "@preconcurrency import KSCrash\n");
81
+ }
82
+
83
+ function listFiles(root) {
84
+ if (!fs.existsSync(root)) {
85
+ return [];
86
+ }
87
+ return fs.readdirSync(root, { withFileTypes: true })
88
+ .flatMap((entry) => {
89
+ const entryPath = path.join(root, entry.name);
90
+ return entry.isDirectory() ? listFiles(entryPath) : [entryPath];
91
+ })
92
+ .sort();
93
+ }
@@ -0,0 +1,12 @@
1
+ import type { CodegenTypes, TurboModule } from "react-native";
2
+ import { TurboModuleRegistry } from "react-native";
3
+
4
+ export interface Spec extends TurboModule {
5
+ installNativeDiagnostics(
6
+ configuration: CodegenTypes.UnsafeObject
7
+ ): CodegenTypes.UnsafeObject;
8
+ replayNativeDiagnostics(): Promise<CodegenTypes.UnsafeObject>;
9
+ nativeDiagnosticsStatus(): CodegenTypes.UnsafeObject;
10
+ }
11
+
12
+ export default TurboModuleRegistry.get<Spec>("LogBrewAppleDiagnostics");