@allstak/react-native 0.1.3 → 0.3.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/AllStakRN.podspec +25 -0
- package/README.md +393 -64
- package/app.plugin.js +6 -0
- package/build-hooks/allstak-sourcemaps.gradle +132 -0
- package/build-hooks/eas-post-bundle.js +127 -0
- package/build-hooks/upload-sourcemaps.js +175 -0
- package/build-hooks/xcode-build-phase.sh +90 -0
- package/dist/build/sourcemaps.d.mts +94 -0
- package/dist/build/sourcemaps.d.ts +94 -0
- package/dist/build/sourcemaps.js +142 -0
- package/dist/build/sourcemaps.js.map +1 -0
- package/dist/build/sourcemaps.mjs +115 -0
- package/dist/build/sourcemaps.mjs.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +11 -0
- package/dist/chunk-BJTO5JO5.mjs.map +1 -0
- package/dist/expo-plugin.d.mts +56 -0
- package/dist/expo-plugin.d.ts +56 -0
- package/dist/expo-plugin.js +44 -0
- package/dist/expo-plugin.js.map +1 -0
- package/dist/expo-plugin.mjs +25 -0
- package/dist/expo-plugin.mjs.map +1 -0
- package/dist/index.d.mts +873 -1
- package/dist/index.d.ts +873 -1
- package/dist/index.js +2159 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2150 -2
- package/dist/index.mjs.map +1 -1
- package/native/android/build.gradle +41 -0
- package/native/android/src/main/AndroidManifest.xml +2 -0
- package/native/android/src/main/java/io/allstak/rn/AllStakRNModule.java +17 -0
- package/native/android/src/main/java/io/allstak/rn/AllStakRNPackage.java +36 -0
- package/native/ios/AllStakRN.podspec +21 -0
- package/native/ios/AllStakRNModule.m +16 -0
- package/package.json +24 -9
- package/react-native.config.js +28 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
# Root-level podspec — modern @react-native-community/cli auto-discovers
|
|
4
|
+
# the iOS native module by scanning the package root for `*.podspec`. This
|
|
5
|
+
# file simply re-exports the real spec under native/ios/.
|
|
6
|
+
|
|
7
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
8
|
+
|
|
9
|
+
Pod::Spec.new do |s|
|
|
10
|
+
s.name = "AllStakRN"
|
|
11
|
+
s.version = package["version"]
|
|
12
|
+
s.summary = "AllStak React Native — native iOS crash capture"
|
|
13
|
+
s.description = "Captures uncaught NSExceptions on iOS, persists them across launches, and exposes drainPendingCrash() to the JS layer."
|
|
14
|
+
s.homepage = package["homepage"]
|
|
15
|
+
s.license = "MIT"
|
|
16
|
+
s.authors = { "AllStak" => "hello@allstak.io" }
|
|
17
|
+
s.platforms = { :ios => "12.0" }
|
|
18
|
+
s.source = { :git => package["repository"]["url"], :tag => "v#{s.version}" }
|
|
19
|
+
|
|
20
|
+
# Source files live under native/ios/ to keep the package layout clean.
|
|
21
|
+
s.source_files = "native/ios/*.{h,m,mm}"
|
|
22
|
+
s.requires_arc = true
|
|
23
|
+
|
|
24
|
+
s.dependency "React-Core"
|
|
25
|
+
end
|
package/README.md
CHANGED
|
@@ -1,118 +1,447 @@
|
|
|
1
1
|
# @allstak/react-native
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AllStak's React Native SDK captures JS errors, render errors, unhandled promises, logs, HTTP breadcrumbs/events, navigation breadcrumbs, device tags, and source maps from React Native apps.
|
|
4
|
+
|
|
5
|
+
Use one wrapper, keep privacy-first defaults, support Hermes, and upload React Native source maps through build hooks instead of manual release chores.
|
|
4
6
|
|
|
5
7
|
[](https://www.npmjs.com/package/@allstak/react-native)
|
|
6
8
|
[](https://github.com/allstak-io/allstak-react-native/actions)
|
|
7
9
|
[](https://opensource.org/licenses/MIT)
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## 1. Overview
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Use `@allstak/react-native` when you want production mobile error context without wiring several separate tools: a provider-first setup, automatic JS/runtime capture, privacy-safe breadcrumbs, Hermes-aware tags, and source-map upload through EAS, Gradle, Xcode, or custom CI build hooks.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## 2. Installation
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install @allstak/react-native
|
|
19
|
+
```
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
Peer expectations:
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- Works with RN 0.70+
|
|
23
|
+
| Peer | Supported |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| React | `>=16.8.0` |
|
|
26
|
+
| React Native | `>=0.70` |
|
|
27
|
+
| Expo | Supported in Expo apps. Expo Go can use the JS SDK paths; native crash capture requires native modules in a dev client or native build. |
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
The published package is standalone: no browser DOM, Node runtime, or `@allstak/js` dependency is required.
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
## 3. Quick Start — Provider-first
|
|
29
32
|
|
|
30
|
-
-
|
|
31
|
-
- **Native crashes** — iOS (Obj-C/Swift) and Android (Java/Kotlin) fatals
|
|
32
|
-
- **Logs** — structured logs with search and filters
|
|
33
|
-
- **HTTP** — outbound request timing, status codes, failed calls
|
|
34
|
-
- **Device tags** — `Platform.OS`, `Platform.Version`, release channel
|
|
35
|
-
- **Alerts** — email and webhook notifications on regressions
|
|
33
|
+
Provider-first setup is the recommended path.
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
```tsx
|
|
36
|
+
import { AllStakProvider } from "@allstak/react-native";
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
export default function App() {
|
|
39
|
+
return (
|
|
40
|
+
<AllStakProvider
|
|
41
|
+
apiKey="ask_live_..."
|
|
42
|
+
environment="production"
|
|
43
|
+
release="mobile@1.0.0+1"
|
|
44
|
+
dist="ios-hermes"
|
|
45
|
+
debug
|
|
46
|
+
>
|
|
47
|
+
<AppRoot />
|
|
48
|
+
</AllStakProvider>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
41
51
|
```
|
|
42
52
|
|
|
43
|
-
|
|
53
|
+
`AllStakProvider` automatically:
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
- initializes the SDK
|
|
56
|
+
- installs React Native integrations
|
|
57
|
+
- wraps children with an error boundary
|
|
58
|
+
- captures render errors
|
|
59
|
+
- captures global JS errors through `ErrorUtils`
|
|
60
|
+
- captures unhandled promise rejections, including Hermes-native promise rejections
|
|
61
|
+
- attaches platform, device, architecture, Hermes, release, dist, and environment tags
|
|
62
|
+
- installs console, HTTP, XHR, fetch, and AppState breadcrumbs according to config
|
|
63
|
+
- attempts navigation auto-instrumentation when possible
|
|
64
|
+
|
|
65
|
+
Navigation note: Metro/React Native static bundling currently prevents the SDK from guaranteeing automatic React Navigation patching in normal native Metro builds. The provider logs the status when `debug` is enabled. Use `instrumentReactNavigation(navigationRef)` when you need guaranteed navigation breadcrumbs.
|
|
66
|
+
|
|
67
|
+
## 4. Verify It Works
|
|
68
|
+
|
|
69
|
+
Add a temporary test button or run these snippets after the provider has mounted:
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { AllStak } from "@allstak/react-native";
|
|
73
|
+
|
|
74
|
+
AllStak.captureException(new Error("AllStak test error"));
|
|
75
|
+
AllStak.captureMessage("AllStak test log");
|
|
76
|
+
console.warn("AllStak warning breadcrumb");
|
|
77
|
+
Promise.reject(new Error("AllStak unhandled rejection test"));
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Expected result:
|
|
81
|
+
|
|
82
|
+
- with `debug`, Metro shows `[AllStak] Initialized — session <id>`
|
|
83
|
+
- the manual error appears in the AllStak dashboard
|
|
84
|
+
- the message appears as a log event
|
|
85
|
+
- the warning is attached as a breadcrumb to the next captured error
|
|
86
|
+
- the unhandled rejection is captured with `metadata.source = "unhandledRejection"`
|
|
87
|
+
|
|
88
|
+
## 5. Automatic Capture Matrix
|
|
89
|
+
|
|
90
|
+
| Feature | Default | Config | Status | Notes |
|
|
91
|
+
| --- | --- | --- | --- | --- |
|
|
92
|
+
| Render errors | On with provider | `fallback`, `onError`; manual setup skips the boundary | Verified on iOS simulator | Captured with `metadata.source = "AllStakProvider.ErrorBoundary"` and component stack. |
|
|
93
|
+
| Global JS errors | On | `autoErrorHandler` | Verified on iOS simulator; unit-tested elsewhere | Uses `ErrorUtils.setGlobalHandler`. |
|
|
94
|
+
| Unhandled promises | On | `autoPromiseRejections` | Verified on iOS simulator | Uses Hermes rejection tracker plus polyfill/browser fallbacks. |
|
|
95
|
+
| Manual `captureException` | Manual | `AllStak.captureException(error)` | Verified on iOS simulator and backend contract tests | Posts to `/ingest/v1/errors`. |
|
|
96
|
+
| Manual `captureMessage` | Manual | `AllStak.captureMessage(message, level?)` | Verified on iOS simulator and backend contract tests | Info/warn go to logs; error/fatal also create error events. |
|
|
97
|
+
| `console.warn` / `console.error` | On | `autoConsoleBreadcrumbs`, `captureConsole` | Verified on iOS simulator | Breadcrumbs only; original console methods still run. |
|
|
98
|
+
| `console.log` / `console.info` | Off | `captureConsole={{ log: true, info: true }}` | Verified on iOS simulator | Opt-in only to avoid noisy dashboards. |
|
|
99
|
+
| Fetch breadcrumbs | On | `autoFetchBreadcrumbs` | Verified on iOS simulator | Query strings are stripped from breadcrumb URLs. |
|
|
100
|
+
| XHR breadcrumbs | On | `autoNetworkCapture` | Unit-tested; RN fetch is XHR-based in many setups | Skips AllStak ingest host to avoid recursion. |
|
|
101
|
+
| HTTP 4xx/5xx | On for breadcrumbs | `autoFetchBreadcrumbs`, `autoNetworkCapture` | Verified on iOS simulator | Error-level breadcrumb for status `>=400`. |
|
|
102
|
+
| Network failures | On for breadcrumbs | `autoFetchBreadcrumbs`, `autoNetworkCapture` | Verified on iOS simulator | Records failed request breadcrumb and rethrows original error. |
|
|
103
|
+
| Full HTTP request events | Off | `enableHttpTracking`, `httpTracking` | Verified on iOS simulator | Posts to `/ingest/v1/http_requests`; headers/bodies off by default. |
|
|
104
|
+
| AppState breadcrumbs | On | `autoAppStateBreadcrumbs` | Listener verified; OS transitions not fully scripted | Foreground/background transition testing is environment-dependent. |
|
|
105
|
+
| Navigation breadcrumbs | Best effort automatic, manual fallback guaranteed | `autoNavigationBreadcrumbs`, `instrumentReactNavigation(ref)` | Manual path verified on iOS simulator; auto path unit-tested under Node; Metro native auto-patch intentionally falls back | Use manual ref instrumentation for guaranteed React Navigation breadcrumbs. |
|
|
106
|
+
| Device/platform tags | On | `autoDeviceTags` | Verified on iOS simulator | Adds `device.os`, `device.osVersion`, `device.model` where available. |
|
|
107
|
+
| Hermes detection | On | automatic | Verified on iOS simulator | Adds `rn.hermes` and selects `ios-hermes` / `android-hermes` dist when possible. |
|
|
108
|
+
| Release/dist/environment tags | Environment defaults to `production`; release is caller-supplied; dist auto-detected unless overridden | `environment`, `release`, `dist` | Verified on iOS simulator | `release` and `dist` must match uploaded source maps for symbolication. |
|
|
109
|
+
| Native iOS crashes | Manual drain API; native module must be linked | `drainPendingNativeCrashes(release?)` | Verified on iOS simulator | Crash is stored by native handler and sent on next launch. Provider does not call this automatically. |
|
|
110
|
+
| Native Android crashes | Manual drain API; native module must be linked | `drainPendingNativeCrashes(release?)` | Implemented, not emulator/device verified | Android native module and dev crash trigger exist; emulator verification was blocked by disk in latest report. |
|
|
111
|
+
| Offline queue | On, in-memory only | transport internal | Backend-contract verified | Buffered retry works while process lives; events are lost after app restart. |
|
|
112
|
+
| Source maps | Build-time hook | EAS, Gradle, Xcode, or custom CI hooks | Build hooks implemented; backend upload path exists | Hooks inject `debugId` and upload maps. End-to-end Hermes symbolication still depends on matching release/dist/debugId. |
|
|
113
|
+
|
|
114
|
+
## 6. Configuration Reference
|
|
115
|
+
|
|
116
|
+
`AllStakProvider` accepts the SDK config and React Native integration flags:
|
|
117
|
+
|
|
118
|
+
| Prop | Type | Default | Notes |
|
|
119
|
+
| --- | --- | --- | --- |
|
|
120
|
+
| `apiKey` | `string` | required | Runtime project API key such as `ask_live_...`. Not the source-map upload token. |
|
|
121
|
+
| `environment` | `string` | `"production"` | Attached to errors, logs, spans, and HTTP events. |
|
|
122
|
+
| `release` | `string` | unset | App release, for example `mobile@1.2.3+45`. Required for source-map matching. |
|
|
123
|
+
| `dist` | `string` | auto-detected | Override build flavor, for example `android-hermes`. |
|
|
124
|
+
| `debug` | `boolean` | `false` | Prints SDK init and selected integration status logs. |
|
|
125
|
+
| `fallback` | `ReactNode` or function | `null` on render error | Error boundary fallback UI. |
|
|
126
|
+
| `onError` | function | unset | Called after render error capture. |
|
|
127
|
+
| `destroyOnUnmount` | `boolean` | `false` | Keep `false` for app roots, Fast Refresh, and Strict Mode. |
|
|
128
|
+
| `captureConsole` | object | `{ warn: true, error: true, log: false, info: false }` | Per-method console breadcrumb flags. |
|
|
129
|
+
| `autoConsoleBreadcrumbs` | `boolean` | `true` | Kill switch for console wrapping. |
|
|
130
|
+
| `autoFetchBreadcrumbs` | `boolean` | `true` | Wraps `fetch` for HTTP breadcrumbs. |
|
|
131
|
+
| `autoNetworkCapture` | `boolean` | `true` | Wraps `XMLHttpRequest` for network breadcrumbs. |
|
|
132
|
+
| `enableHttpTracking` | `boolean` | `false` | Enables full HTTP request events. |
|
|
133
|
+
| `httpTracking` | `HttpTrackingOptions` | privacy-first defaults | Controls body/header capture, redaction, ignore lists, and byte limits. |
|
|
134
|
+
| `autoAppStateBreadcrumbs` | `boolean` | `true` | Captures AppState changes as breadcrumbs. |
|
|
135
|
+
| `autoDeviceTags` | `boolean` | `true` | Captures platform/device tags. |
|
|
136
|
+
| `autoNavigationBreadcrumbs` | `boolean` | `true` | Best-effort auto navigation patch; manual fallback is recommended for Metro-native builds. |
|
|
137
|
+
|
|
138
|
+
Common optional props also supported by the underlying client include `host`, `user`, `tags`, `sampleRate`, `beforeSend`, `tracesSampleRate`, `service`, and `replay`.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<AllStakProvider
|
|
142
|
+
apiKey="ask_live_..."
|
|
143
|
+
environment="production"
|
|
144
|
+
release="mobile@1.2.3+45"
|
|
145
|
+
dist="android-hermes"
|
|
146
|
+
captureConsole={{ log: true, info: true }}
|
|
147
|
+
enableHttpTracking
|
|
148
|
+
>
|
|
149
|
+
<AppRoot />
|
|
150
|
+
</AllStakProvider>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
HTTP tracking defaults are intentionally conservative. Request bodies, response bodies, and headers are not captured unless explicitly enabled. Sensitive headers and query parameters are still redacted even when header/body capture is enabled.
|
|
154
|
+
|
|
155
|
+
## 7. Manual / Advanced API
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import {
|
|
159
|
+
AllStak,
|
|
160
|
+
instrumentReactNavigation,
|
|
161
|
+
drainPendingNativeCrashes,
|
|
162
|
+
} from "@allstak/react-native";
|
|
163
|
+
|
|
164
|
+
AllStak.captureException(error);
|
|
165
|
+
AllStak.captureMessage("message");
|
|
166
|
+
AllStak.addBreadcrumb("ui", "Tapped checkout", "info", { screen: "Checkout" });
|
|
167
|
+
AllStak.setUser({ id: "user_123", email: "user@example.com" });
|
|
168
|
+
AllStak.setTag("key", "value");
|
|
169
|
+
AllStak.setContext("device", { model: "simulator" });
|
|
170
|
+
await AllStak.flush();
|
|
171
|
+
AllStak.destroy();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Other advanced APIs include `setTags`, `setExtra`, `setExtras`, `setLevel`, `setFingerprint`, `withScope`, tracing helpers, `getReplay`, and manual `instrumentAxios`.
|
|
175
|
+
|
|
176
|
+
Manual setup is available when you need full initialization control:
|
|
46
177
|
|
|
47
178
|
```ts
|
|
48
|
-
import {
|
|
179
|
+
import { AllStak, installReactNative } from "@allstak/react-native";
|
|
49
180
|
|
|
50
|
-
|
|
51
|
-
apiKey:
|
|
52
|
-
environment:
|
|
53
|
-
release:
|
|
181
|
+
AllStak.init({
|
|
182
|
+
apiKey: "ask_live_...",
|
|
183
|
+
environment: "production",
|
|
184
|
+
release: "mobile@1.2.3+45",
|
|
54
185
|
});
|
|
55
186
|
|
|
56
|
-
|
|
187
|
+
installReactNative();
|
|
57
188
|
```
|
|
58
189
|
|
|
59
|
-
|
|
190
|
+
Manual navigation fallback:
|
|
60
191
|
|
|
61
|
-
|
|
192
|
+
```tsx
|
|
193
|
+
import { NavigationContainer, useNavigationContainerRef } from "@react-navigation/native";
|
|
194
|
+
import { instrumentReactNavigation } from "@allstak/react-native";
|
|
62
195
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
3. Copy your API key from **Project Settings → API Keys**
|
|
66
|
-
4. Export it as `ALLSTAK_API_KEY` or pass it to `installReactNative(...)`
|
|
196
|
+
export function AppNavigation() {
|
|
197
|
+
const navigationRef = useNavigationContainerRef();
|
|
67
198
|
|
|
68
|
-
|
|
199
|
+
return (
|
|
200
|
+
<NavigationContainer
|
|
201
|
+
ref={navigationRef}
|
|
202
|
+
onReady={() => instrumentReactNavigation(navigationRef)}
|
|
203
|
+
>
|
|
204
|
+
{/* navigators */}
|
|
205
|
+
</NavigationContainer>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
69
209
|
|
|
70
|
-
|
|
71
|
-
|---|---|---|---|---|
|
|
72
|
-
| `apiKey` | `string` | yes | — | Project API key (`ask_live_…`) |
|
|
73
|
-
| `environment` | `string` | no | — | Deployment env |
|
|
74
|
-
| `release` | `string` | no | — | App version |
|
|
75
|
-
| `host` | `string` | no | `https://api.allstak.sa` | Ingest host override |
|
|
76
|
-
| `user` | `{ id?, email? }` | no | — | Default user context |
|
|
77
|
-
| `tags` | `Record<string,string>` | no | — | Default tags |
|
|
210
|
+
Auto navigation works only where the SDK can safely patch `@react-navigation/native`. In normal Metro-native builds, manual ref instrumentation is the guaranteed path.
|
|
78
211
|
|
|
79
|
-
##
|
|
212
|
+
## 8. Source Maps — automatic via build hooks
|
|
80
213
|
|
|
81
|
-
|
|
214
|
+
React Native source maps become hands-off after adding one build hook for your build system. The hook injects a `debugId` into both the JS bundle and source map, then uploads the map to AllStak.
|
|
82
215
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
216
|
+
### EAS / Expo
|
|
217
|
+
|
|
218
|
+
Add the EAS post-build hook:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"scripts": {
|
|
223
|
+
"eas-build-on-success": "node ./node_modules/@allstak/react-native/build-hooks/eas-post-bundle.js"
|
|
224
|
+
}
|
|
88
225
|
}
|
|
89
226
|
```
|
|
90
227
|
|
|
91
|
-
|
|
228
|
+
Required environment:
|
|
92
229
|
|
|
93
|
-
|
|
94
|
-
|
|
230
|
+
- `ALLSTAK_UPLOAD_TOKEN`
|
|
231
|
+
- `ALLSTAK_RELEASE`
|
|
232
|
+
- `ALLSTAK_API_URL` optional, defaults to AllStak production API
|
|
233
|
+
|
|
234
|
+
`ALLSTAK_UPLOAD_TOKEN` is a project-scoped upload token from Project Settings. It is not the runtime `apiKey`.
|
|
235
|
+
|
|
236
|
+
### Android Gradle
|
|
237
|
+
|
|
238
|
+
Add this to `android/app/build.gradle` after the React Native Gradle plugin setup:
|
|
239
|
+
|
|
240
|
+
```groovy
|
|
241
|
+
apply from: "../../node_modules/@allstak/react-native/build-hooks/allstak-sourcemaps.gradle"
|
|
95
242
|
```
|
|
96
243
|
|
|
97
|
-
|
|
244
|
+
Supported Gradle properties / environment:
|
|
98
245
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
246
|
+
- `ALLSTAK_UPLOAD_TOKEN` or `allstakUploadToken`
|
|
247
|
+
- `ALLSTAK_RELEASE` or `allstakRelease`
|
|
248
|
+
- optional API URL override when self-hosting
|
|
249
|
+
|
|
250
|
+
Then run your normal release task, for example:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
cd android
|
|
254
|
+
./gradlew :app:bundleRelease
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### iOS Xcode Build Phase
|
|
258
|
+
|
|
259
|
+
Add a Run Script build phase after "Bundle React Native code and images":
|
|
260
|
+
|
|
261
|
+
```sh
|
|
262
|
+
"${SRCROOT}/../node_modules/@allstak/react-native/build-hooks/xcode-build-phase.sh"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Set these in the build phase, `.xcconfig`, or CI shell:
|
|
266
|
+
|
|
267
|
+
```sh
|
|
268
|
+
ALLSTAK_UPLOAD_TOKEN=aspk_...
|
|
269
|
+
ALLSTAK_RELEASE=mobile@1.2.3+45
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The script is designed for release builds; debug builds should not upload source maps.
|
|
273
|
+
|
|
274
|
+
### Custom CI
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
node ./node_modules/@allstak/react-native/build-hooks/upload-sourcemaps.js \
|
|
278
|
+
--platform ios \
|
|
279
|
+
--bundle path/to/main.jsbundle \
|
|
280
|
+
--sourcemap path/to/main.jsbundle.map \
|
|
281
|
+
--release mobile@1.2.3+45 \
|
|
282
|
+
--dist ios-hermes
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Programmatic API:
|
|
286
|
+
|
|
287
|
+
```js
|
|
288
|
+
const { uploadReactNativeSourcemap } = require("@allstak/react-native/sourcemaps");
|
|
289
|
+
|
|
290
|
+
await uploadReactNativeSourcemap({
|
|
291
|
+
platform: "ios",
|
|
292
|
+
bundle: "path/to/main.jsbundle",
|
|
293
|
+
sourcemap: "path/to/main.jsbundle.map",
|
|
294
|
+
release: "mobile@1.2.3+45",
|
|
295
|
+
dist: "ios-hermes",
|
|
296
|
+
token: process.env.ALLSTAK_UPLOAD_TOKEN,
|
|
297
|
+
});
|
|
102
298
|
```
|
|
103
299
|
|
|
104
|
-
|
|
300
|
+
How matching works:
|
|
301
|
+
|
|
302
|
+
- `debugId` is injected into the bundle and the source map.
|
|
303
|
+
- The backend matches stack frames using `debugId`, `release`, and `dist`.
|
|
304
|
+
- Maps are uploaded to `/api/v1/artifacts/upload`.
|
|
305
|
+
- Upload auth uses `X-AllStak-Upload-Token`; do not use the runtime `ask_live_...` API key.
|
|
105
306
|
|
|
106
|
-
|
|
307
|
+
If no upload token is present, the hook can run in inject-only mode so CI can still produce bundles with debug IDs without uploading artifacts.
|
|
308
|
+
|
|
309
|
+
## 9. Native Crashes
|
|
310
|
+
|
|
311
|
+
JS errors are verified. Native crash files exist for iOS and Android, and the SDK exports a drain API:
|
|
107
312
|
|
|
108
313
|
```ts
|
|
109
|
-
|
|
314
|
+
import { drainPendingNativeCrashes } from "@allstak/react-native";
|
|
315
|
+
|
|
316
|
+
await drainPendingNativeCrashes("mobile@1.2.3+45");
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The provider does not call `drainPendingNativeCrashes()` automatically. Call it once early after SDK initialization, before user flows start:
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
import { AllStakProvider, drainPendingNativeCrashes } from "@allstak/react-native";
|
|
323
|
+
import { useEffect } from "react";
|
|
324
|
+
|
|
325
|
+
function AppRoot() {
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
drainPendingNativeCrashes("mobile@1.2.3+45");
|
|
328
|
+
}, []);
|
|
329
|
+
|
|
330
|
+
return <Routes />;
|
|
331
|
+
}
|
|
110
332
|
```
|
|
111
333
|
|
|
334
|
+
Current verification status:
|
|
335
|
+
|
|
336
|
+
- iOS native crash capture and drain were verified end-to-end on an iOS simulator.
|
|
337
|
+
- Android native crash capture code exists and has parity with iOS, but emulator/device verification was not completed in the latest report.
|
|
338
|
+
- Do not mark Android native crash capture production-ready until an Android emulator or device run proves crash -> relaunch -> drain -> backend ingest.
|
|
339
|
+
|
|
340
|
+
Native modules are not available in Expo Go. Use a dev client or native build for native crash verification.
|
|
341
|
+
|
|
342
|
+
## 10. Privacy Defaults
|
|
343
|
+
|
|
344
|
+
- Headers are off by default.
|
|
345
|
+
- Request bodies are off by default.
|
|
346
|
+
- Response bodies are off by default.
|
|
347
|
+
- `Authorization`, `Cookie`, `Set-Cookie`, `X-API-Key`, `X-Auth-Token`, and `Proxy-Authorization` are always redacted.
|
|
348
|
+
- Sensitive query parameters such as `token`, `password`, `api_key`, `authorization`, `secret`, `access_token`, `refresh_token`, and `jwt` are redacted.
|
|
349
|
+
- `console.log` and `console.info` are off by default.
|
|
350
|
+
- `console.warn` and `console.error` are captured as breadcrumbs by default.
|
|
351
|
+
- Source maps containing `sourcesContent` may be rejected when organization privacy mode requires stripped sources. Use `stripSources: true` or configure your build hook accordingly.
|
|
352
|
+
|
|
353
|
+
## 11. Troubleshooting
|
|
354
|
+
|
|
355
|
+
### Events not appearing
|
|
356
|
+
|
|
357
|
+
- Confirm `apiKey` is the runtime project key and starts with `ask_live_...`.
|
|
358
|
+
- Enable `debug` and check for `[AllStak] Initialized — session <id>`.
|
|
359
|
+
- Confirm the app can reach `https://api.allstak.sa`.
|
|
360
|
+
- For self-hosted installs, pass `host="https://your-api.example.com"`.
|
|
361
|
+
- Check the project/environment you are viewing in the dashboard.
|
|
362
|
+
|
|
363
|
+
### Wrong `apiKey`
|
|
364
|
+
|
|
365
|
+
Runtime ingestion uses the project API key. Source-map upload uses `ALLSTAK_UPLOAD_TOKEN`. They are different credentials and are not interchangeable.
|
|
366
|
+
|
|
367
|
+
### Upload token vs runtime API key confusion
|
|
368
|
+
|
|
369
|
+
- `apiKey="ask_live_..."`: ships runtime errors/logs/breadcrumbs.
|
|
370
|
+
- `ALLSTAK_UPLOAD_TOKEN=aspk_...`: uploads source maps and artifacts in CI.
|
|
371
|
+
- Never put the upload token in app code.
|
|
372
|
+
|
|
373
|
+
### Source maps uploaded but stack is not symbolicated
|
|
374
|
+
|
|
375
|
+
- Ensure the runtime `release` matches `ALLSTAK_RELEASE`.
|
|
376
|
+
- Ensure runtime `dist` matches the uploaded map's `dist`.
|
|
377
|
+
- Confirm the event contains a matching `debugId` or release/dist combination.
|
|
378
|
+
- Confirm the map was uploaded to the same project as the runtime API key.
|
|
379
|
+
|
|
380
|
+
### Release/dist mismatch
|
|
381
|
+
|
|
382
|
+
Use stable release names such as `mobile@1.2.3+45` and platform dists such as `ios-hermes`, `android-hermes`, `ios-jsc`, or `android-jsc`. Mismatched values prevent backend joining between event and source map.
|
|
383
|
+
|
|
384
|
+
### Hermes stacks not resolving
|
|
385
|
+
|
|
386
|
+
Hermes stack traces need the correct Metro/Hermes source-map chain. Use the provided build hooks instead of uploading a random map file from an intermediate build step.
|
|
387
|
+
|
|
388
|
+
### Navigation breadcrumbs not appearing
|
|
389
|
+
|
|
390
|
+
- In Metro-native builds, use `instrumentReactNavigation(navigationRef)`.
|
|
391
|
+
- Confirm `NavigationContainer` has mounted and `onReady` fires.
|
|
392
|
+
- Avoid deep imports that bypass `@react-navigation/native`.
|
|
393
|
+
- Enable `debug` to see whether auto navigation instrumentation was applied or skipped.
|
|
394
|
+
|
|
395
|
+
### Metro / Expo issues
|
|
396
|
+
|
|
397
|
+
- Rebuild after adding native modules or source-map hooks.
|
|
398
|
+
- Expo Go cannot load custom native crash modules.
|
|
399
|
+
- For native crash testing, use an Expo dev client, simulator build, or physical device build.
|
|
400
|
+
|
|
401
|
+
### Android Gradle hook not running
|
|
402
|
+
|
|
403
|
+
- Confirm the `apply from` path is relative to `android/app/build.gradle`.
|
|
404
|
+
- Confirm `ALLSTAK_RELEASE` and `ALLSTAK_UPLOAD_TOKEN` are visible to Gradle.
|
|
405
|
+
- Run with `--info` to verify the AllStak source-map task executes.
|
|
406
|
+
|
|
407
|
+
### Xcode build phase path wrong
|
|
408
|
+
|
|
409
|
+
- The recommended path is `"${SRCROOT}/../node_modules/@allstak/react-native/build-hooks/xcode-build-phase.sh"`.
|
|
410
|
+
- Place the phase after React Native bundles JS.
|
|
411
|
+
- Confirm the script has executable permissions after install.
|
|
412
|
+
|
|
413
|
+
### AppState breadcrumbs not easy to test
|
|
414
|
+
|
|
415
|
+
The listener registers at startup, but actual foreground/background transitions depend on simulator/device behavior. Verify by backgrounding and foregrounding the app, then capturing an error so breadcrumbs attach.
|
|
416
|
+
|
|
417
|
+
### Docker/backend local issue is not an SDK issue
|
|
418
|
+
|
|
419
|
+
If local backend testing returns `401 INVALID_API_KEY` or nothing reaches ClickHouse, verify the API key exists in the same database used by the running backend. The latest backend verification report found that using the wrong local Postgres instance caused false SDK failures.
|
|
420
|
+
|
|
421
|
+
## 12. Verification Status
|
|
422
|
+
|
|
423
|
+
Latest verification reports are in `docs/reports/`:
|
|
424
|
+
|
|
425
|
+
- `react-native-provider-verification.md`
|
|
426
|
+
- `react-native-backend-ingestion-verification.md`
|
|
427
|
+
- `react-native-production-readiness.md`
|
|
428
|
+
- `console-and-navigation-auto.md`
|
|
429
|
+
|
|
430
|
+
Current status from those reports:
|
|
431
|
+
|
|
432
|
+
| Area | Status |
|
|
433
|
+
| --- | --- |
|
|
434
|
+
| Unit tests | Latest production-readiness report: 132 passing total, including 126 unit tests and 6 live backend-contract tests. Earlier provider report recorded 98/98 before later additions. |
|
|
435
|
+
| iOS simulator verified paths | Provider init, render errors, global JS errors, unhandled promises, manual exception/message, console warn/error defaults, console log/info opt-in behavior, fetch breadcrumbs, HTTP 4xx/5xx/network failure, full HTTP request events, device/platform/Hermes/dist tags, manual React Navigation breadcrumbs, iOS native crash drain. |
|
|
436
|
+
| Android emulator verified paths | Not completed in latest production-readiness pass; emulator boot was blocked by disk. Android native crash and JS paths remain implemented but not device-verified. |
|
|
437
|
+
| Backend ingestion verified paths | `/ingest/v1/errors`, `/ingest/v1/logs`, `/ingest/v1/http_requests`; 8 canonical curl payload shapes accepted; live SDK events landed in ClickHouse; backend-contract tests cover buffering and invalid-key resilience. |
|
|
438
|
+
| Source-map backend status | `/api/v1/artifacts/upload` upload path exists and build hooks inject/upload debug-ID source maps. Full Hermes symbolication remains dependent on matching release/dist/debugId and should be validated per app release pipeline. |
|
|
439
|
+
| Remaining gaps | Android device/emulator verification, persistent offline queue, full AppState transition verification, and per-project source-map symbolication verification in release CI. |
|
|
440
|
+
|
|
112
441
|
## Links
|
|
113
442
|
|
|
114
|
-
- Documentation: https://docs.allstak.sa
|
|
115
443
|
- Dashboard: https://app.allstak.sa
|
|
444
|
+
- Documentation: https://docs.allstak.sa
|
|
116
445
|
- Source: https://github.com/allstak-io/allstak-react-native
|
|
117
446
|
|
|
118
447
|
## License
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Expo entrypoint — re-exports the actual plugin from `dist/expo-plugin.js`
|
|
2
|
+
// so consumers can write `"plugins": ["@allstak/react-native"]` in their
|
|
3
|
+
// app.json and Expo's `withPlugins` resolver finds it without an extra
|
|
4
|
+
// import path. Expo looks for `app.plugin.js` at the package root by
|
|
5
|
+
// convention.
|
|
6
|
+
module.exports = require('./dist/expo-plugin.js');
|