taglib-wasm 0.3.3 → 0.3.9

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 (68) hide show
  1. package/CONTRIBUTING.md +293 -0
  2. package/NOTICE +34 -0
  3. package/README.md +122 -511
  4. package/dist/index.d.ts +132 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +137 -0
  7. package/dist/index.ts +220 -0
  8. package/dist/src/constants.d.ts +201 -0
  9. package/dist/src/constants.d.ts.map +1 -0
  10. package/dist/src/constants.ts +227 -0
  11. package/dist/src/errors.d.ts +89 -0
  12. package/dist/src/errors.d.ts.map +1 -0
  13. package/dist/src/errors.ts +237 -0
  14. package/dist/src/file-utils.d.ts +205 -0
  15. package/dist/src/file-utils.d.ts.map +1 -0
  16. package/dist/src/file-utils.ts +467 -0
  17. package/dist/src/file.js +47 -0
  18. package/dist/src/global.d.ts +10 -0
  19. package/dist/src/mod.d.ts +9 -0
  20. package/dist/src/mod.d.ts.map +1 -0
  21. package/dist/src/mod.ts +19 -0
  22. package/dist/src/simple.d.ts +347 -0
  23. package/dist/src/simple.d.ts.map +1 -0
  24. package/dist/src/simple.ts +659 -0
  25. package/dist/src/taglib.d.ts +502 -0
  26. package/dist/src/taglib.d.ts.map +1 -0
  27. package/dist/src/taglib.ts +959 -0
  28. package/dist/src/types.d.ts +323 -0
  29. package/dist/src/types.d.ts.map +1 -0
  30. package/dist/src/types.ts +538 -0
  31. package/dist/src/utils/file.d.ts +15 -0
  32. package/dist/src/utils/file.d.ts.map +1 -0
  33. package/dist/src/utils/file.ts +82 -0
  34. package/dist/src/utils/write.d.ts +15 -0
  35. package/dist/src/utils/write.d.ts.map +1 -0
  36. package/dist/src/utils/write.ts +61 -0
  37. package/dist/src/wasm-workers.d.ts +33 -0
  38. package/dist/src/wasm-workers.d.ts.map +1 -0
  39. package/dist/src/wasm-workers.ts +176 -0
  40. package/dist/src/wasm.d.ts +97 -0
  41. package/dist/src/wasm.d.ts.map +1 -0
  42. package/dist/src/wasm.ts +133 -0
  43. package/dist/src/web-utils.d.ts +180 -0
  44. package/dist/src/web-utils.d.ts.map +1 -0
  45. package/dist/src/web-utils.ts +347 -0
  46. package/dist/src/workers.d.ts +219 -0
  47. package/dist/src/workers.d.ts.map +1 -0
  48. package/dist/src/workers.ts +465 -0
  49. package/dist/src/write.js +33 -0
  50. package/dist/taglib-wrapper.d.ts +5 -0
  51. package/dist/taglib-wrapper.js +14 -0
  52. package/dist/taglib.wasm +0 -0
  53. package/index.ts +100 -7
  54. package/package.json +40 -16
  55. package/src/errors.ts +237 -0
  56. package/src/file-utils.ts +467 -0
  57. package/src/global.d.ts +10 -0
  58. package/src/simple.ts +399 -84
  59. package/src/taglib.ts +522 -28
  60. package/src/types.ts +1 -1
  61. package/src/utils/file.ts +82 -0
  62. package/src/utils/write.ts +61 -0
  63. package/src/wasm-workers.ts +13 -4
  64. package/src/wasm.ts +1 -1
  65. package/src/web-utils.ts +347 -0
  66. package/src/workers.ts +32 -13
  67. package/build/taglib.js +0 -2407
  68. package/build/taglib.wasm +0 -0
package/src/types.ts CHANGED
@@ -18,7 +18,7 @@ export type { TagLibModule } from "./wasm.ts";
18
18
  *
19
19
  * @example
