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