taglib-wasm 1.2.1 → 1.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.
- package/dist/index.browser.js +232 -102
- package/dist/simple.browser.js +232 -102
- package/dist/src/constants/complex-properties.d.ts +0 -14
- package/dist/src/constants/complex-properties.d.ts.map +1 -1
- package/dist/src/errors/base.js +5 -2
- package/dist/src/errors/classes.js +13 -10
- package/dist/src/msgpack/encoder.d.ts +6 -0
- package/dist/src/msgpack/encoder.d.ts.map +1 -1
- package/dist/src/msgpack/encoder.js +15 -0
- package/dist/src/runtime/unified-loader/types.js +4 -1
- package/dist/src/runtime/wasi-adapter/file-handle.d.ts +3 -1
- package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/file-handle.js +41 -4
- package/dist/src/runtime/wasi-memory.d.ts +0 -5
- package/dist/src/runtime/wasi-memory.d.ts.map +1 -1
- package/dist/src/runtime/wasi-memory.js +6 -10
- package/dist/src/taglib/audio-file-base.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-base.js +13 -1
- package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-impl.js +22 -39
- package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
- package/dist/src/taglib/embind-adapter.js +18 -0
- package/dist/src/taglib/extra-state-registry.d.ts +26 -0
- package/dist/src/taglib/extra-state-registry.d.ts.map +1 -0
- package/dist/src/taglib/extra-state-registry.js +59 -0
- package/dist/src/taglib/mutable-tag.d.ts +7 -0
- package/dist/src/taglib/mutable-tag.d.ts.map +1 -1
- package/dist/src/taglib/save-reconstruct.d.ts +13 -0
- package/dist/src/taglib/save-reconstruct.d.ts.map +1 -0
- package/dist/src/taglib/save-reconstruct.js +39 -0
- package/dist/src/types/metadata-mappings.d.ts.map +1 -1
- package/dist/src/types/metadata-mappings.js +8 -0
- package/dist/src/types/tags.d.ts +10 -0
- package/dist/src/types/tags.d.ts.map +1 -1
- package/dist/src/utils/tag-mapping.d.ts.map +1 -1
- package/dist/src/utils/tag-mapping.js +7 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/wasm.d.ts +14 -0
- package/dist/src/wasm.d.ts.map +1 -1
- package/dist/taglib-wasi.wasm +0 -0
- package/package.json +7 -8
package/dist/simple.browser.js
CHANGED
|
@@ -292,8 +292,8 @@ var init_base = __esm({
|
|
|
292
292
|
*/
|
|
293
293
|
constructor(code, message, details) {
|
|
294
294
|
super(message);
|
|
295
|
-
this
|
|
296
|
-
this
|
|
295
|
+
__publicField(this, "code", code);
|
|
296
|
+
__publicField(this, "details", details);
|
|
297
297
|
this.name = "TagLibError";
|
|
298
298
|
Object.setPrototypeOf(this, _TagLibError.prototype);
|
|
299
299
|
}
|
|
@@ -353,7 +353,7 @@ var init_classes = __esm({
|
|
|
353
353
|
errorDetails.join(". "),
|
|
354
354
|
{ ...details, bufferSize }
|
|
355
355
|
);
|
|
356
|
-
this
|
|
356
|
+
__publicField(this, "bufferSize", bufferSize);
|
|
357
357
|
this.name = "InvalidFormatError";
|
|
358
358
|
Object.setPrototypeOf(this, _InvalidFormatError.prototype);
|
|
359
359
|
}
|
|
@@ -371,8 +371,8 @@ var init_classes = __esm({
|
|
|
371
371
|
`Unsupported audio format: ${format}. Supported formats: ${supportedFormats.join(", ")}`,
|
|
372
372
|
{ ...details, format, supportedFormats }
|
|
373
373
|
);
|
|
374
|
-
this
|
|
375
|
-
this
|
|
374
|
+
__publicField(this, "format", format);
|
|
375
|
+
__publicField(this, "supportedFormats", supportedFormats);
|
|
376
376
|
this.name = "UnsupportedFormatError";
|
|
377
377
|
Object.setPrototypeOf(this, _UnsupportedFormatError.prototype);
|
|
378
378
|
}
|
|
@@ -396,8 +396,8 @@ var init_classes = __esm({
|
|
|
396
396
|
errorDetails.join(". "),
|
|
397
397
|
{ ...details, operation, path }
|
|
398
398
|
);
|
|
399
|
-
this
|
|
400
|
-
this
|
|
399
|
+
__publicField(this, "operation", operation);
|
|
400
|
+
__publicField(this, "path", path);
|
|
401
401
|
this.name = "FileOperationError";
|
|
402
402
|
Object.setPrototypeOf(this, _FileOperationError.prototype);
|
|
403
403
|
}
|
|
@@ -421,8 +421,8 @@ var init_classes = __esm({
|
|
|
421
421
|
errorDetails.join(". "),
|
|
422
422
|
{ ...details, operation, field }
|
|
423
423
|
);
|
|
424
|
-
this
|
|
425
|
-
this
|
|
424
|
+
__publicField(this, "operation", operation);
|
|
425
|
+
__publicField(this, "field", field);
|
|
426
426
|
this.name = "MetadataError";
|
|
427
427
|
Object.setPrototypeOf(this, _MetadataError.prototype);
|
|
428
428
|
}
|
|
@@ -453,9 +453,9 @@ var init_classes = __esm({
|
|
|
453
453
|
constructor(environment, reason, requiredFeature) {
|
|
454
454
|
const message = requiredFeature ? `Environment '${environment}' ${reason}. Required feature: ${requiredFeature}.` : `Environment '${environment}' ${reason}.`;
|
|
455
455
|
super("ENVIRONMENT", message);
|
|
456
|
-
this
|
|
457
|
-
this
|
|
458
|
-
this
|
|
456
|
+
__publicField(this, "environment", environment);
|
|
457
|
+
__publicField(this, "reason", reason);
|
|
458
|
+
__publicField(this, "requiredFeature", requiredFeature);
|
|
459
459
|
this.name = "EnvironmentError";
|
|
460
460
|
Object.setPrototypeOf(this, _EnvironmentError.prototype);
|
|
461
461
|
}
|
|
@@ -561,60 +561,6 @@ var init_platform_io_browser_stub = __esm({
|
|
|
561
561
|
}
|
|
562
562
|
});
|
|
563
563
|
|
|
564
|
-
// src/utils/file.ts
|
|
565
|
-
async function readFileData(file) {
|
|
566
|
-
if (file instanceof Uint8Array) return file;
|
|
567
|
-
if (file instanceof ArrayBuffer) return new Uint8Array(file);
|
|
568
|
-
if (typeof File !== "undefined" && file instanceof File) {
|
|
569
|
-
return new Uint8Array(await file.arrayBuffer());
|
|
570
|
-
}
|
|
571
|
-
if (typeof file === "string") {
|
|
572
|
-
try {
|
|
573
|
-
return await getPlatformIO().readFile(file);
|
|
574
|
-
} catch (error) {
|
|
575
|
-
if (error instanceof EnvironmentError) throw error;
|
|
576
|
-
throw new FileOperationError("read", error.message, file);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
const inputType = Object.prototype.toString.call(file);
|
|
580
|
-
throw new FileOperationError(
|
|
581
|
-
"read",
|
|
582
|
-
`Invalid file input type: ${inputType}. Expected string path, Uint8Array, ArrayBuffer, or File object.`
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
async function getFileSize(path) {
|
|
586
|
-
try {
|
|
587
|
-
const s = await getPlatformIO().stat(path);
|
|
588
|
-
return s.size;
|
|
589
|
-
} catch (error) {
|
|
590
|
-
if (error instanceof EnvironmentError) throw error;
|
|
591
|
-
throw new FileOperationError("stat", error.message, path);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
async function readPartialFileData(path, headerSize, footerSize) {
|
|
595
|
-
const io = getPlatformIO();
|
|
596
|
-
if (!io.readPartial) {
|
|
597
|
-
throw new EnvironmentError(
|
|
598
|
-
"current runtime",
|
|
599
|
-
"does not support partial file reading",
|
|
600
|
-
"filesystem access with seek support"
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
try {
|
|
604
|
-
return await io.readPartial(path, headerSize, footerSize);
|
|
605
|
-
} catch (error) {
|
|
606
|
-
if (error instanceof EnvironmentError) throw error;
|
|
607
|
-
throw new FileOperationError("read", error.message, path);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
var init_file = __esm({
|
|
611
|
-
"src/utils/file.ts"() {
|
|
612
|
-
"use strict";
|
|
613
|
-
init_errors2();
|
|
614
|
-
init_platform_io_browser_stub();
|
|
615
|
-
}
|
|
616
|
-
});
|
|
617
|
-
|
|
618
564
|
// src/utils/write.ts
|
|
619
565
|
async function writeFileData(path, data) {
|
|
620
566
|
try {
|
|
@@ -1383,7 +1329,7 @@ var init_audio_file_base = __esm({
|
|
|
1383
1329
|
init_errors2();
|
|
1384
1330
|
BaseAudioFileImpl = class {
|
|
1385
1331
|
constructor(module, fileHandle, sourcePath, originalSource, isPartiallyLoaded = false, partialLoadOptions) {
|
|
1386
|
-
this
|
|
1332
|
+
__publicField(this, "module", module);
|
|
1387
1333
|
__publicField(this, "fileHandle");
|
|
1388
1334
|
__publicField(this, "cachedAudioProperties", null);
|
|
1389
1335
|
__publicField(this, "sourcePath");
|
|
@@ -1433,6 +1379,9 @@ var init_audio_file_base = __esm({
|
|
|
1433
1379
|
get track() {
|
|
1434
1380
|
return data.track;
|
|
1435
1381
|
},
|
|
1382
|
+
get date() {
|
|
1383
|
+
return handle.getProperty("DATE") || void 0;
|
|
1384
|
+
},
|
|
1436
1385
|
setTitle: (value) => {
|
|
1437
1386
|
handle.setTagData({ title: value });
|
|
1438
1387
|
data = handle.getTagData();
|
|
@@ -1467,6 +1416,15 @@ var init_audio_file_base = __esm({
|
|
|
1467
1416
|
handle.setTagData({ track: value });
|
|
1468
1417
|
data = handle.getTagData();
|
|
1469
1418
|
return tag;
|
|
1419
|
+
},
|
|
1420
|
+
setDate: (value) => {
|
|
1421
|
+
if (value === "") {
|
|
1422
|
+
handle.setTagData({ year: 0 });
|
|
1423
|
+
} else {
|
|
1424
|
+
handle.setProperty("DATE", value);
|
|
1425
|
+
}
|
|
1426
|
+
data = handle.getTagData();
|
|
1427
|
+
return tag;
|
|
1470
1428
|
}
|
|
1471
1429
|
};
|
|
1472
1430
|
return tag;
|
|
@@ -1533,6 +1491,60 @@ var init_audio_file_base = __esm({
|
|
|
1533
1491
|
}
|
|
1534
1492
|
});
|
|
1535
1493
|
|
|
1494
|
+
// src/utils/file.ts
|
|
1495
|
+
async function readFileData(file) {
|
|
1496
|
+
if (file instanceof Uint8Array) return file;
|
|
1497
|
+
if (file instanceof ArrayBuffer) return new Uint8Array(file);
|
|
1498
|
+
if (typeof File !== "undefined" && file instanceof File) {
|
|
1499
|
+
return new Uint8Array(await file.arrayBuffer());
|
|
1500
|
+
}
|
|
1501
|
+
if (typeof file === "string") {
|
|
1502
|
+
try {
|
|
1503
|
+
return await getPlatformIO().readFile(file);
|
|
1504
|
+
} catch (error) {
|
|
1505
|
+
if (error instanceof EnvironmentError) throw error;
|
|
1506
|
+
throw new FileOperationError("read", error.message, file);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
const inputType = Object.prototype.toString.call(file);
|
|
1510
|
+
throw new FileOperationError(
|
|
1511
|
+
"read",
|
|
1512
|
+
`Invalid file input type: ${inputType}. Expected string path, Uint8Array, ArrayBuffer, or File object.`
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
async function getFileSize(path) {
|
|
1516
|
+
try {
|
|
1517
|
+
const s = await getPlatformIO().stat(path);
|
|
1518
|
+
return s.size;
|
|
1519
|
+
} catch (error) {
|
|
1520
|
+
if (error instanceof EnvironmentError) throw error;
|
|
1521
|
+
throw new FileOperationError("stat", error.message, path);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
async function readPartialFileData(path, headerSize, footerSize) {
|
|
1525
|
+
const io = getPlatformIO();
|
|
1526
|
+
if (!io.readPartial) {
|
|
1527
|
+
throw new EnvironmentError(
|
|
1528
|
+
"current runtime",
|
|
1529
|
+
"does not support partial file reading",
|
|
1530
|
+
"filesystem access with seek support"
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
try {
|
|
1534
|
+
return await io.readPartial(path, headerSize, footerSize);
|
|
1535
|
+
} catch (error) {
|
|
1536
|
+
if (error instanceof EnvironmentError) throw error;
|
|
1537
|
+
throw new FileOperationError("read", error.message, path);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
var init_file = __esm({
|
|
1541
|
+
"src/utils/file.ts"() {
|
|
1542
|
+
"use strict";
|
|
1543
|
+
init_errors2();
|
|
1544
|
+
init_platform_io_browser_stub();
|
|
1545
|
+
}
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1536
1548
|
// src/taglib/embind-adapter.ts
|
|
1537
1549
|
function isValidBitrateMode(value) {
|
|
1538
1550
|
return value === "CBR" || value === "VBR" || value === "ABR";
|
|
@@ -1579,6 +1591,24 @@ function wrapEmbindHandle(raw) {
|
|
|
1579
1591
|
data ?? null
|
|
1580
1592
|
);
|
|
1581
1593
|
},
|
|
1594
|
+
// Emscripten exposes USLT only through the PropertyMap "LYRICS" key (no
|
|
1595
|
+
// dedicated Embind binding), so bridge get/setLyrics to get/setProperties.
|
|
1596
|
+
// Text only — language/description are not surfaced by the PropertyMap.
|
|
1597
|
+
getLyrics() {
|
|
1598
|
+
const props = raw.getProperties();
|
|
1599
|
+
return (props["LYRICS"] ?? []).map((text) => ({
|
|
1600
|
+
text,
|
|
1601
|
+
description: "",
|
|
1602
|
+
language: ""
|
|
1603
|
+
}));
|
|
1604
|
+
},
|
|
1605
|
+
setLyrics(lyrics) {
|
|
1606
|
+
const handle = raw;
|
|
1607
|
+
const props = handle.getProperties();
|
|
1608
|
+
if (lyrics.length > 0) props["LYRICS"] = lyrics.map((l) => l.text);
|
|
1609
|
+
else delete props["LYRICS"];
|
|
1610
|
+
handle.setProperties(props);
|
|
1611
|
+
},
|
|
1582
1612
|
hasId3Tags() {
|
|
1583
1613
|
const v = raw.hasId3Tags();
|
|
1584
1614
|
if (!v || typeof v !== "object") return { v1: false, v2: false };
|
|
@@ -1628,6 +1658,112 @@ var init_embind_adapter = __esm({
|
|
|
1628
1658
|
}
|
|
1629
1659
|
});
|
|
1630
1660
|
|
|
1661
|
+
// src/taglib/extra-state-registry.ts
|
|
1662
|
+
function chapterStyle(chapters) {
|
|
1663
|
+
const s = chapters[0]?.source;
|
|
1664
|
+
return s === "nero" || s === "both" ? s : "quicktime";
|
|
1665
|
+
}
|
|
1666
|
+
function copyExtraState(target, source, sourceComplete) {
|
|
1667
|
+
for (const field of EXTRA_FIELDS) {
|
|
1668
|
+
field.copy(target, source, sourceComplete);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
var EXTRA_FIELDS;
|
|
1672
|
+
var init_extra_state_registry = __esm({
|
|
1673
|
+
"src/taglib/extra-state-registry.ts"() {
|
|
1674
|
+
"use strict";
|
|
1675
|
+
EXTRA_FIELDS = [
|
|
1676
|
+
{
|
|
1677
|
+
name: "pictures",
|
|
1678
|
+
copy(target, source, complete) {
|
|
1679
|
+
const v = source.getPictures();
|
|
1680
|
+
if (complete || v.length > 0) target.setPictures(v);
|
|
1681
|
+
}
|
|
1682
|
+
},
|
|
1683
|
+
{
|
|
1684
|
+
name: "ratings",
|
|
1685
|
+
copy(target, source, complete) {
|
|
1686
|
+
const v = source.getRatings();
|
|
1687
|
+
if (complete || v.length > 0) target.setRatings(v);
|
|
1688
|
+
}
|
|
1689
|
+
},
|
|
1690
|
+
{
|
|
1691
|
+
name: "lyrics",
|
|
1692
|
+
copy(target, source, complete) {
|
|
1693
|
+
const v = source.getLyrics();
|
|
1694
|
+
if (complete || v.length > 0) target.setLyrics(v);
|
|
1695
|
+
}
|
|
1696
|
+
},
|
|
1697
|
+
{
|
|
1698
|
+
name: "chapters",
|
|
1699
|
+
copy(target, source, complete) {
|
|
1700
|
+
const v = source.getChapters();
|
|
1701
|
+
if (complete || v.length > 0) target.setChapters(v, chapterStyle(v));
|
|
1702
|
+
}
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
name: "bextData",
|
|
1706
|
+
copy(target, source, complete) {
|
|
1707
|
+
const v = source.getBextData();
|
|
1708
|
+
if (v !== void 0) target.setBextData(v);
|
|
1709
|
+
else if (complete) target.setBextData(null);
|
|
1710
|
+
}
|
|
1711
|
+
},
|
|
1712
|
+
{
|
|
1713
|
+
name: "ixml",
|
|
1714
|
+
copy(target, source, complete) {
|
|
1715
|
+
const v = source.getIxml();
|
|
1716
|
+
if (v !== void 0) target.setIxml(v);
|
|
1717
|
+
else if (complete) target.setIxml(null);
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
];
|
|
1721
|
+
}
|
|
1722
|
+
});
|
|
1723
|
+
|
|
1724
|
+
// src/taglib/save-reconstruct.ts
|
|
1725
|
+
function copyEditedState(target, source, sourceComplete) {
|
|
1726
|
+
target.setTagData(source.getTagData());
|
|
1727
|
+
target.setProperties(
|
|
1728
|
+
sourceComplete ? source.getProperties() : { ...target.getProperties(), ...source.getProperties() }
|
|
1729
|
+
);
|
|
1730
|
+
copyExtraState(target, source, sourceComplete);
|
|
1731
|
+
}
|
|
1732
|
+
async function saveViaFreshHandle(module, editing, source, targetPath, sourceComplete) {
|
|
1733
|
+
const rawFullHandle = module.createFileHandle();
|
|
1734
|
+
const fullFileHandle = module.isWasi ? rawFullHandle : wrapEmbindHandle(rawFullHandle);
|
|
1735
|
+
try {
|
|
1736
|
+
{
|
|
1737
|
+
const data = await readFileData(source);
|
|
1738
|
+
if (!fullFileHandle.loadFromBuffer(data)) {
|
|
1739
|
+
throw new InvalidFormatError(
|
|
1740
|
+
"Failed to load full audio file for saving"
|
|
1741
|
+
);
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
copyEditedState(fullFileHandle, editing, sourceComplete);
|
|
1745
|
+
if (!fullFileHandle.save()) {
|
|
1746
|
+
throw new FileOperationError(
|
|
1747
|
+
"save",
|
|
1748
|
+
"Failed to save changes to full file"
|
|
1749
|
+
);
|
|
1750
|
+
}
|
|
1751
|
+
await writeFileData(targetPath, fullFileHandle.getBuffer());
|
|
1752
|
+
} finally {
|
|
1753
|
+
fullFileHandle.destroy();
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
var init_save_reconstruct = __esm({
|
|
1757
|
+
"src/taglib/save-reconstruct.ts"() {
|
|
1758
|
+
"use strict";
|
|
1759
|
+
init_errors2();
|
|
1760
|
+
init_file();
|
|
1761
|
+
init_write();
|
|
1762
|
+
init_embind_adapter();
|
|
1763
|
+
init_extra_state_registry();
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1766
|
+
|
|
1631
1767
|
// src/taglib/audio-file-impl.ts
|
|
1632
1768
|
function sortChapters(list) {
|
|
1633
1769
|
return [...list].sort((a, b) => a.startTimeMs - b.startTimeMs);
|
|
@@ -1657,10 +1793,9 @@ var init_audio_file_impl = __esm({
|
|
|
1657
1793
|
init_types2();
|
|
1658
1794
|
init_audio_file_bwf();
|
|
1659
1795
|
init_errors2();
|
|
1660
|
-
init_file();
|
|
1661
1796
|
init_write();
|
|
1662
1797
|
init_audio_file_base();
|
|
1663
|
-
|
|
1798
|
+
init_save_reconstruct();
|
|
1664
1799
|
AudioFileImpl = class extends BaseAudioFileImpl {
|
|
1665
1800
|
constructor(module, fileHandle, sourcePath, originalSource, isPartiallyLoaded = false, partialLoadOptions) {
|
|
1666
1801
|
super(
|
|
@@ -1706,38 +1841,23 @@ var init_audio_file_impl = __esm({
|
|
|
1706
1841
|
);
|
|
1707
1842
|
}
|
|
1708
1843
|
if (this.isPartiallyLoaded && this.originalSource) {
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
if (!success) {
|
|
1717
|
-
throw new InvalidFormatError(
|
|
1718
|
-
"Failed to load full audio file for saving"
|
|
1719
|
-
);
|
|
1720
|
-
}
|
|
1721
|
-
fullFileHandle.setTagData(this.handle.getTagData());
|
|
1722
|
-
fullFileHandle.setProperties(this.handle.getProperties());
|
|
1723
|
-
fullFileHandle.setPictures(this.handle.getPictures());
|
|
1724
|
-
const bextBytes = this.handle.getBextData();
|
|
1725
|
-
if (bextBytes !== void 0) fullFileHandle.setBextData(bextBytes);
|
|
1726
|
-
const ixmlStr = this.handle.getIxml();
|
|
1727
|
-
if (ixmlStr !== void 0) fullFileHandle.setIxml(ixmlStr);
|
|
1728
|
-
if (!fullFileHandle.save()) {
|
|
1729
|
-
throw new FileOperationError(
|
|
1730
|
-
"save",
|
|
1731
|
-
"Failed to save changes to full file"
|
|
1732
|
-
);
|
|
1733
|
-
}
|
|
1734
|
-
const buffer = fullFileHandle.getBuffer();
|
|
1735
|
-
await writeFileData(targetPath, buffer);
|
|
1736
|
-
} finally {
|
|
1737
|
-
fullFileHandle.destroy();
|
|
1738
|
-
}
|
|
1844
|
+
await saveViaFreshHandle(
|
|
1845
|
+
this.module,
|
|
1846
|
+
this.handle,
|
|
1847
|
+
this.originalSource,
|
|
1848
|
+
targetPath,
|
|
1849
|
+
false
|
|
1850
|
+
);
|
|
1739
1851
|
this.isPartiallyLoaded = false;
|
|
1740
1852
|
this.originalSource = void 0;
|
|
1853
|
+
} else if (this.module.isWasi && this.sourcePath && targetPath !== this.sourcePath) {
|
|
1854
|
+
await saveViaFreshHandle(
|
|
1855
|
+
this.module,
|
|
1856
|
+
this.handle,
|
|
1857
|
+
this.sourcePath,
|
|
1858
|
+
targetPath,
|
|
1859
|
+
true
|
|
1860
|
+
);
|
|
1741
1861
|
} else {
|
|
1742
1862
|
if (!this.save()) {
|
|
1743
1863
|
throw new FileOperationError(
|
|
@@ -1799,13 +1919,16 @@ var init_audio_file_impl = __esm({
|
|
|
1799
1919
|
}
|
|
1800
1920
|
const sorted = sortChapters(chapters);
|
|
1801
1921
|
const trackEndMs = this.audioProperties()?.durationMs;
|
|
1922
|
+
const style = options?.mp4ChapterStyle ?? "quicktime";
|
|
1923
|
+
const source = fmt === "MP4" ? style : "id3";
|
|
1802
1924
|
const raw = sorted.map((c, i) => ({
|
|
1803
1925
|
id: c.id,
|
|
1804
1926
|
startTimeMs: c.startTimeMs,
|
|
1805
1927
|
endTimeMs: inferEndTimeMs(sorted, i, trackEndMs) ?? c.startTimeMs,
|
|
1806
|
-
title: c.title
|
|
1928
|
+
title: c.title,
|
|
1929
|
+
source
|
|
1807
1930
|
}));
|
|
1808
|
-
this.handle.setChapters(raw,
|
|
1931
|
+
this.handle.setChapters(raw, style);
|
|
1809
1932
|
}
|
|
1810
1933
|
getBext() {
|
|
1811
1934
|
return getBext(this.handle);
|
|
@@ -1911,6 +2034,9 @@ function mapPropertiesToExtendedTag(props) {
|
|
|
1911
2034
|
if (tagField === "year" || tagField === "track") {
|
|
1912
2035
|
const num = parseNumeric(values[0]);
|
|
1913
2036
|
if (num !== void 0) tag[tagField] = num;
|
|
2037
|
+
if (propKey === "date") {
|
|
2038
|
+
tag.date = values.length === 1 ? values[0] : values;
|
|
2039
|
+
}
|
|
1914
2040
|
} else {
|
|
1915
2041
|
tag[tagField] = values;
|
|
1916
2042
|
}
|
|
@@ -1951,6 +2077,9 @@ function normalizeTagInput(input) {
|
|
|
1951
2077
|
if (input.year !== void 0) {
|
|
1952
2078
|
props.date = [String(input.year)];
|
|
1953
2079
|
}
|
|
2080
|
+
if (input.date !== void 0) {
|
|
2081
|
+
props.date = Array.isArray(input.date) ? input.date : [input.date];
|
|
2082
|
+
}
|
|
1954
2083
|
if (input.track !== void 0) {
|
|
1955
2084
|
props.trackNumber = [String(input.track)];
|
|
1956
2085
|
}
|
|
@@ -1989,6 +2118,7 @@ var init_tag_mapping = __esm({
|
|
|
1989
2118
|
"comment",
|
|
1990
2119
|
"genre",
|
|
1991
2120
|
"year",
|
|
2121
|
+
"date",
|
|
1992
2122
|
"track"
|
|
1993
2123
|
]);
|
|
1994
2124
|
NUMERIC_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -2007,7 +2137,7 @@ var VERSION;
|
|
|
2007
2137
|
var init_version = __esm({
|
|
2008
2138
|
"src/version.ts"() {
|
|
2009
2139
|
"use strict";
|
|
2010
|
-
VERSION = "1.
|
|
2140
|
+
VERSION = "1.3.0";
|
|
2011
2141
|
}
|
|
2012
2142
|
});
|
|
2013
2143
|
|
|
@@ -87,20 +87,6 @@ export interface ComplexPropertyValueMap {
|
|
|
87
87
|
* Union type of all valid complex property keys.
|
|
88
88
|
*/
|
|
89
89
|
export type ComplexPropertyKey = keyof ComplexPropertyValueMap;
|
|
90
|
-
/**
|
|
91
|
-
* Complex property metadata interface.
|
|
92
|
-
*/
|
|
93
|
-
export interface ComplexPropertyMetadata {
|
|
94
|
-
key: string;
|
|
95
|
-
description: string;
|
|
96
|
-
type: "binary" | "object";
|
|
97
|
-
supportedFormats: readonly string[];
|
|
98
|
-
mappings: Record<string, string | {
|
|
99
|
-
frame?: string;
|
|
100
|
-
atom?: string;
|
|
101
|
-
description?: string;
|
|
102
|
-
}>;
|
|
103
|
-
}
|
|
104
90
|
/**
|
|
105
91
|
* Rich metadata object for complex properties.
|
|
106
92
|
* Contains descriptions, format support info, and underlying format mappings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complex-properties.d.ts","sourceRoot":"","sources":["../../../src/constants/complex-properties.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,WAAW,MAAM;IACrB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,uBAAuB;IACtC,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,uBAAuB,CAAC;AAE/D
|
|
1
|
+
{"version":3,"file":"complex-properties.d.ts","sourceRoot":"","sources":["../../../src/constants/complex-properties.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,WAAW,MAAM;IACrB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,uBAAuB;IACtC,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,uBAAuB,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CrB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,CAAC,IAAI,kBAAkB,GAAG,CAAC;CACtC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,qBAKzB,CAAC"}
|
package/dist/src/errors/base.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
const SUPPORTED_FORMATS = [
|
|
2
5
|
"MP3",
|
|
3
6
|
"MP4",
|
|
@@ -16,8 +19,8 @@ class TagLibError extends Error {
|
|
|
16
19
|
*/
|
|
17
20
|
constructor(code, message, details) {
|
|
18
21
|
super(message);
|
|
19
|
-
this
|
|
20
|
-
this
|
|
22
|
+
__publicField(this, "code", code);
|
|
23
|
+
__publicField(this, "details", details);
|
|
21
24
|
this.name = "TagLibError";
|
|
22
25
|
Object.setPrototypeOf(this, TagLibError.prototype);
|
|
23
26
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
import { SUPPORTED_FORMATS, TagLibError } from "./base.js";
|
|
2
5
|
function errorMessage(error) {
|
|
3
6
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -48,7 +51,7 @@ class InvalidFormatError extends TagLibError {
|
|
|
48
51
|
errorDetails.join(". "),
|
|
49
52
|
{ ...details, bufferSize }
|
|
50
53
|
);
|
|
51
|
-
this
|
|
54
|
+
__publicField(this, "bufferSize", bufferSize);
|
|
52
55
|
this.name = "InvalidFormatError";
|
|
53
56
|
Object.setPrototypeOf(this, InvalidFormatError.prototype);
|
|
54
57
|
}
|
|
@@ -66,8 +69,8 @@ class UnsupportedFormatError extends TagLibError {
|
|
|
66
69
|
`Unsupported audio format: ${format}. Supported formats: ${supportedFormats.join(", ")}`,
|
|
67
70
|
{ ...details, format, supportedFormats }
|
|
68
71
|
);
|
|
69
|
-
this
|
|
70
|
-
this
|
|
72
|
+
__publicField(this, "format", format);
|
|
73
|
+
__publicField(this, "supportedFormats", supportedFormats);
|
|
71
74
|
this.name = "UnsupportedFormatError";
|
|
72
75
|
Object.setPrototypeOf(this, UnsupportedFormatError.prototype);
|
|
73
76
|
}
|
|
@@ -91,8 +94,8 @@ class FileOperationError extends TagLibError {
|
|
|
91
94
|
errorDetails.join(". "),
|
|
92
95
|
{ ...details, operation, path }
|
|
93
96
|
);
|
|
94
|
-
this
|
|
95
|
-
this
|
|
97
|
+
__publicField(this, "operation", operation);
|
|
98
|
+
__publicField(this, "path", path);
|
|
96
99
|
this.name = "FileOperationError";
|
|
97
100
|
Object.setPrototypeOf(this, FileOperationError.prototype);
|
|
98
101
|
}
|
|
@@ -116,8 +119,8 @@ class MetadataError extends TagLibError {
|
|
|
116
119
|
errorDetails.join(". "),
|
|
117
120
|
{ ...details, operation, field }
|
|
118
121
|
);
|
|
119
|
-
this
|
|
120
|
-
this
|
|
122
|
+
__publicField(this, "operation", operation);
|
|
123
|
+
__publicField(this, "field", field);
|
|
121
124
|
this.name = "MetadataError";
|
|
122
125
|
Object.setPrototypeOf(this, MetadataError.prototype);
|
|
123
126
|
}
|
|
@@ -148,9 +151,9 @@ class EnvironmentError extends TagLibError {
|
|
|
148
151
|
constructor(environment, reason, requiredFeature) {
|
|
149
152
|
const message = requiredFeature ? `Environment '${environment}' ${reason}. Required feature: ${requiredFeature}.` : `Environment '${environment}' ${reason}.`;
|
|
150
153
|
super("ENVIRONMENT", message);
|
|
151
|
-
this
|
|
152
|
-
this
|
|
153
|
-
this
|
|
154
|
+
__publicField(this, "environment", environment);
|
|
155
|
+
__publicField(this, "reason", reason);
|
|
156
|
+
__publicField(this, "requiredFeature", requiredFeature);
|
|
154
157
|
this.name = "EnvironmentError";
|
|
155
158
|
Object.setPrototypeOf(this, EnvironmentError.prototype);
|
|
156
159
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/** MessagePack encoder — converts JS objects to binary MessagePack for the C API. */
|
|
2
2
|
import { type EncoderOptions } from "@msgpack/msgpack";
|
|
3
3
|
import type { AudioProperties, ExtendedTag, Picture, PropertyMap } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Structured (non-text-property) keys carried verbatim through the msgpack
|
|
6
|
+
* boundary. The reconstruct registry (`extra-state-registry.ts`) must cover the
|
|
7
|
+
* data fields here; `extra-state-registry.test.ts` enforces that cross-check.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PASSTHROUGH_KEYS: Set<string>;
|
|
4
10
|
export declare function encodeTagData(tagData: ExtendedTag): Uint8Array;
|
|
5
11
|
export declare function encodeAudioProperties(audioProps: AudioProperties): Uint8Array;
|
|
6
12
|
export declare function encodePropertyMap(propertyMap: PropertyMap): Uint8Array;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/msgpack/encoder.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,OAAO,EACP,WAAW,EACZ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/msgpack/encoder.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,OAAO,EACP,WAAW,EACZ,MAAM,aAAa,CAAC;AAGrB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,aAU3B,CAAC;AA4BH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAsC9D;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,eAAe,GAAG,UAAU,CAS7E;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAStE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAe1D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,CAelE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,IAAI,EAAE,CAAC,EACP,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,UAAU,CAUZ;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,UAAU,CAe/D;AAqBD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,UAAU,CAc1E;AAED,wBAAiB,uBAAuB,CAAC,CAAC,EACxC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GACxB,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CActC;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAS7D;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAC1E,UAAU,CAeZ;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAW7D;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAaA"}
|
|
@@ -20,10 +20,24 @@ const MSGPACK_ENCODE_OPTIONS = {
|
|
|
20
20
|
maxDepth: 32,
|
|
21
21
|
extensionCodec: void 0
|
|
22
22
|
};
|
|
23
|
+
function lyricsTexts(value) {
|
|
24
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
25
|
+
return entries.map(
|
|
26
|
+
(entry) => typeof entry === "string" ? entry : String(entry?.text ?? "")
|
|
27
|
+
).filter((text) => text !== "");
|
|
28
|
+
}
|
|
23
29
|
function encodeTagData(tagData) {
|
|
24
30
|
try {
|
|
31
|
+
const dateVal = tagData.date;
|
|
32
|
+
const hasDate = Array.isArray(dateVal) ? dateVal.length > 0 : dateVal !== void 0 && dateVal !== null && dateVal !== "";
|
|
25
33
|
const remapped = {};
|
|
26
34
|
for (const [key, value] of Object.entries(tagData)) {
|
|
35
|
+
if (key === "year" && hasDate) continue;
|
|
36
|
+
if (key === "lyrics") {
|
|
37
|
+
const texts = lyricsTexts(value);
|
|
38
|
+
if (texts.length > 0) remapped["LYRICS"] = texts;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
27
41
|
if (PASSTHROUGH_KEYS.has(key)) {
|
|
28
42
|
remapped[key] = value;
|
|
29
43
|
} else {
|
|
@@ -212,6 +226,7 @@ function compareEncodingEfficiency(data) {
|
|
|
212
226
|
};
|
|
213
227
|
}
|
|
214
228
|
export {
|
|
229
|
+
PASSTHROUGH_KEYS,
|
|
215
230
|
canEncodeToMessagePack,
|
|
216
231
|
compareEncodingEfficiency,
|
|
217
232
|
encodeAudioProperties,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
import { TagLibError } from "../../errors/base.js";
|
|
2
5
|
class UnifiedLoaderError extends TagLibError {
|
|
3
6
|
constructor(message, cause) {
|
|
@@ -10,7 +13,7 @@ class UnifiedLoaderError extends TagLibError {
|
|
|
10
13
|
class ModuleLoadError extends TagLibError {
|
|
11
14
|
constructor(message, wasmType, cause) {
|
|
12
15
|
super("MODULE_LOAD", message, cause ? { cause, wasmType } : { wasmType });
|
|
13
|
-
this
|
|
16
|
+
__publicField(this, "wasmType", wasmType);
|
|
14
17
|
this.name = "ModuleLoadError";
|
|
15
18
|
if (cause) this.cause = cause;
|
|
16
19
|
Object.setPrototypeOf(this, ModuleLoadError.prototype);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview WASI-based FileHandle implementation
|
|
3
3
|
*/
|
|
4
|
-
import type { FileHandle, RawChapter, RawPicture } from "../../wasm.js";
|
|
4
|
+
import type { FileHandle, RawChapter, RawLyrics, RawPicture } from "../../wasm.js";
|
|
5
5
|
import type { BasicTagData } from "../../types/tags.js";
|
|
6
6
|
import type { AudioProperties } from "../../types.js";
|
|
7
7
|
import type { WasiModule } from "../wasmer-sdk-loader/types.js";
|
|
@@ -59,6 +59,8 @@ export declare class WasiFileHandle implements FileHandle {
|
|
|
59
59
|
email?: string;
|
|
60
60
|
counter?: number;
|
|
61
61
|
}[]): void;
|
|
62
|
+
getLyrics(): RawLyrics[];
|
|
63
|
+
setLyrics(lyrics: RawLyrics[]): void;
|
|
62
64
|
destroy(): void;
|
|
63
65
|
}
|
|
64
66
|
//# sourceMappingURL=file-handle.d.ts.map
|