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.
- package/CONTRIBUTING.md +293 -0
- package/NOTICE +34 -0
- package/README.md +122 -511
- package/dist/index.d.ts +132 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.ts +220 -0
- package/dist/src/constants.d.ts +201 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.ts +227 -0
- package/dist/src/errors.d.ts +89 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.ts +237 -0
- package/dist/src/file-utils.d.ts +205 -0
- package/dist/src/file-utils.d.ts.map +1 -0
- package/dist/src/file-utils.ts +467 -0
- package/dist/src/file.js +47 -0
- package/dist/src/global.d.ts +10 -0
- package/dist/src/mod.d.ts +9 -0
- package/dist/src/mod.d.ts.map +1 -0
- package/dist/src/mod.ts +19 -0
- package/dist/src/simple.d.ts +347 -0
- package/dist/src/simple.d.ts.map +1 -0
- package/dist/src/simple.ts +659 -0
- package/dist/src/taglib.d.ts +502 -0
- package/dist/src/taglib.d.ts.map +1 -0
- package/dist/src/taglib.ts +959 -0
- package/dist/src/types.d.ts +323 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.ts +538 -0
- package/dist/src/utils/file.d.ts +15 -0
- package/dist/src/utils/file.d.ts.map +1 -0
- package/dist/src/utils/file.ts +82 -0
- package/dist/src/utils/write.d.ts +15 -0
- package/dist/src/utils/write.d.ts.map +1 -0
- package/dist/src/utils/write.ts +61 -0
- package/dist/src/wasm-workers.d.ts +33 -0
- package/dist/src/wasm-workers.d.ts.map +1 -0
- package/dist/src/wasm-workers.ts +176 -0
- package/dist/src/wasm.d.ts +97 -0
- package/dist/src/wasm.d.ts.map +1 -0
- package/dist/src/wasm.ts +133 -0
- package/dist/src/web-utils.d.ts +180 -0
- package/dist/src/web-utils.d.ts.map +1 -0
- package/dist/src/web-utils.ts +347 -0
- package/dist/src/workers.d.ts +219 -0
- package/dist/src/workers.d.ts.map +1 -0
- package/dist/src/workers.ts +465 -0
- package/dist/src/write.js +33 -0
- package/dist/taglib-wrapper.d.ts +5 -0
- package/dist/taglib-wrapper.js +14 -0
- package/dist/taglib.wasm +0 -0
- package/index.ts +100 -7
- package/package.json +40 -16
- package/src/errors.ts +237 -0
- package/src/file-utils.ts +467 -0
- package/src/global.d.ts +10 -0
- package/src/simple.ts +399 -84
- package/src/taglib.ts +522 -28
- package/src/types.ts +1 -1
- package/src/utils/file.ts +82 -0
- package/src/utils/write.ts +61 -0
- package/src/wasm-workers.ts +13 -4
- package/src/wasm.ts +1 -1
- package/src/web-utils.ts +347 -0
- package/src/workers.ts +32 -13
- package/build/taglib.js +0 -2407
- package/build/taglib.wasm +0 -0
package/index.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* import { TagLib } from "taglib-wasm";
|
|
13
13
|
*
|
|
14
14
|
* const taglib = await TagLib.initialize();
|
|
15
|
-
* const file = await taglib.
|
|
15
|
+
* const file = await taglib.open(audioBuffer);
|
|
16
16
|
* const tag = file.tag();
|
|
17
17
|
* console.log(tag.title);
|
|
18
18
|
* file.dispose();
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
* @example
|
|
22
22
|
* ```typescript
|
|
23
23
|
* // Using the Simple API
|
|
24
|
-
* import { readTags,
|
|
24
|
+
* import { readTags, applyTags } from "taglib-wasm";
|
|
25
25
|
*
|
|
26
26
|
* const tags = await readTags("song.mp3");
|
|
27
27
|
* console.log(tags.artist);
|
|
28
28
|
*
|
|
29
|
-
* const modified = await
|
|
29
|
+
* const modified = await applyTags("song.mp3", {
|
|
30
30
|
* artist: "New Artist",
|
|
31
31
|
* album: "New Album"
|
|
32
32
|
* });
|
|
@@ -45,13 +45,67 @@ export {
|
|
|
45
45
|
TagLib,
|
|
46
46
|
} from "./src/taglib.ts";
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Error types for proper error handling and debugging.
|
|
50
|
+
* @see {@link TagLibError} - Base error class for all TagLib errors
|
|
51
|
+
* @see {@link TagLibInitializationError} - Wasm initialization failures
|
|
52
|
+
* @see {@link InvalidFormatError} - Invalid or corrupted file format
|
|
53
|
+
* @see {@link UnsupportedFormatError} - Valid but unsupported format
|
|
54
|
+
* @see {@link FileOperationError} - File read/write/save failures
|
|
55
|
+
* @see {@link MetadataError} - Tag reading/writing failures
|
|
56
|
+
* @see {@link MemoryError} - Wasm memory allocation issues
|
|
57
|
+
* @see {@link EnvironmentError} - Runtime/environment issues
|
|
58
|
+
*/
|
|
59
|
+
export {
|
|
60
|
+
EnvironmentError,
|
|
61
|
+
FileOperationError,
|
|
62
|
+
InvalidFormatError,
|
|
63
|
+
isEnvironmentError,
|
|
64
|
+
isFileOperationError,
|
|
65
|
+
isInvalidFormatError,
|
|
66
|
+
isMemoryError,
|
|
67
|
+
isMetadataError,
|
|
68
|
+
isTagLibError,
|
|
69
|
+
isUnsupportedFormatError,
|
|
70
|
+
MemoryError,
|
|
71
|
+
MetadataError,
|
|
72
|
+
SUPPORTED_FORMATS,
|
|
73
|
+
TagLibError,
|
|
74
|
+
TagLibInitializationError,
|
|
75
|
+
UnsupportedFormatError,
|
|
76
|
+
} from "./src/errors.ts";
|
|
77
|
+
|
|
48
78
|
/**
|
|
49
79
|
* Simple API exports for easy tag reading and writing.
|
|
50
80
|
* @see {@link readTags} - Read metadata from audio files
|
|
51
|
-
* @see {@link
|
|
81
|
+
* @see {@link applyTags} - Apply metadata changes and return modified buffer
|
|
82
|
+
* @see {@link updateTags} - Update metadata and save to disk
|
|
83
|
+
* @see {@link writeTags} - Deprecated alias for applyTags
|
|
52
84
|
* @see {@link readProperties} - Read audio properties
|
|
85
|
+
* @see {@link readPictures} - Read cover art/pictures
|
|
86
|
+
* @see {@link applyPictures} - Apply pictures to audio files
|
|
87
|
+
* @see {@link getCoverArt} - Get primary cover art data
|
|
88
|
+
* @see {@link setCoverArt} - Set primary cover art
|
|
53
89
|
*/
|
|
54
|
-
export {
|
|
90
|
+
export {
|
|
91
|
+
readProperties,
|
|
92
|
+
readTags,
|
|
93
|
+
applyTags,
|
|
94
|
+
updateTags,
|
|
95
|
+
writeTags, // Deprecated but exported for backward compatibility
|
|
96
|
+
readPictures,
|
|
97
|
+
applyPictures,
|
|
98
|
+
addPicture,
|
|
99
|
+
clearPictures,
|
|
100
|
+
getCoverArt,
|
|
101
|
+
setCoverArt,
|
|
102
|
+
findPictureByType,
|
|
103
|
+
replacePictureByType,
|
|
104
|
+
getPictureMetadata,
|
|
105
|
+
isValidAudioFile,
|
|
106
|
+
getFormat,
|
|
107
|
+
clearTags
|
|
108
|
+
} from "./src/simple.ts";
|
|
55
109
|
|
|
56
110
|
/**
|
|
57
111
|
* Constants and utilities for tag name validation.
|
|
@@ -66,6 +120,41 @@ export {
|
|
|
66
120
|
isValidTagName,
|
|
67
121
|
Tags,
|
|
68
122
|
} from "./src/constants.ts";
|
|
123
|
+
/**
|
|
124
|
+
* File I/O utilities for cover art operations.
|
|
125
|
+
* @see {@link exportCoverArt} - Export cover art to file
|
|
126
|
+
* @see {@link importCoverArt} - Import cover art from file
|
|
127
|
+
* @see {@link copyCoverArt} - Copy cover art between files
|
|
128
|
+
*/
|
|
129
|
+
export {
|
|
130
|
+
exportCoverArt,
|
|
131
|
+
exportPictureByType,
|
|
132
|
+
exportAllPictures,
|
|
133
|
+
importCoverArt,
|
|
134
|
+
importPictureWithType,
|
|
135
|
+
loadPictureFromFile,
|
|
136
|
+
savePictureToFile,
|
|
137
|
+
copyCoverArt,
|
|
138
|
+
findCoverArtFiles
|
|
139
|
+
} from "./src/file-utils.ts";
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Web browser utilities for cover art operations.
|
|
143
|
+
* @see {@link pictureToDataURL} - Convert picture to data URL
|
|
144
|
+
* @see {@link setCoverArtFromCanvas} - Set cover art from HTML canvas
|
|
145
|
+
* @see {@link displayPicture} - Display picture in HTML img element
|
|
146
|
+
*/
|
|
147
|
+
export {
|
|
148
|
+
pictureToDataURL,
|
|
149
|
+
dataURLToPicture,
|
|
150
|
+
setCoverArtFromCanvas,
|
|
151
|
+
canvasToPicture,
|
|
152
|
+
imageFileToPicture,
|
|
153
|
+
displayPicture,
|
|
154
|
+
createPictureDownloadURL,
|
|
155
|
+
createPictureGallery
|
|
156
|
+
} from "./src/web-utils.ts";
|
|
157
|
+
|
|
69
158
|
/**
|
|
70
159
|
* Type exports for TypeScript users.
|
|
71
160
|
* These types define the structure of metadata, audio properties,
|
|
@@ -83,13 +172,17 @@ export type {
|
|
|
83
172
|
FieldMapping,
|
|
84
173
|
FileType,
|
|
85
174
|
Picture,
|
|
86
|
-
PictureType,
|
|
87
175
|
PropertyMap,
|
|
88
176
|
Tag,
|
|
89
177
|
TagLibConfig,
|
|
90
178
|
TagName,
|
|
91
179
|
} from "./src/types.ts";
|
|
92
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Enum exports
|
|
183
|
+
*/
|
|
184
|
+
export { PictureType } from "./src/types.ts";
|
|
185
|
+
|
|
93
186
|
/**
|
|
94
187
|
* Wasm module types for advanced usage.
|
|
95
188
|
* @see {@link TagLibModule} - Full TagLib Wasm module interface
|
|
@@ -121,7 +214,7 @@ import type { TagLibModule } from "./src/wasm.ts";
|
|
|
121
214
|
*/
|
|
122
215
|
export async function loadTagLibModule(): Promise<TagLibModule> {
|
|
123
216
|
// Now that we're using ES6 modules, we can use dynamic import directly
|
|
124
|
-
const { default: createTagLibModule } = await import("./build/taglib.js");
|
|
217
|
+
const { default: createTagLibModule } = await import("./build/taglib-wrapper.js");
|
|
125
218
|
const module = await createTagLibModule();
|
|
126
219
|
return module as TagLibModule;
|
|
127
220
|
}
|
package/package.json
CHANGED
|
@@ -1,34 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taglib-wasm",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "TagLib
|
|
3
|
+
"version": "0.3.9",
|
|
4
|
+
"description": "TagLib for TypeScript platforms: Deno, Node.js, Bun, Electron, browsers, and Cloudflare Workers",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"types": "index.ts",
|
|
7
7
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./index.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./workers": {
|
|
13
|
+
"types": "./src/workers.ts",
|
|
14
|
+
"default": "./dist/src/workers.js"
|
|
15
|
+
},
|
|
16
|
+
"./simple": {
|
|
17
|
+
"types": "./src/simple.ts",
|
|
18
|
+
"default": "./dist/src/simple.js"
|
|
19
|
+
}
|
|
11
20
|
},
|
|
12
21
|
"files": [
|
|
13
22
|
"index.ts",
|
|
14
23
|
"src/**/*",
|
|
15
|
-
"
|
|
16
|
-
"build/taglib.js",
|
|
24
|
+
"dist/**/*",
|
|
17
25
|
"lib/taglib/COPYING*",
|
|
18
|
-
"README.md"
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE",
|
|
28
|
+
"NOTICE",
|
|
29
|
+
"CONTRIBUTING.md"
|
|
19
30
|
],
|
|
20
31
|
"scripts": {
|
|
21
32
|
"build:wasm": "./build/build-wasm.sh",
|
|
22
|
-
"build:ts": "tsc",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"test
|
|
26
|
-
"test:
|
|
27
|
-
"test:
|
|
33
|
+
"build:ts": "tsc && node scripts/build-js.js",
|
|
34
|
+
"postbuild": "node scripts/postbuild.js",
|
|
35
|
+
"build": "npm run build:wasm && npm run build:ts && npm run postbuild",
|
|
36
|
+
"test": "deno test --allow-read --allow-write tests/",
|
|
37
|
+
"test:all": "deno test --allow-read --allow-write tests/index.test.ts",
|
|
38
|
+
"test:core": "deno test --allow-read --allow-write tests/taglib.test.ts",
|
|
39
|
+
"test:pictures": "deno test --allow-read --allow-write tests/picture-api.test.ts",
|
|
40
|
+
"test:edge": "deno test --allow-read --allow-write tests/edge-cases.test.ts",
|
|
41
|
+
"test:errors": "deno test --allow-read --allow-write tests/error-handling.test.ts",
|
|
42
|
+
"test:memory": "deno test --allow-read --allow-write tests/memory.test.ts",
|
|
43
|
+
"test:extended": "deno test --allow-read --allow-write tests/extended-metadata.test.ts",
|
|
44
|
+
"test:multi-runtime": "./tests/test-runtimes.sh",
|
|
45
|
+
"test:bun": "bun test tests/index.test.ts",
|
|
46
|
+
"test:node": "node --loader ts-node/esm --test tests/index.test.ts",
|
|
47
|
+
"test:watch": "deno test --allow-read --allow-write --watch tests/",
|
|
48
|
+
"test:coverage": "deno test --allow-read --allow-write --coverage=coverage tests/ && deno coverage coverage",
|
|
28
49
|
"docs:dev": "cd docs && npm install && npm run dev",
|
|
29
50
|
"docs:build": "cd docs && npm install && npm run build",
|
|
30
51
|
"update-taglib": "./scripts/update-taglib.sh",
|
|
31
52
|
"release": "./scripts/release.sh",
|
|
53
|
+
"prepublishOnly": "npm run build:ts && npm run postbuild",
|
|
32
54
|
"publish:npm": "echo 'Use GitHub Actions workflow for publishing'",
|
|
33
55
|
"publish:github": "echo 'Use GitHub Actions workflow for publishing'"
|
|
34
56
|
},
|
|
@@ -51,12 +73,13 @@
|
|
|
51
73
|
"browser",
|
|
52
74
|
"cloudflare",
|
|
53
75
|
"workers",
|
|
76
|
+
"electron",
|
|
54
77
|
"replaygain",
|
|
55
78
|
"musicbrainz",
|
|
56
79
|
"acoustid"
|
|
57
80
|
],
|
|
58
|
-
"author": "
|
|
59
|
-
"license": "MIT",
|
|
81
|
+
"author": "Charles Wiltgen <cwiltgen@gmail.com>",
|
|
82
|
+
"license": "(MIT AND LGPL-2.1-or-later)",
|
|
60
83
|
"repository": {
|
|
61
84
|
"type": "git",
|
|
62
85
|
"url": "git+https://github.com/CharlesWiltgen/taglib-wasm.git"
|
|
@@ -71,6 +94,7 @@
|
|
|
71
94
|
"devDependencies": {
|
|
72
95
|
"@types/emscripten": "^1.39.6",
|
|
73
96
|
"@types/node": "^20.0.0",
|
|
97
|
+
"esbuild": "^0.25.5",
|
|
74
98
|
"typescript": "^5.0.0"
|
|
75
99
|
},
|
|
76
100
|
"peerDependencies": {
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for taglib-wasm with enhanced context and debugging information
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* List of audio formats supported by taglib-wasm
|
|
7
|
+
*/
|
|
8
|
+
export const SUPPORTED_FORMATS = ['MP3', 'MP4', 'M4A', 'FLAC', 'OGG', 'WAV'] as const;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Error codes for programmatic error handling
|
|
12
|
+
*/
|
|
13
|
+
export enum TagLibErrorCode {
|
|
14
|
+
INITIALIZATION_FAILED = 'INITIALIZATION_FAILED',
|
|
15
|
+
INVALID_FORMAT = 'INVALID_FORMAT',
|
|
16
|
+
UNSUPPORTED_FORMAT = 'UNSUPPORTED_FORMAT',
|
|
17
|
+
FILE_OPERATION_FAILED = 'FILE_OPERATION_FAILED',
|
|
18
|
+
METADATA_ERROR = 'METADATA_ERROR',
|
|
19
|
+
MEMORY_ERROR = 'MEMORY_ERROR',
|
|
20
|
+
ENVIRONMENT_ERROR = 'ENVIRONMENT_ERROR',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Base error class for all taglib-wasm errors
|
|
25
|
+
*/
|
|
26
|
+
export class TagLibError extends Error {
|
|
27
|
+
constructor(
|
|
28
|
+
message: string,
|
|
29
|
+
public readonly code: TagLibErrorCode,
|
|
30
|
+
public readonly context?: Record<string, unknown>
|
|
31
|
+
) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'TagLibError';
|
|
34
|
+
Object.setPrototypeOf(this, TagLibError.prototype);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Error thrown when the Wasm module fails to initialize
|
|
40
|
+
*/
|
|
41
|
+
export class TagLibInitializationError extends TagLibError {
|
|
42
|
+
constructor(message: string, context?: Record<string, unknown>) {
|
|
43
|
+
super(
|
|
44
|
+
createErrorMessage('Failed to initialize TagLib Wasm module', message),
|
|
45
|
+
TagLibErrorCode.INITIALIZATION_FAILED,
|
|
46
|
+
context
|
|
47
|
+
);
|
|
48
|
+
this.name = 'TagLibInitializationError';
|
|
49
|
+
Object.setPrototypeOf(this, TagLibInitializationError.prototype);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Error thrown when an audio file format is invalid or corrupted
|
|
55
|
+
*/
|
|
56
|
+
export class InvalidFormatError extends TagLibError {
|
|
57
|
+
constructor(
|
|
58
|
+
message: string,
|
|
59
|
+
public readonly bufferSize?: number,
|
|
60
|
+
context?: Record<string, unknown>
|
|
61
|
+
) {
|
|
62
|
+
const details = [`Invalid audio file format: ${message}`];
|
|
63
|
+
|
|
64
|
+
if (bufferSize !== undefined) {
|
|
65
|
+
details.push(`Buffer size: ${formatFileSize(bufferSize)}`);
|
|
66
|
+
if (bufferSize < 1024) {
|
|
67
|
+
details.push('Audio files must be at least 1KB to contain valid headers.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
super(
|
|
72
|
+
details.join('. '),
|
|
73
|
+
TagLibErrorCode.INVALID_FORMAT,
|
|
74
|
+
{ ...context, bufferSize }
|
|
75
|
+
);
|
|
76
|
+
this.name = 'InvalidFormatError';
|
|
77
|
+
Object.setPrototypeOf(this, InvalidFormatError.prototype);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Error thrown when an audio format is recognized but not supported
|
|
83
|
+
*/
|
|
84
|
+
export class UnsupportedFormatError extends TagLibError {
|
|
85
|
+
constructor(
|
|
86
|
+
public readonly format: string,
|
|
87
|
+
public readonly supportedFormats: readonly string[] = SUPPORTED_FORMATS,
|
|
88
|
+
context?: Record<string, unknown>
|
|
89
|
+
) {
|
|
90
|
+
super(
|
|
91
|
+
`Unsupported audio format: ${format}. Supported formats: ${supportedFormats.join(', ')}`,
|
|
92
|
+
TagLibErrorCode.UNSUPPORTED_FORMAT,
|
|
93
|
+
{ ...context, format, supportedFormats }
|
|
94
|
+
);
|
|
95
|
+
this.name = 'UnsupportedFormatError';
|
|
96
|
+
Object.setPrototypeOf(this, UnsupportedFormatError.prototype);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Error thrown during file operations (read, write, save)
|
|
102
|
+
*/
|
|
103
|
+
export class FileOperationError extends TagLibError {
|
|
104
|
+
constructor(
|
|
105
|
+
public readonly operation: 'read' | 'write' | 'save',
|
|
106
|
+
message: string,
|
|
107
|
+
public readonly path?: string,
|
|
108
|
+
context?: Record<string, unknown>
|
|
109
|
+
) {
|
|
110
|
+
const details = [`Failed to ${operation} file`];
|
|
111
|
+
if (path) {
|
|
112
|
+
details.push(`Path: ${path}`);
|
|
113
|
+
}
|
|
114
|
+
details.push(message);
|
|
115
|
+
|
|
116
|
+
super(
|
|
117
|
+
details.join('. '),
|
|
118
|
+
TagLibErrorCode.FILE_OPERATION_FAILED,
|
|
119
|
+
{ ...context, operation, path }
|
|
120
|
+
);
|
|
121
|
+
this.name = 'FileOperationError';
|
|
122
|
+
Object.setPrototypeOf(this, FileOperationError.prototype);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Error thrown when metadata operations fail
|
|
128
|
+
*/
|
|
129
|
+
export class MetadataError extends TagLibError {
|
|
130
|
+
constructor(
|
|
131
|
+
public readonly operation: 'read' | 'write',
|
|
132
|
+
message: string,
|
|
133
|
+
public readonly field?: string,
|
|
134
|
+
context?: Record<string, unknown>
|
|
135
|
+
) {
|
|
136
|
+
const details = [`Failed to ${operation} metadata`];
|
|
137
|
+
if (field) {
|
|
138
|
+
details.push(`Field: ${field}`);
|
|
139
|
+
}
|
|
140
|
+
details.push(message);
|
|
141
|
+
|
|
142
|
+
super(
|
|
143
|
+
details.join('. '),
|
|
144
|
+
TagLibErrorCode.METADATA_ERROR,
|
|
145
|
+
{ ...context, operation, field }
|
|
146
|
+
);
|
|
147
|
+
this.name = 'MetadataError';
|
|
148
|
+
Object.setPrototypeOf(this, MetadataError.prototype);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Error thrown when Wasm memory operations fail
|
|
154
|
+
*/
|
|
155
|
+
export class MemoryError extends TagLibError {
|
|
156
|
+
constructor(message: string, context?: Record<string, unknown>) {
|
|
157
|
+
super(
|
|
158
|
+
createErrorMessage('Memory allocation failed', message),
|
|
159
|
+
TagLibErrorCode.MEMORY_ERROR,
|
|
160
|
+
context
|
|
161
|
+
);
|
|
162
|
+
this.name = 'MemoryError';
|
|
163
|
+
Object.setPrototypeOf(this, MemoryError.prototype);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Error thrown when the environment doesn't support required features
|
|
169
|
+
*/
|
|
170
|
+
export class EnvironmentError extends TagLibError {
|
|
171
|
+
constructor(
|
|
172
|
+
public readonly environment: string,
|
|
173
|
+
message: string,
|
|
174
|
+
public readonly requiredFeature?: string,
|
|
175
|
+
context?: Record<string, unknown>
|
|
176
|
+
) {
|
|
177
|
+
const details = [`Environment '${environment}' ${message}`];
|
|
178
|
+
if (requiredFeature) {
|
|
179
|
+
details.push(`Required feature: ${requiredFeature}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
super(
|
|
183
|
+
details.join('. '),
|
|
184
|
+
TagLibErrorCode.ENVIRONMENT_ERROR,
|
|
185
|
+
{ ...context, environment, requiredFeature }
|
|
186
|
+
);
|
|
187
|
+
this.name = 'EnvironmentError';
|
|
188
|
+
Object.setPrototypeOf(this, EnvironmentError.prototype);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Helper function to create consistent error messages
|
|
194
|
+
*/
|
|
195
|
+
function createErrorMessage(prefix: string, details: string): string {
|
|
196
|
+
return `${prefix}: ${details}`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Format file size in human-readable format
|
|
201
|
+
*/
|
|
202
|
+
function formatFileSize(bytes: number): string {
|
|
203
|
+
if (bytes < 1024) return `${bytes} bytes`;
|
|
204
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
205
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Type guards for error handling
|
|
210
|
+
*/
|
|
211
|
+
export function isTagLibError(error: unknown): error is TagLibError {
|
|
212
|
+
return error instanceof TagLibError;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function isInvalidFormatError(error: unknown): error is InvalidFormatError {
|
|
216
|
+
return error instanceof InvalidFormatError;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function isUnsupportedFormatError(error: unknown): error is UnsupportedFormatError {
|
|
220
|
+
return error instanceof UnsupportedFormatError;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function isFileOperationError(error: unknown): error is FileOperationError {
|
|
224
|
+
return error instanceof FileOperationError;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function isMetadataError(error: unknown): error is MetadataError {
|
|
228
|
+
return error instanceof MetadataError;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function isMemoryError(error: unknown): error is MemoryError {
|
|
232
|
+
return error instanceof MemoryError;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function isEnvironmentError(error: unknown): error is EnvironmentError {
|
|
236
|
+
return error instanceof EnvironmentError;
|
|
237
|
+
}
|