@panda-replay/sdk 0.1.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,29 @@
1
+ import { type SdkConfigResponse, type UnifiedEventEnvelope } from "@panda-replay/shared";
2
+ import type { LifecycleName, ReplayEventFactory } from "./events.js";
3
+ export interface BrowserCaptureOptions {
4
+ config: SdkConfigResponse;
5
+ eventFactory: ReplayEventFactory;
6
+ disableRrweb: boolean;
7
+ addBreadcrumb(event: UnifiedEventEnvelope): void;
8
+ onPageHide(): void;
9
+ }
10
+ export declare class BrowserCapture {
11
+ private readonly options;
12
+ private stopRrweb;
13
+ private readonly restoreFns;
14
+ constructor(options: BrowserCaptureOptions);
15
+ start(): Promise<void>;
16
+ stop(): void;
17
+ addLifecycle(name: LifecycleName, data?: Record<string, unknown>): void;
18
+ private addBreadcrumb;
19
+ private addViewport;
20
+ private addRoute;
21
+ private installConsoleCapture;
22
+ private installFetchCapture;
23
+ private installXhrCapture;
24
+ private installRouteCapture;
25
+ private installDomBreadcrumbs;
26
+ private installLifecycleHooks;
27
+ private addNetworkBreadcrumb;
28
+ }
29
+ //# sourceMappingURL=browser-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-capture.d.ts","sourceRoot":"","sources":["../src/browser-capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,aAAa,EAEb,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,YAAY,EAAE,kBAAkB,CAAC;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACjD,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,qBAAa,cAAc;IAIb,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;gBAEvB,OAAO,EAAE,qBAAqB;IAErD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B,IAAI,IAAI,IAAI;IAOZ,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIvE,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,qBAAqB;IAwE7B,OAAO,CAAC,mBAAmB;IAyC3B,OAAO,CAAC,iBAAiB;IAoDzB,OAAO,CAAC,mBAAmB;IA0B3B,OAAO,CAAC,qBAAqB;IA4B7B,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,oBAAoB;CAG7B"}
@@ -0,0 +1,286 @@
1
+ import { sanitizeConsoleArgs } from "@panda-replay/shared";
2
+ export class BrowserCapture {
3
+ options;
4
+ stopRrweb;
5
+ restoreFns = [];
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ async start() {
10
+ this.addLifecycle("sdk_started");
11
+ this.addViewport();
12
+ this.addRoute(window.location.href, "initial");
13
+ this.installConsoleCapture();
14
+ this.installFetchCapture();
15
+ this.installXhrCapture();
16
+ this.installRouteCapture();
17
+ this.installDomBreadcrumbs();
18
+ this.installLifecycleHooks();
19
+ if (!this.options.disableRrweb) {
20
+ const { record } = await import("rrweb");
21
+ this.stopRrweb = record({
22
+ emit: (event) => this.addBreadcrumb(this.options.eventFactory.rrweb(event)),
23
+ blockSelector: this.options.config.privacy.blockSelectors.join(","),
24
+ maskTextSelector: this.options.config.privacy.maskSelectors.join(","),
25
+ maskInputOptions: {
26
+ password: true,
27
+ email: false,
28
+ textarea: false,
29
+ text: false
30
+ },
31
+ maskInputFn: (_text, element) => shouldMaskElement(element, this.options.config.privacy) ? "***" : _text
32
+ });
33
+ }
34
+ }
35
+ stop() {
36
+ this.stopRrweb?.();
37
+ for (const restore of this.restoreFns.reverse()) {
38
+ restore();
39
+ }
40
+ }
41
+ addLifecycle(name, data) {
42
+ this.addBreadcrumb(this.options.eventFactory.lifecycle(name, data));
43
+ }
44
+ addBreadcrumb(event) {
45
+ this.options.addBreadcrumb(event);
46
+ }
47
+ addViewport() {
48
+ this.addBreadcrumb(this.options.eventFactory.viewport({
49
+ width: window.innerWidth,
50
+ height: window.innerHeight,
51
+ devicePixelRatio: window.devicePixelRatio
52
+ }));
53
+ }
54
+ addRoute(to, navigationType, from) {
55
+ this.addBreadcrumb(this.options.eventFactory.route(to, navigationType, from));
56
+ }
57
+ installConsoleCapture() {
58
+ const mode = this.options.config.privacy.consoleCapture;
59
+ if (mode === "off") {
60
+ return;
61
+ }
62
+ const methods = ["log", "info", "warn", "error", "debug"];
63
+ for (const method of methods) {
64
+ if (!shouldCaptureConsole(method, mode)) {
65
+ continue;
66
+ }
67
+ const original = console[method].bind(console);
68
+ console[method] = (...args) => {
69
+ const sanitized = sanitizeConsoleArgs(args, this.options.config.privacy);
70
+ const payload = {
71
+ level: method,
72
+ message: sanitized.message,
73
+ args: sanitized.args,
74
+ redacted: sanitized.redacted
75
+ };
76
+ if (method === "error") {
77
+ const stack = new Error().stack;
78
+ if (stack) {
79
+ payload.stack = stack;
80
+ }
81
+ }
82
+ this.addBreadcrumb(this.options.eventFactory.console(payload));
83
+ original(...args);
84
+ };
85
+ this.restoreFns.push(() => {
86
+ console[method] = original;
87
+ });
88
+ }
89
+ const errorHandler = (event) => {
90
+ const sanitized = sanitizeConsoleArgs([event.message], this.options.config.privacy);
91
+ this.addBreadcrumb(this.options.eventFactory.console({
92
+ level: "error",
93
+ message: sanitized.message,
94
+ stack: event.error?.stack,
95
+ redacted: sanitized.redacted
96
+ }));
97
+ };
98
+ window.addEventListener("error", errorHandler);
99
+ this.restoreFns.push(() => window.removeEventListener("error", errorHandler));
100
+ const rejectionHandler = (event) => {
101
+ const sanitized = sanitizeConsoleArgs([event.reason], this.options.config.privacy);
102
+ this.addBreadcrumb(this.options.eventFactory.console({
103
+ level: "error",
104
+ message: sanitized.message,
105
+ redacted: sanitized.redacted
106
+ }));
107
+ };
108
+ window.addEventListener("unhandledrejection", rejectionHandler);
109
+ this.restoreFns.push(() => window.removeEventListener("unhandledrejection", rejectionHandler));
110
+ }
111
+ installFetchCapture() {
112
+ if (this.options.config.privacy.networkCapture !== "metadata" || !window.fetch) {
113
+ return;
114
+ }
115
+ const original = window.fetch.bind(window);
116
+ window.fetch = async (input, init) => {
117
+ const started = performance.now();
118
+ const method = init?.method ?? (input instanceof Request ? input.method : "GET");
119
+ const url = input instanceof Request ? input.url : String(input);
120
+ try {
121
+ const response = await original(input, init);
122
+ const requestId = getRequestId(response.headers);
123
+ this.addNetworkBreadcrumb({
124
+ method,
125
+ url,
126
+ status: response.status,
127
+ ok: response.ok,
128
+ failed: !response.ok,
129
+ durationMs: performance.now() - started,
130
+ ...(requestId ? { requestId } : {})
131
+ });
132
+ return response;
133
+ }
134
+ catch (error) {
135
+ this.addNetworkBreadcrumb({
136
+ method,
137
+ url,
138
+ failed: true,
139
+ durationMs: performance.now() - started,
140
+ error: error instanceof Error ? error.message : String(error)
141
+ });
142
+ throw error;
143
+ }
144
+ };
145
+ this.restoreFns.push(() => {
146
+ window.fetch = original;
147
+ });
148
+ }
149
+ installXhrCapture() {
150
+ if (this.options.config.privacy.networkCapture !== "metadata" || !window.XMLHttpRequest) {
151
+ return;
152
+ }
153
+ const originalOpen = XMLHttpRequest.prototype.open;
154
+ const originalSend = XMLHttpRequest.prototype.send;
155
+ const addNetwork = this.addNetworkBreadcrumb.bind(this);
156
+ XMLHttpRequest.prototype.open = function open(method, url, ...rest) {
157
+ this.__pandaReplay = {
158
+ method,
159
+ url: String(url),
160
+ started: 0
161
+ };
162
+ return Reflect.apply(originalOpen, this, [method, url, ...rest]);
163
+ };
164
+ XMLHttpRequest.prototype.send = function send(...args) {
165
+ const meta = this.__pandaReplay;
166
+ if (meta) {
167
+ meta.started = performance.now();
168
+ this.addEventListener("loadend", () => {
169
+ const requestId = this.getResponseHeader("x-request-id") ?? undefined;
170
+ addNetwork({
171
+ method: meta.method,
172
+ url: meta.url,
173
+ status: this.status,
174
+ ok: this.status >= 200 && this.status < 400,
175
+ failed: this.status >= 400 || this.status === 0,
176
+ durationMs: performance.now() - meta.started,
177
+ ...(requestId ? { requestId } : {})
178
+ });
179
+ });
180
+ }
181
+ return Reflect.apply(originalSend, this, args);
182
+ };
183
+ this.restoreFns.push(() => {
184
+ XMLHttpRequest.prototype.open = originalOpen;
185
+ XMLHttpRequest.prototype.send = originalSend;
186
+ });
187
+ }
188
+ installRouteCapture() {
189
+ const patchHistory = (name) => {
190
+ const original = history[name];
191
+ history[name] = (...args) => {
192
+ const from = window.location.href;
193
+ const result = original.apply(history, args);
194
+ this.addRoute(window.location.href, name === "pushState" ? "push" : "replace", from);
195
+ return result;
196
+ };
197
+ this.restoreFns.push(() => {
198
+ history[name] = original;
199
+ });
200
+ };
201
+ patchHistory("pushState");
202
+ patchHistory("replaceState");
203
+ const popHandler = () => this.addRoute(window.location.href, "pop");
204
+ window.addEventListener("popstate", popHandler);
205
+ this.restoreFns.push(() => window.removeEventListener("popstate", popHandler));
206
+ }
207
+ installDomBreadcrumbs() {
208
+ const clickHandler = (event) => {
209
+ this.addLifecycle("click", {
210
+ x: event.clientX,
211
+ y: event.clientY,
212
+ target: describeTarget(event.target)
213
+ });
214
+ };
215
+ document.addEventListener("click", clickHandler, true);
216
+ this.restoreFns.push(() => document.removeEventListener("click", clickHandler, true));
217
+ const inputHandler = (event) => {
218
+ this.addLifecycle("input", {
219
+ target: describeTarget(event.target)
220
+ });
221
+ };
222
+ document.addEventListener("input", inputHandler, true);
223
+ this.restoreFns.push(() => document.removeEventListener("input", inputHandler, true));
224
+ const submitHandler = (event) => {
225
+ this.addLifecycle("form_submit", {
226
+ target: describeTarget(event.target)
227
+ });
228
+ };
229
+ document.addEventListener("submit", submitHandler, true);
230
+ this.restoreFns.push(() => document.removeEventListener("submit", submitHandler, true));
231
+ }
232
+ installLifecycleHooks() {
233
+ const visibilityHandler = () => {
234
+ this.addLifecycle("visibility", { state: document.visibilityState });
235
+ };
236
+ document.addEventListener("visibilitychange", visibilityHandler);
237
+ this.restoreFns.push(() => document.removeEventListener("visibilitychange", visibilityHandler));
238
+ const resizeHandler = () => this.addViewport();
239
+ window.addEventListener("resize", resizeHandler);
240
+ this.restoreFns.push(() => window.removeEventListener("resize", resizeHandler));
241
+ const finalize = () => this.options.onPageHide();
242
+ window.addEventListener("pagehide", finalize);
243
+ this.restoreFns.push(() => window.removeEventListener("pagehide", finalize));
244
+ }
245
+ addNetworkBreadcrumb(input) {
246
+ this.addBreadcrumb(this.options.eventFactory.network(input));
247
+ }
248
+ }
249
+ function shouldCaptureConsole(method, mode) {
250
+ if (mode === "all") {
251
+ return true;
252
+ }
253
+ if (mode === "warnings") {
254
+ return method === "warn" || method === "error";
255
+ }
256
+ if (mode === "errors") {
257
+ return method === "error";
258
+ }
259
+ return false;
260
+ }
261
+ function shouldMaskElement(element, config) {
262
+ return config.maskSelectors.some((selector) => element.matches(selector));
263
+ }
264
+ function getRequestId(headers) {
265
+ return (headers.get("x-request-id") ??
266
+ headers.get("x-correlation-id") ??
267
+ headers.get("traceparent") ??
268
+ undefined);
269
+ }
270
+ function describeTarget(target) {
271
+ if (!(target instanceof Element)) {
272
+ return "unknown";
273
+ }
274
+ const tag = target.tagName.toLowerCase();
275
+ const label = target.getAttribute("data-replay-label");
276
+ if (label) {
277
+ return `${tag}[data-replay-label="${label}"]`;
278
+ }
279
+ const id = target.id ? `#${target.id}` : "";
280
+ const classes = Array.from(target.classList)
281
+ .slice(0, 3)
282
+ .map((item) => `.${item}`)
283
+ .join("");
284
+ return `${tag}${id}${classes}`;
285
+ }
286
+ //# sourceMappingURL=browser-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-capture.js","sourceRoot":"","sources":["../src/browser-capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { ConsoleEnvelope, LifecycleEnvelope, NetworkEnvelope, RouteEnvelope, RrwebEnvelope, ViewportEnvelope } from "@panda-replay/shared";
2
+ export type LifecycleName = LifecycleEnvelope["payload"]["name"];
3
+ export interface ViewportSnapshot {
4
+ width: number;
5
+ height: number;
6
+ devicePixelRatio: number;
7
+ }
8
+ export interface NetworkBreadcrumbInput {
9
+ method: string;
10
+ url: string;
11
+ status?: number;
12
+ ok?: boolean;
13
+ failed: boolean;
14
+ durationMs: number;
15
+ requestId?: string;
16
+ error?: string;
17
+ }
18
+ export interface ReplayEventFactory {
19
+ rrweb(payload: Record<string, unknown>): RrwebEnvelope;
20
+ console(payload: ConsoleEnvelope["payload"]): ConsoleEnvelope;
21
+ network(input: NetworkBreadcrumbInput): NetworkEnvelope;
22
+ route(to: string, navigationType: RouteEnvelope["payload"]["navigationType"], from?: string): RouteEnvelope;
23
+ viewport(snapshot: ViewportSnapshot): ViewportEnvelope;
24
+ lifecycle(name: LifecycleName, data?: Record<string, unknown>): LifecycleEnvelope;
25
+ }
26
+ export declare function createReplayEventFactory(startedAt: number, currentUrl: () => string): ReplayEventFactory;
27
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,aAAa,EAEb,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC;IACvD,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,GAAG,eAAe,CAAC;IAC9D,OAAO,CAAC,KAAK,EAAE,sBAAsB,GAAG,eAAe,CAAC;IACxD,KAAK,CACH,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,gBAAgB,CAAC,EAC1D,IAAI,CAAC,EAAE,MAAM,GACZ,aAAa,CAAC;IACjB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,gBAAgB,CAAC;IACvD,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAAC;CACnF;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,MAAM,GACvB,kBAAkB,CAqEpB"}
package/dist/events.js ADDED
@@ -0,0 +1,61 @@
1
+ export function createReplayEventFactory(startedAt, currentUrl) {
2
+ const base = (kind, payload) => {
3
+ const now = Date.now();
4
+ return {
5
+ kind,
6
+ timestamp: now,
7
+ sessionTimeMs: now - startedAt,
8
+ url: currentUrl(),
9
+ payload
10
+ };
11
+ };
12
+ return {
13
+ rrweb(payload) {
14
+ return base("rrweb", payload);
15
+ },
16
+ console(payload) {
17
+ return base("console", payload);
18
+ },
19
+ network(input) {
20
+ const pageUrl = currentUrl();
21
+ const url = new URL(input.url, pageUrl);
22
+ const payload = {
23
+ method: input.method.toUpperCase(),
24
+ url: `${url.origin}${url.pathname}`,
25
+ path: url.pathname,
26
+ failed: input.failed,
27
+ durationMs: Math.round(input.durationMs)
28
+ };
29
+ if (input.status !== undefined) {
30
+ payload.status = input.status;
31
+ }
32
+ if (input.ok !== undefined) {
33
+ payload.ok = input.ok;
34
+ }
35
+ if (input.requestId) {
36
+ payload.requestId = input.requestId;
37
+ }
38
+ if (input.error) {
39
+ payload.error = input.error;
40
+ }
41
+ return base("network", payload);
42
+ },
43
+ route(to, navigationType, from) {
44
+ const payload = {
45
+ to,
46
+ navigationType
47
+ };
48
+ if (from !== undefined) {
49
+ payload.from = from;
50
+ }
51
+ return base("route", payload);
52
+ },
53
+ viewport(snapshot) {
54
+ return base("viewport", snapshot);
55
+ },
56
+ lifecycle(name, data = {}) {
57
+ return base("lifecycle", { name, data });
58
+ }
59
+ };
60
+ }
61
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AA0CA,MAAM,UAAU,wBAAwB,CACtC,SAAiB,EACjB,UAAwB;IAExB,MAAM,IAAI,GAAG,CACX,IAAW,EACX,OAAiB,EACjB,EAAE;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,SAAS,EAAE,GAAG;YACd,aAAa,EAAE,GAAG,GAAG,SAAS;YAC9B,GAAG,EAAE,UAAU,EAAE;YACjB,OAAO;SACR,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,OAAO;YACX,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,CAAC,OAAO;YACb,OAAO,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,CAAC,KAAK;YACX,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,OAAO,GAA+B;gBAC1C,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE;gBAClC,GAAG,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE;gBACnC,IAAI,EAAE,GAAG,CAAC,QAAQ;gBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;aACzC,CAAC;YACF,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAChC,CAAC;YACD,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;YACxB,CAAC;YACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YACtC,CAAC;YACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YAC9B,CAAC;YAED,OAAO,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC;QAED,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI;YAC5B,MAAM,OAAO,GAA6B;gBACxC,EAAE;gBACF,cAAc;aACf,CAAC;YACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;QAED,QAAQ,CAAC,QAAQ;YACf,OAAO,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;QAED,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE;YACvB,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { type ChunkUpload, type UnifiedEventEnvelope } from "@panda-replay/shared";
2
+ export interface PandaReplayOptions {
3
+ ingestUrl: string;
4
+ publicKey: string;
5
+ releaseId?: string;
6
+ releaseVersion?: string;
7
+ gitSha?: string;
8
+ externalSessionId?: string;
9
+ subjectId?: string;
10
+ accountId?: string;
11
+ featureFlags?: Record<string, unknown>;
12
+ metadata?: Record<string, unknown>;
13
+ optOut?: boolean | (() => boolean);
14
+ flushIntervalMs?: number;
15
+ maxBatchEvents?: number;
16
+ disableRrweb?: boolean;
17
+ }
18
+ export interface PandaReplayClient {
19
+ readonly enabled: boolean;
20
+ readonly sessionId?: string;
21
+ addBreadcrumb(event: UnifiedEventEnvelope): void;
22
+ flush(options?: {
23
+ keepalive?: boolean;
24
+ }): Promise<void>;
25
+ stop(): Promise<void>;
26
+ }
27
+ export declare function startPandaReplay(options: PandaReplayOptions): Promise<PandaReplayClient>;
28
+ export declare function encodeChunk(events: UnifiedEventEnvelope[], sequence: number): Promise<ChunkUpload>;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAS9B,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACjD,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgB9F;AAqFD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,oBAAoB,EAAE,EAC9B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAEtB"}
package/dist/index.js ADDED
@@ -0,0 +1,105 @@
1
+ import { encodeReplayChunkUpload } from "@panda-replay/shared";
2
+ import { BrowserCapture } from "./browser-capture.js";
3
+ import { createReplayEventFactory } from "./events.js";
4
+ import { createReplayTransport } from "./transport.js";
5
+ export async function startPandaReplay(options) {
6
+ if (isOptedOut(options.optOut)) {
7
+ return disabledClient();
8
+ }
9
+ const baseUrl = trimSlash(options.ingestUrl);
10
+ const transport = createReplayTransport(baseUrl);
11
+ const config = await transport.fetchConfig(options.publicKey);
12
+ if (Math.random() > config.samplingRate) {
13
+ return disabledClient();
14
+ }
15
+ const session = await transport.createSession(options);
16
+ const client = new BrowserReplayClient(options, config, session, transport);
17
+ await client.start();
18
+ return client;
19
+ }
20
+ class BrowserReplayClient {
21
+ options;
22
+ config;
23
+ session;
24
+ transport;
25
+ enabled = true;
26
+ sessionId;
27
+ startedAt = Date.now();
28
+ events = [];
29
+ flushInterval;
30
+ eventFactory;
31
+ capture;
32
+ sequence = 0;
33
+ stopped = false;
34
+ constructor(options, config, session, transport) {
35
+ this.options = options;
36
+ this.config = config;
37
+ this.session = session;
38
+ this.transport = transport;
39
+ this.sessionId = session.sessionId;
40
+ this.eventFactory = createReplayEventFactory(this.startedAt, () => window.location.href);
41
+ this.capture = new BrowserCapture({
42
+ config: this.config,
43
+ eventFactory: this.eventFactory,
44
+ disableRrweb: this.options.disableRrweb === true,
45
+ addBreadcrumb: (event) => this.addBreadcrumb(event),
46
+ onPageHide: () => {
47
+ void this.flush({ keepalive: true });
48
+ void this.transport.finalizeSession(this.session, true);
49
+ }
50
+ });
51
+ this.flushInterval = setInterval(() => void this.flush(), options.flushIntervalMs ?? 5_000);
52
+ }
53
+ async start() {
54
+ await this.capture.start();
55
+ }
56
+ addBreadcrumb(event) {
57
+ this.events.push(event);
58
+ if (this.events.length >= (this.options.maxBatchEvents ?? 100)) {
59
+ void this.flush();
60
+ }
61
+ }
62
+ async flush(options = {}) {
63
+ if (!this.events.length || this.stopped) {
64
+ return;
65
+ }
66
+ const batch = this.events.splice(0, this.events.length);
67
+ const upload = await encodeChunk(batch, this.sequence++);
68
+ try {
69
+ await this.transport.uploadChunk(this.session, upload, options.keepalive === true);
70
+ }
71
+ catch (error) {
72
+ this.events.unshift(...batch);
73
+ throw error;
74
+ }
75
+ }
76
+ async stop() {
77
+ if (this.stopped) {
78
+ return;
79
+ }
80
+ this.capture.addLifecycle("sdk_stopped");
81
+ await this.flush({ keepalive: true });
82
+ this.stopped = true;
83
+ clearInterval(this.flushInterval);
84
+ this.capture.stop();
85
+ await this.transport.finalizeSession(this.session, true);
86
+ }
87
+ }
88
+ export async function encodeChunk(events, sequence) {
89
+ return encodeReplayChunkUpload(events, sequence);
90
+ }
91
+ function disabledClient() {
92
+ return {
93
+ enabled: false,
94
+ addBreadcrumb: () => undefined,
95
+ flush: async () => undefined,
96
+ stop: async () => undefined
97
+ };
98
+ }
99
+ function isOptedOut(optOut) {
100
+ return typeof optOut === "function" ? optOut() : optOut === true;
101
+ }
102
+ function trimSlash(input) {
103
+ return input.replace(/\/+$/, "");
104
+ }
105
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { ChunkUpload, SdkConfigResponse } from "@panda-replay/shared";
2
+ export interface ActiveSession {
3
+ sessionId: string;
4
+ ingestToken: string;
5
+ }
6
+ export interface SessionCreateOptions {
7
+ publicKey: string;
8
+ releaseId?: string;
9
+ releaseVersion?: string;
10
+ gitSha?: string;
11
+ externalSessionId?: string;
12
+ subjectId?: string;
13
+ accountId?: string;
14
+ featureFlags?: Record<string, unknown>;
15
+ metadata?: Record<string, unknown>;
16
+ }
17
+ export interface ReplayTransport {
18
+ fetchConfig(publicKey: string): Promise<SdkConfigResponse>;
19
+ createSession(options: SessionCreateOptions): Promise<ActiveSession>;
20
+ uploadChunk(session: ActiveSession, upload: ChunkUpload, keepalive?: boolean): Promise<void>;
21
+ finalizeSession(session: ActiveSession, keepalive?: boolean): Promise<void>;
22
+ }
23
+ export declare function createReplayTransport(baseUrl: string): ReplayTransport;
24
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC3D,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACrE,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7E;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CA+EtE"}
@@ -0,0 +1,66 @@
1
+ export function createReplayTransport(baseUrl) {
2
+ return {
3
+ async fetchConfig(publicKey) {
4
+ const response = await fetch(`${baseUrl}/v1/sdk/config?publicKey=${encodeURIComponent(publicKey)}`);
5
+ if (!response.ok) {
6
+ throw new Error(`panda replay config fetch failed: ${response.status}`);
7
+ }
8
+ return (await response.json());
9
+ },
10
+ async createSession(options) {
11
+ const response = await fetch(`${baseUrl}/v1/ingest/sessions`, {
12
+ method: "POST",
13
+ headers: { "content-type": "application/json" },
14
+ body: JSON.stringify({
15
+ publicKey: options.publicKey,
16
+ releaseId: options.releaseId,
17
+ releaseVersion: options.releaseVersion,
18
+ gitSha: options.gitSha,
19
+ externalSessionId: options.externalSessionId,
20
+ subjectId: options.subjectId,
21
+ accountId: options.accountId,
22
+ route: window.location.href,
23
+ viewport: {
24
+ width: window.innerWidth,
25
+ height: window.innerHeight,
26
+ devicePixelRatio: window.devicePixelRatio
27
+ },
28
+ featureFlags: options.featureFlags ?? {},
29
+ metadata: options.metadata ?? {}
30
+ })
31
+ });
32
+ if (!response.ok) {
33
+ throw new Error(`panda replay session create failed: ${response.status}`);
34
+ }
35
+ const body = (await response.json());
36
+ return {
37
+ sessionId: body.session.id,
38
+ ingestToken: body.ingestToken
39
+ };
40
+ },
41
+ async uploadChunk(session, upload, keepalive = false) {
42
+ const response = await fetch(`${baseUrl}/v1/ingest/sessions/${session.sessionId}/chunks`, {
43
+ method: "POST",
44
+ headers: {
45
+ "content-type": "application/json",
46
+ authorization: `Bearer ${session.ingestToken}`
47
+ },
48
+ body: JSON.stringify(upload),
49
+ keepalive
50
+ });
51
+ if (!response.ok) {
52
+ throw new Error(`panda replay chunk upload failed: ${response.status}`);
53
+ }
54
+ },
55
+ async finalizeSession(session, keepalive = false) {
56
+ await fetch(`${baseUrl}/v1/ingest/sessions/${session.sessionId}/finalize`, {
57
+ method: "POST",
58
+ headers: {
59
+ authorization: `Bearer ${session.ingestToken}`
60
+ },
61
+ keepalive
62
+ });
63
+ }
64
+ };
65
+ }
66
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@panda-replay/sdk",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "files": [
8
+ "dist/**/*.d.ts",
9
+ "dist/**/*.d.ts.map",
10
+ "dist/**/*.js",
11
+ "dist/**/*.js.map"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "dependencies": {
20
+ "rrweb": "^2.0.0-alpha.18",
21
+ "@panda-replay/shared": "0.1.0"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.9.3"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -p tsconfig.json",
28
+ "typecheck": "tsc -p tsconfig.json --noEmit"
29
+ }
30
+ }