@fixprompt/react-native 0.0.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/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # @fixprompt/react-native
2
+
3
+ React Native SDK for the [FixPrompt](https://github.com/Geos-LLC/FixPrompt) broker. Captures uncaught JS errors, unhandled promise rejections, and tagged `console.error` / `console.warn` output. Buffers events when offline; drains on the next successful send.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install github:Geos-LLC/FixPrompt#path:react-native-sdk \
9
+ @react-native-async-storage/async-storage
10
+ ```
11
+
12
+ Optional but recommended for stable per-device IDs:
13
+
14
+ ```bash
15
+ npx expo install expo-secure-store
16
+ ```
17
+
18
+ ## Wire it up
19
+
20
+ ```ts
21
+ // App.tsx — call once before any render
22
+ import { initFixPrompt } from '@fixprompt/react-native';
23
+
24
+ initFixPrompt({
25
+ projectKey: process.env.EXPO_PUBLIC_FIXPROMPT_KEY!,
26
+ source: process.env.EXPO_PUBLIC_FIXPROMPT_SOURCE!,
27
+ service: 'my-app',
28
+ app: 'my-app',
29
+ env: __DEV__ ? 'dev' : 'prod',
30
+
31
+ // Optional — empty list (the default) captures every console.error;
32
+ // pass regex prefixes to only capture intentional tagged lines.
33
+ captureTags: [/^\[CRM\b/, /^\[Analytics\b/],
34
+ });
35
+ ```
36
+
37
+ ## Public API
38
+
39
+ ```ts
40
+ // Manual error report — call from a try/catch
41
+ captureException(err, { attrs: { extra: 'context' } });
42
+
43
+ // Attach user context to every subsequent event
44
+ setUser({ id: userId, email });
45
+ setUser(null); // clear on logout
46
+ ```
47
+
48
+ ## Native crash forwarding (optional)
49
+
50
+ The SDK only sees the JS bridge. If a native module deref crashes the app
51
+ (common: native-side TurboModule null pointer), wire up
52
+ `react-native-exception-handler`:
53
+
54
+ ```bash
55
+ npm install react-native-exception-handler
56
+ ```
57
+
58
+ ```ts
59
+ import { setNativeExceptionHandler } from 'react-native-exception-handler';
60
+ import { captureException } from '@fixprompt/react-native';
61
+
62
+ setNativeExceptionHandler((exceptionString) => {
63
+ // Synchronous — runs once before the app process dies.
64
+ // Best we can do is push to the offline buffer; transport will flush on
65
+ // next app launch via AsyncStorage replay.
66
+ captureException(new Error(exceptionString), {
67
+ attrs: { kind: 'native_crash', fatal: true },
68
+ });
69
+ });
70
+ ```
71
+
72
+ ## Offline buffer
73
+
74
+ When the broker is unreachable (network down, 5xx, or 8s timeout), events
75
+ queue in an in-memory ring buffer of 200, persisted to `AsyncStorage` key
76
+ `@fixprompt/buffer`. On the next successful send the whole queue drains in
77
+ order. Events older than 7 days are dropped. 4xx responses are dropped
78
+ immediately (those are bugs on our side, not transient failures).
79
+
80
+ ## Auto-attached attrs
81
+
82
+ Every event ships with:
83
+
84
+ | attr | source |
85
+ |------|--------|
86
+ | `sdk`, `sdk_version` | this package |
87
+ | `platform` | `Platform.OS` (ios / android / web / ...) |
88
+ | `os_version` | `Platform.Version` |
89
+ | `rn_version` | `Platform.constants.reactNativeVersion` |
90
+ | `release` | passed to `initFixPrompt({ release })` or `null` |
91
+ | `session_id` | uuid per cold start, in-memory |
92
+ | `device_id` | uuid per device, persisted (SecureStore → AsyncStorage) |
93
+ | `user_id`, `user_email` | last `setUser({...})` call |
94
+
95
+ The broker promotes `sdk` + `sdk_version` into `project_sdk_installations`, so the dashboard's support copy ("you're on RN SDK 0.0.1") lights up automatically.
96
+
97
+ ## Tag-based capture (advanced)
98
+
99
+ The `captureTags` option mirrors the pattern from the original ProofPix `errorLogger.js`. When set, only `console.error` / `console.warn` lines whose first argument matches one of the regexes get forwarded:
100
+
101
+ ```ts
102
+ initFixPrompt({
103
+ // ...
104
+ captureTags: [
105
+ /^\[Auth\b/,
106
+ /^\[Sync\b/,
107
+ /^\[CRM\b/,
108
+ ],
109
+ });
110
+
111
+ console.error('[Auth] refresh token expired'); // → broker
112
+ console.error('plain message, untagged'); // → original console only
113
+ ```
114
+
115
+ Leave `captureTags` unset to capture every console.error (broader, noisier).
116
+
117
+ ## License
118
+
119
+ UNLICENSED (closed beta).
@@ -0,0 +1,9 @@
1
+ declare const AsyncStorage: {
2
+ getItem(key: string): Promise<string | null>;
3
+ setItem(key: string, value: string): Promise<void>;
4
+ removeItem(key: string): Promise<void>;
5
+ clear(): Promise<void>;
6
+ /** Tests only. */
7
+ __reset(): void;
8
+ };
9
+ export default AsyncStorage;
@@ -0,0 +1,11 @@
1
+ export declare const Platform: {
2
+ OS: string;
3
+ Version: string;
4
+ constants: {
5
+ reactNativeVersion: {
6
+ major: number;
7
+ minor: number;
8
+ patch: number;
9
+ };
10
+ };
11
+ };
@@ -0,0 +1,23 @@
1
+ import type { EventPayload } from './types';
2
+ /**
3
+ * In-memory ring buffer with AsyncStorage persistence.
4
+ *
5
+ * Events accumulate when the broker is unreachable (network error / 5xx /
6
+ * timeout). On the next successful send, the whole buffer drains in order.
7
+ * On cold start, any persisted buffer from a prior crash is replayed.
8
+ */
9
+ declare class OfflineBuffer {
10
+ private items;
11
+ private loaded;
12
+ private persistTimer;
13
+ /** Load the persisted buffer once, on first use. */
14
+ load(): Promise<void>;
15
+ push(payload: EventPayload): void;
16
+ drain(): Promise<EventPayload[]>;
17
+ size(): number;
18
+ private schedulePersist;
19
+ /** Tests only. */
20
+ _resetForTests(): void;
21
+ }
22
+ export declare const offlineBuffer: OfflineBuffer;
23
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { ResolvedConfig } from './types';
2
+ /**
3
+ * Wrap console.error so tagged calls forward to the broker as warning-severity
4
+ * events. The original console.error still runs (so RedBox / Metro logs still
5
+ * show up).
6
+ *
7
+ * Pattern is intentional — ProofPix's existing log lines look like
8
+ * `console.error('[Analytics] tracking failure', err)`. Devs prefix their
9
+ * intentional captures and the broker only sees tagged ones.
10
+ */
11
+ export declare function patchConsoleError(config: ResolvedConfig): () => void;
12
+ export declare function patchConsoleWarn(config: ResolvedConfig): () => void;
@@ -0,0 +1,7 @@
1
+ export interface DeviceAttrs {
2
+ platform: string;
3
+ os_version: string;
4
+ /** RN runtime version (Hermes / JSC). Used for triage. */
5
+ rn_version?: string;
6
+ }
7
+ export declare function getDeviceAttrs(): DeviceAttrs;
@@ -0,0 +1,7 @@
1
+ import type { ResolvedConfig } from './types';
2
+ export declare function installGlobalErrorHandler(config: ResolvedConfig): () => void;
3
+ /**
4
+ * Hook unhandled-promise-rejection tracking. Uses the bundled
5
+ * `promise/setimmediate/rejection-tracking` module that ships with RN.
6
+ */
7
+ export declare function installRejectionHandler(config: ResolvedConfig): () => void;