@embedpdf/engines 2.0.2 → 2.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.
Files changed (50) hide show
  1. package/dist/direct-engine-BeZ18SKz.cjs +2 -0
  2. package/dist/direct-engine-BeZ18SKz.cjs.map +1 -0
  3. package/dist/{direct-engine-CHrj3o_a.js → direct-engine-CB3k-o0I.js} +509 -9
  4. package/dist/direct-engine-CB3k-o0I.js.map +1 -0
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.js +11 -4
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/orchestrator/remote-executor.d.ts +5 -0
  10. package/dist/lib/pdfium/cdn-fonts.d.ts +50 -0
  11. package/dist/lib/pdfium/engine.d.ts +17 -2
  12. package/dist/lib/pdfium/font-fallback.d.ts +207 -0
  13. package/dist/lib/pdfium/index.cjs +1 -1
  14. package/dist/lib/pdfium/index.cjs.map +1 -1
  15. package/dist/lib/pdfium/index.d.ts +2 -0
  16. package/dist/lib/pdfium/index.js +55 -2
  17. package/dist/lib/pdfium/index.js.map +1 -1
  18. package/dist/lib/pdfium/runner.d.ts +5 -1
  19. package/dist/lib/pdfium/web/direct-engine.cjs +1 -1
  20. package/dist/lib/pdfium/web/direct-engine.d.ts +8 -0
  21. package/dist/lib/pdfium/web/direct-engine.js +1 -1
  22. package/dist/lib/pdfium/web/worker-engine.cjs +1 -1
  23. package/dist/lib/pdfium/web/worker-engine.cjs.map +1 -1
  24. package/dist/lib/pdfium/web/worker-engine.d.ts +8 -0
  25. package/dist/lib/pdfium/web/worker-engine.js +5 -4
  26. package/dist/lib/pdfium/web/worker-engine.js.map +1 -1
  27. package/dist/preact/index.cjs +1 -1
  28. package/dist/preact/index.cjs.map +1 -1
  29. package/dist/preact/index.js +14 -4
  30. package/dist/preact/index.js.map +1 -1
  31. package/dist/react/index.cjs +1 -1
  32. package/dist/react/index.cjs.map +1 -1
  33. package/dist/react/index.js +14 -4
  34. package/dist/react/index.js.map +1 -1
  35. package/dist/shared-preact/hooks/use-pdfium-engine.d.ts +5 -0
  36. package/dist/shared-react/hooks/use-pdfium-engine.d.ts +5 -0
  37. package/dist/svelte/hooks/use-pdfium-engine.svelte.d.ts +5 -0
  38. package/dist/svelte/index.cjs +1 -1
  39. package/dist/svelte/index.cjs.map +1 -1
  40. package/dist/svelte/index.js +8 -3
  41. package/dist/svelte/index.js.map +1 -1
  42. package/dist/vue/composables/use-pdfium-engine.d.ts +5 -0
  43. package/dist/vue/index.cjs +1 -1
  44. package/dist/vue/index.cjs.map +1 -1
  45. package/dist/vue/index.js +4 -4
  46. package/dist/vue/index.js.map +1 -1
  47. package/package.json +10 -3
  48. package/dist/direct-engine-B7b7cTsH.cjs +0 -2
  49. package/dist/direct-engine-B7b7cTsH.cjs.map +0 -1
  50. package/dist/direct-engine-CHrj3o_a.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"worker-engine.cjs","sources":["../../../../src/lib/orchestrator/remote-executor.ts","../../../../src/lib/image-encoder/worker-pool.ts"],"sourcesContent":["import {\n BatchProgress,\n Logger,\n NoopLogger,\n PdfDocumentObject,\n PdfPageObject,\n PdfTask,\n PdfErrorReason,\n PdfFile,\n PdfOpenDocumentBufferOptions,\n PdfMetadataObject,\n PdfBookmarksObject,\n PdfBookmarkObject,\n PdfRenderPageOptions,\n PdfRenderThumbnailOptions,\n PdfRenderPageAnnotationOptions,\n PdfAnnotationObject,\n PdfTextRectObject,\n PdfAttachmentObject,\n PdfAddAttachmentParams,\n PdfWidgetAnnoObject,\n FormFieldValue,\n PdfFlattenPageOptions,\n PdfPageFlattenResult,\n PdfRedactTextOptions,\n Rect,\n PageTextSlice,\n PdfGlyphObject,\n PdfPageGeometry,\n PdfPrintOptions,\n PdfSignatureObject,\n AnnotationCreateContext,\n Task,\n TaskError,\n PdfErrorCode,\n SearchResult,\n serializeLogger,\n IPdfiumExecutor,\n ImageDataLike,\n} from '@embedpdf/models';\nimport type { WorkerRequest, WorkerResponse } from './pdfium-native-runner';\n\n/**\n * Options for creating a RemoteExecutor\n */\nexport interface RemoteExecutorOptions {\n /**\n * URL to the pdfium.wasm file (required)\n */\n wasmUrl: string;\n /**\n * Logger instance for debugging\n */\n logger?: Logger;\n}\n\nconst LOG_SOURCE = 'RemoteExecutor';\nconst LOG_CATEGORY = 'Worker';\n\n/**\n * Message types for worker communication\n */\ntype MessageType =\n | 'destroy'\n | 'openDocumentBuffer'\n | 'getMetadata'\n | 'setMetadata'\n | 'getDocPermissions'\n | 'getDocUserPermissions'\n | 'getSignatures'\n | 'getBookmarks'\n | 'setBookmarks'\n | 'deleteBookmarks'\n | 'renderPageRaw'\n | 'renderPageRect'\n | 'renderThumbnailRaw'\n | 'renderPageAnnotationRaw'\n | 'getPageAnnotations'\n | 'getPageAnnotationsRaw'\n | 'createPageAnnotation'\n | 'updatePageAnnotation'\n | 'removePageAnnotation'\n | 'getPageTextRects'\n | 'searchInPage'\n | 'getAnnotationsBatch'\n | 'searchBatch'\n | 'getAttachments'\n | 'addAttachment'\n | 'removeAttachment'\n | 'readAttachmentContent'\n | 'setFormFieldValue'\n | 'flattenPage'\n | 'extractPages'\n | 'extractText'\n | 'redactTextInRects'\n | 'getTextSlices'\n | 'getPageGlyphs'\n | 'getPageGeometry'\n | 'merge'\n | 'mergePages'\n | 'preparePrintDocument'\n | 'saveAsCopy'\n | 'closeDocument'\n | 'closeAllDocuments';\n\n/**\n * RemoteExecutor - Proxy for worker communication\n *\n * This implements IPdfExecutor but forwards all calls to a Web Worker.\n * It handles:\n * - Serialization/deserialization of messages\n * - Promise/Task conversion\n * - Error handling\n * - Progress tracking\n */\nexport class RemoteExecutor implements IPdfiumExecutor {\n private static READY_TASK_ID = '0';\n private pendingRequests = new Map<string, Task<any, any>>();\n private requestCounter = 0;\n private logger: Logger;\n private readyTask: Task<boolean, PdfErrorReason>;\n\n constructor(\n private worker: Worker,\n options: RemoteExecutorOptions,\n ) {\n this.logger = options.logger ?? new NoopLogger();\n this.worker.addEventListener('message', this.handleMessage);\n\n // Create ready task - will be resolved when worker sends 'ready'\n this.readyTask = new Task<boolean, PdfErrorReason>();\n this.pendingRequests.set(RemoteExecutor.READY_TASK_ID, this.readyTask);\n\n // Send initialization message with WASM URL\n this.worker.postMessage({\n id: RemoteExecutor.READY_TASK_ID,\n type: 'wasmInit',\n wasmUrl: options.wasmUrl,\n logger: options.logger ? serializeLogger(options.logger) : undefined,\n });\n\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'RemoteExecutor created');\n }\n\n /**\n * Generate unique request ID\n */\n private generateId(): string {\n return `req-${Date.now()}-${this.requestCounter++}`;\n }\n\n /**\n * Send a message to the worker and return a Task\n * Waits for worker to be ready before sending\n */\n private send<T, P = unknown>(method: MessageType, args: any[]): Task<T, PdfErrorReason, P> {\n const id = this.generateId();\n const task = new Task<T, PdfErrorReason, P>();\n\n const request: WorkerRequest = {\n id,\n type: 'execute',\n method,\n args,\n };\n\n // Wait for worker to be ready before sending\n this.readyTask.wait(\n () => {\n this.pendingRequests.set(id, task);\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Sending ${method} request:`, id);\n this.worker.postMessage(request);\n },\n (error) => {\n this.logger.error(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Worker init failed, rejecting ${method}:`,\n error,\n );\n task.reject({\n code: PdfErrorCode.Initialization,\n message: 'Worker initialization failed',\n });\n },\n );\n\n return task;\n }\n\n /**\n * Handle messages from worker\n */\n private handleMessage = (event: MessageEvent<WorkerResponse>) => {\n const response = event.data;\n\n // Handle ready response - resolve the readyTask\n if (response.type === 'ready') {\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'Worker is ready');\n this.readyTask.resolve(true);\n return;\n }\n\n const task = this.pendingRequests.get(response.id);\n\n if (!task) {\n this.logger.warn(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Received response for unknown request: ${response.id}`,\n );\n return;\n }\n\n switch (response.type) {\n case 'result':\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Received result for ${response.id}`);\n task.resolve(response.data);\n this.pendingRequests.delete(response.id);\n break;\n\n case 'error':\n this.logger.debug(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Received error for ${response.id}:`,\n response.error,\n );\n if (response.error) {\n task.fail(response.error);\n } else {\n task.reject({ code: PdfErrorCode.Unknown, message: 'Unknown error' });\n }\n this.pendingRequests.delete(response.id);\n break;\n\n case 'progress':\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Received progress for ${response.id}`);\n task.progress(response.progress);\n break;\n }\n };\n\n /**\n * Cleanup and terminate worker\n */\n destroy(): void {\n this.worker.removeEventListener('message', this.handleMessage);\n\n // Reject all pending requests (except readyTask)\n this.pendingRequests.forEach((task, id) => {\n if (id !== RemoteExecutor.READY_TASK_ID) {\n task.abort('Worker destroyed');\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Aborted pending request: ${id}`);\n }\n });\n this.pendingRequests.clear();\n\n this.worker.terminate();\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'RemoteExecutor destroyed');\n }\n\n // ========== IPdfExecutor Implementation ==========\n\n openDocumentBuffer(\n file: PdfFile,\n options?: PdfOpenDocumentBufferOptions,\n ): PdfTask<PdfDocumentObject> {\n return this.send<PdfDocumentObject>('openDocumentBuffer', [file, options]);\n }\n\n getMetadata(doc: PdfDocumentObject): PdfTask<PdfMetadataObject> {\n return this.send<PdfMetadataObject>('getMetadata', [doc]);\n }\n\n setMetadata(doc: PdfDocumentObject, metadata: Partial<PdfMetadataObject>): PdfTask<boolean> {\n return this.send<boolean>('setMetadata', [doc, metadata]);\n }\n\n getDocPermissions(doc: PdfDocumentObject): PdfTask<number> {\n return this.send<number>('getDocPermissions', [doc]);\n }\n\n getDocUserPermissions(doc: PdfDocumentObject): PdfTask<number> {\n return this.send<number>('getDocUserPermissions', [doc]);\n }\n\n getSignatures(doc: PdfDocumentObject): PdfTask<PdfSignatureObject[]> {\n return this.send<PdfSignatureObject[]>('getSignatures', [doc]);\n }\n\n getBookmarks(doc: PdfDocumentObject): PdfTask<PdfBookmarksObject> {\n return this.send<PdfBookmarksObject>('getBookmarks', [doc]);\n }\n\n setBookmarks(doc: PdfDocumentObject, bookmarks: PdfBookmarkObject[]): PdfTask<boolean> {\n return this.send<boolean>('setBookmarks', [doc, bookmarks]);\n }\n\n deleteBookmarks(doc: PdfDocumentObject): PdfTask<boolean> {\n return this.send<boolean>('deleteBookmarks', [doc]);\n }\n\n renderPageRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n options?: PdfRenderPageOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderPageRaw', [doc, page, options]);\n }\n\n renderPageRect(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n rect: Rect,\n options?: PdfRenderPageOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderPageRect', [doc, page, rect, options]);\n }\n\n renderThumbnailRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n options?: PdfRenderThumbnailOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderThumbnailRaw', [doc, page, options]);\n }\n\n renderPageAnnotationRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n options?: PdfRenderPageAnnotationOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderPageAnnotationRaw', [doc, page, annotation, options]);\n }\n\n getPageAnnotationsRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n ): PdfTask<PdfAnnotationObject[]> {\n return this.send<PdfAnnotationObject[]>('getPageAnnotationsRaw', [doc, page]);\n }\n\n getPageAnnotations(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfAnnotationObject[]> {\n return this.send<PdfAnnotationObject[]>('getPageAnnotations', [doc, page]);\n }\n\n createPageAnnotation<A extends PdfAnnotationObject>(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: A,\n context?: AnnotationCreateContext<A>,\n ): PdfTask<string> {\n return this.send<string>('createPageAnnotation', [doc, page, annotation, context]);\n }\n\n updatePageAnnotation(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n ): PdfTask<boolean> {\n return this.send<boolean>('updatePageAnnotation', [doc, page, annotation]);\n }\n\n removePageAnnotation(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n ): PdfTask<boolean> {\n return this.send<boolean>('removePageAnnotation', [doc, page, annotation]);\n }\n\n getPageTextRects(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfTextRectObject[]> {\n return this.send<PdfTextRectObject[]>('getPageTextRects', [doc, page]);\n }\n\n searchInPage(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n keyword: string,\n flags: number,\n ): PdfTask<SearchResult[]> {\n return this.send<SearchResult[]>('searchInPage', [doc, page, keyword, flags]);\n }\n\n getAnnotationsBatch(\n doc: PdfDocumentObject,\n pages: PdfPageObject[],\n ): PdfTask<Record<number, PdfAnnotationObject[]>, BatchProgress<PdfAnnotationObject[]>> {\n return this.send<Record<number, PdfAnnotationObject[]>, BatchProgress<PdfAnnotationObject[]>>(\n 'getAnnotationsBatch',\n [doc, pages],\n );\n }\n\n searchBatch(\n doc: PdfDocumentObject,\n pages: PdfPageObject[],\n keyword: string,\n flags: number,\n ): PdfTask<Record<number, SearchResult[]>, BatchProgress<SearchResult[]>> {\n return this.send<Record<number, SearchResult[]>, BatchProgress<SearchResult[]>>('searchBatch', [\n doc,\n pages,\n keyword,\n flags,\n ]);\n }\n\n getAttachments(doc: PdfDocumentObject): PdfTask<PdfAttachmentObject[]> {\n return this.send<PdfAttachmentObject[]>('getAttachments', [doc]);\n }\n\n addAttachment(doc: PdfDocumentObject, params: PdfAddAttachmentParams): PdfTask<boolean> {\n return this.send<boolean>('addAttachment', [doc, params]);\n }\n\n removeAttachment(doc: PdfDocumentObject, attachment: PdfAttachmentObject): PdfTask<boolean> {\n return this.send<boolean>('removeAttachment', [doc, attachment]);\n }\n\n readAttachmentContent(\n doc: PdfDocumentObject,\n attachment: PdfAttachmentObject,\n ): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('readAttachmentContent', [doc, attachment]);\n }\n\n setFormFieldValue(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfWidgetAnnoObject,\n value: FormFieldValue,\n ): PdfTask<boolean> {\n return this.send<boolean>('setFormFieldValue', [doc, page, annotation, value]);\n }\n\n flattenPage(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n options?: PdfFlattenPageOptions,\n ): PdfTask<PdfPageFlattenResult> {\n return this.send<PdfPageFlattenResult>('flattenPage', [doc, page, options]);\n }\n\n extractPages(doc: PdfDocumentObject, pageIndexes: number[]): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('extractPages', [doc, pageIndexes]);\n }\n\n extractText(doc: PdfDocumentObject, pageIndexes: number[]): PdfTask<string> {\n return this.send<string>('extractText', [doc, pageIndexes]);\n }\n\n redactTextInRects(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n rects: Rect[],\n options?: PdfRedactTextOptions,\n ): PdfTask<boolean> {\n return this.send<boolean>('redactTextInRects', [doc, page, rects, options]);\n }\n\n getTextSlices(doc: PdfDocumentObject, slices: PageTextSlice[]): PdfTask<string[]> {\n return this.send<string[]>('getTextSlices', [doc, slices]);\n }\n\n getPageGlyphs(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfGlyphObject[]> {\n return this.send<PdfGlyphObject[]>('getPageGlyphs', [doc, page]);\n }\n\n getPageGeometry(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfPageGeometry> {\n return this.send<PdfPageGeometry>('getPageGeometry', [doc, page]);\n }\n\n merge(files: PdfFile[]): PdfTask<PdfFile> {\n return this.send<PdfFile>('merge', [files]);\n }\n\n mergePages(mergeConfigs: Array<{ docId: string; pageIndices: number[] }>): PdfTask<PdfFile> {\n return this.send<PdfFile>('mergePages', [mergeConfigs]);\n }\n\n preparePrintDocument(doc: PdfDocumentObject, options?: PdfPrintOptions): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('preparePrintDocument', [doc, options]);\n }\n\n saveAsCopy(doc: PdfDocumentObject): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('saveAsCopy', [doc]);\n }\n\n closeDocument(doc: PdfDocumentObject): PdfTask<boolean> {\n return this.send<boolean>('closeDocument', [doc]);\n }\n\n closeAllDocuments(): PdfTask<boolean> {\n return this.send<boolean>('closeAllDocuments', []);\n }\n}\n","import { Logger, NoopLogger } from '@embedpdf/models';\nimport type { EncodeImageRequest, EncodeImageResponse } from './image-encoder-worker';\n\nconst LOG_SOURCE = 'ImageEncoderPool';\nconst LOG_CATEGORY = 'Encoder';\n\ninterface EncodingTask {\n resolve: (blob: Blob) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Pool of image encoding workers to offload OffscreenCanvas operations\n * from the main PDFium worker thread\n */\nexport class ImageEncoderWorkerPool {\n private workers: Worker[] = [];\n private pendingTasks = new Map<string, EncodingTask>();\n private nextWorkerId = 0;\n private requestCounter = 0;\n private logger: Logger;\n\n /**\n * Create a pool of image encoding workers\n * @param poolSize - Number of workers to create (default: 2)\n * @param workerUrl - URL to the worker script\n * @param logger - Logger instance\n */\n constructor(\n private poolSize: number = 2,\n private workerUrl: string,\n logger?: Logger,\n ) {\n this.logger = logger ?? new NoopLogger();\n this.initialize();\n }\n\n /**\n * Initialize the worker pool\n */\n private initialize() {\n this.logger.debug(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Creating worker pool with ${this.poolSize} workers`,\n );\n\n for (let i = 0; i < this.poolSize; i++) {\n try {\n const worker = new Worker(this.workerUrl, { type: 'module' });\n worker.onmessage = this.handleWorkerMessage.bind(this);\n worker.onerror = this.handleWorkerError.bind(this);\n this.workers.push(worker);\n\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Worker ${i} created successfully`);\n } catch (error) {\n this.logger.error(LOG_SOURCE, LOG_CATEGORY, `Failed to create worker ${i}:`, error);\n }\n }\n }\n\n /**\n * Handle messages from workers\n */\n private handleWorkerMessage(event: MessageEvent<EncodeImageResponse>) {\n const response = event.data;\n const task = this.pendingTasks.get(response.id);\n\n if (!task) {\n this.logger.warn(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Received response for unknown task: ${response.id}`,\n );\n return;\n }\n\n this.pendingTasks.delete(response.id);\n\n if (response.type === 'result') {\n task.resolve(response.data as Blob);\n } else {\n const errorData = response.data as { message: string };\n task.reject(new Error(errorData.message));\n }\n }\n\n /**\n * Handle worker errors\n */\n private handleWorkerError(error: ErrorEvent) {\n this.logger.error(LOG_SOURCE, LOG_CATEGORY, 'Worker error:', error.message);\n }\n\n /**\n * Get the next available worker using round-robin\n */\n private getNextWorker(): Worker | null {\n if (this.workers.length === 0) {\n return null;\n }\n\n const worker = this.workers[this.nextWorkerId];\n this.nextWorkerId = (this.nextWorkerId + 1) % this.workers.length;\n return worker;\n }\n\n /**\n * Encode ImageData to Blob using a worker from the pool\n * @param imageData - Raw image data\n * @param imageType - Target image format\n * @param quality - Image quality (0-1) for lossy formats\n * @returns Promise that resolves to encoded Blob\n */\n encode(\n imageData: { data: Uint8ClampedArray; width: number; height: number },\n imageType: 'image/png' | 'image/jpeg' | 'image/webp' = 'image/webp',\n quality?: number,\n ): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const worker = this.getNextWorker();\n\n if (!worker) {\n reject(new Error('No workers available in the pool'));\n return;\n }\n\n const requestId = `encode-${Date.now()}-${this.requestCounter++}`;\n this.pendingTasks.set(requestId, { resolve, reject });\n\n const request: EncodeImageRequest = {\n id: requestId,\n type: 'encode',\n data: {\n imageData: {\n data: imageData.data,\n width: imageData.width,\n height: imageData.height,\n },\n imageType,\n quality,\n },\n };\n\n this.logger.debug(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Sending encoding request ${requestId} (${imageData.width}x${imageData.height})`,\n );\n\n // Transfer the buffer for better performance\n worker.postMessage(request, [imageData.data.buffer]);\n });\n }\n\n /**\n * Destroy all workers in the pool\n */\n destroy() {\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'Destroying worker pool');\n\n // Reject all pending tasks\n this.pendingTasks.forEach((task, id) => {\n task.reject(new Error('Worker pool destroyed'));\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Rejected pending task: ${id}`);\n });\n this.pendingTasks.clear();\n\n // Terminate all workers\n this.workers.forEach((worker, index) => {\n worker.terminate();\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Worker ${index} terminated`);\n });\n this.workers = [];\n }\n\n /**\n * Get the number of active workers in the pool\n */\n get activeWorkers(): number {\n return this.workers.length;\n }\n\n /**\n * Get the number of pending encoding tasks\n */\n get pendingTasksCount(): number {\n return this.pendingTasks.size;\n }\n}\n"],"names":["LOG_SOURCE","LOG_CATEGORY","_RemoteExecutor","constructor","worker","options","this","pendingRequests","Map","requestCounter","handleMessage","event","response","data","type","logger","debug","readyTask","resolve","task","get","id","delete","error","fail","reject","code","PdfErrorCode","Unknown","message","progress","warn","NoopLogger","addEventListener","Task","set","READY_TASK_ID","postMessage","wasmUrl","serializeLogger","generateId","Date","now","send","method","args","request","wait","Initialization","destroy","removeEventListener","forEach","abort","clear","terminate","openDocumentBuffer","file","getMetadata","doc","setMetadata","metadata","getDocPermissions","getDocUserPermissions","getSignatures","getBookmarks","setBookmarks","bookmarks","deleteBookmarks","renderPageRaw","page","renderPageRect","rect","renderThumbnailRaw","renderPageAnnotationRaw","annotation","getPageAnnotationsRaw","getPageAnnotations","createPageAnnotation","context","updatePageAnnotation","removePageAnnotation","getPageTextRects","searchInPage","keyword","flags","getAnnotationsBatch","pages","searchBatch","getAttachments","addAttachment","params","removeAttachment","attachment","readAttachmentContent","setFormFieldValue","value","flattenPage","extractPages","pageIndexes","extractText","redactTextInRects","rects","getTextSlices","slices","getPageGlyphs","getPageGeometry","merge","files","mergePages","mergeConfigs","preparePrintDocument","saveAsCopy","closeDocument","closeAllDocuments","RemoteExecutor","ImageEncoderWorkerPool","poolSize","workerUrl","workers","pendingTasks","nextWorkerId","initialize","i","Worker","onmessage","handleWorkerMessage","bind","onerror","handleWorkerError","push","errorData","Error","getNextWorker","length","encode","imageData","imageType","quality","Promise","requestId","width","height","buffer","index","activeWorkers","pendingTasksCount","size"],"mappings":"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"}
