@computekit/core 0.1.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.js ADDED
@@ -0,0 +1,800 @@
1
+ // src/utils.ts
2
+ function generateId() {
3
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
4
+ }
5
+ function isSharedArrayBufferAvailable() {
6
+ try {
7
+ return typeof SharedArrayBuffer !== "undefined";
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function isWasmSupported() {
13
+ try {
14
+ if (typeof WebAssembly === "object") {
15
+ const module = new WebAssembly.Module(
16
+ Uint8Array.of(0, 97, 115, 109, 1, 0, 0, 0)
17
+ );
18
+ return module instanceof WebAssembly.Module;
19
+ }
20
+ } catch {
21
+ }
22
+ return false;
23
+ }
24
+ function getHardwareConcurrency() {
25
+ if (typeof navigator !== "undefined" && navigator.hardwareConcurrency) {
26
+ return navigator.hardwareConcurrency;
27
+ }
28
+ return 4;
29
+ }
30
+ function createDeferred() {
31
+ let resolve;
32
+ let reject;
33
+ const promise = new Promise((res, rej) => {
34
+ resolve = res;
35
+ reject = rej;
36
+ });
37
+ return { promise, resolve, reject };
38
+ }
39
+ function createTimeout(ms, message) {
40
+ return new Promise((_, reject) => {
41
+ setTimeout(() => {
42
+ reject(new Error(message || `Operation timed out after ${ms}ms`));
43
+ }, ms);
44
+ });
45
+ }
46
+ async function withTimeout(promise, ms, message) {
47
+ return Promise.race([promise, createTimeout(ms, message)]);
48
+ }
49
+ function findTransferables(data) {
50
+ const transferables = [];
51
+ const seen = /* @__PURE__ */ new WeakSet();
52
+ function traverse(obj) {
53
+ if (obj === null || typeof obj !== "object") return;
54
+ if (seen.has(obj)) return;
55
+ seen.add(obj);
56
+ if (obj instanceof ArrayBuffer) {
57
+ transferables.push(obj);
58
+ return;
59
+ }
60
+ if (ArrayBuffer.isView(obj)) {
61
+ transferables.push(obj.buffer);
62
+ return;
63
+ }
64
+ if (obj instanceof MessagePort) {
65
+ transferables.push(obj);
66
+ return;
67
+ }
68
+ if (typeof ImageBitmap !== "undefined" && obj instanceof ImageBitmap) {
69
+ transferables.push(obj);
70
+ return;
71
+ }
72
+ if (typeof OffscreenCanvas !== "undefined" && obj instanceof OffscreenCanvas) {
73
+ transferables.push(obj);
74
+ return;
75
+ }
76
+ if (Array.isArray(obj)) {
77
+ obj.forEach(traverse);
78
+ return;
79
+ }
80
+ if (obj instanceof Map) {
81
+ obj.forEach((value, key) => {
82
+ traverse(key);
83
+ traverse(value);
84
+ });
85
+ return;
86
+ }
87
+ if (obj instanceof Set) {
88
+ obj.forEach(traverse);
89
+ return;
90
+ }
91
+ Object.values(obj).forEach(traverse);
92
+ }
93
+ traverse(data);
94
+ return transferables;
95
+ }
96
+ var EventEmitter = class {
97
+ handlers = /* @__PURE__ */ new Map();
98
+ on(event, handler) {
99
+ if (!this.handlers.has(event)) {
100
+ this.handlers.set(event, /* @__PURE__ */ new Set());
101
+ }
102
+ this.handlers.get(event).add(handler);
103
+ return () => this.off(event, handler);
104
+ }
105
+ off(event, handler) {
106
+ this.handlers.get(event)?.delete(handler);
107
+ }
108
+ emit(event, data) {
109
+ this.handlers.get(event)?.forEach((handler) => {
110
+ try {
111
+ handler(data);
112
+ } catch (err) {
113
+ console.error(`Error in event handler for ${String(event)}:`, err);
114
+ }
115
+ });
116
+ }
117
+ removeAllListeners(event) {
118
+ if (event) {
119
+ this.handlers.delete(event);
120
+ } else {
121
+ this.handlers.clear();
122
+ }
123
+ }
124
+ };
125
+ var LRUCache = class {
126
+ cache = /* @__PURE__ */ new Map();
127
+ maxSize;
128
+ constructor(maxSize = 100) {
129
+ this.maxSize = maxSize;
130
+ }
131
+ get(key) {
132
+ const value = this.cache.get(key);
133
+ if (value !== void 0) {
134
+ this.cache.delete(key);
135
+ this.cache.set(key, value);
136
+ }
137
+ return value;
138
+ }
139
+ set(key, value) {
140
+ if (this.cache.has(key)) {
141
+ this.cache.delete(key);
142
+ } else if (this.cache.size >= this.maxSize) {
143
+ const firstKey = this.cache.keys().next().value;
144
+ if (firstKey !== void 0) {
145
+ this.cache.delete(firstKey);
146
+ }
147
+ }
148
+ this.cache.set(key, value);
149
+ }
150
+ has(key) {
151
+ return this.cache.has(key);
152
+ }
153
+ delete(key) {
154
+ return this.cache.delete(key);
155
+ }
156
+ clear() {
157
+ this.cache.clear();
158
+ }
159
+ get size() {
160
+ return this.cache.size;
161
+ }
162
+ };
163
+ function createLogger(prefix, enabled = false) {
164
+ const noop = () => {
165
+ };
166
+ const log = (level) => enabled ? (...args) => console.log(`[${prefix}:${level}]`, ...args) : noop;
167
+ return {
168
+ debug: log("debug"),
169
+ info: log("info"),
170
+ warn: enabled ? (...args) => console.warn(`[${prefix}:warn]`, ...args) : noop,
171
+ error: (...args) => console.error(`[${prefix}:error]`, ...args)
172
+ };
173
+ }
174
+
175
+ // src/pool.ts
176
+ var WorkerPool = class {
177
+ workers = /* @__PURE__ */ new Map();
178
+ taskQueue = [];
179
+ pendingTasks = /* @__PURE__ */ new Map();
180
+ functions = /* @__PURE__ */ new Map();
181
+ workerUrl = null;
182
+ options;
183
+ logger;
184
+ initialized = false;
185
+ stats = {
186
+ tasksCompleted: 0,
187
+ tasksFailed: 0,
188
+ totalDuration: 0
189
+ };
190
+ constructor(options = {}) {
191
+ this.options = {
192
+ maxWorkers: options.maxWorkers ?? getHardwareConcurrency(),
193
+ timeout: options.timeout ?? 3e4,
194
+ debug: options.debug ?? false,
195
+ workerPath: options.workerPath ?? "",
196
+ useSharedMemory: options.useSharedMemory ?? true
197
+ };
198
+ this.logger = createLogger("ComputeKit:Pool", this.options.debug);
199
+ this.logger.info("WorkerPool created with options:", this.options);
200
+ }
201
+ /**
202
+ * Initialize the worker pool
203
+ */
204
+ async initialize() {
205
+ if (this.initialized) return;
206
+ this.logger.info("Initializing worker pool...");
207
+ this.logger.info("Registered functions:", Array.from(this.functions.keys()));
208
+ this.workerUrl = this.createWorkerBlob();
209
+ const workerCount = Math.min(2, this.options.maxWorkers);
210
+ for (let i = 0; i < workerCount; i++) {
211
+ await this.createWorker();
212
+ }
213
+ this.initialized = true;
214
+ this.logger.info(`Worker pool initialized with ${workerCount} workers`);
215
+ }
216
+ pendingRecreate = null;
217
+ /**
218
+ * Register a compute function
219
+ */
220
+ register(name, fn) {
221
+ this.logger.debug(`Registering function: ${name}`);
222
+ this.functions.set(name, {
223
+ fn,
224
+ serialized: fn.toString()
225
+ });
226
+ if (this.initialized) {
227
+ this.pendingRecreate = this.recreateWorkers();
228
+ } else {
229
+ if (this.workerUrl) {
230
+ URL.revokeObjectURL(this.workerUrl);
231
+ this.workerUrl = null;
232
+ }
233
+ }
234
+ }
235
+ /**
236
+ * Recreate workers with updated function registry
237
+ */
238
+ async recreateWorkers() {
239
+ this.logger.debug("Recreating workers with updated functions...");
240
+ if (this.workerUrl) {
241
+ URL.revokeObjectURL(this.workerUrl);
242
+ }
243
+ this.workerUrl = this.createWorkerBlob();
244
+ const idleWorkers = Array.from(this.workers.entries()).filter(
245
+ ([_, w]) => w.state === "idle"
246
+ );
247
+ for (const [id, poolWorker] of idleWorkers) {
248
+ poolWorker.worker.terminate();
249
+ this.workers.delete(id);
250
+ }
251
+ const workerCount = Math.max(
252
+ 1,
253
+ Math.min(2, this.options.maxWorkers) - this.workers.size
254
+ );
255
+ for (let i = 0; i < workerCount; i++) {
256
+ await this.createWorker();
257
+ }
258
+ }
259
+ /**
260
+ * Execute a compute function
261
+ */
262
+ async execute(name, input, options) {
263
+ if (this.pendingRecreate) {
264
+ await this.pendingRecreate;
265
+ this.pendingRecreate = null;
266
+ }
267
+ if (!this.initialized) {
268
+ await this.initialize();
269
+ }
270
+ const fn = this.functions.get(name);
271
+ if (!fn) {
272
+ throw new Error(`Function "${name}" not registered`);
273
+ }
274
+ const taskId = generateId();
275
+ const timeout = options?.timeout ?? this.options.timeout;
276
+ this.logger.debug(`Executing task ${taskId} for function "${name}"`);
277
+ if (options?.signal?.aborted) {
278
+ throw new Error("Operation aborted");
279
+ }
280
+ const deferred = createDeferred();
281
+ const task = {
282
+ id: taskId,
283
+ functionName: name,
284
+ input,
285
+ options,
286
+ deferred,
287
+ priority: options?.priority ?? 5,
288
+ createdAt: Date.now(),
289
+ onProgress: options?.onProgress
290
+ };
291
+ if (options?.signal) {
292
+ options.signal.addEventListener("abort", () => {
293
+ this.cancelTask(taskId);
294
+ deferred.reject(new Error("Operation aborted"));
295
+ });
296
+ }
297
+ this.enqueue(task);
298
+ this.processQueue();
299
+ return withTimeout(deferred.promise, timeout, `Task "${name}" timed out`);
300
+ }
301
+ /**
302
+ * Get pool statistics
303
+ */
304
+ getStats() {
305
+ const workers = Array.from(this.workers.values()).map(
306
+ (w) => ({
307
+ id: w.id,
308
+ state: w.state,
309
+ currentTask: w.currentTask,
310
+ tasksCompleted: w.tasksCompleted,
311
+ errors: w.errors,
312
+ createdAt: w.createdAt,
313
+ lastActiveAt: w.lastActiveAt
314
+ })
315
+ );
316
+ return {
317
+ workers,
318
+ totalWorkers: this.workers.size,
319
+ activeWorkers: workers.filter((w) => w.state === "busy").length,
320
+ idleWorkers: workers.filter((w) => w.state === "idle").length,
321
+ queueLength: this.taskQueue.length,
322
+ tasksCompleted: this.stats.tasksCompleted,
323
+ tasksFailed: this.stats.tasksFailed,
324
+ averageTaskDuration: this.stats.tasksCompleted > 0 ? this.stats.totalDuration / this.stats.tasksCompleted : 0
325
+ };
326
+ }
327
+ /**
328
+ * Terminate all workers and clean up
329
+ */
330
+ async terminate() {
331
+ this.logger.info("Terminating worker pool...");
332
+ for (const task of this.pendingTasks.values()) {
333
+ task.deferred.reject(new Error("Worker pool terminated"));
334
+ }
335
+ this.pendingTasks.clear();
336
+ this.taskQueue = [];
337
+ for (const poolWorker of this.workers.values()) {
338
+ poolWorker.worker.terminate();
339
+ poolWorker.state = "terminated";
340
+ }
341
+ this.workers.clear();
342
+ if (this.workerUrl) {
343
+ URL.revokeObjectURL(this.workerUrl);
344
+ this.workerUrl = null;
345
+ }
346
+ this.initialized = false;
347
+ this.logger.info("Worker pool terminated");
348
+ }
349
+ /**
350
+ * Create the worker blob URL
351
+ */
352
+ createWorkerBlob() {
353
+ const functionsCode = Array.from(this.functions.entries()).map(([name, { serialized }]) => `"${name}": ${serialized}`).join(",\n");
354
+ this.logger.debug(
355
+ "Creating worker blob with functions:",
356
+ Array.from(this.functions.keys())
357
+ );
358
+ const workerCode = `
359
+ const functions = {
360
+ ${functionsCode}
361
+ };
362
+
363
+ self.onmessage = function(e) {
364
+ const msg = e.data;
365
+ if (msg.type === 'execute') {
366
+ const fn = functions[msg.payload.functionName];
367
+ if (!fn) {
368
+ self.postMessage({ id: msg.id, type: 'error', payload: { message: 'Function not found: ' + msg.payload.functionName } });
369
+ return;
370
+ }
371
+ try {
372
+ const start = performance.now();
373
+ Promise.resolve(fn(msg.payload.input)).then(function(result) {
374
+ self.postMessage({ id: msg.id, type: 'result', payload: { data: result, duration: performance.now() - start } });
375
+ }).catch(function(err) {
376
+ self.postMessage({ id: msg.id, type: 'error', payload: { message: err.message || String(err) } });
377
+ });
378
+ } catch (err) {
379
+ self.postMessage({ id: msg.id, type: 'error', payload: { message: err.message || String(err) } });
380
+ }
381
+ }
382
+ };
383
+ self.postMessage({ type: 'ready' });
384
+ `;
385
+ const blob = new Blob([workerCode], { type: "application/javascript" });
386
+ return URL.createObjectURL(blob);
387
+ }
388
+ /**
389
+ * Create a new worker
390
+ */
391
+ async createWorker() {
392
+ if (!this.workerUrl) {
393
+ this.workerUrl = this.createWorkerBlob();
394
+ }
395
+ const id = generateId();
396
+ const worker = new Worker(this.workerUrl);
397
+ let resolveReady;
398
+ const readyPromise = new Promise((resolve) => {
399
+ resolveReady = resolve;
400
+ });
401
+ const poolWorker = {
402
+ id,
403
+ worker,
404
+ state: "idle",
405
+ tasksCompleted: 0,
406
+ errors: 0,
407
+ createdAt: Date.now(),
408
+ lastActiveAt: Date.now(),
409
+ ready: false,
410
+ readyPromise
411
+ };
412
+ worker.onmessage = (e) => {
413
+ if (e.data.type === "ready") {
414
+ poolWorker.ready = true;
415
+ resolveReady();
416
+ }
417
+ this.handleWorkerMessage(poolWorker, e.data);
418
+ };
419
+ worker.onerror = (e) => {
420
+ this.handleWorkerError(poolWorker, e);
421
+ };
422
+ this.workers.set(id, poolWorker);
423
+ this.logger.debug(`Created worker ${id}`);
424
+ await readyPromise;
425
+ this.logger.debug(`Worker ${id} is ready`);
426
+ return poolWorker;
427
+ }
428
+ /**
429
+ * Handle messages from workers
430
+ */
431
+ handleWorkerMessage(poolWorker, message) {
432
+ this.logger.debug("Received message from worker:", message);
433
+ const { id, type, payload } = message;
434
+ switch (type) {
435
+ case "ready":
436
+ this.logger.debug(`Worker ${poolWorker.id} ready`);
437
+ break;
438
+ case "result": {
439
+ const task = this.pendingTasks.get(id);
440
+ if (task) {
441
+ const resultPayload = payload;
442
+ this.pendingTasks.delete(id);
443
+ poolWorker.state = "idle";
444
+ poolWorker.currentTask = void 0;
445
+ poolWorker.tasksCompleted++;
446
+ poolWorker.lastActiveAt = Date.now();
447
+ this.stats.tasksCompleted++;
448
+ this.stats.totalDuration += resultPayload.duration;
449
+ this.logger.debug(
450
+ `Task ${id} completed in ${resultPayload.duration.toFixed(2)}ms`
451
+ );
452
+ task.deferred.resolve(resultPayload.data);
453
+ this.processQueue();
454
+ }
455
+ break;
456
+ }
457
+ case "error": {
458
+ const task = this.pendingTasks.get(id);
459
+ if (task) {
460
+ const errorPayload = payload;
461
+ this.pendingTasks.delete(id);
462
+ poolWorker.state = "idle";
463
+ poolWorker.currentTask = void 0;
464
+ poolWorker.errors++;
465
+ poolWorker.lastActiveAt = Date.now();
466
+ this.stats.tasksFailed++;
467
+ const error = new Error(errorPayload.message);
468
+ if (errorPayload.stack) {
469
+ error.stack = errorPayload.stack;
470
+ }
471
+ this.logger.error(`Task ${id} failed:`, errorPayload.message);
472
+ task.deferred.reject(error);
473
+ this.processQueue();
474
+ }
475
+ break;
476
+ }
477
+ case "progress": {
478
+ const progressPayload = payload;
479
+ const task = this.pendingTasks.get(progressPayload.taskId);
480
+ if (task?.onProgress) {
481
+ task.onProgress(progressPayload.progress);
482
+ }
483
+ break;
484
+ }
485
+ }
486
+ }
487
+ /**
488
+ * Handle worker errors
489
+ */
490
+ handleWorkerError(poolWorker, error) {
491
+ this.logger.error(`Worker ${poolWorker.id} error:`, error.message);
492
+ poolWorker.state = "error";
493
+ poolWorker.errors++;
494
+ if (poolWorker.currentTask) {
495
+ const task = this.pendingTasks.get(poolWorker.currentTask);
496
+ if (task) {
497
+ this.pendingTasks.delete(poolWorker.currentTask);
498
+ task.deferred.reject(new Error(`Worker error: ${error.message}`));
499
+ }
500
+ }
501
+ poolWorker.worker.terminate();
502
+ this.workers.delete(poolWorker.id);
503
+ this.createWorker().then(() => this.processQueue());
504
+ }
505
+ /**
506
+ * Add task to queue (priority-based)
507
+ */
508
+ enqueue(task) {
509
+ let inserted = false;
510
+ for (let i = 0; i < this.taskQueue.length; i++) {
511
+ if (task.priority > this.taskQueue[i].priority) {
512
+ this.taskQueue.splice(i, 0, task);
513
+ inserted = true;
514
+ break;
515
+ }
516
+ }
517
+ if (!inserted) {
518
+ this.taskQueue.push(task);
519
+ }
520
+ }
521
+ /**
522
+ * Process queued tasks
523
+ */
524
+ async processQueue() {
525
+ if (this.taskQueue.length === 0) return;
526
+ let idleWorker;
527
+ for (const worker of this.workers.values()) {
528
+ if (worker.state === "idle") {
529
+ idleWorker = worker;
530
+ break;
531
+ }
532
+ }
533
+ if (!idleWorker && this.workers.size < this.options.maxWorkers) {
534
+ idleWorker = await this.createWorker();
535
+ }
536
+ if (!idleWorker) return;
537
+ const task = this.taskQueue.shift();
538
+ if (!task) return;
539
+ this.executeOnWorker(idleWorker, task);
540
+ if (this.taskQueue.length > 0) {
541
+ this.processQueue();
542
+ }
543
+ }
544
+ /**
545
+ * Execute task on a specific worker
546
+ */
547
+ executeOnWorker(poolWorker, task) {
548
+ this.logger.debug(
549
+ `executeOnWorker: Starting task ${task.id} (${task.functionName}) on worker ${poolWorker.id}`
550
+ );
551
+ poolWorker.state = "busy";
552
+ poolWorker.currentTask = task.id;
553
+ poolWorker.lastActiveAt = Date.now();
554
+ this.pendingTasks.set(task.id, task);
555
+ const message = {
556
+ id: task.id,
557
+ type: "execute",
558
+ payload: {
559
+ functionName: task.functionName,
560
+ input: task.input
561
+ // Don't send options - they may contain non-cloneable objects like AbortSignal
562
+ },
563
+ timestamp: Date.now()
564
+ };
565
+ const transfer = findTransferables(task.input);
566
+ this.logger.debug(`Posting message to worker:`, message);
567
+ poolWorker.worker.postMessage(message, transfer);
568
+ this.logger.debug(`Message posted to worker ${poolWorker.id}`);
569
+ }
570
+ /**
571
+ * Cancel a pending task
572
+ */
573
+ cancelTask(taskId) {
574
+ const queueIndex = this.taskQueue.findIndex((t) => t.id === taskId);
575
+ if (queueIndex !== -1) {
576
+ this.taskQueue.splice(queueIndex, 1);
577
+ }
578
+ this.pendingTasks.delete(taskId);
579
+ }
580
+ };
581
+
582
+ // src/wasm.ts
583
+ var logger = createLogger("ComputeKit:WASM");
584
+ var moduleCache = new LRUCache(10);
585
+ var instanceCache = new LRUCache(10);
586
+ async function loadWasmModule(source) {
587
+ if (typeof source === "string") {
588
+ const cached = moduleCache.get(source);
589
+ if (cached) {
590
+ logger.debug("Using cached WASM module:", source);
591
+ return cached;
592
+ }
593
+ }
594
+ let bytes;
595
+ if (typeof source === "string") {
596
+ if (source.startsWith("data:")) {
597
+ const base64 = source.split(",")[1];
598
+ bytes = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
599
+ } else {
600
+ logger.debug("Fetching WASM from:", source);
601
+ const response = await fetch(source);
602
+ if (!response.ok) {
603
+ throw new Error(`Failed to fetch WASM: ${response.statusText}`);
604
+ }
605
+ if (WebAssembly.compileStreaming) {
606
+ const module2 = await WebAssembly.compileStreaming(response);
607
+ moduleCache.set(source, module2);
608
+ return module2;
609
+ }
610
+ bytes = await response.arrayBuffer();
611
+ }
612
+ } else {
613
+ bytes = source;
614
+ }
615
+ const module = await WebAssembly.compile(bytes);
616
+ if (typeof source === "string") {
617
+ moduleCache.set(source, module);
618
+ }
619
+ return module;
620
+ }
621
+ async function instantiateWasm(module, imports = {}) {
622
+ return WebAssembly.instantiate(module, imports);
623
+ }
624
+ async function loadAndInstantiate(config) {
625
+ const { source, imports = {}, memory } = config;
626
+ const wasmImports = { ...imports };
627
+ if (memory) {
628
+ wasmImports.env = {
629
+ ...wasmImports.env,
630
+ memory: new WebAssembly.Memory({
631
+ initial: memory.initial,
632
+ maximum: memory.maximum,
633
+ shared: memory.shared
634
+ })
635
+ };
636
+ }
637
+ const module = await loadWasmModule(source);
638
+ const instance = await instantiateWasm(module, wasmImports);
639
+ return { module, instance };
640
+ }
641
+ async function loadAssemblyScript(source, imports = {}) {
642
+ const defaultImports = {
643
+ env: {
644
+ abort: (_message, fileName, line, column) => {
645
+ console.error(`AssemblyScript abort at ${fileName}:${line}:${column}`);
646
+ },
647
+ seed: () => Date.now(),
648
+ ...imports.env || {}
649
+ },
650
+ ...imports
651
+ };
652
+ const { module, instance } = await loadAndInstantiate({
653
+ source,
654
+ imports: defaultImports
655
+ });
656
+ return {
657
+ module,
658
+ instance,
659
+ exports: instance.exports
660
+ };
661
+ }
662
+ function wrapWasmExports(instance) {
663
+ return instance.exports;
664
+ }
665
+ function getMemoryView(memory, ArrayType, offset = 0, length) {
666
+ return new ArrayType(memory.buffer, offset, length);
667
+ }
668
+ function copyToWasmMemory(memory, data, offset) {
669
+ const view = new Uint8Array(memory.buffer);
670
+ const source = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
671
+ view.set(source, offset);
672
+ }
673
+ function copyFromWasmMemory(memory, offset, length) {
674
+ const view = new Uint8Array(memory.buffer, offset, length);
675
+ return new Uint8Array(view);
676
+ }
677
+ function clearWasmCache() {
678
+ moduleCache.clear();
679
+ instanceCache.clear();
680
+ }
681
+ function getWasmCacheStats() {
682
+ return {
683
+ modules: moduleCache.size,
684
+ instances: instanceCache.size
685
+ };
686
+ }
687
+
688
+ // src/index.ts
689
+ var logger2 = createLogger("ComputeKit");
690
+ var ComputeKit = class extends EventEmitter {
691
+ pool;
692
+ constructor(options = {}) {
693
+ super();
694
+ this.pool = new WorkerPool(options);
695
+ logger2.debug("ComputeKit initialized", options);
696
+ }
697
+ /**
698
+ * Initialize ComputeKit
699
+ * Called automatically on first run, but can be called manually for eager initialization
700
+ */
701
+ async initialize() {
702
+ await this.pool.initialize();
703
+ }
704
+ /**
705
+ * Register a compute function
706
+ *
707
+ * @param name - Unique name for the function
708
+ * @param fn - The function to execute (will run in a Web Worker)
709
+ *
710
+ * @example
711
+ * ```ts
712
+ * kit.register('sum', (arr: number[]) => arr.reduce((a, b) => a + b, 0));
713
+ * ```
714
+ */
715
+ register(name, fn) {
716
+ this.pool.register(name, fn);
717
+ return this;
718
+ }
719
+ /**
720
+ * Execute a registered compute function
721
+ *
722
+ * @param name - Name of the registered function
723
+ * @param input - Input data for the function
724
+ * @param options - Execution options
725
+ * @returns Promise resolving to the function result
726
+ *
727
+ * @example
728
+ * ```ts
729
+ * const sum = await kit.run('sum', [1, 2, 3, 4, 5]);
730
+ * ```
731
+ */
732
+ async run(name, input, options) {
733
+ return this.pool.execute(name, input, options);
734
+ }
735
+ /**
736
+ * Execute a registered compute function with full result metadata
737
+ *
738
+ * @param name - Name of the registered function
739
+ * @param input - Input data for the function
740
+ * @param options - Execution options
741
+ * @returns Promise resolving to ComputeResult with metadata
742
+ *
743
+ * @example
744
+ * ```ts
745
+ * const result = await kit.runWithMetadata('sum', data);
746
+ * console.log(`Took ${result.duration}ms`);
747
+ * ```
748
+ */
749
+ async runWithMetadata(name, input, options) {
750
+ const startTime = performance.now();
751
+ const data = await this.pool.execute(name, input, options);
752
+ const duration = performance.now() - startTime;
753
+ return {
754
+ data,
755
+ duration,
756
+ cached: false,
757
+ workerId: "unknown"
758
+ // Would need pool changes to track this
759
+ };
760
+ }
761
+ /**
762
+ * Get pool statistics
763
+ */
764
+ getStats() {
765
+ return this.pool.getStats();
766
+ }
767
+ /**
768
+ * Check if WebAssembly is supported
769
+ */
770
+ isWasmSupported() {
771
+ return isWasmSupported();
772
+ }
773
+ /**
774
+ * Terminate the worker pool and clean up resources
775
+ */
776
+ async terminate() {
777
+ await this.pool.terminate();
778
+ this.removeAllListeners();
779
+ }
780
+ };
781
+ function createComputeKit(options) {
782
+ return new ComputeKit(options);
783
+ }
784
+ var defaultInstance = null;
785
+ function getDefaultInstance() {
786
+ if (!defaultInstance) {
787
+ defaultInstance = new ComputeKit();
788
+ }
789
+ return defaultInstance;
790
+ }
791
+ function register(name, fn) {
792
+ getDefaultInstance().register(name, fn);
793
+ }
794
+ async function run(name, input, options) {
795
+ return getDefaultInstance().run(name, input, options);
796
+ }
797
+
798
+ export { ComputeKit, WorkerPool, clearWasmCache, copyFromWasmMemory, copyToWasmMemory, createComputeKit, findTransferables, getDefaultInstance, getHardwareConcurrency, getMemoryView, getWasmCacheStats, isSharedArrayBufferAvailable, isWasmSupported, loadAndInstantiate, loadAssemblyScript, loadWasmModule, register, run, wrapWasmExports };
799
+ //# sourceMappingURL=index.js.map
800
+ //# sourceMappingURL=index.js.map