@jam.dev/recording-links 0.3.0-electron.5 → 0.3.1

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/lib/electron.d.ts CHANGED
@@ -145,7 +145,7 @@ export declare function initialize(config: {
145
145
  * jam.openRecorder('abc123');
146
146
  *
147
147
  * // Open with title
148
- * jam.openRecorder({ recordingId: 'abc123', title: 'Bug Report' });
148
+ * jam.openRecorder({ recordingId: 'abc123', jamTitle: 'Bug Report' });
149
149
  *
150
150
  * // Open with URLSearchParams (from protocol handler)
151
151
  * const params = new URLSearchParams('jam-recording=abc123&jam-title=Bug+Report');
@@ -165,7 +165,9 @@ export interface IJamData {
165
165
  /** Jam recording ID */
166
166
  readonly recordingId: string;
167
167
  /** Optional recording title */
168
- readonly title: string | undefined | null;
168
+ readonly jamTitle: string | undefined | null;
169
+ /** Optional recording state JWT */
170
+ readonly state: string | undefined | null;
169
171
  /**
170
172
  * URLSearchParams containing jam-* query parameters.
171
173
  * Follows the same convention as URL.searchParams.
@@ -179,12 +181,14 @@ export interface IJamData {
179
181
  }
180
182
  declare class JamData implements IJamData {
181
183
  readonly recordingId: string;
182
- readonly title: string | undefined | null;
184
+ readonly jamTitle: string | undefined | null;
185
+ readonly state: string | undefined | null;
183
186
  get searchParams(): URLSearchParams;
184
187
  get search(): string;
185
188
  constructor(init: URLSearchParams | {
186
189
  recordingId: string;
187
- title?: string | null;
190
+ jamTitle?: string | null;
191
+ state?: string | null;
188
192
  });
189
193
  }
190
194
  export declare function isJamRecorder(win: BrowserWindow | null): boolean;
package/lib/electron.js CHANGED
@@ -1 +1 @@
1
- import{app as e,session as r,webContents as t,BrowserWindow as n,desktopCapturer as o}from"electron";const s={defaultSession:null,windows:new Map,openRecorderWindow(){throw new Error("Not initialized")},loadRecorderPage(){throw new Error("Not initialized")}},i=(e,r)=>{const s=e.frame,i=s?t.fromFrame(s):null,a=i?n.fromWebContents(i):null;u(a)?o.getSources({types:["screen","window"]}).then(e=>f(e,r,a)).catch(e=>{r({})}):r({})};async function a(t){if(!e.isReady())return e.whenReady().then(()=>a(t));const{defaultSession:n=r.defaultSession,defaultDisplayMediaRequestHandler:o=i}=t;s.defaultSession=n,s.openRecorderWindow=t.openRecorderWindow,s.loadRecorderPage=t.loadRecorderPage,o&&n.setDisplayMediaRequestHandler(o,{useSystemPicker:!0})}function d(e,r){const t=r??s.defaultSession;if(null===t)throw new Error("Cannot open recorder: no `session` found or provided");let n=s.windows.get(t);n||(n=s.openRecorderWindow(t),s.windows.set(t,n),n.on("closed",()=>s.windows.delete(t)));const o="string"==typeof e?new l({recordingId:e}):e instanceof l?e:new l(e);return s.loadRecorderPage(n,o).catch(e=>{}),n.isMinimized()&&n.restore(),n.focus(),n}function c(e,r){const t="string"==typeof e?new URL(e):e,n=new URLSearchParams;for(const[e,r]of t.searchParams.entries())e.startsWith("jam-")&&(n.set(e,r),t.searchParams.delete(e));return[t.href,n.has("jam-recording")?d(new l(n),r):null]}class l{get searchParams(){const e=new URLSearchParams;return e.set("jam-recording",this.recordingId),this.title&&e.set("jam-title",this.title),e}get search(){const e=this.searchParams.toString();return e?`?${e}`:""}constructor(e){if(e instanceof URLSearchParams){const r=e.get("jam-recording");if(!r)throw new Error("Missing jam-recording parameter");this.recordingId=r,this.title=e.get("jam-title")}else this.recordingId=e.recordingId,this.title=e.title||null}}function u(e){for(const r of s.windows.values())if(r===e)return!0;return!1}function f(e,r,t){const n=t?.getMediaSourceId(),o=e.filter(e=>!e.name.includes("DevTools")&&e.id!==n),s=o.find(e=>e.id.startsWith("window:")),i=o.find(e=>e.id.startsWith("screen:")),a=s||i||o[0];r(a?{video:a,audio:"loopback"}:{})}export{f as handleDisplayMediaRequest,a as initialize,u as isJamRecorder,d as openRecorder,c as openUrl};//# sourceMappingURL=electron.js.map
1
+ import{app as e,session as t,webContents as r,BrowserWindow as n,desktopCapturer as o}from"electron";const s={defaultSession:null,windows:new Map,openRecorderWindow(){throw new Error("Not initialized")},loadRecorderPage(){throw new Error("Not initialized")}},i=(e,t)=>{const s=e.frame,i=s?r.fromFrame(s):null,a=i?n.fromWebContents(i):null;u(a)?o.getSources({types:["screen","window"]}).then(e=>f(e,t,a)).catch(e=>{t({})}):t({})};async function a(r){if(!e.isReady())return e.whenReady().then(()=>a(r));const{defaultSession:n=t.defaultSession,defaultDisplayMediaRequestHandler:o=i}=r;s.defaultSession=n,s.openRecorderWindow=r.openRecorderWindow,s.loadRecorderPage=r.loadRecorderPage,o&&n.setDisplayMediaRequestHandler(o,{useSystemPicker:!0})}function d(e,t){const r=t??s.defaultSession;if(null===r)throw new Error("Cannot open recorder: no `session` found or provided");let n=s.windows.get(r);n||(n=s.openRecorderWindow(r),s.windows.set(r,n),n.on("closed",()=>s.windows.delete(r)));const o="string"==typeof e?new l({recordingId:e}):e instanceof l?e:new l(e);return s.loadRecorderPage(n,o).catch(e=>{}),n.isMinimized()&&n.restore(),n.focus(),n}function c(e,t){const r="string"==typeof e?new URL(e):e,n=new URLSearchParams;for(const[e,t]of r.searchParams.entries())e.startsWith("jam-")&&(n.set(e,t),r.searchParams.delete(e));return[r.href,n.has("jam-recording")?d(new l(n),t):null]}class l{get searchParams(){const e=new URLSearchParams;return e.set("jam-recording",this.recordingId),this.jamTitle&&e.set("jam-title",this.jamTitle),this.state&&e.set("jam-state",this.state),e}get search(){const e=this.searchParams.toString();return e?`?${e}`:""}constructor(e){if(e instanceof URLSearchParams){const t=e.get("jam-recording");if(!t)throw new Error("Missing jam-recording parameter");this.recordingId=t,this.jamTitle=e.get("jam-title"),this.state=e.get("jam-state")}else this.recordingId=e.recordingId,this.jamTitle=e.jamTitle||null,this.state=e.state||null}}function u(e){for(const t of s.windows.values())if(t===e)return!0;return!1}function f(e,t,r){const n=r?.getMediaSourceId(),o=e.filter(e=>!e.name.includes("DevTools")&&e.id!==n),s=o.find(e=>e.id.startsWith("window:")),i=o.find(e=>e.id.startsWith("screen:")),a=s||i||o[0];t(a?{video:a,audio:"loopback"}:{})}export{f as handleDisplayMediaRequest,a as initialize,u as isJamRecorder,d as openRecorder,c as openUrl};//# sourceMappingURL=electron.js.map
package/lib/sdk.d.ts CHANGED
@@ -23,12 +23,14 @@ type RecorderSingleton = {
23
23
  * @param recordingId - The ID of the recording to open
24
24
  * @param params - Optional parameters for opening the recorder
25
25
  * @param params.jamTitle - Optional title for the recording
26
+ * @param params.state - Optional JWT state for the recording
26
27
  * @param params.removeOnEscape - Whether to remove the opened recorder on Escape presses. Default: true
27
28
  * @param params.applyJamData - Custom function to apply recording data to URL
28
29
  * @returns Unknown - TODO: expose a public API for opened recorders
29
30
  */
30
31
  open(recordingId: string, params?: Pick<InitializeOptions, "applyJamData"> & {
31
32
  jamTitle?: string | null;
33
+ state?: string | null;
32
34
  /** Whether to remove the opened recorder on Escape presses. Default: true */
33
35
  removeOnEscape?: boolean;
34
36
  }): unknown;
@@ -54,8 +56,8 @@ type InitializeOptions = {
54
56
  */
55
57
  openImmediately?: boolean | string | undefined | null;
56
58
  /**
57
- * Extract a `recordingId` and `jamTitle` from the provided string.
58
- * Defaults to reading the `jam-recording` and `jam-title` QSPs off the URL.
59
+ * Extract a `recordingId`, `jamTitle`, and `state` from the provided string.
60
+ * Defaults to reading the `jam-recording`, `jam-title`, and `jam-state` QSPs off the URL.
59
61
  */
60
62
  parseJamData?(input: string): SerializableJamData | null;
61
63
  /**
@@ -75,6 +77,8 @@ export type SerializableJamData = {
75
77
  recordingId: string | null;
76
78
  /** The human-readable title of the recording, or null if not present */
77
79
  jamTitle: string | null;
80
+ /** The JWT state passed in the URL, or null if not present */
81
+ state?: string | null;
78
82
  };
79
83
  declare function resetForTesting(): void;
80
84
  /** @internal - Reset SDK state for testing (only available in dev builds) */
package/lib/sdk.js CHANGED
@@ -1,4 +1,4 @@
1
- function e(){const e=new EventTarget;return{addEventListener(t,n,r){e.addEventListener(t,n,r)},removeEventListener(t,n,r){e.removeEventListener(t,n,r)},dispatch:(t,n)=>e.dispatchEvent(new CustomEvent(t,{detail:n}))}}const t=(t,n=localStorage)=>{const r=`jam:${t}`,i=e();let o=null;try{o=n.getItem(r)}catch(e){}const a={count:Number.parseInt(o??"0",10)||0,addEventListener:i.addEventListener.bind(i),removeEventListener:i.removeEventListener.bind(i),update(e){const t=a.count;switch(e){case"increment":a.count+=1;break;case"decrement":a.count-=1;break;default:a.count=e}if(a.count<0&&(a.count=0),a.count!==t){try{n.setItem(r,`${a.count}`)}catch(e){}Object.assign(a,{count:a.count}),i.dispatch("update",a.count)}return a.count}};return window.addEventListener("storage",e=>{if(e.storageArea===n&&e.key===r){const t=Number.parseInt(e.newValue??"",10);Number.isNaN(t)||t===a.count||(a.count=t,i.dispatch("update",a.count))}}),a},n=e=>{try{const t=new URL(e);return{recordingId:t.searchParams.get("jam-recording"),jamTitle:t.searchParams.get("jam-title")}}catch(e){}return null},r={isInitialized:!1},i=void 0,o=e(),a=o.addEventListener.bind(o),c=o.removeEventListener.bind(o),d=()=>r.isInitialized;let s=null;function u({recorderRefCounter:e=t("numRecorders"),_loadRemoteScript:i=m,...o}={}){if(r.isInitialized)throw new Error("SDK already initialized.");Object.assign(r,{isInitialized:!0,recorderRefCounter:e,config:o,_loadRemoteScript:i}),e.count>0?p():e.addEventListener("update",p,{once:!0}),window.addEventListener("popstate",c);const a={apply(e,t,n){const r=Reflect.apply(e,t,n);return c(),r}};function c(){if(s)return;const e=r.config?.parseJamData??n,t="string"==typeof r.config?.openImmediately?r.config.openImmediately:e(window.location.href)?.recordingId;t&&l({openImmediately:!1!==r.config?.openImmediately&&t})}history.pushState=new Proxy(history.pushState,a),history.replaceState=new Proxy(history.replaceState,a),c()}async function l({...e}={}){if(s)return s;if(!r.isInitialized)throw new Error("SDK not initialized. Call initialize() first.");if(({Recorder:s}=await r._loadRemoteScript("recorder")),!s)throw new Error("Failed to load recorder script.");const{openImmediately:t,...n}={...r.config,...e},i="string"==typeof t?t:null;return s.initialize({...n,openImmediately:!i&&(t??!0)}),r.recorderRefCounter.update("increment"),window.addEventListener("pagehide",()=>{r.recorderRefCounter.update("decrement")}),i&&s.open(i,n),s}async function p(){if(!r.isInitialized||!r._loadRemoteScript)throw new Error("SDK not initialized. Call initialize() first.");const{Capture:e}=await r._loadRemoteScript("capture")??{};await(e?.initialize(r.config))}async function m(e){const t=`https://js.jam.dev/${e}.js`,n=await import(
1
+ function e(){const e=new EventTarget;return{addEventListener(t,n,r){e.addEventListener(t,n,r)},removeEventListener(t,n,r){e.removeEventListener(t,n,r)},dispatch:(t,n)=>e.dispatchEvent(new CustomEvent(t,{detail:n}))}}const t=(t,n=localStorage)=>{const r=`jam:${t}`,i=e();let o=null;try{o=n.getItem(r)}catch(e){}const a={count:Number.parseInt(o??"0",10)||0,addEventListener:i.addEventListener.bind(i),removeEventListener:i.removeEventListener.bind(i),update(e){const t=a.count;switch(e){case"increment":a.count+=1;break;case"decrement":a.count-=1;break;default:a.count=e}if(a.count<0&&(a.count=0),a.count!==t){try{n.setItem(r,`${a.count}`)}catch(e){}Object.assign(a,{count:a.count}),i.dispatch("update",a.count)}return a.count}};return window.addEventListener("storage",e=>{if(e.storageArea===n&&e.key===r){const t=Number.parseInt(e.newValue??"",10);Number.isNaN(t)||t===a.count||(a.count=t,i.dispatch("update",a.count))}}),a},n=e=>{try{const t=new URL(e);return{recordingId:t.searchParams.get("jam-recording"),jamTitle:t.searchParams.get("jam-title"),state:t.searchParams.get("jam-state")}}catch(e){}return null},r={isInitialized:!1},i=void 0,o=e(),a=o.addEventListener.bind(o),c=o.removeEventListener.bind(o),d=()=>r.isInitialized;let s=null;function u({recorderRefCounter:e=t("numRecorders"),_loadRemoteScript:i=m,...o}={}){if(r.isInitialized)throw new Error("SDK already initialized.");Object.assign(r,{isInitialized:!0,recorderRefCounter:e,config:o,_loadRemoteScript:i}),e.count>0?p():e.addEventListener("update",p,{once:!0}),window.addEventListener("popstate",c);const a={apply(e,t,n){const r=Reflect.apply(e,t,n);return c(),r}};function c(){if(s)return;const e=r.config?.parseJamData??n,t="string"==typeof r.config?.openImmediately?r.config.openImmediately:e(window.location.href)?.recordingId;t&&l({openImmediately:!1!==r.config?.openImmediately&&t})}history.pushState=new Proxy(history.pushState,a),history.replaceState=new Proxy(history.replaceState,a),c()}async function l({...e}={}){if(s)return s;if(!r.isInitialized)throw new Error("SDK not initialized. Call initialize() first.");if(({Recorder:s}=await r._loadRemoteScript("recorder")),!s)throw new Error("Failed to load recorder script.");const{openImmediately:t,...n}={...r.config,...e},i="string"==typeof t?t:null;return s.initialize({...n,openImmediately:!i&&(t??!0)}),r.recorderRefCounter.update("increment"),window.addEventListener("pagehide",()=>{r.recorderRefCounter.update("decrement")}),i&&s.open(i,n),s}async function p(){if(!r.isInitialized||!r._loadRemoteScript)throw new Error("SDK not initialized. Call initialize() first.");const{Capture:e}=await r._loadRemoteScript("capture")??{};await(e?.initialize(r.config))}async function m(e){const t=`https://js.jam.dev/${e}.js`,n=await import(
2
2
  /* webpackIgnore: true */
3
3
  /* @vite-ignore */
4
4
  /* @rollup/plugin-dynamic-import-vars ignore */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jam.dev/recording-links",
3
- "version": "0.3.0-electron.5",
3
+ "version": "0.3.1",
4
4
  "description": "Capture bug reports from your users with the Jam recording links SDK",
5
5
  "keywords": [
6
6
  "jam",