glitchgrab 1.37.0 → 1.39.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.
package/README.md CHANGED
@@ -641,6 +641,110 @@ captureError(error: unknown, options?: {
641
641
  - Pass `digest` whenever you have it. In production Next replaces server-boundary error messages with one generic string — without the digest, every distinct server crash on a page collapses into a single deduped issue.
642
642
  - No-ops if no `GlitchgrabProvider` has rendered yet.
643
643
 
644
+ ## How do I catch errors on the server (cron jobs, API routes, workers)?
645
+
646
+ Everything above is browser-side — it hooks `window.onerror` and needs a
647
+ rendered provider. A cron job at 3am has neither, so a nightly digest that
648
+ throws, an SMTP timeout, or a payment webhook a provider rejects is invisible
649
+ to it. `glitchgrab/server` is the same pipeline for code with no tab open.
650
+
651
+ ```bash
652
+ GLITCHGRAB_TOKEN=gg_your_token
653
+ ```
654
+
655
+ ```ts
656
+ // app/api/cron/daily-digest/route.ts
657
+ import { reportServerError } from "glitchgrab/server";
658
+
659
+ export async function GET() {
660
+ try {
661
+ await sendDigest();
662
+ return Response.json({ ok: true });
663
+ } catch (error) {
664
+ await reportServerError(error, { context: "cron/daily-digest" });
665
+ throw error;
666
+ }
667
+ }
668
+ ```
669
+
670
+ That is a GitHub issue with the message, the stack, the Node version and the
671
+ region — no browser, no screenshot, no provider.
672
+
673
+ **Await it.** On a serverless platform your function can be frozen the instant
674
+ the handler returns; a floating promise dies with it and the report never
675
+ leaves the machine.
676
+
677
+ ### Reporting a failure that isn't a thrown error
678
+
679
+ The useful failures are often values, not exceptions — a provider that answers
680
+ `{ ok: false }`, a send the API rejects. Report those the same way:
681
+
682
+ ```ts
683
+ const result = await sendWhatsApp(payload);
684
+ if (!result.success) {
685
+ await reportServerError(result.error, {
686
+ context: "whatsapp/task-reminder",
687
+ description: `Template ${payload.template} rejected for ${payload.to}`,
688
+ severity: "high",
689
+ });
690
+ }
691
+ ```
692
+
693
+ ### Set the token once
694
+
695
+ ```ts
696
+ // instrumentation.ts
697
+ import { configureServerReporter, captureServerErrors } from "glitchgrab/server";
698
+
699
+ export function register() {
700
+ configureServerReporter({
701
+ token: process.env.GLITCHGRAB_TOKEN,
702
+ metadata: { service: "web" },
703
+ });
704
+
705
+ // Optional: report every uncaught exception and unhandled rejection.
706
+ captureServerErrors();
707
+ }
708
+ ```
709
+
710
+ `captureServerErrors()` listens on `uncaughtExceptionMonitor`, which observes
711
+ without taking over — your process still crashes exactly as it would have. A
712
+ reporter that keeps a broken process alive is worse than no reporter.
713
+
714
+ ### `context` is the grouping key
715
+
716
+ It is sent as the report's `pageUrl` (as `server://<context>`), and `pageUrl`
717
+ feeds the dedup signature. Two different jobs throwing the same `"Timeout"`
718
+ therefore stay two issues instead of collapsing into one. Give every call site
719
+ its own context.
720
+
721
+ ### Options
722
+
723
+ ```ts
724
+ reportServerError(error: unknown, options?: {
725
+ token?: string; // default: process.env.GLITCHGRAB_TOKEN
726
+ baseUrl?: string; // default: process.env.GLITCHGRAB_BASE_URL
727
+ context?: string; // "cron/daily-digest" — the grouping key
728
+ description?: string; // what the job was doing
729
+ type?: ReportType; // default "BUG"
730
+ severity?: ReportSeverity; // becomes a severity:<value> label
731
+ pageUrl?: string; // a real request URL, when there is one
732
+ metadata?: Record<string, string>;
733
+ reporter?: { id?: string; name?: string; email?: string; phone?: string };
734
+ enableInDevelopment?: boolean;
735
+ })
736
+ ```
737
+
738
+ - **Deduped server-side**: one issue per signature per 24h, and nothing new for
739
+ 7 days while an issue for it is open. A job failing hourly files one issue,
740
+ not twenty-four.
741
+ - **Silent in development** unless `enableInDevelopment: true`. The browser SDK
742
+ is stopped by the API's localhost check; a server sends no `Origin` header, so
743
+ this flag is the only thing standing between a refactor and real issues.
744
+ - **Never throws.** Returns `null` when nothing was filed — no token,
745
+ development, or the API refused it.
746
+ - No React, no DOM, no `"use client"`. Safe in any Node runtime.
747
+
644
748
  ## What configuration options are available?
645
749
 
646
750
  | Prop | Type | Default | Description |
package/dist/index.d.mts CHANGED
@@ -1,273 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { f as GlitchgrabProviderProps, U as UseGlitchgrabReturn, R as ReportButtonProps, F as FeedbackButtonProps, g as GlitchgrabSession, C as CaptureErrorOptions, e as GlitchgrabFeedback, a as BreadcrumbType, B as Breadcrumb, b as CapturedContext, D as DeviceInfo, c as FeedbackPayload, d as FeedbackResult, h as ReportPayload, i as ReportResult } from './types-DxH3oAL9.mjs';
3
+ export { G as GlitchgrabConfig, j as ReportSeverity, k as ReportType, l as RuntimeInfo } from './types-DxH3oAL9.mjs';
2
4
  import * as React from 'react';
3
5
  import { ReactNode } from 'react';
4
6
 
5
- interface GlitchgrabConfig {
6
- token: string;
7
- baseUrl?: string;
8
- onError?: (error: Error) => void;
9
- /** Called after a report is sent — use to sync with your own ticket system */
10
- onReportSent?: (result: ReportResult) => void;
11
- /** Enable breadcrumb tracking (default: true) */
12
- breadcrumbs?: boolean;
13
- /** Max breadcrumbs to keep (default: 50) */
14
- maxBreadcrumbs?: number;
15
- /**
16
- * Skip auto-capture for errors matching any of these patterns (checked against the
17
- * error message). String = substring match, RegExp = `.test()`. Use for known-noisy
18
- * signatures that aren't app bugs — e.g. browser extension bridge errors.
19
- */
20
- ignoreErrors?: (string | RegExp)[];
21
- }
22
- type ReportType = "BUG" | "FEATURE_REQUEST" | "UI_IMPROVEMENT" | "PERFORMANCE" | "SECURITY" | "QUESTION" | "OTHER";
23
- type ReportSeverity = "low" | "medium" | "high";
24
- interface ReportPayload {
25
- token: string;
26
- source: "SDK_AUTO" | "SDK_USER_REPORT";
27
- type?: ReportType;
28
- description?: string;
29
- errorMessage?: string;
30
- errorStack?: string;
31
- componentStack?: string;
32
- pageUrl?: string;
33
- userAgent?: string;
34
- breadcrumbs?: Breadcrumb[];
35
- deviceInfo?: DeviceInfo;
36
- metadata?: Record<string, string>;
37
- }
38
- /** Extra context for an error your app already caught — see `captureError` */
39
- interface CaptureErrorOptions {
40
- /** React component stack, e.g. from `componentDidCatch` / `onCaughtError` */
41
- componentStack?: string;
42
- /**
43
- * Next.js error digest. In production Next replaces server-boundary error
44
- * messages with a generic string — the digest is the only thing that tells
45
- * two different crashes apart, so it also feeds the dedup signature.
46
- */
47
- digest?: string;
48
- /** Which boundary caught it, e.g. `"next-app-router"` — attached as metadata */
49
- boundary?: string;
50
- /** Extra metadata merged into the report */
51
- metadata?: Record<string, string>;
52
- }
53
- interface ReportResult {
54
- success: boolean;
55
- reportId?: string;
56
- issueUrl?: string;
57
- issueNumber?: number;
58
- title?: string;
59
- intent?: string;
60
- message?: string;
61
- }
62
- interface FeedbackPayload {
63
- token: string;
64
- /** 1–5 stars */
65
- rating: number;
66
- message?: string;
67
- pageUrl?: string;
68
- userAgent?: string;
69
- metadata?: Record<string, string>;
70
- }
71
- interface FeedbackResult {
72
- success: boolean;
73
- feedbackId?: string;
74
- rating?: number;
75
- createdAt?: string;
76
- message?: string;
77
- }
78
- /** One stored feedback entry, as returned by the read endpoint. */
79
- interface GlitchgrabFeedback {
80
- id: string;
81
- rating: number;
82
- message: string | null;
83
- pageUrl: string | null;
84
- /** Whether the repo owner published this entry for public display */
85
- approved: boolean;
86
- reporterPrimaryKey: string;
87
- reporterName: string;
88
- createdAt: string;
89
- }
90
- type BreadcrumbType = "console" | "navigation" | "api" | "click" | "error" | "custom";
91
- interface Breadcrumb {
92
- type: BreadcrumbType;
93
- message: string;
94
- timestamp: string;
95
- data?: Record<string, string>;
96
- }
97
- interface DeviceInfo {
98
- screenWidth: number;
99
- screenHeight: number;
100
- viewportWidth: number;
101
- viewportHeight: number;
102
- platform: string;
103
- language: string;
104
- online: boolean;
105
- colorScheme: string;
106
- devicePixelRatio: number;
107
- }
108
- /**
109
- * Machine state at the moment of the crash, as opposed to `DeviceInfo`, which
110
- * describes the machine itself. Most fields are Chromium-only and simply absent
111
- * elsewhere — never assume one is present.
112
- */
113
- interface RuntimeInfo {
114
- /** ms since this page loaded */
115
- timeOnPageMs: number;
116
- /** How many errors the SDK has already auto-captured in this page session */
117
- errorCount: number;
118
- /** `document.visibilityState` — a crash in a background tab reads differently */
119
- visibility: string;
120
- jsHeapUsedMb?: number;
121
- jsHeapLimitMb?: number;
122
- /** `navigator.connection.effectiveType` — "4g", "3g", "2g", "slow-2g" */
123
- connectionType?: string;
124
- downlinkMbps?: number;
125
- rttMs?: number;
126
- saveData?: boolean;
127
- }
128
- interface CapturedContext {
129
- url: string;
130
- userAgent: string;
131
- timestamp: string;
132
- visitedPages: string[];
133
- breadcrumbs: Breadcrumb[];
134
- deviceInfo: DeviceInfo | null;
135
- /** Runtime health snapshot — null when unavailable (SSR) */
136
- runtime: RuntimeInfo | null;
137
- /** Key-values the host app attached via `setContext` */
138
- appContext: Record<string, string>;
139
- /** Build identifier this crash came from, if known */
140
- release?: string;
141
- }
142
- interface GlitchgrabSession {
143
- /** Primary key of the user in your database (required) */
144
- userId: string;
145
- /** Display name (required) */
146
- name: string;
147
- /** Email address */
148
- email?: string | null;
149
- /** Phone number */
150
- phone?: string | null;
151
- /** Any extra fields you want attached to reports */
152
- [key: string]: unknown;
153
- }
154
- interface GlitchgrabProviderProps {
155
- token: string;
156
- /** Logged-in user session — include userId (your DB primary key) so reports are traceable */
157
- session?: GlitchgrabSession | null;
158
- baseUrl?: string;
159
- onError?: (error: Error) => void;
160
- onReportSent?: (result: ReportResult) => void;
161
- breadcrumbs?: boolean;
162
- maxBreadcrumbs?: number;
163
- children: ReactNode;
164
- fallback?: ReactNode;
165
- /** Which report types to show in the dialog (default: all) */
166
- types?: ReportType[];
167
- /** Show severity picker for BUG type (default: true) */
168
- showSeverity?: boolean;
169
- /**
170
- * Skip auto-capture for errors matching any of these patterns (checked against the
171
- * error message). String = substring match, RegExp = `.test()`. Use for known-noisy
172
- * signatures that aren't app bugs — e.g. browser extension bridge errors.
173
- */
174
- ignoreErrors?: (string | RegExp)[];
175
- /**
176
- * Build identifier attached to every report — a version, a tag, a commit SHA.
177
- * Tells you which deploy introduced a crash. Falls back to
178
- * `NEXT_PUBLIC_APP_VERSION`, `NEXT_PUBLIC_RELEASE`, then
179
- * `NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA` when not passed.
180
- */
181
- release?: string;
182
- /**
183
- * App-owned context attached to every report — orgId, plan, role, feature
184
- * flags. Merged with anything set imperatively via `setContext`.
185
- */
186
- context?: Record<string, unknown>;
187
- /**
188
- * Extra origins whose failed-request bodies may be recorded in breadcrumbs,
189
- * e.g. `["https://api.myapp.com"]`. Same-origin requests are always recorded;
190
- * third-party APIs are excluded by default because their error envelopes carry
191
- * data you don't control and shouldn't forward into a GitHub issue.
192
- */
193
- responseBodyOrigins?: string[];
194
- }
195
- interface ReportButtonProps {
196
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
197
- label?: string;
198
- className?: string;
199
- }
200
- interface FeedbackButtonProps {
201
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
202
- label?: string;
203
- className?: string;
204
- /** Heading inside the dialog (default: "How are we doing?") */
205
- title?: string;
206
- /** Placeholder for the message box */
207
- placeholder?: string;
208
- /** Shown after a successful submit */
209
- thanksMessage?: string;
210
- }
211
- interface UseGlitchgrabReturn {
212
- /** Report a bug programmatically */
213
- reportBug: (description: string, metadata?: Record<string, string>) => Promise<ReportResult | null>;
214
- /** Report with a specific type */
215
- report: (type: ReportType, description: string, metadata?: Record<string, string>) => Promise<ReportResult | null>;
216
- /**
217
- * Report an error your app already caught — a framework error boundary
218
- * (`app/error.tsx`, React Router `errorElement`, Remix `ErrorBoundary`) or a
219
- * `try/catch`. These never reach `window.onerror`, so auto-capture misses them.
220
- * Sends `SDK_AUTO`. Fire-and-forget, never throws.
221
- */
222
- captureError: (error: unknown, options?: CaptureErrorOptions) => void;
223
- /**
224
- * Attach a key-value to every future report — orgId, plan, role, feature flag.
225
- * Pass `null` to remove a key. Survives navigation and provider remounts.
226
- */
227
- setContext: (key: string, value: unknown) => void;
228
- /** Set several context keys at once. Merges; does not replace. */
229
- setContexts: (values: Record<string, unknown>) => void;
230
- /**
231
- * Save a 1–5 star rating your end-user left about your app. Stored by
232
- * Glitchgrab and shown on your Feedback page — never becomes a GitHub issue.
233
- * Returns null on any failure (never throws).
234
- */
235
- sendFeedback: (rating: number, message?: string, metadata?: Record<string, string>) => Promise<FeedbackResult | null>;
236
- /** Open the built-in feedback dialog (stars + message) programmatically */
237
- openFeedbackDialog: () => void;
238
- /** Add a custom breadcrumb */
239
- addBreadcrumb: (message: string, data?: Record<string, string>) => void;
240
- /** Open the ReportButton modal programmatically (captures screenshot + shows dialog) */
241
- openReportDialog: (options?: {
242
- description?: string;
243
- type?: ReportType;
244
- }) => void;
245
- /**
246
- * Open the demo booking dialog.
247
- *
248
- * Slots come from the project owner's real Google calendar, and the booking
249
- * creates a Meet on it — so this is only useful for projects whose owner has
250
- * connected a calendar and enabled booking in Glitchgrab.
251
- */
252
- openBookingDialog: () => void;
253
- /**
254
- * Optional: polish user-written description text via the Glitchgrab AI enhance endpoint.
255
- * Fixes grammar / clarity only — never invents details or changes meaning.
256
- * Returns the polished text, or the original text on any failure (never throws).
257
- */
258
- enhanceText: (text: string, screenshot?: string | null) => Promise<string>;
259
- /**
260
- * OS-aware label for the shortcut that opens the report dialog —
261
- * `⌘⇧G` on Mac, `Ctrl+Shift+G` elsewhere. Render this instead of
262
- * hardcoding the shortcut, so the hint stays in sync with the handler.
263
- */
264
- shortcutLabel: string;
265
- /** The token being used */
266
- token: string;
267
- /** The base URL of the Glitchgrab API */
268
- baseUrl: string;
269
- }
270
-
271
7
  /**
272
8
  * Hook to access Glitchgrab in your components.
273
9
  *
@@ -649,4 +385,4 @@ declare function computeSignature(params: {
649
385
  declare function shouldSkipDuplicate(signature: string, windowMs?: number, now?: number): boolean;
650
386
  declare function clearDedupCache(): void;
651
387
 
652
- export { BookDemoButton, type Breadcrumb, type BreadcrumbType, type CaptureErrorOptions, type CapturedContext, type DeviceInfo, FeedbackButton, type FeedbackButtonProps, type FeedbackPayload, type FeedbackQuery, type FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabConfig, GlitchgrabErrorBoundary, type GlitchgrabFeedback, GlitchgrabProvider, type GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabSession, ReportButton, type ReportButtonProps, type ReportPayload, type ReportResult, type ReportSeverity, type ReportType, type RuntimeInfo, type UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, sanitizeUrl, sendFeedback, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReports };
388
+ export { BookDemoButton, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, GlitchgrabSession, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, sanitizeUrl, sendFeedback, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReports };
package/dist/index.d.ts CHANGED
@@ -1,273 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { f as GlitchgrabProviderProps, U as UseGlitchgrabReturn, R as ReportButtonProps, F as FeedbackButtonProps, g as GlitchgrabSession, C as CaptureErrorOptions, e as GlitchgrabFeedback, a as BreadcrumbType, B as Breadcrumb, b as CapturedContext, D as DeviceInfo, c as FeedbackPayload, d as FeedbackResult, h as ReportPayload, i as ReportResult } from './types-DxH3oAL9.js';
3
+ export { G as GlitchgrabConfig, j as ReportSeverity, k as ReportType, l as RuntimeInfo } from './types-DxH3oAL9.js';
2
4
  import * as React from 'react';
3
5
  import { ReactNode } from 'react';
4
6
 
5
- interface GlitchgrabConfig {
6
- token: string;
7
- baseUrl?: string;
8
- onError?: (error: Error) => void;
9
- /** Called after a report is sent — use to sync with your own ticket system */
10
- onReportSent?: (result: ReportResult) => void;
11
- /** Enable breadcrumb tracking (default: true) */
12
- breadcrumbs?: boolean;
13
- /** Max breadcrumbs to keep (default: 50) */
14
- maxBreadcrumbs?: number;
15
- /**
16
- * Skip auto-capture for errors matching any of these patterns (checked against the
17
- * error message). String = substring match, RegExp = `.test()`. Use for known-noisy
18
- * signatures that aren't app bugs — e.g. browser extension bridge errors.
19
- */
20
- ignoreErrors?: (string | RegExp)[];
21
- }
22
- type ReportType = "BUG" | "FEATURE_REQUEST" | "UI_IMPROVEMENT" | "PERFORMANCE" | "SECURITY" | "QUESTION" | "OTHER";
23
- type ReportSeverity = "low" | "medium" | "high";
24
- interface ReportPayload {
25
- token: string;
26
- source: "SDK_AUTO" | "SDK_USER_REPORT";
27
- type?: ReportType;
28
- description?: string;
29
- errorMessage?: string;
30
- errorStack?: string;
31
- componentStack?: string;
32
- pageUrl?: string;
33
- userAgent?: string;
34
- breadcrumbs?: Breadcrumb[];
35
- deviceInfo?: DeviceInfo;
36
- metadata?: Record<string, string>;
37
- }
38
- /** Extra context for an error your app already caught — see `captureError` */
39
- interface CaptureErrorOptions {
40
- /** React component stack, e.g. from `componentDidCatch` / `onCaughtError` */
41
- componentStack?: string;
42
- /**
43
- * Next.js error digest. In production Next replaces server-boundary error
44
- * messages with a generic string — the digest is the only thing that tells
45
- * two different crashes apart, so it also feeds the dedup signature.
46
- */
47
- digest?: string;
48
- /** Which boundary caught it, e.g. `"next-app-router"` — attached as metadata */
49
- boundary?: string;
50
- /** Extra metadata merged into the report */
51
- metadata?: Record<string, string>;
52
- }
53
- interface ReportResult {
54
- success: boolean;
55
- reportId?: string;
56
- issueUrl?: string;
57
- issueNumber?: number;
58
- title?: string;
59
- intent?: string;
60
- message?: string;
61
- }
62
- interface FeedbackPayload {
63
- token: string;
64
- /** 1–5 stars */
65
- rating: number;
66
- message?: string;
67
- pageUrl?: string;
68
- userAgent?: string;
69
- metadata?: Record<string, string>;
70
- }
71
- interface FeedbackResult {
72
- success: boolean;
73
- feedbackId?: string;
74
- rating?: number;
75
- createdAt?: string;
76
- message?: string;
77
- }
78
- /** One stored feedback entry, as returned by the read endpoint. */
79
- interface GlitchgrabFeedback {
80
- id: string;
81
- rating: number;
82
- message: string | null;
83
- pageUrl: string | null;
84
- /** Whether the repo owner published this entry for public display */
85
- approved: boolean;
86
- reporterPrimaryKey: string;
87
- reporterName: string;
88
- createdAt: string;
89
- }
90
- type BreadcrumbType = "console" | "navigation" | "api" | "click" | "error" | "custom";
91
- interface Breadcrumb {
92
- type: BreadcrumbType;
93
- message: string;
94
- timestamp: string;
95
- data?: Record<string, string>;
96
- }
97
- interface DeviceInfo {
98
- screenWidth: number;
99
- screenHeight: number;
100
- viewportWidth: number;
101
- viewportHeight: number;
102
- platform: string;
103
- language: string;
104
- online: boolean;
105
- colorScheme: string;
106
- devicePixelRatio: number;
107
- }
108
- /**
109
- * Machine state at the moment of the crash, as opposed to `DeviceInfo`, which
110
- * describes the machine itself. Most fields are Chromium-only and simply absent
111
- * elsewhere — never assume one is present.
112
- */
113
- interface RuntimeInfo {
114
- /** ms since this page loaded */
115
- timeOnPageMs: number;
116
- /** How many errors the SDK has already auto-captured in this page session */
117
- errorCount: number;
118
- /** `document.visibilityState` — a crash in a background tab reads differently */
119
- visibility: string;
120
- jsHeapUsedMb?: number;
121
- jsHeapLimitMb?: number;
122
- /** `navigator.connection.effectiveType` — "4g", "3g", "2g", "slow-2g" */
123
- connectionType?: string;
124
- downlinkMbps?: number;
125
- rttMs?: number;
126
- saveData?: boolean;
127
- }
128
- interface CapturedContext {
129
- url: string;
130
- userAgent: string;
131
- timestamp: string;
132
- visitedPages: string[];
133
- breadcrumbs: Breadcrumb[];
134
- deviceInfo: DeviceInfo | null;
135
- /** Runtime health snapshot — null when unavailable (SSR) */
136
- runtime: RuntimeInfo | null;
137
- /** Key-values the host app attached via `setContext` */
138
- appContext: Record<string, string>;
139
- /** Build identifier this crash came from, if known */
140
- release?: string;
141
- }
142
- interface GlitchgrabSession {
143
- /** Primary key of the user in your database (required) */
144
- userId: string;
145
- /** Display name (required) */
146
- name: string;
147
- /** Email address */
148
- email?: string | null;
149
- /** Phone number */
150
- phone?: string | null;
151
- /** Any extra fields you want attached to reports */
152
- [key: string]: unknown;
153
- }
154
- interface GlitchgrabProviderProps {
155
- token: string;
156
- /** Logged-in user session — include userId (your DB primary key) so reports are traceable */
157
- session?: GlitchgrabSession | null;
158
- baseUrl?: string;
159
- onError?: (error: Error) => void;
160
- onReportSent?: (result: ReportResult) => void;
161
- breadcrumbs?: boolean;
162
- maxBreadcrumbs?: number;
163
- children: ReactNode;
164
- fallback?: ReactNode;
165
- /** Which report types to show in the dialog (default: all) */
166
- types?: ReportType[];
167
- /** Show severity picker for BUG type (default: true) */
168
- showSeverity?: boolean;
169
- /**
170
- * Skip auto-capture for errors matching any of these patterns (checked against the
171
- * error message). String = substring match, RegExp = `.test()`. Use for known-noisy
172
- * signatures that aren't app bugs — e.g. browser extension bridge errors.
173
- */
174
- ignoreErrors?: (string | RegExp)[];
175
- /**
176
- * Build identifier attached to every report — a version, a tag, a commit SHA.
177
- * Tells you which deploy introduced a crash. Falls back to
178
- * `NEXT_PUBLIC_APP_VERSION`, `NEXT_PUBLIC_RELEASE`, then
179
- * `NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA` when not passed.
180
- */
181
- release?: string;
182
- /**
183
- * App-owned context attached to every report — orgId, plan, role, feature
184
- * flags. Merged with anything set imperatively via `setContext`.
185
- */
186
- context?: Record<string, unknown>;
187
- /**
188
- * Extra origins whose failed-request bodies may be recorded in breadcrumbs,
189
- * e.g. `["https://api.myapp.com"]`. Same-origin requests are always recorded;
190
- * third-party APIs are excluded by default because their error envelopes carry
191
- * data you don't control and shouldn't forward into a GitHub issue.
192
- */
193
- responseBodyOrigins?: string[];
194
- }
195
- interface ReportButtonProps {
196
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
197
- label?: string;
198
- className?: string;
199
- }
200
- interface FeedbackButtonProps {
201
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
202
- label?: string;
203
- className?: string;
204
- /** Heading inside the dialog (default: "How are we doing?") */
205
- title?: string;
206
- /** Placeholder for the message box */
207
- placeholder?: string;
208
- /** Shown after a successful submit */
209
- thanksMessage?: string;
210
- }
211
- interface UseGlitchgrabReturn {
212
- /** Report a bug programmatically */
213
- reportBug: (description: string, metadata?: Record<string, string>) => Promise<ReportResult | null>;
214
- /** Report with a specific type */
215
- report: (type: ReportType, description: string, metadata?: Record<string, string>) => Promise<ReportResult | null>;
216
- /**
217
- * Report an error your app already caught — a framework error boundary
218
- * (`app/error.tsx`, React Router `errorElement`, Remix `ErrorBoundary`) or a
219
- * `try/catch`. These never reach `window.onerror`, so auto-capture misses them.
220
- * Sends `SDK_AUTO`. Fire-and-forget, never throws.
221
- */
222
- captureError: (error: unknown, options?: CaptureErrorOptions) => void;
223
- /**
224
- * Attach a key-value to every future report — orgId, plan, role, feature flag.
225
- * Pass `null` to remove a key. Survives navigation and provider remounts.
226
- */
227
- setContext: (key: string, value: unknown) => void;
228
- /** Set several context keys at once. Merges; does not replace. */
229
- setContexts: (values: Record<string, unknown>) => void;
230
- /**
231
- * Save a 1–5 star rating your end-user left about your app. Stored by
232
- * Glitchgrab and shown on your Feedback page — never becomes a GitHub issue.
233
- * Returns null on any failure (never throws).
234
- */
235
- sendFeedback: (rating: number, message?: string, metadata?: Record<string, string>) => Promise<FeedbackResult | null>;
236
- /** Open the built-in feedback dialog (stars + message) programmatically */
237
- openFeedbackDialog: () => void;
238
- /** Add a custom breadcrumb */
239
- addBreadcrumb: (message: string, data?: Record<string, string>) => void;
240
- /** Open the ReportButton modal programmatically (captures screenshot + shows dialog) */
241
- openReportDialog: (options?: {
242
- description?: string;
243
- type?: ReportType;
244
- }) => void;
245
- /**
246
- * Open the demo booking dialog.
247
- *
248
- * Slots come from the project owner's real Google calendar, and the booking
249
- * creates a Meet on it — so this is only useful for projects whose owner has
250
- * connected a calendar and enabled booking in Glitchgrab.
251
- */
252
- openBookingDialog: () => void;
253
- /**
254
- * Optional: polish user-written description text via the Glitchgrab AI enhance endpoint.
255
- * Fixes grammar / clarity only — never invents details or changes meaning.
256
- * Returns the polished text, or the original text on any failure (never throws).
257
- */
258
- enhanceText: (text: string, screenshot?: string | null) => Promise<string>;
259
- /**
260
- * OS-aware label for the shortcut that opens the report dialog —
261
- * `⌘⇧G` on Mac, `Ctrl+Shift+G` elsewhere. Render this instead of
262
- * hardcoding the shortcut, so the hint stays in sync with the handler.
263
- */
264
- shortcutLabel: string;
265
- /** The token being used */
266
- token: string;
267
- /** The base URL of the Glitchgrab API */
268
- baseUrl: string;
269
- }
270
-
271
7
  /**
272
8
  * Hook to access Glitchgrab in your components.
273
9
  *
@@ -649,4 +385,4 @@ declare function computeSignature(params: {
649
385
  declare function shouldSkipDuplicate(signature: string, windowMs?: number, now?: number): boolean;
650
386
  declare function clearDedupCache(): void;
651
387
 
652
- export { BookDemoButton, type Breadcrumb, type BreadcrumbType, type CaptureErrorOptions, type CapturedContext, type DeviceInfo, FeedbackButton, type FeedbackButtonProps, type FeedbackPayload, type FeedbackQuery, type FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabConfig, GlitchgrabErrorBoundary, type GlitchgrabFeedback, GlitchgrabProvider, type GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabSession, ReportButton, type ReportButtonProps, type ReportPayload, type ReportResult, type ReportSeverity, type ReportType, type RuntimeInfo, type UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, sanitizeUrl, sendFeedback, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReports };
388
+ export { BookDemoButton, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, GlitchgrabSession, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, sanitizeUrl, sendFeedback, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReports };