⚡ Zero-dependency plcbundle library exclusively for Bun

prepare & finalize

Changed files
+59 -5
examples
src
+23
examples/service-types.ts
··· 1 + const counts: Record<string, number>= {} 2 + 3 + export function process({ op }: { op: any }) { 4 + 5 + if (!op.operation?.services) { 6 + return 7 + } 8 + for (const key of Object.keys(op.operation.services)) { 9 + if (!counts[key]) { 10 + counts[key] = 1 11 + } else { 12 + counts[key] += 1 13 + } 14 + } 15 + } 16 + 17 + export function prepare() { 18 + return { counts } 19 + } 20 + 21 + export function finalize(results: any, { aggregate }: any) { 22 + console.log(Object.fromEntries(Object.entries(aggregate(results.map((r: any) => r.data.counts))).sort((a, b) => a[1] < b[1] ? 1 : -1))) 23 + }
+26 -5
src/plcbundle.ts
··· 309 309 310 310 // Determine mode based on what function is exported 311 311 let mode: 'detect' | 'process' = 'detect'; 312 + let mod: any; 312 313 if (module) { 313 314 try { 314 - const mod = await import(module); 315 + mod = await import(module); 315 316 // If module has 'process' function, use process mode 316 317 if (mod.process) { 317 318 mode = 'process'; ··· 337 338 onMatch 338 339 ); 339 340 } 340 - 341 + 341 342 // Load module if provided but single-threaded 342 - if (module && !callback) { 343 - const resolvedPath = module; 344 - const mod = await import(resolvedPath); 343 + if (mod && !callback) { 345 344 const userFn = mode === 'detect' ? (mod.detect || mod.default) : (mod.process || mod.default); 346 345 347 346 callback = (op, position, bundleNum, line) => { ··· 446 445 447 446 // Cleanup 448 447 workers.forEach(w => w.terminate()); 448 + 449 + if (modulePath) { 450 + const mod = await import(modulePath); 451 + if (mod.finalize) { 452 + await mod.finalize(results, { aggregate: this.aggregate }); 453 + } 454 + } 449 455 450 456 // Aggregate results 451 457 let totalOps = 0; ··· 475 481 matches: flush || mode === 'process' ? undefined : allMatches, 476 482 }; 477 483 } 484 + 485 + private aggregate(objects: Array<{ [key: string]: number }>): { [key: string]: number } { 486 + const aggregatedDict: { [key: string]: number } = {}; 487 + 488 + for (const currentObj of objects) { 489 + for (const key in currentObj) { 490 + if (Object.prototype.hasOwnProperty.call(currentObj, key)) { 491 + aggregatedDict[key] = (aggregatedDict[key] || 0) + currentObj[key]; 492 + } 493 + } 494 + } 495 + 496 + return aggregatedDict; 497 + } 498 + 478 499 479 500 /** 480 501 * Fast single-threaded processing (optimized)
+10
src/worker.ts
··· 123 123 // Continue on error 124 124 } 125 125 } 126 + 127 + let prepareResult: any; 128 + if (typeof mod.prepare === 'function') { 129 + try { 130 + prepareResult = await mod.prepare(); 131 + } catch (error) { 132 + // Silently ignore finalize errors 133 + } 134 + } 126 135 127 136 // Send final result 128 137 self.postMessage({ ··· 130 139 totalOps, 131 140 totalBytes, 132 141 matches: flush ? [] : matches, 142 + data: prepareResult || null 133 143 } as WorkerResult); 134 144 };