@meet-sudo/sdk 0.1.0 → 0.1.2

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/dist/cli.js ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/cli.ts
5
+ var import_crypto = require("crypto");
6
+ var import_os = require("os");
7
+ var VERSION = "0.1.2";
8
+ var API_URL = "https://api.meetsudo.com";
9
+ var colors = {
10
+ reset: "\x1B[0m",
11
+ bold: "\x1B[1m",
12
+ green: "\x1B[32m",
13
+ red: "\x1B[31m",
14
+ yellow: "\x1B[33m",
15
+ cyan: "\x1B[36m",
16
+ dim: "\x1B[2m"
17
+ };
18
+ function log(msg) {
19
+ console.log(msg);
20
+ }
21
+ function success(msg) {
22
+ console.log(`${colors.green}\u2713${colors.reset} ${msg}`);
23
+ }
24
+ function error(msg) {
25
+ console.log(`${colors.red}\u2717${colors.reset} ${msg}`);
26
+ }
27
+ function info(msg) {
28
+ console.log(`${colors.cyan}\u2139${colors.reset} ${msg}`);
29
+ }
30
+ function header(msg) {
31
+ console.log(`
32
+ ${colors.bold}${msg}${colors.reset}`);
33
+ }
34
+ function generateInstallId() {
35
+ const data = `${(0, import_os.hostname)()}-${(0, import_os.platform)()}-${(0, import_os.arch)()}-${process.env.USER || "unknown"}`;
36
+ return (0, import_crypto.createHash)("sha256").update(data).digest("hex").substring(0, 12);
37
+ }
38
+ async function checkApiConnectivity() {
39
+ const start = Date.now();
40
+ try {
41
+ const controller = new AbortController();
42
+ const timeout = setTimeout(() => controller.abort(), 5e3);
43
+ const res = await fetch(`${API_URL}/health`, {
44
+ signal: controller.signal
45
+ });
46
+ clearTimeout(timeout);
47
+ const latency = Date.now() - start;
48
+ if (res.ok) {
49
+ return { ok: true, latency };
50
+ }
51
+ return { ok: false, error: `HTTP ${res.status}` };
52
+ } catch (err) {
53
+ return {
54
+ ok: false,
55
+ error: err instanceof Error ? err.message : "Connection failed"
56
+ };
57
+ }
58
+ }
59
+ async function logInstall(installId, nodeVersion, osInfo) {
60
+ try {
61
+ const res = await fetch(`${API_URL}/sdk/doctor`, {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({
65
+ install_id: installId,
66
+ sdk_version: VERSION,
67
+ node_version: nodeVersion,
68
+ os: osInfo,
69
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
70
+ })
71
+ });
72
+ return res.ok;
73
+ } catch {
74
+ return false;
75
+ }
76
+ }
77
+ async function doctor() {
78
+ log(`
79
+ ${colors.bold}MeetSudo SDK Doctor${colors.reset} ${colors.dim}v${VERSION}${colors.reset}
80
+ `);
81
+ header("Environment");
82
+ const nodeVersion = process.version;
83
+ const osInfo = `${(0, import_os.platform)()} ${(0, import_os.arch)()} (${(0, import_os.release)()})`;
84
+ log(` Node.js: ${nodeVersion}`);
85
+ log(` OS: ${osInfo}`);
86
+ log(` Working dir: ${process.cwd()}`);
87
+ header("API Connectivity");
88
+ const apiCheck = await checkApiConnectivity();
89
+ if (apiCheck.ok) {
90
+ success(`api.meetsudo.com reachable (${apiCheck.latency}ms)`);
91
+ } else {
92
+ error(`api.meetsudo.com unreachable: ${apiCheck.error}`);
93
+ log(`
94
+ ${colors.yellow}Possible causes:${colors.reset}`);
95
+ log(" - No internet connection");
96
+ log(" - Firewall blocking outbound requests");
97
+ log(" - API is temporarily down");
98
+ process.exit(1);
99
+ }
100
+ header("Install Registration");
101
+ const installId = generateInstallId();
102
+ const logged = await logInstall(installId, nodeVersion, osInfo);
103
+ if (logged) {
104
+ success(`Install logged: ${colors.cyan}${installId}${colors.reset}`);
105
+ } else {
106
+ info(`Install ID: ${colors.cyan}${installId}${colors.reset} ${colors.dim}(offline)${colors.reset}`);
107
+ }
108
+ header("Next Steps");
109
+ log(`
110
+ 1. Get your API key at ${colors.cyan}https://www.meetsudo.com/signup${colors.reset}
111
+
112
+ 2. Add to your app:
113
+
114
+ ${colors.dim}import { meetsudo } from '@meet-sudo/sdk';
115
+
116
+ meetsudo.init({ apiKey: 'YOUR_API_KEY' });${colors.reset}
117
+
118
+ 3. See events in your dashboard at ${colors.cyan}https://www.meetsudo.com/inbox${colors.reset}
119
+ `);
120
+ log(`${colors.green}All checks passed!${colors.reset}
121
+ `);
122
+ }
123
+ function showHelp() {
124
+ log(`
125
+ ${colors.bold}MeetSudo SDK CLI${colors.reset} v${VERSION}
126
+
127
+ ${colors.bold}Usage:${colors.reset}
128
+ npx @meet-sudo/sdk <command>
129
+
130
+ ${colors.bold}Commands:${colors.reset}
131
+ doctor Check environment and API connectivity
132
+ version Show SDK version
133
+ help Show this help message
134
+
135
+ ${colors.bold}Examples:${colors.reset}
136
+ npx @meet-sudo/sdk doctor
137
+ npx @meet-sudo/sdk version
138
+
139
+ ${colors.bold}Documentation:${colors.reset}
140
+ https://www.meetsudo.com/docs
141
+ `);
142
+ }
143
+ function showVersion() {
144
+ log(`@meet-sudo/sdk v${VERSION}`);
145
+ }
146
+ var args = process.argv.slice(2);
147
+ var command = args[0] || "doctor";
148
+ switch (command) {
149
+ case "doctor":
150
+ doctor();
151
+ break;
152
+ case "version":
153
+ case "-v":
154
+ case "--version":
155
+ showVersion();
156
+ break;
157
+ case "help":
158
+ case "-h":
159
+ case "--help":
160
+ showHelp();
161
+ break;
162
+ default:
163
+ error(`Unknown command: ${command}`);
164
+ showHelp();
165
+ process.exit(1);
166
+ }
package/dist/index.d.mts CHANGED
@@ -73,6 +73,9 @@ declare class MeetSudo {
73
73
  private shouldSampleReplay;
74
74
  private startReplay;
75
75
  private initRrweb;
76
+ private setupActivityTracking;
77
+ private pauseReplayDueToInactivity;
78
+ private resumeReplay;
76
79
  private isSensitiveInput;
77
80
  private flushReplayChunk;
78
81
  private setupRageClickDetection;
package/dist/index.d.ts CHANGED
@@ -73,6 +73,9 @@ declare class MeetSudo {
73
73
  private shouldSampleReplay;
74
74
  private startReplay;
75
75
  private initRrweb;
76
+ private setupActivityTracking;
77
+ private pauseReplayDueToInactivity;
78
+ private resumeReplay;
76
79
  private isSensitiveInput;
77
80
  private flushReplayChunk;
78
81
  private setupRageClickDetection;
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ module.exports = __toCommonJS(index_exports);
29
29
  var STORAGE_KEY = "meetsudo_anon_id";
30
30
  var FLUSH_INTERVAL = 5e3;
31
31
  var REPLAY_FLUSH_INTERVAL = 1e4;
32
+ var INACTIVITY_TIMEOUT = 6e4;
32
33
  var MeetSudo = class {
33
34
  constructor() {
34
35
  this.state = {
@@ -55,7 +56,10 @@ var MeetSudo = class {
55
56
  lastClickTime: 0,
56
57
  lastClickTarget: null,
57
58
  clickCount: 0,
58
- capturedEmails: {}
59
+ capturedEmails: {},
60
+ lastActivityTime: Date.now(),
61
+ inactivityTimer: null,
62
+ replayPaused: false
59
63
  };
60
64
  this.config = null;
61
65
  }
@@ -333,6 +337,88 @@ var MeetSudo = class {
333
337
  }
334
338
  });
335
339
  this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);
340
+ this.setupActivityTracking();
341
+ }
342
+ setupActivityTracking() {
343
+ const activityEvents = ["mousemove", "keydown", "click", "scroll", "touchstart"];
344
+ const handleActivity = () => {
345
+ this.state.lastActivityTime = Date.now();
346
+ if (this.state.replayPaused) {
347
+ this.resumeReplay();
348
+ }
349
+ if (this.state.inactivityTimer) {
350
+ clearTimeout(this.state.inactivityTimer);
351
+ }
352
+ this.state.inactivityTimer = setTimeout(() => {
353
+ this.pauseReplayDueToInactivity();
354
+ }, INACTIVITY_TIMEOUT);
355
+ };
356
+ activityEvents.forEach((event) => {
357
+ document.addEventListener(event, handleActivity, { passive: true });
358
+ });
359
+ this.state.inactivityTimer = setTimeout(() => {
360
+ this.pauseReplayDueToInactivity();
361
+ }, INACTIVITY_TIMEOUT);
362
+ }
363
+ pauseReplayDueToInactivity() {
364
+ if (this.state.replayPaused || !this.state.replaySessionId) return;
365
+ this.state.replayPaused = true;
366
+ if (this.state.replayStopFn) {
367
+ this.state.replayStopFn();
368
+ this.state.replayStopFn = null;
369
+ }
370
+ this.flushReplayChunk();
371
+ if (this.state.replayFlushTimer) {
372
+ clearInterval(this.state.replayFlushTimer);
373
+ this.state.replayFlushTimer = null;
374
+ }
375
+ if (this.state.apiKey) {
376
+ this.api("/widget/replay/end", {
377
+ anonymous_id: this.state.anonId,
378
+ session_id: this.state.replaySessionId,
379
+ ended_at: (/* @__PURE__ */ new Date()).toISOString(),
380
+ event_count: this.state.replayTotalEvents,
381
+ error_count: this.state.replayErrorCount,
382
+ rage_click_count: this.state.replayRageClickCount,
383
+ end_reason: "inactivity"
384
+ }).catch(() => {
385
+ });
386
+ }
387
+ }
388
+ resumeReplay() {
389
+ if (!this.state.replayPaused || !this.state.features?.replay_enabled) return;
390
+ this.state.replayPaused = false;
391
+ this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();
392
+ this.state.replaySequence = 0;
393
+ this.state.replayEvents = [];
394
+ this.state.replayTotalEvents = 0;
395
+ this.state.replayStartedAt = (/* @__PURE__ */ new Date()).toISOString();
396
+ this.state.replayErrorCount = 0;
397
+ this.state.replayRageClickCount = 0;
398
+ if (window.rrweb?.record) {
399
+ this.state.replayStopFn = window.rrweb.record({
400
+ emit: (event) => {
401
+ this.state.replayEvents.push(event);
402
+ this.state.replayTotalEvents++;
403
+ },
404
+ maskAllInputs: false,
405
+ maskInputFn: (text, element) => {
406
+ if (this.isSensitiveInput(element)) {
407
+ return "*".repeat(text.length || 8);
408
+ }
409
+ return text;
410
+ },
411
+ blockSelector: ".meetsudo-no-record, [data-meetsudo-no-record]",
412
+ inlineStylesheet: true,
413
+ sampling: {
414
+ mousemove: 50,
415
+ mouseInteraction: true,
416
+ scroll: 150,
417
+ input: "last"
418
+ }
419
+ });
420
+ this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);
421
+ }
336
422
  }
