taglib-wasm 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +197 -16
  3. package/dist/index.browser.d.ts +24 -4
  4. package/dist/index.browser.d.ts.map +1 -1
  5. package/dist/index.browser.js +1139 -217
  6. package/dist/index.d.ts +3 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/simple.browser.js +539 -209
  10. package/dist/src/constants/properties.d.ts +2 -2
  11. package/dist/src/constants/specialized-properties.d.ts +2 -2
  12. package/dist/src/constants/specialized-properties.js +2 -2
  13. package/dist/src/errors/base.d.ts +17 -2
  14. package/dist/src/errors/base.d.ts.map +1 -1
  15. package/dist/src/errors/base.js +18 -0
  16. package/dist/src/runtime/detector.d.ts +16 -1
  17. package/dist/src/runtime/detector.d.ts.map +1 -1
  18. package/dist/src/runtime/detector.js +58 -52
  19. package/dist/src/runtime/platform-io.d.ts +8 -0
  20. package/dist/src/runtime/platform-io.d.ts.map +1 -1
  21. package/dist/src/runtime/platform-io.js +11 -11
  22. package/dist/src/runtime/unified-loader/module-selection.d.ts +2 -2
  23. package/dist/src/runtime/unified-loader/module-selection.d.ts.map +1 -1
  24. package/dist/src/runtime/unified-loader/module-selection.js +3 -5
  25. package/dist/src/runtime/wasi-adapter/adapter.d.ts +13 -1
  26. package/dist/src/runtime/wasi-adapter/adapter.d.ts.map +1 -1
  27. package/dist/src/runtime/wasi-adapter/adapter.js +17 -0
  28. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts +4 -1
  29. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts.map +1 -1
  30. package/dist/src/runtime/wasi-adapter/audio-properties.js +24 -6
  31. package/dist/src/runtime/wasi-adapter/path-open.d.ts +68 -0
  32. package/dist/src/runtime/wasi-adapter/path-open.d.ts.map +1 -0
  33. package/dist/src/runtime/wasi-adapter/path-open.js +76 -0
  34. package/dist/src/runtime/wasi-adapter/wasm-io.d.ts.map +1 -1
  35. package/dist/src/runtime/wasi-adapter/wasm-io.js +36 -28
  36. package/dist/src/runtime/wasi-host-loader.js +8 -3
  37. package/dist/src/runtime/wasmer-sdk-loader/types.d.ts +13 -0
  38. package/dist/src/runtime/wasmer-sdk-loader/types.d.ts.map +1 -1
  39. package/dist/src/simple/checksum-operations.d.ts +25 -0
  40. package/dist/src/simple/checksum-operations.d.ts.map +1 -0
  41. package/dist/src/simple/checksum-operations.js +7 -0
  42. package/dist/src/simple/index.d.ts +2 -0
  43. package/dist/src/simple/index.d.ts.map +1 -1
  44. package/dist/src/simple/index.js +2 -0
  45. package/dist/src/taglib/audio-file-checksum.d.ts +47 -0
  46. package/dist/src/taglib/audio-file-checksum.d.ts.map +1 -0
  47. package/dist/src/taglib/audio-file-checksum.js +77 -0
  48. package/dist/src/taglib/audio-file-impl.d.ts +4 -0
  49. package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
  50. package/dist/src/taglib/audio-file-impl.js +34 -2
  51. package/dist/src/taglib/audio-file-interface.d.ts +17 -0
  52. package/dist/src/taglib/audio-file-interface.d.ts.map +1 -1
  53. package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
  54. package/dist/src/taglib/embind-adapter.js +4 -1
  55. package/dist/src/taglib/id3v2-frames.d.ts.map +1 -1
  56. package/dist/src/taglib/id3v2-frames.js +2 -2
  57. package/dist/src/taglib/media-ranges.d.ts +85 -0
  58. package/dist/src/taglib/media-ranges.d.ts.map +1 -0
  59. package/dist/src/taglib/media-ranges.js +192 -0
  60. package/dist/src/taglib/metadata-extent.d.ts +55 -0
  61. package/dist/src/taglib/metadata-extent.d.ts.map +1 -1
  62. package/dist/src/taglib/metadata-extent.js +24 -6
  63. package/dist/src/taglib/taglib-class.d.ts.map +1 -1
  64. package/dist/src/taglib/taglib-class.js +13 -24
  65. package/dist/src/types/audio-formats.d.ts +5 -5
  66. package/dist/src/types/audio-formats.d.ts.map +1 -1
  67. package/dist/src/types/format-property-keys.d.ts +1 -1
  68. package/dist/src/types/format-property-keys.d.ts.map +1 -1
  69. package/dist/src/types/tags.d.ts +8 -1
  70. package/dist/src/types/tags.d.ts.map +1 -1
  71. package/dist/src/utils/path.d.ts +12 -0
  72. package/dist/src/utils/path.d.ts.map +1 -1
  73. package/dist/src/utils/path.js +19 -0
  74. package/dist/src/utils/tag-mapping.d.ts.map +1 -1
  75. package/dist/src/utils/tag-mapping.js +2 -0
  76. package/dist/src/version.d.ts +1 -1
  77. package/dist/src/version.js +1 -1
  78. package/dist/src/wasm.d.ts +9 -0
  79. package/dist/src/wasm.d.ts.map +1 -1
  80. package/dist/src/web-utils/data-url.d.ts.map +1 -1
  81. package/dist/src/web-utils/data-url.js +4 -2
  82. package/dist/taglib-wasi.wasm +0 -0
  83. package/dist/taglib-web.wasm +0 -0
  84. package/dist/web.browser.d.ts +13 -0
  85. package/dist/web.browser.d.ts.map +1 -0
  86. package/dist/web.browser.js +3630 -0
  87. package/package.json +19 -17
