@pocketping/sdk-node 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -33,6 +33,10 @@ interface Bridge {
33
33
  onTyping?(sessionId: string, isTyping: boolean): void | Promise<void>;
34
34
  /** Called when messages are marked as delivered/read */
35
35
  onMessageRead?(sessionId: string, messageIds: string[], status: MessageStatus): void | Promise<void>;
36
+ /** Called when a custom event is triggered from the widget */
37
+ onEvent?(event: CustomEvent, session: Session): void | Promise<void>;
38
+ /** Called when a user identifies themselves via PocketPing.identify() */
39
+ onIdentityUpdate?(session: Session): void | Promise<void>;
36
40
  /** Cleanup when bridge is removed */
37
41
  destroy?(): void | Promise<void>;
38
42
  }
@@ -65,6 +69,24 @@ interface PocketPingConfig {
65
69
  onNewSession?: (session: Session) => void | Promise<void>;
66
70
  /** Callback when a message is received */
67
71
  onMessage?: (message: Message, session: Session) => void | Promise<void>;
72
+ /** Callback when a custom event is received from widget */
73
+ onEvent?: (event: CustomEvent, session: Session) => void | Promise<void>;
74
+ /** Callback when a user identifies themselves */
75
+ onIdentify?: (session: Session) => void | Promise<void>;
76
+ /** Webhook URL to forward custom events (Zapier, Make, n8n, etc.) */
77
+ webhookUrl?: string;
78
+ /** Secret key for HMAC-SHA256 signature (X-PocketPing-Signature header) */
79
+ webhookSecret?: string;
80
+ /** Webhook request timeout in milliseconds (default: 5000) */
81
+ webhookTimeout?: number;
82
+ /** Minimum supported widget version (e.g., "0.2.0") */
83
+ minWidgetVersion?: string;
84
+ /** Latest available widget version (e.g., "0.3.0") */
85
+ latestWidgetVersion?: string;
86
+ /** Custom message for version warnings */
87
+ versionWarningMessage?: string;
88
+ /** URL to upgrade instructions */
89
+ versionUpgradeUrl?: string;
68
90
  }
