@jam.dev/recording-links
Version:
Capture bug reports from your users with the Jam recording links SDK
189 lines (137 loc) • 5.85 kB
Markdown
# @jam.dev/recording-links
A TypeScript SDK for loading & initializing Jam Recording Links scripts across browser tabs and windows.
[](https://www.npmjs.com/package/@jam.dev/recording-links)
[](http://www.typescriptlang.org/)
[](https://bundlephobia.com/package/@jam.dev/recording-links)
[](https://bundlephobia.com/package/@jam.dev/recording-links)
## Overview
This SDK provides a lightweight interface for coordinating Jam recording sessions across multiple browser contexts. It handles dynamic script loading, cross-tab state synchronization, and recording lifecycle management.
## Benefits
- ⚡ **Dynamic script loading:** uses dynamic imports for just-in-time script loading
- 🚀 **Auto-initialization:** uses URL state and cross-tab reference counting to auto-load when necessary
- 🌐 **Cross-browser support:** supports all modern ES2020+ browsers
- 🔧 **Bundler compatibility:** pre-declares dynamic imports as external for popular bundlers
- 📡 **Event system:** subscribe to SDK events like script loading
- 📦 **TypeScript support:** full type definitions included
## Installation
```bash
npm install @jam.dev/recording-links
```
## Usage
### Basic Setup
```typescript
import * as jam from "@jam.dev/recording-links/sdk";
// Initialize the SDK
jam.initialize();
// Load the recorder when needed
const Recorder = await jam.loadRecorder();
Recorder.open("recording-id");
```
### Auto-loading from URL
The SDK automatically detects `jam-recording` and `jam-title` URL parameters and loads the recorder:
```typescript
// On a page with URL: https://example.com?jam-recording=abc123&jam-title=My%20Recording
jam.initialize(); // Automatically loads recorder and opens recording "abc123"
```
### Custom Configuration
```typescript
jam.initialize({
teamId: "team-123,team-456", // Manually provide team ID(s); default: reads `<meta name="jam:team">` from the page
openImmediately: false, // Don't auto-open recorder from URL params
// OR: "recording-123" to auto-open a recording by ID
parseJamData: (href) => {
// Custom logic to extract recording data from URL
const url = new URL(href);
return {
recordingId: url.searchParams.get("jam-recording"),
jamTitle: url.searchParams.get("jam-title")
};
},
applyJamData: (data) => {
// Custom logic to apply recording data to URL
const url = new URL(window.location.href);
url.searchParams.set("jam-recording", data.recordingId);
url.searchParams.set("jam-title", data.jamTitle);
return url.href;
}
});
```
### Event Listeners
```typescript
// Listen for SDK events
jam.addEventListener("loaded", (event) => {
console.log(`Script loaded: ${event.detail.name}`); // "capture" or "recorder"
});
```
## API Reference
### `initialize(options?)`
Initializes the SDK with optional configuration.
**Parameters:**
- `options.teamId?: string` - Team ID for recording validation
- `options.openImmediately?: boolean | string` - Whether to auto-open from URL (default: `true`), or a recording ID string to open immediately
- `options.parseJamData?: (input: string) => SerializableJamData | null` - Custom URL parser
- `options.applyJamData?: (data: SerializableJamData) => string` - Custom URL applier
- `options.recorderRefCounter?: RefCounter` - Custom reference counter (advanced)
**Throws:**
- Error if SDK is already initialized
### `loadRecorder(options?)`
Loads the Jam recorder module and returns a promise that resolves to the recorder interface.
**Parameters:**
- `Omit<InitializeOptions, "recorderRefCounter">`
**Returns:**
- `Promise<RecorderSingleton>` - The Recorder singleton
**Throws:**
- Error if SDK is not initialized
### `isInitialized()`
Returns whether the SDK has been initialized.
**Returns:**
- `boolean` - True if the SDK has been initialized, false otherwise
### `addEventListener(type, listener, options?)`
Add an event listener for SDK events.
**Parameters:**
- `type: "loaded"` - Event type
- `listener: (event: CustomEvent) => void` - Event handler
- `options?: AddEventListenerOptions` - Standard event listener options
### `removeEventListener(type, listener, options?)`
Remove an event listener for SDK events.
### `Recorder`
The loaded recorder singleton (null until `loadRecorder()` is called).
**Methods:**
- `open(recordingId, params?)` - Open recorder for specific recording
- `recordingId: string` - The recording ID to open
- `params.jamTitle?: string` - Optional title for the recording
- `params.removeOnEscape?: boolean` - Whether to close recorder on Escape (default: true)
## Types
The SDK exports several TypeScript types:
### `ScriptName`
```typescript
type ScriptName = "capture" | "recorder";
```
### `SerializableJamData`
```typescript
type SerializableJamData = {
recordingId: string | null;
jamTitle: string | null;
};
```
### `InitializeOptions`
```typescript
type InitializeOptions = {
teamId?: string;
openImmediately?: boolean | string | undefined | null;
parseJamData?(input: string): SerializableJamData | null;
applyJamData?(data: SerializableJamData): string;
recorderRefCounter?: RefCounter;
};
```
### `RecorderSingleton`
```typescript
type RecorderSingleton = {
open(recordingId: string, params?: {
jamTitle?: string | null;
removeOnEscape?: boolean;
}): unknown;
};
```
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup, build commands, and release process.