@jarve/bug-reporter 0.4.3 → 1.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 CHANGED
@@ -19,6 +19,7 @@ Go to your JARVE Agency dashboard at `/admin/bug-reports/sites` and:
19
19
  - Enter your site name and color
20
20
  - Click **Generate API Key**
21
21
  - Copy the API key (starts with `brk_`)
22
+ - Copy the public Site ID for the same site
22
23
 
23
24
  ### 2. Install
24
25
 
@@ -57,6 +58,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
57
58
  <JarveBugReporter
58
59
  apiUrl="https://www.jarve.com.au/api/bug-reporter/external"
59
60
  apiKey="brk_your_api_key_here"
61
+ siteId="your_public_site_id"
60
62
  user={{ name: 'James', email: 'james@example.com' }}
61
63
  >
62
64
  {children}
@@ -77,6 +79,7 @@ Click the blue bug icon (bottom-right) to report bugs. They'll appear in your JA
77
79
  | ---------------- | --------------------------------- | -------- | -------------------------------------------------------------------------------------- |
78
80
  | `apiUrl` | `string` | Yes | Base URL for the external bug reporter API |
79
81
  | `apiKey` | `string` | Yes | Your site's API key (starts with `brk_`) |
82
+ | `siteId` | `string` | Yes | Public site identifier used for widget state and labels. Do not derive it from apiKey. |
80
83
  | `buttonPosition` | `'left' \| 'right'` | No | Floating button position. Default: `'right'`. Sibling-aware with other @jarve widgets. |
81
84
  | `user` | `{ name: string, email: string }` | No | User info. If omitted, the AI will ask during conversation |
82
85
  | `children` | `ReactNode` | Yes | Your app content |
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { JarveTheme } from '@jarve/widget-shared';
2
3
 
3
4
  type FloatingButtonPosition = 'left' | 'right';
4
5
 
@@ -6,35 +7,154 @@ interface BugReporterUser {
6
7
  name: string;
7
8
  email: string;
8
9
  }
10
+ interface ClickedElement {
11
+ tagName: string;
12
+ textContent: string | null;
13
+ className: string;
14
+ id: string | null;
15
+ ariaLabel: string | null;
16
+ dataAttributes: Record<string, string>;
17
+ selectorPath: string;
18
+ clickX: number;
19
+ clickY: number;
20
+ relativeClickX: number;
21
+ relativeClickY: number;
22
+ }
23
+ interface CaptureMetadata {
24
+ pageUrl: string;
25
+ sectionId: string | null;
26
+ viewportWidth: number;
27
+ viewportHeight: number;
28
+ deviceType: 'desktop' | 'tablet' | 'mobile';
29
+ browser: string;
30
+ os: string;
31
+ timestamp: string;
32
+ timestampUtc: string;
33
+ reporterName: string;
34
+ reporterEmail: string;
35
+ /**
36
+ * Public site identifier supplied explicitly by the host app. This is used
37
+ * for prompt context and client-side draft scoping; it must never be
38
+ * derived from the secret API key.
39
+ */
40
+ siteId: string;
41
+ screenshotCaptureFailed?: boolean;
42
+ clickedElement?: ClickedElement;
43
+ }
44
+ interface ConversationMessage {
45
+ role: 'user' | 'assistant';
46
+ content: string;
47
+ }
48
+ interface ConsoleError {
49
+ message: string;
50
+ source?: string;
51
+ lineno?: number;
52
+ colno?: number;
53
+ timestamp: string;
54
+ }
55
+ interface FailedNetworkRequest {
56
+ url: string;
57
+ hasQueryString: boolean;
58
+ method: string;
59
+ status: number;
60
+ statusText: string;
61
+ /**
62
+ * Response body text, truncated to `TRUNCATE_LEN`. Always `null` unless
63
+ * the consumer opted in via `captureResponseBodies`. See Issue B4 —
64
+ * bodies routinely contain JWTs, Supabase RLS errors, and Stripe IDs,
65
+ * so we capture only status metadata by default.
66
+ */
67
+ responseBody: string | null;
68
+ /**
69
+ * The response `Content-Type` header, captured for every failed request
70
+ * regardless of the body-capture opt-in. Useful for triage without the
71
+ * privacy cost of the full body.
72
+ */
73
+ contentType: string | null;
74
+ timestamp: string;
75
+ }
76
+ interface CaptureResult {
77
+ screenshot: Blob;
78
+ metadata: CaptureMetadata;
79
+ consoleErrors: ConsoleError[];
80
+ networkErrors: FailedNetworkRequest[];
81
+ }
9
82
  interface BugReporterApiConfig {
10
83
  apiUrl: string;
11
84
  apiKey: string;
12
85
  }
