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.
- package/README.md +264 -0
- package/dist/client.d.ts +124 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +323 -0
- package/dist/client.js.map +1 -0
- package/dist/crypto.d.ts +26 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +161 -0
- package/dist/crypto.js.map +1 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/client.mjs +319 -0
- package/dist/esm/crypto.js.map +1 -0
- package/dist/esm/crypto.mjs +123 -0
- package/dist/esm/events.js.map +1 -0
- package/dist/esm/events.mjs +100 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/http.mjs +159 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index.mjs +32 -0
- package/dist/esm/session.js.map +1 -0
- package/dist/esm/session.mjs +186 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/types.mjs +5 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/utils.mjs +139 -0
- package/dist/esm/websocket.js.map +1 -0
- package/dist/esm/websocket.mjs +363 -0
- package/dist/events.d.ts +38 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +104 -0
- package/dist/events.js.map +1 -0
- package/dist/http.d.ts +37 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +163 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/session.d.ts +75 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +190 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +149 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +56 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +153 -0
- package/dist/utils.js.map +1 -0
- package/dist/websocket.d.ts +93 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +367 -0
- package/dist/websocket.js.map +1 -0
- 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":"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"}
|
|
@@ -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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"}
|