@squoosh-kit/webp 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40squoosh-kit%2Fwebp.svg)](https://badge.fury.io/js/%40squoosh-kit%2Fwebp)
4
4
 
5
- WebP encoder functionality from Google's Squoosh, packaged for modern JavaScript environments.
5
+ **Professional WebP encoding that doesn't get in your way**
6
6
 
7
- This package provides high-performance WebP encoding using WebAssembly, offloading the work to a Web Worker to avoid blocking the main thread.
7
+ Transform your images into the modern WebP format with the same technology that powers Google's Squoosh. Built on WebAssembly for incredible speed, this package handles the heavy lifting while keeping your application responsive through intelligent worker management.
8
+
9
+ Perfect for optimizing images in web applications, processing user uploads, or building image conversion services. Whether you're working with Bun, Node.js, or the browser, WebP encoding has never been this straightforward.
8
10
 
9
11
  ## Installation
10
12
 
@@ -16,55 +18,118 @@ npm install @squoosh-kit/webp
16
18
 
17
19
  ## Quick Start
18
20
 
21
+ Get started with minimal fuss:
22
+
19
23
  ```typescript
20
24
  import { encode, createWebpEncoder } from '@squoosh-kit/webp';
21
- import type { ImageInput, WebpOptions } from '@squoosh-kit/runtime';
25
+ import type { ImageInput } from '@squoosh-kit/webp';
22
26
 
23
- // Assume `imageData` is an object like { data: Uint8Array, width: number, height: number }
24
- const imageData: ImageInput = /* ... */;
27
+ // Your image data - from a file, canvas, or anywhere
28
+ const imageData: ImageInput = {
29
+ data: imageBuffer,
30
+ width: 1920,
31
+ height: 1080
32
+ };
25
33
 
26
- // Simple, one-off encoding
27
- const webpData = await encode(
34
+ // One-off encoding (worker spins up automatically)
35
+ const webpBuffer = await encode(
28
36
  new AbortController().signal,
29
- null,
30
37
  imageData,
31
- { quality: 75 }
38
+ { quality: 85 }
32
39
  );
33
40
 
34
- // For multiple operations, create a persistent encoder
35
- const encoder = createWebpEncoder('worker'); // 'client' also available
36
- const result = await encoder(
41
+ // For multiple images, create a persistent encoder
42
+ const encoder = createWebpEncoder('worker');
43
+ const optimized = await encoder(
37
44
  new AbortController().signal,
38
45
  imageData,
39
- { quality: 90 }
46
+ { quality: 90, lossless: false }
40
47
  );
41
48
  ```
42
49
 
43
- ## API
50
+ ## How It Works
44
51
 
45
- ### `encode(signal, workerBridge, imageData, options)`
52
+ Under the hood, this package leverages Google's Squoosh WebP encoder compiled to WebAssembly. The heavy processing happens in a Web Worker by default, so your main thread stays free for user interactions.
46
53
 
47
- - `signal`: `AbortSignal` to cancel the operation.
48
- - `workerBridge`: (Optional) A `WorkerBridge` instance.
49
- - `imageData`: `ImageInput` to encode.
50
- - `options`: `WebpOptions` for encoding.
51
- - **Returns**: `Promise<Uint8Array>`
54
+ You get the same quality and performance as the original Squoosh tool, but wrapped in a clean JavaScript API that fits naturally into modern applications.
52
55
 
53
- ### `createWebpEncoder(mode)`
56
+ ## Real-World Examples
54
57
 
55
- - `mode`: `'worker'` or `'client'`.
56
- - **Returns**: A reusable encoding function.
58
+ **Image Upload Processing**
59
+ ```typescript
60
+ // In your upload handler
61
+ const processedImage = await encode(
62
+ new AbortController().signal,
63
+ uploadedImage,
64
+ {
65
+ quality: 85,
66
+ lossless: false // Perfect for photos
67
+ }
68
+ );
57
69
 
58
- ### `WebpOptions`
70
+ await saveToStorage('optimized.webp', processedImage);
71
+ ```
59
72
 
73
+ **Batch Conversion Service**
60
74
  ```typescript
61
- interface WebpOptions {
62
- quality?: number; // 0-100, default: 82
63
- lossless?: boolean; // default: false
64
- nearLossless?: boolean; // default: false
75
+ const encoder = createWebpEncoder('client'); // Direct encoding, no worker
76
+
77
+ for (const imagePath of imageFiles) {
78
+ const imageData = await loadImage(imagePath);
79
+ const webpData = await encoder(
80
+ new AbortController().signal,
81
+ imageData,
82
+ { quality: 75 }
83
+ );
84
+
85
+ await writeFile(`${imagePath}.webp`, webpData);
65
86
  }
66
87
  ```
67
88
 
89
+ ## API Reference
90
+
91
+ ### `encode(signal, imageData, options?)`
92
+
93
+ The main encoding function. Handles everything automatically and returns a Promise.
94
+
95
+ - `signal` - `AbortSignal` to cancel long-running operations
96
+ - `imageData` - `ImageInput` object with your pixel data
97
+ - `options` - (optional) `WebpOptions` for quality and format settings
98
+ - **Returns** - `Promise<Uint8Array>` with your encoded WebP data
99
+
100
+ ### `createWebpEncoder(mode?)`
101
+
102
+ Creates a reusable encoder function. More efficient for processing multiple images.
103
+
104
+ - `mode` - (optional) `'worker'` or `'client'`, defaults to `'worker'`
105
+ - **Returns** - A function with the same signature as `encode()`
106
+
107
+ ### `WebpOptions`
108
+
109
+ Fine-tune your encoding:
110
+
111
+ ```typescript
112
+ type WebpOptions = {
113
+ quality?: number; // 0-100, controls file size vs quality (default: 82)
114
+ lossless?: boolean; // Lossless compression, larger files (default: false)
115
+ nearLossless?: boolean; // Near-lossless mode, best of both worlds (default: false)
116
+ };
117
+ ```
118
+
119
+ ## Performance Tips
120
+
121
+ - **Use workers for UI apps** - Keeps your interface responsive during encoding
122
+ - **Use client mode for servers** - Direct encoding without worker overhead
123
+ - **Batch with persistent encoders** - More efficient than one-off calls
124
+ - **Adjust quality strategically** - Often 80-90% quality looks identical to 100%
125
+
126
+ ## Works With
127
+
128
+ - **Bun** - First-class support, fastest performance
129
+ - **Node.js** - Works great in server environments
130
+ - **Browsers** - Full Web Worker support for responsive UIs
131
+ - **TypeScript** - Complete type definitions included
132
+
68
133
  ## License
69
134
 
70
- MIT
135
+ MIT - use it freely in your projects
package/dist/types.d.ts CHANGED
@@ -1,8 +1,23 @@
1
1
  /**
2
2
  * Type definitions for the WebP package
3
3
  */
4
- export interface WebpOptions {
4
+ /**
5
+ * Options for WebP encoding.
6
+ */
7
+ export type WebpOptions = {
8
+ /**
9
+ * Quality, 0-100.
10
+ * @default 82
11
+ */
5
12
  quality?: number;
13
+ /**
14
+ * Use lossless compression.
15
+ * @default false
16
+ */
6
17
  lossless?: boolean;
18
+ /**
19
+ * Use near-lossless compression.
20
+ * @default false
21
+ */
7
22
  nearLossless?: boolean;
8
- }
23
+ };
@@ -1,6 +1,6 @@
1
1
  // @bun
2
- var N=null;async function U(){if(N)return N;try{if(typeof self>"u")global.self=global;if(typeof self<"u"&&!self.location)self.location={href:import.meta.url};let x=import.meta.url.endsWith(".ts")?"../dist/wasm/webp":"./wasm/webp",G=await import(new URL(`${x}/webp_enc.js`,import.meta.url).href),J=new URL(`${x}/`,import.meta.url).href,H=await G.default({locateFile:(I)=>{if(I.endsWith(".wasm"))return new URL(I,J).href;return I}});return N=H,H}catch(j){throw Error(`Failed to load WebP module: ${j instanceof Error?j.message:String(j)}`)}}function V(j){let x=Math.max(0,Math.min(100,j?.quality??82)),z=j?.lossless??!1,G=j?.nearLossless??!1;return{quality:x,target_size:0,target_PSNR:0,method:4,sns_strength:50,filter_strength:60,filter_sharpness:0,filter_type:1,partitions:0,segments:4,pass:1,show_compressed:0,preprocessing:0,autofilter:0,partition_limit:0,alpha_compression:1,alpha_filtering:1,alpha_quality:100,lossless:z?1:0,exact:0,image_hint:0,emulate_jpeg_size:0,thread_level:0,low_memory:0,near_lossless:G?x:100,use_delta_palette:0,use_sharp_yuv:0}}async function X(j,x,z){if(j.aborted)throw new DOMException("Aborted","AbortError");let{width:G,height:J,data:H}=x;if(!(H instanceof Uint8Array)&&!(H instanceof Uint8ClampedArray))throw Error("Image data must be Uint8Array or Uint8ClampedArray");let I=await U();if(j.aborted)throw new DOMException("Aborted","AbortError");let K=V(z),R=H instanceof Uint8ClampedArray?new Uint8Array(H):H,S=new Uint8Array(R),Q=I.encode(S,G,J,K);if(j.aborted)throw new DOMException("Aborted","AbortError");if(!Q)throw Error("WebP encoding failed");return Q}console.log("\uD83D\uDD27 WebP worker: Message handler registered");if(typeof self<"u")self.onmessage=async(j)=>{console.log("\uD83D\uDD27 WebP worker: Received message",j.data);let x=j.data,z={id:x.id,ok:!1};try{if(x.type==="webp:encode"){let{image:G,options:J}=x.payload,H=new AbortController,I=await X(H.signal,G,J);z.ok=!0,z.data=I;let K=z.data.buffer;self.postMessage(z,[K])}else z.error=`Unknown message type: ${x.type}`,self.postMessage(z)}catch(G){z.error=G instanceof Error?G.message:String(G),self.postMessage(z)}};export{X as webpEncodeClient};
2
+ var N=null;async function U(){if(N)return N;try{if(typeof self>"u")global.self=global;if(typeof self<"u"&&!self.location)self.location={href:import.meta.url};let j="./wasm/webp",x=await import(new URL(`${j}/webp_enc.js`,import.meta.url).href),G=new URL(`${j}/`,import.meta.url).href,I=await x.default({locateFile:(H)=>{if(H.endsWith(".wasm"))return new URL(H,G).href;return H}});return N=I,I}catch(j){throw Error(`Failed to load WebP module: ${j instanceof Error?j.message:String(j)}`)}}function V(j){let z=Math.max(0,Math.min(100,j?.quality??82)),x=j?.lossless??!1,G=j?.nearLossless??!1;return{quality:z,target_size:0,target_PSNR:0,method:4,sns_strength:50,filter_strength:60,filter_sharpness:0,filter_type:1,partitions:0,segments:4,pass:1,show_compressed:0,preprocessing:0,autofilter:0,partition_limit:0,alpha_compression:1,alpha_filtering:1,alpha_quality:100,lossless:x?1:0,exact:0,image_hint:0,emulate_jpeg_size:0,thread_level:0,low_memory:0,near_lossless:G?z:100,use_delta_palette:0,use_sharp_yuv:0}}async function X(j,z,x){if(j.aborted)throw new DOMException("Aborted","AbortError");let{width:G,height:I,data:H}=z;if(!(H instanceof Uint8Array)&&!(H instanceof Uint8ClampedArray))throw Error("Image data must be Uint8Array or Uint8ClampedArray");let J=await U();if(j.aborted)throw new DOMException("Aborted","AbortError");let K=V(x),R=H instanceof Uint8ClampedArray?new Uint8Array(H):H,S=new Uint8Array(R),Q=J.encode(S,G,I,K);if(j.aborted)throw new DOMException("Aborted","AbortError");if(!Q)throw Error("WebP encoding failed");return Q}if(typeof self<"u")self.onmessage=async(j)=>{let z=j.data,x={id:z.id,ok:!1};try{if(z.type==="webp:encode"){let{image:G,options:I}=z.payload,H=new AbortController,J=await X(H.signal,G,I);x.ok=!0,x.data=J;let K=x.data.buffer;self.postMessage(x,[K])}else x.error=`Unknown message type: ${z.type}`,self.postMessage(x)}catch(G){x.error=G instanceof Error?G.message:String(G),self.postMessage(x)}};export{X as webpEncodeClient};
3
3
  export{X as a};
4
4
 
5
- //# debugId=12CA6CEA9252561D64756E2164756E21
5
+ //# debugId=66000A60E94E382464756E2164756E21
6
6
  //# sourceMappingURL=webp.worker.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/webp.worker.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * WebP encoder - single-source worker/client implementation\n */\n\nimport {\n isWorker,\n type WorkerRequest,\n type WorkerResponse,\n type ImageInput,\n} from '@squoosh-kit/runtime';\nimport type { WebpOptions } from './types.js';\n\n// Types from webp_enc.d.ts\ninterface EncodeOptions {\n quality: number;\n target_size: number;\n target_PSNR: number;\n method: number;\n sns_strength: number;\n filter_strength: number;\n filter_sharpness: number;\n filter_type: number;\n partitions: number;\n segments: number;\n pass: number;\n show_compressed: number;\n preprocessing: number;\n autofilter: number;\n partition_limit: number;\n alpha_compression: number;\n alpha_filtering: number;\n alpha_quality: number;\n lossless: number;\n exact: number;\n image_hint: number;\n emulate_jpeg_size: number;\n thread_level: number;\n low_memory: number;\n near_lossless: number;\n use_delta_palette: number;\n use_sharp_yuv: number;\n}\n\ninterface WebPModule {\n encode(\n data: BufferSource,\n width: number,\n height: number,\n options: EncodeOptions\n ): Uint8Array | null;\n}\n\nlet cachedModule: WebPModule | null = null;\n\nasync function loadWebPModule(): Promise<WebPModule> {\n if (cachedModule) {\n return cachedModule;\n }\n\n try {\n // Environment polyfills for Emscripten-generated code\n // The WebP encoder WASM module expects browser-like globals (self, location)\n // These polyfills ensure compatibility when running in Bun/Node.js environments\n if (typeof self === 'undefined') {\n // Polyfill 'self' global for Emscripten compatibility\n (global as { self?: typeof globalThis }).self = global;\n }\n if (typeof self !== 'undefined' && !self.location) {\n // Polyfill 'location' object for Emscripten module initialization\n (self as { location?: { href: string } }).location = {\n href: import.meta.url,\n };\n }\n\n // When running tests, Bun executes the .ts file directly from `src`.\n // In production, the compiled .js file is run from `dist`.\n // We need to adjust the asset path accordingly.\n const isTest = import.meta.url.endsWith('.ts');\n const wasmDirectory = isTest ? '../dist/wasm/webp' : './wasm/webp';\n\n // Dynamically import the WebP encoder module\n const modulePath = new URL(`${wasmDirectory}/webp_enc.js`, import.meta.url)\n .href;\n const moduleFactory = await import(modulePath);\n\n // Initialize the WebP module with locateFile to properly resolve the WASM\n const wasmPath = new URL(`${wasmDirectory}/`, import.meta.url).href;\n const module = await moduleFactory.default({\n locateFile: (path: string) => {\n // Return the full URL to the WASM file\n if (path.endsWith('.wasm')) {\n return new URL(path, wasmPath).href;\n }\n return path;\n },\n });\n\n cachedModule = module;\n return module;\n } catch (error) {\n throw new Error(\n `Failed to load WebP module: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Convert our simplified options to full EncodeOptions\n */\nfunction createEncodeOptions(options?: WebpOptions): EncodeOptions {\n const quality = Math.max(0, Math.min(100, options?.quality ?? 82));\n const lossless = options?.lossless ?? false;\n const nearLossless = options?.nearLossless ?? false;\n\n // Default encode options from Squoosh\n return {\n quality,\n target_size: 0,\n target_PSNR: 0,\n method: 4,\n sns_strength: 50,\n filter_strength: 60,\n filter_sharpness: 0,\n filter_type: 1,\n partitions: 0,\n segments: 4,\n pass: 1,\n show_compressed: 0,\n preprocessing: 0,\n autofilter: 0,\n partition_limit: 0,\n alpha_compression: 1,\n alpha_filtering: 1,\n alpha_quality: 100,\n lossless: lossless ? 1 : 0,\n exact: 0,\n image_hint: 0,\n emulate_jpeg_size: 0,\n thread_level: 0,\n low_memory: 0,\n near_lossless: nearLossless ? quality : 100,\n use_delta_palette: 0,\n use_sharp_yuv: 0,\n };\n}\n\n/**\n * Client-mode WebP encoder (exported for direct use)\n */\nexport async function webpEncodeClient(\n signal: AbortSignal,\n image: ImageInput,\n options?: WebpOptions\n): Promise<Uint8Array> {\n // Check abort before starting\n if (signal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n // Normalize image input\n const width = image.width;\n const height = image.height;\n const data = image.data;\n\n if (!(data instanceof Uint8Array) && !(data instanceof Uint8ClampedArray)) {\n throw new Error('Image data must be Uint8Array or Uint8ClampedArray');\n }\n\n const module = await loadWebPModule();\n\n // Check abort after async operation\n if (signal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n const encodeOptions = createEncodeOptions(options);\n\n // Call the encode function\n // Convert Uint8ClampedArray to Uint8Array if needed for BufferSource compatibility\n const dataArray =\n data instanceof Uint8ClampedArray ? new Uint8Array(data) : data;\n // Create a new Uint8Array with a proper ArrayBuffer to satisfy BufferSource\n const buffer = new Uint8Array(dataArray);\n const result = module.encode(buffer, width, height, encodeOptions);\n\n if (signal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n if (!result) {\n throw new Error('WebP encoding failed');\n }\n\n return result;\n}\n\n/**\n * Worker message handler\n * Register the handler regardless of environment (for both worker context and tests)\n */\nconsole.log('🔧 WebP worker: Message handler registered');\nif (typeof self !== 'undefined') {\n self.onmessage = async (event: MessageEvent) => {\n console.log('🔧 WebP worker: Received message', event.data);\n const request = event.data as WorkerRequest<{\n image: ImageInput;\n options?: WebpOptions;\n }>;\n\n const response: WorkerResponse<Uint8Array> = {\n id: request.id,\n ok: false,\n };\n\n try {\n if (request.type === 'webp:encode') {\n const { image, options } = request.payload;\n\n // Create an AbortController for this request\n const controller = new AbortController();\n\n const result = await webpEncodeClient(\n controller.signal,\n image,\n options\n );\n\n response.ok = true;\n response.data = result;\n\n // Transfer the result buffer back directly from the response data\n const resultBuffer: ArrayBuffer = response.data.buffer as ArrayBuffer;\n self.postMessage(response, [resultBuffer]);\n } else {\n response.error = `Unknown message type: ${request.type}`;\n self.postMessage(response);\n }\n } catch (error) {\n response.error = error instanceof Error ? error.message : String(error);\n self.postMessage(response);\n }\n };\n}\n"
5
+ "/**\n * WebP encoder - single-source worker/client implementation\n */\n\nimport {\n isWorker,\n type WorkerRequest,\n type WorkerResponse,\n type ImageInput,\n} from '@squoosh-kit/runtime';\nimport type { WebpOptions } from './types.js';\n\n// Types from webp_enc.d.ts\ninterface EncodeOptions {\n quality: number;\n target_size: number;\n target_PSNR: number;\n method: number;\n sns_strength: number;\n filter_strength: number;\n filter_sharpness: number;\n filter_type: number;\n partitions: number;\n segments: number;\n pass: number;\n show_compressed: number;\n preprocessing: number;\n autofilter: number;\n partition_limit: number;\n alpha_compression: number;\n alpha_filtering: number;\n alpha_quality: number;\n lossless: number;\n exact: number;\n image_hint: number;\n emulate_jpeg_size: number;\n thread_level: number;\n low_memory: number;\n near_lossless: number;\n use_delta_palette: number;\n use_sharp_yuv: number;\n}\n\ninterface WebPModule {\n encode(\n data: BufferSource,\n width: number,\n height: number,\n options: EncodeOptions\n ): Uint8Array | null;\n}\n\nlet cachedModule: WebPModule | null = null;\n\nasync function loadWebPModule(): Promise<WebPModule> {\n if (cachedModule) {\n return cachedModule;\n }\n\n try {\n // Environment polyfills for Emscripten-generated code\n // The WebP encoder WASM module expects browser-like globals (self, location)\n // These polyfills ensure compatibility when running in Bun/Node.js environments\n if (typeof self === 'undefined') {\n // Polyfill 'self' global for Emscripten compatibility\n (global as { self?: typeof globalThis }).self = global;\n }\n if (typeof self !== 'undefined' && !self.location) {\n // Polyfill 'location' object for Emscripten module initialization\n (self as { location?: { href: string } }).location = {\n href: import.meta.url,\n };\n }\n\n // The WASM assets are expected to be in a directory relative to the worker script.\n const wasmDirectory = './wasm/webp';\n\n // Dynamically import the WebP encoder module\n const modulePath = new URL(`${wasmDirectory}/webp_enc.js`, import.meta.url)\n .href;\n const moduleFactory = await import(modulePath);\n\n // Initialize the WebP module with locateFile to properly resolve the WASM\n const wasmPath = new URL(`${wasmDirectory}/`, import.meta.url).href;\n const module = await moduleFactory.default({\n locateFile: (path: string) => {\n // Return the full URL to the WASM file\n if (path.endsWith('.wasm')) {\n return new URL(path, wasmPath).href;\n }\n return path;\n },\n });\n\n cachedModule = module;\n return module;\n } catch (error) {\n throw new Error(\n `Failed to load WebP module: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Convert our simplified options to full EncodeOptions\n */\nfunction createEncodeOptions(options?: WebpOptions): EncodeOptions {\n const quality = Math.max(0, Math.min(100, options?.quality ?? 82));\n const lossless = options?.lossless ?? false;\n const nearLossless = options?.nearLossless ?? false;\n\n // Default encode options from Squoosh\n return {\n quality,\n target_size: 0,\n target_PSNR: 0,\n method: 4,\n sns_strength: 50,\n filter_strength: 60,\n filter_sharpness: 0,\n filter_type: 1,\n partitions: 0,\n segments: 4,\n pass: 1,\n show_compressed: 0,\n preprocessing: 0,\n autofilter: 0,\n partition_limit: 0,\n alpha_compression: 1,\n alpha_filtering: 1,\n alpha_quality: 100,\n lossless: lossless ? 1 : 0,\n exact: 0,\n image_hint: 0,\n emulate_jpeg_size: 0,\n thread_level: 0,\n low_memory: 0,\n near_lossless: nearLossless ? quality : 100,\n use_delta_palette: 0,\n use_sharp_yuv: 0,\n };\n}\n\n/**\n * Client-mode WebP encoder (exported for direct use)\n */\nexport async function webpEncodeClient(\n signal: AbortSignal,\n image: ImageInput,\n options?: WebpOptions\n): Promise<Uint8Array> {\n // Check abort before starting\n if (signal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n // Normalize image input\n const width = image.width;\n const height = image.height;\n const data = image.data;\n\n if (!(data instanceof Uint8Array) && !(data instanceof Uint8ClampedArray)) {\n throw new Error('Image data must be Uint8Array or Uint8ClampedArray');\n }\n\n const module = await loadWebPModule();\n\n // Check abort after async operation\n if (signal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n const encodeOptions = createEncodeOptions(options);\n\n // Call the encode function\n // Convert Uint8ClampedArray to Uint8Array if needed for BufferSource compatibility\n const dataArray =\n data instanceof Uint8ClampedArray ? new Uint8Array(data) : data;\n // Create a new Uint8Array with a proper ArrayBuffer to satisfy BufferSource\n const buffer = new Uint8Array(dataArray);\n const result = module.encode(buffer, width, height, encodeOptions);\n\n if (signal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n if (!result) {\n throw new Error('WebP encoding failed');\n }\n\n return result;\n}\n\n/**\n * Worker message handler\n * Register the handler regardless of environment (for both worker context and tests)\n */\nif (typeof self !== 'undefined') {\n self.onmessage = async (event: MessageEvent) => {\n const request = event.data as WorkerRequest<{\n image: ImageInput;\n options?: WebpOptions;\n }>;\n\n const response: WorkerResponse<Uint8Array> = {\n id: request.id,\n ok: false,\n };\n\n try {\n if (request.type === 'webp:encode') {\n const { image, options } = request.payload;\n\n // Create an AbortController for this request\n const controller = new AbortController();\n\n const result = await webpEncodeClient(\n controller.signal,\n image,\n options\n );\n\n response.ok = true;\n response.data = result;\n\n // Transfer the result buffer back directly from the response data\n const resultBuffer: ArrayBuffer = response.data.buffer as ArrayBuffer;\n self.postMessage(response, [resultBuffer]);\n } else {\n response.error = `Unknown message type: ${request.type}`;\n self.postMessage(response);\n }\n } catch (error) {\n response.error = error instanceof Error ? error.message : String(error);\n self.postMessage(response);\n }\n };\n}\n"
6
6
  ],
