taglib-wasm 0.3.1 → 0.3.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 CHANGED
@@ -1,25 +1,45 @@
1
1
  # taglib-wasm
2
2
 
3
- This is the Wasm version of [**TagLib**](https://taglib.org/), the most robust, de-facto standard for reading and editing metadata tags (Title, Album, Artist, etc.) in all popular audio formats. `taglib-wasm` exists because the JavaScipt/TypeScipt ecosystem had no battle-tested audio tagging library that supports reading and writing music metadata to all popular audio formats — until now!
4
-
5
- `taglib-wasm` stands on the shoulders of giants, including [TagLib](https://taglib.org/) itself, [Emscripten](https://emscripten.org/), and [Wasm](https://webassembly.org/) ([WebAssembly](https://webassembly.org/)).
6
-
7
- `taglib-wasm` aspires to be a universal solution for **JavaScript/TypeScript** platforms — Deno, Node.js, Bun, web browsers, and Cloudflare Workers. Note: This project is a baby, and you’re likely to experience some surprises at this stage of its development. I’m extremely motivated to help address them, since I’ll also be depending on this project.
3
+ This is the Wasm version of [**TagLib**](https://taglib.org/), the most robust,
4
+ de-facto standard for reading and editing metadata tags (Title, Album, Artist,
5
+ etc.) in all popular audio formats. `taglib-wasm` exists because the
6
+ JavaScipt/TypeScipt ecosystem had no battle-tested audio tagging library that
7
+ supports reading and writing music metadata to all popular audio formats until
8
+ now!
9
+
10
+ `taglib-wasm` stands on the shoulders of giants, including
11
+ [TagLib](https://taglib.org/) itself, [Emscripten](https://emscripten.org/), and
12
+ [Wasm](https://webassembly.org/) ([WebAssembly](https://webassembly.org/)).
13
+
14
+ `taglib-wasm` aspires to be a universal solution for **JavaScript/TypeScript**
15
+ platforms — Deno, Node.js, Bun, web browsers, and Cloudflare Workers. Note: This
16
+ project is a baby, and you’re likely to experience some surprises at this stage
17
+ of its development. I’m extremely motivated to help address them, since I’ll
18
+ also be depending on this project.
8
19
 
9
20
  ## 🤔 Why?
10
21
 
11
- Because there’s nothing like it. [`mp3tag.js`](https://mp3tag.js.org/) is mature and active, but only supports MP3 files and ID3 tags. TagLib was an ideal choice from a maturity and capabilities point of view, but wrappers like `node-taglib` appeared to be dormant, and I wanted to avoid making users install platform-specific dependencies whenever possible.
22
+ Because there’s nothing like it. [`mp3tag.js`](https://mp3tag.js.org/) is mature
23
+ and active, but only supports MP3 files and ID3 tags. TagLib was an ideal choice
24
+ from a maturity and capabilities point of view, but wrappers like `node-taglib`
25
+ appeared to be dormant, and I wanted to avoid making users install
26
+ platform-specific dependencies whenever possible.
12
27
 
13
28
  ## 🎯 Features
14
29
 
15
- - **✅ Universal compatibility** – Works with Deno, Node.js, Bun, web browsers, and Cloudflare Workers
30
+ - **✅ Universal compatibility** – Works with Deno, Node.js, Bun, web browsers,
31
+ and Cloudflare Workers
16
32
  - **✅ TypeScript first** – Complete type definitions and modern API
17
- - **✅ Full audio format support** – Supports all audio formats supported by TagLib
18
- - **✅ Format abstraction** – `taglib-wasm` deals with how tags are read from/written to in different file formats
33
+ - **✅ Full audio format support** – Supports all audio formats supported by
34
+ TagLib
35
+ - **✅ Format abstraction** – `taglib-wasm` deals with how tags are read
36
+ from/written to in different file formats
19
37
  - **✅ Zero dependencies** – Self-contained WASM bundle
20
38
  - **✅ Memory efficient** – In-memory processing without filesystem access
21
- - **✅ Production ready** – Growing test suite helps ensure safety and reliability
22
- - **🆕 Two API styles** – Choose between Simple (3 functions) or Core (full control) APIs
39
+ - **✅ Production ready** – Growing test suite helps ensure safety and
40
+ reliability
41
+ - **🆕 Two API styles** – Choose between Simple (3 functions) or Core (full
42
+ control) APIs
23
43
 
24
44
  ## 📦 Installation
25
45
 
@@ -35,7 +55,19 @@ import { TagLib } from "npm:taglib-wasm";
35
55
  npm install taglib-wasm
36
56
  ```
37
57
 
38
- **Note:** The NPM package ships TypeScript source files. Use a TypeScript loader like [`tsx`](https://github.com/privatenumber/tsx):
58
+ The package uses TypeScript. You have two options:
59
+
60
+ #### Option 1: Use Node’s native TypeScript support
61
+
62
+ ```bash
63
+ # Node.js 22.6.0+ with experimental flag
64
+ node --experimental-strip-types your-script.ts
65
+
66
+ # Node.js 23.6.0+ (no flag needed)
67
+ node your-script.ts
68
+ ```
69
+
70
+ #### Option 2: TypeScript loader (recommended for production)
39
71
 
40
72
  ```bash
41
73
  npm install --save-dev tsx
@@ -52,16 +84,17 @@ bun add taglib-wasm
52
84
 
53
85
  ### Simple API
54
86
 
55
- Inspired by [go-taglib](https://github.com/sentriz/go-taglib)’s excellent developer experience:
87
+ This was inspired by [go-taglib](https://github.com/sentriz/go-taglib), a
88
+ similar project for Go created at about the same time.
56
89
 
57
90
  ```typescript
58
91
  import { readProperties, readTags, writeTags } from "taglib-wasm/simple";
59
92
 
60
- // Read tags - just one function call!
93
+ // Read tags
61
94
  const tags = await readTags("song.mp3");
62
95
  console.log(tags.title, tags.artist, tags.album);
63
96
 
64
- // Write tags - simple as can be
97
+ // Write tags
65
98
  await writeTags("song.mp3", {
66
99
  title: "New Title",
67
100
  artist: "New Artist",
@@ -75,7 +108,7 @@ console.log(`Duration: ${props.length}s, Bitrate: ${props.bitrate} kbps`);
75
108
 
76
109
  ### Core API
77
110
 
78
- Full control when you need it:
111
+ The Core API provides full control for more advanced applications.
79
112
 
80
113
  ```typescript
81
114
  import { TagLib } from "taglib-wasm";
@@ -111,19 +144,50 @@ console.log("Updated tags:", file.tag());
111
144
  file.dispose();
112
145
  ```
113
146
 
147
+ ### Tag Constants
148
+
149
+ taglib-wasm provides type-safe tag constants with IDE autocomplete:
150
+
151
+ ```typescript
152
+ import { Tags } from "taglib-wasm";
153
+
154
+ // Use constants for better type safety and autocomplete
155
+ const properties = file.properties();
156
+
157
+ // Read properties
158
+ const title = properties[Tags.Title]?.[0];
159
+ const albumArtist = properties[Tags.AlbumArtist]?.[0];
160
+ const musicBrainzId = properties[Tags.MusicBrainzArtistId]?.[0];
161
+
162
+ // Write properties
163
+ file.setProperties({
164
+ [Tags.Title]: ["My Song"],
165
+ [Tags.AlbumArtist]: ["Various Artists"],
166
+ [Tags.Bpm]: ["128"]
167
+ });
168
+
169
+ // All constants provide IDE autocomplete
170
+ Tags.Title // → "TITLE"
171
+ Tags.Artist // → "ARTIST"
172
+ Tags.AlbumArtist // → "ALBUMARTIST"
173
+ Tags.TrackGain // → "REPLAYGAIN_TRACK_GAIN"
174
+ // ... and many more
175
+ ```
176
+
177
+ See [Tag Name Constants](docs/Tag-Name-Constants.md) for the complete list of available tags and format-specific mappings.
178
+
114
179
  ## Platform examples
115
180
 
116
- ### Node.js
181
+ ### Deno
117
182
 
118
183
  ```typescript
119
- import { TagLib } from "taglib-wasm";
120
- import { readFile } from "fs/promises";
184
+ import { TagLib } from "npm:taglib-wasm";
121
185
 
122
186
  // Initialize taglib-wasm
123
187
  const taglib = await TagLib.initialize();
124
188
 
125
189
  // Load audio file from filesystem
126
- const audioData = await readFile("song.mp3");
190
+ const audioData = await Deno.readFile("song.mp3");
127
191
  const file = taglib.openFile(audioData);
128
192
 
129
193
  // Read metadata
@@ -150,17 +214,18 @@ console.log("Updated tags:", file.tag());
150
214
  file.dispose();
151
215
  ```
152
216
 
153
- ### Bun
217
+ ### Node.js
154
218
 
155
219
  ```typescript
156
220
  import { TagLib } from "taglib-wasm";
221
+ import { readFile } from "fs/promises";
157
222
 
158
223
  // Initialize taglib-wasm
159
224
  const taglib = await TagLib.initialize();
160
225
 
161
- // Load from file system (Bun's native file API)
162
- const audioData = await Bun.file("song.mp3").arrayBuffer();
163
- const file = taglib.openFile(new Uint8Array(audioData));
226
+ // Load audio file from filesystem
227
+ const audioData = await readFile("song.mp3");
228
+ const file = taglib.openFile(audioData);
164
229
 
165
230
  // Read metadata
166
231
  const tags = file.tag();
@@ -186,7 +251,7 @@ console.log("Updated tags:", file.tag());
186
251
  file.dispose();
187
252
  ```
188
253
 
189
- ### Browser
254
+ ### Bun
190
255
 
191
256
  ```typescript
192
257
  import { TagLib } from "taglib-wasm";
@@ -194,11 +259,9 @@ import { TagLib } from "taglib-wasm";
194
259
  // Initialize taglib-wasm
195
260
  const taglib = await TagLib.initialize();
196
261
 
197
- // Load from file input or fetch
198
- const fileInput = document.querySelector('input[type="file"]');
199
- const audioFile = fileInput.files[0];
200
- const audioData = new Uint8Array(await audioFile.arrayBuffer());
201
- const file = taglib.openFile(audioData);
262
+ // Load from file system (Bun's native file API)
263
+ const audioData = await Bun.file("song.mp3").arrayBuffer();
264
+ const file = taglib.openFile(new Uint8Array(audioData));
202
265
 
203
266
  // Read metadata
204
267
  const tags = file.tag();
@@ -224,16 +287,18 @@ console.log("Updated tags:", file.tag());
224
287
  file.dispose();
225
288
  ```
226
289
 
227
- ### Deno
290
+ ### Browser
228
291
 
229
292
  ```typescript
230
- import { TagLib } from "npm:taglib-wasm";
293
+ import { TagLib } from "taglib-wasm";
231
294
 
232
295
  // Initialize taglib-wasm
233
296
  const taglib = await TagLib.initialize();
234
297
 
235
- // Load audio file from filesystem
236
- const audioData = await Deno.readFile("song.mp3");
298
+ // Load from file input or fetch
299
+ const fileInput = document.querySelector('input[type="file"]');
300
+ const audioFile = fileInput.files[0];
301
+ const audioData = new Uint8Array(await audioFile.arrayBuffer());
237
302
  const file = taglib.openFile(audioData);
238
303
 
239
304
  // Read metadata
@@ -269,7 +334,8 @@ export default {
269
334
  async fetch(request: Request): Promise<Response> {
270
335
  if (request.method === "POST") {
271
336
  try {
272
- // Initialize taglib-wasm
337
+ // Initialize taglib-wasm with Workers-specific configuration
338
+ // See docs/Cloudflare-Workers.md for memory configuration details
273
339
  const taglib = await TagLib.initialize({
274
340
  memory: { initial: 8 * 1024 * 1024 }, // 8MB for Workers
275
341
  });
@@ -319,22 +385,30 @@ export default {
319
385
 
320
386
  `tag-wasm` is designed to support all formats supported by TagLib:
321
387
 
322
- - ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless audio
388
+ - ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless
389
+ audio
323
390
  - ✅ **.mp3** – ID3v2 and ID3v1 tags
324
391
  - ✅ **.flac** – Vorbis comments and audio properties
325
392
  - ✅ **.wav** – INFO chunk metadata
326
- - ✅ **Legacy formats**: Opus, APE, MPC, WavPack, TrueAudio, and more
393
+ - ✅ **Legacy formats** Opus, APE, MPC, WavPack, TrueAudio, and more
327
394
 
328
395
  ## 🎯 Extended Metadata with PropertyMap
329
396
 
330
- `taglib-wasm` provides a **PropertyMap API** for accessing extended metadata beyond the basic tags. This allows you to read and write format-specific fields and custom metadata.
397
+ `taglib-wasm` provides a **PropertyMap API** for accessing extended metadata
398
+ beyond the basic tags. This allows you to read and write format-specific fields
399
+ and custom metadata.
331
400
 
332
401
  ### AcoustID example
333
402
 
334
403
  ```typescript
335
- // Using PropertyMap API to set extended metadata
404
+ import { Tags } from "taglib-wasm";
405
+
406
+ // Using PropertyMap API to set extended metadata with tag constants
407
+ file.setProperty(Tags.AcoustidFingerprint, "AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
408
+ file.setProperty(Tags.AcoustidId, "e7359e88-f1f7-41ed-b9f6-16e58e906997");
409
+
410
+ // Or using string property names
336
411
  file.setProperty("ACOUSTID_FINGERPRINT", "AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
337
- file.setProperty("ACOUSTID_ID", "e7359e88-f1f7-41ed-b9f6-16e58e906997");
338
412
 
339
413
  // Note: Property keys may vary by format
340
414
  // Use file.properties() to see all available properties
@@ -344,20 +418,23 @@ file.save(); // Don't forget to save!
344
418
  ### MusicBrainz example
345
419
 
346
420
  ```typescript
347
- // MusicBrainz metadata using PropertyMap
348
- file.setProperty("MUSICBRAINZ_TRACKID", "f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
349
- file.setProperty("MUSICBRAINZ_ALBUMID", "a1b2c3d4-e5f6-7890-abcd-ef1234567890");
350
- file.setProperty("MUSICBRAINZ_ARTISTID", "12345678-90ab-cdef-1234-567890abcdef");
421
+ // MusicBrainz metadata using PropertyMap with tag constants
422
+ file.setProperty(Tags.MusicBrainzTrackId, "f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
423
+ file.setProperty(Tags.MusicBrainzAlbumId, "a1b2c3d4-e5f6-7890-abcd-ef1234567890");
424
+ file.setProperty(
425
+ Tags.MusicBrainzArtistId,
426
+ "12345678-90ab-cdef-1234-567890abcdef",
427
+ );
351
428
  ```
352
429
 
353
430
  ### Volume example
354
431
 
355
432
  ```typescript
356
- // ReplayGain volume normalization
357
- file.setProperty("REPLAYGAIN_TRACK_GAIN", "-6.54 dB");
358
- file.setProperty("REPLAYGAIN_TRACK_PEAK", "0.987654");
359
- file.setProperty("REPLAYGAIN_ALBUM_GAIN", "-8.12 dB");
360
- file.setProperty("REPLAYGAIN_ALBUM_PEAK", "0.995432");
433
+ // ReplayGain volume normalization with tag constants
434
+ file.setProperty(Tags.TrackGain, "-6.54 dB");
435
+ file.setProperty(Tags.TrackPeak, "0.987654");
436
+ file.setProperty(Tags.AlbumGain, "-8.12 dB");
437
+ file.setProperty(Tags.AlbumPeak, "0.995432");
361
438
  ```
362
439
 
363
440
  ### Extended fields
@@ -366,20 +443,20 @@ file.setProperty("REPLAYGAIN_ALBUM_PEAK", "0.995432");
366
443
  // Using PropertyMap to set multiple properties at once
367
444
  const properties = file.properties(); // Get current properties
368
445
 
369
- // Set extended metadata
446
+ // Set extended metadata with tag constants
370
447
  file.setProperties({
371
- ALBUMARTIST: ["Various Artists"],
372
- COMPOSER: ["Composer Name"],
373
- BPM: ["120"],
374
- COMPILATION: ["1"],
375
- DISCNUMBER: ["1"],
376
- TRACKTOTAL: ["12"],
448
+ [Tags.AlbumArtist]: ["Various Artists"],
449
+ [Tags.Composer]: ["Composer Name"],
450
+ [Tags.Bpm]: ["120"],
451
+ [Tags.Compilation]: ["1"],
452
+ [Tags.DiscNumber]: ["1"],
453
+ [Tags.TrackTotal]: ["12"],
377
454
  // Note: Property keys vary by format
378
455
  });
379
456
 
380
457
  // Or set individual properties
381
- file.setProperty("ALBUMARTIST", "Various Artists");
382
- file.setProperty("COMPOSER", "Composer Name");
458
+ file.setProperty(Tags.AlbumArtist, "Various Artists");
459
+ file.setProperty(Tags.Composer, "Composer Name");
383
460
  ```
384
461
 
385
462
  ## 🏗️ Development
@@ -442,23 +519,29 @@ npm test
442
519
  # ✅ MP3 - ID3v1/v2 tag support
443
520
  # ✅ FLAC - Vorbis comments and properties
444
521
  # ✅ OGG - Vorbis comments
445
- # ✅ M4A - iTunes-compatible metadata atoms
522
+ # ✅ M4A - MPEG-4 (AAC and Apple Lossless) metadata
446
523
  ```
447
524
 
448
525
  ## 🔧 Technical Implementation
449
526
 
450
527
  ### Key architecture decisions
451
528
 
452
- 1. **Memory Management**: Uses Emscripten's `allocate()` for reliable JS↔WASM data transfer
453
- 2. **Buffer-Based Processing**: `TagLib::ByteVectorStream` enables in-memory file processing
529
+ 1. **Memory Management**: Uses Emscripten's `allocate()` for reliable JS↔WASM
530
+ data transfer
531
+ 2. **Buffer-Based Processing**: `TagLib::ByteVectorStream` enables in-memory
532
+ file processing
454
533
  3. **C++ Wrapper**: Custom C functions bridge TagLib's C++ API to WASM exports
455
- 4. **Type Safety**: Complete TypeScript definitions for all audio formats and metadata
534
+ 4. **Type Safety**: Complete TypeScript definitions for all audio formats and
535
+ metadata
456
536
 
457
537
  ### Critical implementation details
458
538
 
459
- - **ByteVectorStream**: Enables processing audio files from memory buffers without filesystem
460
- - **ID-based Object Management**: C++ objects managed via integer IDs for memory safety
461
- - **Emscripten allocate()**: Ensures proper memory synchronization between JS and WASM
539
+ - **ByteVectorStream**: Enables processing audio files from memory buffers
540
+ without filesystem
541
+ - **ID-based Object Management**: C++ objects managed via integer IDs for memory
542
+ safety
543
+ - **Emscripten allocate()**: Ensures proper memory synchronization between JS
544
+ and WASM
462
545
  - **UTF-8 String Handling**: Proper encoding for international metadata
463
546
 
464
547
  ## 📚 API Reference
@@ -536,51 +619,44 @@ interface Tag {
536
619
  type PropertyMap = { [key: string]: string[] };
537
620
  ```
538
621
 
539
- ## 🎛️ Configuration
622
+ ## 📖 Additional Documentation
540
623
 
541
- ```typescript
542
- interface TagLibConfig {
543
- memory?: {
544
- initial?: number; // Initial memory size (default: 16MB)
545
- maximum?: number; // Maximum memory size (default: 256MB)
546
- };
547
- debug?: boolean; // Enable debug output
548
- }
549
- ```
624
+ - [**Tag Name Constants**](docs/Tag-Name-Constants.md) - Comprehensive reference for standard tag names and cross-format mapping
625
+ - [**Automatic Tag Mapping**](docs/Automatic-Tag-Mapping.md) - How taglib-wasm handles format-specific tag differences
626
+ - [**Implementation Details**](docs/Implementation.md) - Technical details about the Wasm implementation
627
+ - [**Runtime Compatibility**](docs/Runtime-Compatibility.md) - Platform-specific setup and considerations
550
628
 
551
629
  ## 🌐 Runtime Compatibility
552
630
 
553
- `taglib-wasm` works seamlessly across all major JavaScript runtimes:
631
+ `taglib-wasm` works across all major JavaScript runtimes:
554
632
 
555
- | Runtime | Status | Installation | Performance | TypeScript |
556
- | ----------- | ------- | --------------------------------- | ----------- | ---------- |
557
- | **Deno** | ✅ Full | `npm:taglib-wasm` | Excellent | Native |
558
- | **Bun** | ✅ Full | `bun add taglib-wasm` | Excellent | Native |
559
- | **Node.js** | ✅ Full | `npm install taglib-wasm` | Good | Via loader |
560
- | **Browser** | ✅ Full | CDN/bundler | Good | Via build |
633
+ | Runtime | Status | Installation | Performance | TypeScript |
634
+ | ----------- | ------- | ------------------------- | ----------- | ---------- |
635
+ | **Deno** | ✅ Full | `npm:taglib-wasm` | Excellent | Native |
636
+ | **Bun** | ✅ Full | `bun add taglib-wasm` | Excellent | Native |
637
+ | **Node.js** | ✅ Full | `npm install taglib-wasm` | Good | Native/tsx |
638
+ | **Browser** | ✅ Full | CDN/bundler | Good | Via build |
561
639
 
562
- **📖 See [docs/Runtime-Compatibility.md](docs/Runtime-Compatibility.md) for detailed runtime information**
640
+ **📖 See [docs/Runtime-Compatibility.md](docs/Runtime-Compatibility.md) for
641
+ detailed runtime information**
563
642
 
564
643
  ## 🚧 Known Limitations
565
644
 
566
- - **File Writing**: Saves only affect in-memory representation (no filesystem persistence)
567
- - **Large Files**: Memory usage scales with file size (entire file loaded into memory)
568
- - **Concurrent Access**: Not thread-safe (JavaScript single-threaded nature)
645
+ - **File Writing** Saves only affect in-memory representation (no filesystem
646
+ persistence)
647
+ - **Large Files** Memory usage scales with file size (entire file loaded into
648
+ memory)
649
+ - **Concurrent Access** – Not thread-safe (JavaScript single-threaded nature)
569
650
 
570
651
  ## 🤝 Contributing
571
652
 
572
- Contributions welcome! Areas of interest:
573
-
574
- - Additional format support (DSF, DSDIFF, etc.)
575
- - Advanced metadata implementation (PropertyMap integration)
576
- - Performance optimizations
577
- - Runtime-specific optimizations
578
- - Documentation improvements
653
+ Contributions welcome!
579
654
 
580
655
  ## 📄 License
581
656
 
582
657
  - **This project**: MIT License (see [LICENSE](LICENSE))
583
- - **TagLib library**: LGPL/MPL dual license (see [lib/taglib/COPYING.LGPL](lib/taglib/COPYING.LGPL))
658
+ - **TagLib library**: LGPL/MPL dual license (see
659
+ [lib/taglib/COPYING.LGPL](lib/taglib/COPYING.LGPL))
584
660
 
585
661
  ## 🙏 Acknowledgments
586
662
 
package/index.ts CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  export { AudioFileImpl as AudioFile, TagLib, createTagLib } from "./src/taglib.ts";
9
9
  export { readTags, writeTags, readProperties } from "./src/simple.ts";
10
+ export { Tags, FormatMappings, isValidTagName, getAllTagNames } from "./src/constants.ts";
10
11
  export type {
11
12
  AudioFormat,
12
13
  AudioProperties,
@@ -18,6 +19,7 @@ export type {
18
19
  PropertyMap,
19
20
  Tag,
20
21
  TagLibConfig,
22
+ TagName,
21
23
  } from "./src/types.ts";
22
24
  export type { TagLibModule, WasmModule } from "./src/wasm.ts";
23
25
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taglib-wasm",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "TagLib compiled to WebAssembly with TypeScript bindings for universal audio metadata handling",
5
5
  "main": "index.ts",
6
6
  "types": "index.ts",
@@ -32,6 +32,9 @@
32
32
  "publish:npm": "echo 'Use GitHub Actions workflow for publishing'",
33
33
  "publish:github": "echo 'Use GitHub Actions workflow for publishing'"
34
34
  },
35
+ "engines": {
36
+ "node": ">=22.6.0"
37
+ },
35
38
  "keywords": [
36
39
  "taglib",
37
40
  "webassembly",
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Standard tag property names used by TagLib.
3
+ * These constants provide type-safe access to tag properties with IDE autocomplete.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { Tags } from 'taglib-wasm';
8
+ *
9
+ * // Read tags
10
+ * const title = file.tag.properties.get(Tags.Title);
11
+ * const artist = file.tag.properties.get(Tags.Artist);
12
+ *
13
+ * // Write tags
14
+ * file.tag.properties.set(Tags.Album, "Dark Side of the Moon");
15
+ * file.tag.properties.set(Tags.Year, "1973");
16
+ * ```
17
+ */
18
+ export const Tags = {
19
+ // Basic Properties
20
+ /** Track/song title */
21
+ Title: 'TITLE',
22
+ /** Primary performer(s) */
23
+ Artist: 'ARTIST',
24
+ /** Album/collection name */
25
+ Album: 'ALBUM',
26
+ /** Date of recording (year) */
27
+ Date: 'DATE',
28
+ /** Track number on album */
29
+ TrackNumber: 'TRACKNUMBER',
30
+ /** Musical genre */
31
+ Genre: 'GENRE',
32
+ /** Comments/notes */
33
+ Comment: 'COMMENT',
34
+
35
+ // Extended Properties
36
+ /** Band/orchestra/ensemble */
37
+ AlbumArtist: 'ALBUMARTIST',
38
+ /** Original composer(s) */
39
+ Composer: 'COMPOSER',
40
+ /** Copyright information */
41
+ Copyright: 'COPYRIGHT',
42
+ /** Encoding software/person */
43
+ EncodedBy: 'ENCODEDBY',
44
+ /** Disc number for multi-disc sets */
45
+ DiscNumber: 'DISCNUMBER',
46
+ /** Beats per minute */
47
+ Bpm: 'BPM',
48
+ /** Lyrics/text writer(s) */
49
+ Lyricist: 'LYRICIST',
50
+ /** Conductor */
51
+ Conductor: 'CONDUCTOR',
52
+ /** Person who remixed */
53
+ Remixer: 'REMIXEDBY',
54
+ /** Language of vocals/lyrics */
55
+ Language: 'LANGUAGE',
56
+ /** Publisher */
57
+ Publisher: 'PUBLISHER',
58
+ /** Mood/atmosphere */
59
+ Mood: 'MOOD',
60
+ /** Media type (CD, vinyl, etc.) */
61
+ Media: 'MEDIA',
62
+ /** Radio station owner */
63
+ RadioStationOwner: 'RADIOSTATIONOWNER',
64
+ /** Producer */
65
+ Producer: 'PRODUCER',
66
+ /** Album subtitle */
67
+ Subtitle: 'SUBTITLE',
68
+ /** Release label */
69
+ Label: 'LABEL',
70
+
71
+ // Sorting Properties
72
+ /** Sort name for title */
73
+ TitleSort: 'TITLESORT',
74
+ /** Sort name for artist */
75
+ ArtistSort: 'ARTISTSORT',
76
+ /** Sort name for album artist */
77
+ AlbumArtistSort: 'ALBUMARTISTSORT',
78
+ /** Sort name for album */
79
+ AlbumSort: 'ALBUMSORT',
80
+ /** Sort name for composer */
81
+ ComposerSort: 'COMPOSERSORT',
82
+
83
+ // Identifiers
84
+ /** International Standard Recording Code */
85
+ Isrc: 'ISRC',
86
+ /** Amazon Standard Identification Number */
87
+ Asin: 'ASIN',
88
+ /** Catalog number */
89
+ CatalogNumber: 'CATALOGNUMBER',
90
+ /** Barcode (EAN/UPC) */
91
+ Barcode: 'BARCODE',
92
+
93
+ // MusicBrainz Identifiers
94
+ /** MusicBrainz Artist ID */
95
+ MusicBrainzArtistId: 'MUSICBRAINZ_ARTISTID',
96
+ /** MusicBrainz Release Artist ID */
97
+ MusicBrainzReleaseArtistId: 'MUSICBRAINZ_ALBUMARTISTID',
98
+ /** MusicBrainz Work ID */
99
+ MusicBrainzWorkId: 'MUSICBRAINZ_WORKID',
100
+ /** MusicBrainz Release ID */
101
+ MusicBrainzReleaseId: 'MUSICBRAINZ_ALBUMID',
102
+ /** MusicBrainz Recording ID */
103
+ MusicBrainzRecordingId: 'MUSICBRAINZ_TRACKID',
104
+ /** MusicBrainz Track ID (deprecated, use RecordingId) */
105
+ MusicBrainzTrackId: 'MUSICBRAINZ_TRACKID',
106
+ /** MusicBrainz Release Group ID */
107
+ MusicBrainzReleaseGroupId: 'MUSICBRAINZ_RELEASEGROUPID',
108
+ /** MusicBrainz Release Track ID */
109
+ MusicBrainzReleaseTrackId: 'MUSICBRAINZ_RELEASETRACKID',
110
+
111
+ // Podcast Properties
112
+ /** Podcast identifier */
113
+ PodcastId: 'PODCASTID',
114
+ /** Podcast URL */
115
+ PodcastUrl: 'PODCASTURL',
116
+
117
+ // Grouping and Work
118
+ /** Content group/work */
119
+ Grouping: 'GROUPING',
120
+ /** Work name */
121
+ Work: 'WORK',
122
+
123
+ // Additional Metadata
124
+ /** Lyrics content */
125
+ Lyrics: 'LYRICS',
126
+ /** Album gain (ReplayGain) */
127
+ AlbumGain: 'REPLAYGAIN_ALBUM_GAIN',
128
+ /** Album peak (ReplayGain) */
129
+ AlbumPeak: 'REPLAYGAIN_ALBUM_PEAK',
130
+ /** Track gain (ReplayGain) */
131
+ TrackGain: 'REPLAYGAIN_TRACK_GAIN',
132
+ /** Track peak (ReplayGain) */
133
+ TrackPeak: 'REPLAYGAIN_TRACK_PEAK',
134
+
135
+ // Special handling
136
+ /** Original artist for covers */
137
+ OriginalArtist: 'ORIGINALARTIST',
138
+ /** Original album */
139
+ OriginalAlbum: 'ORIGINALALBUM',
140
+ /** Original release date */
141
+ OriginalDate: 'ORIGINALDATE',
142
+ /** Script/writing system */
143
+ Script: 'SCRIPT',
144
+ /** Involved people list */
145
+ InvolvedPeopleList: 'INVOLVEDPEOPLELIST',
146
+
147
+ // Technical Properties
148
+ /** Encoder settings/software */
149
+ EncoderSettings: 'ENCODERSETTINGS',
150
+ /** Source media */
151
+ SourceMedia: 'SOURCEMEDIA',
152
+ } as const;
153
+
154
+ /**
155
+ * Type representing all valid tag property names
156
+ */
157
+ export type TagName = typeof Tags[keyof typeof Tags];
158
+
159
+ /**
160
+ * Type guard to check if a string is a valid tag name
161
+ */
162
+ export function isValidTagName(name: string): name is TagName {
163
+ return Object.values(Tags).includes(name as TagName);
164
+ }
165
+
166
+ /**
167
+ * Get all available tag names as an array
168
+ */
169
+ export function getAllTagNames(): readonly TagName[] {
170
+ return Object.values(Tags);
171
+ }
172
+
173
+ /**
174
+ * Format-specific tag mappings (for reference only - TagLib handles these automatically)
175
+ * This shows how standard property names map to format-specific identifiers.
176
+ */
177
+ export const FormatMappings = {
178
+ Title: {
179
+ id3v2: 'TIT2',
180
+ mp4: '©nam',
181
+ vorbis: 'TITLE',
182
+ ape: 'Title',
183
+ riff: 'INAM'
184
+ },
185
+ Artist: {
186
+ id3v2: 'TPE1',
187
+ mp4: '©ART',
188
+ vorbis: 'ARTIST',
189
+ ape: 'Artist',
190
+ riff: 'IART'
191
+ },
192
+ Album: {
193
+ id3v2: 'TALB',
194
+ mp4: '©alb',
195
+ vorbis: 'ALBUM',
196
+ ape: 'Album',
197
+ riff: 'IPRD'
198
+ },
199
+ Date: {
200
+ id3v2: 'TDRC',
201
+ mp4: '©day',
202
+ vorbis: 'DATE',
203
+ ape: 'Year',
204
+ riff: 'ICRD'
205
+ },
206
+ Genre: {
207
+ id3v2: 'TCON',
208
+ mp4: '©gen',
209
+ vorbis: 'GENRE',
210
+ ape: 'Genre',
211
+ riff: 'IGNR'
212
+ },
213
+ Comment: {
214
+ id3v2: 'COMM',
215
+ mp4: '©cmt',
216
+ vorbis: 'COMMENT',
217
+ ape: 'Comment',
218
+ riff: 'ICMT'
219
+ },
220
+ TrackNumber: {
221
+ id3v2: 'TRCK',
222
+ mp4: 'trkn',
223
+ vorbis: 'TRACKNUMBER',
224
+ ape: 'Track',
225
+ riff: 'ITRK'
226
+ }
227
+ } as const;
package/src/types.ts CHANGED
@@ -303,6 +303,11 @@ export interface PropertyMap {
303
303
  [key: string]: string[];
304
304
  }
305
305
 
306
+ /**
307
+ * Re-export TagName type from constants
308
+ */
309
+ export type { TagName } from "./constants.ts";
310
+
306
311
  /**
307
312
  * Picture/artwork data
308
313
  */