package/LICENSE CHANGED
@@ -42,7 +42,7 @@ The WebAssembly binaries are subject to LGPL requirements. This means:
42
42
  To rebuild the WebAssembly binaries with a modified TagLib:
43
43
  1. Modify the TagLib source in lib/taglib/
44
44
  2. Run: npm run build:wasm (builds both backends; requires the
45
- Emscripten SDK and WASI SDK 33 — see CONTRIBUTING.md)
45
+ Emscripten SDK and WASI SDK 34 — see CONTRIBUTING.md)
46
46
  3. The new binaries will be in build/taglib-web.wasm and
47
47
  build/taglib-wasi.wasm
48
48
 
package/README.md CHANGED
@@ -37,9 +37,10 @@ TagLib-Wasm is the **universal tagging library for TypeScript/JavaScript**
37
37
  zero-padded `"03"` is preserved, and MP4 freeform atoms keep their exact
38
38
  casing and vendor `mean`, so other tools still recognise them
39
39
  - **Zero dependencies** – Self-contained Wasm bundle
40
- - **Tested** – 448 tests across all formats, with cross-backend parity coverage
41
- - **Two API styles** – Use the "Simple" API (3 functions), or the full "Core"
42
- API for more advanced applications
40
+ - **Tested** – Cross-backend parity coverage across the supported formats
41
+ - **Two API styles** – Use the "Simple" API for one-shot reads and writes, batch
42
+ helpers, cover art, and checksums, or the full "Core" API for more advanced
43
+ applications
43
44
  - **Batch folder operations** – Scan directories, process multiple files, find
44
45
  duplicates, and export metadata catalogs
45
46
 