13
86
 
14
- declare global {
15
- interface Window {
16
- __jarve_widgets?: Map<string, {
17
- type: string;
18
- label: string;
19
- tooltip: string;
20
- iconName: string;
21
- accentColor: string;
22
- isActive: boolean;
23
- trigger: () => void;
24
- }>;
25
- }
87
+ /**
88
+ * Payload handed to `onBeforeSubmit` immediately before the widget POSTs
89
+ * `/submit`. Consumers can mutate/redact in place and return either the
90
+ * same reference or a freshly built object — whatever is returned replaces
91
+ * the payload wholesale. See Issue B8.
92
+ */
93
+ interface BugReportSubmitPayload {
94
+ metadata: CaptureResult['metadata'];
95
+ conversation: ConversationMessage[];
96
+ structuredReport: {
97
+ summary: string;
98
+ expected_behavior: string;
99
+ actual_behavior: string;
100
+ reproducibility: string;
101
+ specific_data: string;
102
+ severity: string;
103
+ } | undefined;
104
+ consoleErrors: CaptureResult['consoleErrors'];
105
+ networkErrors: CaptureResult['networkErrors'];
106
+ clickedElement: CaptureResult['metadata']['clickedElement'] | null;
26
107
  }
108
+
27
109
  interface JarveBugReporterProps {
28
110
  /** Base URL for the external bug reporter API (e.g. "https://www.jarve.com.au/api/bug-reporter/external") */
29
111
  apiUrl: string;
30
112
  /** API key for your site (starts with "brk_") */
31
113
  apiKey: string;
114
+ /**
115
+ * Public site identifier for this widget install. Used for client-side draft
116
+ * scoping and prompt context. Must be supplied explicitly by the host app
117
+ * and must never be derived from the secret API key.
118
+ */
119
+ siteId: string;
32
120
  /** Optional position for the floating button (default: 'right') */
33
121
  buttonPosition?: FloatingButtonPosition;
34
122
  /** Optional user info. If not provided, the AI will ask for name/email during the conversation. */
35
123
  user?: BugReporterUser;
124
+ /**
125
+ * Base z-index for every rendered widget layer (FAB, overlay, modal).
126
+ * Default `10000`. Raise this when the host application already uses high
127
+ * z-indexes for its own modals/toasts and the widget needs to sit above
128
+ * them. See Issue F2.
129
+ */
130
+ zIndexBase?: number;
131
+ /**
132
+ * When `true`, capture a truncated copy of each failed response body in
133
+ * addition to status metadata. Default `false`. Response bodies routinely
134
+ * contain JWTs, Supabase RLS errors exposing schema, and vendor IDs —
135
+ * only opt in when you have reviewed those privacy implications. See
136
+ * Issue B4.
137
+ */
138
+ captureResponseBodies?: boolean;
139
+ /**
140
+ * Color theme for the bug-report modal. Defaults to `'auto'` which
141
+ * follows `matchMedia('(prefers-color-scheme: dark)')`. Use `'light'` or
142
+ * `'dark'` to force a palette. The widget owns its own `.dark` class —
143
+ * consumer apps do not need `darkMode: 'class'` in their Tailwind config.
144
+ * See Issue E11.
145
+ */
146
+ theme?: JarveTheme;
147
+ /**
148
+ * Final chance to scrub the bug-report payload before it leaves the
149
+ * browser. The hook receives the full `/submit` payload and must return
150
+ * either a replacement object (mutated or rebuilt) or `null`/`false` /
151
+ * throw to cancel the submit. On cancel the modal stays open with the
152
+ * draft intact and shows an inline `role="alert"` error so the user can
153
+ * retry. Async hooks are awaited. See Issue B8.
154
+ */
155
+ onBeforeSubmit?: (payload: BugReportSubmitPayload) => BugReportSubmitPayload | null | false | Promise<BugReportSubmitPayload | null | false>;
36
156
  children: React.ReactNode;
37
157
  }
38
- declare function JarveBugReporter({ apiUrl, apiKey, user, buttonPosition, children, }: JarveBugReporterProps): react_jsx_runtime.JSX.Element;
158
+ declare function JarveBugReporter({ apiUrl, apiKey, siteId, user, buttonPosition, zIndexBase, captureResponseBodies, theme, onBeforeSubmit, children, }: JarveBugReporterProps): react_jsx_runtime.JSX.Element;
39
159
 
40
- export { type BugReporterApiConfig, type BugReporterUser, type FloatingButtonPosition, JarveBugReporter };
160
+ export { type BugReportSubmitPayload, type BugReporterApiConfig, type BugReporterUser, type FloatingButtonPosition, JarveBugReporter, type JarveBugReporterProps };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { JarveTheme } from '@jarve/widget-shared';
2
3
 
3
4
  type FloatingButtonPosition = 'left' | 'right';
4
5
 
@@ -6,35 +7,154 @@ interface BugReporterUser {
6
7
  name: string;
7
8
  email: string;
8
9
  }
10
+ interface ClickedElement {
11
+ tagName: string;
12
+ textContent: string | null;
13
+ className: string;
14
+ id: string | null;
15
+ ariaLabel: string | null;
16
+ dataAttributes: Record<string, string>;
17
+ selectorPath: string;
18
+ clickX: number;
19
+ clickY: number;
20
+ relativeClickX: number;
21
+ relativeClickY: number;
22
+ }
23
+ interface CaptureMetadata {
24
+ pageUrl: string;
25
+ sectionId: string | null;
26
+ viewportWidth: number;
27
+ viewportHeight: number;
28
+ deviceType: 'desktop' | 'tablet' | 'mobile';
29
+ browser: string;
30
+ os: string;
31
+ timestamp: string;
32
+ timestampUtc: string;
33
+ reporterName: string;
34
+ reporterEmail: string;
35
+ /**
36
+ * Public site identifier supplied explicitly by the host app. This is used
37
+ * for prompt context and client-side draft scoping; it must never be
38
+ * derived from the secret API key.
39
+ */
40
+ siteId: string;
41
+ screenshotCaptureFailed?: boolean;
42
+ clickedElement?: ClickedElement;
43
+ }
44
+ interface ConversationMessage {
45
+ role: 'user' | 'assistant';
46
+ content: string;
47
+ }
48
+ interface ConsoleError {
49
+ message: string;
50
+ source?: string;
51
+ lineno?: number;
52
+ colno?: number;
53
+ timestamp: string;
54
+ }
55
+ interface FailedNetworkRequest {
56
+ url: string;
57
+ hasQueryString: boolean;
58
+ method: string;
59
+ status: number;
60
+ statusText: string;
61
+ /**
62
+ * Response body text, truncated to `TRUNCATE_LEN`. Always `null` unless
63
+ * the consumer opted in via `captureResponseBodies`. See Issue B4 —
64
+ * bodies routinely contain JWTs, Supabase RLS errors, and Stripe IDs,
65
+ * so we capture only status metadata by default.
66
+ */
67
+ responseBody: string | null;
68
+ /**
69
+ * The response `Content-Type` header, captured for every failed request
70
+ * regardless of the body-capture opt-in. Useful for triage without the
71
+ * privacy cost of the full body.
72
+ */
73
+ contentType: string | null;
74
+ timestamp: string;
75
+ }
76
+ interface CaptureResult {
77
+ screenshot: Blob;
78
+ metadata: CaptureMetadata;
79
+ consoleErrors: ConsoleError[];
80
+ networkErrors: FailedNetworkRequest[];
81
+ }
9
82
  interface BugReporterApiConfig {
10
83
  apiUrl: string;
11
84
  apiKey: string;
12
85
  }
13
86
 
14
- declare global {
15
- interface Window {
16
- __jarve_widgets?: Map<string, {
17
- type: string;
18
- label: string;
19
- tooltip: string;
20
- iconName: string;
21
- accentColor: string;
22
- isActive: boolean;
23
- trigger: () => void;
24
- }>;
25
- }
87
+ /**
88
+ * Payload handed to `onBeforeSubmit` immediately before the widget POSTs
89
+ * `/submit`. Consumers can mutate/redact in place and return either the
90
+ * same reference or a freshly built object — whatever is returned replaces
91
+ * the payload wholesale. See Issue B8.
92
+ */
93
+ interface BugReportSubmitPayload {
94
+ metadata: CaptureResult['metadata'];
95
+ conversation: ConversationMessage[];
96
+ structuredReport: {
97
+ summary: string;
98
+ expected_behavior: string;
99
+ actual_behavior: string;
100
+ reproducibility: string;
101
+ specific_data: string;
102
+ severity: string;
103
+ } | undefined;
104
+ consoleErrors: CaptureResult['consoleErrors'];
105
+ networkErrors: CaptureResult['networkErrors'];
106
+ clickedElement: CaptureResult['metadata']['clickedElement'] | null;
26
107
  }
108
+
27
109
  interface JarveBugReporterProps {
28
110
  /** Base URL for the external bug reporter API (e.g. "https://www.jarve.com.au/api/bug-reporter/external") */
29
111
  apiUrl: string;
30
112
  /** API key for your site (starts with "brk_") */
31
113
  apiKey: string;
114
+ /**
115
+ * Public site identifier for this widget install. Used for client-side draft
116
+ * scoping and prompt context. Must be supplied explicitly by the host app
117
+ * and must never be derived from the secret API key.
118
+ */
119
+ siteId: string;
32
120
  /** Optional position for the floating button (default: 'right') */
33
121
  buttonPosition?: FloatingButtonPosition;
34
122
  /** Optional user info. If not provided, the AI will ask for name/email during the conversation. */
35
123
  user?: BugReporterUser;
124
+ /**
125
+ * Base z-index for every rendered widget layer (FAB, overlay, modal).
126
+ * Default `10000`. Raise this when the host application already uses high
127
+ * z-indexes for its own modals/toasts and the widget needs to sit above
128
+ * them. See Issue F2.
129
+ */
130
+ zIndexBase?: number;
131
+ /**
132
+ * When `true`, capture a truncated copy of each failed response body in
133
+ * addition to status metadata. Default `false`. Response bodies routinely
134
+ * contain JWTs, Supabase RLS errors exposing schema, and vendor IDs —
135
+ * only opt in when you have reviewed those privacy implications. See
136
+ * Issue B4.
137
+ */
138
+ captureResponseBodies?: boolean;
139
+ /**
140
+ * Color theme for the bug-report modal. Defaults to `'auto'` which
141
+ * follows `matchMedia('(prefers-color-scheme: dark)')`. Use `'light'` or
142
+ * `'dark'` to force a palette. The widget owns its own `.dark` class —
143
+ * consumer apps do not need `darkMode: 'class'` in their Tailwind config.
144
+ * See Issue E11.
145
+ */
146
+ theme?: JarveTheme;
147
+ /**
148
+ * Final chance to scrub the bug-report payload before it leaves the
149
+ * browser. The hook receives the full `/submit` payload and must return
150
+ * either a replacement object (mutated or rebuilt) or `null`/`false` /
151
+ * throw to cancel the submit. On cancel the modal stays open with the
152
+ * draft intact and shows an inline `role="alert"` error so the user can
153
+ * retry. Async hooks are awaited. See Issue B8.
154
+ */
155
+ onBeforeSubmit?: (payload: BugReportSubmitPayload) => BugReportSubmitPayload | null | false | Promise<BugReportSubmitPayload | null | false>;
36
156
  children: React.ReactNode;
37
157
  }
38
- declare function JarveBugReporter({ apiUrl, apiKey, user, buttonPosition, children, }: JarveBugReporterProps): react_jsx_runtime.JSX.Element;
158
+ declare function JarveBugReporter({ apiUrl, apiKey, siteId, user, buttonPosition, zIndexBase, captureResponseBodies, theme, onBeforeSubmit, children, }: JarveBugReporterProps): react_jsx_runtime.JSX.Element;
39
159
 
40
- export { type BugReporterApiConfig, type BugReporterUser, type FloatingButtonPosition, JarveBugReporter };
160
+ export { type BugReportSubmitPayload, type BugReporterApiConfig, type BugReporterUser, type FloatingButtonPosition, JarveBugReporter, type JarveBugReporterProps };