337
423
  isSensitiveInput(el) {
338
424
  if (!el) return true;
@@ -346,7 +432,7 @@ var MeetSudo = class {
346
432
  return sensitivePatterns.some((p) => p.test(identifiers));
347
433
  }
348
434
  flushReplayChunk() {
349
- if (!this.state.replayEvents.length) return;
435
+ if (!this.state.replayEvents.length || this.state.replayPaused) return;
350
436
  const events = this.state.replayEvents.splice(0);
351
437
  const seq = this.state.replaySequence++;
352
438
  const payload = {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/sdk.ts"],"sourcesContent":["export { MeetSudo } from \"./sdk\";\nexport type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n ChatAction,\n} from \"./types\";\n\n// Default instance for convenience\nimport { MeetSudo } from \"./sdk\";\nexport const meetsudo = new MeetSudo();\n","import type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n Features,\n InitResponse,\n IdentifyResponse,\n ChatAction,\n} from \"./types\";\n\nconst STORAGE_KEY = \"meetsudo_anon_id\";\nconst FLUSH_INTERVAL = 5000;\nconst REPLAY_FLUSH_INTERVAL = 10000;\n\ninterface EventData {\n name: string;\n properties: EventProperties;\n page_url: string;\n timestamp: string;\n}\n\ninterface State {\n apiKey: string | null;\n apiUrl: string;\n widgetUrl: string;\n anonId: string | null;\n custId: string | null;\n features: Features | null;\n workspaceName: string | null;\n initialized: boolean;\n iframe: HTMLIFrameElement | null;\n eventQ: EventData[];\n flushTimer: ReturnType<typeof setInterval> | null;\n replaySessionId: string | null;\n replaySequence: number;\n replayEvents: unknown[];\n replayFlushTimer: ReturnType<typeof setInterval> | null;\n replayStopFn: (() => void) | null;\n replayTotalEvents: number;\n replayStartedAt: string | null;\n replayRageClickCount: number;\n replayErrorCount: number;\n lastClickTime: number;\n lastClickTarget: EventTarget | null;\n clickCount: number;\n capturedEmails: Record<string, boolean>;\n}\n\nexport class MeetSudo {\n private state: State = {\n apiKey: null,\n apiUrl: \"https://api.meetsudo.com\",\n widgetUrl: \"https://widget.meetsudo.com\",\n anonId: null,\n custId: null,\n features: null,\n workspaceName: null,\n initialized: false,\n iframe: null,\n eventQ: [],\n flushTimer: null,\n replaySessionId: null,\n replaySequence: 0,\n replayEvents: [],\n replayFlushTimer: null,\n replayStopFn: null,\n replayTotalEvents: 0,\n replayStartedAt: null,\n replayRageClickCount: 0,\n replayErrorCount: 0,\n lastClickTime: 0,\n lastClickTarget: null,\n clickCount: 0,\n capturedEmails: {},\n };\n\n private config: MeetSudoConfig | null = null;\n\n /**\n * Initialize the MeetSudo SDK\n */\n async init(config: MeetSudoConfig): Promise<void> {\n if (!config.apiKey) {\n throw new Error(\"MeetSudo: apiKey is required\");\n }\n\n this.config = config;\n this.state.apiKey = config.apiKey;\n this.state.apiUrl = config.apiUrl || \"https://api.meetsudo.com\";\n this.state.widgetUrl = config.widgetUrl || \"https://widget.meetsudo.com\";\n this.state.anonId = this.getAnonId();\n\n try {\n const res = await this.api<InitResponse>(\"/widget/init\", {\n anonymous_id: this.state.anonId,\n url: window.location.href,\n referrer: document.referrer,\n });\n\n this.state.custId = res.customer_id;\n this.state.features = res.features;\n this.state.workspaceName = res.workspace_name;\n this.state.initialized = true;\n\n // Create chat iframe if enabled\n if (res.features.chat_enabled && !config.disableChat) {\n this.createIframe(res);\n }\n\n // Start event tracking if enabled\n if (res.features.events_enabled && !config.disableEvents) {\n this.state.flushTimer = setInterval(() => this.flushEvents(), FLUSH_INTERVAL);\n if (res.features.events_auto_page && !config.disableAutoPageView) {\n this.page();\n }\n this.setupEmailCapture();\n }\n\n // Start session replay if enabled and sampled in\n if (this.shouldSampleReplay() && !config.disableReplay) {\n this.startReplay();\n }\n\n // Setup beforeunload handler\n window.addEventListener(\"beforeunload\", () => this.handleUnload());\n } catch (error) {\n console.error(\"MeetSudo: init failed\", error);\n throw error;\n }\n }\n\n /**\n * Identify a user\n */\n async identify(userId: string, traits?: UserTraits): Promise<void> {\n if (!this.state.initialized) {\n console.warn(\"MeetSudo: call init() before identify()\");\n return;\n }\n\n try {\n const res = await this.api<IdentifyResponse>(\"/widget/identify\", {\n anonymous_id: this.state.anonId,\n external_id: userId,\n properties: traits || {},\n });\n\n this.state.custId = res.customer_id;\n\n // Notify chat iframe about identity change\n if (this.state.iframe?.contentWindow) {\n this.state.iframe.contentWindow.postMessage(\n {\n type: \"fi:identify\",\n customerId: res.customer_id,\n merged: res.merged,\n },\n \"*\"\n );\n }\n } catch (error) {\n console.error(\"MeetSudo: identify failed\", error);\n }\n }\n\n /**\n * Track a custom event\n */\n track(eventName: string, properties?: EventProperties): void {\n if (!this.state.initialized || !this.state.features?.events_enabled) {\n return;\n }\n\n this.state.eventQ.push({\n name: eventName,\n properties: properties || {},\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Track a page view\n */\n page(properties?: PageProperties): void {\n const props: PageProperties = {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n ...properties,\n };\n this.track(\"page_view\", props);\n }\n\n /**\n * Control the chat widget\n */\n chat(action: ChatAction): void {\n if (!this.state.iframe?.contentWindow) return;\n\n switch (action) {\n case \"open\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"open\" }, \"*\");\n this.state.iframe.style.width = \"400px\";\n this.state.iframe.style.height = \"560px\";\n break;\n case \"close\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"close\" }, \"*\");\n this.state.iframe.style.width = \"80px\";\n this.state.iframe.style.height = \"80px\";\n break;\n case \"hide\":\n this.state.iframe.style.display = \"none\";\n break;\n case \"show\":\n this.state.iframe.style.display = \"\";\n break;\n }\n }\n\n /**\n * Check if SDK is initialized\n */\n isInitialized(): boolean {\n return this.state.initialized;\n }\n\n /**\n * Get the anonymous ID\n */\n getAnonymousId(): string | null {\n return this.state.anonId;\n }\n\n /**\n * Get the customer ID (after identify)\n */\n getCustomerId(): string | null {\n return this.state.custId;\n }\n\n // Private methods\n\n private getAnonId(): string {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) return stored;\n } catch {\n /* private browsing */\n }\n\n const id = crypto.randomUUID?.() || this.generateUUID();\n try {\n localStorage.setItem(STORAGE_KEY, id);\n } catch {\n /* ignore */\n }\n return id;\n }\n\n private generateUUID(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n\n private async api<T>(path: string, data: unknown): Promise<T> {\n const res = await fetch(this.state.apiUrl + path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.state.apiKey!,\n },\n body: JSON.stringify(data),\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n\n return res.json();\n }\n\n private createIframe(initData: InitResponse): void {\n if (this.state.iframe) return;\n\n const pos = this.state.features?.chat_position || \"bottom-right\";\n const iframe = document.createElement(\"iframe\");\n iframe.id = \"meetsudo-widget\";\n const posCSS = pos === \"bottom-left\" ? \"left:0;\" : \"right:0;\";\n iframe.style.cssText = `position:fixed;bottom:0;${posCSS}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`;\n iframe.allow = \"clipboard-write\";\n iframe.src = this.state.widgetUrl;\n\n document.body.appendChild(iframe);\n this.state.iframe = iframe;\n\n iframe.onload = () => {\n iframe.contentWindow?.postMessage(\n {\n type: \"fi:config\",\n apiKey: this.state.apiKey,\n apiUrl: this.state.apiUrl,\n anonymousId: this.state.anonId,\n customerId: this.state.custId,\n workspaceName: this.state.workspaceName,\n features: this.state.features,\n conversationId: initData.open_conversation_id,\n messages: initData.messages || [],\n },\n \"*\"\n );\n };\n\n window.addEventListener(\"message\", (e) => {\n if (e.data?.type === \"fi:resize\") {\n if (e.data.state === \"open\") {\n iframe.style.width = \"400px\";\n iframe.style.height = \"560px\";\n } else {\n iframe.style.width = \"80px\";\n iframe.style.height = \"80px\";\n }\n }\n });\n }\n\n private flushEvents(): void {\n if (!this.state.eventQ.length) return;\n\n const batch = this.state.eventQ.splice(0);\n this.api(\"/widget/events\", {\n anonymous_id: this.state.anonId,\n events: batch,\n }).catch(() => {\n // Put events back on failure\n this.state.eventQ = batch.concat(this.state.eventQ);\n });\n }\n\n private shouldSampleReplay(): boolean {\n if (!this.state.features?.replay_enabled) return false;\n return Math.random() < (this.state.features.replay_sample_rate || 0);\n }\n\n private startReplay(): void {\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n this.setupRageClickDetection();\n this.setupErrorCapture();\n\n // Load rrweb dynamically\n const script = document.createElement(\"script\");\n script.type = \"module\";\n script.src = this.state.widgetUrl.replace(/\\/?(index\\.html)?$/, \"\") + \"/replay.js\";\n document.head.appendChild(script);\n\n // Wait for rrweb to load\n let attempts = 0;\n const checkRrweb = setInterval(() => {\n attempts++;\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n clearInterval(checkRrweb);\n this.initRrweb();\n } else if (attempts > 50) {\n clearInterval(checkRrweb);\n console.warn(\"MeetSudo: replay failed to load\");\n }\n }, 100);\n }\n\n private initRrweb(): void {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n }\n\n private isSensitiveInput(el: HTMLElement): boolean {\n if (!el) return true;\n const input = el as HTMLInputElement;\n const type = (input.type || \"\").toLowerCase();\n const name = (input.name || \"\").toLowerCase();\n const id = (input.id || \"\").toLowerCase();\n\n if (type === \"password\") return true;\n\n const sensitivePatterns = [/password/i, /card/i, /cvv/i, /cvc/i, /ssn/i, /secret/i, /token/i];\n const identifiers = name + \" \" + id;\n return sensitivePatterns.some((p) => p.test(identifiers));\n }\n\n private flushReplayChunk(): void {\n if (!this.state.replayEvents.length) return;\n\n const events = this.state.replayEvents.splice(0);\n const seq = this.state.replaySequence++;\n\n const payload: Record<string, unknown> = {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n sequence: seq,\n events,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n };\n\n if (seq === 0) {\n payload.page_url = window.location.href;\n payload.user_agent = navigator.userAgent;\n payload.screen_width = window.innerWidth;\n payload.screen_height = window.innerHeight;\n payload.started_at = this.state.replayStartedAt;\n }\n\n this.api(\"/widget/replay/chunk\", payload).catch(() => {\n this.state.replayEvents = events.concat(this.state.replayEvents);\n this.state.replaySequence--;\n });\n }\n\n private setupRageClickDetection(): void {\n document.addEventListener(\n \"click\",\n (e) => {\n if (!this.state.replaySessionId) return;\n\n const now = Date.now();\n const target = e.target;\n\n if (target === this.state.lastClickTarget && now - this.state.lastClickTime < 500) {\n this.state.clickCount++;\n if (this.state.clickCount >= 3) {\n this.state.replayRageClickCount++;\n this.state.clickCount = 0;\n this.track(\"rage_click\", { page_url: window.location.href });\n }\n } else {\n this.state.clickCount = 1;\n }\n\n this.state.lastClickTime = now;\n this.state.lastClickTarget = target;\n },\n true\n );\n }\n\n private setupErrorCapture(): void {\n window.onerror = (message, source, lineno, colno) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n this.track(\"js_error\", {\n message: String(message).substring(0, 500),\n source: source || \"\",\n lineno: lineno || 0,\n });\n }\n return false;\n };\n\n window.addEventListener(\"unhandledrejection\", (e) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n const message = e.reason instanceof Error ? e.reason.message : String(e.reason);\n this.track(\"js_error\", { message: message.substring(0, 500), type: \"unhandledrejection\" });\n }\n });\n }\n\n private setupEmailCapture(): void {\n document.addEventListener(\n \"blur\",\n (e) => {\n const el = e.target as HTMLInputElement;\n if (!el || el.tagName !== \"INPUT\") return;\n\n const type = (el.type || \"\").toLowerCase();\n const name = (el.name || \"\").toLowerCase();\n if (type === \"email\" || /email/.test(name)) {\n const value = el.value?.trim();\n if (value && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) && !this.state.capturedEmails[value]) {\n this.state.capturedEmails[value] = true;\n this.track(\"email_captured\", { email: value });\n }\n }\n },\n true\n );\n }\n\n private handleUnload(): void {\n if (this.state.flushTimer) {\n clearInterval(this.state.flushTimer);\n }\n\n // Flush remaining events\n if (this.state.eventQ.length && this.state.apiKey) {\n const apiKey = this.state.apiKey;\n try {\n fetch(this.state.apiUrl + \"/widget/events\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": apiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n events: this.state.eventQ,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n\n // End replay\n if (this.state.replaySessionId && this.state.apiKey) {\n const replayApiKey = this.state.apiKey;\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n }\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n }\n\n try {\n fetch(this.state.apiUrl + \"/widget/replay/end\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": replayApiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/sdk.ts"],"sourcesContent":["export { MeetSudo } from \"./sdk\";\nexport type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n ChatAction,\n} from \"./types\";\n\n// Default instance for convenience\nimport { MeetSudo } from \"./sdk\";\nexport const meetsudo = new MeetSudo();\n","import type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n Features,\n InitResponse,\n IdentifyResponse,\n ChatAction,\n} from \"./types\";\n\nconst STORAGE_KEY = \"meetsudo_anon_id\";\nconst FLUSH_INTERVAL = 5000;\nconst REPLAY_FLUSH_INTERVAL = 10000;\nconst INACTIVITY_TIMEOUT = 60000; // 1 minute\n\ninterface EventData {\n name: string;\n properties: EventProperties;\n page_url: string;\n timestamp: string;\n}\n\ninterface State {\n apiKey: string | null;\n apiUrl: string;\n widgetUrl: string;\n anonId: string | null;\n custId: string | null;\n features: Features | null;\n workspaceName: string | null;\n initialized: boolean;\n iframe: HTMLIFrameElement | null;\n eventQ: EventData[];\n flushTimer: ReturnType<typeof setInterval> | null;\n replaySessionId: string | null;\n replaySequence: number;\n replayEvents: unknown[];\n replayFlushTimer: ReturnType<typeof setInterval> | null;\n replayStopFn: (() => void) | null;\n replayTotalEvents: number;\n replayStartedAt: string | null;\n replayRageClickCount: number;\n replayErrorCount: number;\n lastClickTime: number;\n lastClickTarget: EventTarget | null;\n clickCount: number;\n capturedEmails: Record<string, boolean>;\n lastActivityTime: number;\n inactivityTimer: ReturnType<typeof setTimeout> | null;\n replayPaused: boolean;\n}\n\nexport class MeetSudo {\n private state: State = {\n apiKey: null,\n apiUrl: \"https://api.meetsudo.com\",\n widgetUrl: \"https://widget.meetsudo.com\",\n anonId: null,\n custId: null,\n features: null,\n workspaceName: null,\n initialized: false,\n iframe: null,\n eventQ: [],\n flushTimer: null,\n replaySessionId: null,\n replaySequence: 0,\n replayEvents: [],\n replayFlushTimer: null,\n replayStopFn: null,\n replayTotalEvents: 0,\n replayStartedAt: null,\n replayRageClickCount: 0,\n replayErrorCount: 0,\n lastClickTime: 0,\n lastClickTarget: null,\n clickCount: 0,\n capturedEmails: {},\n lastActivityTime: Date.now(),\n inactivityTimer: null,\n replayPaused: false,\n };\n\n private config: MeetSudoConfig | null = null;\n\n /**\n * Initialize the MeetSudo SDK\n */\n async init(config: MeetSudoConfig): Promise<void> {\n if (!config.apiKey) {\n throw new Error(\"MeetSudo: apiKey is required\");\n }\n\n this.config = config;\n this.state.apiKey = config.apiKey;\n this.state.apiUrl = config.apiUrl || \"https://api.meetsudo.com\";\n this.state.widgetUrl = config.widgetUrl || \"https://widget.meetsudo.com\";\n this.state.anonId = this.getAnonId();\n\n try {\n const res = await this.api<InitResponse>(\"/widget/init\", {\n anonymous_id: this.state.anonId,\n url: window.location.href,\n referrer: document.referrer,\n });\n\n this.state.custId = res.customer_id;\n this.state.features = res.features;\n this.state.workspaceName = res.workspace_name;\n this.state.initialized = true;\n\n // Create chat iframe if enabled\n if (res.features.chat_enabled && !config.disableChat) {\n this.createIframe(res);\n }\n\n // Start event tracking if enabled\n if (res.features.events_enabled && !config.disableEvents) {\n this.state.flushTimer = setInterval(() => this.flushEvents(), FLUSH_INTERVAL);\n if (res.features.events_auto_page && !config.disableAutoPageView) {\n this.page();\n }\n this.setupEmailCapture();\n }\n\n // Start session replay if enabled and sampled in\n if (this.shouldSampleReplay() && !config.disableReplay) {\n this.startReplay();\n }\n\n // Setup beforeunload handler\n window.addEventListener(\"beforeunload\", () => this.handleUnload());\n } catch (error) {\n console.error(\"MeetSudo: init failed\", error);\n throw error;\n }\n }\n\n /**\n * Identify a user\n */\n async identify(userId: string, traits?: UserTraits): Promise<void> {\n if (!this.state.initialized) {\n console.warn(\"MeetSudo: call init() before identify()\");\n return;\n }\n\n try {\n const res = await this.api<IdentifyResponse>(\"/widget/identify\", {\n anonymous_id: this.state.anonId,\n external_id: userId,\n properties: traits || {},\n });\n\n this.state.custId = res.customer_id;\n\n // Notify chat iframe about identity change\n if (this.state.iframe?.contentWindow) {\n this.state.iframe.contentWindow.postMessage(\n {\n type: \"fi:identify\",\n customerId: res.customer_id,\n merged: res.merged,\n },\n \"*\"\n );\n }\n } catch (error) {\n console.error(\"MeetSudo: identify failed\", error);\n }\n }\n\n /**\n * Track a custom event\n */\n track(eventName: string, properties?: EventProperties): void {\n if (!this.state.initialized || !this.state.features?.events_enabled) {\n return;\n }\n\n this.state.eventQ.push({\n name: eventName,\n properties: properties || {},\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Track a page view\n */\n page(properties?: PageProperties): void {\n const props: PageProperties = {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n ...properties,\n };\n this.track(\"page_view\", props);\n }\n\n /**\n * Control the chat widget\n */\n chat(action: ChatAction): void {\n if (!this.state.iframe?.contentWindow) return;\n\n switch (action) {\n case \"open\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"open\" }, \"*\");\n this.state.iframe.style.width = \"400px\";\n this.state.iframe.style.height = \"560px\";\n break;\n case \"close\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"close\" }, \"*\");\n this.state.iframe.style.width = \"80px\";\n this.state.iframe.style.height = \"80px\";\n break;\n case \"hide\":\n this.state.iframe.style.display = \"none\";\n break;\n case \"show\":\n this.state.iframe.style.display = \"\";\n break;\n }\n }\n\n /**\n * Check if SDK is initialized\n */\n isInitialized(): boolean {\n return this.state.initialized;\n }\n\n /**\n * Get the anonymous ID\n */\n getAnonymousId(): string | null {\n return this.state.anonId;\n }\n\n /**\n * Get the customer ID (after identify)\n */\n getCustomerId(): string | null {\n return this.state.custId;\n }\n\n // Private methods\n\n private getAnonId(): string {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) return stored;\n } catch {\n /* private browsing */\n }\n\n const id = crypto.randomUUID?.() || this.generateUUID();\n try {\n localStorage.setItem(STORAGE_KEY, id);\n } catch {\n /* ignore */\n }\n return id;\n }\n\n private generateUUID(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n\n private async api<T>(path: string, data: unknown): Promise<T> {\n const res = await fetch(this.state.apiUrl + path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.state.apiKey!,\n },\n body: JSON.stringify(data),\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n\n return res.json();\n }\n\n private createIframe(initData: InitResponse): void {\n if (this.state.iframe) return;\n\n const pos = this.state.features?.chat_position || \"bottom-right\";\n const iframe = document.createElement(\"iframe\");\n iframe.id = \"meetsudo-widget\";\n const posCSS = pos === \"bottom-left\" ? \"left:0;\" : \"right:0;\";\n iframe.style.cssText = `position:fixed;bottom:0;${posCSS}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`;\n iframe.allow = \"clipboard-write\";\n iframe.src = this.state.widgetUrl;\n\n document.body.appendChild(iframe);\n this.state.iframe = iframe;\n\n iframe.onload = () => {\n iframe.contentWindow?.postMessage(\n {\n type: \"fi:config\",\n apiKey: this.state.apiKey,\n apiUrl: this.state.apiUrl,\n anonymousId: this.state.anonId,\n customerId: this.state.custId,\n workspaceName: this.state.workspaceName,\n features: this.state.features,\n conversationId: initData.open_conversation_id,\n messages: initData.messages || [],\n },\n \"*\"\n );\n };\n\n window.addEventListener(\"message\", (e) => {\n if (e.data?.type === \"fi:resize\") {\n if (e.data.state === \"open\") {\n iframe.style.width = \"400px\";\n iframe.style.height = \"560px\";\n } else {\n iframe.style.width = \"80px\";\n iframe.style.height = \"80px\";\n }\n }\n });\n }\n\n private flushEvents(): void {\n if (!this.state.eventQ.length) return;\n\n const batch = this.state.eventQ.splice(0);\n this.api(\"/widget/events\", {\n anonymous_id: this.state.anonId,\n events: batch,\n }).catch(() => {\n // Put events back on failure\n this.state.eventQ = batch.concat(this.state.eventQ);\n });\n }\n\n private shouldSampleReplay(): boolean {\n if (!this.state.features?.replay_enabled) return false;\n return Math.random() < (this.state.features.replay_sample_rate || 0);\n }\n\n private startReplay(): void {\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n this.setupRageClickDetection();\n this.setupErrorCapture();\n\n // Load rrweb dynamically\n const script = document.createElement(\"script\");\n script.type = \"module\";\n script.src = this.state.widgetUrl.replace(/\\/?(index\\.html)?$/, \"\") + \"/replay.js\";\n document.head.appendChild(script);\n\n // Wait for rrweb to load\n let attempts = 0;\n const checkRrweb = setInterval(() => {\n attempts++;\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n clearInterval(checkRrweb);\n this.initRrweb();\n } else if (attempts > 50) {\n clearInterval(checkRrweb);\n console.warn(\"MeetSudo: replay failed to load\");\n }\n }, 100);\n }\n\n private initRrweb(): void {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n\n // Setup inactivity tracking\n this.setupActivityTracking();\n }\n\n private setupActivityTracking(): void {\n const activityEvents = [\"mousemove\", \"keydown\", \"click\", \"scroll\", \"touchstart\"];\n\n const handleActivity = () => {\n this.state.lastActivityTime = Date.now();\n\n // Resume replay if it was paused\n if (this.state.replayPaused) {\n this.resumeReplay();\n }\n\n // Reset inactivity timer\n if (this.state.inactivityTimer) {\n clearTimeout(this.state.inactivityTimer);\n }\n\n this.state.inactivityTimer = setTimeout(() => {\n this.pauseReplayDueToInactivity();\n }, INACTIVITY_TIMEOUT);\n };\n\n // Add event listeners\n activityEvents.forEach((event) => {\n document.addEventListener(event, handleActivity, { passive: true });\n });\n\n // Start initial inactivity timer\n this.state.inactivityTimer = setTimeout(() => {\n this.pauseReplayDueToInactivity();\n }, INACTIVITY_TIMEOUT);\n }\n\n private pauseReplayDueToInactivity(): void {\n if (this.state.replayPaused || !this.state.replaySessionId) return;\n\n this.state.replayPaused = true;\n\n // Stop rrweb recording\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n this.state.replayStopFn = null;\n }\n\n // Flush remaining events\n this.flushReplayChunk();\n\n // Stop flush timer\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n this.state.replayFlushTimer = null;\n }\n\n // Send end signal with inactivity flag\n if (this.state.apiKey) {\n this.api(\"/widget/replay/end\", {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n end_reason: \"inactivity\",\n }).catch(() => {});\n }\n }\n\n private resumeReplay(): void {\n if (!this.state.replayPaused || !this.state.features?.replay_enabled) return;\n\n this.state.replayPaused = false;\n\n // Start a new replay session\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n // Restart rrweb recording\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n }\n }\n\n private isSensitiveInput(el: HTMLElement): boolean {\n if (!el) return true;\n const input = el as HTMLInputElement;\n const type = (input.type || \"\").toLowerCase();\n const name = (input.name || \"\").toLowerCase();\n const id = (input.id || \"\").toLowerCase();\n\n if (type === \"password\") return true;\n\n const sensitivePatterns = [/password/i, /card/i, /cvv/i, /cvc/i, /ssn/i, /secret/i, /token/i];\n const identifiers = name + \" \" + id;\n return sensitivePatterns.some((p) => p.test(identifiers));\n }\n\n private flushReplayChunk(): void {\n if (!this.state.replayEvents.length || this.state.replayPaused) return;\n\n const events = this.state.replayEvents.splice(0);\n const seq = this.state.replaySequence++;\n\n const payload: Record<string, unknown> = {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n sequence: seq,\n events,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n };\n\n if (seq === 0) {\n payload.page_url = window.location.href;\n payload.user_agent = navigator.userAgent;\n payload.screen_width = window.innerWidth;\n payload.screen_height = window.innerHeight;\n payload.started_at = this.state.replayStartedAt;\n }\n\n this.api(\"/widget/replay/chunk\", payload).catch(() => {\n this.state.replayEvents = events.concat(this.state.replayEvents);\n this.state.replaySequence--;\n });\n }\n\n private setupRageClickDetection(): void {\n document.addEventListener(\n \"click\",\n (e) => {\n if (!this.state.replaySessionId) return;\n\n const now = Date.now();\n const target = e.target;\n\n if (target === this.state.lastClickTarget && now - this.state.lastClickTime < 500) {\n this.state.clickCount++;\n if (this.state.clickCount >= 3) {\n this.state.replayRageClickCount++;\n this.state.clickCount = 0;\n this.track(\"rage_click\", { page_url: window.location.href });\n }\n } else {\n this.state.clickCount = 1;\n }\n\n this.state.lastClickTime = now;\n this.state.lastClickTarget = target;\n },\n true\n );\n }\n\n private setupErrorCapture(): void {\n window.onerror = (message, source, lineno, colno) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n this.track(\"js_error\", {\n message: String(message).substring(0, 500),\n source: source || \"\",\n lineno: lineno || 0,\n });\n }\n return false;\n };\n\n window.addEventListener(\"unhandledrejection\", (e) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n const message = e.reason instanceof Error ? e.reason.message : String(e.reason);\n this.track(\"js_error\", { message: message.substring(0, 500), type: \"unhandledrejection\" });\n }\n });\n }\n\n private setupEmailCapture(): void {\n document.addEventListener(\n \"blur\",\n (e) => {\n const el = e.target as HTMLInputElement;\n if (!el || el.tagName !== \"INPUT\") return;\n\n const type = (el.type || \"\").toLowerCase();\n const name = (el.name || \"\").toLowerCase();\n if (type === \"email\" || /email/.test(name)) {\n const value = el.value?.trim();\n if (value && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) && !this.state.capturedEmails[value]) {\n this.state.capturedEmails[value] = true;\n this.track(\"email_captured\", { email: value });\n }\n }\n },\n true\n );\n }\n\n private handleUnload(): void {\n if (this.state.flushTimer) {\n clearInterval(this.state.flushTimer);\n }\n\n // Flush remaining events\n if (this.state.eventQ.length && this.state.apiKey) {\n const apiKey = this.state.apiKey;\n try {\n fetch(this.state.apiUrl + \"/widget/events\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": apiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n events: this.state.eventQ,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n\n // End replay\n if (this.state.replaySessionId && this.state.apiKey) {\n const replayApiKey = this.state.apiKey;\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n }\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n }\n\n try {\n fetch(this.state.apiUrl + \"/widget/replay/end\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": replayApiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
  var STORAGE_KEY = "meetsudo_anon_id";
3
3
  var FLUSH_INTERVAL = 5e3;
4
4
  var REPLAY_FLUSH_INTERVAL = 1e4;
5
+ var INACTIVITY_TIMEOUT = 6e4;
5
6
  var MeetSudo = class {
6
7
  constructor() {
7
8
  this.state = {
@@ -28,7 +29,10 @@ var MeetSudo = class {
28
29
  lastClickTime: 0,
29
30
  lastClickTarget: null,
30
31
  clickCount: 0,
31
- capturedEmails: {}
32
+ capturedEmails: {},
33
+ lastActivityTime: Date.now(),
34
+ inactivityTimer: null,
35
+ replayPaused: false
32
36
  };
33
37
  this.config = null;
34
38
  }
@@ -306,6 +310,88 @@ var MeetSudo = class {
306
310
  }
307
311
  });
308
312
  this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);
313
+ this.setupActivityTracking();
314
+ }
315
+ setupActivityTracking() {
316
+ const activityEvents = ["mousemove", "keydown", "click", "scroll", "touchstart"];
317
+ const handleActivity = () => {
318
+ this.state.lastActivityTime = Date.now();
319
+ if (this.state.replayPaused) {
320
+ this.resumeReplay();
321
+ }
322
+ if (this.state.inactivityTimer) {
323
+ clearTimeout(this.state.inactivityTimer);
324
+ }
325
+ this.state.inactivityTimer = setTimeout(() => {
326
+ this.pauseReplayDueToInactivity();
327
+ }, INACTIVITY_TIMEOUT);
328
+ };
329
+ activityEvents.forEach((event) => {
330
+ document.addEventListener(event, handleActivity, { passive: true });
331
+ });
332
+ this.state.inactivityTimer = setTimeout(() => {
333
+ this.pauseReplayDueToInactivity();
334
+ }, INACTIVITY_TIMEOUT);
335
+ }
336
+ pauseReplayDueToInactivity() {
337
+ if (this.state.replayPaused || !this.state.replaySessionId) return;
338
+ this.state.replayPaused = true;
339
+ if (this.state.replayStopFn) {
340
+ this.state.replayStopFn();
341
+ this.state.replayStopFn = null;
342
+ }
343
+ this.flushReplayChunk();
344
+ if (this.state.replayFlushTimer) {
345
+ clearInterval(this.state.replayFlushTimer);
346
+ this.state.replayFlushTimer = null;
347
+ }
348
+ if (this.state.apiKey) {
349
+ this.api("/widget/replay/end", {
350
+ anonymous_id: this.state.anonId,
351
+ session_id: this.state.replaySessionId,
352
+ ended_at: (/* @__PURE__ */ new Date()).toISOString(),
353
+ event_count: this.state.replayTotalEvents,
354
+ error_count: this.state.replayErrorCount,
355
+ rage_click_count: this.state.replayRageClickCount,
356
+ end_reason: "inactivity"
357
+ }).catch(() => {
358
+ });
359
+ }
360
+ }
361
+ resumeReplay() {
362
+ if (!this.state.replayPaused || !this.state.features?.replay_enabled) return;
363
+ this.state.replayPaused = false;
364
+ this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();
365
+ this.state.replaySequence = 0;
366
+ this.state.replayEvents = [];
367
+ this.state.replayTotalEvents = 0;
368
+ this.state.replayStartedAt = (/* @__PURE__ */ new Date()).toISOString();
369
+ this.state.replayErrorCount = 0;
370
+ this.state.replayRageClickCount = 0;
371
+ if (window.rrweb?.record) {
372
+ this.state.replayStopFn = window.rrweb.record({
373
+ emit: (event) => {
374
+ this.state.replayEvents.push(event);
375
+ this.state.replayTotalEvents++;
376
+ },
377
+ maskAllInputs: false,
378
+ maskInputFn: (text, element) => {
379
+ if (this.isSensitiveInput(element)) {
380
+ return "*".repeat(text.length || 8);
381
+ }
382
+ return text;
383
+ },
384
+ blockSelector: ".meetsudo-no-record, [data-meetsudo-no-record]",
385
+ inlineStylesheet: true,
386
+ sampling: {
387
+ mousemove: 50,
388
+ mouseInteraction: true,
389
+ scroll: 150,
390
+ input: "last"
391
+ }
392
+ });
393
+ this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);
394
+ }
309
395
  }
