@seekora-ai/search-sdk 0.2.7 → 0.2.12

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.
@@ -1,195 +0,0 @@
1
- /**
2
- * Event Queue for Seekora SDK
3
- *
4
- * Provides offline event buffering, automatic retry with exponential backoff,
5
- * and localStorage persistence for resilient analytics tracking.
6
- */
7
- import type { ExtendedEventPayload } from './client';
8
- import type { Logger } from './logger';
9
- /**
10
- * Queued event with metadata for retry logic
11
- */
12
- export interface QueuedEvent {
13
- /** Unique ID for this queued event */
14
- id: string;
15
- /** The event payload */
16
- payload: ExtendedEventPayload;
17
- /** Timestamp when the event was queued */
18
- queuedAt: number;
19
- /** Number of retry attempts */
20
- retryCount: number;
21
- /** Next retry timestamp (for exponential backoff) */
22
- nextRetryAt: number;
23
- /** Whether this is a batch event */
24
- isBatch: boolean;
25
- }
26
- /**
27
- * Event queue configuration
28
- */
29
- export interface EventQueueConfig {
30
- /**
31
- * Maximum number of events to store in the queue
32
- * @default 1000
33
- */
34
- maxQueueSize?: number;
35
- /**
36
- * Maximum number of retry attempts per event
37
- * @default 5
38
- */
39
- maxRetries?: number;
40
- /**
41
- * Base delay for exponential backoff (ms)
42
- * @default 1000
43
- */
44
- baseRetryDelay?: number;
45
- /**
46
- * Maximum delay between retries (ms)
47
- * @default 60000 (1 minute)
48
- */
49
- maxRetryDelay?: number;
50
- /**
51
- * Flush interval for automatic queue processing (ms)
52
- * Set to 0 to disable automatic flushing
53
- * @default 5000 (5 seconds)
54
- */
55
- flushInterval?: number;
56
- /**
57
- * Batch size for sending events
58
- * @default 10
59
- */
60
- batchSize?: number;
61
- /**
62
- * Storage key for localStorage persistence
63
- * @default 'seekora_event_queue'
64
- */
65
- storageKey?: string;
66
- /**
67
- * Enable localStorage persistence
68
- * @default true
69
- */
70
- enablePersistence?: boolean;
71
- /**
72
- * Maximum age of queued events before they are discarded (ms)
73
- * @default 86400000 (24 hours)
74
- */
75
- maxEventAge?: number;
76
- }
77
- /**
78
- * Function type for sending events to the backend
79
- */
80
- export type EventSender = (events: ExtendedEventPayload[]) => Promise<void>;
81
- /**
82
- * EventQueue class for resilient event tracking
83
- */
84
- export declare class EventQueue {
85
- private config;
86
- private queue;
87
- private isOnline;
88
- private isFlushing;
89
- private flushTimer;
90
- private logger;
91
- private sender;
92
- constructor(config?: EventQueueConfig);
93
- /**
94
- * Set the logger instance
95
- */
96
- setLogger(logger: Logger): void;
97
- /**
98
- * Set the event sender function
99
- */
100
- setSender(sender: EventSender): void;
101
- /**
102
- * Check if running in browser environment
103
- */
104
- private isBrowser;
105
- /**
106
- * Setup network status listeners
107
- */
108
- private setupNetworkListeners;
109
- /**
110
- * Setup beforeunload handler to persist queue
111
- */
112
- private setupBeforeUnloadHandler;
113
- /**
114
- * Start the automatic flush timer
115
- */
116
- private startFlushTimer;
117
- /**
118
- * Stop the automatic flush timer
119
- */
120
- stopFlushTimer(): void;
121
- /**
122
- * Log a message using the configured logger
123
- */
124
- private log;
125
- /**
126
- * Enqueue a single event
127
- */
128
- enqueue(payload: ExtendedEventPayload): void;
129
- /**
130
- * Enqueue a batch of events
131
- */
132
- enqueueBatch(payloads: ExtendedEventPayload[]): void;
133
- /**
134
- * Internal enqueue implementation
135
- */
136
- private enqueueInternal;
137
- /**
138
- * Flush the queue - send pending events to the backend
139
- */
140
- flush(): Promise<void>;
141
- /**
142
- * Create batches from events
143
- */
144
- private createBatches;
145
- /**
146
- * Send a batch of events
147
- */
148
- private sendBatch;
149
- /**
150
- * Persist queue to localStorage
151
- */
152
- persist(): void;
153
- /**
154
- * Restore queue from localStorage
155
- */
156
- private restore;
157
- /**
158
- * Get current queue size
159
- */
160
- size(): number;
161
- /**
162
- * Check if queue is empty
163
- */
164
- isEmpty(): boolean;
165
- /**
166
- * Check if currently online
167
- */
168
- getOnlineStatus(): boolean;
169
- /**
170
- * Clear the queue
171
- */
172
- clear(): void;
173
- /**
174
- * Get queue statistics
175
- */
176
- getStats(): {
177
- queueSize: number;
178
- isOnline: boolean;
179
- isFlushing: boolean;
180
- oldestEventAge: number | null;
181
- pendingRetries: number;
182
- };
183
- /**
184
- * Destroy the queue and cleanup resources
185
- */
186
- destroy(): void;
187
- }
188
- /**
189
- * Get or create the default event queue
190
- */
191
- export declare function getDefaultEventQueue(config?: EventQueueConfig): EventQueue;
192
- /**
193
- * Create a new event queue instance
194
- */
195
- export declare function createEventQueue(config?: EventQueueConfig): EventQueue;
@@ -1,424 +0,0 @@
1
- "use strict";
2
- /**
3
- * Event Queue for Seekora SDK
4
- *
5
- * Provides offline event buffering, automatic retry with exponential backoff,
6
- * and localStorage persistence for resilient analytics tracking.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.EventQueue = void 0;
10
- exports.getDefaultEventQueue = getDefaultEventQueue;
11
- exports.createEventQueue = createEventQueue;
12
- const utils_1 = require("./utils");
13
- /**
14
- * Default configuration
15
- */
16
- const DEFAULT_CONFIG = {
17
- maxQueueSize: 1000,
18
- maxRetries: 5,
19
- baseRetryDelay: 1000,
20
- maxRetryDelay: 60000,
21
- flushInterval: 5000,
22
- batchSize: 10,
23
- storageKey: 'seekora_event_queue',
24
- enablePersistence: true,
25
- maxEventAge: 86400000, // 24 hours
26
- };
27
- /**
28
- * EventQueue class for resilient event tracking
29
- */
30
- class EventQueue {
31
- constructor(config = {}) {
32
- this.queue = [];
33
- this.isOnline = true;
34
- this.isFlushing = false;
35
- this.flushTimer = null;
36
- this.logger = null;
37
- this.sender = null;
38
- this.config = { ...DEFAULT_CONFIG, ...config };
39
- // Check online status
40
- if (typeof navigator !== 'undefined') {
41
- this.isOnline = navigator.onLine;
42
- }
43
- // Restore queue from storage
44
- if (this.config.enablePersistence) {
45
- this.restore();
46
- }
47
- // Setup network listeners
48
- this.setupNetworkListeners();
49
- // Start flush timer
50
- if (this.config.flushInterval > 0) {
51
- this.startFlushTimer();
52
- }
53
- // Setup beforeunload handler for persistence
54
- this.setupBeforeUnloadHandler();
55
- }
56
- /**
57
- * Set the logger instance
58
- */
59
- setLogger(logger) {
60
- this.logger = logger;
61
- }
62
- /**
63
- * Set the event sender function
64
- */
65
- setSender(sender) {
66
- this.sender = sender;
67
- }
68
- /**
69
- * Check if running in browser environment
70
- */
71
- isBrowser() {
72
- return typeof window !== 'undefined' && typeof localStorage !== 'undefined';
73
- }
74
- /**
75
- * Setup network status listeners
76
- */
77
- setupNetworkListeners() {
78
- if (typeof window === 'undefined')
79
- return;
80
- window.addEventListener('online', () => {
81
- this.isOnline = true;
82
- this.log('verbose', 'Network online, triggering flush');
83
- this.flush();
84
- });
85
- window.addEventListener('offline', () => {
86
- this.isOnline = false;
87
- this.log('verbose', 'Network offline, pausing flush');
88
- });
89
- }
90
- /**
91
- * Setup beforeunload handler to persist queue
92
- */
93
- setupBeforeUnloadHandler() {
94
- if (typeof window === 'undefined')
95
- return;
96
- window.addEventListener('beforeunload', () => {
97
- this.persist();
98
- });
99
- // Also handle visibility change for mobile
100
- document.addEventListener('visibilitychange', () => {
101
- if (document.visibilityState === 'hidden') {
102
- this.persist();
103
- }
104
- });
105
- }
106
- /**
107
- * Start the automatic flush timer
108
- */
109
- startFlushTimer() {
110
- if (this.flushTimer) {
111
- clearInterval(this.flushTimer);
112
- }
113
- this.flushTimer = setInterval(() => {
114
- this.flush();
115
- }, this.config.flushInterval);
116
- }
117
- /**
118
- * Stop the automatic flush timer
119
- */
120
- stopFlushTimer() {
121
- if (this.flushTimer) {
122
- clearInterval(this.flushTimer);
123
- this.flushTimer = null;
124
- }
125
- }
126
- /**
127
- * Log a message using the configured logger
128
- */
129
- log(level, message, data) {
130
- if (!this.logger)
131
- return;
132
- switch (level) {
133
- case 'verbose':
134
- this.logger.verbose(message, data);
135
- break;
136
- case 'info':
137
- this.logger.info(message, data);
138
- break;
139
- case 'warn':
140
- this.logger.warn(message, data);
141
- break;
142
- case 'error':
143
- this.logger.error(message, data);
144
- break;
145
- }
146
- }
147
- /**
148
- * Enqueue a single event
149
- */
150
- enqueue(payload) {
151
- this.enqueueInternal(payload, false);
152
- }
153
- /**
154
- * Enqueue a batch of events
155
- */
156
- enqueueBatch(payloads) {
157
- payloads.forEach(payload => {
158
- this.enqueueInternal(payload, true);
159
- });
160
- }
161
- /**
162
- * Internal enqueue implementation
163
- */
164
- enqueueInternal(payload, isBatch) {
165
- // Check queue size limit
166
- if (this.queue.length >= this.config.maxQueueSize) {
167
- // Remove oldest events to make room
168
- const removeCount = Math.ceil(this.config.maxQueueSize * 0.1); // Remove 10%
169
- this.queue.splice(0, removeCount);
170
- this.log('warn', `Queue full, removed ${removeCount} oldest events`);
171
- }
172
- const now = Date.now();
173
- const event = {
174
- id: (0, utils_1.generateUUID)(),
175
- payload,
176
- queuedAt: now,
177
- retryCount: 0,
178
- nextRetryAt: now,
179
- isBatch,
180
- };
181
- this.queue.push(event);
182
- this.log('verbose', 'Event enqueued', { id: event.id, queueSize: this.queue.length });
183
- // Try to flush immediately if online
184
- if (this.isOnline && !this.isFlushing) {
185
- this.flush();
186
- }
187
- }
188
- /**
189
- * Flush the queue - send pending events to the backend
190
- */
191
- async flush() {
192
- // Skip if already flushing, offline, or no sender
193
- if (this.isFlushing || !this.isOnline || !this.sender) {
194
- return;
195
- }
196
- // Skip if queue is empty
197
- if (this.queue.length === 0) {
198
- return;
199
- }
200
- this.isFlushing = true;
201
- this.log('verbose', 'Starting queue flush', { queueSize: this.queue.length });
202
- try {
203
- const now = Date.now();
204
- // Filter events that are ready to be sent
205
- const readyEvents = this.queue.filter(event => {
206
- // Check if event is too old
207
- if (now - event.queuedAt > this.config.maxEventAge) {
208
- return false;
209
- }
210
- // Check if event is ready for retry
211
- return event.nextRetryAt <= now;
212
- });
213
- // Remove expired events
214
- this.queue = this.queue.filter(event => now - event.queuedAt <= this.config.maxEventAge);
215
- if (readyEvents.length === 0) {
216
- this.log('verbose', 'No events ready for sending');
217
- return;
218
- }
219
- // Process events in batches
220
- const batches = this.createBatches(readyEvents);
221
- for (const batch of batches) {
222
- await this.sendBatch(batch);
223
- }
224
- // Persist after successful flush
225
- if (this.config.enablePersistence) {
226
- this.persist();
227
- }
228
- }
229
- catch (error) {
230
- this.log('error', 'Queue flush failed', { error: error.message });
231
- }
232
- finally {
233
- this.isFlushing = false;
234
- }
235
- }
236
- /**
237
- * Create batches from events
238
- */
239
- createBatches(events) {
240
- const batches = [];
241
- for (let i = 0; i < events.length; i += this.config.batchSize) {
242
- batches.push(events.slice(i, i + this.config.batchSize));
243
- }
244
- return batches;
245
- }
246
- /**
247
- * Send a batch of events
248
- */
249
- async sendBatch(batch) {
250
- if (!this.sender)
251
- return;
252
- const payloads = batch.map(event => event.payload);
253
- const eventIds = batch.map(event => event.id);
254
- try {
255
- await this.sender(payloads);
256
- // Success - remove events from queue
257
- this.queue = this.queue.filter(event => !eventIds.includes(event.id));
258
- this.log('verbose', 'Batch sent successfully', {
259
- count: batch.length,
260
- remainingQueueSize: this.queue.length
261
- });
262
- }
263
- catch (error) {
264
- // Failure - update retry counts
265
- const now = Date.now();
266
- for (const event of batch) {
267
- const queuedEvent = this.queue.find(e => e.id === event.id);
268
- if (!queuedEvent)
269
- continue;
270
- queuedEvent.retryCount++;
271
- if (queuedEvent.retryCount >= this.config.maxRetries) {
272
- // Max retries reached - remove from queue
273
- this.queue = this.queue.filter(e => e.id !== event.id);
274
- this.log('warn', 'Event discarded after max retries', {
275
- id: event.id,
276
- retryCount: queuedEvent.retryCount
277
- });
278
- }
279
- else {
280
- // Calculate next retry with exponential backoff
281
- const delay = Math.min(this.config.baseRetryDelay * Math.pow(2, queuedEvent.retryCount), this.config.maxRetryDelay);
282
- queuedEvent.nextRetryAt = now + delay;
283
- this.log('verbose', 'Event scheduled for retry', {
284
- id: event.id,
285
- retryCount: queuedEvent.retryCount,
286
- nextRetryIn: delay
287
- });
288
- }
289
- }
290
- this.log('warn', 'Batch send failed, events scheduled for retry', {
291
- count: batch.length,
292
- error: error.message
293
- });
294
- }
295
- }
296
- /**
297
- * Persist queue to localStorage
298
- */
299
- persist() {
300
- if (!this.isBrowser() || !this.config.enablePersistence)
301
- return;
302
- try {
303
- const data = JSON.stringify(this.queue);
304
- localStorage.setItem(this.config.storageKey, data);
305
- this.log('verbose', 'Queue persisted to localStorage', {
306
- queueSize: this.queue.length
307
- });
308
- }
309
- catch (error) {
310
- this.log('warn', 'Failed to persist queue', { error: error.message });
311
- }
312
- }
313
- /**
314
- * Restore queue from localStorage
315
- */
316
- restore() {
317
- if (!this.isBrowser())
318
- return;
319
- try {
320
- const data = localStorage.getItem(this.config.storageKey);
321
- if (!data)
322
- return;
323
- const storedQueue = JSON.parse(data);
324
- const now = Date.now();
325
- // Filter out expired events
326
- this.queue = storedQueue.filter(event => now - event.queuedAt <= this.config.maxEventAge);
327
- // Reset nextRetryAt for all events to now (give them a fresh start)
328
- this.queue.forEach(event => {
329
- event.nextRetryAt = now;
330
- });
331
- this.log('info', 'Queue restored from localStorage', {
332
- storedCount: storedQueue.length,
333
- restoredCount: this.queue.length
334
- });
335
- }
336
- catch (error) {
337
- this.log('warn', 'Failed to restore queue', { error: error.message });
338
- // Clear corrupted data
339
- try {
340
- localStorage.removeItem(this.config.storageKey);
341
- }
342
- catch {
343
- // Ignore
344
- }
345
- }
346
- }
347
- /**
348
- * Get current queue size
349
- */
350
- size() {
351
- return this.queue.length;
352
- }
353
- /**
354
- * Check if queue is empty
355
- */
356
- isEmpty() {
357
- return this.queue.length === 0;
358
- }
359
- /**
360
- * Check if currently online
361
- */
362
- getOnlineStatus() {
363
- return this.isOnline;
364
- }
365
- /**
366
- * Clear the queue
367
- */
368
- clear() {
369
- this.queue = [];
370
- if (this.isBrowser() && this.config.enablePersistence) {
371
- try {
372
- localStorage.removeItem(this.config.storageKey);
373
- }
374
- catch {
375
- // Ignore
376
- }
377
- }
378
- this.log('info', 'Queue cleared');
379
- }
380
- /**
381
- * Get queue statistics
382
- */
383
- getStats() {
384
- const now = Date.now();
385
- const oldestEvent = this.queue[0];
386
- return {
387
- queueSize: this.queue.length,
388
- isOnline: this.isOnline,
389
- isFlushing: this.isFlushing,
390
- oldestEventAge: oldestEvent ? now - oldestEvent.queuedAt : null,
391
- pendingRetries: this.queue.filter(e => e.retryCount > 0).length,
392
- };
393
- }
394
- /**
395
- * Destroy the queue and cleanup resources
396
- */
397
- destroy() {
398
- this.stopFlushTimer();
399
- this.persist();
400
- this.queue = [];
401
- this.sender = null;
402
- this.logger = null;
403
- }
404
- }
405
- exports.EventQueue = EventQueue;
406
- /**
407
- * Default event queue instance
408
- */
409
- let defaultQueue = null;
410
- /**
411
- * Get or create the default event queue
412
- */
413
- function getDefaultEventQueue(config) {
414
- if (!defaultQueue) {
415
- defaultQueue = new EventQueue(config);
416
- }
417
- return defaultQueue;
418
- }
419
- /**
420
- * Create a new event queue instance
421
- */
422
- function createEventQueue(config) {
423
- return new EventQueue(config);
424
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Seekora Search SDK
3
- *
4
- * Main entry point for the SDK
5
- */
6
- export { SeekoraClient, type SeekoraClientConfig, type SearchOptions, type SearchResponse, type SearchContext, type ExtendedEventPayload, type QuerySuggestionsFullResponse } from './client';
7
- export type { SeekoraEnvironment } from './config';
8
- export { ENVIRONMENTS, getBaseUrl, getEnvironment, type EnvironmentConfig } from './config';
9
- export { Logger, createLogger, getLogLevelFromEnv, type LogLevel, type LoggerConfig } from './logger';
10
- export { loadConfig, loadConfigFromFile, loadConfigFromEnv, type FileConfig } from './config-loader';
11
- export { ContextCollector, collectBrowserContext, getDefaultContextCollector, type BrowserContext, type ContextCollectorConfig } from './context-collector';
12
- export { EventQueue, createEventQueue, getDefaultEventQueue, type QueuedEvent, type EventQueueConfig, type EventSender } from './event-queue';
13
- export * from '../generated';
14
- export { SeekoraClient as default } from './client';
package/dist/src/index.js DELETED
@@ -1,48 +0,0 @@
1
- "use strict";
2
- /**
3
- * Seekora Search SDK
4
- *
5
- * Main entry point for the SDK
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
- };
21
- Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.default = exports.getDefaultEventQueue = exports.createEventQueue = exports.EventQueue = exports.getDefaultContextCollector = exports.collectBrowserContext = exports.ContextCollector = exports.loadConfigFromEnv = exports.loadConfigFromFile = exports.loadConfig = exports.getLogLevelFromEnv = exports.createLogger = exports.Logger = exports.getEnvironment = exports.getBaseUrl = exports.ENVIRONMENTS = exports.SeekoraClient = void 0;
23
- var client_1 = require("./client");
24
- Object.defineProperty(exports, "SeekoraClient", { enumerable: true, get: function () { return client_1.SeekoraClient; } });
25
- var config_1 = require("./config");
26
- Object.defineProperty(exports, "ENVIRONMENTS", { enumerable: true, get: function () { return config_1.ENVIRONMENTS; } });
27
- Object.defineProperty(exports, "getBaseUrl", { enumerable: true, get: function () { return config_1.getBaseUrl; } });
28
- Object.defineProperty(exports, "getEnvironment", { enumerable: true, get: function () { return config_1.getEnvironment; } });
29
- var logger_1 = require("./logger");
30
- Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
31
- Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
32
- Object.defineProperty(exports, "getLogLevelFromEnv", { enumerable: true, get: function () { return logger_1.getLogLevelFromEnv; } });
33
- var config_loader_1 = require("./config-loader");
34
- Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_loader_1.loadConfig; } });
35
- Object.defineProperty(exports, "loadConfigFromFile", { enumerable: true, get: function () { return config_loader_1.loadConfigFromFile; } });
36
- Object.defineProperty(exports, "loadConfigFromEnv", { enumerable: true, get: function () { return config_loader_1.loadConfigFromEnv; } });
37
- var context_collector_1 = require("./context-collector");
38
- Object.defineProperty(exports, "ContextCollector", { enumerable: true, get: function () { return context_collector_1.ContextCollector; } });
39
- Object.defineProperty(exports, "collectBrowserContext", { enumerable: true, get: function () { return context_collector_1.collectBrowserContext; } });
40
- Object.defineProperty(exports, "getDefaultContextCollector", { enumerable: true, get: function () { return context_collector_1.getDefaultContextCollector; } });
41
- var event_queue_1 = require("./event-queue");
42
- Object.defineProperty(exports, "EventQueue", { enumerable: true, get: function () { return event_queue_1.EventQueue; } });
43
- Object.defineProperty(exports, "createEventQueue", { enumerable: true, get: function () { return event_queue_1.createEventQueue; } });
44
- Object.defineProperty(exports, "getDefaultEventQueue", { enumerable: true, get: function () { return event_queue_1.getDefaultEventQueue; } });
45
- __exportStar(require("../generated"), exports);
46
- // Default export
47
- var client_2 = require("./client");
48
- Object.defineProperty(exports, "default", { enumerable: true, get: function () { return client_2.SeekoraClient; } });