@watchupltd/browser 0.1.9 → 0.2.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.
@@ -0,0 +1,254 @@
1
+ interface WatchupUser {
2
+ /** Your app's internal user ID — the only required field. */
3
+ id: string | number;
4
+ email?: string;
5
+ name?: string;
6
+ /** Any extra key/value pairs you want attached to events. */
7
+ [key: string]: unknown;
8
+ }
9
+ interface WatchupOptions {
10
+ /**
11
+ * Your project's **public** API key from the Watchup dashboard.
12
+ * Format: `wup_pub_xxxxxxxxxxxx`
13
+ * This key is safe to include in client-side code.
14
+ */
15
+ apiKey: string;
16
+ /** Defaults to `https://api.watchup.site`. Override for self-hosted. */
17
+ baseUrl?: string;
18
+ /** Flush interval in ms. Default: `5000`. */
19
+ flushInterval?: number;
20
+ /** Max items before forcing a flush. Default: `100`. */
21
+ maxBatchSize?: number;
22
+ /** Log SDK warnings to `console.warn`. Default: `false`. */
23
+ debug?: boolean;
24
+ /** Environment label on every payload. Default: `'production'`. */
25
+ environment?: string;
26
+ /** Git SHA / release tag for deploy correlation. */
27
+ release?: string;
28
+ /**
29
+ * Fraction of navigations/fetches captured as traces (0–1).
30
+ * Default: `1` (100 %).
31
+ */
32
+ sampleRate?: number;
33
+ /** Fine-grained control over what gets captured automatically. */
34
+ autoCapture?: {
35
+ /** Capture `window.onerror` and `unhandledrejection`. Default: `true`. */
36
+ errors?: boolean;
37
+ /** Capture FCP, LCP, and page-load timing. Default: `true`. */
38
+ performance?: boolean;
39
+ /**
40
+ * Track the initial page view and SPA navigations (History API).
41
+ * Default: `true`.
42
+ * Set to `false` when a framework SDK (React, Next.js, Svelte) handles
43
+ * page view tracking via the router.
44
+ */
45
+ pageViews?: boolean;
46
+ };
47
+ }
48
+ interface TracePayload {
49
+ span: string;
50
+ ms: number;
51
+ status_code: number;
52
+ status: 'ok' | 'warn' | 'err';
53
+ timestamp: string;
54
+ environment?: string;
55
+ release?: string;
56
+ meta?: Record<string, unknown>;
57
+ user?: WatchupUser;
58
+ }
59
+ interface ErrorPayload {
60
+ message: string;
61
+ level: 'debug' | 'info' | 'warning' | 'error' | 'fatal';
62
+ route?: string;
63
+ stack?: string;
64
+ context?: Record<string, unknown>;
65
+ timestamp: string;
66
+ environment?: string;
67
+ release?: string;
68
+ user?: WatchupUser;
69
+ }
70
+ interface EventPayload {
71
+ name: string;
72
+ properties?: Record<string, unknown>;
73
+ occurred_at: string;
74
+ }
75
+ interface IngestBatch {
76
+ traces?: TracePayload[];
77
+ errors?: ErrorPayload[];
78
+ events?: EventPayload[];
79
+ }
80
+ interface WebAnalyticsPayload {
81
+ /** URL path, e.g. "/pricing". */
82
+ path: string;
83
+ /** Hostname of the tracked site, e.g. "example.com". */
84
+ hostname: string;
85
+ /** Full referrer URL (document.referrer). */
86
+ referrer?: string;
87
+ /** document.title at tracking time. */
88
+ title?: string;
89
+ /** Screen width in CSS pixels. */
90
+ screen_w?: number;
91
+ /** Screen height in CSS pixels. */
92
+ screen_h?: number;
93
+ /** navigator.language, e.g. "en-GB". */
94
+ lang?: string;
95
+ /** Intl.DateTimeFormat().resolvedOptions().timeZone */
96
+ timezone?: string;
97
+ /** UTM parameters parsed from the current URL's query string. */
98
+ utm_source?: string;
99
+ utm_medium?: string;
100
+ utm_campaign?: string;
101
+ utm_term?: string;
102
+ utm_content?: string;
103
+ /**
104
+ * Persistent visitor UUID (stored in localStorage).
105
+ * The server hashes this before storing — the raw value is never persisted.
106
+ */
107
+ visitor_id: string;
108
+ /**
109
+ * Per-session UUID (stored in sessionStorage).
110
+ * The server hashes this before storing — the raw value is never persisted.
111
+ */
112
+ session_id: string;
113
+ /** Event type — defaults to "pageview". Use for custom web events. */
114
+ event_name?: string;
115
+ /** ISO-8601 timestamp when the event occurred. */
116
+ occurred_at: string;
117
+ }
118
+ interface FlagVariant {
119
+ key: string;
120
+ weight: number;
121
+ }
122
+ interface FlagTargetingRule {
123
+ attribute: string;
124
+ operator: 'in' | 'not_in' | 'contains' | 'equals';
125
+ values: string[];
126
+ }
127
+ interface FeatureFlag {
128
+ id: string;
129
+ key: string;
130
+ name: string;
131
+ description?: string;
132
+ enabled: boolean;
133
+ rollout_percentage: number;
134
+ variants: FlagVariant[];
135
+ targeting_rules: FlagTargetingRule[];
136
+ }
137
+ interface FlagContext {
138
+ userId?: string | number;
139
+ email?: string;
140
+ plan?: string;
141
+ [key: string]: unknown;
142
+ }
143
+
144
+ declare class Watchup {
145
+ private readonly cfg;
146
+ private readonly batcher;
147
+ private readonly cleanup;
148
+ private _user;
149
+ /**
150
+ * A random UUID generated on init. Stable for the lifetime of the page —
151
+ * useful for correlating all events from one user session.
152
+ */
153
+ readonly sessionId: string;
154
+ /**
155
+ * Persistent visitor ID. Stored in localStorage so it survives browser
156
+ * sessions. Falls back to a per-session UUID when localStorage is blocked.
157
+ * The server hashes this value with SHA-256 before persisting.
158
+ */
159
+ private readonly visitorId;
160
+ /**
161
+ * Per-session ID stored in sessionStorage. Resets on tab close.
162
+ * The server hashes this value before persisting.
163
+ */
164
+ private readonly webSessionId;
165
+ private _flags;
166
+ private _flagTimer;
167
+ constructor(options: WatchupOptions);
168
+ private _fetchFlags;
169
+ private _getOrCreateVisitorId;
170
+ private _getOrCreateSessionId;
171
+ /**
172
+ * Attach a user to all subsequent errors, traces, and events.
173
+ * Call this after login; the context persists until `clearUser()` or page reload.
174
+ *
175
+ * @example
176
+ * watchup.setUser({ id: '42', email: 'ada@example.com', name: 'Ada Lovelace' });
177
+ */
178
+ setUser(user: WatchupUser): void;
179
+ /**
180
+ * Remove the current user context (e.g. after logout).
181
+ */
182
+ clearUser(): void;
183
+ /**
184
+ * Track a custom analytics event.
185
+ *
186
+ * @example
187
+ * watchup.track('button.clicked', { label: 'Sign Up', variant: 'A' });
188
+ */
189
+ track(name: string, properties?: Record<string, unknown>): void;
190
+ /**
191
+ * Track a web analytics page view (or custom web event).
192
+ * Enriches the payload with visitor context, UTM params, and device info.
193
+ *
194
+ * Normally called automatically. Call manually when you need custom event_name.
195
+ *
196
+ * @example
197
+ * watchup.trackWebView({ event_name: 'conversion', path: '/checkout/success' });
198
+ */
199
+ trackWebView(overrides?: Partial<WebAnalyticsPayload>): void;
200
+ /**
201
+ * Manually capture an error.
202
+ *
203
+ * @example
204
+ * try { ... } catch (err) {
205
+ * watchup.captureError(err, { component: 'CheckoutForm' });
206
+ * }
207
+ */
208
+ captureError(error: Error | string | unknown, context?: Record<string, unknown> & {
209
+ route?: string;
210
+ level?: ErrorPayload['level'];
211
+ }): void;
212
+ /**
213
+ * Time any async operation and record it as a trace.
214
+ * Returns an `end()` function — call it when the operation finishes.
215
+ *
216
+ * @example
217
+ * const end = watchup.startTrace('fetch /api/cart');
218
+ * const cart = await fetch('/api/cart');
219
+ * end({ status: cart.ok ? 'ok' : 'err' });
220
+ */
221
+ startTrace(span: string): (opts?: {
222
+ status?: TracePayload['status'];
223
+ meta?: Record<string, unknown>;
224
+ }) => void;
225
+ /**
226
+ * Check whether a feature flag is enabled. Evaluated locally — zero
227
+ * network latency. Flag rules refresh every 30 seconds in the background.
228
+ * Falls back to the identified user (via `setUser`) when no context is given.
229
+ *
230
+ * @example
231
+ * if (watchup.isEnabled('new-checkout')) {
232
+ * renderNewCheckout();
233
+ * }
234
+ */
235
+ isEnabled(key: string, ctx?: FlagContext): boolean;
236
+ /**
237
+ * Get the variant key for a multivariate (A/B) flag.
238
+ * Returns `"control"` if the flag is off or the visitor isn't in the rollout.
239
+ *
240
+ * @example
241
+ * const variant = watchup.getVariant('pricing-layout');
242
+ * // → "control" | "variant-a" | "variant-b"
243
+ */
244
+ getVariant(key: string, ctx?: FlagContext): string;
245
+ /** Immediately flush all queued items (both telemetry and web analytics). */
246
+ flush(): void;
247
+ /** Stop the flush timer and release all listeners. */
248
+ shutdown(): void;
249
+ private _setupAutoCapture;
250
+ private _setupPageViewTracking;
251
+ private _timezone;
252
+ }
253
+
254
+ export { type ErrorPayload, type EventPayload, type FeatureFlag, type FlagContext, type FlagTargetingRule, type FlagVariant, type IngestBatch, type TracePayload, Watchup, type WatchupOptions, type WatchupUser };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,254 @@
1
- import { WatchUpClient, WatchUpClientOptions } from "@watchup/core";
2
- export * from "@watchup/core";
3
- export interface BrowserWatchUpOptions extends WatchUpClientOptions {
4
- autoCaptureErrors?: boolean;
5
- autoCaptureUnhandledRejections?: boolean;
6
- }
7
- export declare function initBrowserWatchUp(options: BrowserWatchUpOptions): WatchUpClient;
8
- export declare function getWatchUpClient(): WatchUpClient;
9
- export declare function shutdownBrowserWatchUp(): void;
10
- //# sourceMappingURL=index.d.ts.map
1
+ interface WatchupUser {
2
+ /** Your app's internal user ID — the only required field. */
3
+ id: string | number;
4
+ email?: string;
5
+ name?: string;
6
+ /** Any extra key/value pairs you want attached to events. */
7
+ [key: string]: unknown;
8
+ }
9
+ interface WatchupOptions {
10
+ /**
11
+ * Your project's **public** API key from the Watchup dashboard.
12
+ * Format: `wup_pub_xxxxxxxxxxxx`
13
+ * This key is safe to include in client-side code.
14
+ */
15
+ apiKey: string;
16
+ /** Defaults to `https://api.watchup.site`. Override for self-hosted. */
17
+ baseUrl?: string;
18
+ /** Flush interval in ms. Default: `5000`. */
19
+ flushInterval?: number;
20
+ /** Max items before forcing a flush. Default: `100`. */
21
+ maxBatchSize?: number;
22
+ /** Log SDK warnings to `console.warn`. Default: `false`. */
23
+ debug?: boolean;
24
+ /** Environment label on every payload. Default: `'production'`. */
25
+ environment?: string;
26
+ /** Git SHA / release tag for deploy correlation. */
27
+ release?: string;
28
+ /**
29
+ * Fraction of navigations/fetches captured as traces (0–1).
30
+ * Default: `1` (100 %).
31
+ */
32
+ sampleRate?: number;
33
+ /** Fine-grained control over what gets captured automatically. */
34
+ autoCapture?: {
35
+ /** Capture `window.onerror` and `unhandledrejection`. Default: `true`. */
36
+ errors?: boolean;
37
+ /** Capture FCP, LCP, and page-load timing. Default: `true`. */
38
+ performance?: boolean;
39
+ /**
40
+ * Track the initial page view and SPA navigations (History API).
41
+ * Default: `true`.
42
+ * Set to `false` when a framework SDK (React, Next.js, Svelte) handles
43
+ * page view tracking via the router.
44
+ */
45
+ pageViews?: boolean;
46
+ };
47
+ }
48
+ interface TracePayload {
49
+ span: string;
50
+ ms: number;
51
+ status_code: number;
52
+ status: 'ok' | 'warn' | 'err';
53
+ timestamp: string;
54
+ environment?: string;
55
+ release?: string;
56
+ meta?: Record<string, unknown>;
57
+ user?: WatchupUser;
58
+ }
59
+ interface ErrorPayload {
60
+ message: string;
61
+ level: 'debug' | 'info' | 'warning' | 'error' | 'fatal';
62
+ route?: string;
63
+ stack?: string;
64
+ context?: Record<string, unknown>;
65
+ timestamp: string;
66
+ environment?: string;
67
+ release?: string;
68
+ user?: WatchupUser;
69
+ }
70
+ interface EventPayload {
71
+ name: string;
72
+ properties?: Record<string, unknown>;
73
+ occurred_at: string;
74
+ }
75
+ interface IngestBatch {
76
+ traces?: TracePayload[];
77
+ errors?: ErrorPayload[];
78
+ events?: EventPayload[];
79
+ }
80
+ interface WebAnalyticsPayload {
81
+ /** URL path, e.g. "/pricing". */
82
+ path: string;
83
+ /** Hostname of the tracked site, e.g. "example.com". */
84
+ hostname: string;
85
+ /** Full referrer URL (document.referrer). */
86
+ referrer?: string;
87
+ /** document.title at tracking time. */
88
+ title?: string;
89
+ /** Screen width in CSS pixels. */
90
+ screen_w?: number;
91
+ /** Screen height in CSS pixels. */
92
+ screen_h?: number;
93
+ /** navigator.language, e.g. "en-GB". */
94
+ lang?: string;
95
+ /** Intl.DateTimeFormat().resolvedOptions().timeZone */
96
+ timezone?: string;
97
+ /** UTM parameters parsed from the current URL's query string. */
98
+ utm_source?: string;
99
+ utm_medium?: string;
100
+ utm_campaign?: string;
101
+ utm_term?: string;
102
+ utm_content?: string;
103
+ /**
104
+ * Persistent visitor UUID (stored in localStorage).
105
+ * The server hashes this before storing — the raw value is never persisted.
106
+ */
107
+ visitor_id: string;
108
+ /**
109
+ * Per-session UUID (stored in sessionStorage).
110
+ * The server hashes this before storing — the raw value is never persisted.
111
+ */
112
+ session_id: string;
113
+ /** Event type — defaults to "pageview". Use for custom web events. */
114
+ event_name?: string;
115
+ /** ISO-8601 timestamp when the event occurred. */
116
+ occurred_at: string;
117
+ }
118
+ interface FlagVariant {
119
+ key: string;
120
+ weight: number;
121
+ }
122
+ interface FlagTargetingRule {
123
+ attribute: string;
124
+ operator: 'in' | 'not_in' | 'contains' | 'equals';
125
+ values: string[];
126
+ }
127
+ interface FeatureFlag {
128
+ id: string;
129
+ key: string;
130
+ name: string;
131
+ description?: string;
132
+ enabled: boolean;
133
+ rollout_percentage: number;
134
+ variants: FlagVariant[];
135
+ targeting_rules: FlagTargetingRule[];
136
+ }
137
+ interface FlagContext {
138
+ userId?: string | number;
139
+ email?: string;
140
+ plan?: string;
141
+ [key: string]: unknown;
142
+ }
143
+
144
+ declare class Watchup {
145
+ private readonly cfg;
146
+ private readonly batcher;
147
+ private readonly cleanup;
148
+ private _user;
149
+ /**
150
+ * A random UUID generated on init. Stable for the lifetime of the page —
151
+ * useful for correlating all events from one user session.
152
+ */
153
+ readonly sessionId: string;
154
+ /**
155
+ * Persistent visitor ID. Stored in localStorage so it survives browser
156
+ * sessions. Falls back to a per-session UUID when localStorage is blocked.
157
+ * The server hashes this value with SHA-256 before persisting.
158
+ */
159
+ private readonly visitorId;
160
+ /**
161
+ * Per-session ID stored in sessionStorage. Resets on tab close.
162
+ * The server hashes this value before persisting.
163
+ */
164
+ private readonly webSessionId;
165
+ private _flags;
166
+ private _flagTimer;
167
+ constructor(options: WatchupOptions);
168
+ private _fetchFlags;
169
+ private _getOrCreateVisitorId;
170
+ private _getOrCreateSessionId;
171
+ /**
172
+ * Attach a user to all subsequent errors, traces, and events.
173
+ * Call this after login; the context persists until `clearUser()` or page reload.
174
+ *
175
+ * @example
176
+ * watchup.setUser({ id: '42', email: 'ada@example.com', name: 'Ada Lovelace' });
177
+ */
178
+ setUser(user: WatchupUser): void;
179
+ /**
180
+ * Remove the current user context (e.g. after logout).
181
+ */
182
+ clearUser(): void;
183
+ /**
184
+ * Track a custom analytics event.
185
+ *
186
+ * @example
187
+ * watchup.track('button.clicked', { label: 'Sign Up', variant: 'A' });
188
+ */
189
+ track(name: string, properties?: Record<string, unknown>): void;
190
+ /**
191
+ * Track a web analytics page view (or custom web event).
192
+ * Enriches the payload with visitor context, UTM params, and device info.
193
+ *
194
+ * Normally called automatically. Call manually when you need custom event_name.
195
+ *
196
+ * @example
197
+ * watchup.trackWebView({ event_name: 'conversion', path: '/checkout/success' });
198
+ */
199
+ trackWebView(overrides?: Partial<WebAnalyticsPayload>): void;
200
+ /**
201
+ * Manually capture an error.
202
+ *
203
+ * @example
204
+ * try { ... } catch (err) {
205
+ * watchup.captureError(err, { component: 'CheckoutForm' });
206
+ * }
207
+ */
208
+ captureError(error: Error | string | unknown, context?: Record<string, unknown> & {
209
+ route?: string;
210
+ level?: ErrorPayload['level'];
211
+ }): void;
212
+ /**
213
+ * Time any async operation and record it as a trace.
214
+ * Returns an `end()` function — call it when the operation finishes.
215
+ *
216
+ * @example
217
+ * const end = watchup.startTrace('fetch /api/cart');
218
+ * const cart = await fetch('/api/cart');
219
+ * end({ status: cart.ok ? 'ok' : 'err' });
220
+ */
221
+ startTrace(span: string): (opts?: {
222
+ status?: TracePayload['status'];
223
+ meta?: Record<string, unknown>;
224
+ }) => void;
225
+ /**
226
+ * Check whether a feature flag is enabled. Evaluated locally — zero
227
+ * network latency. Flag rules refresh every 30 seconds in the background.
228
+ * Falls back to the identified user (via `setUser`) when no context is given.
229
+ *
230
+ * @example
231
+ * if (watchup.isEnabled('new-checkout')) {
232
+ * renderNewCheckout();
233
+ * }
234
+ */
235
+ isEnabled(key: string, ctx?: FlagContext): boolean;
236
+ /**
237
+ * Get the variant key for a multivariate (A/B) flag.
238
+ * Returns `"control"` if the flag is off or the visitor isn't in the rollout.
239
+ *
240
+ * @example
241
+ * const variant = watchup.getVariant('pricing-layout');
242
+ * // → "control" | "variant-a" | "variant-b"
243
+ */
244
+ getVariant(key: string, ctx?: FlagContext): string;
245
+ /** Immediately flush all queued items (both telemetry and web analytics). */
246
+ flush(): void;
247
+ /** Stop the flush timer and release all listeners. */
248
+ shutdown(): void;
249
+ private _setupAutoCapture;
250
+ private _setupPageViewTracking;
251
+ private _timezone;
252
+ }
253
+
254
+ export { type ErrorPayload, type EventPayload, type FeatureFlag, type FlagContext, type FlagTargetingRule, type FlagVariant, type IngestBatch, type TracePayload, Watchup, type WatchupOptions, type WatchupUser };