310
396
  isSensitiveInput(el) {
311
397
  if (!el) return true;
@@ -319,7 +405,7 @@ var MeetSudo = class {
319
405
  return sensitivePatterns.some((p) => p.test(identifiers));
320
406
  }
321
407
  flushReplayChunk() {
322
- if (!this.state.replayEvents.length) return;
408
+ if (!this.state.replayEvents.length || this.state.replayPaused) return;
323
409
  const events = this.state.replayEvents.splice(0);
324
410
  const seq = this.state.replaySequence++;
325
411
  const payload = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk.ts","../src/index.ts"],"sourcesContent":["import type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n Features,\n InitResponse,\n IdentifyResponse,\n ChatAction,\n} from \"./types\";\n\nconst STORAGE_KEY = \"meetsudo_anon_id\";\nconst FLUSH_INTERVAL = 5000;\nconst REPLAY_FLUSH_INTERVAL = 10000;\n\ninterface EventData {\n name: string;\n properties: EventProperties;\n page_url: string;\n timestamp: string;\n}\n\ninterface State {\n apiKey: string | null;\n apiUrl: string;\n widgetUrl: string;\n anonId: string | null;\n custId: string | null;\n features: Features | null;\n workspaceName: string | null;\n initialized: boolean;\n iframe: HTMLIFrameElement | null;\n eventQ: EventData[];\n flushTimer: ReturnType<typeof setInterval> | null;\n replaySessionId: string | null;\n replaySequence: number;\n replayEvents: unknown[];\n replayFlushTimer: ReturnType<typeof setInterval> | null;\n replayStopFn: (() => void) | null;\n replayTotalEvents: number;\n replayStartedAt: string | null;\n replayRageClickCount: number;\n replayErrorCount: number;\n lastClickTime: number;\n lastClickTarget: EventTarget | null;\n clickCount: number;\n capturedEmails: Record<string, boolean>;\n}\n\nexport class MeetSudo {\n private state: State = {\n apiKey: null,\n apiUrl: \"https://api.meetsudo.com\",\n widgetUrl: \"https://widget.meetsudo.com\",\n anonId: null,\n custId: null,\n features: null,\n workspaceName: null,\n initialized: false,\n iframe: null,\n eventQ: [],\n flushTimer: null,\n replaySessionId: null,\n replaySequence: 0,\n replayEvents: [],\n replayFlushTimer: null,\n replayStopFn: null,\n replayTotalEvents: 0,\n replayStartedAt: null,\n replayRageClickCount: 0,\n replayErrorCount: 0,\n lastClickTime: 0,\n lastClickTarget: null,\n clickCount: 0,\n capturedEmails: {},\n };\n\n private config: MeetSudoConfig | null = null;\n\n /**\n * Initialize the MeetSudo SDK\n */\n async init(config: MeetSudoConfig): Promise<void> {\n if (!config.apiKey) {\n throw new Error(\"MeetSudo: apiKey is required\");\n }\n\n this.config = config;\n this.state.apiKey = config.apiKey;\n this.state.apiUrl = config.apiUrl || \"https://api.meetsudo.com\";\n this.state.widgetUrl = config.widgetUrl || \"https://widget.meetsudo.com\";\n this.state.anonId = this.getAnonId();\n\n try {\n const res = await this.api<InitResponse>(\"/widget/init\", {\n anonymous_id: this.state.anonId,\n url: window.location.href,\n referrer: document.referrer,\n });\n\n this.state.custId = res.customer_id;\n this.state.features = res.features;\n this.state.workspaceName = res.workspace_name;\n this.state.initialized = true;\n\n // Create chat iframe if enabled\n if (res.features.chat_enabled && !config.disableChat) {\n this.createIframe(res);\n }\n\n // Start event tracking if enabled\n if (res.features.events_enabled && !config.disableEvents) {\n this.state.flushTimer = setInterval(() => this.flushEvents(), FLUSH_INTERVAL);\n if (res.features.events_auto_page && !config.disableAutoPageView) {\n this.page();\n }\n this.setupEmailCapture();\n }\n\n // Start session replay if enabled and sampled in\n if (this.shouldSampleReplay() && !config.disableReplay) {\n this.startReplay();\n }\n\n // Setup beforeunload handler\n window.addEventListener(\"beforeunload\", () => this.handleUnload());\n } catch (error) {\n console.error(\"MeetSudo: init failed\", error);\n throw error;\n }\n }\n\n /**\n * Identify a user\n */\n async identify(userId: string, traits?: UserTraits): Promise<void> {\n if (!this.state.initialized) {\n console.warn(\"MeetSudo: call init() before identify()\");\n return;\n }\n\n try {\n const res = await this.api<IdentifyResponse>(\"/widget/identify\", {\n anonymous_id: this.state.anonId,\n external_id: userId,\n properties: traits || {},\n });\n\n this.state.custId = res.customer_id;\n\n // Notify chat iframe about identity change\n if (this.state.iframe?.contentWindow) {\n this.state.iframe.contentWindow.postMessage(\n {\n type: \"fi:identify\",\n customerId: res.customer_id,\n merged: res.merged,\n },\n \"*\"\n );\n }\n } catch (error) {\n console.error(\"MeetSudo: identify failed\", error);\n }\n }\n\n /**\n * Track a custom event\n */\n track(eventName: string, properties?: EventProperties): void {\n if (!this.state.initialized || !this.state.features?.events_enabled) {\n return;\n }\n\n this.state.eventQ.push({\n name: eventName,\n properties: properties || {},\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Track a page view\n */\n page(properties?: PageProperties): void {\n const props: PageProperties = {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n ...properties,\n };\n this.track(\"page_view\", props);\n }\n\n /**\n * Control the chat widget\n */\n chat(action: ChatAction): void {\n if (!this.state.iframe?.contentWindow) return;\n\n switch (action) {\n case \"open\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"open\" }, \"*\");\n this.state.iframe.style.width = \"400px\";\n this.state.iframe.style.height = \"560px\";\n break;\n case \"close\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"close\" }, \"*\");\n this.state.iframe.style.width = \"80px\";\n this.state.iframe.style.height = \"80px\";\n break;\n case \"hide\":\n this.state.iframe.style.display = \"none\";\n break;\n case \"show\":\n this.state.iframe.style.display = \"\";\n break;\n }\n }\n\n /**\n * Check if SDK is initialized\n */\n isInitialized(): boolean {\n return this.state.initialized;\n }\n\n /**\n * Get the anonymous ID\n */\n getAnonymousId(): string | null {\n return this.state.anonId;\n }\n\n /**\n * Get the customer ID (after identify)\n */\n getCustomerId(): string | null {\n return this.state.custId;\n }\n\n // Private methods\n\n private getAnonId(): string {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) return stored;\n } catch {\n /* private browsing */\n }\n\n const id = crypto.randomUUID?.() || this.generateUUID();\n try {\n localStorage.setItem(STORAGE_KEY, id);\n } catch {\n /* ignore */\n }\n return id;\n }\n\n private generateUUID(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n\n private async api<T>(path: string, data: unknown): Promise<T> {\n const res = await fetch(this.state.apiUrl + path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.state.apiKey!,\n },\n body: JSON.stringify(data),\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n\n return res.json();\n }\n\n private createIframe(initData: InitResponse): void {\n if (this.state.iframe) return;\n\n const pos = this.state.features?.chat_position || \"bottom-right\";\n const iframe = document.createElement(\"iframe\");\n iframe.id = \"meetsudo-widget\";\n const posCSS = pos === \"bottom-left\" ? \"left:0;\" : \"right:0;\";\n iframe.style.cssText = `position:fixed;bottom:0;${posCSS}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`;\n iframe.allow = \"clipboard-write\";\n iframe.src = this.state.widgetUrl;\n\n document.body.appendChild(iframe);\n this.state.iframe = iframe;\n\n iframe.onload = () => {\n iframe.contentWindow?.postMessage(\n {\n type: \"fi:config\",\n apiKey: this.state.apiKey,\n apiUrl: this.state.apiUrl,\n anonymousId: this.state.anonId,\n customerId: this.state.custId,\n workspaceName: this.state.workspaceName,\n features: this.state.features,\n conversationId: initData.open_conversation_id,\n messages: initData.messages || [],\n },\n \"*\"\n );\n };\n\n window.addEventListener(\"message\", (e) => {\n if (e.data?.type === \"fi:resize\") {\n if (e.data.state === \"open\") {\n iframe.style.width = \"400px\";\n iframe.style.height = \"560px\";\n } else {\n iframe.style.width = \"80px\";\n iframe.style.height = \"80px\";\n }\n }\n });\n }\n\n private flushEvents(): void {\n if (!this.state.eventQ.length) return;\n\n const batch = this.state.eventQ.splice(0);\n this.api(\"/widget/events\", {\n anonymous_id: this.state.anonId,\n events: batch,\n }).catch(() => {\n // Put events back on failure\n this.state.eventQ = batch.concat(this.state.eventQ);\n });\n }\n\n private shouldSampleReplay(): boolean {\n if (!this.state.features?.replay_enabled) return false;\n return Math.random() < (this.state.features.replay_sample_rate || 0);\n }\n\n private startReplay(): void {\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n this.setupRageClickDetection();\n this.setupErrorCapture();\n\n // Load rrweb dynamically\n const script = document.createElement(\"script\");\n script.type = \"module\";\n script.src = this.state.widgetUrl.replace(/\\/?(index\\.html)?$/, \"\") + \"/replay.js\";\n document.head.appendChild(script);\n\n // Wait for rrweb to load\n let attempts = 0;\n const checkRrweb = setInterval(() => {\n attempts++;\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n clearInterval(checkRrweb);\n this.initRrweb();\n } else if (attempts > 50) {\n clearInterval(checkRrweb);\n console.warn(\"MeetSudo: replay failed to load\");\n }\n }, 100);\n }\n\n private initRrweb(): void {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n }\n\n private isSensitiveInput(el: HTMLElement): boolean {\n if (!el) return true;\n const input = el as HTMLInputElement;\n const type = (input.type || \"\").toLowerCase();\n const name = (input.name || \"\").toLowerCase();\n const id = (input.id || \"\").toLowerCase();\n\n if (type === \"password\") return true;\n\n const sensitivePatterns = [/password/i, /card/i, /cvv/i, /cvc/i, /ssn/i, /secret/i, /token/i];\n const identifiers = name + \" \" + id;\n return sensitivePatterns.some((p) => p.test(identifiers));\n }\n\n private flushReplayChunk(): void {\n if (!this.state.replayEvents.length) return;\n\n const events = this.state.replayEvents.splice(0);\n const seq = this.state.replaySequence++;\n\n const payload: Record<string, unknown> = {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n sequence: seq,\n events,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n };\n\n if (seq === 0) {\n payload.page_url = window.location.href;\n payload.user_agent = navigator.userAgent;\n payload.screen_width = window.innerWidth;\n payload.screen_height = window.innerHeight;\n payload.started_at = this.state.replayStartedAt;\n }\n\n this.api(\"/widget/replay/chunk\", payload).catch(() => {\n this.state.replayEvents = events.concat(this.state.replayEvents);\n this.state.replaySequence--;\n });\n }\n\n private setupRageClickDetection(): void {\n document.addEventListener(\n \"click\",\n (e) => {\n if (!this.state.replaySessionId) return;\n\n const now = Date.now();\n const target = e.target;\n\n if (target === this.state.lastClickTarget && now - this.state.lastClickTime < 500) {\n this.state.clickCount++;\n if (this.state.clickCount >= 3) {\n this.state.replayRageClickCount++;\n this.state.clickCount = 0;\n this.track(\"rage_click\", { page_url: window.location.href });\n }\n } else {\n this.state.clickCount = 1;\n }\n\n this.state.lastClickTime = now;\n this.state.lastClickTarget = target;\n },\n true\n );\n }\n\n private setupErrorCapture(): void {\n window.onerror = (message, source, lineno, colno) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n this.track(\"js_error\", {\n message: String(message).substring(0, 500),\n source: source || \"\",\n lineno: lineno || 0,\n });\n }\n return false;\n };\n\n window.addEventListener(\"unhandledrejection\", (e) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n const message = e.reason instanceof Error ? e.reason.message : String(e.reason);\n this.track(\"js_error\", { message: message.substring(0, 500), type: \"unhandledrejection\" });\n }\n });\n }\n\n private setupEmailCapture(): void {\n document.addEventListener(\n \"blur\",\n (e) => {\n const el = e.target as HTMLInputElement;\n if (!el || el.tagName !== \"INPUT\") return;\n\n const type = (el.type || \"\").toLowerCase();\n const name = (el.name || \"\").toLowerCase();\n if (type === \"email\" || /email/.test(name)) {\n const value = el.value?.trim();\n if (value && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) && !this.state.capturedEmails[value]) {\n this.state.capturedEmails[value] = true;\n this.track(\"email_captured\", { email: value });\n }\n }\n },\n true\n );\n }\n\n private handleUnload(): void {\n if (this.state.flushTimer) {\n clearInterval(this.state.flushTimer);\n }\n\n // Flush remaining events\n if (this.state.eventQ.length && this.state.apiKey) {\n const apiKey = this.state.apiKey;\n try {\n fetch(this.state.apiUrl + \"/widget/events\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": apiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n events: this.state.eventQ,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n\n // End replay\n if (this.state.replaySessionId && this.state.apiKey) {\n const replayApiKey = this.state.apiKey;\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n }\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n }\n\n try {\n fetch(this.state.apiUrl + \"/widget/replay/end\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": replayApiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n }\n}\n","export { MeetSudo } from \"./sdk\";\nexport type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n ChatAction,\n} from \"./types\";\n\n// Default instance for convenience\nimport { MeetSudo } from \"./sdk\";\nexport const meetsudo = new MeetSudo();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/sdk.ts","../src/index.ts"],"sourcesContent":["import type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n Features,\n InitResponse,\n IdentifyResponse,\n ChatAction,\n} from \"./types\";\n\nconst STORAGE_KEY = \"meetsudo_anon_id\";\nconst FLUSH_INTERVAL = 5000;\nconst REPLAY_FLUSH_INTERVAL = 10000;\nconst INACTIVITY_TIMEOUT = 60000; // 1 minute\n\ninterface EventData {\n name: string;\n properties: EventProperties;\n page_url: string;\n timestamp: string;\n}\n\ninterface State {\n apiKey: string | null;\n apiUrl: string;\n widgetUrl: string;\n anonId: string | null;\n custId: string | null;\n features: Features | null;\n workspaceName: string | null;\n initialized: boolean;\n iframe: HTMLIFrameElement | null;\n eventQ: EventData[];\n flushTimer: ReturnType<typeof setInterval> | null;\n replaySessionId: string | null;\n replaySequence: number;\n replayEvents: unknown[];\n replayFlushTimer: ReturnType<typeof setInterval> | null;\n replayStopFn: (() => void) | null;\n replayTotalEvents: number;\n replayStartedAt: string | null;\n replayRageClickCount: number;\n replayErrorCount: number;\n lastClickTime: number;\n lastClickTarget: EventTarget | null;\n clickCount: number;\n capturedEmails: Record<string, boolean>;\n lastActivityTime: number;\n inactivityTimer: ReturnType<typeof setTimeout> | null;\n replayPaused: boolean;\n}\n\nexport class MeetSudo {\n private state: State = {\n apiKey: null,\n apiUrl: \"https://api.meetsudo.com\",\n widgetUrl: \"https://widget.meetsudo.com\",\n anonId: null,\n custId: null,\n features: null,\n workspaceName: null,\n initialized: false,\n iframe: null,\n eventQ: [],\n flushTimer: null,\n replaySessionId: null,\n replaySequence: 0,\n replayEvents: [],\n replayFlushTimer: null,\n replayStopFn: null,\n replayTotalEvents: 0,\n replayStartedAt: null,\n replayRageClickCount: 0,\n replayErrorCount: 0,\n lastClickTime: 0,\n lastClickTarget: null,\n clickCount: 0,\n capturedEmails: {},\n lastActivityTime: Date.now(),\n inactivityTimer: null,\n replayPaused: false,\n };\n\n private config: MeetSudoConfig | null = null;\n\n /**\n * Initialize the MeetSudo SDK\n */\n async init(config: MeetSudoConfig): Promise<void> {\n if (!config.apiKey) {\n throw new Error(\"MeetSudo: apiKey is required\");\n }\n\n this.config = config;\n this.state.apiKey = config.apiKey;\n this.state.apiUrl = config.apiUrl || \"https://api.meetsudo.com\";\n this.state.widgetUrl = config.widgetUrl || \"https://widget.meetsudo.com\";\n this.state.anonId = this.getAnonId();\n\n try {\n const res = await this.api<InitResponse>(\"/widget/init\", {\n anonymous_id: this.state.anonId,\n url: window.location.href,\n referrer: document.referrer,\n });\n\n this.state.custId = res.customer_id;\n this.state.features = res.features;\n this.state.workspaceName = res.workspace_name;\n this.state.initialized = true;\n\n // Create chat iframe if enabled\n if (res.features.chat_enabled && !config.disableChat) {\n this.createIframe(res);\n }\n\n // Start event tracking if enabled\n if (res.features.events_enabled && !config.disableEvents) {\n this.state.flushTimer = setInterval(() => this.flushEvents(), FLUSH_INTERVAL);\n if (res.features.events_auto_page && !config.disableAutoPageView) {\n this.page();\n }\n this.setupEmailCapture();\n }\n\n // Start session replay if enabled and sampled in\n if (this.shouldSampleReplay() && !config.disableReplay) {\n this.startReplay();\n }\n\n // Setup beforeunload handler\n window.addEventListener(\"beforeunload\", () => this.handleUnload());\n } catch (error) {\n console.error(\"MeetSudo: init failed\", error);\n throw error;\n }\n }\n\n /**\n * Identify a user\n */\n async identify(userId: string, traits?: UserTraits): Promise<void> {\n if (!this.state.initialized) {\n console.warn(\"MeetSudo: call init() before identify()\");\n return;\n }\n\n try {\n const res = await this.api<IdentifyResponse>(\"/widget/identify\", {\n anonymous_id: this.state.anonId,\n external_id: userId,\n properties: traits || {},\n });\n\n this.state.custId = res.customer_id;\n\n // Notify chat iframe about identity change\n if (this.state.iframe?.contentWindow) {\n this.state.iframe.contentWindow.postMessage(\n {\n type: \"fi:identify\",\n customerId: res.customer_id,\n merged: res.merged,\n },\n \"*\"\n );\n }\n } catch (error) {\n console.error(\"MeetSudo: identify failed\", error);\n }\n }\n\n /**\n * Track a custom event\n */\n track(eventName: string, properties?: EventProperties): void {\n if (!this.state.initialized || !this.state.features?.events_enabled) {\n return;\n }\n\n this.state.eventQ.push({\n name: eventName,\n properties: properties || {},\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Track a page view\n */\n page(properties?: PageProperties): void {\n const props: PageProperties = {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n ...properties,\n };\n this.track(\"page_view\", props);\n }\n\n /**\n * Control the chat widget\n */\n chat(action: ChatAction): void {\n if (!this.state.iframe?.contentWindow) return;\n\n switch (action) {\n case \"open\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"open\" }, \"*\");\n this.state.iframe.style.width = \"400px\";\n this.state.iframe.style.height = \"560px\";\n break;\n case \"close\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"close\" }, \"*\");\n this.state.iframe.style.width = \"80px\";\n this.state.iframe.style.height = \"80px\";\n break;\n case \"hide\":\n this.state.iframe.style.display = \"none\";\n break;\n case \"show\":\n this.state.iframe.style.display = \"\";\n break;\n }\n }\n\n /**\n * Check if SDK is initialized\n */\n isInitialized(): boolean {\n return this.state.initialized;\n }\n\n /**\n * Get the anonymous ID\n */\n getAnonymousId(): string | null {\n return this.state.anonId;\n }\n\n /**\n * Get the customer ID (after identify)\n */\n getCustomerId(): string | null {\n return this.state.custId;\n }\n\n // Private methods\n\n private getAnonId(): string {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) return stored;\n } catch {\n /* private browsing */\n }\n\n const id = crypto.randomUUID?.() || this.generateUUID();\n try {\n localStorage.setItem(STORAGE_KEY, id);\n } catch {\n /* ignore */\n }\n return id;\n }\n\n private generateUUID(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n\n private async api<T>(path: string, data: unknown): Promise<T> {\n const res = await fetch(this.state.apiUrl + path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.state.apiKey!,\n },\n body: JSON.stringify(data),\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n\n return res.json();\n }\n\n private createIframe(initData: InitResponse): void {\n if (this.state.iframe) return;\n\n const pos = this.state.features?.chat_position || \"bottom-right\";\n const iframe = document.createElement(\"iframe\");\n iframe.id = \"meetsudo-widget\";\n const posCSS = pos === \"bottom-left\" ? \"left:0;\" : \"right:0;\";\n iframe.style.cssText = `position:fixed;bottom:0;${posCSS}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`;\n iframe.allow = \"clipboard-write\";\n iframe.src = this.state.widgetUrl;\n\n document.body.appendChild(iframe);\n this.state.iframe = iframe;\n\n iframe.onload = () => {\n iframe.contentWindow?.postMessage(\n {\n type: \"fi:config\",\n apiKey: this.state.apiKey,\n apiUrl: this.state.apiUrl,\n anonymousId: this.state.anonId,\n customerId: this.state.custId,\n workspaceName: this.state.workspaceName,\n features: this.state.features,\n conversationId: initData.open_conversation_id,\n messages: initData.messages || [],\n },\n \"*\"\n );\n };\n\n window.addEventListener(\"message\", (e) => {\n if (e.data?.type === \"fi:resize\") {\n if (e.data.state === \"open\") {\n iframe.style.width = \"400px\";\n iframe.style.height = \"560px\";\n } else {\n iframe.style.width = \"80px\";\n iframe.style.height = \"80px\";\n }\n }\n });\n }\n\n private flushEvents(): void {\n if (!this.state.eventQ.length) return;\n\n const batch = this.state.eventQ.splice(0);\n this.api(\"/widget/events\", {\n anonymous_id: this.state.anonId,\n events: batch,\n }).catch(() => {\n // Put events back on failure\n this.state.eventQ = batch.concat(this.state.eventQ);\n });\n }\n\n private shouldSampleReplay(): boolean {\n if (!this.state.features?.replay_enabled) return false;\n return Math.random() < (this.state.features.replay_sample_rate || 0);\n }\n\n private startReplay(): void {\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n this.setupRageClickDetection();\n this.setupErrorCapture();\n\n // Load rrweb dynamically\n const script = document.createElement(\"script\");\n script.type = \"module\";\n script.src = this.state.widgetUrl.replace(/\\/?(index\\.html)?$/, \"\") + \"/replay.js\";\n document.head.appendChild(script);\n\n // Wait for rrweb to load\n let attempts = 0;\n const checkRrweb = setInterval(() => {\n attempts++;\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n clearInterval(checkRrweb);\n this.initRrweb();\n } else if (attempts > 50) {\n clearInterval(checkRrweb);\n console.warn(\"MeetSudo: replay failed to load\");\n }\n }, 100);\n }\n\n private initRrweb(): void {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n\n // Setup inactivity tracking\n this.setupActivityTracking();\n }\n\n private setupActivityTracking(): void {\n const activityEvents = [\"mousemove\", \"keydown\", \"click\", \"scroll\", \"touchstart\"];\n\n const handleActivity = () => {\n this.state.lastActivityTime = Date.now();\n\n // Resume replay if it was paused\n if (this.state.replayPaused) {\n this.resumeReplay();\n }\n\n // Reset inactivity timer\n if (this.state.inactivityTimer) {\n clearTimeout(this.state.inactivityTimer);\n }\n\n this.state.inactivityTimer = setTimeout(() => {\n this.pauseReplayDueToInactivity();\n }, INACTIVITY_TIMEOUT);\n };\n\n // Add event listeners\n activityEvents.forEach((event) => {\n document.addEventListener(event, handleActivity, { passive: true });\n });\n\n // Start initial inactivity timer\n this.state.inactivityTimer = setTimeout(() => {\n this.pauseReplayDueToInactivity();\n }, INACTIVITY_TIMEOUT);\n }\n\n private pauseReplayDueToInactivity(): void {\n if (this.state.replayPaused || !this.state.replaySessionId) return;\n\n this.state.replayPaused = true;\n\n // Stop rrweb recording\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n this.state.replayStopFn = null;\n }\n\n // Flush remaining events\n this.flushReplayChunk();\n\n // Stop flush timer\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n this.state.replayFlushTimer = null;\n }\n\n // Send end signal with inactivity flag\n if (this.state.apiKey) {\n this.api(\"/widget/replay/end\", {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n end_reason: \"inactivity\",\n }).catch(() => {});\n }\n }\n\n private resumeReplay(): void {\n if (!this.state.replayPaused || !this.state.features?.replay_enabled) return;\n\n this.state.replayPaused = false;\n\n // Start a new replay session\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n // Restart rrweb recording\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n }\n }\n\n private isSensitiveInput(el: HTMLElement): boolean {\n if (!el) return true;\n const input = el as HTMLInputElement;\n const type = (input.type || \"\").toLowerCase();\n const name = (input.name || \"\").toLowerCase();\n const id = (input.id || \"\").toLowerCase();\n\n if (type === \"password\") return true;\n\n const sensitivePatterns = [/password/i, /card/i, /cvv/i, /cvc/i, /ssn/i, /secret/i, /token/i];\n const identifiers = name + \" \" + id;\n return sensitivePatterns.some((p) => p.test(identifiers));\n }\n\n private flushReplayChunk(): void {\n if (!this.state.replayEvents.length || this.state.replayPaused) return;\n\n const events = this.state.replayEvents.splice(0);\n const seq = this.state.replaySequence++;\n\n const payload: Record<string, unknown> = {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n sequence: seq,\n events,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n };\n\n if (seq === 0) {\n payload.page_url = window.location.href;\n payload.user_agent = navigator.userAgent;\n payload.screen_width = window.innerWidth;\n payload.screen_height = window.innerHeight;\n payload.started_at = this.state.replayStartedAt;\n }\n\n this.api(\"/widget/replay/chunk\", payload).catch(() => {\n this.state.replayEvents = events.concat(this.state.replayEvents);\n this.state.replaySequence--;\n });\n }\n\n private setupRageClickDetection(): void {\n document.addEventListener(\n \"click\",\n (e) => {\n if (!this.state.replaySessionId) return;\n\n const now = Date.now();\n const target = e.target;\n\n if (target === this.state.lastClickTarget && now - this.state.lastClickTime < 500) {\n this.state.clickCount++;\n if (this.state.clickCount >= 3) {\n this.state.replayRageClickCount++;\n this.state.clickCount = 0;\n this.track(\"rage_click\", { page_url: window.location.href });\n }\n } else {\n this.state.clickCount = 1;\n }\n\n this.state.lastClickTime = now;\n this.state.lastClickTarget = target;\n },\n true\n );\n }\n\n private setupErrorCapture(): void {\n window.onerror = (message, source, lineno, colno) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n this.track(\"js_error\", {\n message: String(message).substring(0, 500),\n source: source || \"\",\n lineno: lineno || 0,\n });\n }\n return false;\n };\n\n window.addEventListener(\"unhandledrejection\", (e) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n const message = e.reason instanceof Error ? e.reason.message : String(e.reason);\n this.track(\"js_error\", { message: message.substring(0, 500), type: \"unhandledrejection\" });\n }\n });\n }\n\n private setupEmailCapture(): void {\n document.addEventListener(\n \"blur\",\n (e) => {\n const el = e.target as HTMLInputElement;\n if (!el || el.tagName !== \"INPUT\") return;\n\n const type = (el.type || \"\").toLowerCase();\n const name = (el.name || \"\").toLowerCase();\n if (type === \"email\" || /email/.test(name)) {\n const value = el.value?.trim();\n if (value && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) && !this.state.capturedEmails[value]) {\n this.state.capturedEmails[value] = true;\n this.track(\"email_captured\", { email: value });\n }\n }\n },\n true\n );\n }\n\n private handleUnload(): void {\n if (this.state.flushTimer) {\n clearInterval(this.state.flushTimer);\n }\n\n // Flush remaining events\n if (this.state.eventQ.length && this.state.apiKey) {\n const apiKey = this.state.apiKey;\n try {\n fetch(this.state.apiUrl + \"/widget/events\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": apiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n events: this.state.eventQ,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n\n // End replay\n if (this.state.replaySessionId && this.state.apiKey) {\n const replayApiKey = this.state.apiKey;\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n }\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n }\n\n try {\n fetch(this.state.apiUrl + \"/widget/replay/end\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": replayApiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n }\n}\n","export { MeetSudo } from \"./sdk\";\nexport type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n ChatAction,\n} from \"./types\";\n\n// Default instance for convenience\nimport { MeetSudo } from \"./sdk\";\nexport const meetsudo = new MeetSudo();\n"],"mappings":"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","names":[]}
@@ -1,2 +1,2 @@
1
- "use strict";var MeetSudo=(()=>{var l=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var f=(n,t)=>{for(var e in t)l(n,e,{get:t[e],enumerable:!0})},g=(n,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of y(t))!m.call(n,i)&&i!==e&&l(n,i,{get:()=>t[i],enumerable:!(s=u(t,i))||s.enumerable});return n};var w=n=>g(l({},"__esModule",{value:!0}),n);var v={};f(v,{MeetSudo:()=>o,meetsudo:()=>a});var p="meetsudo_anon_id";var o=class{constructor(){this.state={apiKey:null,apiUrl:"https://api.meetsudo.com",widgetUrl:"https://widget.meetsudo.com",anonId:null,custId:null,features:null,workspaceName:null,initialized:!1,iframe:null,eventQ:[],flushTimer:null,replaySessionId:null,replaySequence:0,replayEvents:[],replayFlushTimer:null,replayStopFn:null,replayTotalEvents:0,replayStartedAt:null,replayRageClickCount:0,replayErrorCount:0,lastClickTime:0,lastClickTarget:null,clickCount:0,capturedEmails:{}};this.config=null}async init(t){if(!t.apiKey)throw new Error("MeetSudo: apiKey is required");this.config=t,this.state.apiKey=t.apiKey,this.state.apiUrl=t.apiUrl||"https://api.meetsudo.com",this.state.widgetUrl=t.widgetUrl||"https://widget.meetsudo.com",this.state.anonId=this.getAnonId();try{let e=await this.api("/widget/init",{anonymous_id:this.state.anonId,url:window.location.href,referrer:document.referrer});this.state.custId=e.customer_id,this.state.features=e.features,this.state.workspaceName=e.workspace_name,this.state.initialized=!0,e.features.chat_enabled&&!t.disableChat&&this.createIframe(e),e.features.events_enabled&&!t.disableEvents&&(this.state.flushTimer=setInterval(()=>this.flushEvents(),5e3),e.features.events_auto_page&&!t.disableAutoPageView&&this.page(),this.setupEmailCapture()),this.shouldSampleReplay()&&!t.disableReplay&&this.startReplay(),window.addEventListener("beforeunload",()=>this.handleUnload())}catch(e){throw console.error("MeetSudo: init failed",e),e}}async identify(t,e){if(!this.state.initialized){console.warn("MeetSudo: call init() before identify()");return}try{let s=await this.api("/widget/identify",{anonymous_id:this.state.anonId,external_id:t,properties:e||{}});this.state.custId=s.customer_id,this.state.iframe?.contentWindow&&this.state.iframe.contentWindow.postMessage({type:"fi:identify",customerId:s.customer_id,merged:s.merged},"*")}catch(s){console.error("MeetSudo: identify failed",s)}}track(t,e){!this.state.initialized||!this.state.features?.events_enabled||this.state.eventQ.push({name:t,properties:e||{},page_url:window.location.href,timestamp:new Date().toISOString()})}page(t){let e={url:window.location.href,title:document.title,referrer:document.referrer,...t};this.track("page_view",e)}chat(t){if(this.state.iframe?.contentWindow)switch(t){case"open":this.state.iframe.contentWindow.postMessage({type:"fi:chat",action:"open"},"*"),this.state.iframe.style.width="400px",this.state.iframe.style.height="560px";break;case"close":this.state.iframe.contentWindow.postMessage({type:"fi:chat",action:"close"},"*"),this.state.iframe.style.width="80px",this.state.iframe.style.height="80px";break;case"hide":this.state.iframe.style.display="none";break;case"show":this.state.iframe.style.display="";break}}isInitialized(){return this.state.initialized}getAnonymousId(){return this.state.anonId}getCustomerId(){return this.state.custId}getAnonId(){try{let e=localStorage.getItem(p);if(e)return e}catch{}let t=crypto.randomUUID?.()||this.generateUUID();try{localStorage.setItem(p,t)}catch{}return t}generateUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}async api(t,e){let s=await fetch(this.state.apiUrl+t,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.state.apiKey},body:JSON.stringify(e)});if(!s.ok)throw new Error(`HTTP ${s.status}`);return s.json()}createIframe(t){if(this.state.iframe)return;let e=this.state.features?.chat_position||"bottom-right",s=document.createElement("iframe");s.id="meetsudo-widget";let i=e==="bottom-left"?"left:0;":"right:0;";s.style.cssText=`position:fixed;bottom:0;${i}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`,s.allow="clipboard-write",s.src=this.state.widgetUrl,document.body.appendChild(s),this.state.iframe=s,s.onload=()=>{s.contentWindow?.postMessage({type:"fi:config",apiKey:this.state.apiKey,apiUrl:this.state.apiUrl,anonymousId:this.state.anonId,customerId:this.state.custId,workspaceName:this.state.workspaceName,features:this.state.features,conversationId:t.open_conversation_id,messages:t.messages||[]},"*")},window.addEventListener("message",r=>{r.data?.type==="fi:resize"&&(r.data.state==="open"?(s.style.width="400px",s.style.height="560px"):(s.style.width="80px",s.style.height="80px"))})}flushEvents(){if(!this.state.eventQ.length)return;let t=this.state.eventQ.splice(0);this.api("/widget/events",{anonymous_id:this.state.anonId,events:t}).catch(()=>{this.state.eventQ=t.concat(this.state.eventQ)})}shouldSampleReplay(){return this.state.features?.replay_enabled?Math.random()<(this.state.features.replay_sample_rate||0):!1}startReplay(){this.state.replaySessionId=crypto.randomUUID?.()||this.generateUUID(),this.state.replaySequence=0,this.state.replayEvents=[],this.state.replayTotalEvents=0,this.state.replayStartedAt=new Date().toISOString(),this.state.replayErrorCount=0,this.state.replayRageClickCount=0,this.setupRageClickDetection(),this.setupErrorCapture();let t=document.createElement("script");t.type="module",t.src=this.state.widgetUrl.replace(/\/?(index\.html)?$/,"")+"/replay.js",document.head.appendChild(t);let e=0,s=setInterval(()=>{e++,window.rrweb?.record?(clearInterval(s),this.initRrweb()):e>50&&(clearInterval(s),console.warn("MeetSudo: replay failed to load"))},100)}initRrweb(){this.state.replayStopFn=window.rrweb.record({emit:t=>{this.state.replayEvents.push(t),this.state.replayTotalEvents++},maskAllInputs:!1,maskInputFn:(t,e)=>this.isSensitiveInput(e)?"*".repeat(t.length||8):t,blockSelector:".meetsudo-no-record, [data-meetsudo-no-record]",inlineStylesheet:!0,sampling:{mousemove:50,mouseInteraction:!0,scroll:150,input:"last"}}),this.state.replayFlushTimer=setInterval(()=>this.flushReplayChunk(),1e4)}isSensitiveInput(t){if(!t)return!0;let e=t,s=(e.type||"").toLowerCase(),i=(e.name||"").toLowerCase(),r=(e.id||"").toLowerCase();if(s==="password")return!0;let d=[/password/i,/card/i,/cvv/i,/cvc/i,/ssn/i,/secret/i,/token/i],c=i+" "+r;return d.some(h=>h.test(c))}flushReplayChunk(){if(!this.state.replayEvents.length)return;let t=this.state.replayEvents.splice(0),e=this.state.replaySequence++,s={anonymous_id:this.state.anonId,session_id:this.state.replaySessionId,sequence:e,events:t,error_count:this.state.replayErrorCount,rage_click_count:this.state.replayRageClickCount};e===0&&(s.page_url=window.location.href,s.user_agent=navigator.userAgent,s.screen_width=window.innerWidth,s.screen_height=window.innerHeight,s.started_at=this.state.replayStartedAt),this.api("/widget/replay/chunk",s).catch(()=>{this.state.replayEvents=t.concat(this.state.replayEvents),this.state.replaySequence--})}setupRageClickDetection(){document.addEventListener("click",t=>{if(!this.state.replaySessionId)return;let e=Date.now(),s=t.target;s===this.state.lastClickTarget&&e-this.state.lastClickTime<500?(this.state.clickCount++,this.state.clickCount>=3&&(this.state.replayRageClickCount++,this.state.clickCount=0,this.track("rage_click",{page_url:window.location.href}))):this.state.clickCount=1,this.state.lastClickTime=e,this.state.lastClickTarget=s},!0)}setupErrorCapture(){window.onerror=(t,e,s,i)=>(this.state.replaySessionId&&(this.state.replayErrorCount++,this.track("js_error",{message:String(t).substring(0,500),source:e||"",lineno:s||0})),!1),window.addEventListener("unhandledrejection",t=>{if(this.state.replaySessionId){this.state.replayErrorCount++;let e=t.reason instanceof Error?t.reason.message:String(t.reason);this.track("js_error",{message:e.substring(0,500),type:"unhandledrejection"})}})}setupEmailCapture(){document.addEventListener("blur",t=>{let e=t.target;if(!e||e.tagName!=="INPUT")return;let s=(e.type||"").toLowerCase(),i=(e.name||"").toLowerCase();if(s==="email"||/email/.test(i)){let r=e.value?.trim();r&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r)&&!this.state.capturedEmails[r]&&(this.state.capturedEmails[r]=!0,this.track("email_captured",{email:r}))}},!0)}handleUnload(){if(this.state.flushTimer&&clearInterval(this.state.flushTimer),this.state.eventQ.length&&this.state.apiKey){let t=this.state.apiKey;try{fetch(this.state.apiUrl+"/widget/events",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":t},body:JSON.stringify({anonymous_id:this.state.anonId,events:this.state.eventQ}),keepalive:!0}).catch(()=>{})}catch{}}if(this.state.replaySessionId&&this.state.apiKey){let t=this.state.apiKey;this.state.replayStopFn&&this.state.replayStopFn(),this.state.replayFlushTimer&&clearInterval(this.state.replayFlushTimer);try{fetch(this.state.apiUrl+"/widget/replay/end",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":t},body:JSON.stringify({anonymous_id:this.state.anonId,session_id:this.state.replaySessionId,ended_at:new Date().toISOString(),event_count:this.state.replayTotalEvents,error_count:this.state.replayErrorCount,rage_click_count:this.state.replayRageClickCount}),keepalive:!0}).catch(()=>{})}catch{}}}};var a=new o;typeof window<"u"&&(window.MeetSudo={MeetSudo:o,meetsudo:a,init:a.init.bind(a),identify:a.identify.bind(a),track:a.track.bind(a),page:a.page.bind(a),chat:a.chat.bind(a)});return w(v);})();
1
+ "use strict";var MeetSudo=(()=>{var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var f=(n,t)=>{for(var e in t)l(n,e,{get:t[e],enumerable:!0})},v=(n,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of y(t))!m.call(n,i)&&i!==e&&l(n,i,{get:()=>t[i],enumerable:!(s=d(t,i))||s.enumerable});return n};var g=n=>v(l({},"__esModule",{value:!0}),n);var w={};f(w,{MeetSudo:()=>o,meetsudo:()=>a});var p="meetsudo_anon_id";var o=class{constructor(){this.state={apiKey:null,apiUrl:"https://api.meetsudo.com",widgetUrl:"https://widget.meetsudo.com",anonId:null,custId:null,features:null,workspaceName:null,initialized:!1,iframe:null,eventQ:[],flushTimer:null,replaySessionId:null,replaySequence:0,replayEvents:[],replayFlushTimer:null,replayStopFn:null,replayTotalEvents:0,replayStartedAt:null,replayRageClickCount:0,replayErrorCount:0,lastClickTime:0,lastClickTarget:null,clickCount:0,capturedEmails:{},lastActivityTime:Date.now(),inactivityTimer:null,replayPaused:!1};this.config=null}async init(t){if(!t.apiKey)throw new Error("MeetSudo: apiKey is required");this.config=t,this.state.apiKey=t.apiKey,this.state.apiUrl=t.apiUrl||"https://api.meetsudo.com",this.state.widgetUrl=t.widgetUrl||"https://widget.meetsudo.com",this.state.anonId=this.getAnonId();try{let e=await this.api("/widget/init",{anonymous_id:this.state.anonId,url:window.location.href,referrer:document.referrer});this.state.custId=e.customer_id,this.state.features=e.features,this.state.workspaceName=e.workspace_name,this.state.initialized=!0,e.features.chat_enabled&&!t.disableChat&&this.createIframe(e),e.features.events_enabled&&!t.disableEvents&&(this.state.flushTimer=setInterval(()=>this.flushEvents(),5e3),e.features.events_auto_page&&!t.disableAutoPageView&&this.page(),this.setupEmailCapture()),this.shouldSampleReplay()&&!t.disableReplay&&this.startReplay(),window.addEventListener("beforeunload",()=>this.handleUnload())}catch(e){throw console.error("MeetSudo: init failed",e),e}}async identify(t,e){if(!this.state.initialized){console.warn("MeetSudo: call init() before identify()");return}try{let s=await this.api("/widget/identify",{anonymous_id:this.state.anonId,external_id:t,properties:e||{}});this.state.custId=s.customer_id,this.state.iframe?.contentWindow&&this.state.iframe.contentWindow.postMessage({type:"fi:identify",customerId:s.customer_id,merged:s.merged},"*")}catch(s){console.error("MeetSudo: identify failed",s)}}track(t,e){!this.state.initialized||!this.state.features?.events_enabled||this.state.eventQ.push({name:t,properties:e||{},page_url:window.location.href,timestamp:new Date().toISOString()})}page(t){let e={url:window.location.href,title:document.title,referrer:document.referrer,...t};this.track("page_view",e)}chat(t){if(this.state.iframe?.contentWindow)switch(t){case"open":this.state.iframe.contentWindow.postMessage({type:"fi:chat",action:"open"},"*"),this.state.iframe.style.width="400px",this.state.iframe.style.height="560px";break;case"close":this.state.iframe.contentWindow.postMessage({type:"fi:chat",action:"close"},"*"),this.state.iframe.style.width="80px",this.state.iframe.style.height="80px";break;case"hide":this.state.iframe.style.display="none";break;case"show":this.state.iframe.style.display="";break}}isInitialized(){return this.state.initialized}getAnonymousId(){return this.state.anonId}getCustomerId(){return this.state.custId}getAnonId(){try{let e=localStorage.getItem(p);if(e)return e}catch{}let t=crypto.randomUUID?.()||this.generateUUID();try{localStorage.setItem(p,t)}catch{}return t}generateUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}async api(t,e){let s=await fetch(this.state.apiUrl+t,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.state.apiKey},body:JSON.stringify(e)});if(!s.ok)throw new Error(`HTTP ${s.status}`);return s.json()}createIframe(t){if(this.state.iframe)return;let e=this.state.features?.chat_position||"bottom-right",s=document.createElement("iframe");s.id="meetsudo-widget";let i=e==="bottom-left"?"left:0;":"right:0;";s.style.cssText=`position:fixed;bottom:0;${i}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`,s.allow="clipboard-write",s.src=this.state.widgetUrl,document.body.appendChild(s),this.state.iframe=s,s.onload=()=>{s.contentWindow?.postMessage({type:"fi:config",apiKey:this.state.apiKey,apiUrl:this.state.apiUrl,anonymousId:this.state.anonId,customerId:this.state.custId,workspaceName:this.state.workspaceName,features:this.state.features,conversationId:t.open_conversation_id,messages:t.messages||[]},"*")},window.addEventListener("message",r=>{r.data?.type==="fi:resize"&&(r.data.state==="open"?(s.style.width="400px",s.style.height="560px"):(s.style.width="80px",s.style.height="80px"))})}flushEvents(){if(!this.state.eventQ.length)return;let t=this.state.eventQ.splice(0);this.api("/widget/events",{anonymous_id:this.state.anonId,events:t}).catch(()=>{this.state.eventQ=t.concat(this.state.eventQ)})}shouldSampleReplay(){return this.state.features?.replay_enabled?Math.random()<(this.state.features.replay_sample_rate||0):!1}startReplay(){this.state.replaySessionId=crypto.randomUUID?.()||this.generateUUID(),this.state.replaySequence=0,this.state.replayEvents=[],this.state.replayTotalEvents=0,this.state.replayStartedAt=new Date().toISOString(),this.state.replayErrorCount=0,this.state.replayRageClickCount=0,this.setupRageClickDetection(),this.setupErrorCapture();let t=document.createElement("script");t.type="module",t.src=this.state.widgetUrl.replace(/\/?(index\.html)?$/,"")+"/replay.js",document.head.appendChild(t);let e=0,s=setInterval(()=>{e++,window.rrweb?.record?(clearInterval(s),this.initRrweb()):e>50&&(clearInterval(s),console.warn("MeetSudo: replay failed to load"))},100)}initRrweb(){this.state.replayStopFn=window.rrweb.record({emit:t=>{this.state.replayEvents.push(t),this.state.replayTotalEvents++},maskAllInputs:!1,maskInputFn:(t,e)=>this.isSensitiveInput(e)?"*".repeat(t.length||8):t,blockSelector:".meetsudo-no-record, [data-meetsudo-no-record]",inlineStylesheet:!0,sampling:{mousemove:50,mouseInteraction:!0,scroll:150,input:"last"}}),this.state.replayFlushTimer=setInterval(()=>this.flushReplayChunk(),1e4),this.setupActivityTracking()}setupActivityTracking(){let t=["mousemove","keydown","click","scroll","touchstart"],e=()=>{this.state.lastActivityTime=Date.now(),this.state.replayPaused&&this.resumeReplay(),this.state.inactivityTimer&&clearTimeout(this.state.inactivityTimer),this.state.inactivityTimer=setTimeout(()=>{this.pauseReplayDueToInactivity()},6e4)};t.forEach(s=>{document.addEventListener(s,e,{passive:!0})}),this.state.inactivityTimer=setTimeout(()=>{this.pauseReplayDueToInactivity()},6e4)}pauseReplayDueToInactivity(){this.state.replayPaused||!this.state.replaySessionId||(this.state.replayPaused=!0,this.state.replayStopFn&&(this.state.replayStopFn(),this.state.replayStopFn=null),this.flushReplayChunk(),this.state.replayFlushTimer&&(clearInterval(this.state.replayFlushTimer),this.state.replayFlushTimer=null),this.state.apiKey&&this.api("/widget/replay/end",{anonymous_id:this.state.anonId,session_id:this.state.replaySessionId,ended_at:new Date().toISOString(),event_count:this.state.replayTotalEvents,error_count:this.state.replayErrorCount,rage_click_count:this.state.replayRageClickCount,end_reason:"inactivity"}).catch(()=>{}))}resumeReplay(){!this.state.replayPaused||!this.state.features?.replay_enabled||(this.state.replayPaused=!1,this.state.replaySessionId=crypto.randomUUID?.()||this.generateUUID(),this.state.replaySequence=0,this.state.replayEvents=[],this.state.replayTotalEvents=0,this.state.replayStartedAt=new Date().toISOString(),this.state.replayErrorCount=0,this.state.replayRageClickCount=0,window.rrweb?.record&&(this.state.replayStopFn=window.rrweb.record({emit:t=>{this.state.replayEvents.push(t),this.state.replayTotalEvents++},maskAllInputs:!1,maskInputFn:(t,e)=>this.isSensitiveInput(e)?"*".repeat(t.length||8):t,blockSelector:".meetsudo-no-record, [data-meetsudo-no-record]",inlineStylesheet:!0,sampling:{mousemove:50,mouseInteraction:!0,scroll:150,input:"last"}}),this.state.replayFlushTimer=setInterval(()=>this.flushReplayChunk(),1e4)))}isSensitiveInput(t){if(!t)return!0;let e=t,s=(e.type||"").toLowerCase(),i=(e.name||"").toLowerCase(),r=(e.id||"").toLowerCase();if(s==="password")return!0;let u=[/password/i,/card/i,/cvv/i,/cvc/i,/ssn/i,/secret/i,/token/i],h=i+" "+r;return u.some(c=>c.test(h))}flushReplayChunk(){if(!this.state.replayEvents.length||this.state.replayPaused)return;let t=this.state.replayEvents.splice(0),e=this.state.replaySequence++,s={anonymous_id:this.state.anonId,session_id:this.state.replaySessionId,sequence:e,events:t,error_count:this.state.replayErrorCount,rage_click_count:this.state.replayRageClickCount};e===0&&(s.page_url=window.location.href,s.user_agent=navigator.userAgent,s.screen_width=window.innerWidth,s.screen_height=window.innerHeight,s.started_at=this.state.replayStartedAt),this.api("/widget/replay/chunk",s).catch(()=>{this.state.replayEvents=t.concat(this.state.replayEvents),this.state.replaySequence--})}setupRageClickDetection(){document.addEventListener("click",t=>{if(!this.state.replaySessionId)return;let e=Date.now(),s=t.target;s===this.state.lastClickTarget&&e-this.state.lastClickTime<500?(this.state.clickCount++,this.state.clickCount>=3&&(this.state.replayRageClickCount++,this.state.clickCount=0,this.track("rage_click",{page_url:window.location.href}))):this.state.clickCount=1,this.state.lastClickTime=e,this.state.lastClickTarget=s},!0)}setupErrorCapture(){window.onerror=(t,e,s,i)=>(this.state.replaySessionId&&(this.state.replayErrorCount++,this.track("js_error",{message:String(t).substring(0,500),source:e||"",lineno:s||0})),!1),window.addEventListener("unhandledrejection",t=>{if(this.state.replaySessionId){this.state.replayErrorCount++;let e=t.reason instanceof Error?t.reason.message:String(t.reason);this.track("js_error",{message:e.substring(0,500),type:"unhandledrejection"})}})}setupEmailCapture(){document.addEventListener("blur",t=>{let e=t.target;if(!e||e.tagName!=="INPUT")return;let s=(e.type||"").toLowerCase(),i=(e.name||"").toLowerCase();if(s==="email"||/email/.test(i)){let r=e.value?.trim();r&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r)&&!this.state.capturedEmails[r]&&(this.state.capturedEmails[r]=!0,this.track("email_captured",{email:r}))}},!0)}handleUnload(){if(this.state.flushTimer&&clearInterval(this.state.flushTimer),this.state.eventQ.length&&this.state.apiKey){let t=this.state.apiKey;try{fetch(this.state.apiUrl+"/widget/events",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":t},body:JSON.stringify({anonymous_id:this.state.anonId,events:this.state.eventQ}),keepalive:!0}).catch(()=>{})}catch{}}if(this.state.replaySessionId&&this.state.apiKey){let t=this.state.apiKey;this.state.replayStopFn&&this.state.replayStopFn(),this.state.replayFlushTimer&&clearInterval(this.state.replayFlushTimer);try{fetch(this.state.apiUrl+"/widget/replay/end",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":t},body:JSON.stringify({anonymous_id:this.state.anonId,session_id:this.state.replaySessionId,ended_at:new Date().toISOString(),event_count:this.state.replayTotalEvents,error_count:this.state.replayErrorCount,rage_click_count:this.state.replayRageClickCount}),keepalive:!0}).catch(()=>{})}catch{}}}};var a=new o;typeof window<"u"&&(window.MeetSudo={MeetSudo:o,meetsudo:a,init:a.init.bind(a),identify:a.identify.bind(a),track:a.track.bind(a),page:a.page.bind(a),chat:a.chat.bind(a)});return g(w);})();
2
2
  //# sourceMappingURL=meetsudo.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/browser.ts","../src/sdk.ts"],"sourcesContent":["/**\n * Browser bundle entry point for script tag usage\n * This file is bundled as an IIFE and exposes window.MeetSudo\n */\nimport { MeetSudo } from \"./sdk\";\nimport type { MeetSudoConfig, UserTraits, EventProperties, PageProperties, ChatAction } from \"./types\";\n\n// Create default instance\nconst meetsudo = new MeetSudo();\n\n// Export everything for the IIFE global\nexport { MeetSudo, meetsudo };\nexport type { MeetSudoConfig, UserTraits, EventProperties, PageProperties, ChatAction };\n\n// Make it available globally\nif (typeof window !== \"undefined\") {\n (window as unknown as Record<string, unknown>).MeetSudo = {\n MeetSudo,\n meetsudo,\n init: meetsudo.init.bind(meetsudo),\n identify: meetsudo.identify.bind(meetsudo),\n track: meetsudo.track.bind(meetsudo),\n page: meetsudo.page.bind(meetsudo),\n chat: meetsudo.chat.bind(meetsudo),\n };\n}\n","import type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n Features,\n InitResponse,\n IdentifyResponse,\n ChatAction,\n} from \"./types\";\n\nconst STORAGE_KEY = \"meetsudo_anon_id\";\nconst FLUSH_INTERVAL = 5000;\nconst REPLAY_FLUSH_INTERVAL = 10000;\n\ninterface EventData {\n name: string;\n properties: EventProperties;\n page_url: string;\n timestamp: string;\n}\n\ninterface State {\n apiKey: string | null;\n apiUrl: string;\n widgetUrl: string;\n anonId: string | null;\n custId: string | null;\n features: Features | null;\n workspaceName: string | null;\n initialized: boolean;\n iframe: HTMLIFrameElement | null;\n eventQ: EventData[];\n flushTimer: ReturnType<typeof setInterval> | null;\n replaySessionId: string | null;\n replaySequence: number;\n replayEvents: unknown[];\n replayFlushTimer: ReturnType<typeof setInterval> | null;\n replayStopFn: (() => void) | null;\n replayTotalEvents: number;\n replayStartedAt: string | null;\n replayRageClickCount: number;\n replayErrorCount: number;\n lastClickTime: number;\n lastClickTarget: EventTarget | null;\n clickCount: number;\n capturedEmails: Record<string, boolean>;\n}\n\nexport class MeetSudo {\n private state: State = {\n apiKey: null,\n apiUrl: \"https://api.meetsudo.com\",\n widgetUrl: \"https://widget.meetsudo.com\",\n anonId: null,\n custId: null,\n features: null,\n workspaceName: null,\n initialized: false,\n iframe: null,\n eventQ: [],\n flushTimer: null,\n replaySessionId: null,\n replaySequence: 0,\n replayEvents: [],\n replayFlushTimer: null,\n replayStopFn: null,\n replayTotalEvents: 0,\n replayStartedAt: null,\n replayRageClickCount: 0,\n replayErrorCount: 0,\n lastClickTime: 0,\n lastClickTarget: null,\n clickCount: 0,\n capturedEmails: {},\n };\n\n private config: MeetSudoConfig | null = null;\n\n /**\n * Initialize the MeetSudo SDK\n */\n async init(config: MeetSudoConfig): Promise<void> {\n if (!config.apiKey) {\n throw new Error(\"MeetSudo: apiKey is required\");\n }\n\n this.config = config;\n this.state.apiKey = config.apiKey;\n this.state.apiUrl = config.apiUrl || \"https://api.meetsudo.com\";\n this.state.widgetUrl = config.widgetUrl || \"https://widget.meetsudo.com\";\n this.state.anonId = this.getAnonId();\n\n try {\n const res = await this.api<InitResponse>(\"/widget/init\", {\n anonymous_id: this.state.anonId,\n url: window.location.href,\n referrer: document.referrer,\n });\n\n this.state.custId = res.customer_id;\n this.state.features = res.features;\n this.state.workspaceName = res.workspace_name;\n this.state.initialized = true;\n\n // Create chat iframe if enabled\n if (res.features.chat_enabled && !config.disableChat) {\n this.createIframe(res);\n }\n\n // Start event tracking if enabled\n if (res.features.events_enabled && !config.disableEvents) {\n this.state.flushTimer = setInterval(() => this.flushEvents(), FLUSH_INTERVAL);\n if (res.features.events_auto_page && !config.disableAutoPageView) {\n this.page();\n }\n this.setupEmailCapture();\n }\n\n // Start session replay if enabled and sampled in\n if (this.shouldSampleReplay() && !config.disableReplay) {\n this.startReplay();\n }\n\n // Setup beforeunload handler\n window.addEventListener(\"beforeunload\", () => this.handleUnload());\n } catch (error) {\n console.error(\"MeetSudo: init failed\", error);\n throw error;\n }\n }\n\n /**\n * Identify a user\n */\n async identify(userId: string, traits?: UserTraits): Promise<void> {\n if (!this.state.initialized) {\n console.warn(\"MeetSudo: call init() before identify()\");\n return;\n }\n\n try {\n const res = await this.api<IdentifyResponse>(\"/widget/identify\", {\n anonymous_id: this.state.anonId,\n external_id: userId,\n properties: traits || {},\n });\n\n this.state.custId = res.customer_id;\n\n // Notify chat iframe about identity change\n if (this.state.iframe?.contentWindow) {\n this.state.iframe.contentWindow.postMessage(\n {\n type: \"fi:identify\",\n customerId: res.customer_id,\n merged: res.merged,\n },\n \"*\"\n );\n }\n } catch (error) {\n console.error(\"MeetSudo: identify failed\", error);\n }\n }\n\n /**\n * Track a custom event\n */\n track(eventName: string, properties?: EventProperties): void {\n if (!this.state.initialized || !this.state.features?.events_enabled) {\n return;\n }\n\n this.state.eventQ.push({\n name: eventName,\n properties: properties || {},\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Track a page view\n */\n page(properties?: PageProperties): void {\n const props: PageProperties = {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n ...properties,\n };\n this.track(\"page_view\", props);\n }\n\n /**\n * Control the chat widget\n */\n chat(action: ChatAction): void {\n if (!this.state.iframe?.contentWindow) return;\n\n switch (action) {\n case \"open\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"open\" }, \"*\");\n this.state.iframe.style.width = \"400px\";\n this.state.iframe.style.height = \"560px\";\n break;\n case \"close\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"close\" }, \"*\");\n this.state.iframe.style.width = \"80px\";\n this.state.iframe.style.height = \"80px\";\n break;\n case \"hide\":\n this.state.iframe.style.display = \"none\";\n break;\n case \"show\":\n this.state.iframe.style.display = \"\";\n break;\n }\n }\n\n /**\n * Check if SDK is initialized\n */\n isInitialized(): boolean {\n return this.state.initialized;\n }\n\n /**\n * Get the anonymous ID\n */\n getAnonymousId(): string | null {\n return this.state.anonId;\n }\n\n /**\n * Get the customer ID (after identify)\n */\n getCustomerId(): string | null {\n return this.state.custId;\n }\n\n // Private methods\n\n private getAnonId(): string {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) return stored;\n } catch {\n /* private browsing */\n }\n\n const id = crypto.randomUUID?.() || this.generateUUID();\n try {\n localStorage.setItem(STORAGE_KEY, id);\n } catch {\n /* ignore */\n }\n return id;\n }\n\n private generateUUID(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n\n private async api<T>(path: string, data: unknown): Promise<T> {\n const res = await fetch(this.state.apiUrl + path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.state.apiKey!,\n },\n body: JSON.stringify(data),\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n\n return res.json();\n }\n\n private createIframe(initData: InitResponse): void {\n if (this.state.iframe) return;\n\n const pos = this.state.features?.chat_position || \"bottom-right\";\n const iframe = document.createElement(\"iframe\");\n iframe.id = \"meetsudo-widget\";\n const posCSS = pos === \"bottom-left\" ? \"left:0;\" : \"right:0;\";\n iframe.style.cssText = `position:fixed;bottom:0;${posCSS}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`;\n iframe.allow = \"clipboard-write\";\n iframe.src = this.state.widgetUrl;\n\n document.body.appendChild(iframe);\n this.state.iframe = iframe;\n\n iframe.onload = () => {\n iframe.contentWindow?.postMessage(\n {\n type: \"fi:config\",\n apiKey: this.state.apiKey,\n apiUrl: this.state.apiUrl,\n anonymousId: this.state.anonId,\n customerId: this.state.custId,\n workspaceName: this.state.workspaceName,\n features: this.state.features,\n conversationId: initData.open_conversation_id,\n messages: initData.messages || [],\n },\n \"*\"\n );\n };\n\n window.addEventListener(\"message\", (e) => {\n if (e.data?.type === \"fi:resize\") {\n if (e.data.state === \"open\") {\n iframe.style.width = \"400px\";\n iframe.style.height = \"560px\";\n } else {\n iframe.style.width = \"80px\";\n iframe.style.height = \"80px\";\n }\n }\n });\n }\n\n private flushEvents(): void {\n if (!this.state.eventQ.length) return;\n\n const batch = this.state.eventQ.splice(0);\n this.api(\"/widget/events\", {\n anonymous_id: this.state.anonId,\n events: batch,\n }).catch(() => {\n // Put events back on failure\n this.state.eventQ = batch.concat(this.state.eventQ);\n });\n }\n\n private shouldSampleReplay(): boolean {\n if (!this.state.features?.replay_enabled) return false;\n return Math.random() < (this.state.features.replay_sample_rate || 0);\n }\n\n private startReplay(): void {\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n this.setupRageClickDetection();\n this.setupErrorCapture();\n\n // Load rrweb dynamically\n const script = document.createElement(\"script\");\n script.type = \"module\";\n script.src = this.state.widgetUrl.replace(/\\/?(index\\.html)?$/, \"\") + \"/replay.js\";\n document.head.appendChild(script);\n\n // Wait for rrweb to load\n let attempts = 0;\n const checkRrweb = setInterval(() => {\n attempts++;\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n clearInterval(checkRrweb);\n this.initRrweb();\n } else if (attempts > 50) {\n clearInterval(checkRrweb);\n console.warn(\"MeetSudo: replay failed to load\");\n }\n }, 100);\n }\n\n private initRrweb(): void {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n }\n\n private isSensitiveInput(el: HTMLElement): boolean {\n if (!el) return true;\n const input = el as HTMLInputElement;\n const type = (input.type || \"\").toLowerCase();\n const name = (input.name || \"\").toLowerCase();\n const id = (input.id || \"\").toLowerCase();\n\n if (type === \"password\") return true;\n\n const sensitivePatterns = [/password/i, /card/i, /cvv/i, /cvc/i, /ssn/i, /secret/i, /token/i];\n const identifiers = name + \" \" + id;\n return sensitivePatterns.some((p) => p.test(identifiers));\n }\n\n private flushReplayChunk(): void {\n if (!this.state.replayEvents.length) return;\n\n const events = this.state.replayEvents.splice(0);\n const seq = this.state.replaySequence++;\n\n const payload: Record<string, unknown> = {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n sequence: seq,\n events,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n };\n\n if (seq === 0) {\n payload.page_url = window.location.href;\n payload.user_agent = navigator.userAgent;\n payload.screen_width = window.innerWidth;\n payload.screen_height = window.innerHeight;\n payload.started_at = this.state.replayStartedAt;\n }\n\n this.api(\"/widget/replay/chunk\", payload).catch(() => {\n this.state.replayEvents = events.concat(this.state.replayEvents);\n this.state.replaySequence--;\n });\n }\n\n private setupRageClickDetection(): void {\n document.addEventListener(\n \"click\",\n (e) => {\n if (!this.state.replaySessionId) return;\n\n const now = Date.now();\n const target = e.target;\n\n if (target === this.state.lastClickTarget && now - this.state.lastClickTime < 500) {\n this.state.clickCount++;\n if (this.state.clickCount >= 3) {\n this.state.replayRageClickCount++;\n this.state.clickCount = 0;\n this.track(\"rage_click\", { page_url: window.location.href });\n }\n } else {\n this.state.clickCount = 1;\n }\n\n this.state.lastClickTime = now;\n this.state.lastClickTarget = target;\n },\n true\n );\n }\n\n private setupErrorCapture(): void {\n window.onerror = (message, source, lineno, colno) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n this.track(\"js_error\", {\n message: String(message).substring(0, 500),\n source: source || \"\",\n lineno: lineno || 0,\n });\n }\n return false;\n };\n\n window.addEventListener(\"unhandledrejection\", (e) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n const message = e.reason instanceof Error ? e.reason.message : String(e.reason);\n this.track(\"js_error\", { message: message.substring(0, 500), type: \"unhandledrejection\" });\n }\n });\n }\n\n private setupEmailCapture(): void {\n document.addEventListener(\n \"blur\",\n (e) => {\n const el = e.target as HTMLInputElement;\n if (!el || el.tagName !== \"INPUT\") return;\n\n const type = (el.type || \"\").toLowerCase();\n const name = (el.name || \"\").toLowerCase();\n if (type === \"email\" || /email/.test(name)) {\n const value = el.value?.trim();\n if (value && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) && !this.state.capturedEmails[value]) {\n this.state.capturedEmails[value] = true;\n this.track(\"email_captured\", { email: value });\n }\n }\n },\n true\n );\n }\n\n private handleUnload(): void {\n if (this.state.flushTimer) {\n clearInterval(this.state.flushTimer);\n }\n\n // Flush remaining events\n if (this.state.eventQ.length && this.state.apiKey) {\n const apiKey = this.state.apiKey;\n try {\n fetch(this.state.apiUrl + \"/widget/events\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": apiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n events: this.state.eventQ,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n\n // End replay\n if (this.state.replaySessionId && this.state.apiKey) {\n const replayApiKey = this.state.apiKey;\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n }\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n }\n\n try {\n fetch(this.state.apiUrl + \"/widget/replay/end\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": replayApiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n }\n}\n"],"mappings":"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","names":["browser_exports","__export","MeetSudo","meetsudo","STORAGE_KEY","MeetSudo","config","res","error","userId","traits","eventName","properties","props","action","stored","STORAGE_KEY","id","c","r","path","data","initData","pos","iframe","posCSS","e","batch","script","attempts","checkRrweb","event","text","element","el","input","type","name","sensitivePatterns","identifiers","p","events","seq","payload","now","target","message","source","lineno","colno","value","apiKey","replayApiKey","meetsudo","MeetSudo","MeetSudo","meetsudo"]}
