swish-recorder 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,11 +29,15 @@ npm install swish-recorder
29
29
  pnpm add swish-recorder
30
30
  ```
31
31
 
32
+ `posthog-js` must already be installed in your project. `swish-recorder` has no dependencies of its own.
33
+
32
34
  ---
33
35
 
34
36
  ## Usage
35
37
 
36
- Call `SwishRecorder.init` right after `posthog.init`, passing in the same PostHog instance. The project token is read automatically — no extra credentials needed.
38
+ ### Vanilla JS
39
+
40
+ Call `SwishRecorder.init` right after `posthog.init`. The project token is read automatically from the PostHog instance — no extra credentials needed.
37
41
 
38
42
  ```ts
39
43
  import posthog from 'posthog-js'
@@ -49,26 +53,35 @@ SwishRecorder.init({ posthog })
49
53
 
50
54
  ### React
51
55
 
56
+ Initialize PostHog before mounting your app, then pass the instance to `PostHogProvider` via `client=`. Call `SwishRecorder.init` in between — before `createRoot`.
57
+
52
58
  ```tsx
53
59
  // src/main.tsx
60
+ import { StrictMode } from 'react'
61
+ import { createRoot } from 'react-dom/client'
54
62
  import posthog from 'posthog-js'
55
63
  import { PostHogProvider } from 'posthog-js/react'
56
64
  import { SwishRecorder } from 'swish-recorder'
65
+ import App from './App'
57
66
 
58
- posthog.init('phc_your_project_token', {
59
- api_host: 'https://eu.i.posthog.com',
67
+ posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_TOKEN, {
68
+ api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
60
69
  defaults: '2026-01-30',
61
70
  })
62
71
 
63
72
  SwishRecorder.init({ posthog })
64
73
 
65
74
  createRoot(document.getElementById('root')!).render(
66
- <PostHogProvider client={posthog}>
67
- <App />
68
- </PostHogProvider>
75
+ <StrictMode>
76
+ <PostHogProvider client={posthog}>
77
+ <App />
78
+ </PostHogProvider>
79
+ </StrictMode>
69
80
  )
70
81
  ```
71
82
 
83
+ > If you use `@posthog/react` instead of `posthog-js/react`, replace the import accordingly — the API is identical.
84
+
72
85
  ---
73
86
 
74
87
  ## API
package/dist/index.cjs CHANGED
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
26
  var API_HOST = "https://api.swish.is";
