rn-backstage 1.2.1 → 1.4.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.
Files changed (99) hide show
  1. package/README.md +109 -2
  2. package/lib/commonjs/Backstage.js +19 -2
  3. package/lib/commonjs/Backstage.js.map +1 -1
  4. package/lib/commonjs/bug-report.js +173 -0
  5. package/lib/commonjs/bug-report.js.map +1 -0
  6. package/lib/commonjs/components/BackstagePanel.js +100 -17
  7. package/lib/commonjs/components/BackstagePanel.js.map +1 -1
  8. package/lib/commonjs/components/BugReportComposer.js +510 -0
  9. package/lib/commonjs/components/BugReportComposer.js.map +1 -0
  10. package/lib/commonjs/components/FlagsTab.js +21 -11
  11. package/lib/commonjs/components/FlagsTab.js.map +1 -1
  12. package/lib/commonjs/components/FloatingPill.js +82 -22
  13. package/lib/commonjs/components/FloatingPill.js.map +1 -1
  14. package/lib/commonjs/components/InfoTab.js +5 -1
  15. package/lib/commonjs/components/InfoTab.js.map +1 -1
  16. package/lib/commonjs/components/LogItem.js +6 -0
  17. package/lib/commonjs/components/LogItem.js.map +1 -1
  18. package/lib/commonjs/components/LogsTab.js +3 -3
  19. package/lib/commonjs/components/LogsTab.js.map +1 -1
  20. package/lib/commonjs/components/NetworkTab.js +3 -2
  21. package/lib/commonjs/components/NetworkTab.js.map +1 -1
  22. package/lib/commonjs/components/StorageTab.js +672 -0
  23. package/lib/commonjs/components/StorageTab.js.map +1 -0
  24. package/lib/commonjs/constants.js +88 -6
  25. package/lib/commonjs/constants.js.map +1 -1
  26. package/lib/commonjs/index.js +84 -0
  27. package/lib/commonjs/index.js.map +1 -1
  28. package/lib/commonjs/types.js +2 -0
  29. package/lib/commonjs/types.js.map +1 -1
  30. package/lib/module/Backstage.js +19 -2
  31. package/lib/module/Backstage.js.map +1 -1
  32. package/lib/module/bug-report.js +164 -0
  33. package/lib/module/bug-report.js.map +1 -0
  34. package/lib/module/components/BackstagePanel.js +101 -18
  35. package/lib/module/components/BackstagePanel.js.map +1 -1
  36. package/lib/module/components/BugReportComposer.js +505 -0
  37. package/lib/module/components/BugReportComposer.js.map +1 -0
  38. package/lib/module/components/FlagsTab.js +23 -13
  39. package/lib/module/components/FlagsTab.js.map +1 -1
  40. package/lib/module/components/FloatingPill.js +86 -26
  41. package/lib/module/components/FloatingPill.js.map +1 -1
  42. package/lib/module/components/InfoTab.js +6 -2
  43. package/lib/module/components/InfoTab.js.map +1 -1
  44. package/lib/module/components/LogItem.js +7 -1
  45. package/lib/module/components/LogItem.js.map +1 -1
  46. package/lib/module/components/LogsTab.js +3 -3
  47. package/lib/module/components/LogsTab.js.map +1 -1
  48. package/lib/module/components/NetworkTab.js +3 -2
  49. package/lib/module/components/NetworkTab.js.map +1 -1
  50. package/lib/module/components/StorageTab.js +667 -0
  51. package/lib/module/components/StorageTab.js.map +1 -0
  52. package/lib/module/constants.js +88 -6
  53. package/lib/module/constants.js.map +1 -1
  54. package/lib/module/index.js +14 -0
  55. package/lib/module/index.js.map +1 -1
  56. package/lib/module/types.js +4 -0
  57. package/lib/module/types.js.map +1 -1
  58. package/lib/typescript/Backstage.d.ts.map +1 -1
  59. package/lib/typescript/bug-report.d.ts +12 -0
  60. package/lib/typescript/bug-report.d.ts.map +1 -0
  61. package/lib/typescript/components/BackstagePanel.d.ts +4 -1
  62. package/lib/typescript/components/BackstagePanel.d.ts.map +1 -1
  63. package/lib/typescript/components/BugReportComposer.d.ts +17 -0
  64. package/lib/typescript/components/BugReportComposer.d.ts.map +1 -0
  65. package/lib/typescript/components/FlagsTab.d.ts.map +1 -1
  66. package/lib/typescript/components/FloatingPill.d.ts +2 -0
  67. package/lib/typescript/components/FloatingPill.d.ts.map +1 -1
  68. package/lib/typescript/components/InfoTab.d.ts.map +1 -1
  69. package/lib/typescript/components/LogItem.d.ts.map +1 -1
  70. package/lib/typescript/components/LogsTab.d.ts.map +1 -1
  71. package/lib/typescript/components/NetworkTab.d.ts.map +1 -1
  72. package/lib/typescript/components/StorageTab.d.ts +9 -0
  73. package/lib/typescript/components/StorageTab.d.ts.map +1 -0
  74. package/lib/typescript/constants.d.ts +74 -4
  75. package/lib/typescript/constants.d.ts.map +1 -1
  76. package/lib/typescript/index.d.ts +13 -1
  77. package/lib/typescript/index.d.ts.map +1 -1
  78. package/lib/typescript/types.d.ts +55 -0
  79. package/lib/typescript/types.d.ts.map +1 -1
  80. package/package.json +7 -6
  81. package/src/Backstage.tsx +0 -209
  82. package/src/ThemeContext.tsx +0 -38
  83. package/src/components/BackstagePanel.tsx +0 -258
  84. package/src/components/FlagsTab.tsx +0 -198
  85. package/src/components/FloatingPill.tsx +0 -153
  86. package/src/components/InfoTab.tsx +0 -230
  87. package/src/components/JsonTreeView.tsx +0 -239
  88. package/src/components/LogItem.tsx +0 -144
  89. package/src/components/LogsTab.tsx +0 -217
  90. package/src/components/NetworkItem.tsx +0 -425
  91. package/src/components/NetworkTab.tsx +0 -240
  92. package/src/components/TabBar.tsx +0 -154
  93. package/src/constants.ts +0 -114
  94. package/src/index.ts +0 -18
  95. package/src/log-interceptor.ts +0 -148
  96. package/src/network-interceptor.ts +0 -468
  97. package/src/types.ts +0 -213
  98. package/src/utils/formatTimestamp.ts +0 -22
  99. package/src/utils/stringify.ts +0 -90