69
91
  interface AIConfig {
70
92
  provider: AIProvider | 'openai' | 'gemini' | 'anthropic';
@@ -73,6 +95,17 @@ interface AIConfig {
73
95
  systemPrompt?: string;
74
96
  fallbackAfter?: number;
75
97
  }
98
+ /** User identity data from PocketPing.identify() */
99
+ interface UserIdentity {
100
+ /** Required unique user identifier */
101
+ id: string;
102
+ /** User's email address */
103
+ email?: string;
104
+ /** User's display name */
105
+ name?: string;
106
+ /** Any custom fields (plan, company, etc.) */
107
+ [key: string]: unknown;
108
+ }
76
109
  interface Session {
77
110
  id: string;
78
111
  visitorId: string;
@@ -81,6 +114,8 @@ interface Session {
81
114
  operatorOnline: boolean;
82
115
  aiActive: boolean;
83
116
  metadata?: SessionMetadata;
117
+ /** User identity if identified via PocketPing.identify() */
118
+ identity?: UserIdentity;
84
119
  }
85
120
  interface SessionMetadata {
86
121
  url?: string;
@@ -115,6 +150,8 @@ interface ConnectRequest {
115
150
  visitorId: string;
116
151
  sessionId?: string;
117
152
  metadata?: SessionMetadata;
153
+ /** User identity if already identified */
154
+ identity?: UserIdentity;
118
155
  }
119
156
  interface ConnectResponse {
120
157
  sessionId: string;
@@ -155,6 +192,13 @@ interface ReadRequest {
155
192
  interface ReadResponse {
156
193
  updated: number;
157
194
  }
195
+ interface IdentifyRequest {
196
+ sessionId: string;
197
+ identity: UserIdentity;
198
+ }
199
+ interface IdentifyResponse {
200
+ ok: boolean;
201
+ }
158
202
  interface PresenceResponse {
159
203
  online: boolean;
160
204
  operators?: Array<{
@@ -165,6 +209,41 @@ interface PresenceResponse {
165
209
  aiEnabled: boolean;
166
210
  aiActiveAfter?: number;
167
211
  }
212
+ /** Custom event sent from widget to backend or vice versa */
213
+ interface CustomEvent {
214
+ /** Event name (e.g., 'clicked_pricing', 'show_offer') */
215
+ name: string;
216
+ /** Event payload */
217
+ data?: Record<string, unknown>;
218
+ /** Timestamp of the event */
219
+ timestamp: string;
220
+ /** Session ID (populated by SDK when event comes from widget) */
221
+ sessionId?: string;
222
+ }
223
+ /** Handler for custom events */
224
+ type CustomEventHandler = (event: CustomEvent, session: Session) => void | Promise<void>;
225
+ type VersionStatus = 'ok' | 'outdated' | 'deprecated' | 'unsupported';
226
+ interface VersionCheckResult {
227
+ status: VersionStatus;
228
+ message?: string;
229
+ minVersion?: string;
230
+ latestVersion?: string;
231
+ canContinue: boolean;
232
+ }
233
+ /** Payload sent to webhook URL */
234
+ interface WebhookPayload {
235
+ /** The custom event */
236
+ event: CustomEvent;
237
+ /** Session information */
238
+ session: {
239
+ id: string;
240
+ visitorId: string;
241
+ metadata?: SessionMetadata;
242
+ identity?: UserIdentity;
243
+ };
244
+ /** Timestamp when webhook was sent */
245
+ sentAt: string;
246
+ }
168
247
 
169
248
  declare class PocketPing {
170
249
  private storage;
@@ -173,6 +252,7 @@ declare class PocketPing {
173
252
  private wss;
174
253
  private sessionSockets;
175
254
  private operatorOnline;
255
+ private eventHandlers;
176
256
  constructor(config?: PocketPingConfig);
177
257
  private initStorage;
178
258
  middleware(): (req: IncomingMessage & {
@@ -182,6 +262,7 @@ declare class PocketPing {
182
262
  private parseBody;
183
263
  attachWebSocket(server: any): void;
184
264
  private handleWebSocketMessage;
265
+ private handleCustomEvent;
185
266
  private broadcastToSession;
186
267
  handleConnect(request: ConnectRequest): Promise<ConnectResponse>;
187
268
  handleMessage(request: SendMessageRequest): Promise<SendMessageResponse>;
@@ -191,13 +272,109 @@ declare class PocketPing {
191
272
  }>;
192
273
  handlePresence(): Promise<PresenceResponse>;
193
274
  handleRead(request: ReadRequest): Promise<ReadResponse>;
275
+ /**
276
+ * Handle user identification from widget
277
+ * Called when visitor calls PocketPing.identify()
278
+ */
279
+ handleIdentify(request: IdentifyRequest): Promise<IdentifyResponse>;
280
+ /**
281
+ * Get a session by ID
282
+ */
283
+ getSession(sessionId: string): Promise<Session | null>;
194
284
  sendOperatorMessage(sessionId: string, content: string): Promise<Message>;
195
285
  setOperatorOnline(online: boolean): void;
286
+ /**
287
+ * Subscribe to custom events from widgets
288
+ * @param eventName - The name of the event to listen for, or '*' for all events
289
+ * @param handler - Callback function when event is received
290
+ * @returns Unsubscribe function
291
+ * @example
292
+ * // Listen for specific event
293
+ * pp.onEvent('clicked_pricing', async (event, session) => {
294
+ * console.log(`User ${session.visitorId} clicked pricing: ${event.data?.plan}`)
295
+ * })
296
+ *
297
+ * // Listen for all events
298
+ * pp.onEvent('*', async (event, session) => {
299
+ * console.log(`Event: ${event.name}`, event.data)
300
+ * })
301
+ */
302
+ onEvent(eventName: string, handler: CustomEventHandler): () => void;
303
+ /**
304
+ * Unsubscribe from a custom event
305
+ * @param eventName - The name of the event
306
+ * @param handler - The handler to remove
307
+ */
308
+ offEvent(eventName: string, handler: CustomEventHandler): void;
309
+ /**
310
+ * Send a custom event to a specific widget/session
311
+ * @param sessionId - The session ID to send the event to
312
+ * @param eventName - The name of the event
313
+ * @param data - Optional payload to send with the event
314
+ * @example
315
+ * // Send a promotion offer to a specific user
316
+ * pp.emitEvent('session-123', 'show_offer', {
317
+ * discount: 20,
318
+ * code: 'SAVE20',
319
+ * message: 'Special offer just for you!'
320
+ * })
321
+ */
322
+ emitEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): void;
323
+ /**
324
+ * Broadcast a custom event to all connected widgets
325
+ * @param eventName - The name of the event
326
+ * @param data - Optional payload to send with the event
327
+ * @example
328
+ * // Notify all users about maintenance
329
+ * pp.broadcastEvent('maintenance_warning', {
330
+ * message: 'Site will be down for maintenance in 5 minutes'
331
+ * })
332
+ */
333
+ broadcastEvent(eventName: string, data?: Record<string, unknown>): void;
334
+ /**
335
+ * Process a custom event server-side (runs handlers, bridges, webhooks)
336
+ * Useful for server-side automation or triggering events programmatically
337
+ * @param sessionId - The session ID to associate with the event
338
+ * @param eventName - The name of the event
339
+ * @param data - Optional payload for the event
340
+ * @example
341
+ * // Trigger event from backend logic (e.g., after purchase)
342
+ * await pp.triggerEvent('session-123', 'purchase_completed', {
343
+ * orderId: 'order-456',
344
+ * amount: 99.99
345
+ * })
346
+ */
347
+ triggerEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): Promise<void>;
196
348
  private notifyBridges;
197
349
  private notifyBridgesRead;
350
+ private notifyBridgesEvent;
351
+ private notifyBridgesIdentity;
352
+ /**
353
+ * Forward custom event to configured webhook URL (non-blocking)
354
+ * Used for integrations with Zapier, Make, n8n, or custom backends
355
+ */
356
+ private forwardToWebhook;
357
+ /**
358
+ * Forward identity update to webhook as a special event
359
+ */
360
+ private forwardIdentityToWebhook;
198
361
  addBridge(bridge: Bridge): void;
199
362
  private generateId;
200
363
  getStorage(): Storage;
364
+ /**
365
+ * Check widget version against configured min/latest versions
366
+ * @param widgetVersion - Version from X-PocketPing-Version header
367
+ * @returns Version check result with status and headers to set
368
+ */
369
+ checkWidgetVersion(widgetVersion: string | undefined): VersionCheckResult;
370
+ /**
371
+ * Set version warning headers on HTTP response
372
+ */
373
+ private setVersionHeaders;
374
+ /**
375
+ * Send version warning via WebSocket to a session
376
+ */
377
+ sendVersionWarning(sessionId: string, versionCheck: VersionCheckResult): void;
201
378
  }
202
379
 
203
380
  /**
@@ -219,4 +396,4 @@ declare class MemoryStorage implements Storage {
219
396
  cleanupOldSessions(olderThan: Date): Promise<number>;
220
397
  }
221
398
 
222
- export { type AIProvider, type Bridge, type ConnectRequest, type ConnectResponse, MemoryStorage, type Message, PocketPing, type PocketPingConfig, type PresenceResponse, type SendMessageRequest, type SendMessageResponse, type Session, type Storage };
399
+ export { type AIProvider, type Bridge, type ConnectRequest, type ConnectResponse, type CustomEvent, type CustomEventHandler, MemoryStorage, type Message, PocketPing, type PocketPingConfig, type PresenceResponse, type SendMessageRequest, type SendMessageResponse, type Session, type Storage, type WebhookPayload };
package/dist/index.d.ts CHANGED
@@ -33,6 +33,10 @@ interface Bridge {
33
33
  onTyping?(sessionId: string, isTyping: boolean): void | Promise<void>;
34
34
  /** Called when messages are marked as delivered/read */
35
35
  onMessageRead?(sessionId: string, messageIds: string[], status: MessageStatus): void | Promise<void>;
36
+ /** Called when a custom event is triggered from the widget */
37
+ onEvent?(event: CustomEvent, session: Session): void | Promise<void>;
38
+ /** Called when a user identifies themselves via PocketPing.identify() */
39
+ onIdentityUpdate?(session: Session): void | Promise<void>;
36
40
  /** Cleanup when bridge is removed */
37
41
  destroy?(): void | Promise<void>;
38
42
  }
@@ -65,6 +69,24 @@ interface PocketPingConfig {
65
69
  onNewSession?: (session: Session) => void | Promise<void>;
66
70
  /** Callback when a message is received */
67
71
  onMessage?: (message: Message, session: Session) => void | Promise<void>;
72
+ /** Callback when a custom event is received from widget */
73
+ onEvent?: (event: CustomEvent, session: Session) => void | Promise<void>;
74
+ /** Callback when a user identifies themselves */
75
+ onIdentify?: (session: Session) => void | Promise<void>;
76
+ /** Webhook URL to forward custom events (Zapier, Make, n8n, etc.) */
77
+ webhookUrl?: string;
78
+ /** Secret key for HMAC-SHA256 signature (X-PocketPing-Signature header) */
79
+ webhookSecret?: string;
80
+ /** Webhook request timeout in milliseconds (default: 5000) */
81
+ webhookTimeout?: number;
82
+ /** Minimum supported widget version (e.g., "0.2.0") */
83
+ minWidgetVersion?: string;
84
+ /** Latest available widget version (e.g., "0.3.0") */
85
+ latestWidgetVersion?: string;
86
+ /** Custom message for version warnings */
87
+ versionWarningMessage?: string;
88
+ /** URL to upgrade instructions */
89
+ versionUpgradeUrl?: string;
68
90
  }
69
91
  interface AIConfig {
70
92
  provider: AIProvider | 'openai' | 'gemini' | 'anthropic';
@@ -73,6 +95,17 @@ interface AIConfig {
73
95
  systemPrompt?: string;
74
96
  fallbackAfter?: number;
75
97
  }
98
+ /** User identity data from PocketPing.identify() */
99
+ interface UserIdentity {
100
+ /** Required unique user identifier */
101
+ id: string;
102
+ /** User's email address */
103
+ email?: string;
104
+ /** User's display name */
105
+ name?: string;
106
+ /** Any custom fields (plan, company, etc.) */
107
+ [key: string]: unknown;
108
+ }
76
109
  interface Session {
77
110
  id: string;
78
111
  visitorId: string;
@@ -81,6 +114,8 @@ interface Session {
81
114
  operatorOnline: boolean;
82
115
  aiActive: boolean;
83
116
  metadata?: SessionMetadata;
117
+ /** User identity if identified via PocketPing.identify() */
118
+ identity?: UserIdentity;
84
119
  }
85
120
  interface SessionMetadata {
86
121
  url?: string;
@@ -115,6 +150,8 @@ interface ConnectRequest {
115
150
  visitorId: string;
116
151
  sessionId?: string;
117
152
  metadata?: SessionMetadata;
153
+ /** User identity if already identified */
154
+ identity?: UserIdentity;
118
155
  }
119
156
  interface ConnectResponse {
120
157
  sessionId: string;
@@ -155,6 +192,13 @@ interface ReadRequest {
155
192
  interface ReadResponse {
156
193
  updated: number;
157
194
  }
195
+ interface IdentifyRequest {
196
+ sessionId: string;
197
+ identity: UserIdentity;
198
+ }
199
+ interface IdentifyResponse {
200
+ ok: boolean;
201
+ }
158
202
  interface PresenceResponse {
159
203
  online: boolean;
160
204
  operators?: Array<{
@@ -165,6 +209,41 @@ interface PresenceResponse {
165
209
  aiEnabled: boolean;
166
210
  aiActiveAfter?: number;
167
211
  }
212
+ /** Custom event sent from widget to backend or vice versa */
213
+ interface CustomEvent {
214
+ /** Event name (e.g., 'clicked_pricing', 'show_offer') */
215
+ name: string;
216
+ /** Event payload */
217
+ data?: Record<string, unknown>;
218
+ /** Timestamp of the event */
219
+ timestamp: string;
220
+ /** Session ID (populated by SDK when event comes from widget) */
221
+ sessionId?: string;
222
+ }
223
+ /** Handler for custom events */
224
+ type CustomEventHandler = (event: CustomEvent, session: Session) => void | Promise<void>;
225
+ type VersionStatus = 'ok' | 'outdated' | 'deprecated' | 'unsupported';
226
+ interface VersionCheckResult {
227
+ status: VersionStatus;
228
+ message?: string;
229
+ minVersion?: string;
230
+ latestVersion?: string;
231
+ canContinue: boolean;
232
+ }
233
+ /** Payload sent to webhook URL */
234
+ interface WebhookPayload {
235
+ /** The custom event */
236
+ event: CustomEvent;
237
+ /** Session information */
238
+ session: {
239
+ id: string;
240
+ visitorId: string;
241
+ metadata?: SessionMetadata;
242
+ identity?: UserIdentity;
243
+ };
244
+ /** Timestamp when webhook was sent */
245
+ sentAt: string;
246
+ }
168
247
 
169
248
  declare class PocketPing {
170
249
  private storage;
@@ -173,6 +252,7 @@ declare class PocketPing {
173
252
  private wss;
174
253
  private sessionSockets;
175
254
  private operatorOnline;
255
+ private eventHandlers;
176
256
  constructor(config?: PocketPingConfig);
177
257
  private initStorage;
178
258
  middleware(): (req: IncomingMessage & {
@@ -182,6 +262,7 @@ declare class PocketPing {
182
262
  private parseBody;
183
263
  attachWebSocket(server: any): void;
184
264
  private handleWebSocketMessage;
265
+ private handleCustomEvent;
185
266
  private broadcastToSession;
186
267
  handleConnect(request: ConnectRequest): Promise<ConnectResponse>;
187
268
  handleMessage(request: SendMessageRequest): Promise<SendMessageResponse>;
@@ -191,13 +272,109 @@ declare class PocketPing {
191
272
  }>;
192
273
  handlePresence(): Promise<PresenceResponse>;
193
274
  handleRead(request: ReadRequest): Promise<ReadResponse>;
275
+ /**
276
+ * Handle user identification from widget
277
+ * Called when visitor calls PocketPing.identify()
278
+ */
279
+ handleIdentify(request: IdentifyRequest): Promise<IdentifyResponse>;
280
+ /**
281
+ * Get a session by ID
282
+ */
283
+ getSession(sessionId: string): Promise<Session | null>;
194
284
  sendOperatorMessage(sessionId: string, content: string): Promise<Message>;
195
285
  setOperatorOnline(online: boolean): void;
286
+ /**
287
+ * Subscribe to custom events from widgets
288
+ * @param eventName - The name of the event to listen for, or '*' for all events
289
+ * @param handler - Callback function when event is received
290
+ * @returns Unsubscribe function
291
+ * @example
292
+ * // Listen for specific event
293
+ * pp.onEvent('clicked_pricing', async (event, session) => {
294
+ * console.log(`User ${session.visitorId} clicked pricing: ${event.data?.plan}`)
295
+ * })
296
+ *
297
+ * // Listen for all events
298
+ * pp.onEvent('*', async (event, session) => {
299
+ * console.log(`Event: ${event.name}`, event.data)
300
+ * })
301
+ */
302
+ onEvent(eventName: string, handler: CustomEventHandler): () => void;
303
+ /**
304
+ * Unsubscribe from a custom event
305
+ * @param eventName - The name of the event
306
+ * @param handler - The handler to remove
307
+ */
308
+ offEvent(eventName: string, handler: CustomEventHandler): void;
309
+ /**
310
+ * Send a custom event to a specific widget/session
311
+ * @param sessionId - The session ID to send the event to
312
+ * @param eventName - The name of the event
313
+ * @param data - Optional payload to send with the event
314
+ * @example
315
+ * // Send a promotion offer to a specific user
316
+ * pp.emitEvent('session-123', 'show_offer', {
317
+ * discount: 20,
318
+ * code: 'SAVE20',
319
+ * message: 'Special offer just for you!'
320
+ * })
321
+ */
322
+ emitEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): void;
323
+ /**
324
+ * Broadcast a custom event to all connected widgets
325
+ * @param eventName - The name of the event
326
+ * @param data - Optional payload to send with the event
327
+ * @example
328
+ * // Notify all users about maintenance
329
+ * pp.broadcastEvent('maintenance_warning', {
330
+ * message: 'Site will be down for maintenance in 5 minutes'
331
+ * })
332
+ */
333
+ broadcastEvent(eventName: string, data?: Record<string, unknown>): void;
334
+ /**
335
+ * Process a custom event server-side (runs handlers, bridges, webhooks)
336
+ * Useful for server-side automation or triggering events programmatically
337
+ * @param sessionId - The session ID to associate with the event
338
+ * @param eventName - The name of the event
339
+ * @param data - Optional payload for the event
340
+ * @example
341
+ * // Trigger event from backend logic (e.g., after purchase)
342
+ * await pp.triggerEvent('session-123', 'purchase_completed', {
343
+ * orderId: 'order-456',
344
+ * amount: 99.99
345
+ * })
346
+ */
347
+ triggerEvent(sessionId: string, eventName: string, data?: Record<string, unknown>): Promise<void>;
196
348
  private notifyBridges;
197
349
  private notifyBridgesRead;
350
+ private notifyBridgesEvent;
351
+ private notifyBridgesIdentity;
352
+ /**
353
+ * Forward custom event to configured webhook URL (non-blocking)
354
+ * Used for integrations with Zapier, Make, n8n, or custom backends
355
+ */
356
+ private forwardToWebhook;
357
+ /**
358
+ * Forward identity update to webhook as a special event
359
+ */
360
+ private forwardIdentityToWebhook;
198
361
  addBridge(bridge: Bridge): void;
199
362
  private generateId;
200
363
  getStorage(): Storage;
364
+ /**
365
+ * Check widget version against configured min/latest versions
366
+ * @param widgetVersion - Version from X-PocketPing-Version header
367
+ * @returns Version check result with status and headers to set
368
+ */
369
+ checkWidgetVersion(widgetVersion: string | undefined): VersionCheckResult;
370
+ /**
371
+ * Set version warning headers on HTTP response
372
+ */
373
+ private setVersionHeaders;
374
+ /**
375
+ * Send version warning via WebSocket to a session
376
+ */
377
+ sendVersionWarning(sessionId: string, versionCheck: VersionCheckResult): void;
201
378
  }
202
379
 
203
380
  /**
@@ -219,4 +396,4 @@ declare class MemoryStorage implements Storage {
219
396
  cleanupOldSessions(olderThan: Date): Promise<number>;
220
397
  }
221
398
 
222
- export { type AIProvider, type Bridge, type ConnectRequest, type ConnectResponse, MemoryStorage, type Message, PocketPing, type PocketPingConfig, type PresenceResponse, type SendMessageRequest, type SendMessageResponse, type Session, type Storage };
399
+ export { type AIProvider, type Bridge, type ConnectRequest, type ConnectResponse, type CustomEvent, type CustomEventHandler, MemoryStorage, type Message, PocketPing, type PocketPingConfig, type PresenceResponse, type SendMessageRequest, type SendMessageResponse, type Session, type Storage, type WebhookPayload };