1
+ {"version":3,"sources":["../src/browser.ts","../src/sdk.ts"],"sourcesContent":["/**\n * Browser bundle entry point for script tag usage\n * This file is bundled as an IIFE and exposes window.MeetSudo\n */\nimport { MeetSudo } from \"./sdk\";\nimport type { MeetSudoConfig, UserTraits, EventProperties, PageProperties, ChatAction } from \"./types\";\n\n// Create default instance\nconst meetsudo = new MeetSudo();\n\n// Export everything for the IIFE global\nexport { MeetSudo, meetsudo };\nexport type { MeetSudoConfig, UserTraits, EventProperties, PageProperties, ChatAction };\n\n// Make it available globally\nif (typeof window !== \"undefined\") {\n (window as unknown as Record<string, unknown>).MeetSudo = {\n MeetSudo,\n meetsudo,\n init: meetsudo.init.bind(meetsudo),\n identify: meetsudo.identify.bind(meetsudo),\n track: meetsudo.track.bind(meetsudo),\n page: meetsudo.page.bind(meetsudo),\n chat: meetsudo.chat.bind(meetsudo),\n };\n}\n","import type {\n MeetSudoConfig,\n UserTraits,\n EventProperties,\n PageProperties,\n Features,\n InitResponse,\n IdentifyResponse,\n ChatAction,\n} from \"./types\";\n\nconst STORAGE_KEY = \"meetsudo_anon_id\";\nconst FLUSH_INTERVAL = 5000;\nconst REPLAY_FLUSH_INTERVAL = 10000;\nconst INACTIVITY_TIMEOUT = 60000; // 1 minute\n\ninterface EventData {\n name: string;\n properties: EventProperties;\n page_url: string;\n timestamp: string;\n}\n\ninterface State {\n apiKey: string | null;\n apiUrl: string;\n widgetUrl: string;\n anonId: string | null;\n custId: string | null;\n features: Features | null;\n workspaceName: string | null;\n initialized: boolean;\n iframe: HTMLIFrameElement | null;\n eventQ: EventData[];\n flushTimer: ReturnType<typeof setInterval> | null;\n replaySessionId: string | null;\n replaySequence: number;\n replayEvents: unknown[];\n replayFlushTimer: ReturnType<typeof setInterval> | null;\n replayStopFn: (() => void) | null;\n replayTotalEvents: number;\n replayStartedAt: string | null;\n replayRageClickCount: number;\n replayErrorCount: number;\n lastClickTime: number;\n lastClickTarget: EventTarget | null;\n clickCount: number;\n capturedEmails: Record<string, boolean>;\n lastActivityTime: number;\n inactivityTimer: ReturnType<typeof setTimeout> | null;\n replayPaused: boolean;\n}\n\nexport class MeetSudo {\n private state: State = {\n apiKey: null,\n apiUrl: \"https://api.meetsudo.com\",\n widgetUrl: \"https://widget.meetsudo.com\",\n anonId: null,\n custId: null,\n features: null,\n workspaceName: null,\n initialized: false,\n iframe: null,\n eventQ: [],\n flushTimer: null,\n replaySessionId: null,\n replaySequence: 0,\n replayEvents: [],\n replayFlushTimer: null,\n replayStopFn: null,\n replayTotalEvents: 0,\n replayStartedAt: null,\n replayRageClickCount: 0,\n replayErrorCount: 0,\n lastClickTime: 0,\n lastClickTarget: null,\n clickCount: 0,\n capturedEmails: {},\n lastActivityTime: Date.now(),\n inactivityTimer: null,\n replayPaused: false,\n };\n\n private config: MeetSudoConfig | null = null;\n\n /**\n * Initialize the MeetSudo SDK\n */\n async init(config: MeetSudoConfig): Promise<void> {\n if (!config.apiKey) {\n throw new Error(\"MeetSudo: apiKey is required\");\n }\n\n this.config = config;\n this.state.apiKey = config.apiKey;\n this.state.apiUrl = config.apiUrl || \"https://api.meetsudo.com\";\n this.state.widgetUrl = config.widgetUrl || \"https://widget.meetsudo.com\";\n this.state.anonId = this.getAnonId();\n\n try {\n const res = await this.api<InitResponse>(\"/widget/init\", {\n anonymous_id: this.state.anonId,\n url: window.location.href,\n referrer: document.referrer,\n });\n\n this.state.custId = res.customer_id;\n this.state.features = res.features;\n this.state.workspaceName = res.workspace_name;\n this.state.initialized = true;\n\n // Create chat iframe if enabled\n if (res.features.chat_enabled && !config.disableChat) {\n this.createIframe(res);\n }\n\n // Start event tracking if enabled\n if (res.features.events_enabled && !config.disableEvents) {\n this.state.flushTimer = setInterval(() => this.flushEvents(), FLUSH_INTERVAL);\n if (res.features.events_auto_page && !config.disableAutoPageView) {\n this.page();\n }\n this.setupEmailCapture();\n }\n\n // Start session replay if enabled and sampled in\n if (this.shouldSampleReplay() && !config.disableReplay) {\n this.startReplay();\n }\n\n // Setup beforeunload handler\n window.addEventListener(\"beforeunload\", () => this.handleUnload());\n } catch (error) {\n console.error(\"MeetSudo: init failed\", error);\n throw error;\n }\n }\n\n /**\n * Identify a user\n */\n async identify(userId: string, traits?: UserTraits): Promise<void> {\n if (!this.state.initialized) {\n console.warn(\"MeetSudo: call init() before identify()\");\n return;\n }\n\n try {\n const res = await this.api<IdentifyResponse>(\"/widget/identify\", {\n anonymous_id: this.state.anonId,\n external_id: userId,\n properties: traits || {},\n });\n\n this.state.custId = res.customer_id;\n\n // Notify chat iframe about identity change\n if (this.state.iframe?.contentWindow) {\n this.state.iframe.contentWindow.postMessage(\n {\n type: \"fi:identify\",\n customerId: res.customer_id,\n merged: res.merged,\n },\n \"*\"\n );\n }\n } catch (error) {\n console.error(\"MeetSudo: identify failed\", error);\n }\n }\n\n /**\n * Track a custom event\n */\n track(eventName: string, properties?: EventProperties): void {\n if (!this.state.initialized || !this.state.features?.events_enabled) {\n return;\n }\n\n this.state.eventQ.push({\n name: eventName,\n properties: properties || {},\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Track a page view\n */\n page(properties?: PageProperties): void {\n const props: PageProperties = {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n ...properties,\n };\n this.track(\"page_view\", props);\n }\n\n /**\n * Control the chat widget\n */\n chat(action: ChatAction): void {\n if (!this.state.iframe?.contentWindow) return;\n\n switch (action) {\n case \"open\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"open\" }, \"*\");\n this.state.iframe.style.width = \"400px\";\n this.state.iframe.style.height = \"560px\";\n break;\n case \"close\":\n this.state.iframe.contentWindow.postMessage({ type: \"fi:chat\", action: \"close\" }, \"*\");\n this.state.iframe.style.width = \"80px\";\n this.state.iframe.style.height = \"80px\";\n break;\n case \"hide\":\n this.state.iframe.style.display = \"none\";\n break;\n case \"show\":\n this.state.iframe.style.display = \"\";\n break;\n }\n }\n\n /**\n * Check if SDK is initialized\n */\n isInitialized(): boolean {\n return this.state.initialized;\n }\n\n /**\n * Get the anonymous ID\n */\n getAnonymousId(): string | null {\n return this.state.anonId;\n }\n\n /**\n * Get the customer ID (after identify)\n */\n getCustomerId(): string | null {\n return this.state.custId;\n }\n\n // Private methods\n\n private getAnonId(): string {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) return stored;\n } catch {\n /* private browsing */\n }\n\n const id = crypto.randomUUID?.() || this.generateUUID();\n try {\n localStorage.setItem(STORAGE_KEY, id);\n } catch {\n /* ignore */\n }\n return id;\n }\n\n private generateUUID(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n\n private async api<T>(path: string, data: unknown): Promise<T> {\n const res = await fetch(this.state.apiUrl + path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.state.apiKey!,\n },\n body: JSON.stringify(data),\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n\n return res.json();\n }\n\n private createIframe(initData: InitResponse): void {\n if (this.state.iframe) return;\n\n const pos = this.state.features?.chat_position || \"bottom-right\";\n const iframe = document.createElement(\"iframe\");\n iframe.id = \"meetsudo-widget\";\n const posCSS = pos === \"bottom-left\" ? \"left:0;\" : \"right:0;\";\n iframe.style.cssText = `position:fixed;bottom:0;${posCSS}width:80px;height:80px;border:none;z-index:999999;background:transparent;color-scheme:normal;`;\n iframe.allow = \"clipboard-write\";\n iframe.src = this.state.widgetUrl;\n\n document.body.appendChild(iframe);\n this.state.iframe = iframe;\n\n iframe.onload = () => {\n iframe.contentWindow?.postMessage(\n {\n type: \"fi:config\",\n apiKey: this.state.apiKey,\n apiUrl: this.state.apiUrl,\n anonymousId: this.state.anonId,\n customerId: this.state.custId,\n workspaceName: this.state.workspaceName,\n features: this.state.features,\n conversationId: initData.open_conversation_id,\n messages: initData.messages || [],\n },\n \"*\"\n );\n };\n\n window.addEventListener(\"message\", (e) => {\n if (e.data?.type === \"fi:resize\") {\n if (e.data.state === \"open\") {\n iframe.style.width = \"400px\";\n iframe.style.height = \"560px\";\n } else {\n iframe.style.width = \"80px\";\n iframe.style.height = \"80px\";\n }\n }\n });\n }\n\n private flushEvents(): void {\n if (!this.state.eventQ.length) return;\n\n const batch = this.state.eventQ.splice(0);\n this.api(\"/widget/events\", {\n anonymous_id: this.state.anonId,\n events: batch,\n }).catch(() => {\n // Put events back on failure\n this.state.eventQ = batch.concat(this.state.eventQ);\n });\n }\n\n private shouldSampleReplay(): boolean {\n if (!this.state.features?.replay_enabled) return false;\n return Math.random() < (this.state.features.replay_sample_rate || 0);\n }\n\n private startReplay(): void {\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n this.setupRageClickDetection();\n this.setupErrorCapture();\n\n // Load rrweb dynamically\n const script = document.createElement(\"script\");\n script.type = \"module\";\n script.src = this.state.widgetUrl.replace(/\\/?(index\\.html)?$/, \"\") + \"/replay.js\";\n document.head.appendChild(script);\n\n // Wait for rrweb to load\n let attempts = 0;\n const checkRrweb = setInterval(() => {\n attempts++;\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n clearInterval(checkRrweb);\n this.initRrweb();\n } else if (attempts > 50) {\n clearInterval(checkRrweb);\n console.warn(\"MeetSudo: replay failed to load\");\n }\n }, 100);\n }\n\n private initRrweb(): void {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n\n // Setup inactivity tracking\n this.setupActivityTracking();\n }\n\n private setupActivityTracking(): void {\n const activityEvents = [\"mousemove\", \"keydown\", \"click\", \"scroll\", \"touchstart\"];\n\n const handleActivity = () => {\n this.state.lastActivityTime = Date.now();\n\n // Resume replay if it was paused\n if (this.state.replayPaused) {\n this.resumeReplay();\n }\n\n // Reset inactivity timer\n if (this.state.inactivityTimer) {\n clearTimeout(this.state.inactivityTimer);\n }\n\n this.state.inactivityTimer = setTimeout(() => {\n this.pauseReplayDueToInactivity();\n }, INACTIVITY_TIMEOUT);\n };\n\n // Add event listeners\n activityEvents.forEach((event) => {\n document.addEventListener(event, handleActivity, { passive: true });\n });\n\n // Start initial inactivity timer\n this.state.inactivityTimer = setTimeout(() => {\n this.pauseReplayDueToInactivity();\n }, INACTIVITY_TIMEOUT);\n }\n\n private pauseReplayDueToInactivity(): void {\n if (this.state.replayPaused || !this.state.replaySessionId) return;\n\n this.state.replayPaused = true;\n\n // Stop rrweb recording\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n this.state.replayStopFn = null;\n }\n\n // Flush remaining events\n this.flushReplayChunk();\n\n // Stop flush timer\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n this.state.replayFlushTimer = null;\n }\n\n // Send end signal with inactivity flag\n if (this.state.apiKey) {\n this.api(\"/widget/replay/end\", {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n end_reason: \"inactivity\",\n }).catch(() => {});\n }\n }\n\n private resumeReplay(): void {\n if (!this.state.replayPaused || !this.state.features?.replay_enabled) return;\n\n this.state.replayPaused = false;\n\n // Start a new replay session\n this.state.replaySessionId = crypto.randomUUID?.() || this.generateUUID();\n this.state.replaySequence = 0;\n this.state.replayEvents = [];\n this.state.replayTotalEvents = 0;\n this.state.replayStartedAt = new Date().toISOString();\n this.state.replayErrorCount = 0;\n this.state.replayRageClickCount = 0;\n\n // Restart rrweb recording\n // @ts-expect-error rrweb is loaded dynamically\n if (window.rrweb?.record) {\n // @ts-expect-error rrweb is loaded dynamically\n this.state.replayStopFn = window.rrweb.record({\n emit: (event: unknown) => {\n this.state.replayEvents.push(event);\n this.state.replayTotalEvents++;\n },\n maskAllInputs: false,\n maskInputFn: (text: string, element: HTMLElement) => {\n if (this.isSensitiveInput(element)) {\n return \"*\".repeat(text.length || 8);\n }\n return text;\n },\n blockSelector: \".meetsudo-no-record, [data-meetsudo-no-record]\",\n inlineStylesheet: true,\n sampling: {\n mousemove: 50,\n mouseInteraction: true,\n scroll: 150,\n input: \"last\",\n },\n });\n\n this.state.replayFlushTimer = setInterval(() => this.flushReplayChunk(), REPLAY_FLUSH_INTERVAL);\n }\n }\n\n private isSensitiveInput(el: HTMLElement): boolean {\n if (!el) return true;\n const input = el as HTMLInputElement;\n const type = (input.type || \"\").toLowerCase();\n const name = (input.name || \"\").toLowerCase();\n const id = (input.id || \"\").toLowerCase();\n\n if (type === \"password\") return true;\n\n const sensitivePatterns = [/password/i, /card/i, /cvv/i, /cvc/i, /ssn/i, /secret/i, /token/i];\n const identifiers = name + \" \" + id;\n return sensitivePatterns.some((p) => p.test(identifiers));\n }\n\n private flushReplayChunk(): void {\n if (!this.state.replayEvents.length || this.state.replayPaused) return;\n\n const events = this.state.replayEvents.splice(0);\n const seq = this.state.replaySequence++;\n\n const payload: Record<string, unknown> = {\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n sequence: seq,\n events,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n };\n\n if (seq === 0) {\n payload.page_url = window.location.href;\n payload.user_agent = navigator.userAgent;\n payload.screen_width = window.innerWidth;\n payload.screen_height = window.innerHeight;\n payload.started_at = this.state.replayStartedAt;\n }\n\n this.api(\"/widget/replay/chunk\", payload).catch(() => {\n this.state.replayEvents = events.concat(this.state.replayEvents);\n this.state.replaySequence--;\n });\n }\n\n private setupRageClickDetection(): void {\n document.addEventListener(\n \"click\",\n (e) => {\n if (!this.state.replaySessionId) return;\n\n const now = Date.now();\n const target = e.target;\n\n if (target === this.state.lastClickTarget && now - this.state.lastClickTime < 500) {\n this.state.clickCount++;\n if (this.state.clickCount >= 3) {\n this.state.replayRageClickCount++;\n this.state.clickCount = 0;\n this.track(\"rage_click\", { page_url: window.location.href });\n }\n } else {\n this.state.clickCount = 1;\n }\n\n this.state.lastClickTime = now;\n this.state.lastClickTarget = target;\n },\n true\n );\n }\n\n private setupErrorCapture(): void {\n window.onerror = (message, source, lineno, colno) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n this.track(\"js_error\", {\n message: String(message).substring(0, 500),\n source: source || \"\",\n lineno: lineno || 0,\n });\n }\n return false;\n };\n\n window.addEventListener(\"unhandledrejection\", (e) => {\n if (this.state.replaySessionId) {\n this.state.replayErrorCount++;\n const message = e.reason instanceof Error ? e.reason.message : String(e.reason);\n this.track(\"js_error\", { message: message.substring(0, 500), type: \"unhandledrejection\" });\n }\n });\n }\n\n private setupEmailCapture(): void {\n document.addEventListener(\n \"blur\",\n (e) => {\n const el = e.target as HTMLInputElement;\n if (!el || el.tagName !== \"INPUT\") return;\n\n const type = (el.type || \"\").toLowerCase();\n const name = (el.name || \"\").toLowerCase();\n if (type === \"email\" || /email/.test(name)) {\n const value = el.value?.trim();\n if (value && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) && !this.state.capturedEmails[value]) {\n this.state.capturedEmails[value] = true;\n this.track(\"email_captured\", { email: value });\n }\n }\n },\n true\n );\n }\n\n private handleUnload(): void {\n if (this.state.flushTimer) {\n clearInterval(this.state.flushTimer);\n }\n\n // Flush remaining events\n if (this.state.eventQ.length && this.state.apiKey) {\n const apiKey = this.state.apiKey;\n try {\n fetch(this.state.apiUrl + \"/widget/events\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": apiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n events: this.state.eventQ,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n\n // End replay\n if (this.state.replaySessionId && this.state.apiKey) {\n const replayApiKey = this.state.apiKey;\n if (this.state.replayStopFn) {\n this.state.replayStopFn();\n }\n if (this.state.replayFlushTimer) {\n clearInterval(this.state.replayFlushTimer);\n }\n\n try {\n fetch(this.state.apiUrl + \"/widget/replay/end\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": replayApiKey,\n },\n body: JSON.stringify({\n anonymous_id: this.state.anonId,\n session_id: this.state.replaySessionId,\n ended_at: new Date().toISOString(),\n event_count: this.state.replayTotalEvents,\n error_count: this.state.replayErrorCount,\n rage_click_count: this.state.replayRageClickCount,\n }),\n keepalive: true,\n }).catch(() => {});\n } catch {\n /* ignore */\n }\n }\n }\n}\n"],"mappings":"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","names":["browser_exports","__export","MeetSudo","meetsudo","STORAGE_KEY","MeetSudo","config","res","error","userId","traits","eventName","properties","props","action","stored","STORAGE_KEY","id","c","r","path","data","initData","pos","iframe","posCSS","e","batch","script","attempts","checkRrweb","event","text","element","activityEvents","handleActivity","el","input","type","name","sensitivePatterns","identifiers","p","events","seq","payload","now","target","message","source","lineno","colno","value","apiKey","replayApiKey","meetsudo","MeetSudo","MeetSudo","meetsudo"]}
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@meet-sudo/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "MeetSudo SDK - Chat, Analytics, Session Replay",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "meet-sudo": "./dist/cli.js"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
13
  "types": "./dist/index.d.ts",