package/README.md CHANGED
@@ -1,18 +1,22 @@
1
1
  # rn-backstage
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/rn-backstage.svg)](https://www.npmjs.com/package/rn-backstage)
4
+ [![npm downloads](https://img.shields.io/npm/dm/rn-backstage.svg)](https://www.npmjs.com/package/rn-backstage)
5
+
3
6
  A zero-dependency developer/QA debug panel for React Native apps. Inspect device info, view state trees, monitor console logs, inspect network requests, and trigger custom actions — all from a sleek in-app panel.
4
7
 
5
8
  ## Features
6
9
 
7
- - 🎯 **Draggable floating pill** — always accessible, repositionable trigger
10
+ - 🎯 **Draggable floating pill** — always accessible, repositionable trigger with safe area bounds
8
11
  - 📱 **Device & build info** — OS version, app version, build number, and custom data
9
12
  - 🌳 **State tree inspector** — visualize Redux, Zustand, or any store state
10
13
  - 📋 **Console log viewer** — intercepts all console methods with search & filtering
11
14
  - 🌐 **Network inspector** — intercepts fetch & XMLHttpRequest with request/response details, headers, body, timing, and copy-as-cURL
12
15
  - 🎚 **Feature flag toggle** — render switches to toggle flags in real-time without restarting
16
+ - 🗄 **Storage viewer** — inspect, edit, and delete AsyncStorage/MMKV entries via a pluggable adapter
13
17
  - ⚡ **Quick actions** — add custom buttons (logout, clear cache, etc.)
14
18
  - 🔌 **Extensible tabs** — add custom tabs for app-specific debugging tools
15
- - 🎨 **Dark glassmorphism UI** — beautiful, professional developer tool aesthetic
19
+ - 🎨 **Light & dark theme** — auto-follows device setting, or override manually
16
20
  - 📦 **Zero dependencies** — only peer deps are `react` and `react-native`
17
21
 
18
22
  ## Installation
@@ -55,6 +59,7 @@ export default function App() {
55
59
  The Network tab automatically intercepts all `fetch()` and `XMLHttpRequest` traffic — including libraries built on top of them like **Axios**, **Apisauce**, **ky**, and **Apollo Client**.
56
60
 
57
61
  Each request shows:
62
+
58
63
  - Method, URL, status code, and duration
59
64
  - Request & response headers
60
65
  - Request & response body (auto-parsed JSON with tree view)
@@ -74,6 +79,7 @@ Each request shows:
74
79
  autoFilterNetworkLogs={true}
75
80
  />
76
81
  ```
82
+
77
83
  ## Feature Flag Toggle
78
84
 
79
85
  Pass feature flags to render a dedicated **Flags** tab with toggle switches. The tab only appears when at least one flag is provided. Toggling calls your callback in real-time — no app restart needed.
@@ -92,6 +98,59 @@ const [flags, setFlags] = useState([
92
98
  />
93
99
  ```
94
100
 
101
+ ## Storage Viewer
102
+
103
+ Pass a `storageAdapter` to render a **Storage** tab that lets you browse, edit, add, and delete key-value entries. The tab only appears when an adapter is provided. Works with any storage backend — zero dependencies.
104
+
105
+ ```tsx
106
+ import AsyncStorage from '@react-native-async-storage/async-storage'
107
+
108
+ ;<Backstage
109
+ storageAdapter={{
110
+ getAllKeys: () => AsyncStorage.getAllKeys(),
111
+ getItem: key => AsyncStorage.getItem(key),
112
+ setItem: (key, value) => AsyncStorage.setItem(key, value),
113
+ removeItem: key => AsyncStorage.removeItem(key),
114
+ }}
115
+ />
116
+ ```
117
+
118
+ MMKV example:
119
+
120
+ ```tsx
121
+ import { storage } from './mmkv'
122
+
123
+ ;<Backstage
124
+ storageAdapter={{
125
+ getAllKeys: () => Promise.resolve(storage.getAllKeys()),
126
+ getItem: key => Promise.resolve(storage.getString(key) ?? null),
127
+ setItem: (key, value) => Promise.resolve(storage.set(key, value)),
128
+ removeItem: key => Promise.resolve(storage.delete(key)),
129
+ }}
130
+ />
131
+ ```
132
+
133
+ ## Bug Report
134
+
135
+ Add a `bugReport` config to enable one-tap bug reporting. Tapping the 🐛 button in the panel header opens a composer that auto-attaches device info, logs, network activity, and state. Reports can be shared via the system share sheet or submitted to a webhook.
136
+
137
+ ```tsx
138
+ <Backstage
139
+ bugReport={{
140
+ onSubmit: report => {
141
+ // Full BugReport object with all context
142
+ console.log(report.title, report.severity, report.logs.length)
143
+ },
144
+ // Optional: POST to a webhook
145
+ webhookUrl: 'https://your-api.com/bugs',
146
+ // Optional: capture screenshot (requires a library like react-native-view-shot)
147
+ captureScreenshot: () => viewShotRef.current.capture(),
148
+ maxLogsInReport: 50,
149
+ maxNetworkEntriesInReport: 20,
150
+ }}
151
+ />
152
+ ```
153
+
95
154
  ## Props
96
155
 
97
156
  | Prop | Type | Default | Description |
@@ -106,6 +165,7 @@ const [flags, setFlags] = useState([
106
165
  | `quickActions` | `QuickAction[]` | `[]` | Custom action buttons |
107
166
  | `featureFlags` | `FeatureFlag[]` | `[]` | Feature flags with toggle switches |
108
167
  | `onToggleFeatureFlag` | `(key, val: boolean) => void` | `undefined` | Callback when a flag is toggled |
168
+ | `storageAdapter` | `StorageAdapter` | `undefined` | Storage adapter for the Storage Viewer tab |
109
169
  | `maxLogs` | `number` | `500` | Maximum logs to retain |
110
170
  | `logFilters` | `string[]` | `[]` | Messages to exclude from logs |
111
171
  | `onCopyLogs` | `(logs: string) => void` | `undefined` | Callback when copying logs |
@@ -115,7 +175,14 @@ const [flags, setFlags] = useState([
115
175
  | `networkFilters` | `string[]` | `[]` | URL substrings to exclude from capture |
116
176
  | `autoFilterNetworkLogs` | `boolean` | `true` | Auto-filter network callback logs from Logs tab |
117
177
  | `jsonMaxDepth` | `number` | `10` | Max nesting depth for all JSON tree views |
178
+ | `initialX` | `number` | `undefined` | Initial X position for the floating pill |
179
+ | `initialY` | `number` | `undefined` | Initial Y position for the floating pill |
180
+ | `pillText` | `string` | `undefined` | Text on the pill (defaults to version or "DEV") |
181
+ | `pillWidth` | `number` | `60` | Width of the floating pill |
182
+ | `pillHeight` | `number` | `32` | Height of the floating pill |
118
183
  | `extraTabs` | `BackstageTab[]` | `[]` | Additional custom tabs |
184
+ | `bugReport` | `BugReportConfig` | `undefined` | Bug report config (shows 🐛 button in header) |
185
+ | `styles` | `BackstageStyleOverrides` | `undefined` | Custom style overrides |
119
186
  | `children` | `ReactNode` | `undefined` | Extra content in InfoTab |
120
187
 
121
188
  ## Ref Methods
@@ -126,6 +193,46 @@ const ref = useRef<BackstageRef>(null)
126
193
  ref.current?.open() // Open the panel
127
194
  ref.current?.close() // Close the panel
128
195
  ref.current?.clearLogs() // Clear all captured logs
196
+ ref.current?.submitBugReport() // Open bug report composer
197
+ ```
198
+
199
+ ## Individual Components
200
+
201
+ All internal components are exported for advanced use cases — compose your own custom debug UI:
202
+
203
+ ```tsx
204
+ import {
205
+ BackstagePanel,
206
+ FloatingPill,
207
+ TabBar,
208
+ InfoTab,
209
+ LogsTab,
210
+ LogItem,
211
+ NetworkTab,
212
+ NetworkItem,
213
+ FlagsTab,
214
+ StorageTab,
215
+ BugReportComposer,
216
+ JsonTreeView, // useful standalone for any JSON data
217
+ } from 'rn-backstage'
218
+ ```
219
+
220
+ ## TestIDs
221
+
222
+ All interactive elements have consistent `testID` attributes for E2E testing. Import the `TestIDs` object to reference them:
223
+
224
+ ```tsx
225
+ import { TestIDs } from 'rn-backstage'
226
+
227
+ // Static IDs
228
+ TestIDs.floatingPill // 'backstage.floating-pill'
229
+ TestIDs.panel // 'backstage.panel'
230
+ TestIDs.header.closeButton // 'backstage.header.close'
231
+
232
+ // Dynamic IDs (for items in lists)
233
+ TestIDs.logItem.container(id) // 'backstage.log-item.{id}'
234
+ TestIDs.flagsTab.flagSwitch(key) // 'backstage.flag.{key}'
235
+ TestIDs.storageTab.entryRow(key) // 'backstage.storage.entry.{key}'
129
236
  ```
130
237
 
131
238
  ## License
@@ -27,6 +27,7 @@ const Backstage = exports.Backstage = /*#__PURE__*/(0, _react.forwardRef)(({
27
27
  quickActions,
28
28
  featureFlags,
29
29
  onToggleFeatureFlag,
30
+ storageAdapter,
30
31
  maxLogs = _constants.DEFAULT_MAX_LOGS,
31
32
  logFilters,
32
33
  onCopyLogs,
@@ -36,12 +37,15 @@ const Backstage = exports.Backstage = /*#__PURE__*/(0, _react.forwardRef)(({
36
37
  initialX,
37
38
  initialY,
38
39
  pillText,
40
+ pillWidth,
41
+ pillHeight,
39
42
  enableNetworkInspector = true,
40
43
  maxNetworkEntries = _constants.DEFAULT_MAX_NETWORK_ENTRIES,
41
44
  maxNetworkBodySize,
42
45
  networkFilters,
43
46
  autoFilterNetworkLogs = true,
44
- jsonMaxDepth
47
+ jsonMaxDepth,
48
+ bugReport: bugReportConfig
45
49
  }, ref) => {
46
50
  const [panelVisible, setPanelVisible] = (0, _react.useState)(false);
47
51
  const [hasError, setHasError] = (0, _react.useState)(false);
@@ -125,10 +129,18 @@ const Backstage = exports.Backstage = /*#__PURE__*/(0, _react.forwardRef)(({
125
129
 
126
130
  // ── Expose ref methods ────────────────────────────────────
127
131
 
132
+ const openBugReportRef = (0, _react.useRef)(null);
128
133
  (0, _react.useImperativeHandle)(ref, () => ({
129
134
  open: openPanel,
130
135
  close: closePanel,
131
- clearLogs
136
+ clearLogs,
137
+ submitBugReport: () => {
138
+ if (bugReportConfig) {
139
+ openPanel();
140
+ // Small delay to let panel mount first
141
+ setTimeout(() => openBugReportRef.current?.(), 100);
142
+ }
143
+ }
132
144
  }));
133
145
 
134
146
  // ── Render ────────────────────────────────────────────────
@@ -146,6 +158,8 @@ const Backstage = exports.Backstage = /*#__PURE__*/(0, _react.forwardRef)(({
146
158
  onPress: openPanel,
147
159
  initialX: initialX,
148
160
  initialY: initialY,
161
+ pillWidth: pillWidth,
162
+ pillHeight: pillHeight,
149
163
  styles: propStyles
150
164
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_BackstagePanel.BackstagePanel, {
151
165
  visible: panelVisible,
@@ -167,6 +181,9 @@ const Backstage = exports.Backstage = /*#__PURE__*/(0, _react.forwardRef)(({
167
181
  onCopyNetwork: onCopyLogs,
168
182
  extraTabs: extraTabs,
169
183
  jsonMaxDepth: jsonMaxDepth,
184
+ storageAdapter: storageAdapter,
185
+ bugReportConfig: bugReportConfig,
186
+ bugReportOpenerRef: openBugReportRef,
170
187
  styles: propStyles,
171
188
  children: children
172
189
  })]
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_constants","_logInterceptor","_networkInterceptor","_FloatingPill","_BackstagePanel","_ThemeContext","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Backstage","exports","forwardRef","visible","theme","themePreference","appVersion","buildNumber","bundleId","deviceInfo","state","quickActions","featureFlags","onToggleFeatureFlag","maxLogs","DEFAULT_MAX_LOGS","logFilters","onCopyLogs","extraTabs","children","styles","propStyles","initialX","initialY","pillText","enableNetworkInspector","maxNetworkEntries","DEFAULT_MAX_NETWORK_ENTRIES","maxNetworkBodySize","networkFilters","autoFilterNetworkLogs","jsonMaxDepth","ref","panelVisible","setPanelVisible","useState","hasError","setHasError","logs","setLogs","networkEntries","setNetworkEntries","logBuffer","useRef","LogBuffer","networkBuffer","NetworkBuffer","openPanel","useCallback","current","getAll","closePanel","clearLogs","clear","refreshLogs","refreshNetwork","clearNetwork","useEffect","handleLogEntry","entry","push","level","installInterceptor","uninstallInterceptor","handleNetworkEntry","upsert","installNetworkInterceptor","filters","maxBodySize","uninstallNetworkInterceptor","useImperativeHandle","open","close","displayText","jsx","BackstageThemeProvider","preference","jsxs","View","style","container","pointerEvents","FloatingPill","text","onPress","BackstagePanel","onClose","onRefreshLogs","onRefreshNetwork","onClearNetwork","onCopyNetwork","displayName","StyleSheet","create","absoluteFillObject","zIndex","elevation"],"sourceRoot":"../../src","sources":["Backstage.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_constants","_logInterceptor","_networkInterceptor","_FloatingPill","_BackstagePanel","_ThemeContext","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Backstage","exports","forwardRef","visible","theme","themePreference","appVersion","buildNumber","bundleId","deviceInfo","state","quickActions","featureFlags","onToggleFeatureFlag","storageAdapter","maxLogs","DEFAULT_MAX_LOGS","logFilters","onCopyLogs","extraTabs","children","styles","propStyles","initialX","initialY","pillText","pillWidth","pillHeight","enableNetworkInspector","maxNetworkEntries","DEFAULT_MAX_NETWORK_ENTRIES","maxNetworkBodySize","networkFilters","autoFilterNetworkLogs","jsonMaxDepth","bugReport","bugReportConfig","ref","panelVisible","setPanelVisible","useState","hasError","setHasError","logs","setLogs","networkEntries","setNetworkEntries","logBuffer","useRef","LogBuffer","networkBuffer","NetworkBuffer","openPanel","useCallback","current","getAll","closePanel","clearLogs","clear","refreshLogs","refreshNetwork","clearNetwork","useEffect","handleLogEntry","entry","push","level","installInterceptor","uninstallInterceptor","handleNetworkEntry","upsert","installNetworkInterceptor","filters","maxBodySize","uninstallNetworkInterceptor","openBugReportRef","useImperativeHandle","open","close","submitBugReport","setTimeout","displayText","jsx","BackstageThemeProvider","preference","jsxs","View","style","container","pointerEvents","FloatingPill","text","onPress","BackstagePanel","onClose","onRefreshLogs","onRefreshNetwork","onClearNetwork","onCopyNetwork","bugReportOpenerRef","displayName","StyleSheet","create","absoluteFillObject","zIndex","elevation"],"sourceRoot":"../../src","sources":["Backstage.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.buildDeviceInfo = buildDeviceInfo;
7
+ exports.composeBugReport = composeBugReport;
8
+ exports.formatDeviceInfoForReport = formatDeviceInfoForReport;
9
+ exports.formatLogsForReport = formatLogsForReport;
10
+ exports.formatNetworkForReport = formatNetworkForReport;
11
+ exports.formatStateForReport = formatStateForReport;
12
+ exports.submitToWebhook = submitToWebhook;
13
+ var _reactNative = require("react-native");
14
+ var _types = require("./types");
15
+ // ─── Report Composition ──────────────────────────────────────────────────────
16
+
17
+ const SEVERITY_LABELS = {
18
+ low: '🟢 Low',
19
+ medium: '🟡 Medium',
20
+ high: '🟠 High',
21
+ critical: '🔴 Critical'
22
+ };
23
+ function formatTimestamp(ts) {
24
+ const d = new Date(ts);
25
+ return d.toISOString().replace('T', ' ').substring(0, 19);
26
+ }
27
+ function formatLogLevel(level) {
28
+ switch (level) {
29
+ case _types.LogLevel.error:
30
+ return '❌ ERROR';
31
+ case _types.LogLevel.warn:
32
+ return '⚠️ WARN';
33
+ case _types.LogLevel.info:
34
+ return 'ℹ️ INFO';
35
+ case _types.LogLevel.debug:
36
+ return '🔍 DEBUG';
37
+ default:
38
+ return '📝 LOG';
39
+ }
40
+ }
41
+ function formatDeviceInfoForReport(items) {
42
+ if (items.length === 0) return '';
43
+ const lines = items.map(i => `- **${i.label}**: ${i.value}`);
44
+ return `## 📱 Device Info\n\n${lines.join('\n')}\n`;
45
+ }
46
+ function formatLogsForReport(logs) {
47
+ if (logs.length === 0) return '';
48
+ const lines = logs.map(l => `\`${formatTimestamp(l.timestamp)}\` ${formatLogLevel(l.level)} ${l.message}`);
49
+ return `## 📋 Console Logs (${logs.length})\n\n\`\`\`\n${lines.join('\n')}\n\`\`\`\n`;
50
+ }
51
+ function formatNetworkForReport(entries) {
52
+ if (entries.length === 0) return '';
53
+ const lines = entries.map(e => {
54
+ const status = e.status ?? '⏳';
55
+ const duration = e.duration ? `${e.duration}ms` : '...';
56
+ return `- \`${e.method}\` ${e.url} → ${status} (${duration})`;
57
+ });
58
+ return `## 🌐 Network Activity (${entries.length})\n\n${lines.join('\n')}\n`;
59
+ }
60
+ function formatStateForReport(state) {
61
+ try {
62
+ const json = JSON.stringify(state, null, 2);
63
+ // Truncate if too large
64
+ const truncated = json.length > 5000 ? json.substring(0, 5000) + '\n... (truncated)' : json;
65
+ return `## 🌳 State Snapshot\n\n\`\`\`json\n${truncated}\n\`\`\`\n`;
66
+ } catch {
67
+ return `## 🌳 State Snapshot\n\n\`[Could not serialize state]\`\n`;
68
+ }
69
+ }
70
+ function composeBugReport(report) {
71
+ const sections = [];
72
+ sections.push(`# 🐛 Bug Report: ${report.title}\n`);
73
+ sections.push(`**Severity**: ${SEVERITY_LABELS[report.severity]}`);
74
+ sections.push(`**Reported**: ${formatTimestamp(report.timestamp)}`);
75
+ sections.push(`**Platform**: ${_reactNative.Platform.OS} ${_reactNative.Platform.Version}\n`);
76
+ if (report.description) {
77
+ sections.push(`## Description\n\n${report.description}\n`);
78
+ }
79
+ if (report.deviceInfo.length > 0) {
80
+ sections.push(formatDeviceInfoForReport(report.deviceInfo));
81
+ }
82
+ if (report.logs.length > 0) {
83
+ sections.push(formatLogsForReport(report.logs));
84
+ }
85
+ if (report.networkEntries.length > 0) {
86
+ sections.push(formatNetworkForReport(report.networkEntries));
87
+ }
88
+ if (report.state && Object.keys(report.state).length > 0) {
89
+ sections.push(formatStateForReport(report.state));
90
+ }
91
+ if (report.screenshotUri) {
92
+ sections.push(`## 📸 Screenshot\n\nAttached: ${report.screenshotUri}\n`);
93
+ }
94
+ sections.push('---\n*Generated by rn-backstage*');
95
+ return sections.join('\n');
96
+ }
97
+
98
+ // ─── Webhook Submission ──────────────────────────────────────────────────────
99
+
100
+ async function submitToWebhook(webhookUrl, report) {
101
+ try {
102
+ const body = {
103
+ title: report.title,
104
+ description: report.description,
105
+ severity: report.severity,
106
+ platform: _reactNative.Platform.OS,
107
+ platformVersion: String(_reactNative.Platform.Version),
108
+ timestamp: report.timestamp,
109
+ deviceInfo: report.deviceInfo,
110
+ logs: report.logs.map(l => ({
111
+ level: l.level,
112
+ message: l.message,
113
+ timestamp: l.timestamp
114
+ })),
115
+ networkEntries: report.networkEntries.map(e => ({
116
+ method: e.method,
117
+ url: e.url,
118
+ status: e.status,
119
+ duration: e.duration
120
+ }))
121
+ };
122
+ if (report.state) {
123
+ body.state = report.state;
124
+ }
125
+ if (report.screenshotUri) {
126
+ body.screenshotUri = report.screenshotUri;
127
+ }
128
+ const response = await fetch(webhookUrl, {
129
+ method: 'POST',
130
+ headers: {
131
+ 'Content-Type': 'application/json'
132
+ },
133
+ body: JSON.stringify(body)
134
+ });
135
+ if (!response.ok) {
136
+ return {
137
+ success: false,
138
+ error: `HTTP ${response.status}`
139
+ };
140
+ }
141
+ return {
142
+ success: true
143
+ };
144
+ } catch (err) {
145
+ return {
146
+ success: false,
147
+ error: err instanceof Error ? err.message : 'Unknown error'
148
+ };
149
+ }
150
+ }
151
+
152
+ // ─── Device Info Builder ─────────────────────────────────────────────────────
153
+
154
+ function buildDeviceInfo(appVersion, buildNumber, bundleId, extraInfo = []) {
155
+ const info = [{
156
+ label: 'Platform',
157
+ value: `${_reactNative.Platform.OS} ${_reactNative.Platform.Version}`
158
+ }];
159
+ if (appVersion) info.push({
160
+ label: 'App Version',
161
+ value: appVersion
162
+ });
163
+ if (buildNumber) info.push({
164
+ label: 'Build Number',
165
+ value: buildNumber
166
+ });
167
+ if (bundleId) info.push({
168
+ label: 'Bundle ID',
169
+ value: bundleId
170
+ });
171
+ return [...info, ...extraInfo];
172
+ }
173
+ //# sourceMappingURL=bug-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","_types","SEVERITY_LABELS","low","medium","high","critical","formatTimestamp","ts","d","Date","toISOString","replace","substring","formatLogLevel","level","LogLevel","error","warn","info","debug","formatDeviceInfoForReport","items","length","lines","map","i","label","value","join","formatLogsForReport","logs","l","timestamp","message","formatNetworkForReport","entries","e","status","duration","method","url","formatStateForReport","state","json","JSON","stringify","truncated","composeBugReport","report","sections","push","title","severity","Platform","OS","Version","description","deviceInfo","networkEntries","Object","keys","screenshotUri","submitToWebhook","webhookUrl","body","platform","platformVersion","String","response","fetch","headers","ok","success","err","Error","buildDeviceInfo","appVersion","buildNumber","bundleId","extraInfo"],"sourceRoot":"../../src","sources":["bug-report.ts"],"mappings":"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","ignoreList":[]}
@@ -13,6 +13,8 @@ var _InfoTab = require("./InfoTab");
13
13
  var _LogsTab = require("./LogsTab");
14
14
  var _NetworkTab = require("./NetworkTab");
15
15
  var _FlagsTab = require("./FlagsTab");
16
+ var _StorageTab = require("./StorageTab");
17
+ var _BugReportComposer = require("./BugReportComposer");
16
18
  var _jsxRuntime = require("react/jsx-runtime");
17
19
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
18
20
  // ─── Types ───────────────────────────────────────────────────────────────────
@@ -33,6 +35,11 @@ const FLAGS_TAB = {
33
35
  title: 'Flags',
34
36
  icon: '🎚'
35
37
  };
38
+ const STORAGE_TAB = {
39
+ key: 'storage',
40
+ title: 'Storage',
41
+ icon: '🗄'
42
+ };
36
43
  const LOGS_TAB = {
37
44
  key: 'logs',
38
45
  title: 'Logs',
@@ -61,16 +68,37 @@ const BackstagePanel = ({
61
68
  onCopyNetwork,
62
69
  extraTabs = [],
63
70
  jsonMaxDepth,
71
+ storageAdapter,
72
+ bugReportConfig,
73
+ bugReportOpenerRef,
64
74
  styles: propStyles,
65
75
  children
66
76
  }) => {
67
77
  const [activeTab, setActiveTab] = (0, _react.useState)('info');
78
+ const [bugReportVisible, setBugReportVisible] = (0, _react.useState)(false);
68
79
  const theme = (0, _ThemeContext.useBackstageTheme)();
69
80
  const styles = (0, _react.useMemo)(() => createStyles(theme), [theme]);
70
81
 
82
+ // Reset to Info tab when panel closes so indicator and content stay in sync
83
+ (0, _react.useEffect)(() => {
84
+ if (!visible) {
85
+ setActiveTab('info');
86
+ }
87
+ }, [visible]);
88
+
89
+ // Register opener callback for the parent ref
90
+ (0, _react.useEffect)(() => {
91
+ if (!bugReportOpenerRef) return;
92
+ bugReportOpenerRef.current = () => setBugReportVisible(true);
93
+ return () => {
94
+ bugReportOpenerRef.current = null;
95
+ };
96
+ }, [bugReportOpenerRef]);
97
+
71
98
  // Compose all tabs: built-in (conditionally including Flags) + extra
72
99
  const hasFlags = featureFlags && featureFlags.length > 0;
73
- const allTabs = [...ALWAYS_ON_TABS, ...(hasFlags ? [FLAGS_TAB] : []), LOGS_TAB, ...extraTabs.map(t => ({
100
+ const hasStorage = !!storageAdapter;
101
+ const allTabs = [...ALWAYS_ON_TABS, ...(hasFlags ? [FLAGS_TAB] : []), ...(hasStorage ? [STORAGE_TAB] : []), LOGS_TAB, ...extraTabs.map(t => ({
74
102
  key: t.key,
75
103
  title: t.title,
76
104
  icon: t.icon
@@ -97,6 +125,11 @@ const BackstagePanel = ({
97
125
  flags: featureFlags ?? [],
98
126
  onToggle: onToggleFeatureFlag
99
127
  });
128
+ case 'storage':
129
+ return storageAdapter ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageTab.StorageTab, {
130
+ adapter: storageAdapter,
131
+ jsonMaxDepth: jsonMaxDepth
132
+ }) : null;
100
133
  case 'network':
101
134
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkTab.NetworkTab, {
102
135
  entries: networkEntries,
@@ -127,7 +160,7 @@ const BackstagePanel = ({
127
160
  }
128
161
  };
129
162
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Modal, {
130
- testID: _constants.TestIDs.panel,
163
+ testID: _constants.TestIDs.panelModal,
131
164
  animationType: "slide",
132
165
  transparent: false,
133
166
  visible: visible,
@@ -137,8 +170,10 @@ const BackstagePanel = ({
137
170
  barStyle: theme.background < '#888' ? 'light-content' : 'dark-content',
138
171
  backgroundColor: theme.background
139
172
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.SafeAreaView, {
173
+ testID: _constants.TestIDs.panel,
140
174
  style: [styles.safeArea, propStyles?.panelStyle],
141
175
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
176
+ testID: _constants.TestIDs.header.container,
142
177
  style: styles.header,
143
178
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
144
179
  style: styles.headerLeft,
@@ -146,24 +181,43 @@ const BackstagePanel = ({
146
181
  style: styles.headerBrand,
147
182
  children: "\u2699"
148
183
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
184
+ testID: _constants.TestIDs.header.title,
149
185
  style: [styles.headerTitle, propStyles?.headerTitleStyle],
150
186
  children: "Backstage"
151
187
  })]
152
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
153
- testID: _constants.TestIDs.header.closeButton,
154
- style: styles.closeButton,
155
- onPress: onClose,
156
- activeOpacity: 0.7,
157
- hitSlop: {
158
- top: 8,
159
- bottom: 8,
160
- left: 8,
161
- right: 8
162
- },
163
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
164
- style: styles.closeButtonText,
165
- children: "\u2715"
166
- })
188
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
189
+ style: styles.headerRight,
190
+ children: [bugReportConfig && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
191
+ testID: _constants.TestIDs.bugReport.triggerButton,
192
+ style: styles.headerButton,
193
+ onPress: () => setBugReportVisible(true),
194
+ activeOpacity: 0.7,
195
+ hitSlop: {
196
+ top: 8,
197
+ bottom: 8,
198
+ left: 8,
199
+ right: 8
200
+ },
201
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
202
+ style: styles.headerButtonText,
203
+ children: "\uD83D\uDC1B"
204
+ })
205
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
206
+ testID: _constants.TestIDs.header.closeButton,
207
+ style: styles.closeButton,
208
+ onPress: onClose,
209
+ activeOpacity: 0.7,
210
+ hitSlop: {
211
+ top: 8,
212
+ bottom: 8,
213
+ left: 8,
214
+ right: 8
215
+ },
216
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
217
+ style: styles.closeButtonText,
218
+ children: "\u2715"
219
+ })
220
+ })]
167
221
  })]
168
222
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TabBar.TabBar, {
169
223
  tabs: allTabs,
@@ -173,6 +227,17 @@ const BackstagePanel = ({
173
227
  style: styles.content,
174
228
  children: renderTabContent()
175
229
  })]
230
+ }), bugReportConfig && /*#__PURE__*/(0, _jsxRuntime.jsx)(_BugReportComposer.BugReportComposer, {
231
+ visible: bugReportVisible,
232
+ onClose: () => setBugReportVisible(false),
233
+ config: bugReportConfig,
234
+ logs: logs,
235
+ networkEntries: networkEntries,
236
+ state: state,
237
+ appVersion: appVersion,
238
+ buildNumber: buildNumber,
239
+ bundleId: bundleId,
240
+ deviceInfo: deviceInfo
176
241
  })]
177
242
  });
178
243
  };
@@ -223,6 +288,24 @@ const createStyles = t => _reactNative.StyleSheet.create({
223
288
  color: t.textSecondary,
224
289
  fontWeight: '700'
225
290
  },
291
+ headerRight: {
292
+ flexDirection: 'row',
293
+ alignItems: 'center',
294
+ gap: 8
295
+ },
296
+ headerButton: {
297
+ width: 32,
298
+ height: 32,
299
+ borderRadius: 16,
300
+ backgroundColor: t.surfaceElevated,
301
+ borderWidth: 1,
302
+ borderColor: t.border,
303
+ alignItems: 'center',
304
+ justifyContent: 'center'
305
+ },
306
+ headerButtonText: {
307
+ fontSize: 16
308
+ },
226
309
  content: {
227
310
  flex: 1
228
311
  }