taglib-wasm 0.4.0 → 0.4.2
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 +74 -4
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/src/errors.d.ts +2 -2
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/folder-api.d.ts +136 -0
- package/dist/src/folder-api.d.ts.map +1 -0
- package/dist/src/folder-api.js +242 -0
- package/dist/src/taglib.d.ts +6 -3
- package/dist/src/taglib.d.ts.map +1 -1
- package/dist/src/taglib.js +105 -9
- package/dist/src/types.d.ts +37 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/file.d.ts +20 -0
- package/dist/src/utils/file.d.ts.map +1 -1
- package/dist/src/utils/file.js +120 -1
- package/dist/src/wasm.d.ts +6 -0
- package/dist/src/wasm.d.ts.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -43,6 +43,8 @@ TagLib itself is legendary, and a core dependency of many music apps.
|
|
|
43
43
|
reliability
|
|
44
44
|
- **✅ Two API styles** – Use the “Simple” API (3 functions), or the full “Core”
|
|
45
45
|
API for more advanced applications
|
|
46
|
+
- **✅ Batch folder operations** – Scan directories, process multiple files,
|
|
47
|
+
find duplicates, and export metadata catalogs
|
|
46
48
|
|
|
47
49
|
## 📦 Installation
|
|
48
50
|
|
|
@@ -102,6 +104,10 @@ const taglib = await initializeForDenoCompile();
|
|
|
102
104
|
// deno compile --allow-read --include taglib.wasm myapp.ts
|
|
103
105
|
```
|
|
104
106
|
|
|
107
|
+
See the
|
|
108
|
+
[complete Deno compile guide](https://charleswiltgen.github.io/taglib-wasm/guide/deno-compile.html)
|
|
109
|
+
for more options including CDN loading.
|
|
110
|
+
|
|
105
111
|
For manual control:
|
|
106
112
|
|
|
107
113
|
```typescript
|
|
@@ -163,6 +169,36 @@ file.save();
|
|
|
163
169
|
file.dispose();
|
|
164
170
|
```
|
|
165
171
|
|
|
172
|
+
### Batch Folder Operations
|
|
173
|
+
|
|
174
|
+
Process entire music collections efficiently:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { findDuplicates, scanFolder } from "taglib-wasm/folder";
|
|
178
|
+
|
|
179
|
+
// Scan a music library
|
|
180
|
+
const result = await scanFolder("/path/to/music", {
|
|
181
|
+
recursive: true,
|
|
182
|
+
concurrency: 4,
|
|
183
|
+
onProgress: (processed, total, file) => {
|
|
184
|
+
console.log(`Processing ${processed}/${total}: ${file}`);
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
console.log(`Found ${result.totalFound} audio files`);
|
|
189
|
+
console.log(`Successfully processed ${result.totalProcessed} files`);
|
|
190
|
+
|
|
191
|
+
// Process results
|
|
192
|
+
for (const file of result.files) {
|
|
193
|
+
console.log(`${file.path}: ${file.tags.artist} - ${file.tags.title}`);
|
|
194
|
+
console.log(`Duration: ${file.properties?.duration}s`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Find duplicates
|
|
198
|
+
const duplicates = await findDuplicates("/path/to/music", ["artist", "title"]);
|
|
199
|
+
console.log(`Found ${duplicates.size} groups of duplicates`);
|
|
200
|
+
```
|
|
201
|
+
|
|
166
202
|
### Working with Cover Art
|
|
167
203
|
|
|
168
204
|
```typescript
|
|
@@ -216,17 +252,17 @@ Supported codec detection:
|
|
|
216
252
|
|
|
217
253
|
### Guides
|
|
218
254
|
|
|
219
|
-
- [API Reference](https://charleswiltgen.github.io/taglib-wasm/
|
|
255
|
+
- [API Reference](https://charleswiltgen.github.io/taglib-wasm/api/)
|
|
220
256
|
- [Platform Examples](https://charleswiltgen.github.io/taglib-wasm/guide/platform-examples.html)
|
|
221
257
|
- [Working with Cover Art](https://charleswiltgen.github.io/taglib-wasm/guide/cover-art.html)
|
|
222
258
|
- [Cloudflare Workers Setup](https://charleswiltgen.github.io/taglib-wasm/guide/workers-setup.html)
|
|
223
|
-
- [Error Handling](https://charleswiltgen.github.io/taglib-wasm/
|
|
259
|
+
- [Error Handling](https://charleswiltgen.github.io/taglib-wasm/concepts/error-handling.html)
|
|
224
260
|
|
|
225
261
|
### Development
|
|
226
262
|
|
|
227
263
|
- [Testing Guide](https://charleswiltgen.github.io/taglib-wasm/development/testing.html)
|
|
228
264
|
- [Future Improvements](https://charleswiltgen.github.io/taglib-wasm/development/improvements.html)
|
|
229
|
-
- [Contributing](
|
|
265
|
+
- [Contributing](CONTRIBUTING.md)
|
|
230
266
|
|
|
231
267
|
## 📋 Supported Formats
|
|
232
268
|
|
|
@@ -266,7 +302,41 @@ file.setProperty(Tags.TrackGain, "-6.54 dB");
|
|
|
266
302
|
file.setProperty(Tags.TrackPeak, "0.987654");
|
|
267
303
|
```
|
|
268
304
|
|
|
269
|
-
[View all supported tag constants →](https://charleswiltgen.github.io/taglib-wasm/
|
|
305
|
+
[View all supported tag constants →](https://charleswiltgen.github.io/taglib-wasm/api/tag-name-constants.html)
|
|
306
|
+
|
|
307
|
+
## ⚡ Performance & Smart Partial Loading
|
|
308
|
+
|
|
309
|
+
`taglib-wasm` now supports Smart Partial Loading, dramatically improving
|
|
310
|
+
performance for large audio files:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// Enable partial loading for large files (>50MB)
|
|
314
|
+
const file = await taglib.open("large-concert.flac", {
|
|
315
|
+
partial: true,
|
|
316
|
+
maxHeaderSize: 2 * 1024 * 1024, // 2MB header
|
|
317
|
+
maxFooterSize: 256 * 1024, // 256KB footer
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Read operations work normally
|
|
321
|
+
const tags = file.tag();
|
|
322
|
+
console.log(tags.title, tags.artist);
|
|
323
|
+
|
|
324
|
+
// Make multiple changes efficiently
|
|
325
|
+
tags.setTitle("Live at Madison Square Garden");
|
|
326
|
+
tags.setArtist("The Beatles");
|
|
327
|
+
tags.setAlbum("Greatest Live Performances");
|
|
328
|
+
|
|
329
|
+
// Smart save - automatically loads full file when needed
|
|
330
|
+
await file.saveToFile(); // Full file loaded only here
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Performance gains:**
|
|
334
|
+
|
|
335
|
+
- **500MB file**: ~450x less memory usage (1.1MB vs 500MB)
|
|
336
|
+
- **Initial load**: 50x faster (50ms vs 2500ms)
|
|
337
|
+
- **Memory peak**: 3.3MB instead of 1.5GB
|
|
338
|
+
|
|
339
|
+
[View performance guide →](https://charleswiltgen.github.io/taglib-wasm/concepts/performance.html)
|
|
270
340
|
|
|
271
341
|
## 🏗️ Development
|
|
272
342
|
|
package/dist/index.d.ts
CHANGED
|
@@ -79,6 +79,14 @@ export { FormatMappings, getAllTagNames, isValidTagName, Tags, } from "./src/con
|
|
|
79
79
|
* @see {@link copyCoverArt} - Copy cover art between files
|
|
80
80
|
*/
|
|
81
81
|
export { copyCoverArt, exportAllPictures, exportCoverArt, exportPictureByType, findCoverArtFiles, importCoverArt, importPictureWithType, loadPictureFromFile, savePictureToFile, } from "./src/file-utils.ts";
|
|
82
|
+
/**
|
|
83
|
+
* Folder/batch operations for processing multiple audio files.
|
|
84
|
+
* @see {@link scanFolder} - Scan folder for audio files and read metadata
|
|
85
|
+
* @see {@link updateFolderTags} - Update tags for multiple files
|
|
86
|
+
* @see {@link findDuplicates} - Find duplicate files based on metadata
|
|
87
|
+
* @see {@link exportFolderMetadata} - Export folder metadata to JSON
|
|
88
|
+
*/
|
|
89
|
+
export { type AudioFileMetadata, exportFolderMetadata, findDuplicates, type FolderScanOptions, type FolderScanResult, scanFolder, updateFolderTags, } from "./src/folder-api.ts";
|
|
82
90
|
/**
|
|
83
91
|
* Web browser utilities for cover art operations.
|
|
84
92
|
* @see {@link pictureToDataURL} - Convert picture to data URL
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;GAKG;AACH,OAAO,EACL,aAAa,IAAI,SAAS,EAC1B,YAAY,EACZ,MAAM,GACP,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,OAAO,EACL,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,oBAAoB,EACpB,WAAW,EACX,UAAU,GACX,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AACH,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,IAAI,GACL,MAAM,oBAAoB,CAAC;AAC5B;;;;;GAKG;AACH,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B;;;;;GAKG;AACH,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;GAQG;AACH,YAAY,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,WAAW,EACX,GAAG,EACH,OAAO,GACR,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;GAIG;AACH,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC;IAEtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA0BvB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;GAKG;AACH,OAAO,EACL,aAAa,IAAI,SAAS,EAC1B,YAAY,EACZ,MAAM,GACP,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,OAAO,EACL,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,oBAAoB,EACpB,WAAW,EACX,UAAU,GACX,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AACH,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,IAAI,GACL,MAAM,oBAAoB,CAAC;AAC5B;;;;;GAKG;AACH,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;GAMG;AACH,OAAO,EACL,KAAK,iBAAiB,EACtB,oBAAoB,EACpB,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,UAAU,EACV,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B;;;;;GAKG;AACH,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;GAQG;AACH,YAAY,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,WAAW,EACX,GAAG,EACH,OAAO,GACR,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;GAIG;AACH,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC;IAEtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA0BvB"}
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,12 @@ import {
|
|
|
57
57
|
loadPictureFromFile,
|
|
58
58
|
savePictureToFile
|
|
59
59
|
} from "./src/file-utils.js";
|
|
60
|
+
import {
|
|
61
|
+
exportFolderMetadata,
|
|
62
|
+
findDuplicates,
|
|
63
|
+
scanFolder,
|
|
64
|
+
updateFolderTags
|
|
65
|
+
} from "./src/folder-api.js";
|
|
60
66
|
import {
|
|
61
67
|
canvasToPicture,
|
|
62
68
|
createPictureDownloadURL,
|
|
@@ -114,8 +120,10 @@ export {
|
|
|
114
120
|
displayPicture,
|
|
115
121
|
exportAllPictures,
|
|
116
122
|
exportCoverArt,
|
|
123
|
+
exportFolderMetadata,
|
|
117
124
|
exportPictureByType,
|
|
118
125
|
findCoverArtFiles,
|
|
126
|
+
findDuplicates,
|
|
119
127
|
findPictureByType,
|
|
120
128
|
getAllTagNames,
|
|
121
129
|
getCoverArt,
|
|
@@ -141,7 +149,9 @@ export {
|
|
|
141
149
|
readTags,
|
|
142
150
|
replacePictureByType,
|
|
143
151
|
savePictureToFile,
|
|
152
|
+
scanFolder,
|
|
144
153
|
setCoverArt,
|
|
145
154
|
setCoverArtFromCanvas,
|
|
155
|
+
updateFolderTags,
|
|
146
156
|
updateTags
|
|
147
157
|
};
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -50,9 +50,9 @@ export declare class UnsupportedFormatError extends TagLibError {
|
|
|
50
50
|
* Error thrown during file operations (read, write, save)
|
|
51
51
|
*/
|
|
52
52
|
export declare class FileOperationError extends TagLibError {
|
|
53
|
-
readonly operation: "read" | "write" | "save";
|
|
53
|
+
readonly operation: "read" | "write" | "save" | "stat";
|
|
54
54
|
readonly path?: string | undefined;
|
|
55
|
-
constructor(operation: "read" | "write" | "save", message: string, path?: string | undefined, context?: Record<string, unknown>);
|
|
55
|
+
constructor(operation: "read" | "write" | "save" | "stat", message: string, path?: string | undefined, context?: Record<string, unknown>);
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* Error thrown when metadata operations fail
|
package/dist/src/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,sDAOpB,CAAC;AAEX;;GAEG;AACH,oBAAY,eAAe;IACzB,qBAAqB,0BAA0B;IAC/C,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;IACzC,qBAAqB,0BAA0B;IAC/C,cAAc,mBAAmB;IACjC,YAAY,iBAAiB;IAC7B,iBAAiB,sBAAsB;CACxC;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;aAGlB,IAAI,EAAE,eAAe;aACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAFjD,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAMpD;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,WAAW;gBAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAS/D;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,WAAW;aAG/B,UAAU,CAAC,EAAE,MAAM;gBADnC,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA,EACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAqBpC;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,WAAW;aAEnC,MAAM,EAAE,MAAM;aACd,gBAAgB,EAAE,SAAS,MAAM,EAAE;gBADnC,MAAM,EAAE,MAAM,EACd,gBAAgB,GAAE,SAAS,MAAM,EAAsB,EACvE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYpC;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,WAAW;aAE/B,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch folder operations for taglib-wasm
|
|
3
|
+
* Provides APIs for scanning directories and processing multiple audio files
|
|
4
|
+
*/
|
|
5
|
+
import { type Tag } from "./simple.ts";
|
|
6
|
+
import type { AudioProperties } from "./types.ts";
|
|
7
|
+
/**
|
|
8
|
+
* Metadata for a single audio file including path information
|
|
9
|
+
*/
|
|
10
|
+
export interface AudioFileMetadata {
|
|
11
|
+
/** Absolute or relative path to the audio file */
|
|
12
|
+
path: string;
|
|
13
|
+
/** Basic tag information (title, artist, album, etc.) */
|
|
14
|
+
tags: Tag;
|
|
15
|
+
/** Audio properties (duration, bitrate, sample rate, etc.) */
|
|
16
|
+
properties?: AudioProperties;
|
|
17
|
+
/** Any errors encountered while reading this file */
|
|
18
|
+
error?: Error;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for scanning folders
|
|
22
|
+
*/
|
|
23
|
+
export interface FolderScanOptions {
|
|
24
|
+
/** Whether to scan subdirectories recursively (default: true) */
|
|
25
|
+
recursive?: boolean;
|
|
26
|
+
/** File extensions to include (default: common audio formats) */
|
|
27
|
+
extensions?: string[];
|
|
28
|
+
/** Maximum number of files to process (default: unlimited) */
|
|
29
|
+
maxFiles?: number;
|
|
30
|
+
/** Progress callback called after each file is processed */
|
|
31
|
+
onProgress?: (processed: number, total: number, currentFile: string) => void;
|
|
32
|
+
/** Whether to include audio properties (default: true) */
|
|
33
|
+
includeProperties?: boolean;
|
|
34
|
+
/** Whether to continue on errors (default: true) */
|
|
35
|
+
continueOnError?: boolean;
|
|
36
|
+
/** Number of files to process in parallel (default: 4) */
|
|
37
|
+
concurrency?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Result of a folder scan operation
|
|
41
|
+
*/
|
|
42
|
+
export interface FolderScanResult {
|
|
43
|
+
/** Successfully processed files with metadata */
|
|
44
|
+
files: AudioFileMetadata[];
|
|
45
|
+
/** Files that failed to process */
|
|
46
|
+
errors: Array<{
|
|
47
|
+
path: string;
|
|
48
|
+
error: Error;
|
|
49
|
+
}>;
|
|
50
|
+
/** Total number of audio files found */
|
|
51
|
+
totalFound: number;
|
|
52
|
+
/** Total number of files successfully processed */
|
|
53
|
+
totalProcessed: number;
|
|
54
|
+
/** Time taken in milliseconds */
|
|
55
|
+
duration: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Scan a folder and read metadata from all audio files
|
|
59
|
+
*
|
|
60
|
+
* @param folderPath - Path to the folder to scan
|
|
61
|
+
* @param options - Scanning options
|
|
62
|
+
* @returns Metadata for all audio files found
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Scan a folder recursively
|
|
67
|
+
* const result = await scanFolder("/path/to/music");
|
|
68
|
+
* console.log(`Found ${result.totalFound} audio files`);
|
|
69
|
+
* console.log(`Successfully processed ${result.totalProcessed} files`);
|
|
70
|
+
*
|
|
71
|
+
* // Process results
|
|
72
|
+
* for (const file of result.files) {
|
|
73
|
+
* console.log(`${file.path}: ${file.tags.artist} - ${file.tags.title}`);
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* // Scan with options
|
|
77
|
+
* const result2 = await scanFolder("/path/to/music", {
|
|
78
|
+
* recursive: false,
|
|
79
|
+
* extensions: [".mp3", ".flac"],
|
|
80
|
+
* onProgress: (processed, total, file) => {
|
|
81
|
+
* console.log(`Processing ${processed}/${total}: ${file}`);
|
|
82
|
+
* }
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function scanFolder(folderPath: string, options?: FolderScanOptions): Promise<FolderScanResult>;
|
|
87
|
+
/**
|
|
88
|
+
* Update metadata for multiple files in a folder
|
|
89
|
+
*
|
|
90
|
+
* @param updates - Array of objects containing path and tags to update
|
|
91
|
+
* @param options - Update options
|
|
92
|
+
* @returns Results of the update operation
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Update multiple files
|
|
97
|
+
* const updates = [
|
|
98
|
+
* { path: "/music/song1.mp3", tags: { artist: "New Artist" } },
|
|
99
|
+
* { path: "/music/song2.mp3", tags: { album: "New Album" } }
|
|
100
|
+
* ];
|
|
101
|
+
*
|
|
102
|
+
* const result = await updateFolderTags(updates);
|
|
103
|
+
* console.log(`Updated ${result.successful} files`);
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function updateFolderTags(updates: Array<{
|
|
107
|
+
path: string;
|
|
108
|
+
tags: Partial<Tag>;
|
|
109
|
+
}>, options?: {
|
|
110
|
+
continueOnError?: boolean;
|
|
111
|
+
concurrency?: number;
|
|
112
|
+
}): Promise<{
|
|
113
|
+
successful: number;
|
|
114
|
+
failed: Array<{
|
|
115
|
+
path: string;
|
|
116
|
+
error: Error;
|
|
117
|
+
}>;
|
|
118
|
+
duration: number;
|
|
119
|
+
}>;
|
|
120
|
+
/**
|
|
121
|
+
* Find duplicate audio files based on metadata
|
|
122
|
+
*
|
|
123
|
+
* @param folderPath - Path to scan for duplicates
|
|
124
|
+
* @param criteria - Which fields to compare (default: artist and title)
|
|
125
|
+
* @returns Groups of potential duplicate files
|
|
126
|
+
*/
|
|
127
|
+
export declare function findDuplicates(folderPath: string, criteria?: Array<keyof Tag>): Promise<Map<string, AudioFileMetadata[]>>;
|
|
128
|
+
/**
|
|
129
|
+
* Export metadata from a folder to JSON
|
|
130
|
+
*
|
|
131
|
+
* @param folderPath - Path to scan
|
|
132
|
+
* @param outputPath - Where to save the JSON file
|
|
133
|
+
* @param options - Scan options
|
|
134
|
+
*/
|
|
135
|
+
export declare function exportFolderMetadata(folderPath: string, outputPath: string, options?: FolderScanOptions): Promise<void>;
|
|
136
|
+
//# sourceMappingURL=folder-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folder-api.d.ts","sourceRoot":"","sources":["../../src/folder-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAuB,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAgBlD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,EAAE,GAAG,CAAC;IACV,8DAA8D;IAC9D,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,qDAAqD;IACrD,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oDAAoD;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,mCAAmC;IACnC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IAC9C,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAsF3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,EACpD,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CA0CD;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,KAAK,CAAC,MAAM,GAAG,CAAuB,GAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC,CA4B3C;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuBf"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { TagLib } from "./taglib.js";
|
|
2
|
+
import { applyTags, readTags } from "./simple.js";
|
|
3
|
+
function join(...paths) {
|
|
4
|
+
return paths.filter((p) => p).join("/").replace(/\/+/g, "/");
|
|
5
|
+
}
|
|
6
|
+
function extname(path) {
|
|
7
|
+
const lastDot = path.lastIndexOf(".");
|
|
8
|
+
if (lastDot === -1 || lastDot === path.length - 1) return "";
|
|
9
|
+
return path.slice(lastDot);
|
|
10
|
+
}
|
|
11
|
+
const DEFAULT_AUDIO_EXTENSIONS = [
|
|
12
|
+
".mp3",
|
|
13
|
+
".m4a",
|
|
14
|
+
".mp4",
|
|
15
|
+
".flac",
|
|
16
|
+
".ogg",
|
|
17
|
+
".oga",
|
|
18
|
+
".opus",
|
|
19
|
+
".wav",
|
|
20
|
+
".wv",
|
|
21
|
+
".ape",
|
|
22
|
+
".mpc",
|
|
23
|
+
".tta",
|
|
24
|
+
".wma"
|
|
25
|
+
];
|
|
26
|
+
async function* walkDirectory(path, options = {}) {
|
|
27
|
+
const { recursive = true, extensions = DEFAULT_AUDIO_EXTENSIONS } = options;
|
|
28
|
+
if (typeof Deno !== "undefined") {
|
|
29
|
+
for await (const entry of Deno.readDir(path)) {
|
|
30
|
+
const fullPath = join(path, entry.name);
|
|
31
|
+
if (entry.isDirectory && recursive) {
|
|
32
|
+
yield* walkDirectory(fullPath, options);
|
|
33
|
+
} else if (entry.isFile) {
|
|
34
|
+
const ext = extname(entry.name).toLowerCase();
|
|
35
|
+
if (extensions.includes(ext)) {
|
|
36
|
+
yield fullPath;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} else if (typeof globalThis.process !== "undefined" && globalThis.process.versions?.node) {
|
|
41
|
+
const fs = await import("fs/promises");
|
|
42
|
+
const entries = await fs.readdir(path, { withFileTypes: true });
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const fullPath = join(path, entry.name);
|
|
45
|
+
if (entry.isDirectory() && recursive) {
|
|
46
|
+
yield* walkDirectory(fullPath, options);
|
|
47
|
+
} else if (entry.isFile()) {
|
|
48
|
+
const ext = extname(entry.name).toLowerCase();
|
|
49
|
+
if (extensions.includes(ext)) {
|
|
50
|
+
yield fullPath;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} else if (typeof globalThis.process !== "undefined" && globalThis.process.versions?.bun) {
|
|
55
|
+
const fs = await import("fs/promises");
|
|
56
|
+
const entries = await fs.readdir(path, { withFileTypes: true });
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const fullPath = join(path, entry.name);
|
|
59
|
+
if (entry.isDirectory() && recursive) {
|
|
60
|
+
yield* walkDirectory(fullPath, options);
|
|
61
|
+
} else if (entry.isFile()) {
|
|
62
|
+
const ext = extname(entry.name).toLowerCase();
|
|
63
|
+
if (extensions.includes(ext)) {
|
|
64
|
+
yield fullPath;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
throw new Error("Directory scanning not supported in this runtime");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function processBatch(files, processor, concurrency) {
|
|
73
|
+
const results = [];
|
|
74
|
+
const executing = [];
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
const promise = processor(file).then((result) => {
|
|
77
|
+
results.push(result);
|
|
78
|
+
});
|
|
79
|
+
executing.push(promise);
|
|
80
|
+
if (executing.length >= concurrency) {
|
|
81
|
+
await Promise.race(executing);
|
|
82
|
+
executing.splice(executing.findIndex((p) => p === promise), 1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await Promise.all(executing);
|
|
86
|
+
return results;
|
|
87
|
+
}
|
|
88
|
+
async function scanFolder(folderPath, options = {}) {
|
|
89
|
+
const startTime = Date.now();
|
|
90
|
+
const {
|
|
91
|
+
maxFiles = Infinity,
|
|
92
|
+
includeProperties = true,
|
|
93
|
+
continueOnError = true,
|
|
94
|
+
concurrency = 4,
|
|
95
|
+
onProgress
|
|
96
|
+
} = options;
|
|
97
|
+
const files = [];
|
|
98
|
+
const errors = [];
|
|
99
|
+
const filePaths = [];
|
|
100
|
+
let fileCount = 0;
|
|
101
|
+
for await (const filePath of walkDirectory(folderPath, options)) {
|
|
102
|
+
filePaths.push(filePath);
|
|
103
|
+
fileCount++;
|
|
104
|
+
if (fileCount >= maxFiles) break;
|
|
105
|
+
}
|
|
106
|
+
const totalFound = filePaths.length;
|
|
107
|
+
let processed = 0;
|
|
108
|
+
const taglib = await TagLib.initialize();
|
|
109
|
+
try {
|
|
110
|
+
const processor = async (filePath) => {
|
|
111
|
+
try {
|
|
112
|
+
const tags = await readTags(filePath);
|
|
113
|
+
let properties;
|
|
114
|
+
if (includeProperties) {
|
|
115
|
+
const audioFile = await taglib.open(filePath);
|
|
116
|
+
try {
|
|
117
|
+
const props = audioFile.audioProperties();
|
|
118
|
+
if (props) {
|
|
119
|
+
properties = props;
|
|
120
|
+
}
|
|
121
|
+
} finally {
|
|
122
|
+
audioFile.dispose();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
processed++;
|
|
126
|
+
onProgress?.(processed, totalFound, filePath);
|
|
127
|
+
return { path: filePath, tags, properties };
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
130
|
+
if (continueOnError) {
|
|
131
|
+
errors.push({ path: filePath, error: err });
|
|
132
|
+
processed++;
|
|
133
|
+
onProgress?.(processed, totalFound, filePath);
|
|
134
|
+
return { path: filePath, tags: {}, error: err };
|
|
135
|
+
} else {
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const batchSize = concurrency * 10;
|
|
141
|
+
for (let i = 0; i < filePaths.length; i += batchSize) {
|
|
142
|
+
const batch = filePaths.slice(
|
|
143
|
+
i,
|
|
144
|
+
Math.min(i + batchSize, filePaths.length)
|
|
145
|
+
);
|
|
146
|
+
const batchResults = await processBatch(batch, processor, concurrency);
|
|
147
|
+
files.push(...batchResults.filter((r) => !r.error));
|
|
148
|
+
}
|
|
149
|
+
} finally {
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
files,
|
|
153
|
+
errors,
|
|
154
|
+
totalFound,
|
|
155
|
+
totalProcessed: processed,
|
|
156
|
+
duration: Date.now() - startTime
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
async function updateFolderTags(updates, options = {}) {
|
|
160
|
+
const startTime = Date.now();
|
|
161
|
+
const { continueOnError = true, concurrency = 4 } = options;
|
|
162
|
+
let successful = 0;
|
|
163
|
+
const failed = [];
|
|
164
|
+
const processor = async (update) => {
|
|
165
|
+
try {
|
|
166
|
+
await applyTags(update.path, update.tags);
|
|
167
|
+
successful++;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
170
|
+
if (continueOnError) {
|
|
171
|
+
failed.push({ path: update.path, error: err });
|
|
172
|
+
} else {
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const batchSize = concurrency * 10;
|
|
178
|
+
for (let i = 0; i < updates.length; i += batchSize) {
|
|
179
|
+
const batch = updates.slice(i, Math.min(i + batchSize, updates.length));
|
|
180
|
+
await processBatch(
|
|
181
|
+
batch.map((u) => u.path),
|
|
182
|
+
async (path) => {
|
|
183
|
+
const update = batch.find((u) => u.path === path);
|
|
184
|
+
await processor(update);
|
|
185
|
+
return { path, tags: {} };
|
|
186
|
+
},
|
|
187
|
+
concurrency
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
successful,
|
|
192
|
+
failed,
|
|
193
|
+
duration: Date.now() - startTime
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
async function findDuplicates(folderPath, criteria = ["artist", "title"]) {
|
|
197
|
+
const result = await scanFolder(folderPath);
|
|
198
|
+
const duplicates = /* @__PURE__ */ new Map();
|
|
199
|
+
for (const file of result.files) {
|
|
200
|
+
const key = criteria.map((field) => file.tags[field] || "").filter((v) => v !== "").join("|");
|
|
201
|
+
if (key) {
|
|
202
|
+
const group = duplicates.get(key) || [];
|
|
203
|
+
group.push(file);
|
|
204
|
+
if (group.length > 1) {
|
|
205
|
+
duplicates.set(key, group);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const [key, files] of duplicates.entries()) {
|
|
210
|
+
if (files.length < 2) {
|
|
211
|
+
duplicates.delete(key);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return duplicates;
|
|
215
|
+
}
|
|
216
|
+
async function exportFolderMetadata(folderPath, outputPath, options) {
|
|
217
|
+
const result = await scanFolder(folderPath, options);
|
|
218
|
+
const data = {
|
|
219
|
+
folder: folderPath,
|
|
220
|
+
scanDate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
221
|
+
summary: {
|
|
222
|
+
totalFiles: result.totalFound,
|
|
223
|
+
processedFiles: result.totalProcessed,
|
|
224
|
+
errors: result.errors.length,
|
|
225
|
+
duration: result.duration
|
|
226
|
+
},
|
|
227
|
+
files: result.files,
|
|
228
|
+
errors: result.errors
|
|
229
|
+
};
|
|
230
|
+
if (typeof Deno !== "undefined") {
|
|
231
|
+
await Deno.writeTextFile(outputPath, JSON.stringify(data, null, 2));
|
|
232
|
+
} else if (typeof globalThis.process !== "undefined") {
|
|
233
|
+
const fs = await import("fs/promises");
|
|
234
|
+
await fs.writeFile(outputPath, JSON.stringify(data, null, 2));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
export {
|
|
238
|
+
exportFolderMetadata,
|
|
239
|
+
findDuplicates,
|
|
240
|
+
scanFolder,
|
|
241
|
+
updateFolderTags
|
|
242
|
+
};
|
package/dist/src/taglib.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TagLibModule, WasmModule } from "./wasm.ts";
|
|
2
|
-
import type { AudioProperties, FileType, Picture, PropertyMap, Tag as BasicTag } from "./types.ts";
|
|
2
|
+
import type { AudioProperties, FileType, OpenOptions, Picture, PropertyMap, Tag as BasicTag } from "./types.ts";
|
|
3
3
|
/**
|
|
4
4
|
* Extended Tag interface with read/write capabilities for audio metadata.
|
|
5
5
|
* Extends the basic Tag interface with setter methods for modifying metadata.
|
|
@@ -291,7 +291,10 @@ export declare class AudioFileImpl implements AudioFile {
|
|
|
291
291
|
private cachedTag;
|
|
292
292
|
private cachedAudioProperties;
|
|
293
293
|
private sourcePath?;
|
|
294
|
-
|
|
294
|
+
private originalSource?;
|
|
295
|
+
private isPartiallyLoaded;
|
|
296
|
+
private partialLoadOptions?;
|
|
297
|
+
constructor(module: TagLibModule, fileHandle: any, sourcePath?: string, originalSource?: string | File | ArrayBuffer | Uint8Array, isPartiallyLoaded?: boolean, partialLoadOptions?: OpenOptions);
|
|
295
298
|
/** @inheritdoc */
|
|
296
299
|
getFormat(): FileType;
|
|
297
300
|
/** @inheritdoc */
|
|
@@ -448,7 +451,7 @@ export declare class TagLib {
|
|
|
448
451
|
* file.dispose();
|
|
449
452
|
* ```
|
|
450
453
|
*/
|
|
451
|
-
open(input: string | ArrayBuffer | Uint8Array | File): Promise<AudioFile>;
|
|
454
|
+
open(input: string | ArrayBuffer | Uint8Array | File, options?: OpenOptions): Promise<AudioFile>;
|
|
452
455
|
/**
|
|
453
456
|
* Update tags in a file and save changes to disk in one operation.
|
|
454
457
|
* This is a convenience method that opens, modifies, saves, and closes the file.
|
package/dist/src/taglib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"taglib.d.ts","sourceRoot":"","sources":["../../src/taglib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,OAAO,EACP,WAAW,EACX,GAAG,IAAI,QAAQ,EAChB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"taglib.d.ts","sourceRoot":"","sources":["../../src/taglib.ts"],"names":[],"mappings":"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"}
|
package/dist/src/taglib.js
CHANGED
|
@@ -4,15 +4,23 @@ import {
|
|
|
4
4
|
TagLibInitializationError,
|
|
5
5
|
UnsupportedFormatError
|
|
6
6
|
} from "./errors.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
getFileSize,
|
|
9
|
+
readFileData,
|
|
10
|
+
readPartialFileData
|
|
11
|
+
} from "./utils/file.js";
|
|
8
12
|
import { writeFileData } from "./utils/write.js";
|
|
9
13
|
class AudioFileImpl {
|
|
10
|
-
constructor(module, fileHandle, sourcePath) {
|
|
14
|
+
constructor(module, fileHandle, sourcePath, originalSource, isPartiallyLoaded = false, partialLoadOptions) {
|
|
11
15
|
this.module = module;
|
|
12
16
|
this.cachedTag = null;
|
|
13
17
|
this.cachedAudioProperties = null;
|
|
18
|
+
this.isPartiallyLoaded = false;
|
|
14
19
|
this.fileHandle = fileHandle;
|
|
15
20
|
this.sourcePath = sourcePath;
|
|
21
|
+
this.originalSource = originalSource;
|
|
22
|
+
this.isPartiallyLoaded = isPartiallyLoaded;
|
|
23
|
+
this.partialLoadOptions = partialLoadOptions;
|
|
16
24
|
}
|
|
17
25
|
/** @inheritdoc */
|
|
18
26
|
getFormat() {
|
|
@@ -126,6 +134,11 @@ class AudioFileImpl {
|
|
|
126
134
|
}
|
|
127
135
|
/** @inheritdoc */
|
|
128
136
|
save() {
|
|
137
|
+
if (this.isPartiallyLoaded && this.originalSource) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
"Cannot save partially loaded file directly. Use saveToFile() instead, which will automatically load the full file."
|
|
140
|
+
);
|
|
141
|
+
}
|
|
129
142
|
this.cachedTag = null;
|
|
130
143
|
this.cachedAudioProperties = null;
|
|
131
144
|
return this.fileHandle.save();
|
|
@@ -146,11 +159,47 @@ class AudioFileImpl {
|
|
|
146
159
|
"No file path available. Either provide a path or open the file from a path."
|
|
147
160
|
);
|
|
148
161
|
}
|
|
149
|
-
if (
|
|
150
|
-
|
|
162
|
+
if (this.isPartiallyLoaded && this.originalSource) {
|
|
163
|
+
const fullData = await readFileData(this.originalSource);
|
|
164
|
+
const fullFileHandle = this.module.createFileHandle();
|
|
165
|
+
const success = fullFileHandle.loadFromBuffer(fullData);
|
|
166
|
+
if (!success) {
|
|
167
|
+
throw new InvalidFormatError(
|
|
168
|
+
"Failed to load full audio file for saving",
|
|
169
|
+
fullData.byteLength
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
const partialTag = this.fileHandle.getTag();
|
|
173
|
+
const fullTag = fullFileHandle.getTag();
|
|
174
|
+
if (partialTag && fullTag) {
|
|
175
|
+
fullTag.setTitle(partialTag.title());
|
|
176
|
+
fullTag.setArtist(partialTag.artist());
|
|
177
|
+
fullTag.setAlbum(partialTag.album());
|
|
178
|
+
fullTag.setComment(partialTag.comment());
|
|
179
|
+
fullTag.setGenre(partialTag.genre());
|
|
180
|
+
fullTag.setYear(partialTag.year());
|
|
181
|
+
fullTag.setTrack(partialTag.track());
|
|
182
|
+
}
|
|
183
|
+
const properties = this.fileHandle.getProperties();
|
|
184
|
+
fullFileHandle.setProperties(properties);
|
|
185
|
+
const pictures = this.fileHandle.getPictures();
|
|
186
|
+
fullFileHandle.setPictures(pictures);
|
|
187
|
+
if (!fullFileHandle.save()) {
|
|
188
|
+
fullFileHandle.destroy();
|
|
189
|
+
throw new Error("Failed to save changes to full file");
|
|
190
|
+
}
|
|
191
|
+
const buffer = fullFileHandle.getBuffer();
|
|
192
|
+
fullFileHandle.destroy();
|
|
193
|
+
await writeFileData(targetPath, buffer);
|
|
194
|
+
this.isPartiallyLoaded = false;
|
|
195
|
+
this.originalSource = void 0;
|
|
196
|
+
} else {
|
|
197
|
+
if (!this.save()) {
|
|
198
|
+
throw new Error("Failed to save changes to in-memory buffer");
|
|
199
|
+
}
|
|
200
|
+
const buffer = this.getFileBuffer();
|
|
201
|
+
await writeFileData(targetPath, buffer);
|
|
151
202
|
}
|
|
152
|
-
const buffer = this.getFileBuffer();
|
|
153
|
-
await writeFileData(targetPath, buffer);
|
|
154
203
|
}
|
|
155
204
|
/** @inheritdoc */
|
|
156
205
|
isValid() {
|
|
@@ -361,14 +410,53 @@ class TagLib {
|
|
|
361
410
|
* file.dispose();
|
|
362
411
|
* ```
|
|
363
412
|
*/
|
|
364
|
-
async open(input) {
|
|
413
|
+
async open(input, options) {
|
|
365
414
|
if (!this.module.createFileHandle) {
|
|
366
415
|
throw new TagLibInitializationError(
|
|
367
416
|
"TagLib module not properly initialized: createFileHandle not found. Make sure the module is fully loaded before calling open."
|
|
368
417
|
);
|
|
369
418
|
}
|
|
370
419
|
const sourcePath = typeof input === "string" ? input : void 0;
|
|
371
|
-
const
|
|
420
|
+
const opts = {
|
|
421
|
+
partial: false,
|
|
422
|
+
maxHeaderSize: 1024 * 1024,
|
|
423
|
+
// 1MB
|
|
424
|
+
maxFooterSize: 128 * 1024,
|
|
425
|
+
// 128KB
|
|
426
|
+
...options
|
|
427
|
+
};
|
|
428
|
+
let audioData;
|
|
429
|
+
let isPartiallyLoaded = false;
|
|
430
|
+
if (opts.partial && typeof File !== "undefined" && input instanceof File) {
|
|
431
|
+
const headerSize = Math.min(opts.maxHeaderSize, input.size);
|
|
432
|
+
const footerSize = Math.min(opts.maxFooterSize, input.size);
|
|
433
|
+
if (input.size <= headerSize + footerSize) {
|
|
434
|
+
audioData = await readFileData(input);
|
|
435
|
+
} else {
|
|
436
|
+
const header = await input.slice(0, headerSize).arrayBuffer();
|
|
437
|
+
const footerStart = Math.max(0, input.size - footerSize);
|
|
438
|
+
const footer = await input.slice(footerStart).arrayBuffer();
|
|
439
|
+
const combined = new Uint8Array(header.byteLength + footer.byteLength);
|
|
440
|
+
combined.set(new Uint8Array(header), 0);
|
|
441
|
+
combined.set(new Uint8Array(footer), header.byteLength);
|
|
442
|
+
audioData = combined;
|
|
443
|
+
isPartiallyLoaded = true;
|
|
444
|
+
}
|
|
445
|
+
} else if (opts.partial && typeof input === "string") {
|
|
446
|
+
const fileSize = await getFileSize(input);
|
|
447
|
+
if (fileSize > opts.maxHeaderSize + opts.maxFooterSize) {
|
|
448
|
+
audioData = await readPartialFileData(
|
|
449
|
+
input,
|
|
450
|
+
opts.maxHeaderSize,
|
|
451
|
+
opts.maxFooterSize
|
|
452
|
+
);
|
|
453
|
+
isPartiallyLoaded = true;
|
|
454
|
+
} else {
|
|
455
|
+
audioData = await readFileData(input);
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
audioData = await readFileData(input);
|
|
459
|
+
}
|
|
372
460
|
const buffer = audioData.buffer.slice(
|
|
373
461
|
audioData.byteOffset,
|
|
374
462
|
audioData.byteOffset + audioData.byteLength
|
|
@@ -382,7 +470,15 @@ class TagLib {
|
|
|
382
470
|
buffer.byteLength
|
|
383
471
|
);
|
|
384
472
|
}
|
|
385
|
-
return new AudioFileImpl(
|
|
473
|
+
return new AudioFileImpl(
|
|
474
|
+
this.module,
|
|
475
|
+
fileHandle,
|
|
476
|
+
sourcePath,
|
|
477
|
+
input,
|
|
478
|
+
// Store original source for lazy loading
|
|
479
|
+
isPartiallyLoaded,
|
|
480
|
+
opts
|
|
481
|
+
);
|
|
386
482
|
}
|
|
387
483
|
/**
|
|
388
484
|
* Update tags in a file and save changes to disk in one operation.
|
package/dist/src/types.d.ts
CHANGED
|
@@ -328,4 +328,41 @@ export interface TagLibWorkersConfig {
|
|
|
328
328
|
/** Enable debug output */
|
|
329
329
|
debug?: boolean;
|
|
330
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Options for opening audio files with partial loading support.
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* ```typescript
|
|
336
|
+
* // Enable partial loading for large files
|
|
337
|
+
* const file = await taglib.open(largeFile, {
|
|
338
|
+
* partial: true,
|
|
339
|
+
* maxHeaderSize: 2 * 1024 * 1024, // 2MB
|
|
340
|
+
* maxFooterSize: 256 * 1024 // 256KB
|
|
341
|
+
* });
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
export interface OpenOptions {
|
|
345
|
+
/**
|
|
346
|
+
* Enable partial file loading for better performance with large files.
|
|
347
|
+
* When enabled, only the header and footer sections are loaded initially.
|
|
348
|
+
* The full file is loaded automatically when save() is called.
|
|
349
|
+
*
|
|
350
|
+
* @default false
|
|
351
|
+
*/
|
|
352
|
+
partial?: boolean;
|
|
353
|
+
/**
|
|
354
|
+
* Maximum size of the header section to load (in bytes).
|
|
355
|
+
* This should be large enough to contain all metadata at the beginning of the file.
|
|
356
|
+
*
|
|
357
|
+
* @default 1048576 (1MB)
|
|
358
|
+
*/
|
|
359
|
+
maxHeaderSize?: number;
|
|
360
|
+
/**
|
|
361
|
+
* Maximum size of the footer section to load (in bytes).
|
|
362
|
+
* This should be large enough to contain metadata at the end of the file (e.g., ID3v1 tags).
|
|
363
|
+
*
|
|
364
|
+
* @default 131072 (128KB)
|
|
365
|
+
*/
|
|
366
|
+
maxFooterSize?: number;
|
|
367
|
+
}
|
|
331
368
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/src/utils/file.d.ts
CHANGED
|
@@ -12,4 +12,24 @@
|
|
|
12
12
|
* @throws {EnvironmentError} If environment doesn't support file paths
|
|
13
13
|
*/
|
|
14
14
|
export declare function readFileData(file: string | Uint8Array | ArrayBuffer | File): Promise<Uint8Array>;
|
|
15
|
+
/**
|
|
16
|
+
* Get the size of a file without reading its contents.
|
|
17
|
+
*
|
|
18
|
+
* @param path - File path
|
|
19
|
+
* @returns Promise resolving to file size in bytes
|
|
20
|
+
* @throws {FileOperationError} If file stat fails
|
|
21
|
+
* @throws {EnvironmentError} If environment doesn't support file paths
|
|
22
|
+
*/
|
|
23
|
+
export declare function getFileSize(path: string): Promise<number>;
|
|
24
|
+
/**
|
|
25
|
+
* Read partial file data (header and footer sections).
|
|
26
|
+
*
|
|
27
|
+
* @param path - File path
|
|
28
|
+
* @param headerSize - Size of header section to read
|
|
29
|
+
* @param footerSize - Size of footer section to read
|
|
30
|
+
* @returns Promise resolving to combined header and footer data
|
|
31
|
+
* @throws {FileOperationError} If file read fails
|
|
32
|
+
* @throws {EnvironmentError} If environment doesn't support file paths
|
|
33
|
+
*/
|
|
34
|
+
export declare function readPartialFileData(path: string, headerSize: number, footerSize: number): Promise<Uint8Array>;
|
|
15
35
|
//# sourceMappingURL=file.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/utils/file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,GAC7C,OAAO,CAAC,UAAU,CAAC,CAmErB"}
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/utils/file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,GAC7C,OAAO,CAAC,UAAU,CAAC,CAmErB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgD/D;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC,CA4GrB"}
|
package/dist/src/utils/file.js
CHANGED
|
@@ -47,6 +47,125 @@ async function readFileData(file) {
|
|
|
47
47
|
`Invalid file input type: ${inputType}. Expected string path, Uint8Array, ArrayBuffer, or File object.`
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
|
+
async function getFileSize(path) {
|
|
51
|
+
const hasDeno = typeof globalThis.Deno !== "undefined";
|
|
52
|
+
const hasNode = typeof globalThis.process !== "undefined" && globalThis.process.versions && globalThis.process.versions.node;
|
|
53
|
+
const hasBun = typeof globalThis.Bun !== "undefined";
|
|
54
|
+
if (!hasDeno && !hasNode && !hasBun) {
|
|
55
|
+
throw new EnvironmentError(
|
|
56
|
+
"Browser",
|
|
57
|
+
"does not support file path operations",
|
|
58
|
+
"filesystem access"
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
if (hasDeno) {
|
|
63
|
+
const stat = await globalThis.Deno.stat(path);
|
|
64
|
+
return stat.size;
|
|
65
|
+
}
|
|
66
|
+
if (hasNode) {
|
|
67
|
+
const { stat } = await import("fs/promises");
|
|
68
|
+
const stats = await stat(path);
|
|
69
|
+
return stats.size;
|
|
70
|
+
}
|
|
71
|
+
if (hasBun) {
|
|
72
|
+
const bunFile = globalThis.Bun.file(path);
|
|
73
|
+
return bunFile.size;
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new FileOperationError(
|
|
77
|
+
"stat",
|
|
78
|
+
error.message,
|
|
79
|
+
path
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
throw new EnvironmentError(
|
|
83
|
+
"Unknown",
|
|
84
|
+
"No runtime detected",
|
|
85
|
+
"filesystem access"
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
async function readPartialFileData(path, headerSize, footerSize) {
|
|
89
|
+
const hasDeno = typeof globalThis.Deno !== "undefined";
|
|
90
|
+
const hasNode = typeof globalThis.process !== "undefined" && globalThis.process.versions && globalThis.process.versions.node;
|
|
91
|
+
if (!hasDeno && !hasNode) {
|
|
92
|
+
throw new EnvironmentError(
|
|
93
|
+
"Browser/Bun",
|
|
94
|
+
"does not support partial file reading",
|
|
95
|
+
"filesystem access with seek support"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
if (hasDeno) {
|
|
100
|
+
const file = await globalThis.Deno.open(path, { read: true });
|
|
101
|
+
try {
|
|
102
|
+
const stat = await file.stat();
|
|
103
|
+
const fileSize = stat.size;
|
|
104
|
+
const actualHeaderSize = Math.min(headerSize, fileSize);
|
|
105
|
+
const header = new Uint8Array(actualHeaderSize);
|
|
106
|
+
await file.read(header);
|
|
107
|
+
const actualFooterSize = Math.min(footerSize, fileSize);
|
|
108
|
+
const footerStart = Math.max(0, fileSize - actualFooterSize);
|
|
109
|
+
if (footerStart <= actualHeaderSize) {
|
|
110
|
+
return header.slice(0, fileSize);
|
|
111
|
+
}
|
|
112
|
+
await file.seek(footerStart, globalThis.Deno.SeekMode.Start);
|
|
113
|
+
const footer = new Uint8Array(actualFooterSize);
|
|
114
|
+
await file.read(footer);
|
|
115
|
+
const combined = new Uint8Array(actualHeaderSize + actualFooterSize);
|
|
116
|
+
combined.set(header, 0);
|
|
117
|
+
combined.set(footer, actualHeaderSize);
|
|
118
|
+
return combined;
|
|
119
|
+
} finally {
|
|
120
|
+
file.close();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (hasNode) {
|
|
124
|
+
const { open } = await import("fs/promises");
|
|
125
|
+
const file = await open(path, "r");
|
|
126
|
+
try {
|
|
127
|
+
const stats = await file.stat();
|
|
128
|
+
const fileSize = stats.size;
|
|
129
|
+
const actualHeaderSize = Math.min(headerSize, fileSize);
|
|
130
|
+
const { Buffer } = await import("buffer");
|
|
131
|
+
const header = Buffer.alloc(actualHeaderSize);
|
|
132
|
+
await file.read(header, 0, actualHeaderSize, 0);
|
|
133
|
+
const actualFooterSize = Math.min(footerSize, fileSize);
|
|
134
|
+
const footerStart = Math.max(0, fileSize - actualFooterSize);
|
|
135
|
+
if (footerStart <= actualHeaderSize) {
|
|
136
|
+
return new Uint8Array(header.buffer, 0, fileSize);
|
|
137
|
+
}
|
|
138
|
+
const footer = Buffer.alloc(actualFooterSize);
|
|
139
|
+
await file.read(footer, 0, actualFooterSize, footerStart);
|
|
140
|
+
const combined = new Uint8Array(actualHeaderSize + actualFooterSize);
|
|
141
|
+
combined.set(
|
|
142
|
+
new Uint8Array(header.buffer, header.byteOffset, header.byteLength),
|
|
143
|
+
0
|
|
144
|
+
);
|
|
145
|
+
combined.set(
|
|
146
|
+
new Uint8Array(footer.buffer, footer.byteOffset, footer.byteLength),
|
|
147
|
+
actualHeaderSize
|
|
148
|
+
);
|
|
149
|
+
return combined;
|
|
150
|
+
} finally {
|
|
151
|
+
await file.close();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
} catch (error) {
|
|
155
|
+
throw new FileOperationError(
|
|
156
|
+
"read",
|
|
157
|
+
error.message,
|
|
158
|
+
path
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
throw new EnvironmentError(
|
|
162
|
+
"Unknown",
|
|
163
|
+
"No runtime detected",
|
|
164
|
+
"filesystem access"
|
|
165
|
+
);
|
|
166
|
+
}
|
|
50
167
|
export {
|
|
51
|
-
|
|
168
|
+
getFileSize,
|
|
169
|
+
readFileData,
|
|
170
|
+
readPartialFileData
|
|
52
171
|
};
|
package/dist/src/wasm.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ export interface FileHandle {
|
|
|
35
35
|
removeMP4Item(key: string): void;
|
|
36
36
|
getTag(): TagWrapper;
|
|
37
37
|
getAudioProperties(): AudioPropertiesWrapper;
|
|
38
|
+
getBuffer(): Uint8Array;
|
|
39
|
+
getPictures(): any[];
|
|
40
|
+
setPictures(pictures: any[]): void;
|
|
41
|
+
addPicture(picture: any): void;
|
|
42
|
+
removePictures(): void;
|
|
43
|
+
destroy(): void;
|
|
38
44
|
}
|
|
39
45
|
export interface TagWrapper {
|
|
40
46
|
title(): string;
|
package/dist/src/wasm.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../../src/wasm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,gBAAgB;IAE/B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,YAAY,CAAC;IAGtB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,KAAK,CAAC,CACJ,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,EAAE,GAAG,EAAE,GACV,GAAG,CAAC;IACP,KAAK,CAAC,CACJ,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,GACjB,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IAG3B,EAAE,CAAC,EAAE,GAAG,CAAC;IAGT,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1D,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC;AAGD,MAAM,WAAW,UAAU;IACzB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAC1C,OAAO,IAAI,OAAO,CAAC;IACnB,IAAI,IAAI,OAAO,CAAC;IAChB,SAAS,IAAI,MAAM,CAAC;IACpB,aAAa,IAAI,GAAG,CAAC;IACrB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,KAAK,IAAI,OAAO,CAAC;IACjB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,IAAI,UAAU,CAAC;IACrB,kBAAkB,IAAI,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../../src/wasm.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taglib-wasm",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "TagLib for TypeScript platforms: Deno, Node.js, Bun, Electron, browsers, and Cloudflare Workers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"./simple": {
|
|
17
17
|
"types": "./dist/src/simple.d.ts",
|
|
18
18
|
"default": "./dist/src/simple.js"
|
|
19
|
+
},
|
|
20
|
+
"./folder": {
|
|
21
|
+
"types": "./dist/src/folder-api.d.ts",
|
|
22
|
+
"default": "./dist/src/folder-api.js"
|
|
19
23
|
}
|
|
20
24
|
},
|
|
21
25
|
"files": [
|