20
20
  * ```typescript
21
- * const file = await taglib.openFile(buffer);
21
+ * const file = await taglib.open(buffer);
22
22
  * const format = file.getFormat();
23
23
  * if (format === "MP3") {
24
24
  * // Handle MP3-specific features
@@ -0,0 +1,82 @@
1
+ /**
2
+ * File reading utilities for taglib-wasm
3
+ * Provides cross-runtime support for reading files from various sources
4
+ */
5
+
6
+ import { EnvironmentError, FileOperationError } from "../errors.ts";
7
+
8
+ /**
9
+ * Read a file's data from various sources.
10
+ * Supports file paths (Node.js/Deno/Bun), buffers, and File objects (browser).
11
+ *
12
+ * @param file - File path, Uint8Array, ArrayBuffer, or File object
13
+ * @returns Promise resolving to Uint8Array of file data
14
+ * @throws {FileOperationError} If file read fails
15
+ * @throws {EnvironmentError} If environment doesn't support file paths
16
+ */
17
+ export async function readFileData(
18
+ file: string | Uint8Array | ArrayBuffer | File,
19
+ ): Promise<Uint8Array> {
20
+ // Already a Uint8Array
21
+ if (file instanceof Uint8Array) {
22
+ return file;
23
+ }
24
+
25
+ // ArrayBuffer - convert to Uint8Array
26
+ if (file instanceof ArrayBuffer) {
27
+ return new Uint8Array(file);
28
+ }
29
+
30
+ // File object (browser)
31
+ if (typeof File !== "undefined" && file instanceof File) {
32
+ return new Uint8Array(await file.arrayBuffer());
33
+ }
34
+
35
+ // String path - read from filesystem
36
+ if (typeof file === "string") {
37
+ try {
38
+ // Deno
39
+ if (typeof Deno !== "undefined") {
40
+ return await Deno.readFile(file);
41
+ }
42
+
43
+ // Node.js
44
+ if (
45
+ typeof process !== "undefined" && process.versions &&
46
+ process.versions.node
47
+ ) {
48
+ const { readFile } = await import("fs/promises");
49
+ return new Uint8Array(await readFile(file));
50
+ }
51
+
52
+ // Bun
53
+ if (typeof (globalThis as any).Bun !== "undefined") {
54
+ const bunFile = (globalThis as any).Bun.file(file);
55
+ return new Uint8Array(await bunFile.arrayBuffer());
56
+ }
57
+ } catch (error) {
58
+ // Convert system file errors to FileOperationError
59
+ throw new FileOperationError(
60
+ "read",
61
+ (error as Error).message,
62
+ file
63
+ );
64
+ }
65
+
66
+ const env = typeof Deno !== "undefined" ? "Deno" :
67
+ typeof process !== "undefined" ? "Node.js" :
68
+ typeof (globalThis as any).Bun !== "undefined" ? "Bun" :
69
+ "Browser";
70
+ throw new EnvironmentError(
71
+ env,
72
+ "does not support file path reading",
73
+ "filesystem access"
74
+ );
75
+ }
76
+
77
+ const inputType = Object.prototype.toString.call(file);
78
+ throw new FileOperationError(
79
+ "read",
80
+ `Invalid file input type: ${inputType}. Expected string path, Uint8Array, ArrayBuffer, or File object.`
81
+ );
82
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * File writing utilities for taglib-wasm
3
+ * Provides cross-runtime support for writing files
4
+ */
5
+
6
+ import { EnvironmentError, FileOperationError } from "../errors.ts";
7
+
8
+ /**
9
+ * Write data to a file across different runtimes.
10
+ * Supports Node.js, Deno, and Bun environments.
11
+ *
12
+ * @param path - File path to write to
13
+ * @param data - Data to write (Uint8Array)
14
+ * @throws {FileOperationError} If file write fails
15
+ * @throws {EnvironmentError} If environment doesn't support file writing
16
+ */
17
+ export async function writeFileData(
18
+ path: string,
19
+ data: Uint8Array,
20
+ ): Promise<void> {
21
+ try {
22
+ // Deno
23
+ if (typeof Deno !== "undefined") {
24
+ await Deno.writeFile(path, data);
25
+ return;
26
+ }
27
+
28
+ // Node.js
29
+ if (
30
+ typeof process !== "undefined" && process.versions &&
31
+ process.versions.node
32
+ ) {
33
+ const { writeFile } = await import("fs/promises");
34
+ await writeFile(path, data);
35
+ return;
36
+ }
37
+
38
+ // Bun
39
+ if (typeof (globalThis as any).Bun !== "undefined") {
40
+ await (globalThis as any).Bun.write(path, data);
41
+ return;
42
+ }
43
+ } catch (error) {
44
+ // Convert system file errors to FileOperationError
45
+ throw new FileOperationError(
46
+ "write",
47
+ (error as Error).message,
48
+ path
49
+ );
50
+ }
51
+
52
+ const env = typeof Deno !== "undefined" ? "Deno" :
53
+ typeof process !== "undefined" ? "Node.js" :
54
+ typeof (globalThis as any).Bun !== "undefined" ? "Bun" :
55
+ "Browser";
56
+ throw new EnvironmentError(
57
+ env,
58
+ "does not support file path writing",
59
+ "filesystem access"
60
+ );
61
+ }
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { TagLibConfig, TagLibModule } from "./types.ts";
6
+ import { TagLibInitializationError } from "./errors.ts";
6
7
 
7
8
  // Re-export TagLibModule for convenience
8
9
  export type { TagLibModule };
@@ -69,7 +70,10 @@ export async function loadTagLibModuleForWorkers(
69
70
  const TagLibWasm = await createWorkersCompatibleModule();
70
71
 
71
72
  if (typeof TagLibWasm !== "function") {
72
- throw new Error("Failed to load taglib-wasm module for Workers");
73
+ throw new TagLibInitializationError(
74
+ "Failed to load taglib-wasm module for Workers. " +
75
+ "The module may not be properly bundled for the Workers environment.",
76
+ );
73
77
  }
74
78
 
75
79
  const wasmInstance = await TagLibWasm(moduleConfig);
@@ -91,8 +95,12 @@ export async function loadTagLibModuleForWorkers(
91
95
 
92
96
  return wasmInstance as TagLibModule;
93
97
  } catch (error) {
94
- throw new Error(
98
+ if (error instanceof TagLibInitializationError) {
99
+ throw error;
100
+ }
101
+ throw new TagLibInitializationError(
95
102
  `Failed to load taglib-wasm for Workers: ${(error as Error).message}`,
103
+ { error: (error as Error).message },
96
104
  );
97
105
  }
98
106
  }
@@ -110,14 +118,15 @@ async function createWorkersCompatibleModule(): Promise<any> {
110
118
  // For now, we'll attempt to load the existing module with Workers compatibility
111
119
  try {
112
120
  // Try to import the existing module
113
- const wasmModule = await import("../build/taglib.js");
121
+ const wasmModule = await import("../build/taglib-wrapper.js");
114
122
  return wasmModule.default || wasmModule;
115
123
  } catch (error) {
116
124
  // If that fails, provide a fallback implementation
117
- throw new Error(
125
+ throw new TagLibInitializationError(
118
126
  "Workers-compatible Wasm module not available. " +
119
127
  "Please build with Workers target or use a bundler that supports Wasm modules. " +
120
128
  `Original error: ${(error as Error).message}`,
129
+ { error: (error as Error).message },
121
130
  );
122
131
  }
123
132
  }
package/src/wasm.ts CHANGED
@@ -84,7 +84,7 @@ export interface AudioPropertiesWrapper {
84
84
  channels(): number;
85
85
  }
86
86
 
87
- export interface TagLibModule extends EmscriptenModule {
87
+ export interface TagLibModule extends Omit<EmscriptenModule, 'then'> {
88
88
  // Embind classes
89
89
  FileHandle: new () => FileHandle;
90
90
  TagWrapper: new () => TagWrapper;
@@ -0,0 +1,347 @@
1
+ /**
2
+ * @fileoverview Web browser utilities for working with cover art in taglib-wasm
3
+ *
4
+ * This module provides browser-specific helpers for integrating taglib-wasm
5
+ * with web applications, including canvas integration and data URL support.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { pictureToDataURL, setCoverArtFromCanvas } from "taglib-wasm/web-utils";
10
+ *
11
+ * // Display cover art in an <img> element
12
+ * const pictures = await readPictures("song.mp3");
13
+ * if (pictures.length > 0) {
14
+ * const dataURL = pictureToDataURL(pictures[0]);
15
+ * document.getElementById('cover').src = dataURL;
16
+ * }
17
+ *
18
+ * // Set cover art from a canvas
19
+ * const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
20
+ * const modifiedBuffer = await setCoverArtFromCanvas("song.mp3", canvas);
21
+ * ```
22
+ */
23
+
24
+ import type { Picture } from "./types.ts";
25
+ import { PictureType } from "./types.ts";
26
+ import { applyPictures, readPictures } from "./simple.ts";
27
+
28
+ /**
29
+ * Convert a Picture object to a data URL for display in web browsers
30
+ *
31
+ * @param picture - Picture object from taglib-wasm
32
+ * @returns Data URL string that can be used as src for <img> elements
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const pictures = await readPictures("song.mp3");
37
+ * const imgElement = document.getElementById('coverArt') as HTMLImageElement;
38
+ * imgElement.src = pictureToDataURL(pictures[0]);
39
+ * ```
40
+ */
41
+ export function pictureToDataURL(picture: Picture): string {
42
+ // Convert Uint8Array to base64
43
+ const base64 = btoa(String.fromCharCode(...picture.data));
44
+ return `data:${picture.mimeType};base64,${base64}`;
45
+ }
46
+
47
+ /**
48
+ * Convert a data URL to a Picture object
49
+ *
50
+ * @param dataURL - Data URL string (e.g., "data:image/jpeg;base64,...")
51
+ * @param type - Picture type (defaults to FrontCover)
52
+ * @param description - Optional description
53
+ * @returns Picture object
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const dataURL = canvas.toDataURL('image/jpeg');
58
+ * const picture = dataURLToPicture(dataURL, PictureType.FrontCover);
59
+ * const modifiedBuffer = await applyPictures("song.mp3", [picture]);
60
+ * ```
61
+ */
62
+ export function dataURLToPicture(
63
+ dataURL: string,
64
+ type: PictureType = PictureType.FrontCover,
65
+ description?: string,
66
+ ): Picture {
67
+ // Parse data URL
68
+ const matches = dataURL.match(/^data:([^;]+);base64,(.+)$/);
69
+ if (!matches) {
70
+ throw new Error("Invalid data URL format");
71
+ }
72
+
73
+ const [, mimeType, base64] = matches;
74
+
75
+ // Convert base64 to Uint8Array
76
+ const binaryString = atob(base64);
77
+ const data = new Uint8Array(binaryString.length);
78
+ for (let i = 0; i < binaryString.length; i++) {
79
+ data[i] = binaryString.charCodeAt(i);
80
+ }
81
+
82
+ return {
83
+ mimeType,
84
+ data,
85
+ type,
86
+ description,
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Set cover art from an HTML canvas element
92
+ *
93
+ * @param file - File path, Uint8Array buffer, ArrayBuffer, or File object
94
+ * @param canvas - HTMLCanvasElement containing the image
95
+ * @param options - Options for image format and quality
96
+ * @returns Modified file buffer with cover art from canvas
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const canvas = document.getElementById('albumArt') as HTMLCanvasElement;
101
+ * const modifiedBuffer = await setCoverArtFromCanvas("song.mp3", canvas, {
102
+ * format: 'image/jpeg',
103
+ * quality: 0.9
104
+ * });
105
+ * ```
106
+ */
107
+ export async function setCoverArtFromCanvas(
108
+ file: string | Uint8Array | ArrayBuffer | File,
109
+ canvas: HTMLCanvasElement,
110
+ options: {
111
+ format?: 'image/jpeg' | 'image/png' | 'image/webp';
112
+ quality?: number;
113
+ type?: PictureType;
114
+ description?: string;
115
+ } = {},
116
+ ): Promise<Uint8Array> {
117
+ const {
118
+ format = 'image/jpeg',
119
+ quality = 0.92,
120
+ type = PictureType.FrontCover,
121
+ description = "Front Cover",
122
+ } = options;
123
+
124
+ // Convert canvas to data URL
125
+ const dataURL = canvas.toDataURL(format, quality);
126
+
127
+ // Convert to Picture object
128
+ const picture = dataURLToPicture(dataURL, type, description);
129
+
130
+ // Apply to file
131
+ return applyPictures(file, [picture]);
132
+ }
133
+
134
+ /**
135
+ * Convert canvas to Picture object using blob for better performance
136
+ *
137
+ * This is more efficient than toDataURL for large images as it avoids
138
+ * the base64 encoding/decoding step.
139
+ *
140
+ * @param canvas - HTMLCanvasElement containing the image
141
+ * @param options - Options for image format and quality
142
+ * @returns Promise resolving to Picture object
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const canvas = document.getElementById('albumArt') as HTMLCanvasElement;
147
+ * const picture = await canvasToPicture(canvas, {
148
+ * format: 'image/png',
149
+ * type: PictureType.BackCover
150
+ * });
151
+ * ```
152
+ */
153
+ export async function canvasToPicture(
154
+ canvas: HTMLCanvasElement,
155
+ options: {
156
+ format?: 'image/jpeg' | 'image/png' | 'image/webp';
157
+ quality?: number;
158
+ type?: PictureType;
159
+ description?: string;
160
+ } = {},
161
+ ): Promise<Picture> {
162
+ const {
163
+ format = 'image/jpeg',
164
+ quality = 0.92,
165
+ type = PictureType.FrontCover,
166
+ description,
167
+ } = options;
168
+
169
+ return new Promise((resolve, reject) => {
170
+ canvas.toBlob(
171
+ async (blob) => {
172
+ if (!blob) {
173
+ reject(new Error("Failed to convert canvas to blob"));
174
+ return;
175
+ }
176
+
177
+ // Convert blob to Uint8Array
178
+ const arrayBuffer = await blob.arrayBuffer();
179
+ const data = new Uint8Array(arrayBuffer);
180
+
181
+ resolve({
182
+ mimeType: format,
183
+ data,
184
+ type,
185
+ description,
186
+ });
187
+ },
188
+ format,
189
+ quality,
190
+ );
191
+ });
192
+ }
193
+
194
+ /**
195
+ * Load an image file into a Picture object
196
+ *
197
+ * @param file - File object from <input type="file"> or drag-and-drop
198
+ * @param type - Picture type (defaults to FrontCover)
199
+ * @param description - Optional description
200
+ * @returns Promise resolving to Picture object
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * // From file input
205
+ * const input = document.getElementById('fileInput') as HTMLInputElement;
206
+ * input.addEventListener('change', async (e) => {
207
+ * const file = e.target.files[0];
208
+ * const picture = await imageFileToPicture(file);
209
+ * const modifiedBuffer = await applyPictures("song.mp3", [picture]);
210
+ * });
211
+ * ```
212
+ */
213
+ export async function imageFileToPicture(
214
+ file: File,
215
+ type: PictureType = PictureType.FrontCover,
216
+ description?: string,
217
+ ): Promise<Picture> {
218
+ const arrayBuffer = await file.arrayBuffer();
219
+ const data = new Uint8Array(arrayBuffer);
220
+
221
+ return {
222
+ mimeType: file.type,
223
+ data,
224
+ type,
225
+ description: description || file.name,
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Display a Picture in an HTML img element
231
+ *
232
+ * @param picture - Picture object from taglib-wasm
233
+ * @param imgElement - HTMLImageElement to display the picture in
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * const pictures = await readPictures("song.mp3");
238
+ * const img = document.getElementById('coverArt') as HTMLImageElement;
239
+ * displayPicture(pictures[0], img);
240
+ * ```
241
+ */
242
+ export function displayPicture(
243
+ picture: Picture,
244
+ imgElement: HTMLImageElement,
245
+ ): void {
246
+ // Clean up previous object URL if any
247
+ if (imgElement.src.startsWith('blob:')) {
248
+ URL.revokeObjectURL(imgElement.src);
249
+ }
250
+
251
+ // Create blob and object URL
252
+ const blob = new Blob([picture.data], { type: picture.mimeType });
253
+ const objectURL = URL.createObjectURL(blob);
254
+
255
+ // Set the src
256
+ imgElement.src = objectURL;
257
+
258
+ // Clean up object URL when image is no longer needed
259
+ imgElement.addEventListener('load', () => {
260
+ // Keep the URL alive for a bit to ensure image is rendered
261
+ setTimeout(() => URL.revokeObjectURL(objectURL), 100);
262
+ }, { once: true });
263
+ }
264
+
265
+ /**
266
+ * Create a download link for a Picture
267
+ *
268
+ * @param picture - Picture object to download
269
+ * @param filename - Suggested filename for download
270
+ * @returns Temporary download URL (remember to revoke it after use)
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * const pictures = await readPictures("song.mp3");
275
+ * const downloadUrl = createPictureDownloadURL(pictures[0], "cover.jpg");
276
+ *
277
+ * const link = document.createElement('a');
278
+ * link.href = downloadUrl;
279
+ * link.download = "cover.jpg";
280
+ * link.click();
281
+ *
282
+ * // Clean up
283
+ * URL.revokeObjectURL(downloadUrl);
284
+ * ```
285
+ */
286
+ export function createPictureDownloadURL(
287
+ picture: Picture,
288
+ filename: string = "cover",
289
+ ): string {
290
+ const blob = new Blob([picture.data], { type: picture.mimeType });
291
+ return URL.createObjectURL(blob);
292
+ }
293
+
294
+ /**
295
+ * Extract all pictures and create a gallery
296
+ *
297
+ * @param file - Audio file to extract pictures from
298
+ * @param container - HTML element to append gallery items to
299
+ * @param options - Gallery display options
300
+ *
301
+ * @example
302
+ * ```typescript
303
+ * const galleryDiv = document.getElementById('pictureGallery');
304
+ * await createPictureGallery("song.mp3", galleryDiv, {
305
+ * className: 'album-art',
306
+ * includeDescription: true
307
+ * });
308
+ * ```
309
+ */
310
+ export async function createPictureGallery(
311
+ file: string | Uint8Array | ArrayBuffer | File,
312
+ container: HTMLElement,
313
+ options: {
314
+ className?: string;
315
+ includeDescription?: boolean;
316
+ onClick?: (picture: Picture, index: number) => void;
317
+ } = {},
318
+ ): Promise<void> {
319
+ const pictures = await readPictures(file);
320
+
321
+ // Clear container
322
+ container.innerHTML = '';
323
+
324
+ pictures.forEach((picture, index) => {
325
+ const wrapper = document.createElement('div');
326
+ wrapper.className = options.className || 'picture-item';
327
+
328
+ const img = document.createElement('img');
329
+ displayPicture(picture, img);
330
+ img.alt = picture.description || `Picture ${index + 1}`;
331
+
332
+ if (options.onClick) {
333
+ img.style.cursor = 'pointer';
334
+ img.addEventListener('click', () => options.onClick!(picture, index));
335
+ }
336
+
337
+ wrapper.appendChild(img);
338
+
339
+ if (options.includeDescription && picture.description) {
340
+ const caption = document.createElement('p');
341
+ caption.textContent = picture.description;
342
+ wrapper.appendChild(caption);
343
+ }
344
+
345
+ container.appendChild(wrapper);
346
+ });
347
+ }
package/src/workers.ts CHANGED
@@ -21,6 +21,11 @@ import {
21
21
  loadTagLibModuleForWorkers,
22
22
  type TagLibModule,
23
23
  } from "./wasm-workers.ts";
24
+ import {
25
+ EnvironmentError,
26
+ InvalidFormatError,
27
+ MemoryError,
28
+ } from "./errors.ts";
24
29
 
25
30
  /**
26
31
  * Represents an audio file with metadata and properties (Workers-compatible).
@@ -123,7 +128,6 @@ export class AudioFileWorkers {
123
128
  bitrate,
124
129
  sampleRate,
125
130
  channels,
126
- format: this.format(),
127
131
  };
128
132
  }
129
133
 
@@ -324,7 +328,7 @@ export class TagLibWorkers {
324
328
  * import wasmBinary from "../build/taglib.wasm";
325
329
  *
326
330
  * const taglib = await TagLibWorkers.initialize(wasmBinary);
327
- * const file = taglib.openFile(audioBuffer);
331
+ * const file = taglib.open(audioBuffer);
328
332
  * const metadata = file.tag();
329
333
  * ```
330
334
  */
@@ -348,12 +352,15 @@ export class TagLibWorkers {
348
352
  * @example
349
353
  * ```typescript
350
354
  * const audioData = new Uint8Array(await request.arrayBuffer());
351
- * const file = taglib.openFile(audioData);
355
+ * const file = taglib.open(audioData);
352
356
  * ```
353
357
  */
354
- openFile(buffer: Uint8Array): AudioFileWorkers {
358
+ open(buffer: Uint8Array): AudioFileWorkers {
355
359
  if (!this.module.HEAPU8) {
356
- throw new Error("Wasm module not properly initialized - missing HEAPU8");
360
+ throw new MemoryError(
361
+ "Wasm module not properly initialized: missing HEAPU8. " +
362
+ "The module may not have loaded correctly in the Workers environment."
363
+ );
357
364
  }
358
365
 
359
366
  // Use Emscripten's allocate function for proper memory management
@@ -366,8 +373,10 @@ export class TagLibWorkers {
366
373
  }
367
374
 
368
375
  if (!this.module._taglib_file_new_from_buffer) {
369
- throw new Error(
370
- "Workers API requires C-style functions. Use Core API instead.",
376
+ throw new EnvironmentError(
377
+ "Workers",
378
+ "requires C-style functions which are not available. Use the Core API instead for this environment",
379
+ "C-style function exports"
371
380
  );
372
381
  }
373
382
 
@@ -377,11 +386,11 @@ export class TagLibWorkers {
377
386
  );
378
387
 
379
388
  if (fileId === 0) {
380
- console.log(
381
- `DEBUG: File creation failed, not freeing memory at ${dataPtr}`,
382
- );
383
- throw new Error(
384
- "Failed to open audio file - invalid format or corrupted data",
389
+ // Free the allocated memory since file creation failed
390
+ this.module._free(dataPtr);
391
+ throw new InvalidFormatError(
392
+ "Failed to open audio file. File format may be invalid or not supported",
393
+ buffer.length
385
394
  );
386
395
  }
387
396
 
@@ -391,6 +400,16 @@ export class TagLibWorkers {
391
400
  return new AudioFileWorkers(this.module, fileId);
392
401
  }
393
402
 
403
+ /**
404
+ * @deprecated Use `open()` instead. This method will be removed in the next major version.
405
+ * Open an audio file from a buffer (backward compatibility).
406
+ * @param buffer Audio file data as Uint8Array
407
+ * @returns Audio file instance
408
+ */
409
+ openFile(buffer: Uint8Array): AudioFileWorkers {
410
+ return this.open(buffer);
411
+ }
412
+
394
413
  /**
395
414
  * Get the underlying Wasm module for advanced usage.
396
415
  * @returns The initialized TagLib Wasm module
@@ -425,7 +444,7 @@ export async function processAudioMetadata(
425
444
  { tag: Tag; properties: AudioProperties | null; format: AudioFormat }
426
445
  > {
427
446
  const taglib = await TagLibWorkers.initialize(wasmBinary, config);
428
- const file = taglib.openFile(audioData);
447
+ const file = taglib.open(audioData);
429
448
 
430
449
  try {
431
450
  const tag = file.tag();