wakz-sdk 1.0.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.
Files changed (56) hide show
  1. package/README.md +264 -0
  2. package/dist/client.d.ts +124 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +323 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/crypto.d.ts +26 -0
  7. package/dist/crypto.d.ts.map +1 -0
  8. package/dist/crypto.js +161 -0
  9. package/dist/crypto.js.map +1 -0
  10. package/dist/esm/client.js.map +1 -0
  11. package/dist/esm/client.mjs +319 -0
  12. package/dist/esm/crypto.js.map +1 -0
  13. package/dist/esm/crypto.mjs +123 -0
  14. package/dist/esm/events.js.map +1 -0
  15. package/dist/esm/events.mjs +100 -0
  16. package/dist/esm/http.js.map +1 -0
  17. package/dist/esm/http.mjs +159 -0
  18. package/dist/esm/index.js.map +1 -0
  19. package/dist/esm/index.mjs +32 -0
  20. package/dist/esm/session.js.map +1 -0
  21. package/dist/esm/session.mjs +186 -0
  22. package/dist/esm/types.js.map +1 -0
  23. package/dist/esm/types.mjs +5 -0
  24. package/dist/esm/utils.js.map +1 -0
  25. package/dist/esm/utils.mjs +139 -0
  26. package/dist/esm/websocket.js.map +1 -0
  27. package/dist/esm/websocket.mjs +363 -0
  28. package/dist/events.d.ts +38 -0
  29. package/dist/events.d.ts.map +1 -0
  30. package/dist/events.js +104 -0
  31. package/dist/events.js.map +1 -0
  32. package/dist/http.d.ts +37 -0
  33. package/dist/http.d.ts.map +1 -0
  34. package/dist/http.js +163 -0
  35. package/dist/http.js.map +1 -0
  36. package/dist/index.d.ts +27 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +49 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/session.d.ts +75 -0
  41. package/dist/session.d.ts.map +1 -0
  42. package/dist/session.js +190 -0
  43. package/dist/session.js.map +1 -0
  44. package/dist/types.d.ts +149 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +6 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/utils.d.ts +56 -0
  49. package/dist/utils.d.ts.map +1 -0
  50. package/dist/utils.js +153 -0
  51. package/dist/utils.js.map +1 -0
  52. package/dist/websocket.d.ts +93 -0
  53. package/dist/websocket.d.ts.map +1 -0
  54. package/dist/websocket.js +367 -0
  55. package/dist/websocket.js.map +1 -0
  56. package/package.json +50 -0