27
+ var PREFIX = "[swish-recorder]";
27
28
  var SwishRecorder = class _SwishRecorder {
28
29
  constructor(config) {
29
30
  this.config = config;
@@ -31,12 +32,19 @@ var SwishRecorder = class _SwishRecorder {
31
32
  this.unsubscribeSessionId = null;
32
33
  this.handleUnload = null;
33
34
  }
35
+ _log(...args) {
36
+ if (this.config.debug) console.log(PREFIX, ...args);
37
+ }
38
+ _warn(...args) {
39
+ if (this.config.debug) console.warn(PREFIX, ...args);
40
+ }
34
41
  static init(config) {
35
42
  const instance = new _SwishRecorder(config);
36
43
  instance._setup();
37
44
  return instance;
38
45
  }
39
46
  _sendSessionEnd(sessionId, reason) {
47
+ this._log(`session end \u2014 session=${sessionId} reason=${reason}`);
40
48
  navigator.sendBeacon(
41
49
  `${API_HOST}/replays/session-end`,
42
50
  new Blob(
@@ -52,6 +60,9 @@ var SwishRecorder = class _SwishRecorder {
52
60
  );
53
61
  }
54
62
  _ingestSnapshot(sessionId, windowId, snapshotData, distinctId) {
63
+ this._log(
64
+ `ingesting snapshot \u2014 session=${sessionId} window=${windowId} distinct_id=${distinctId}`
65
+ );
55
66
  fetch(`${API_HOST}/replays/ingest`, {
56
67
  method: "POST",
57
68
  headers: {
@@ -65,11 +76,26 @@ var SwishRecorder = class _SwishRecorder {
65
76
  distinct_id: distinctId,
66
77
  timestamp: Date.now()
67
78
  })
68
- }).catch(() => {
79
+ }).then((res) => {
80
+ if (this.config.debug) {
81
+ if (res.ok) {
82
+ this._log(`ingest OK \u2014 ${res.status}`);
83
+ } else {
84
+ this._warn(`ingest failed \u2014 ${res.status} ${res.statusText}`);
85
+ }
86
+ }
87
+ }).catch((err) => {
88
+ this._warn("ingest error \u2014", err);
69
89
  });
70
90
  }
71
91
  _setup() {
72
92
  const { posthog } = this.config;
93
+ const token = posthog.config.token;
94
+ this._log(`init \u2014 token=${token.slice(0, 12)}\u2026`);
95
+ if (!token) {
96
+ this._warn("no PostHog token found \u2014 recording disabled");
97
+ return;
98
+ }
73
99
  const snapshotHandler = (event) => {
74
100
  if ((event == null ? void 0 : event.event) === "$snapshot") {
75
101
  const props = event.properties;
@@ -79,15 +105,23 @@ var SwishRecorder = class _SwishRecorder {
79
105
  props.$snapshot_data,
80
106
  props.distinct_id
81
107
  );
108
+ } else if (this.config.debug && event) {
109
+ this._log(`before_send passthrough \u2014 event=${event.event}`);
82
110
  }
83
111
  return event;
84
112
  };
85
113
  const existing = posthog.config.before_send;
114
+ this._log(
115
+ `before_send \u2014 existing handler: ${existing ? Array.isArray(existing) ? `array(${existing.length})` : "function" : "none"}`
116
+ );
86
117
  posthog.set_config({
87
118
  before_send: existing ? Array.isArray(existing) ? [...existing, snapshotHandler] : [existing, snapshotHandler] : snapshotHandler
88
119
  });
89
120
  this.unsubscribeSessionId = posthog.onSessionId(
90
121
  (newSessionId, _windowId, changeReason) => {
122
+ this._log(
123
+ `session ID changed \u2014 new=${newSessionId} reason=${JSON.stringify(changeReason != null ? changeReason : null)}`
124
+ );
91
125
  if (this.currentSessionId && changeReason) {
92
126
  const reason = changeReason.activityTimeout ? "activity_timeout" : changeReason.sessionPastMaximumLength ? "session_length" : null;
93
127
  if (reason) this._sendSessionEnd(this.currentSessionId, reason);
@@ -100,9 +134,11 @@ var SwishRecorder = class _SwishRecorder {
100
134
  this._sendSessionEnd(this.currentSessionId, "tab_close");
101
135
  };
102
136
  window.addEventListener("beforeunload", this.handleUnload);
137
+ this._log("ready");
103
138
  }
104
139
  destroy() {
105
140
  var _a;
141
+ this._log("destroy");
106
142
  (_a = this.unsubscribeSessionId) == null ? void 0 : _a.call(this);
107
143
  if (this.handleUnload) {
108
144
  window.removeEventListener("beforeunload", this.handleUnload);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Minimal PostHog interface — no posthog-js dependency needed\ninterface PostHogLike {\n set_config(config: { before_send?: unknown }): void;\n onSessionId(\n callback: (\n sessionId: string,\n windowId: string | null | undefined,\n changeReason?: {\n activityTimeout?: boolean;\n sessionPastMaximumLength?: boolean;\n },\n ) => void,\n ): () => void;\n readonly config: {\n token: string;\n before_send?: unknown;\n };\n}\n\ntype BeforeSendFn = (\n event: { event: string; properties: Record<string, unknown> } | null,\n) => { event: string; properties: Record<string, unknown> } | null;\n\nconst API_HOST = \"https://api.swish.is\";\n\nexport interface SwishRecorderConfig {\n /** PostHog instance from your app — token is read automatically. */\n posthog: PostHogLike;\n}\n\nexport class SwishRecorder {\n private currentSessionId: string | null = null;\n private unsubscribeSessionId: (() => void) | null = null;\n private handleUnload: (() => void) | null = null;\n\n private constructor(private readonly config: SwishRecorderConfig) {}\n\n static init(config: SwishRecorderConfig): SwishRecorder {\n const instance = new SwishRecorder(config);\n instance._setup();\n return instance;\n }\n\n private _sendSessionEnd(sessionId: string, reason: string): void {\n navigator.sendBeacon(\n `${API_HOST}/replays/session-end`,\n new Blob(\n [\n JSON.stringify({\n session_id: sessionId,\n reason,\n token: this.config.posthog.config.token,\n }),\n ],\n { type: \"application/json\" },\n ),\n );\n }\n\n private _ingestSnapshot(\n sessionId: string,\n windowId: string,\n snapshotData: unknown,\n distinctId: string,\n ): void {\n fetch(`${API_HOST}/replays/ingest`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-PostHog-Token\": this.config.posthog.config.token,\n },\n body: JSON.stringify({\n session_id: sessionId,\n window_id: windowId,\n snapshot_data: snapshotData,\n distinct_id: distinctId,\n timestamp: Date.now(),\n }),\n }).catch(() => {\n // fire and forgetnever block the main thread\n });\n }\n\n private _setup(): void {\n const { posthog } = this.config;\n\n // 1. Intercept $snapshot events via before_send (non-destructive append)\n const snapshotHandler: BeforeSendFn = (event) => {\n if (event?.event === \"$snapshot\") {\n const props = event.properties;\n this._ingestSnapshot(\n props.$session_id as string,\n props.$window_id as string,\n props.$snapshot_data,\n props.distinct_id as string,\n );\n }\n return event;\n };\n\n const existing = posthog.config.before_send;\n posthog.set_config({\n before_send: existing\n ? Array.isArray(existing)\n ? [...(existing as BeforeSendFn[]), snapshotHandler]\n : [existing as BeforeSendFn, snapshotHandler]\n : snapshotHandler,\n });\n\n // 2. Session rotation signal — fires on idle timeout or max session length\n this.unsubscribeSessionId = posthog.onSessionId(\n (newSessionId, _windowId, changeReason) => {\n if (this.currentSessionId && changeReason) {\n const reason = changeReason.activityTimeout\n ? \"activity_timeout\"\n : changeReason.sessionPastMaximumLength\n ? \"session_length\"\n : null;\n if (reason) this._sendSessionEnd(this.currentSessionId, reason);\n }\n this.currentSessionId = newSessionId;\n },\n );\n\n // 3. Tab close — sendBeacon survives page unload, fetch does not\n this.handleUnload = () => {\n if (this.currentSessionId)\n this._sendSessionEnd(this.currentSessionId, \"tab_close\");\n };\n window.addEventListener(\"beforeunload\", this.handleUnload);\n }\n\n destroy(): void {\n this.unsubscribeSessionId?.();\n if (this.handleUnload) {\n window.removeEventListener(\"beforeunload\", this.handleUnload);\n }\n this.unsubscribeSessionId = null;\n this.handleUnload = null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBA,IAAM,WAAW;AAOV,IAAM,gBAAN,MAAM,eAAc;AAAA,EAKjB,YAA6B,QAA6B;AAA7B;AAJrC,SAAQ,mBAAkC;AAC1C,SAAQ,uBAA4C;AACpD,SAAQ,eAAoC;AAAA,EAEuB;AAAA,EAEnE,OAAO,KAAK,QAA4C;AACtD,UAAM,WAAW,IAAI,eAAc,MAAM;AACzC,aAAS,OAAO;AAChB,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,WAAmB,QAAsB;AAC/D,cAAU;AAAA,MACR,GAAG,QAAQ;AAAA,MACX,IAAI;AAAA,QACF;AAAA,UACE,KAAK,UAAU;AAAA,YACb,YAAY;AAAA,YACZ;AAAA,YACA,OAAO,KAAK,OAAO,QAAQ,OAAO;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,QACA,EAAE,MAAM,mBAAmB;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBACN,WACA,UACA,cACA,YACM;AACN,UAAM,GAAG,QAAQ,mBAAmB;AAAA,MAClC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,mBAAmB,KAAK,OAAO,QAAQ,OAAO;AAAA,MAChD;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,eAAe;AAAA,QACf,aAAa;AAAA,QACb,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH,CAAC,EAAE,MAAM,MAAM;AAAA,IAEf,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,UAAM,EAAE,QAAQ,IAAI,KAAK;AAGzB,UAAM,kBAAgC,CAAC,UAAU;AAC/C,WAAI,+BAAO,WAAU,aAAa;AAChC,cAAM,QAAQ,MAAM;AACpB,aAAK;AAAA,UACH,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,QAAQ,OAAO;AAChC,YAAQ,WAAW;AAAA,MACjB,aAAa,WACT,MAAM,QAAQ,QAAQ,IACpB,CAAC,GAAI,UAA6B,eAAe,IACjD,CAAC,UAA0B,eAAe,IAC5C;AAAA,IACN,CAAC;AAGD,SAAK,uBAAuB,QAAQ;AAAA,MAClC,CAAC,cAAc,WAAW,iBAAiB;AACzC,YAAI,KAAK,oBAAoB,cAAc;AACzC,gBAAM,SAAS,aAAa,kBACxB,qBACA,aAAa,2BACX,mBACA;AACN,cAAI,OAAQ,MAAK,gBAAgB,KAAK,kBAAkB,MAAM;AAAA,QAChE;AACA,aAAK,mBAAmB;AAAA,MAC1B;AAAA,IACF;AAGA,SAAK,eAAe,MAAM;AACxB,UAAI,KAAK;AACP,aAAK,gBAAgB,KAAK,kBAAkB,WAAW;AAAA,IAC3D;AACA,WAAO,iBAAiB,gBAAgB,KAAK,YAAY;AAAA,EAC3D;AAAA,EAEA,UAAgB;AApIlB;AAqII,eAAK,yBAAL;AACA,QAAI,KAAK,cAAc;AACrB,aAAO,oBAAoB,gBAAgB,KAAK,YAAY;AAAA,IAC9D;AACA,SAAK,uBAAuB;AAC5B,SAAK,eAAe;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Minimal PostHog interface — no posthog-js dependency needed\ninterface PostHogLike {\n set_config(config: { before_send?: unknown }): void;\n onSessionId(\n callback: (\n sessionId: string,\n windowId: string | null | undefined,\n changeReason?: {\n activityTimeout?: boolean;\n sessionPastMaximumLength?: boolean;\n },\n ) => void,\n ): () => void;\n readonly config: {\n token: string;\n before_send?: unknown;\n };\n}\n\ntype BeforeSendFn = (\n event: { event: string; properties: Record<string, unknown> } | null,\n) => { event: string; properties: Record<string, unknown> } | null;\n\nconst API_HOST = \"https://api.swish.is\";\nconst PREFIX = \"[swish-recorder]\";\n\nexport interface SwishRecorderConfig {\n /** PostHog instance from your app — token is read automatically. */\n posthog: PostHogLike;\n /** Enable console logging for debugging. */\n debug?: boolean;\n}\n\nexport class SwishRecorder {\n private currentSessionId: string | null = null;\n private unsubscribeSessionId: (() => void) | null = null;\n private handleUnload: (() => void) | null = null;\n\n private constructor(private readonly config: SwishRecorderConfig) {}\n\n private _log(...args: unknown[]): void {\n if (this.config.debug) console.log(PREFIX, ...args);\n }\n\n private _warn(...args: unknown[]): void {\n if (this.config.debug) console.warn(PREFIX, ...args);\n }\n\n static init(config: SwishRecorderConfig): SwishRecorder {\n const instance = new SwishRecorder(config);\n instance._setup();\n return instance;\n }\n\n private _sendSessionEnd(sessionId: string, reason: string): void {\n this._log(`session end — session=${sessionId} reason=${reason}`);\n navigator.sendBeacon(\n `${API_HOST}/replays/session-end`,\n new Blob(\n [\n JSON.stringify({\n session_id: sessionId,\n reason,\n token: this.config.posthog.config.token,\n }),\n ],\n { type: \"application/json\" },\n ),\n );\n }\n\n private _ingestSnapshot(\n sessionId: string,\n windowId: string,\n snapshotData: unknown,\n distinctId: string,\n ): void {\n this._log(\n `ingesting snapshot — session=${sessionId} window=${windowId} distinct_id=${distinctId}`,\n );\n fetch(`${API_HOST}/replays/ingest`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-PostHog-Token\": this.config.posthog.config.token,\n },\n body: JSON.stringify({\n session_id: sessionId,\n window_id: windowId,\n snapshot_data: snapshotData,\n distinct_id: distinctId,\n timestamp: Date.now(),\n }),\n })\n .then((res) => {\n if (this.config.debug) {\n if (res.ok) {\n this._log(`ingest OK ${res.status}`);\n } else {\n this._warn(`ingest failed — ${res.status} ${res.statusText}`);\n }\n }\n })\n .catch((err) => {\n this._warn(\"ingest error —\", err);\n });\n }\n\n private _setup(): void {\n const { posthog } = this.config;\n const token = posthog.config.token;\n\n this._log(`init — token=${token.slice(0, 12)}…`);\n\n if (!token) {\n this._warn(\"no PostHog token found — recording disabled\");\n return;\n }\n\n // 1. Intercept $snapshot events via before_send (non-destructive append)\n const snapshotHandler: BeforeSendFn = (event) => {\n if (event?.event === \"$snapshot\") {\n const props = event.properties;\n this._ingestSnapshot(\n props.$session_id as string,\n props.$window_id as string,\n props.$snapshot_data,\n props.distinct_id as string,\n );\n } else if (this.config.debug && event) {\n this._log(`before_send passthrough — event=${event.event}`);\n }\n return event;\n };\n\n const existing = posthog.config.before_send;\n this._log(\n `before_send — existing handler: ${existing ? (Array.isArray(existing) ? `array(${(existing as unknown[]).length})` : \"function\") : \"none\"}`,\n );\n posthog.set_config({\n before_send: existing\n ? Array.isArray(existing)\n ? [...(existing as BeforeSendFn[]), snapshotHandler]\n : [existing as BeforeSendFn, snapshotHandler]\n : snapshotHandler,\n });\n\n // 2. Session rotation signal — fires on idle timeout or max session length\n this.unsubscribeSessionId = posthog.onSessionId(\n (newSessionId, _windowId, changeReason) => {\n this._log(\n `session ID changed — new=${newSessionId} reason=${JSON.stringify(changeReason ?? null)}`,\n );\n if (this.currentSessionId && changeReason) {\n const reason = changeReason.activityTimeout\n ? \"activity_timeout\"\n : changeReason.sessionPastMaximumLength\n ? \"session_length\"\n : null;\n if (reason) this._sendSessionEnd(this.currentSessionId, reason);\n }\n this.currentSessionId = newSessionId;\n },\n );\n\n // 3. Tab close — sendBeacon survives page unload, fetch does not\n this.handleUnload = () => {\n if (this.currentSessionId)\n this._sendSessionEnd(this.currentSessionId, \"tab_close\");\n };\n window.addEventListener(\"beforeunload\", this.handleUnload);\n\n this._log(\"ready\");\n }\n\n destroy(): void {\n this._log(\"destroy\");\n this.unsubscribeSessionId?.();\n if (this.handleUnload) {\n window.removeEventListener(\"beforeunload\", this.handleUnload);\n }\n this.unsubscribeSessionId = null;\n this.handleUnload = null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBA,IAAM,WAAW;AACjB,IAAM,SAAS;AASR,IAAM,gBAAN,MAAM,eAAc;AAAA,EAKjB,YAA6B,QAA6B;AAA7B;AAJrC,SAAQ,mBAAkC;AAC1C,SAAQ,uBAA4C;AACpD,SAAQ,eAAoC;AAAA,EAEuB;AAAA,EAE3D,QAAQ,MAAuB;AACrC,QAAI,KAAK,OAAO,MAAO,SAAQ,IAAI,QAAQ,GAAG,IAAI;AAAA,EACpD;AAAA,EAEQ,SAAS,MAAuB;AACtC,QAAI,KAAK,OAAO,MAAO,SAAQ,KAAK,QAAQ,GAAG,IAAI;AAAA,EACrD;AAAA,EAEA,OAAO,KAAK,QAA4C;AACtD,UAAM,WAAW,IAAI,eAAc,MAAM;AACzC,aAAS,OAAO;AAChB,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,WAAmB,QAAsB;AAC/D,SAAK,KAAK,8BAAyB,SAAS,WAAW,MAAM,EAAE;AAC/D,cAAU;AAAA,MACR,GAAG,QAAQ;AAAA,MACX,IAAI;AAAA,QACF;AAAA,UACE,KAAK,UAAU;AAAA,YACb,YAAY;AAAA,YACZ;AAAA,YACA,OAAO,KAAK,OAAO,QAAQ,OAAO;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,QACA,EAAE,MAAM,mBAAmB;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBACN,WACA,UACA,cACA,YACM;AACN,SAAK;AAAA,MACH,qCAAgC,SAAS,WAAW,QAAQ,gBAAgB,UAAU;AAAA,IACxF;AACA,UAAM,GAAG,QAAQ,mBAAmB;AAAA,MAClC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,mBAAmB,KAAK,OAAO,QAAQ,OAAO;AAAA,MAChD;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,eAAe;AAAA,QACf,aAAa;AAAA,QACb,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH,CAAC,EACE,KAAK,CAAC,QAAQ;AACb,UAAI,KAAK,OAAO,OAAO;AACrB,YAAI,IAAI,IAAI;AACV,eAAK,KAAK,oBAAe,IAAI,MAAM,EAAE;AAAA,QACvC,OAAO;AACL,eAAK,MAAM,wBAAmB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,QAC9D;AAAA,MACF;AAAA,IACF,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,WAAK,MAAM,uBAAkB,GAAG;AAAA,IAClC,CAAC;AAAA,EACL;AAAA,EAEQ,SAAe;AACrB,UAAM,EAAE,QAAQ,IAAI,KAAK;AACzB,UAAM,QAAQ,QAAQ,OAAO;AAE7B,SAAK,KAAK,qBAAgB,MAAM,MAAM,GAAG,EAAE,CAAC,QAAG;AAE/C,QAAI,CAAC,OAAO;AACV,WAAK,MAAM,kDAA6C;AACxD;AAAA,IACF;AAGA,UAAM,kBAAgC,CAAC,UAAU;AAC/C,WAAI,+BAAO,WAAU,aAAa;AAChC,cAAM,QAAQ,MAAM;AACpB,aAAK;AAAA,UACH,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF,WAAW,KAAK,OAAO,SAAS,OAAO;AACrC,aAAK,KAAK,wCAAmC,MAAM,KAAK,EAAE;AAAA,MAC5D;AACA,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,QAAQ,OAAO;AAChC,SAAK;AAAA,MACH,wCAAmC,WAAY,MAAM,QAAQ,QAAQ,IAAI,SAAU,SAAuB,MAAM,MAAM,aAAc,MAAM;AAAA,IAC5I;AACA,YAAQ,WAAW;AAAA,MACjB,aAAa,WACT,MAAM,QAAQ,QAAQ,IACpB,CAAC,GAAI,UAA6B,eAAe,IACjD,CAAC,UAA0B,eAAe,IAC5C;AAAA,IACN,CAAC;AAGD,SAAK,uBAAuB,QAAQ;AAAA,MAClC,CAAC,cAAc,WAAW,iBAAiB;AACzC,aAAK;AAAA,UACH,iCAA4B,YAAY,WAAW,KAAK,UAAU,sCAAgB,IAAI,CAAC;AAAA,QACzF;AACA,YAAI,KAAK,oBAAoB,cAAc;AACzC,gBAAM,SAAS,aAAa,kBACxB,qBACA,aAAa,2BACX,mBACA;AACN,cAAI,OAAQ,MAAK,gBAAgB,KAAK,kBAAkB,MAAM;AAAA,QAChE;AACA,aAAK,mBAAmB;AAAA,MAC1B;AAAA,IACF;AAGA,SAAK,eAAe,MAAM;AACxB,UAAI,KAAK;AACP,aAAK,gBAAgB,KAAK,kBAAkB,WAAW;AAAA,IAC3D;AACA,WAAO,iBAAiB,gBAAgB,KAAK,YAAY;AAEzD,SAAK,KAAK,OAAO;AAAA,EACnB;AAAA,EAEA,UAAgB;AA/KlB;AAgLI,SAAK,KAAK,SAAS;AACnB,eAAK,yBAAL;AACA,QAAI,KAAK,cAAc;AACrB,aAAO,oBAAoB,gBAAgB,KAAK,YAAY;AAAA,IAC9D;AACA,SAAK,uBAAuB;AAC5B,SAAK,eAAe;AAAA,EACtB;AACF;","names":[]}
package/dist/index.d.cts CHANGED
@@ -14,6 +14,8 @@ interface PostHogLike {
14
14
  interface SwishRecorderConfig {
15
15
  /** PostHog instance from your app — token is read automatically. */
16
16
  posthog: PostHogLike;
17
+ /** Enable console logging for debugging. */
18
+ debug?: boolean;
17
19
  }
18
20
  declare class SwishRecorder {
19
21
  private readonly config;
@@ -21,6 +23,8 @@ declare class SwishRecorder {
21
23
  private unsubscribeSessionId;
22
24
  private handleUnload;
23
25
  private constructor();
26
+ private _log;
27
+ private _warn;
24
28
  static init(config: SwishRecorderConfig): SwishRecorder;
25
29
  private _sendSessionEnd;
26
30
  private _ingestSnapshot;
package/dist/index.d.ts CHANGED
@@ -14,6 +14,8 @@ interface PostHogLike {
14
14
  interface SwishRecorderConfig {
15
15
  /** PostHog instance from your app — token is read automatically. */
16
16
  posthog: PostHogLike;
17
+ /** Enable console logging for debugging. */
18
+ debug?: boolean;
17
19
  }
18
20
  declare class SwishRecorder {
19
21
  private readonly config;
@@ -21,6 +23,8 @@ declare class SwishRecorder {
21
23
  private unsubscribeSessionId;
22
24
  private handleUnload;
23
25
  private constructor();
26
+ private _log;
27
+ private _warn;
24
28
  static init(config: SwishRecorderConfig): SwishRecorder;
25
29
  private _sendSessionEnd;
26
30
  private _ingestSnapshot;
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/index.ts
2
2
  var API_HOST = "https://api.swish.is";
3
+ var PREFIX = "[swish-recorder]";
3
4
  var SwishRecorder = class _SwishRecorder {
4
5
  constructor(config) {
5
6
  this.config = config;
@@ -7,12 +8,19 @@ var SwishRecorder = class _SwishRecorder {
7
8
  this.unsubscribeSessionId = null;
8
9
  this.handleUnload = null;
9
10
  }
11
+ _log(...args) {
12
+ if (this.config.debug) console.log(PREFIX, ...args);
13
+ }
14
+ _warn(...args) {
15
+ if (this.config.debug) console.warn(PREFIX, ...args);
16
+ }
10
17
  static init(config) {
11
18
  const instance = new _SwishRecorder(config);
12
19
  instance._setup();
13
20
  return instance;
14
21
  }
15
22
  _sendSessionEnd(sessionId, reason) {
23
+ this._log(`session end \u2014 session=${sessionId} reason=${reason}`);
16
24
  navigator.sendBeacon(
17
25
  `${API_HOST}/replays/session-end`,
18
26
  new Blob(
@@ -28,6 +36,9 @@ var SwishRecorder = class _SwishRecorder {
28
36
  );
29
37
  }
30
38
  _ingestSnapshot(sessionId, windowId, snapshotData, distinctId) {
39
+ this._log(
40
+ `ingesting snapshot \u2014 session=${sessionId} window=${windowId} distinct_id=${distinctId}`
41
+ );
31
42
  fetch(`${API_HOST}/replays/ingest`, {
32
43
  method: "POST",
33
44
  headers: {
@@ -41,11 +52,26 @@ var SwishRecorder = class _SwishRecorder {
41
52
  distinct_id: distinctId,
42
53
  timestamp: Date.now()
43
54
  })
44
- }).catch(() => {
55
+ }).then((res) => {
56
+ if (this.config.debug) {
57
+ if (res.ok) {
58
+ this._log(`ingest OK \u2014 ${res.status}`);
59
+ } else {
60
+ this._warn(`ingest failed \u2014 ${res.status} ${res.statusText}`);
61
+ }
62
+ }
63
+ }).catch((err) => {
64
+ this._warn("ingest error \u2014", err);
45
65
  });
46
66
  }
47
67
  _setup() {
48
68
  const { posthog } = this.config;
69
+ const token = posthog.config.token;
70
+ this._log(`init \u2014 token=${token.slice(0, 12)}\u2026`);
71
+ if (!token) {
72
+ this._warn("no PostHog token found \u2014 recording disabled");
73
+ return;
74
+ }
49
75
  const snapshotHandler = (event) => {
50
76
  if ((event == null ? void 0 : event.event) === "$snapshot") {
51
77
  const props = event.properties;
@@ -55,15 +81,23 @@ var SwishRecorder = class _SwishRecorder {
55
81
  props.$snapshot_data,
56
82
  props.distinct_id
57
83
  );
84
+ } else if (this.config.debug && event) {
85
+ this._log(`before_send passthrough \u2014 event=${event.event}`);
58
86
  }
59
87
  return event;
60
88
  };
61
89
  const existing = posthog.config.before_send;
90
+ this._log(
91
+ `before_send \u2014 existing handler: ${existing ? Array.isArray(existing) ? `array(${existing.length})` : "function" : "none"}`
92
+ );
62
93
  posthog.set_config({
63
94
  before_send: existing ? Array.isArray(existing) ? [...existing, snapshotHandler] : [existing, snapshotHandler] : snapshotHandler
64
95
  });
65
96
  this.unsubscribeSessionId = posthog.onSessionId(
66
97
  (newSessionId, _windowId, changeReason) => {
98
+ this._log(
99
+ `session ID changed \u2014 new=${newSessionId} reason=${JSON.stringify(changeReason != null ? changeReason : null)}`
100
+ );
67
101
  if (this.currentSessionId && changeReason) {
68
102
  const reason = changeReason.activityTimeout ? "activity_timeout" : changeReason.sessionPastMaximumLength ? "session_length" : null;
69
103
  if (reason) this._sendSessionEnd(this.currentSessionId, reason);
@@ -76,9 +110,11 @@ var SwishRecorder = class _SwishRecorder {
76
110
  this._sendSessionEnd(this.currentSessionId, "tab_close");
77
111
  };
78
112
  window.addEventListener("beforeunload", this.handleUnload);
113
+ this._log("ready");
79
114
  }
80
115
  destroy() {
81
116
  var _a;
117
+ this._log("destroy");
82
118
  (_a = this.unsubscribeSessionId) == null ? void 0 : _a.call(this);
83
119
  if (this.handleUnload) {
84
120
  window.removeEventListener("beforeunload", this.handleUnload);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Minimal PostHog interface — no posthog-js dependency needed\ninterface PostHogLike {\n set_config(config: { before_send?: unknown }): void;\n onSessionId(\n callback: (\n sessionId: string,\n windowId: string | null | undefined,\n changeReason?: {\n activityTimeout?: boolean;\n sessionPastMaximumLength?: boolean;\n },\n ) => void,\n ): () => void;\n readonly config: {\n token: string;\n before_send?: unknown;\n };\n}\n\ntype BeforeSendFn = (\n event: { event: string; properties: Record<string, unknown> } | null,\n) => { event: string; properties: Record<string, unknown> } | null;\n\nconst API_HOST = \"https://api.swish.is\";\n\nexport interface SwishRecorderConfig {\n /** PostHog instance from your app — token is read automatically. */\n posthog: PostHogLike;\n}\n\nexport class SwishRecorder {\n private currentSessionId: string | null = null;\n private unsubscribeSessionId: (() => void) | null = null;\n private handleUnload: (() => void) | null = null;\n\n private constructor(private readonly config: SwishRecorderConfig) {}\n\n static init(config: SwishRecorderConfig): SwishRecorder {\n const instance = new SwishRecorder(config);\n instance._setup();\n return instance;\n }\n\n private _sendSessionEnd(sessionId: string, reason: string): void {\n navigator.sendBeacon(\n `${API_HOST}/replays/session-end`,\n new Blob(\n [\n JSON.stringify({\n session_id: sessionId,\n reason,\n token: this.config.posthog.config.token,\n }),\n ],\n { type: \"application/json\" },\n ),\n );\n }\n\n private _ingestSnapshot(\n sessionId: string,\n windowId: string,\n snapshotData: unknown,\n distinctId: string,\n ): void {\n fetch(`${API_HOST}/replays/ingest`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-PostHog-Token\": this.config.posthog.config.token,\n },\n body: JSON.stringify({\n session_id: sessionId,\n window_id: windowId,\n snapshot_data: snapshotData,\n distinct_id: distinctId,\n timestamp: Date.now(),\n }),\n }).catch(() => {\n // fire and forgetnever block the main thread\n });\n }\n\n private _setup(): void {\n const { posthog } = this.config;\n\n // 1. Intercept $snapshot events via before_send (non-destructive append)\n const snapshotHandler: BeforeSendFn = (event) => {\n if (event?.event === \"$snapshot\") {\n const props = event.properties;\n this._ingestSnapshot(\n props.$session_id as string,\n props.$window_id as string,\n props.$snapshot_data,\n props.distinct_id as string,\n );\n }\n return event;\n };\n\n const existing = posthog.config.before_send;\n posthog.set_config({\n before_send: existing\n ? Array.isArray(existing)\n ? [...(existing as BeforeSendFn[]), snapshotHandler]\n : [existing as BeforeSendFn, snapshotHandler]\n : snapshotHandler,\n });\n\n // 2. Session rotation signal — fires on idle timeout or max session length\n this.unsubscribeSessionId = posthog.onSessionId(\n (newSessionId, _windowId, changeReason) => {\n if (this.currentSessionId && changeReason) {\n const reason = changeReason.activityTimeout\n ? \"activity_timeout\"\n : changeReason.sessionPastMaximumLength\n ? \"session_length\"\n : null;\n if (reason) this._sendSessionEnd(this.currentSessionId, reason);\n }\n this.currentSessionId = newSessionId;\n },\n );\n\n // 3. Tab close — sendBeacon survives page unload, fetch does not\n this.handleUnload = () => {\n if (this.currentSessionId)\n this._sendSessionEnd(this.currentSessionId, \"tab_close\");\n };\n window.addEventListener(\"beforeunload\", this.handleUnload);\n }\n\n destroy(): void {\n this.unsubscribeSessionId?.();\n if (this.handleUnload) {\n window.removeEventListener(\"beforeunload\", this.handleUnload);\n }\n this.unsubscribeSessionId = null;\n this.handleUnload = null;\n }\n}\n"],"mappings":";AAuBA,IAAM,WAAW;AAOV,IAAM,gBAAN,MAAM,eAAc;AAAA,EAKjB,YAA6B,QAA6B;AAA7B;AAJrC,SAAQ,mBAAkC;AAC1C,SAAQ,uBAA4C;AACpD,SAAQ,eAAoC;AAAA,EAEuB;AAAA,EAEnE,OAAO,KAAK,QAA4C;AACtD,UAAM,WAAW,IAAI,eAAc,MAAM;AACzC,aAAS,OAAO;AAChB,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,WAAmB,QAAsB;AAC/D,cAAU;AAAA,MACR,GAAG,QAAQ;AAAA,MACX,IAAI;AAAA,QACF;AAAA,UACE,KAAK,UAAU;AAAA,YACb,YAAY;AAAA,YACZ;AAAA,YACA,OAAO,KAAK,OAAO,QAAQ,OAAO;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,QACA,EAAE,MAAM,mBAAmB;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBACN,WACA,UACA,cACA,YACM;AACN,UAAM,GAAG,QAAQ,mBAAmB;AAAA,MAClC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,mBAAmB,KAAK,OAAO,QAAQ,OAAO;AAAA,MAChD;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,eAAe;AAAA,QACf,aAAa;AAAA,QACb,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH,CAAC,EAAE,MAAM,MAAM;AAAA,IAEf,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,UAAM,EAAE,QAAQ,IAAI,KAAK;AAGzB,UAAM,kBAAgC,CAAC,UAAU;AAC/C,WAAI,+BAAO,WAAU,aAAa;AAChC,cAAM,QAAQ,MAAM;AACpB,aAAK;AAAA,UACH,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,QAAQ,OAAO;AAChC,YAAQ,WAAW;AAAA,MACjB,aAAa,WACT,MAAM,QAAQ,QAAQ,IACpB,CAAC,GAAI,UAA6B,eAAe,IACjD,CAAC,UAA0B,eAAe,IAC5C;AAAA,IACN,CAAC;AAGD,SAAK,uBAAuB,QAAQ;AAAA,MAClC,CAAC,cAAc,WAAW,iBAAiB;AACzC,YAAI,KAAK,oBAAoB,cAAc;AACzC,gBAAM,SAAS,aAAa,kBACxB,qBACA,aAAa,2BACX,mBACA;AACN,cAAI,OAAQ,MAAK,gBAAgB,KAAK,kBAAkB,MAAM;AAAA,QAChE;AACA,aAAK,mBAAmB;AAAA,MAC1B;AAAA,IACF;AAGA,SAAK,eAAe,MAAM;AACxB,UAAI,KAAK;AACP,aAAK,gBAAgB,KAAK,kBAAkB,WAAW;AAAA,IAC3D;AACA,WAAO,iBAAiB,gBAAgB,KAAK,YAAY;AAAA,EAC3D;AAAA,EAEA,UAAgB;AApIlB;AAqII,eAAK,yBAAL;AACA,QAAI,KAAK,cAAc;AACrB,aAAO,oBAAoB,gBAAgB,KAAK,YAAY;AAAA,IAC9D;AACA,SAAK,uBAAuB;AAC5B,SAAK,eAAe;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Minimal PostHog interface — no posthog-js dependency needed\ninterface PostHogLike {\n set_config(config: { before_send?: unknown }): void;\n onSessionId(\n callback: (\n sessionId: string,\n windowId: string | null | undefined,\n changeReason?: {\n activityTimeout?: boolean;\n sessionPastMaximumLength?: boolean;\n },\n ) => void,\n ): () => void;\n readonly config: {\n token: string;\n before_send?: unknown;\n };\n}\n\ntype BeforeSendFn = (\n event: { event: string; properties: Record<string, unknown> } | null,\n) => { event: string; properties: Record<string, unknown> } | null;\n\nconst API_HOST = \"https://api.swish.is\";\nconst PREFIX = \"[swish-recorder]\";\n\nexport interface SwishRecorderConfig {\n /** PostHog instance from your app — token is read automatically. */\n posthog: PostHogLike;\n /** Enable console logging for debugging. */\n debug?: boolean;\n}\n\nexport class SwishRecorder {\n private currentSessionId: string | null = null;\n private unsubscribeSessionId: (() => void) | null = null;\n private handleUnload: (() => void) | null = null;\n\n private constructor(private readonly config: SwishRecorderConfig) {}\n\n private _log(...args: unknown[]): void {\n if (this.config.debug) console.log(PREFIX, ...args);\n }\n\n private _warn(...args: unknown[]): void {\n if (this.config.debug) console.warn(PREFIX, ...args);\n }\n\n static init(config: SwishRecorderConfig): SwishRecorder {\n const instance = new SwishRecorder(config);\n instance._setup();\n return instance;\n }\n\n private _sendSessionEnd(sessionId: string, reason: string): void {\n this._log(`session end — session=${sessionId} reason=${reason}`);\n navigator.sendBeacon(\n `${API_HOST}/replays/session-end`,\n new Blob(\n [\n JSON.stringify({\n session_id: sessionId,\n reason,\n token: this.config.posthog.config.token,\n }),\n ],\n { type: \"application/json\" },\n ),\n );\n }\n\n private _ingestSnapshot(\n sessionId: string,\n windowId: string,\n snapshotData: unknown,\n distinctId: string,\n ): void {\n this._log(\n `ingesting snapshot — session=${sessionId} window=${windowId} distinct_id=${distinctId}`,\n );\n fetch(`${API_HOST}/replays/ingest`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-PostHog-Token\": this.config.posthog.config.token,\n },\n body: JSON.stringify({\n session_id: sessionId,\n window_id: windowId,\n snapshot_data: snapshotData,\n distinct_id: distinctId,\n timestamp: Date.now(),\n }),\n })\n .then((res) => {\n if (this.config.debug) {\n if (res.ok) {\n this._log(`ingest OK ${res.status}`);\n } else {\n this._warn(`ingest failed — ${res.status} ${res.statusText}`);\n }\n }\n })\n .catch((err) => {\n this._warn(\"ingest error —\", err);\n });\n }\n\n private _setup(): void {\n const { posthog } = this.config;\n const token = posthog.config.token;\n\n this._log(`init — token=${token.slice(0, 12)}…`);\n\n if (!token) {\n this._warn(\"no PostHog token found — recording disabled\");\n return;\n }\n\n // 1. Intercept $snapshot events via before_send (non-destructive append)\n const snapshotHandler: BeforeSendFn = (event) => {\n if (event?.event === \"$snapshot\") {\n const props = event.properties;\n this._ingestSnapshot(\n props.$session_id as string,\n props.$window_id as string,\n props.$snapshot_data,\n props.distinct_id as string,\n );\n } else if (this.config.debug && event) {\n this._log(`before_send passthrough — event=${event.event}`);\n }\n return event;\n };\n\n const existing = posthog.config.before_send;\n this._log(\n `before_send — existing handler: ${existing ? (Array.isArray(existing) ? `array(${(existing as unknown[]).length})` : \"function\") : \"none\"}`,\n );\n posthog.set_config({\n before_send: existing\n ? Array.isArray(existing)\n ? [...(existing as BeforeSendFn[]), snapshotHandler]\n : [existing as BeforeSendFn, snapshotHandler]\n : snapshotHandler,\n });\n\n // 2. Session rotation signal — fires on idle timeout or max session length\n this.unsubscribeSessionId = posthog.onSessionId(\n (newSessionId, _windowId, changeReason) => {\n this._log(\n `session ID changed — new=${newSessionId} reason=${JSON.stringify(changeReason ?? null)}`,\n );\n if (this.currentSessionId && changeReason) {\n const reason = changeReason.activityTimeout\n ? \"activity_timeout\"\n : changeReason.sessionPastMaximumLength\n ? \"session_length\"\n : null;\n if (reason) this._sendSessionEnd(this.currentSessionId, reason);\n }\n this.currentSessionId = newSessionId;\n },\n );\n\n // 3. Tab close — sendBeacon survives page unload, fetch does not\n this.handleUnload = () => {\n if (this.currentSessionId)\n this._sendSessionEnd(this.currentSessionId, \"tab_close\");\n };\n window.addEventListener(\"beforeunload\", this.handleUnload);\n\n this._log(\"ready\");\n }\n\n destroy(): void {\n this._log(\"destroy\");\n this.unsubscribeSessionId?.();\n if (this.handleUnload) {\n window.removeEventListener(\"beforeunload\", this.handleUnload);\n }\n this.unsubscribeSessionId = null;\n this.handleUnload = null;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swish-recorder",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "First-party session recording SDK for Swish",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",