7
- "mappings": ";AAoDA,IAAI,EAAkC,KAEtC,eAAe,CAAc,EAAwB,CACnD,GAAI,EACF,OAAO,EAGT,GAAI,CAIF,GAAI,OAAO,KAAS,IAEjB,OAAwC,KAAO,OAElD,GAAI,OAAO,KAAS,KAAe,CAAC,KAAK,SAEtC,KAAyC,SAAW,CACnD,KAAM,YAAY,GACpB,EAOF,IAAM,EADS,YAAY,IAAI,SAAS,KAAK,EACd,oBAAsB,cAK/C,EAAgB,MAAa,OAFhB,IAAI,IAAI,GAAG,gBAA6B,YAAY,GAAG,EACvE,MAIG,EAAW,IAAI,IAAI,GAAG,KAAkB,YAAY,GAAG,EAAE,KACzD,EAAS,MAAM,EAAc,QAAQ,CACzC,WAAY,CAAC,IAAiB,CAE5B,GAAI,EAAK,SAAS,OAAO,EACvB,OAAO,IAAI,IAAI,EAAM,CAAQ,EAAE,KAEjC,OAAO,EAEX,CAAC,EAGD,OADA,EAAe,EACR,EACP,MAAO,EAAO,CACd,MAAU,MACR,+BAA+B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GACtF,GAOJ,SAAS,CAAmB,CAAC,EAAsC,CACjE,IAAM,EAAU,KAAK,IAAI,EAAG,KAAK,IAAI,IAAK,GAAS,SAAW,EAAE,CAAC,EAC3D,EAAW,GAAS,UAAY,GAChC,EAAe,GAAS,cAAgB,GAG9C,MAAO,CACL,UACA,YAAa,EACb,YAAa,EACb,OAAQ,EACR,aAAc,GACd,gBAAiB,GACjB,iBAAkB,EAClB,YAAa,EACb,WAAY,EACZ,SAAU,EACV,KAAM,EACN,gBAAiB,EACjB,cAAe,EACf,WAAY,EACZ,gBAAiB,EACjB,kBAAmB,EACnB,gBAAiB,EACjB,cAAe,IACf,SAAU,EAAW,EAAI,EACzB,MAAO,EACP,WAAY,EACZ,kBAAmB,EACnB,aAAc,EACd,WAAY,EACZ,cAAe,EAAe,EAAU,IACxC,kBAAmB,EACnB,cAAe,CACjB,EAMF,eAAsB,CAAgB,CACpC,EACA,EACA,EACqB,CAErB,GAAI,EAAO,QACT,MAAM,IAAI,aAAa,UAAW,YAAY,EAIhD,IAAoB,MAAd,EACe,OAAf,EACa,KAAb,GADS,EAGf,GAAI,EAAE,aAAgB,aAAe,EAAE,aAAgB,mBACrD,MAAU,MAAM,oDAAoD,EAGtE,IAAM,EAAS,MAAM,EAAe,EAGpC,GAAI,EAAO,QACT,MAAM,IAAI,aAAa,UAAW,YAAY,EAGhD,IAAM,EAAgB,EAAoB,CAAO,EAI3C,EACJ,aAAgB,kBAAoB,IAAI,WAAW,CAAI,EAAI,EAEvD,EAAS,IAAI,WAAW,CAAS,EACjC,EAAS,EAAO,OAAO,EAAQ,EAAO,EAAQ,CAAa,EAEjE,GAAI,EAAO,QACT,MAAM,IAAI,aAAa,UAAW,YAAY,EAGhD,GAAI,CAAC,EACH,MAAU,MAAM,sBAAsB,EAGxC,OAAO,EAOT,QAAQ,IAAI,sDAA2C,EACvD,GAAI,OAAO,KAAS,IAClB,KAAK,UAAY,MAAO,IAAwB,CAC9C,QAAQ,IAAI,6CAAmC,EAAM,IAAI,EACzD,IAAM,EAAU,EAAM,KAKhB,EAAuC,CAC3C,GAAI,EAAQ,GACZ,GAAI,EACN,EAEA,GAAI,CACF,GAAI,EAAQ,OAAS,cAAe,CAClC,IAAQ,QAAO,WAAY,EAAQ,QAG7B,EAAa,IAAI,gBAEjB,EAAS,MAAM,EACnB,EAAW,OACX,EACA,CACF,EAEA,EAAS,GAAK,GACd,EAAS,KAAO,EAGhB,IAAM,EAA4B,EAAS,KAAK,OAChD,KAAK,YAAY,EAAU,CAAC,CAAY,CAAC,EAEzC,OAAS,MAAQ,yBAAyB,EAAQ,OAClD,KAAK,YAAY,CAAQ,EAE3B,MAAO,EAAO,CACd,EAAS,MAAQ,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACtE,KAAK,YAAY,CAAQ",
8
- "debugId": "12CA6CEA9252561D64756E2164756E21",
7
+ "mappings": ";AAoDA,IAAI,EAAkC,KAEtC,eAAe,CAAc,EAAwB,CACnD,GAAI,EACF,OAAO,EAGT,GAAI,CAIF,GAAI,OAAO,KAAS,IAEjB,OAAwC,KAAO,OAElD,GAAI,OAAO,KAAS,KAAe,CAAC,KAAK,SAEtC,KAAyC,SAAW,CACnD,KAAM,YAAY,GACpB,EAIF,IAAM,EAAgB,cAKhB,EAAgB,MAAa,OAFhB,IAAI,IAAI,GAAG,gBAA6B,YAAY,GAAG,EACvE,MAIG,EAAW,IAAI,IAAI,GAAG,KAAkB,YAAY,GAAG,EAAE,KACzD,EAAS,MAAM,EAAc,QAAQ,CACzC,WAAY,CAAC,IAAiB,CAE5B,GAAI,EAAK,SAAS,OAAO,EACvB,OAAO,IAAI,IAAI,EAAM,CAAQ,EAAE,KAEjC,OAAO,EAEX,CAAC,EAGD,OADA,EAAe,EACR,EACP,MAAO,EAAO,CACd,MAAU,MACR,+BAA+B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GACtF,GAOJ,SAAS,CAAmB,CAAC,EAAsC,CACjE,IAAM,EAAU,KAAK,IAAI,EAAG,KAAK,IAAI,IAAK,GAAS,SAAW,EAAE,CAAC,EAC3D,EAAW,GAAS,UAAY,GAChC,EAAe,GAAS,cAAgB,GAG9C,MAAO,CACL,UACA,YAAa,EACb,YAAa,EACb,OAAQ,EACR,aAAc,GACd,gBAAiB,GACjB,iBAAkB,EAClB,YAAa,EACb,WAAY,EACZ,SAAU,EACV,KAAM,EACN,gBAAiB,EACjB,cAAe,EACf,WAAY,EACZ,gBAAiB,EACjB,kBAAmB,EACnB,gBAAiB,EACjB,cAAe,IACf,SAAU,EAAW,EAAI,EACzB,MAAO,EACP,WAAY,EACZ,kBAAmB,EACnB,aAAc,EACd,WAAY,EACZ,cAAe,EAAe,EAAU,IACxC,kBAAmB,EACnB,cAAe,CACjB,EAMF,eAAsB,CAAgB,CACpC,EACA,EACA,EACqB,CAErB,GAAI,EAAO,QACT,MAAM,IAAI,aAAa,UAAW,YAAY,EAIhD,IAAoB,MAAd,EACe,OAAf,EACa,KAAb,GADS,EAGf,GAAI,EAAE,aAAgB,aAAe,EAAE,aAAgB,mBACrD,MAAU,MAAM,oDAAoD,EAGtE,IAAM,EAAS,MAAM,EAAe,EAGpC,GAAI,EAAO,QACT,MAAM,IAAI,aAAa,UAAW,YAAY,EAGhD,IAAM,EAAgB,EAAoB,CAAO,EAI3C,EACJ,aAAgB,kBAAoB,IAAI,WAAW,CAAI,EAAI,EAEvD,EAAS,IAAI,WAAW,CAAS,EACjC,EAAS,EAAO,OAAO,EAAQ,EAAO,EAAQ,CAAa,EAEjE,GAAI,EAAO,QACT,MAAM,IAAI,aAAa,UAAW,YAAY,EAGhD,GAAI,CAAC,EACH,MAAU,MAAM,sBAAsB,EAGxC,OAAO,EAOT,GAAI,OAAO,KAAS,IAClB,KAAK,UAAY,MAAO,IAAwB,CAC9C,IAAM,EAAU,EAAM,KAKhB,EAAuC,CAC3C,GAAI,EAAQ,GACZ,GAAI,EACN,EAEA,GAAI,CACF,GAAI,EAAQ,OAAS,cAAe,CAClC,IAAQ,QAAO,WAAY,EAAQ,QAG7B,EAAa,IAAI,gBAEjB,EAAS,MAAM,EACnB,EAAW,OACX,EACA,CACF,EAEA,EAAS,GAAK,GACd,EAAS,KAAO,EAGhB,IAAM,EAA4B,EAAS,KAAK,OAChD,KAAK,YAAY,EAAU,CAAC,CAAY,CAAC,EAEzC,OAAS,MAAQ,yBAAyB,EAAQ,OAClD,KAAK,YAAY,CAAQ,EAE3B,MAAO,EAAO,CACd,EAAS,MAAQ,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACtE,KAAK,YAAY,CAAQ",
8
+ "debugId": "66000A60E94E382464756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@squoosh-kit/webp",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
- "entry": "src/index.ts",
6
5
  "description": "WebP codec for squoosh-kit, providing encoding functionality.",
7
6
  "author": "Bartosz Nowak <bnowak008@gmail.com>",
8
7
  "license": "MIT",
@@ -33,9 +32,10 @@
33
32
  "scripts": {
34
33
  "build": "bun run scripts/copy-assets.ts && tsc && bun build --sourcemap --minify --format=esm --splitting --target=bun --outdir=dist src/index.ts src/webp.worker.ts",
35
34
  "clean:local": "rm -rf dist *.tsbuildinfo",
36
- "prepack": "bun run build"
35
+ "prepack": "bun run build && bun test",
36
+ "test": "bun test"
37
37
  },
38
38
  "dependencies": {
39
- "@squoosh-kit/runtime": "0.1.0"
39
+ "@squoosh-kit/runtime": "0.0.3"
40
40
  }
41
41
  }