@@ -0,0 +1,319 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // WAKZ SDK — Main Client
3
+ // ═══════════════════════════════════════════════════════════════
4
+ import { WAKZEventEmitter } from './events';
5
+ import { WebSocketTransport } from './websocket';
6
+ import { HttpTransport } from './http';
7
+ import { SessionManager } from './session';
8
+ import { httpToWsUrl, normalizeUrl, resolveTransportMode, Logger } from './utils';
9
+ /**
10
+ * WAKZ SDK Client — The main entry point for integrating WAKZ AI.
11
+ *
12
+ * Features:
13
+ * - Dual transport: WebSocket (primary) with HTTP/REST fallback
14
+ * - Automatic reconnection with exponential backoff
15
+ * - API key authentication with HMAC-SHA256 request signing
16
+ * - Typed event emitter for real-time updates
17
+ * - Session management with visitor fingerprinting
18
+ * - Works in both browser and Node.js environments
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const client = new WAKZClient({
23
+ * apiKey: 'wakz_live_xxxxx',
24
+ * });
25
+ *
26
+ * await client.connect();
27
+ * client.on('message', (msg) => console.log(msg));
28
+ * const response = await client.sendMessage('Hello!');
29
+ * ```
30
+ */
31
+ export class WAKZClient extends WAKZEventEmitter {
32
+ /**
33
+ * Create a new WAKZ SDK client instance.
34
+ *
35
+ * @param options - Client configuration options
36
+ */
37
+ constructor(options) {
38
+ super();
39
+ this.wsTransport = null;
40
+ this._status = 'disconnected';
41
+ this._currentTransport = 'http';
42
+ if (!options.apiKey || typeof options.apiKey !== 'string') {
43
+ throw new Error('[WAKZ SDK] A valid API key is required. API keys start with "wakz_live_".');
44
+ }
45
+ if (!options.apiKey.startsWith('wakz_live_')) {
46
+ this.warn('[WAKZ SDK] API key does not start with "wakz_live_". Please verify your key.');
47
+ }
48
+ this.options = {
49
+ apiKey: options.apiKey,
50
+ baseUrl: normalizeUrl(options.baseUrl || 'https://api.wakz.dev'),
51
+ websocketUrl: options.websocketUrl || httpToWsUrl(options.baseUrl || 'https://api.wakz.dev'),
52
+ autoReconnect: options.autoReconnect ?? true,
53
+ maxRetries: options.maxRetries ?? 5,
54
+ initialRetryDelay: options.initialRetryDelay ?? 1000,
55
+ maxRetryDelay: options.maxRetryDelay ?? 30000,
56
+ visitorId: options.visitorId,
57
+ metadata: options.metadata,
58
+ timeout: options.timeout ?? 30000,
59
+ debug: options.debug ?? false,
60
+ };
61
+ this.logger = new Logger(this.options.debug);
62
+ // Initialize HTTP transport (always available as fallback)
63
+ this.httpTransport = new HttpTransport(this.options.apiKey, this.options.baseUrl, this.options.timeout, this.options.debug);
64
+ // Initialize session manager
65
+ this.sessionManager = new SessionManager(this.options.visitorId, this.options.metadata);
66
+ }
67
+ /**
68
+ * Connect to the WAKZ API.
69
+ *
70
+ * Attempts WebSocket connection first. Falls back to HTTP if:
71
+ * - WebSocket is not available in the environment
72
+ * - WebSocket connection fails after max retries
73
+ *
74
+ * @returns Promise that resolves when connected
75
+ */
76
+ async connect() {
77
+ this._status = 'connecting';
78
+ this.logger.info('Connecting to WAKZ API...');
79
+ // Resolve the best available transport
80
+ const preferredTransport = resolveTransportMode();
81
+ if (preferredTransport === 'websocket') {
82
+ try {
83
+ await this.connectWebSocket();
84
+ return;
85
+ }
86
+ catch (err) {
87
+ this.logger.warn('WebSocket connection failed, falling back to HTTP:', err);
88
+ }
89
+ }
90
+ // Fallback to HTTP transport
91
+ this._currentTransport = 'http';
92
+ this._status = 'connected';
93
+ this.logger.info('Connected via HTTP transport');
94
+ this.emit('connected', undefined);
95
+ // Initialize session
96
+ const session = await this.sessionManager.getSession();
97
+ this.emit('session_start', session);
98
+ }
99
+ /**
100
+ * Send a chat message.
101
+ *
102
+ * Uses the current active transport (WebSocket or HTTP).
103
+ *
104
+ * @param content - The message text to send
105
+ * @returns Promise resolving to the assistant's reply
106
+ */
107
+ async sendMessage(content) {
108
+ if (!content || typeof content !== 'string') {
109
+ return { success: false, error: 'Message content is required' };
110
+ }
111
+ const session = await this.sessionManager.getSession();
112
+ // Try WebSocket first
113
+ if (this._currentTransport === 'websocket' && this.wsTransport?.isConnected) {
114
+ try {
115
+ const message = await this.wsTransport.sendMessage(content, session.id, session.visitorId);
116
+ this.sessionManager.incrementMessageCount();
117
+ return { success: true, message };
118
+ }
119
+ catch (err) {
120
+ this.logger.warn('WebSocket send failed, falling back to HTTP:', err);
121
+ // Fall through to HTTP
122
+ }
123
+ }
124
+ // HTTP fallback
125
+ try {
126
+ const result = await this.httpTransport.sendMessage(content, session.id, session.visitorId);
127
+ if (result.success) {
128
+ this.sessionManager.incrementMessageCount();
129
+ if (result.message) {
130
+ this.emit('message', result.message);
131
+ }
132
+ }
133
+ return result;
134
+ }
135
+ catch (err) {
136
+ return {
137
+ success: false,
138
+ error: err instanceof Error ? err.message : 'Failed to send message',
139
+ };
140
+ }
141
+ }
142
+ /**
143
+ * Disconnect from the WAKZ API.
144
+ */
145
+ disconnect() {
146
+ this._status = 'disconnected';
147
+ this.wsTransport?.disconnect();
148
+ this.sessionManager.endSession();
149
+ this.logger.info('Disconnected');
150
+ }
151
+ /**
152
+ * Register an event listener.
153
+ */
154
+ on(event, callback) {
155
+ super.on(event, callback);
156
+ return this;
157
+ }
158
+ /**
159
+ * Register a one-time event listener.
160
+ */
161
+ once(event, callback) {
162
+ super.once(event, callback);
163
+ return this;
164
+ }
165
+ /**
166
+ * Remove an event listener.
167
+ */
168
+ off(event, callback) {
169
+ super.off(event, callback);
170
+ return this;
171
+ }
172
+ /**
173
+ * Get the current session information.
174
+ */
175
+ async getSession() {
176
+ return this.sessionManager.getSession();
177
+ }
178
+ /**
179
+ * Get the current visitor ID.
180
+ */
181
+ getVisitorId() {
182
+ return this.sessionManager.getVisitorId();
183
+ }
184
+ /**
185
+ * Get the current connection status.
186
+ */
187
+ getStatus() {
188
+ return this._status;
189
+ }
190
+ /**
191
+ * Get the current transport mode.
192
+ */
193
+ getTransport() {
194
+ return this._currentTransport;
195
+ }
196
+ /**
197
+ * Fetch the widget configuration from the API.
198
+ */
199
+ async getWidgetConfig() {
200
+ return this.httpTransport.fetchWidgetConfig();
201
+ }
202
+ /**
203
+ * Perform a health check against the WAKZ API.
204
+ */
205
+ async healthCheck() {
206
+ // Use the active transport for health check
207
+ if (this._currentTransport === 'websocket' && this.wsTransport?.isConnected) {
208
+ return this.wsTransport.healthCheck();
209
+ }
210
+ return this.httpTransport.healthCheck();
211
+ }
212
+ /**
213
+ * Update visitor metadata.
214
+ */
215
+ updateMetadata(metadata) {
216
+ this.sessionManager.updateMetadata(metadata);
217
+ }
218
+ /**
219
+ * Destroy the client — disconnect and clean up all resources.
220
+ */
221
+ destroy() {
222
+ this.disconnect();
223
+ this.wsTransport = null;
224
+ this.sessionManager.destroy();
225
+ this.removeAllListeners();
226
+ this.logger.info('Client destroyed');
227
+ }
228
+ /**
229
+ * ─── Static Methods ──────────────────────────────────────
230
+ */
231
+ /**
232
+ * Perform a quick health check against a WAKZ API endpoint.
233
+ * Useful for checking connectivity before creating a client instance.
234
+ *
235
+ * @param baseUrl - The API base URL to check
236
+ * @param timeout - Request timeout in ms (default: 10000)
237
+ * @returns Health check result
238
+ */
239
+ static async healthCheck(baseUrl = 'https://api.wakz.dev', timeout = 10000) {
240
+ const startTime = Date.now();
241
+ try {
242
+ const url = `${normalizeUrl(baseUrl)}/api/v1/embed/health`;
243
+ const controller = new AbortController();
244
+ const timer = setTimeout(() => controller.abort(), timeout);
245
+ const response = await fetch(url, {
246
+ method: 'GET',
247
+ signal: controller.signal,
248
+ }).finally(() => clearTimeout(timer));
249
+ const data = await response.json().catch(() => ({}));
250
+ return {
251
+ healthy: response.ok,
252
+ latency: Date.now() - startTime,
253
+ version: data.version,
254
+ };
255
+ }
256
+ catch {
257
+ return {
258
+ healthy: false,
259
+ latency: Date.now() - startTime,
260
+ };
261
+ }
262
+ }
263
+ // ─── Private Methods ──────────────────────────────────────
264
+ /**
265
+ * Connect via WebSocket transport.
266
+ */
267
+ async connectWebSocket() {
268
+ this._currentTransport = 'websocket';
269
+ // Create WebSocket transport and forward events
270
+ this.wsTransport = new WebSocketTransport(this.options.apiKey, this.options.websocketUrl, {
271
+ autoReconnect: this.options.autoReconnect,
272
+ maxRetries: this.options.maxRetries,
273
+ initialRetryDelay: this.options.initialRetryDelay,
274
+ maxRetryDelay: this.options.maxRetryDelay,
275
+ debug: this.options.debug,
276
+ });
277
+ // Forward WebSocket events to client
278
+ this.wsTransport.on('connected', () => {
279
+ this._status = 'connected';
280
+ this.emit('connected', undefined);
281
+ // Start session
282
+ this.sessionManager.getSession().then((session) => {
283
+ this.emit('session_start', session);
284
+ });
285
+ });
286
+ this.wsTransport.on('disconnected', (data) => {
287
+ if (this._status === 'connected') {
288
+ this._status = 'disconnected';
289
+ }
290
+ this.emit('disconnected', data);
291
+ });
292
+ this.wsTransport.on('reconnecting', (data) => {
293
+ this._status = 'reconnecting';
294
+ this.emit('reconnecting', data);
295
+ });
296
+ this.wsTransport.on('reconnect_failed', (data) => {
297
+ this.logger.warn('WebSocket reconnect failed, switching to HTTP');
298
+ this.emit('reconnect_failed', data);
299
+ // Auto-switch to HTTP transport
300
+ this._currentTransport = 'http';
301
+ this._status = 'connected';
302
+ this.emit('transport_change', { from: 'websocket', to: 'http' });
303
+ this.emit('connected', undefined);
304
+ });
305
+ this.wsTransport.on('message', (msg) => {
306
+ this.sessionManager.incrementMessageCount();
307
+ this.emit('message', msg);
308
+ });
309
+ this.wsTransport.on('error', (err) => {
310
+ this.emit('error', err);
311
+ });
312
+ // Connect
313
+ await this.wsTransport.connect();
314
+ }
315
+ warn(msg) {
316
+ console.warn(msg);
317
+ }
318
+ }
319
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,qCAAqC;AACrC,kEAAkE;AAIlE;;;GAGG;AAEH,mEAAmE;AAEnE,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,WAAW;IAC9B,OAAO,OAAO,CAAC,QAAQ,KAAK,WAAW;IACvC,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,WAAW,CAAC;AAE/C,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,WAAW,CAAC;AAExF,mEAAmE;AAEnE;;;GAGG;AACH,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAAe;IACpD,IAAI,MAAM,EAAE,CAAC;QACX,iBAAiB;QACjB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO,UAAU;aACd,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC;aACzB,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAED,IAAI,SAAS,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAC7D,yBAAyB;QACzB,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAExC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CACpD,KAAK,EACL,OAAO,EACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;aACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IAED,MAAM,IAAI,KAAK,CACb,wDAAwD;QACxD,yEAAyE,CAC1E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,IAA6B;IAE7B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,GAAG,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAE3D,OAAO;QACL,WAAW,EAAE,MAAM;QACnB,aAAa,EAAE,SAAS;QACxB,aAAa,EAAE,SAAS;QACxB,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAa;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,SAAS,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAChE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aAC3C,IAAI,CAAC,EAAE,CAAC;aACR,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,4CAA4C;IAC5C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,SAAS,GACb,OAAO,OAAO,KAAK,WAAW;QAC9B,OAAO,OAAO,CAAC,QAAQ,KAAK,WAAW;QACvC,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,WAAW,CAAC;IAE/C,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrC,OAAO,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;IACH,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,eAAe,KAAK,WAAW,EAAE,CAAC;QACnF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;aACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IAED,sDAAsD;IACtD,MAAM,KAAK,GAAG,kBAAkB,CAAC;IACjC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,123 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // WAKZ SDK — Cryptographic Utilities
3
+ // ═══════════════════════════════════════════════════════════════
4
+ /**
5
+ * Cryptographic utilities for API request signing and verification.
6
+ * Uses the Web Crypto API (browser) or Node.js crypto (server).
7
+ */
8
+ // ── Platform Detection ──────────────────────────────────────────
9
+ const isNode = typeof process !== 'undefined' &&
10
+ typeof process.versions !== 'undefined' &&
11
+ typeof process.versions.node !== 'undefined';
12
+ const isBrowser = typeof window !== 'undefined' && typeof window.crypto !== 'undefined';
13
+ // ── HMAC-SHA256 Implementation ──────────────────────────────────
14
+ /**
15
+ * Create HMAC-SHA256 signature using the best available crypto API.
16
+ * Works in both browser (Web Crypto) and Node.js environments.
17
+ */
18
+ async function hmacSha256(key, message) {
19
+ if (isNode) {
20
+ // Node.js crypto
21
+ const nodeCrypto = await import('crypto');
22
+ return nodeCrypto
23
+ .createHmac('sha256', key)
24
+ .update(message)
25
+ .digest('hex');
26
+ }
27
+ if (isBrowser && typeof window.crypto.subtle !== 'undefined') {
28
+ // Web Crypto API (async)
29
+ const encoder = new TextEncoder();
30
+ const keyData = encoder.encode(key);
31
+ const msgData = encoder.encode(message);
32
+ const cryptoKey = await window.crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
33
+ const signature = await window.crypto.subtle.sign('HMAC', cryptoKey, msgData);
34
+ return Array.from(new Uint8Array(signature))
35
+ .map((b) => b.toString(16).padStart(2, '0'))
36
+ .join('');
37
+ }
38
+ throw new Error('[WAKZ SDK] No cryptographic implementation available. ' +
39
+ 'Requires Node.js >= 16 or a modern browser with Web Crypto API support.');
40
+ }
41
+ /**
42
+ * Sign an API request payload for authentication.
43
+ *
44
+ * The signing process:
45
+ * 1. Create a timestamp string (ISO 8601)
46
+ * 2. Build the signing payload: `${timestamp}.${JSON.stringify(body)}`
47
+ * 3. HMAC-SHA256 sign with the API key
48
+ *
49
+ * Headers produced:
50
+ * - `X-API-Key`: The raw API key
51
+ * - `X-Timestamp`: ISO timestamp
52
+ * - `X-Signature`: HMAC hex digest
53
+ * - `Content-Type`: application/json
54
+ */
55
+ export async function signRequest(apiKey, body) {
56
+ const timestamp = new Date().toISOString();
57
+ const signingPayload = `${timestamp}.${JSON.stringify(body)}`;
58
+ const signature = await hmacSha256(apiKey, signingPayload);
59
+ return {
60
+ 'X-API-Key': apiKey,
61
+ 'X-Timestamp': timestamp,
62
+ 'X-Signature': signature,
63
+ 'Content-Type': 'application/json',
64
+ };
65
+ }
66
+ /**
67
+ * Simple hash function for visitor fingerprinting.
68
+ * NOT cryptographically secure — used only for session identification.
69
+ */
70
+ export async function simpleHash(input) {
71
+ if (isNode) {
72
+ const nodeCrypto = await import('crypto');
73
+ return nodeCrypto.createHash('sha256').update(input).digest('hex').slice(0, 16);
74
+ }
75
+ if (isBrowser && typeof window.crypto.subtle !== 'undefined') {
76
+ const encoder = new TextEncoder();
77
+ const data = encoder.encode(input);
78
+ const hash = await window.crypto.subtle.digest('SHA-256', data);
79
+ return Array.from(new Uint8Array(hash))
80
+ .map((b) => b.toString(16).padStart(2, '0'))
81
+ .join('')
82
+ .slice(0, 16);
83
+ }
84
+ // Fallback: simple string hash (non-crypto)
85
+ let hash = 0;
86
+ for (let i = 0; i < input.length; i++) {
87
+ const char = input.charCodeAt(i);
88
+ hash = ((hash << 5) - hash + char) | 0;
89
+ }
90
+ return Math.abs(hash).toString(16).padStart(16, '0');
91
+ }
92
+ /**
93
+ * Generate a random hex string of specified byte length.
94
+ */
95
+ export function randomHex(bytes) {
96
+ const isNodeEnv = typeof process !== 'undefined' &&
97
+ typeof process.versions !== 'undefined' &&
98
+ typeof process.versions.node !== 'undefined';
99
+ if (isNodeEnv) {
100
+ try {
101
+ const nodeCrypto = require('crypto');
102
+ return nodeCrypto.randomBytes(bytes).toString('hex');
103
+ }
104
+ catch {
105
+ // Fallback below
106
+ }
107
+ }
108
+ if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues !== 'undefined') {
109
+ const array = new Uint8Array(bytes);
110
+ crypto.getRandomValues(array);
111
+ return Array.from(array)
112
+ .map((b) => b.toString(16).padStart(2, '0'))
113
+ .join('');
114
+ }
115
+ // Math.random fallback (not cryptographically secure)
116
+ const chars = '0123456789abcdef';
117
+ let result = '';
118
+ for (let i = 0; i < bytes * 2; i++) {
119
+ result += chars[Math.floor(Math.random() * chars.length)];
120
+ }
121
+ return result;
122
+ }
123
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // WAKZ SDK — Event Emitter System
3
+ // ═══════════════════════════════════════════════════════════════
4
+ /**
5
+ * Lightweight typed event emitter for the WAKZ SDK.
6
+ * Zero external dependencies.
7
+ */
8
+ export class WAKZEventEmitter {
9
+ constructor() {
10
+ this.listeners = new Map();
11
+ this.onceListeners = new Map();
12
+ }
13
+ /**
14
+ * Register an event listener.
15
+ */
16
+ on(event, callback) {
17
+ if (!this.listeners.has(event)) {
18
+ this.listeners.set(event, new Set());
19
+ }
20
+ this.listeners.get(event).add(callback);
21
+ return this;
22
+ }
23
+ /**
24
+ * Register a one-time event listener (auto-removes after first call).
25
+ */
26
+ once(event, callback) {
27
+ if (!this.onceListeners.has(event)) {
28
+ this.onceListeners.set(event, new Set());
29
+ }
30
+ this.onceListeners.get(event).add(callback);
31
+ return this;
32
+ }
33
+ /**
34
+ * Remove a specific event listener.
35
+ */
36
+ off(event, callback) {
37
+ this.listeners.get(event)?.delete(callback);
38
+ this.onceListeners.get(event)?.delete(callback);
39
+ return this;
40
+ }
41
+ /**
42
+ * Remove all listeners for a specific event, or all events if no event specified.
43
+ */
44
+ removeAllListeners(event) {
45
+ if (event) {
46
+ this.listeners.delete(event);
47
+ this.onceListeners.delete(event);
48
+ }
49
+ else {
50
+ this.listeners.clear();
51
+ this.onceListeners.clear();
52
+ }
53
+ return this;
54
+ }
55
+ /**
56
+ * Emit an event to all registered listeners.
57
+ */
58
+ emit(event, data) {
59
+ // Fire persistent listeners
60
+ const persistent = this.listeners.get(event);
61
+ if (persistent) {
62
+ for (const cb of persistent) {
63
+ try {
64
+ cb(data);
65
+ }
66
+ catch (err) {
67
+ // Prevent listener errors from breaking the emitter
68
+ console.error(`[WAKZ SDK] Error in "${event}" listener:`, err);
69
+ }
70
+ }
71
+ }
72
+ // Fire and consume once-listeners
73
+ const once = this.onceListeners.get(event);
74
+ if (once) {
75
+ for (const cb of once) {
76
+ try {
77
+ cb(data);
78
+ }
79
+ catch (err) {
80
+ console.error(`[WAKZ SDK] Error in "${event}" once-listener:`, err);
81
+ }
82
+ }
83
+ this.onceListeners.delete(event);
84
+ }
85
+ }
86
+ /**
87
+ * Get the count of listeners for a specific event.
88
+ */
89
+ listenerCount(event) {
90
+ return (this.listeners.get(event)?.size ?? 0) + (this.onceListeners.get(event)?.size ?? 0);
91
+ }
92
+ /**
93
+ * Destroy the emitter — remove all listeners.
94
+ */
95
+ destroy() {
96
+ this.listeners.clear();
97
+ this.onceListeners.clear();
98
+ }
99
+ }
100
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/http.ts"],"names":[],"mappings":"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"}