@@ -107,6 +108,14 @@ See the
107
108
  [complete Deno compile guide](https://charleswiltgen.github.io/TagLib-Wasm/guide/deno-compile.html)
108
109
  for more options including CDN loading.
109
110
 
111
+ `prepareWasmForEmbedding` and `initializeForDenoCompile` resolve a Deno main
112
+ module and file paths, so they belong to the Node/Deno entry: they are absent
113
+ from the `browser` condition, and a browser-targeted build reports them as
114
+ missing exports — the section below, "Bundle Size and Tree-Shaking", shows how
115
+ to get that as a TypeScript error instead of a bundler error. `isDenoCompiled`,
116
+ the `typeof Deno` probe under them, is exported by both: in a browser it answers
117
+ `false`.
118
+
110
119
  For manual control:
111
120
 
112
121
  ```typescript
@@ -248,6 +257,16 @@ Wasm-free — import them from the dedicated subpath in browser/UI contexts
248
257
  import { discFolderInfo, groupAlbums } from "taglib-wasm/disc-folder";
249
258
  ```
250
259
 
260
+ `scanFolder`, `scanForAlbums`, `findDuplicates` and `exportFolderMetadata` read
261
+ and write a filesystem, so they are **Node/Deno/Bun-only**, and so is the
262
+ `taglib-wasm/folder` subpath that exports them: it declares no `browser`
263
+ `exports` condition, which makes a browser-targeted build fail loudly (esbuild:
264
+ `Could not resolve "node:fs/promises"`). That failure is deliberate — a browser
265
+ stub that threw at runtime would move the same mistake from build time to the
266
+ first call in production. In a browser, scan on a server and post the result:
267
+ `groupAlbums` and `discFolderInfo` are exported from both `taglib-wasm` and
268
+ `taglib-wasm/disc-folder` and run anywhere.
269
+
251
270
  ### Working with Cover Art
252
271
 
253
272
  ```typescript
@@ -386,7 +405,7 @@ import { readProperties } from "taglib-wasm/simple";
386
405
  const props = await readProperties("song.m4a");
387
406
 
388
407
  console.log(props.containerFormat); // "MP4" (container format)
389
- console.log(props.codec); // "AAC" or "ALAC" (compressed media format)
408
+ console.log(props.codec); // "AAC", "ALAC", "AC-3", … (compressed media format)
390
409
  console.log(props.isLossless); // false for AAC, true for ALAC
391
410
  console.log(props.bitsPerSample); // 16 for most formats
392
411
  console.log(props.bitrate); // 256 (kbps)
@@ -407,7 +426,7 @@ Container format vs Codec:
407
426
 
408
427
  Supported formats:
409
428
 
410
- - **MP4 container** (.mp4, .m4a) – Can contain AAC (lossy) or ALAC (lossless)
429
+ - **MP4 container** (.mp4, .m4a) – Can contain AAC, ALAC, AC-3, E-AC-3, DTS, FLAC, or Opus
411
430
  - **OGG container** (.ogg) – Can contain Vorbis, Opus, FLAC, or Speex
412
431
  - **MP3** – Both container and codec (lossy)
413
432
  - **FLAC** – Both container and codec (lossless)
@@ -427,8 +446,16 @@ Supported formats:
427
446
  ### Guides
428
447
 
429
448
  - [API Reference](https://charleswiltgen.github.io/TagLib-Wasm/api/)
449
+ - [Folder API](https://charleswiltgen.github.io/TagLib-Wasm/api/folder-api.html)
450
+ - [Property Map](https://charleswiltgen.github.io/TagLib-Wasm/api/property-map.html)
451
+ - [Tag Name Constants](https://charleswiltgen.github.io/TagLib-Wasm/api/tag-constants.html)
430
452
  - [Performance Guide](https://charleswiltgen.github.io/TagLib-Wasm/concepts/performance.html)
453
+ - [Memory Management](https://charleswiltgen.github.io/TagLib-Wasm/concepts/memory-management.html)
454
+ - [Runtime Compatibility](https://charleswiltgen.github.io/TagLib-Wasm/concepts/runtime-compatibility.html)
431
455
  - [Album Processing Guide](https://charleswiltgen.github.io/TagLib-Wasm/guide/album-processing.html)
456
+ - [Folder Operations](https://charleswiltgen.github.io/TagLib-Wasm/guide/folder-operations.html)
457
+ - [Codec Detection](https://charleswiltgen.github.io/TagLib-Wasm/guide/codec-detection.html)
458
+ - [Deno Compile](https://charleswiltgen.github.io/TagLib-Wasm/guide/deno-compile.html)
432
459
  - [Platform Examples](https://charleswiltgen.github.io/TagLib-Wasm/guide/platform-examples.html)
433
460
  - [Working with Cover Art](https://charleswiltgen.github.io/TagLib-Wasm/guide/cover-art.html)
434
461
  - [Track Ratings](https://charleswiltgen.github.io/TagLib-Wasm/guide/ratings.html)
@@ -441,15 +468,26 @@ Supported formats:
441
468
 
442
469
  ## Supported Formats
443
470
 
444
- `taglib-wasm` is designed to support all formats supported by TagLib:
471
+ `taglib-wasm` is designed to support all formats supported by TagLib. The
472
+ authoritative list is the [`SUPPORTED_FORMATS`](src/errors/base.ts) constant
473
+ (the names `getFormat()` answers):
445
474
 
446
475
  - **.mp3** – ID3v2 and ID3v1 tags
476
+ - **.aac** – ADTS / raw AAC streams (ID3v2 metadata, read through the MPEG reader)
447
477
  - **.m4a/.mp4** – MPEG-4/AAC metadata for AAC and Apple Lossless audio
448
478
  - **.flac** – Vorbis comments and audio properties (plus BWF `bext`/iXML)
449
- - **.ogg** – Ogg Vorbis format with full metadata support
479
+ - **.ogg** – Ogg container: Vorbis with full metadata support, plus FLAC-in-Ogg
480
+ and Speex
450
481
  - **.wav** – INFO chunk metadata, plus BWF `bext` and iXML
451
- - **Additional formats** – Opus, APE, MPC, WavPack, TrueAudio, AIFF, WMA, and
452
- more
482
+ - **Additional formats** – Opus, AIFF (`.aiff`/`.aif`), WMA (`.wma`, the ASF
483
+ container), APE, WavPack (`.wv`), Musepack (`.mpc`), TrueAudio (`.tta`), DSD
484
+ (`.dsf`/`.dff`), Shorten (`.shn`), the tracker modules
485
+ (`.mod`/`.s3m`/`.it`/`.xm`), and Matroska (`.mka`/`.mkv`/`.webm`)
486
+
487
+ These open and report their format on both backends. One difference remains: on
488
+ Emscripten, `audioProperties().containerFormat` and `.codec` still report
489
+ `"unknown"` for the formats its sniffer cannot place (APE, DSF, DSDIFF, MPC,
490
+ SHN, and the tracker modules) — their tags and remaining properties load.
453
491
 
454
492
  ## Performance and Best Practices
455
493
 
@@ -513,12 +551,149 @@ await file.saveToFile(); // Full file loaded only here
513
551
 
514
552
  taglib-wasm auto-selects the fastest available backend — no configuration needed:
515
553
 
516
- | Environment | Backend | How it works | Performance |
517
- | ------------------------ | ----------------- | ------------------------------------------------------ | ----------- |
518
- | **Node.js / Deno / Bun** | WASI (auto) | Seek-based filesystem I/O; reads only headers and tags | Fastest |
519
- | **Browsers / Workers** | Emscripten (auto) | Entire file loaded into memory as buffer | Baseline |
554
+ | Environment | Backend | How it works | Performance |
555
+ | ------------------------ | ----------------- | -------------------------------------------------------------------------------------------------------- | ----------- |
556
+ | **Node.js / Deno / Bun** | WASI (auto) | Seek-based filesystem I/O; reads only headers and tags | Fastest |
557
+ | **Browsers / Workers** | Emscripten (auto) | Buffer-based: the whole file by default, or a header/footer window for a `File` with `{ partial: true }` | Baseline |
520
558
 
521
559
  On Node.js, Deno, and Bun you get WASI automatically — nothing to configure.
560
+ Partial loading (`{ partial: true }`) works on both paths; see the
561
+ [Performance Guide](https://charleswiltgen.github.io/TagLib-Wasm/concepts/performance.html#smart-partial-loading).
562
+
563
+ ### Bundle Size and Tree-Shaking
564
+
565
+ Importing the barrel (`taglib-wasm`) does **not** pull in the Folder or Web API:
566
+ every bundler tested here tree-shakes to leaf granularity. Measured on
567
+ taglib-wasm 2.2.3 installed from a packed tarball (`npm pack` →
568
+ `npm install <tarball>`), minified ES2022 ESM bundles on Node 24.21.0. Figures
569
+ are minified JavaScript bytes — the ~700 KB Wasm binary is loaded at runtime and
570
+ is not part of the bundle in any scenario below. The `./web` figures further down
571
+ were re-measured with the same invocations after that subpath gained a `browser`
572
+ condition.
573
+
574
+ Each row is a one-file app whose whole body is that import plus the call the row
575
+ names, keeping the imported function reachable (`globalThis.__app = { … }`).
576
+ Exact invocations, so the table can be reproduced:
577
+
578
+ - **esbuild 0.28.2** — `esbuild <app> --bundle --minify --format=esm
579
+ --target=es2022 --platform=browser --external:module` for the browser column;
580
+ the same with `--platform=node` and no `--external` for the Node column.
581
+ (`--external` takes a colon, not `=`.)
582
+ - **rollup 4.63.3** — `input: <app>`, plugins `@rollup/plugin-node-resolve`
583
+ (`{ browser: true, exportConditions: ["browser", "default"] }` for the browser
584
+ column, default options for the Node column) and `@rollup/plugin-terser`,
585
+ output `{ format: "esm", inlineDynamicImports: true }`.
586
+ - **vite 8.3.0** — a real app build: `index.html` plus a
587
+ `<script type="module">` pointing at the entry, `build.minify: "esbuild"`,
588
+ `target: "es2022"`. Vite builds for the browser.
589
+ - **webpack 5.111.1** — `mode: "production"`, `target: "web"`,
590
+ `externals: { module: "module" }`. `target: "web"` alone fails on the
591
+ `import("module")` inside `dist/taglib-wrapper.js`.
592
+
593
+ | Consumer app | esbuild (browser)¹ | rollup (browser)¹ | vite (app) | webpack (web)² | esbuild (Node)³ | rollup (Node)³ |
594
+ | ------------------------------------- | ------------------ | ----------------- | ---------- | -------------- | --------------- | -------------- |
595
+ | `taglib-wasm` — `TagLib.initialize()` | 81,991 | 78,374 | 84,802 | 57,141 | 145,056 | 134,312 |
596
+ | `taglib-wasm/simple` — `getTagLib()` | 81,279 | 78,495 | 84,094 | 57,260 | 146,047 | 134,713 |
597
+ | `taglib-wasm/folder` — `scanFolder`⁴ | — | 138,075⁴ | 146,094⁴ | — | 149,396 | 138,075 |
598
+
599
+ ¹ the `browser` `exports` condition. ² `target: "web"`. ³ the Node `exports`
600
+ condition. ⁴ Node-only entry — see below.
601
+
602
+ **`./folder` is Node-only.** The subpath declares no `browser` export condition
603
+ because `scanFolder` and friends read and write a filesystem, so a
604
+ browser-targeted build resolves the Node-oriented graph and fails: esbuild
605
+ `--platform=browser` reports `Could not resolve "node:fs/promises"`, and webpack
606
+ `target: "web"` fails with four errors (`./taglib-web.wasm`, `node:fs`,
607
+ `node:fs/promises`, `node:buffer`). That outcome is the design: a build error
608
+ beats a stub that throws on the first call in production. If the same cells were
609
+ reachable they would come from shimming Node builtins into a bundle that cannot
610
+ work — which is exactly what vite and rollup did before the condition was
611
+ declared. `./rating` and `./disc-folder` are pure JavaScript and build for
612
+ either target. In a browser, scan on a server and post the result; the pure
613
+ `groupAlbums` / `discFolderInfo` half is exported from `taglib-wasm` and
614
+ `taglib-wasm/disc-folder` and runs anywhere.
615
+
616
+ **`./web` builds for the browser.** It declares a `browser` condition, so a
617
+ browser-targeted build resolves an Emscripten-only build of that entry and pulls
618
+ **`taglib-web.wasm` alone** — measured with the vite invocation above on
619
+ `pictureToDataURL` from `taglib-wasm/web`: one 703,477-byte Wasm asset where the
620
+ Node-oriented graph emitted both `taglib-web.wasm` and `taglib-wasi.wasm`
621
+ (1.4 MB of assets for a call that needs neither engine), and a 6,289-byte
622
+ JavaScript bundle where the shimmed Node graph produced 17,461 bytes. Note the
623
+ browser build is a pre-bundled file like `index.browser.js`, so it does not
624
+ tree-shake to a leaf the way the Node files do: the same call costs 80,959 bytes
625
+ in the browser column against 205 bytes on Node, and importing any pure helper
626
+ from the barrel costs ~82 KB there too. That granularity is a property of the
627
+ pre-bundled browser entries, not of this subpath.
628
+
629
+ **TypeScript resolves the same condition.** A browser consumer gets the matching
630
+ type surface only if TypeScript is told about it — in `tsconfig.json`:
631
+
632
+ ```json
633
+ {
634
+ "compilerOptions": {
635
+ "moduleResolution": "bundler",
636
+ "customConditions": ["browser"]
637
+ }
638
+ }
639
+ ```
640
+
641
+ With that condition, `dist/index.browser.d.ts` is the declaration file used, so
642
+ `import { scanFolder } from "taglib-wasm"` is a compile error naming the missing
643
+ export (`TS2305: Module '"taglib-wasm"' has no exported member 'scanFolder'`)
644
+ instead of a bundler error — and importing `bwf`, `groupAlbums`,
645
+ `discFolderInfo`, or any type (including `FolderScanResult`) compiles. Without
646
+ `customConditions`, TypeScript reads the Node declarations from
647
+ `dist/index.d.ts` while the bundler still ships `dist/index.browser.js`; that
648
+ mismatch is what produced the original silent failure.
649
+
650
+ **Bundler interop.** `dist/taglib-wrapper.js` — the Emscripten glue — contains a
651
+ dynamic `import("module")`, and browser targets have no such builtin, so the two
652
+ targets need one line each: esbuild `--external:module`, webpack
653
+ `externals: { module: "module" }` (webpack `target: "web"` alone fails on it).
654
+ Rollup needs nothing extra; vite externalizes it for the browser with a warning.
655
+ The `browser` condition itself is resolved by default by esbuild
656
+ (`--platform=browser`), vite, and webpack (`target: "web"`); rollup needs
657
+ `nodeResolve({ browser: true, exportConditions: ["browser", "default"] })`.
658
+
659
+ **The barrel is not a tax.** Adding an API to an import that already loads the
660
+ engine costs only that API. Against the `taglib-wasm` row above (esbuild, Node
661
+ column): adding `scanFolder` costs **4,377 bytes** and adding
662
+ `pictureToDataURL` costs **187 bytes**, because neither drags in the rest of the
663
+ Folder or Web module tree.
664
+
665
+ **The browser barrel's residue.** The browser entry is a pre-bundled file, and
666
+ aligning its export surface with the Node barrel's added the pure
667
+ `bwf` / `groupAlbums` / `discFolderInfo` exports to it. A browser consumer that
668
+ imports none of them pays **350 bytes** more than before (measured on
669
+ `import { TagLib }`, one toolchain and one snapshot, pre- and post-change
670
+ entries): **56 bytes** for the `bwf` namespace object's top-level export table
671
+ and **294 bytes** for the `discFolderInfo`/`groupAlbums` re-export entries —
672
+ neither is droppable when unused. Nothing else moved: `isDenoCompiled`, a plain
673
+ function, shakes away completely, the Folder and Web APIs are still reached only
674
+ when imported, and the Node entries are unchanged.
675
+
676
+ **Entry-point choice is not a size lever.** `taglib-wasm` and
677
+ `taglib-wasm/simple` differ by less than 1 KB in either direction — in a browser
678
+ bundle `simple` is 712 bytes _smaller_, on Node 991 bytes _larger_, because
679
+ `getTagLib()` reaches the full `TagLib` class through a dynamic import. Pick by
680
+ API surface. The lever that does matter is the `browser` export condition: a
681
+ browser-targeted bundle is ~82 KB where a Node-targeted one is ~145 KB.
682
+
683
+ **`"sideEffects": false`** is set in `package.json`, so a bundler may drop any
684
+ module whose exports go unused. Before that field, importers of the sub-entries
685
+ paid ~17 KB for property-metadata tables that were kept only because module-level
686
+ table building looked impure; those bundles are now a few hundred bytes or less.
687
+ Measured with esbuild `--platform=node`, rollup with default `node-resolve`
688
+ options, and vite's app build — the combination under which all four apps build
689
+ under every bundler:
690
+
691
+ | Consumer app | esbuild off → on | rollup off → on | vite off → on |
692
+ | -------------------------------------------------------------- | ----------------- | ----------------- | --------------- |
693
+ | `import "taglib-wasm/web"` (uses nothing) | 17,198 → 21 | 16,329 → 21 | 17,348 → 731 |
694
+ | `import "taglib-wasm/folder"` (uses nothing) | 17,430 → 21 | 16,380 → 21 | 17,689 → 731 |
695
+ | `pictureToDataURL` from `taglib-wasm/web` | 17,361 → 184 | 16,497 → 189 | 17,519 → 902 |
696
+ | `import { TagLib } from "taglib-wasm"`, referenced by `typeof` | 145,596 → 145,030 | 134,337 → 134,286 | 84,278 → 84,278 |
522
697
 
523
698
  ## Runtime Compatibility
524
699
 
@@ -535,8 +710,11 @@ On Node.js, Deno, and Bun you get WASI automatically — nothing to configure.
535
710
 
536
711
  ## Known Limitations
537
712
 
538
- - **Memory Usage (browsers)** – In browser environments, entire files are loaded
539
- into memory. On Node.js/Deno, WASI reads only headers and tags from disk.
713
+ - **Memory Usage (browsers)** – By default, browser environments load the entire
714
+ file into memory; with `{ partial: true }` a `File` reads only the
715
+ header/footer window through `File.slice()`, falling back to the whole file
716
+ when the metadata overruns that window. On Node.js/Deno, WASI reads only
717
+ headers and tags from disk. See the [Performance Guide](https://charleswiltgen.github.io/TagLib-Wasm/concepts/performance.html#smart-partial-loading).
540
718
  - **Concurrent Access** – Not thread-safe (JavaScript single-threaded nature
541
719
  mitigates this)
542
720
 
@@ -561,7 +739,10 @@ means:
561
739
  - If you modify the TagLib C++ code, you must share those changes
562
740
  - You must provide a way for users to relink with a modified TagLib
563
741
 
564
- For details, see [lib/taglib/COPYING.LGPL](lib/taglib/COPYING.LGPL)
742
+ For details, see [TagLib's COPYING.LGPL](https://github.com/taglib/taglib/blob/master/COPYING.LGPL)
743
+ — this repository vendors TagLib as a git submodule at `lib/taglib`, so that
744
+ path belongs to the submodule and is not part of this tree (the npm package
745
+ ships `LICENSE` only).
565
746
 
566
747
  ## Acknowledgments
567
748
 
@@ -2,7 +2,20 @@
2
2
  * @fileoverview Browser entry point for TagLib-Wasm
3
3
  *
4
4
  * Emscripten-only build with no WASI, Node.js, or Deno dependencies.
5
- * Excludes server-only exports: folder-api, file-utils, deno-compile.
5
+ *
6
+ * The surface is the Node barrel's minus what cannot run in a browser, and the
7
+ * `browser` `exports` condition resolves both the runtime and (via
8
+ * `dist/index.browser.d.ts`) the types to this file, so importing an omitted
9
+ * name is a compile error naming it rather than a bundler error. Two kinds of
10
+ * omission, each marked where it applies below:
11
+ *
12
+ * - the filesystem-bound halves of `file-utils` and `folder-api`, plus the
13
+ * Deno-compile helpers — a function that writes to a path or walks a
14
+ * directory has no browser implementation;
15
+ * - nothing else. Types are not omitted: a type describes data, and data
16
+ * crosses networks, so the type surface here matches `index.ts` exactly.
17
+ *
18
+ * `tests/browser-entry-surface.test.ts` is the enforcement.
6
19
  *
7
20
  * @module TagLib-Wasm/browser
8
21
  */
@@ -12,15 +25,22 @@ export type { MutableTag } from "./src/taglib.js";
12
25
  export { isNamedAudioInput } from "./src/types/audio-formats.js";
13
26
  export { EnvironmentError, FileOperationError, InvalidFormatError, isEnvironmentError, isFileOperationError, isInvalidFormatError, isMemoryError, isMetadataError, isTagLibError, isUnsupportedFormatError, MemoryError, MetadataError, SUPPORTED_FORMATS, TagLibError, TagLibInitializationError, UnsupportedFormatError, } from "./src/errors.js";
14
27
  export type { TagLibErrorCode } from "./src/errors.js";
15
- export { addPicture, applyCoverArt, applyPictures, applyTags, applyTagsToFile, type BatchItem, type BatchOptions, type BatchResult, clearPictures, clearTags, type FileMetadata, findPictureByType, isValidAudioFile, readCoverArt, readFormat, readMetadata, readMetadataBatch, readPictureMetadata, readPictures, readProperties, readPropertiesBatch, readTags, readTagsBatch, replacePictureByType, setBufferMode, } from "./src/simple/index.js";
28
+ export { isDenoCompiled } from "./src/runtime/deno-detect.js";
29
+ export { addPicture, applyCoverArt, applyPictures, applyTags, applyTagsToFile, type BatchItem, type BatchOptions, type BatchResult, clearPictures, clearTags, type FileMetadata, findPictureByType, isValidAudioFile, readCoverArt, readFormat, readMediaChecksum, readMetadata, readMetadataBatch, readPictureMetadata, readPictures, readProperties, readPropertiesBatch, readTags, readTagsBatch, replacePictureByType, setBufferMode, } from "./src/simple/index.js";
30
+ export type { ChecksumAlgorithm, ChecksumSource, MediaChecksum, MediaChecksumOptions, } from "./src/taglib/audio-file-checksum.js";
16
31
  export { FormatMappings, getAllProperties, getAllPropertyKeys, getPropertiesByFormat, getPropertyMetadata, isValidProperty, PROPERTIES, propertyValue, propertyValues, } from "./src/constants.js";
17
32
  export type { PropertyMetadata } from "./src/constants/property-types.js";
33
+ export { discFolderInfo } from "./src/folder-api/folder-disc.js";
34
+ export { groupAlbums } from "./src/folder-api/album-grouping.js";
35
+ export type { AlbumDisc, AlbumGroup, AlbumGroupingResult, AlbumGroupItem, AlbumGroupKey, AudioDynamics, AudioFileMetadata, DiscConfidence, DiscFolderInfo, DuplicateGroup, FolderScanItem, FolderScanOptions, FolderScanResult, GroupAlbumsOptions, ScanForAlbumsOptions, } from "./src/folder-api/index.js";
18
36
  export { canvasToPicture, createPictureDownloadURL, createPictureGallery, dataURLToPicture, displayPicture, imageFileToPicture, pictureToDataURL, setCoverArtFromCanvas, } from "./src/web-utils/index.js";
19
- export type { AudioCodec, AudioFileInput, AudioProperties, BitrateControlMode, ContainerFormat, ExtendedTag, FieldMapping, FileType, NamedAudioInput, OpenOptions, Picture, PictureType, PropertyMap, Tag, TagInput, } from "./src/types.js";
37
+ export type { AudioCodec, AudioFileInput, AudioProperties, BitrateControlMode, BroadcastAudioExtension, Chapter, ContainerFormat, ExtendedTag, FieldMapping, FileType, NamedAudioInput, OpenOptions, Picture, PictureType, PropertyMap, SetChaptersOptions, Tag, TagInput, } from "./src/types.js";
20
38
  export { BITRATE_CONTROL_MODE_NAMES, BITRATE_CONTROL_MODE_VALUES, PICTURE_TYPE_NAMES, PICTURE_TYPE_VALUES, } from "./src/types.js";
21
39
  export type { PropertyKey, PropertyValue } from "./src/constants.js";
22
40
  export type { FormatPropertyKey, TagFormat, } from "./src/types/format-property-keys.js";
23
- export type { Rating, UnsyncedLyrics, VariantMap, } from "./src/constants/complex-properties.js";
41
+ export type { TypedAudioProperties } from "./src/types/audio-formats.js";
42
+ export type { Id3v2Frame, Rating, UnsyncedLyrics, VariantMap, } from "./src/constants/complex-properties.js";
43
+ export * as bwf from "./src/bwf/bext.js";
24
44
  export { RatingUtils } from "./src/utils/rating.js";
25
45
  export type { NormalizedRating, PopmRating } from "./src/utils/rating.js";
26
46
  export type { TagLibModule, WasmModule } from "./src/wasm.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EACV,SAAS,EACT,cAAc,GACf,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGjE,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;AACzB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,UAAU,EACV,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,aAAa,EACb,SAAS,EACT,KAAK,YAAY,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,aAAa,GACd,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,aAAa,EACb,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,WAAW,EACX,OAAO,EACP,WAAW,EACX,WAAW,EACX,GAAG,EACH,QAAQ,GACT,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACrE,YAAY,EACV,iBAAiB,EACjB,SAAS,GACV,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EACV,MAAM,EACN,cAAc,EACd,UAAU,GACX,MAAM,uCAAuC,CAAC;AAG/C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAG1E,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9D,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../index.browser.ts"],"names":[],"mappings":"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"}