1
+ {"version":3,"file":"worker-engine.cjs","sources":["../../../../src/lib/orchestrator/remote-executor.ts","../../../../src/lib/image-encoder/worker-pool.ts"],"sourcesContent":["import {\n BatchProgress,\n Logger,\n NoopLogger,\n PdfDocumentObject,\n PdfPageObject,\n PdfTask,\n PdfErrorReason,\n PdfFile,\n PdfOpenDocumentBufferOptions,\n PdfMetadataObject,\n PdfBookmarksObject,\n PdfBookmarkObject,\n PdfRenderPageOptions,\n PdfRenderThumbnailOptions,\n PdfRenderPageAnnotationOptions,\n PdfAnnotationObject,\n PdfTextRectObject,\n PdfAttachmentObject,\n PdfAddAttachmentParams,\n PdfWidgetAnnoObject,\n FormFieldValue,\n PdfFlattenPageOptions,\n PdfPageFlattenResult,\n PdfRedactTextOptions,\n Rect,\n PageTextSlice,\n PdfGlyphObject,\n PdfPageGeometry,\n PdfPrintOptions,\n PdfSignatureObject,\n AnnotationCreateContext,\n Task,\n TaskError,\n PdfErrorCode,\n SearchResult,\n serializeLogger,\n IPdfiumExecutor,\n ImageDataLike,\n} from '@embedpdf/models';\nimport type { WorkerRequest, WorkerResponse } from './pdfium-native-runner';\nimport type { FontFallbackConfig } from '../pdfium/font-fallback';\n\n/**\n * Options for creating a RemoteExecutor\n */\nexport interface RemoteExecutorOptions {\n /**\n * URL to the pdfium.wasm file (required)\n */\n wasmUrl: string;\n /**\n * Logger instance for debugging\n */\n logger?: Logger;\n /**\n * Font fallback configuration for handling missing fonts\n */\n fontFallback?: FontFallbackConfig;\n}\n\nconst LOG_SOURCE = 'RemoteExecutor';\nconst LOG_CATEGORY = 'Worker';\n\n/**\n * Message types for worker communication\n */\ntype MessageType =\n | 'destroy'\n | 'openDocumentBuffer'\n | 'getMetadata'\n | 'setMetadata'\n | 'getDocPermissions'\n | 'getDocUserPermissions'\n | 'getSignatures'\n | 'getBookmarks'\n | 'setBookmarks'\n | 'deleteBookmarks'\n | 'renderPageRaw'\n | 'renderPageRect'\n | 'renderThumbnailRaw'\n | 'renderPageAnnotationRaw'\n | 'getPageAnnotations'\n | 'getPageAnnotationsRaw'\n | 'createPageAnnotation'\n | 'updatePageAnnotation'\n | 'removePageAnnotation'\n | 'getPageTextRects'\n | 'searchInPage'\n | 'getAnnotationsBatch'\n | 'searchBatch'\n | 'getAttachments'\n | 'addAttachment'\n | 'removeAttachment'\n | 'readAttachmentContent'\n | 'setFormFieldValue'\n | 'flattenPage'\n | 'extractPages'\n | 'extractText'\n | 'redactTextInRects'\n | 'getTextSlices'\n | 'getPageGlyphs'\n | 'getPageGeometry'\n | 'merge'\n | 'mergePages'\n | 'preparePrintDocument'\n | 'saveAsCopy'\n | 'closeDocument'\n | 'closeAllDocuments';\n\n/**\n * RemoteExecutor - Proxy for worker communication\n *\n * This implements IPdfExecutor but forwards all calls to a Web Worker.\n * It handles:\n * - Serialization/deserialization of messages\n * - Promise/Task conversion\n * - Error handling\n * - Progress tracking\n */\nexport class RemoteExecutor implements IPdfiumExecutor {\n private static READY_TASK_ID = '0';\n private pendingRequests = new Map<string, Task<any, any>>();\n private requestCounter = 0;\n private logger: Logger;\n private readyTask: Task<boolean, PdfErrorReason>;\n\n constructor(\n private worker: Worker,\n options: RemoteExecutorOptions,\n ) {\n this.logger = options.logger ?? new NoopLogger();\n this.worker.addEventListener('message', this.handleMessage);\n\n // Create ready task - will be resolved when worker sends 'ready'\n this.readyTask = new Task<boolean, PdfErrorReason>();\n this.pendingRequests.set(RemoteExecutor.READY_TASK_ID, this.readyTask);\n\n // Send initialization message with WASM URL and font fallback config\n this.worker.postMessage({\n id: RemoteExecutor.READY_TASK_ID,\n type: 'wasmInit',\n wasmUrl: options.wasmUrl,\n logger: options.logger ? serializeLogger(options.logger) : undefined,\n fontFallback: options.fontFallback,\n });\n\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'RemoteExecutor created');\n }\n\n /**\n * Generate unique request ID\n */\n private generateId(): string {\n return `req-${Date.now()}-${this.requestCounter++}`;\n }\n\n /**\n * Send a message to the worker and return a Task\n * Waits for worker to be ready before sending\n */\n private send<T, P = unknown>(method: MessageType, args: any[]): Task<T, PdfErrorReason, P> {\n const id = this.generateId();\n const task = new Task<T, PdfErrorReason, P>();\n\n const request: WorkerRequest = {\n id,\n type: 'execute',\n method,\n args,\n };\n\n // Wait for worker to be ready before sending\n this.readyTask.wait(\n () => {\n this.pendingRequests.set(id, task);\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Sending ${method} request:`, id);\n this.worker.postMessage(request);\n },\n (error) => {\n this.logger.error(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Worker init failed, rejecting ${method}:`,\n error,\n );\n task.reject({\n code: PdfErrorCode.Initialization,\n message: 'Worker initialization failed',\n });\n },\n );\n\n return task;\n }\n\n /**\n * Handle messages from worker\n */\n private handleMessage = (event: MessageEvent<WorkerResponse>) => {\n const response = event.data;\n\n // Handle ready response - resolve the readyTask\n if (response.type === 'ready') {\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'Worker is ready');\n this.readyTask.resolve(true);\n return;\n }\n\n const task = this.pendingRequests.get(response.id);\n\n if (!task) {\n this.logger.warn(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Received response for unknown request: ${response.id}`,\n );\n return;\n }\n\n switch (response.type) {\n case 'result':\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Received result for ${response.id}`);\n task.resolve(response.data);\n this.pendingRequests.delete(response.id);\n break;\n\n case 'error':\n this.logger.debug(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Received error for ${response.id}:`,\n response.error,\n );\n if (response.error) {\n task.fail(response.error);\n } else {\n task.reject({ code: PdfErrorCode.Unknown, message: 'Unknown error' });\n }\n this.pendingRequests.delete(response.id);\n break;\n\n case 'progress':\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Received progress for ${response.id}`);\n task.progress(response.progress);\n break;\n }\n };\n\n /**\n * Cleanup and terminate worker\n */\n destroy(): void {\n this.worker.removeEventListener('message', this.handleMessage);\n\n // Reject all pending requests (except readyTask)\n this.pendingRequests.forEach((task, id) => {\n if (id !== RemoteExecutor.READY_TASK_ID) {\n task.abort('Worker destroyed');\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Aborted pending request: ${id}`);\n }\n });\n this.pendingRequests.clear();\n\n this.worker.terminate();\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'RemoteExecutor destroyed');\n }\n\n // ========== IPdfExecutor Implementation ==========\n\n openDocumentBuffer(\n file: PdfFile,\n options?: PdfOpenDocumentBufferOptions,\n ): PdfTask<PdfDocumentObject> {\n return this.send<PdfDocumentObject>('openDocumentBuffer', [file, options]);\n }\n\n getMetadata(doc: PdfDocumentObject): PdfTask<PdfMetadataObject> {\n return this.send<PdfMetadataObject>('getMetadata', [doc]);\n }\n\n setMetadata(doc: PdfDocumentObject, metadata: Partial<PdfMetadataObject>): PdfTask<boolean> {\n return this.send<boolean>('setMetadata', [doc, metadata]);\n }\n\n getDocPermissions(doc: PdfDocumentObject): PdfTask<number> {\n return this.send<number>('getDocPermissions', [doc]);\n }\n\n getDocUserPermissions(doc: PdfDocumentObject): PdfTask<number> {\n return this.send<number>('getDocUserPermissions', [doc]);\n }\n\n getSignatures(doc: PdfDocumentObject): PdfTask<PdfSignatureObject[]> {\n return this.send<PdfSignatureObject[]>('getSignatures', [doc]);\n }\n\n getBookmarks(doc: PdfDocumentObject): PdfTask<PdfBookmarksObject> {\n return this.send<PdfBookmarksObject>('getBookmarks', [doc]);\n }\n\n setBookmarks(doc: PdfDocumentObject, bookmarks: PdfBookmarkObject[]): PdfTask<boolean> {\n return this.send<boolean>('setBookmarks', [doc, bookmarks]);\n }\n\n deleteBookmarks(doc: PdfDocumentObject): PdfTask<boolean> {\n return this.send<boolean>('deleteBookmarks', [doc]);\n }\n\n renderPageRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n options?: PdfRenderPageOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderPageRaw', [doc, page, options]);\n }\n\n renderPageRect(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n rect: Rect,\n options?: PdfRenderPageOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderPageRect', [doc, page, rect, options]);\n }\n\n renderThumbnailRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n options?: PdfRenderThumbnailOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderThumbnailRaw', [doc, page, options]);\n }\n\n renderPageAnnotationRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n options?: PdfRenderPageAnnotationOptions,\n ): PdfTask<ImageDataLike> {\n return this.send<ImageDataLike>('renderPageAnnotationRaw', [doc, page, annotation, options]);\n }\n\n getPageAnnotationsRaw(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n ): PdfTask<PdfAnnotationObject[]> {\n return this.send<PdfAnnotationObject[]>('getPageAnnotationsRaw', [doc, page]);\n }\n\n getPageAnnotations(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfAnnotationObject[]> {\n return this.send<PdfAnnotationObject[]>('getPageAnnotations', [doc, page]);\n }\n\n createPageAnnotation<A extends PdfAnnotationObject>(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: A,\n context?: AnnotationCreateContext<A>,\n ): PdfTask<string> {\n return this.send<string>('createPageAnnotation', [doc, page, annotation, context]);\n }\n\n updatePageAnnotation(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n ): PdfTask<boolean> {\n return this.send<boolean>('updatePageAnnotation', [doc, page, annotation]);\n }\n\n removePageAnnotation(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n ): PdfTask<boolean> {\n return this.send<boolean>('removePageAnnotation', [doc, page, annotation]);\n }\n\n getPageTextRects(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfTextRectObject[]> {\n return this.send<PdfTextRectObject[]>('getPageTextRects', [doc, page]);\n }\n\n searchInPage(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n keyword: string,\n flags: number,\n ): PdfTask<SearchResult[]> {\n return this.send<SearchResult[]>('searchInPage', [doc, page, keyword, flags]);\n }\n\n getAnnotationsBatch(\n doc: PdfDocumentObject,\n pages: PdfPageObject[],\n ): PdfTask<Record<number, PdfAnnotationObject[]>, BatchProgress<PdfAnnotationObject[]>> {\n return this.send<Record<number, PdfAnnotationObject[]>, BatchProgress<PdfAnnotationObject[]>>(\n 'getAnnotationsBatch',\n [doc, pages],\n );\n }\n\n searchBatch(\n doc: PdfDocumentObject,\n pages: PdfPageObject[],\n keyword: string,\n flags: number,\n ): PdfTask<Record<number, SearchResult[]>, BatchProgress<SearchResult[]>> {\n return this.send<Record<number, SearchResult[]>, BatchProgress<SearchResult[]>>('searchBatch', [\n doc,\n pages,\n keyword,\n flags,\n ]);\n }\n\n getAttachments(doc: PdfDocumentObject): PdfTask<PdfAttachmentObject[]> {\n return this.send<PdfAttachmentObject[]>('getAttachments', [doc]);\n }\n\n addAttachment(doc: PdfDocumentObject, params: PdfAddAttachmentParams): PdfTask<boolean> {\n return this.send<boolean>('addAttachment', [doc, params]);\n }\n\n removeAttachment(doc: PdfDocumentObject, attachment: PdfAttachmentObject): PdfTask<boolean> {\n return this.send<boolean>('removeAttachment', [doc, attachment]);\n }\n\n readAttachmentContent(\n doc: PdfDocumentObject,\n attachment: PdfAttachmentObject,\n ): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('readAttachmentContent', [doc, attachment]);\n }\n\n setFormFieldValue(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfWidgetAnnoObject,\n value: FormFieldValue,\n ): PdfTask<boolean> {\n return this.send<boolean>('setFormFieldValue', [doc, page, annotation, value]);\n }\n\n flattenPage(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n options?: PdfFlattenPageOptions,\n ): PdfTask<PdfPageFlattenResult> {\n return this.send<PdfPageFlattenResult>('flattenPage', [doc, page, options]);\n }\n\n extractPages(doc: PdfDocumentObject, pageIndexes: number[]): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('extractPages', [doc, pageIndexes]);\n }\n\n extractText(doc: PdfDocumentObject, pageIndexes: number[]): PdfTask<string> {\n return this.send<string>('extractText', [doc, pageIndexes]);\n }\n\n redactTextInRects(\n doc: PdfDocumentObject,\n page: PdfPageObject,\n rects: Rect[],\n options?: PdfRedactTextOptions,\n ): PdfTask<boolean> {\n return this.send<boolean>('redactTextInRects', [doc, page, rects, options]);\n }\n\n getTextSlices(doc: PdfDocumentObject, slices: PageTextSlice[]): PdfTask<string[]> {\n return this.send<string[]>('getTextSlices', [doc, slices]);\n }\n\n getPageGlyphs(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfGlyphObject[]> {\n return this.send<PdfGlyphObject[]>('getPageGlyphs', [doc, page]);\n }\n\n getPageGeometry(doc: PdfDocumentObject, page: PdfPageObject): PdfTask<PdfPageGeometry> {\n return this.send<PdfPageGeometry>('getPageGeometry', [doc, page]);\n }\n\n merge(files: PdfFile[]): PdfTask<PdfFile> {\n return this.send<PdfFile>('merge', [files]);\n }\n\n mergePages(mergeConfigs: Array<{ docId: string; pageIndices: number[] }>): PdfTask<PdfFile> {\n return this.send<PdfFile>('mergePages', [mergeConfigs]);\n }\n\n preparePrintDocument(doc: PdfDocumentObject, options?: PdfPrintOptions): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('preparePrintDocument', [doc, options]);\n }\n\n saveAsCopy(doc: PdfDocumentObject): PdfTask<ArrayBuffer> {\n return this.send<ArrayBuffer>('saveAsCopy', [doc]);\n }\n\n closeDocument(doc: PdfDocumentObject): PdfTask<boolean> {\n return this.send<boolean>('closeDocument', [doc]);\n }\n\n closeAllDocuments(): PdfTask<boolean> {\n return this.send<boolean>('closeAllDocuments', []);\n }\n}\n","import { Logger, NoopLogger } from '@embedpdf/models';\nimport type { EncodeImageRequest, EncodeImageResponse } from './image-encoder-worker';\n\nconst LOG_SOURCE = 'ImageEncoderPool';\nconst LOG_CATEGORY = 'Encoder';\n\ninterface EncodingTask {\n resolve: (blob: Blob) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Pool of image encoding workers to offload OffscreenCanvas operations\n * from the main PDFium worker thread\n */\nexport class ImageEncoderWorkerPool {\n private workers: Worker[] = [];\n private pendingTasks = new Map<string, EncodingTask>();\n private nextWorkerId = 0;\n private requestCounter = 0;\n private logger: Logger;\n\n /**\n * Create a pool of image encoding workers\n * @param poolSize - Number of workers to create (default: 2)\n * @param workerUrl - URL to the worker script\n * @param logger - Logger instance\n */\n constructor(\n private poolSize: number = 2,\n private workerUrl: string,\n logger?: Logger,\n ) {\n this.logger = logger ?? new NoopLogger();\n this.initialize();\n }\n\n /**\n * Initialize the worker pool\n */\n private initialize() {\n this.logger.debug(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Creating worker pool with ${this.poolSize} workers`,\n );\n\n for (let i = 0; i < this.poolSize; i++) {\n try {\n const worker = new Worker(this.workerUrl, { type: 'module' });\n worker.onmessage = this.handleWorkerMessage.bind(this);\n worker.onerror = this.handleWorkerError.bind(this);\n this.workers.push(worker);\n\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Worker ${i} created successfully`);\n } catch (error) {\n this.logger.error(LOG_SOURCE, LOG_CATEGORY, `Failed to create worker ${i}:`, error);\n }\n }\n }\n\n /**\n * Handle messages from workers\n */\n private handleWorkerMessage(event: MessageEvent<EncodeImageResponse>) {\n const response = event.data;\n const task = this.pendingTasks.get(response.id);\n\n if (!task) {\n this.logger.warn(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Received response for unknown task: ${response.id}`,\n );\n return;\n }\n\n this.pendingTasks.delete(response.id);\n\n if (response.type === 'result') {\n task.resolve(response.data as Blob);\n } else {\n const errorData = response.data as { message: string };\n task.reject(new Error(errorData.message));\n }\n }\n\n /**\n * Handle worker errors\n */\n private handleWorkerError(error: ErrorEvent) {\n this.logger.error(LOG_SOURCE, LOG_CATEGORY, 'Worker error:', error.message);\n }\n\n /**\n * Get the next available worker using round-robin\n */\n private getNextWorker(): Worker | null {\n if (this.workers.length === 0) {\n return null;\n }\n\n const worker = this.workers[this.nextWorkerId];\n this.nextWorkerId = (this.nextWorkerId + 1) % this.workers.length;\n return worker;\n }\n\n /**\n * Encode ImageData to Blob using a worker from the pool\n * @param imageData - Raw image data\n * @param imageType - Target image format\n * @param quality - Image quality (0-1) for lossy formats\n * @returns Promise that resolves to encoded Blob\n */\n encode(\n imageData: { data: Uint8ClampedArray; width: number; height: number },\n imageType: 'image/png' | 'image/jpeg' | 'image/webp' = 'image/webp',\n quality?: number,\n ): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const worker = this.getNextWorker();\n\n if (!worker) {\n reject(new Error('No workers available in the pool'));\n return;\n }\n\n const requestId = `encode-${Date.now()}-${this.requestCounter++}`;\n this.pendingTasks.set(requestId, { resolve, reject });\n\n const request: EncodeImageRequest = {\n id: requestId,\n type: 'encode',\n data: {\n imageData: {\n data: imageData.data,\n width: imageData.width,\n height: imageData.height,\n },\n imageType,\n quality,\n },\n };\n\n this.logger.debug(\n LOG_SOURCE,\n LOG_CATEGORY,\n `Sending encoding request ${requestId} (${imageData.width}x${imageData.height})`,\n );\n\n // Transfer the buffer for better performance\n worker.postMessage(request, [imageData.data.buffer]);\n });\n }\n\n /**\n * Destroy all workers in the pool\n */\n destroy() {\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, 'Destroying worker pool');\n\n // Reject all pending tasks\n this.pendingTasks.forEach((task, id) => {\n task.reject(new Error('Worker pool destroyed'));\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Rejected pending task: ${id}`);\n });\n this.pendingTasks.clear();\n\n // Terminate all workers\n this.workers.forEach((worker, index) => {\n worker.terminate();\n this.logger.debug(LOG_SOURCE, LOG_CATEGORY, `Worker ${index} terminated`);\n });\n this.workers = [];\n }\n\n /**\n * Get the number of active workers in the pool\n */\n get activeWorkers(): number {\n return this.workers.length;\n }\n\n /**\n * Get the number of pending encoding tasks\n */\n get pendingTasksCount(): number {\n return this.pendingTasks.size;\n }\n}\n"],"names":["LOG_SOURCE","LOG_CATEGORY","_RemoteExecutor","constructor","worker","options","this","pendingRequests","Map","requestCounter","handleMessage","event","response","data","type","logger","debug","readyTask","resolve","task","get","id","delete","error","fail","reject","code","PdfErrorCode","Unknown","message","progress","warn","NoopLogger","addEventListener","Task","set","READY_TASK_ID","postMessage","wasmUrl","serializeLogger","fontFallback","generateId","Date","now","send","method","args","request","wait","Initialization","destroy","removeEventListener","forEach","abort","clear","terminate","openDocumentBuffer","file","getMetadata","doc","setMetadata","metadata","getDocPermissions","getDocUserPermissions","getSignatures","getBookmarks","setBookmarks","bookmarks","deleteBookmarks","renderPageRaw","page","renderPageRect","rect","renderThumbnailRaw","renderPageAnnotationRaw","annotation","getPageAnnotationsRaw","getPageAnnotations","createPageAnnotation","context","updatePageAnnotation","removePageAnnotation","getPageTextRects","searchInPage","keyword","flags","getAnnotationsBatch","pages","searchBatch","getAttachments","addAttachment","params","removeAttachment","attachment","readAttachmentContent","setFormFieldValue","value","flattenPage","extractPages","pageIndexes","extractText","redactTextInRects","rects","getTextSlices","slices","getPageGlyphs","getPageGeometry","merge","files","mergePages","mergeConfigs","preparePrintDocument","saveAsCopy","closeDocument","closeAllDocuments","RemoteExecutor","ImageEncoderWorkerPool","poolSize","workerUrl","workers","pendingTasks","nextWorkerId","initialize","i","Worker","onmessage","handleWorkerMessage","bind","onerror","handleWorkerError","push","errorData","Error","getNextWorker","length","encode","imageData","imageType","quality","Promise","requestId","width","height","buffer","index","activeWorkers","pendingTasksCount","size"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import { Logger } from '@embedpdf/models';
2
2
  import { PdfEngine } from '../../orchestrator/pdf-engine';
3
+ import { FontFallbackConfig } from '../font-fallback';
4
+ export type { FontFallbackConfig };
3
5
  export interface CreatePdfiumEngineOptions {
4
6
  /**
5
7
  * Logger instance for debugging
@@ -10,6 +12,12 @@ export interface CreatePdfiumEngineOptions {
10
12
  * Set to 2-4 for optimal performance with parallel encoding
11
13
  */
12
14
  encoderPoolSize?: number;
15
+ /**
16
+ * Font fallback configuration for handling missing fonts in PDFs.
17
+ * When enabled, PDFium will request fallback fonts from configured URLs
18
+ * when it encounters text that requires fonts not embedded in the PDF.
19
+ */
20
+ fontFallback?: FontFallbackConfig;
13
21
  }
14
22
  /**
15
23
  * Create a PDFium engine running in a Web Worker