taglib-wasm 1.4.2 → 1.5.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/README.md +34 -0
- package/dist/index.browser.js +84 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/simple.browser.js +84 -1
- package/dist/src/constants/complex-properties.d.ts +19 -0
- package/dist/src/constants/complex-properties.d.ts.map +1 -1
- package/dist/src/msgpack/encoder.d.ts.map +1 -1
- package/dist/src/msgpack/encoder.js +1 -0
- package/dist/src/runtime/loader-types.d.ts +5 -2
- package/dist/src/runtime/loader-types.d.ts.map +1 -1
- package/dist/src/runtime/module-loader.d.ts +3 -2
- package/dist/src/runtime/module-loader.d.ts.map +1 -1
- package/dist/src/runtime/module-loader.js +12 -0
- package/dist/src/runtime/unified-loader/loader.d.ts.map +1 -1
- package/dist/src/runtime/unified-loader/loader.js +7 -0
- package/dist/src/runtime/unified-loader/module-loading.js +7 -0
- package/dist/src/runtime/unified-loader/module-selection.d.ts.map +1 -1
- package/dist/src/runtime/unified-loader/module-selection.js +3 -0
- package/dist/src/runtime/unified-loader/types.d.ts +4 -1
- package/dist/src/runtime/unified-loader/types.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/file-handle.d.ts +5 -1
- package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/file-handle.js +34 -0
- package/dist/src/runtime/wasi-adapter/wasm-io.d.ts +2 -0
- package/dist/src/runtime/wasi-adapter/wasm-io.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/wasm-io.js +56 -1
- package/dist/src/runtime/wasi-host-loader.d.ts.map +1 -1
- package/dist/src/runtime/wasi-host-loader.js +4 -1
- package/dist/src/runtime/wasmer-sdk-loader/types.d.ts +1 -0
- package/dist/src/runtime/wasmer-sdk-loader/types.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-impl.d.ts +4 -1
- package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-impl.js +22 -0
- package/dist/src/taglib/audio-file-interface.d.ts +16 -1
- package/dist/src/taglib/audio-file-interface.d.ts.map +1 -1
- package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
- package/dist/src/taglib/embind-adapter.js +12 -0
- package/dist/src/taglib/extra-state-registry.d.ts.map +1 -1
- package/dist/src/taglib/extra-state-registry.js +10 -0
- package/dist/src/taglib/id3v2-frames.d.ts +12 -0
- package/dist/src/taglib/id3v2-frames.d.ts.map +1 -0
- package/dist/src/taglib/id3v2-frames.js +42 -0
- package/dist/src/types/metadata-mappings.d.ts +1 -1
- package/dist/src/types/metadata-mappings.d.ts.map +1 -1
- package/dist/src/types/tags.d.ts +2 -0
- package/dist/src/types/tags.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/wasm.d.ts +20 -0
- package/dist/src/wasm.d.ts.map +1 -1
- package/dist/taglib-wasi.wasm +0 -0
- package/dist/taglib-web.wasm +0 -0
- package/dist/taglib-wrapper.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,10 @@ const wasmBinary = await Deno.readFile(
|
|
|
114
114
|
const taglib = await TagLib.initialize({ wasmBinary });
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
Supplying `wasmBinary` selects the Emscripten backend (the bytes above are
|
|
118
|
+
`taglib-web.wasm`, its artifact). The WASI backend loads from a filesystem
|
|
119
|
+
path or URL instead — use `wasmUrl` with it.
|
|
120
|
+
|
|
117
121
|
## Quick Start
|
|
118
122
|
|
|
119
123
|
> **Import paths:** Deno uses `@charlesw/taglib-wasm`, npm uses `taglib-wasm`.
|
|
@@ -319,6 +323,36 @@ removes the chunk. iXML is passed through verbatim as a string
|
|
|
319
323
|
measurements, distinct from ReplayGain tags. `bwf.decodeBext` / `bwf.encodeBext`
|
|
320
324
|
are also exported for working with raw `bext` bytes directly.
|
|
321
325
|
|
|
326
|
+
### Raw ID3v2 Frames (Escape Hatch)
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
import { TagLib } from "taglib-wasm";
|
|
330
|
+
|
|
331
|
+
const taglib = await TagLib.initialize();
|
|
332
|
+
using file = await taglib.open("song.mp3");
|
|
333
|
+
|
|
334
|
+
// Escape hatch: read/write raw ID3v2 frame bytes by ID (MP3 only)
|
|
335
|
+
const frames = file.getId3v2Frames("TXXX"); // [{ id, data, flags? }]
|
|
336
|
+
file.setId3v2Frames("RGAD", [rgadBody]); // replaces ALL RGAD frames
|
|
337
|
+
file.removeId3v2Frames("NCON"); // removes every NCON frame
|
|
338
|
+
file.save();
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`data` is the frame body without the 10-byte header; the caller owns the body
|
|
342
|
+
encoding. Bytes round-trip verbatim for frames TagLib does not model. For
|
|
343
|
+
TagLib-modeled IDs (`TIT2`, `APIC`, …): typed getters see a raw write only
|
|
344
|
+
after save+reload; bytes may be normalized by later saves after that reload;
|
|
345
|
+
and raw reads reflect persisted state plus pending raw writes — not pending
|
|
346
|
+
typed edits (backend-dependent). A typed write to the same ID as an existing
|
|
347
|
+
raw write is silently ignored until that raw frame is removed or the file is
|
|
348
|
+
saved and reloaded — raw writes always win within a save. Frames with
|
|
349
|
+
compression/encryption flags are not supported for write (writes emit zero
|
|
350
|
+
flags). `flags` exists on the returned frames for forward compatibility, but
|
|
351
|
+
reads never populate it today — TagLib always blanks header flags when
|
|
352
|
+
re-rendering a frame. On both backends, a raw write to an ID3v1-mapped frame ID
|
|
353
|
+
(`TIT2`, `TPE1`, `TALB`, `COMM`, `TCON`, `TDRC`, `TRCK`) suspends the usual
|
|
354
|
+
ID3v1↔ID3v2 duplicate-sync on `save()` until that raw frame is removed.
|
|
355
|
+
|
|
322
356
|
### Container Format and Codec Detection
|
|
323
357
|
|
|
324
358
|
```typescript
|
package/dist/index.browser.js
CHANGED
|
@@ -564,6 +564,50 @@ var init_audio_file_bwf = __esm({
|
|
|
564
564
|
}
|
|
565
565
|
});
|
|
566
566
|
|
|
567
|
+
// src/taglib/id3v2-frames.ts
|
|
568
|
+
function assertMp3(format) {
|
|
569
|
+
if (format !== "MP3") {
|
|
570
|
+
throw new UnsupportedFormatError(format, ["MP3"], {
|
|
571
|
+
operation: "id3v2Frames"
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function assertFrameId(id, operation) {
|
|
576
|
+
if (!FRAME_ID_PATTERN.test(id)) {
|
|
577
|
+
throw new MetadataError(
|
|
578
|
+
operation,
|
|
579
|
+
`Invalid ID3v2 frame ID: "${id}". Frame IDs must match [A-Z0-9]{4}`,
|
|
580
|
+
id
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
function assertFrameBodies(id, data) {
|
|
585
|
+
for (const body of data) {
|
|
586
|
+
if (body.length === 0) {
|
|
587
|
+
throw new MetadataError(
|
|
588
|
+
"write",
|
|
589
|
+
"Frame data must not be empty: zero-size ID3v2 frames are invalid",
|
|
590
|
+
id
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function toPublicFrame(frame) {
|
|
596
|
+
return {
|
|
597
|
+
id: frame.id,
|
|
598
|
+
data: frame.data,
|
|
599
|
+
...frame.flags ? { flags: frame.flags } : {}
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
var FRAME_ID_PATTERN;
|
|
603
|
+
var init_id3v2_frames = __esm({
|
|
604
|
+
"src/taglib/id3v2-frames.ts"() {
|
|
605
|
+
"use strict";
|
|
606
|
+
init_classes();
|
|
607
|
+
FRAME_ID_PATTERN = /^[A-Z0-9]{4}$/;
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
|
|
567
611
|
// browser-stub:platform-io-browser-stub
|
|
568
612
|
function getPlatformIO() {
|
|
569
613
|
throw new Error("Filesystem operations are not available in the browser.");
|
|
@@ -1590,6 +1634,7 @@ function isValidBitrateMode(value) {
|
|
|
1590
1634
|
return value === "CBR" || value === "VBR" || value === "ABR";
|
|
1591
1635
|
}
|
|
1592
1636
|
function wrapEmbindHandle(raw) {
|
|
1637
|
+
const stagedId3v2Frames = {};
|
|
1593
1638
|
const overrides = {
|
|
1594
1639
|
getTagData() {
|
|
1595
1640
|
const tw = raw.getTag();
|
|
@@ -1649,6 +1694,17 @@ function wrapEmbindHandle(raw) {
|
|
|
1649
1694
|
else delete props["LYRICS"];
|
|
1650
1695
|
handle.setProperties(props);
|
|
1651
1696
|
},
|
|
1697
|
+
setId3v2Frames(id, data) {
|
|
1698
|
+
stagedId3v2Frames[id] = data.map((d) => new Uint8Array(d));
|
|
1699
|
+
raw.setId3v2Frames(id, data);
|
|
1700
|
+
},
|
|
1701
|
+
removeId3v2Frames(id) {
|
|
1702
|
+
stagedId3v2Frames[id] = [];
|
|
1703
|
+
raw.removeId3v2Frames(id);
|
|
1704
|
+
},
|
|
1705
|
+
getStagedId3v2Frames() {
|
|
1706
|
+
return Object.keys(stagedId3v2Frames).length > 0 ? { ...stagedId3v2Frames } : void 0;
|
|
1707
|
+
},
|
|
1652
1708
|
hasId3Tags() {
|
|
1653
1709
|
const v = raw.hasId3Tags();
|
|
1654
1710
|
if (!v || typeof v !== "object") return { v1: false, v2: false };
|
|
@@ -1756,6 +1812,16 @@ var init_extra_state_registry = __esm({
|
|
|
1756
1812
|
if (v !== void 0) target.setIxml(v);
|
|
1757
1813
|
else if (complete) target.setIxml(null);
|
|
1758
1814
|
}
|
|
1815
|
+
},
|
|
1816
|
+
{
|
|
1817
|
+
name: "id3v2Frames",
|
|
1818
|
+
copy(target, source) {
|
|
1819
|
+
const staged = source.getStagedId3v2Frames?.();
|
|
1820
|
+
if (!staged) return;
|
|
1821
|
+
for (const [id, bodies] of Object.entries(staged)) {
|
|
1822
|
+
target.setId3v2Frames(id, bodies);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1759
1825
|
}
|
|
1760
1826
|
];
|
|
1761
1827
|
}
|
|
@@ -1832,6 +1898,7 @@ var init_audio_file_impl = __esm({
|
|
|
1832
1898
|
"use strict";
|
|
1833
1899
|
init_types2();
|
|
1834
1900
|
init_audio_file_bwf();
|
|
1901
|
+
init_id3v2_frames();
|
|
1835
1902
|
init_errors2();
|
|
1836
1903
|
init_write();
|
|
1837
1904
|
init_audio_file_base();
|
|
@@ -2027,6 +2094,22 @@ var init_audio_file_impl = __esm({
|
|
|
2027
2094
|
setRating(rating, email) {
|
|
2028
2095
|
this.setRatings([{ rating, email, counter: 0 }]);
|
|
2029
2096
|
}
|
|
2097
|
+
getId3v2Frames(id) {
|
|
2098
|
+
assertMp3(this.getFormat());
|
|
2099
|
+
if (id !== void 0) assertFrameId(id, "read");
|
|
2100
|
+
return this.handle.getId3v2Frames(id ?? "").map(toPublicFrame);
|
|
2101
|
+
}
|
|
2102
|
+
setId3v2Frames(id, data) {
|
|
2103
|
+
assertMp3(this.getFormat());
|
|
2104
|
+
assertFrameId(id, "write");
|
|
2105
|
+
assertFrameBodies(id, data);
|
|
2106
|
+
this.handle.setId3v2Frames(id, data);
|
|
2107
|
+
}
|
|
2108
|
+
removeId3v2Frames(id) {
|
|
2109
|
+
assertMp3(this.getFormat());
|
|
2110
|
+
assertFrameId(id, "write");
|
|
2111
|
+
this.handle.removeId3v2Frames(id);
|
|
2112
|
+
}
|
|
2030
2113
|
hasId3Tags() {
|
|
2031
2114
|
return this.handle.hasId3Tags();
|
|
2032
2115
|
}
|
|
@@ -2211,7 +2294,7 @@ var VERSION;
|
|
|
2211
2294
|
var init_version = __esm({
|
|
2212
2295
|
"src/version.ts"() {
|
|
2213
2296
|
"use strict";
|
|
2214
|
-
VERSION = "1.
|
|
2297
|
+
VERSION = "1.5.0";
|
|
2215
2298
|
}
|
|
2216
2299
|
});
|
|
2217
2300
|
|
package/dist/index.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export type { PropertyKey, PropertyValue } from "./src/constants.js";
|
|
|
51
51
|
export type { FormatPropertyKey, TagFormat, } from "./src/types/format-property-keys.js";
|
|
52
52
|
export type { TypedAudioProperties } from "./src/types/audio-formats.js";
|
|
53
53
|
export { COMPLEX_PROPERTIES, COMPLEX_PROPERTY_KEY, } from "./src/constants/complex-properties.js";
|
|
54
|
-
export type { ComplexPropertyKey, ComplexPropertyKeyMap, ComplexPropertyValueMap, Rating, UnsyncedLyrics, VariantMap, } from "./src/constants/complex-properties.js";
|
|
54
|
+
export type { ComplexPropertyKey, ComplexPropertyKeyMap, ComplexPropertyValueMap, Id3v2Frame, Rating, UnsyncedLyrics, VariantMap, } from "./src/constants/complex-properties.js";
|
|
55
55
|
export { RatingUtils } from "./src/utils/rating.js";
|
|
56
56
|
export type { NormalizedRating, PopmRating } from "./src/utils/rating.js";
|
|
57
57
|
export * as bwf from "./src/bwf/bext.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
package/dist/simple.browser.js
CHANGED
|
@@ -552,6 +552,50 @@ var init_audio_file_bwf = __esm({
|
|
|
552
552
|
}
|
|
553
553
|
});
|
|
554
554
|
|
|
555
|
+
// src/taglib/id3v2-frames.ts
|
|
556
|
+
function assertMp3(format) {
|
|
557
|
+
if (format !== "MP3") {
|
|
558
|
+
throw new UnsupportedFormatError(format, ["MP3"], {
|
|
559
|
+
operation: "id3v2Frames"
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
function assertFrameId(id, operation) {
|
|
564
|
+
if (!FRAME_ID_PATTERN.test(id)) {
|
|
565
|
+
throw new MetadataError(
|
|
566
|
+
operation,
|
|
567
|
+
`Invalid ID3v2 frame ID: "${id}". Frame IDs must match [A-Z0-9]{4}`,
|
|
568
|
+
id
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
function assertFrameBodies(id, data) {
|
|
573
|
+
for (const body of data) {
|
|
574
|
+
if (body.length === 0) {
|
|
575
|
+
throw new MetadataError(
|
|
576
|
+
"write",
|
|
577
|
+
"Frame data must not be empty: zero-size ID3v2 frames are invalid",
|
|
578
|
+
id
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function toPublicFrame(frame) {
|
|
584
|
+
return {
|
|
585
|
+
id: frame.id,
|
|
586
|
+
data: frame.data,
|
|
587
|
+
...frame.flags ? { flags: frame.flags } : {}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
var FRAME_ID_PATTERN;
|
|
591
|
+
var init_id3v2_frames = __esm({
|
|
592
|
+
"src/taglib/id3v2-frames.ts"() {
|
|
593
|
+
"use strict";
|
|
594
|
+
init_classes();
|
|
595
|
+
FRAME_ID_PATTERN = /^[A-Z0-9]{4}$/;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
|
|
555
599
|
// browser-stub:platform-io-browser-stub
|
|
556
600
|
function getPlatformIO() {
|
|
557
601
|
throw new Error("Filesystem operations are not available in the browser.");
|
|
@@ -1578,6 +1622,7 @@ function isValidBitrateMode(value) {
|
|
|
1578
1622
|
return value === "CBR" || value === "VBR" || value === "ABR";
|
|
1579
1623
|
}
|
|
1580
1624
|
function wrapEmbindHandle(raw) {
|
|
1625
|
+
const stagedId3v2Frames = {};
|
|
1581
1626
|
const overrides = {
|
|
1582
1627
|
getTagData() {
|
|
1583
1628
|
const tw = raw.getTag();
|
|
@@ -1637,6 +1682,17 @@ function wrapEmbindHandle(raw) {
|
|
|
1637
1682
|
else delete props["LYRICS"];
|
|
1638
1683
|
handle.setProperties(props);
|
|
1639
1684
|
},
|
|
1685
|
+
setId3v2Frames(id, data) {
|
|
1686
|
+
stagedId3v2Frames[id] = data.map((d) => new Uint8Array(d));
|
|
1687
|
+
raw.setId3v2Frames(id, data);
|
|
1688
|
+
},
|
|
1689
|
+
removeId3v2Frames(id) {
|
|
1690
|
+
stagedId3v2Frames[id] = [];
|
|
1691
|
+
raw.removeId3v2Frames(id);
|
|
1692
|
+
},
|
|
1693
|
+
getStagedId3v2Frames() {
|
|
1694
|
+
return Object.keys(stagedId3v2Frames).length > 0 ? { ...stagedId3v2Frames } : void 0;
|
|
1695
|
+
},
|
|
1640
1696
|
hasId3Tags() {
|
|
1641
1697
|
const v = raw.hasId3Tags();
|
|
1642
1698
|
if (!v || typeof v !== "object") return { v1: false, v2: false };
|
|
@@ -1744,6 +1800,16 @@ var init_extra_state_registry = __esm({
|
|
|
1744
1800
|
if (v !== void 0) target.setIxml(v);
|
|
1745
1801
|
else if (complete) target.setIxml(null);
|
|
1746
1802
|
}
|
|
1803
|
+
},
|
|
1804
|
+
{
|
|
1805
|
+
name: "id3v2Frames",
|
|
1806
|
+
copy(target, source) {
|
|
1807
|
+
const staged = source.getStagedId3v2Frames?.();
|
|
1808
|
+
if (!staged) return;
|
|
1809
|
+
for (const [id, bodies] of Object.entries(staged)) {
|
|
1810
|
+
target.setId3v2Frames(id, bodies);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1747
1813
|
}
|
|
1748
1814
|
];
|
|
1749
1815
|
}
|
|
@@ -1820,6 +1886,7 @@ var init_audio_file_impl = __esm({
|
|
|
1820
1886
|
"use strict";
|
|
1821
1887
|
init_types2();
|
|
1822
1888
|
init_audio_file_bwf();
|
|
1889
|
+
init_id3v2_frames();
|
|
1823
1890
|
init_errors2();
|
|
1824
1891
|
init_write();
|
|
1825
1892
|
init_audio_file_base();
|
|
@@ -2015,6 +2082,22 @@ var init_audio_file_impl = __esm({
|
|
|
2015
2082
|
setRating(rating, email) {
|
|
2016
2083
|
this.setRatings([{ rating, email, counter: 0 }]);
|
|
2017
2084
|
}
|
|
2085
|
+
getId3v2Frames(id) {
|
|
2086
|
+
assertMp3(this.getFormat());
|
|
2087
|
+
if (id !== void 0) assertFrameId(id, "read");
|
|
2088
|
+
return this.handle.getId3v2Frames(id ?? "").map(toPublicFrame);
|
|
2089
|
+
}
|
|
2090
|
+
setId3v2Frames(id, data) {
|
|
2091
|
+
assertMp3(this.getFormat());
|
|
2092
|
+
assertFrameId(id, "write");
|
|
2093
|
+
assertFrameBodies(id, data);
|
|
2094
|
+
this.handle.setId3v2Frames(id, data);
|
|
2095
|
+
}
|
|
2096
|
+
removeId3v2Frames(id) {
|
|
2097
|
+
assertMp3(this.getFormat());
|
|
2098
|
+
assertFrameId(id, "write");
|
|
2099
|
+
this.handle.removeId3v2Frames(id);
|
|
2100
|
+
}
|
|
2018
2101
|
hasId3Tags() {
|
|
2019
2102
|
return this.handle.hasId3Tags();
|
|
2020
2103
|
}
|
|
@@ -2199,7 +2282,7 @@ var VERSION;
|
|
|
2199
2282
|
var init_version = __esm({
|
|
2200
2283
|
"src/version.ts"() {
|
|
2201
2284
|
"use strict";
|
|
2202
|
-
VERSION = "1.
|
|
2285
|
+
VERSION = "1.5.0";
|
|
2203
2286
|
}
|
|
2204
2287
|
});
|
|
2205
2288
|
|
|
@@ -36,6 +36,25 @@ export interface Rating {
|
|
|
36
36
|
/** Play counter (if supported by format) */
|
|
37
37
|
counter?: number;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* A raw ID3v2 frame (escape hatch for vendor and unsupported frames).
|
|
41
|
+
*
|
|
42
|
+
* `data` is the frame BODY only (no 10-byte header); the caller owns the
|
|
43
|
+
* body encoding. Reads of TagLib-modeled IDs (TIT2, APIC, ...) return
|
|
44
|
+
* TagLib's canonical rendering; see the raw-frames docs for caveats.
|
|
45
|
+
*/
|
|
46
|
+
export interface Id3v2Frame {
|
|
47
|
+
/** 4-character frame ID matching [A-Z0-9]{4}, e.g. "TXXX", "RGAD" */
|
|
48
|
+
id: string;
|
|
49
|
+
/** Frame body bytes (without the 10-byte frame header) */
|
|
50
|
+
data: Uint8Array;
|
|
51
|
+
/**
|
|
52
|
+
* Frame header flags. Reserved for forward compatibility: currently never
|
|
53
|
+
* populated — TagLib blanks frame header flags when rendering, so they
|
|
54
|
+
* cannot be observed or preserved. Read-only.
|
|
55
|
+
*/
|
|
56
|
+
flags?: number;
|
|
57
|
+
}
|
|
39
58
|
/**
|
|
40
59
|
* Unsynchronized lyrics text.
|
|
41
60
|
* For lyrics without timing information.
|
|
@@ -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;;;;;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"}
|
|
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;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,IAAI,EAAE,UAAU,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;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"}
|
|
@@ -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;AAGrB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,
|
|
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,aAW3B,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"}
|
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export interface LoadTagLibOptions {
|
|
10
10
|
/**
|
|
11
|
-
* Optional pre-loaded
|
|
12
|
-
* If provided,
|
|
11
|
+
* Optional pre-loaded Wasm binary data (Emscripten backend only).
|
|
12
|
+
* If provided, it is used instead of fetching from network, and auto mode
|
|
13
|
+
* selects the Emscripten backend deterministically. Combining with
|
|
14
|
+
* `forceWasmType: "wasi"` throws — the WASI backend loads from a
|
|
15
|
+
* filesystem path or URL; use `wasmUrl` for that backend.
|
|
13
16
|
*/
|
|
14
17
|
wasmBinary?: ArrayBuffer | Uint8Array;
|
|
15
18
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-types.d.ts","sourceRoot":"","sources":["../../../src/runtime/loader-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC
|
|
1
|
+
{"version":3,"file":"loader-types.d.ts","sourceRoot":"","sources":["../../../src/runtime/loader-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC;IAEtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAEtC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC"}
|
|
@@ -32,8 +32,9 @@ import type { TagLibModule } from "../wasm.js";
|
|
|
32
32
|
* // Force WASI mode (Deno/Node.js only)
|
|
33
33
|
* const module = await loadTagLibModule({ forceWasmType: "wasi" });
|
|
34
34
|
*
|
|
35
|
-
* // With custom WASM binary
|
|
36
|
-
*
|
|
35
|
+
* // With custom WASM binary (selects the Emscripten backend; the bytes
|
|
36
|
+
* // must be its artifact, taglib-web.wasm)
|
|
37
|
+
* const wasmData = await fetch("taglib-web.wasm").then(r => r.arrayBuffer());
|
|
37
38
|
* const module = await loadTagLibModule({ wasmBinary: wasmData });
|
|
38
39
|
* ```
|
|
39
40
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-loader.d.ts","sourceRoot":"","sources":["../../../src/runtime/module-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAS/C
|
|
1
|
+
{"version":3,"file":"module-loader.d.ts","sourceRoot":"","sources":["../../../src/runtime/module-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAS/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAqEvB"}
|
|
@@ -12,6 +12,12 @@ async function loadTagLibModule(options) {
|
|
|
12
12
|
if (versionError) {
|
|
13
13
|
throw new EnvironmentError("Node.js", versionError, "WASI support");
|
|
14
14
|
}
|
|
15
|
+
if (options?.forceWasmType === "wasi" && options?.wasmBinary) {
|
|
16
|
+
throw new TagLibInitializationError(
|
|
17
|
+
"wasmBinary is not supported by the WASI backend: it loads from a filesystem path or URL. Use wasmUrl, or omit forceWasmType to use the Emscripten backend",
|
|
18
|
+
{ forceWasmType: "wasi" }
|
|
19
|
+
);
|
|
20
|
+
}
|
|
15
21
|
if (!options?.wasmBinary && !options?.wasmUrl && !options?.forceWasmType && isDenoCompiled()) {
|
|
16
22
|
const wasmBinary = await tryLoadEmbeddedWasm();
|
|
17
23
|
if (!wasmBinary) {
|
|
@@ -37,6 +43,12 @@ async function loadTagLibModule(options) {
|
|
|
37
43
|
debug: false
|
|
38
44
|
});
|
|
39
45
|
} catch (error) {
|
|
46
|
+
if (options?.forceWasmType === "wasi") {
|
|
47
|
+
throw new TagLibInitializationError(
|
|
48
|
+
`WASI backend failed to load: ${errorMessage(error)}. forceWasmType is "wasi", so the Emscripten fallback was not attempted`,
|
|
49
|
+
{ cause: error, forceWasmType: "wasi" }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
40
52
|
console.warn(
|
|
41
53
|
`[TagLib] Unified loader failed, falling back to buffer mode: ${errorMessage(error)}`
|
|
42
54
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAK5E,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA4C9B"}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { detectRuntime } from "../detector.js";
|
|
2
|
+
import { ModuleLoadError } from "./types.js";
|
|
2
3
|
import { selectWasmType } from "./module-selection.js";
|
|
3
4
|
import { loadModule } from "./module-loading.js";
|
|
4
5
|
async function loadUnifiedTagLibModule(options = {}) {
|
|
6
|
+
if (options.forceWasmType === "wasi" && options.wasmBinary) {
|
|
7
|
+
throw new ModuleLoadError(
|
|
8
|
+
"wasmBinary is not supported by the WASI backend: it loads from a filesystem path or URL. Use wasmUrl, or omit forceWasmType to select the Emscripten backend",
|
|
9
|
+
"wasi"
|
|
10
|
+
);
|
|
11
|
+
}
|
|
5
12
|
const startTime = performance.now();
|
|
6
13
|
const runtime = detectRuntime();
|
|
7
14
|
if (options.debug) {
|
|
@@ -47,6 +47,13 @@ async function loadWasiModuleWithFallback(runtime, options) {
|
|
|
47
47
|
});
|
|
48
48
|
return { module: wasiModule, actualWasmType: "wasi" };
|
|
49
49
|
} catch (hostError) {
|
|
50
|
+
if (options.forceWasmType === "wasi") {
|
|
51
|
+
throw new ModuleLoadError(
|
|
52
|
+
`WASI backend failed to load: ${errorMessage(hostError)}. forceWasmType is "wasi", so the Emscripten fallback was not attempted`,
|
|
53
|
+
"wasi",
|
|
54
|
+
hostError
|
|
55
|
+
);
|
|
56
|
+
}
|
|
50
57
|
if (runtime.environment === "node-wasi" && !supportsExnref()) {
|
|
51
58
|
const g = globalThis;
|
|
52
59
|
const nodeVersion = g.process?.versions?.node ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-selection.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/module-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"module-selection.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/module-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,YAAY,CAqBvB;AAED,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED,wBAAgB,oBAAoB,IAAI,oBAAoB,CAoB3D"}
|
|
@@ -14,7 +14,10 @@ export interface UnifiedLoaderOptions {
|
|
|
14
14
|
forceWasmType?: "wasi" | "emscripten";
|
|
15
15
|
/** Disable optimizations for debugging */
|
|
16
16
|
disableOptimizations?: boolean;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Pre-loaded Wasm binary (Emscripten backend only; auto mode selects
|
|
19
|
+
* Emscripten when set, and forcing "wasi" with it throws — use wasmUrl).
|
|
20
|
+
*/
|
|
18
21
|
wasmBinary?: ArrayBuffer | Uint8Array;
|
|
19
22
|
/** Custom WASM URL */
|
|
20
23
|
wasmUrl?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,qBAAa,kBAAmB,SAAQ,WAAW;gBACrC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM7C;AAED,qBAAa,eAAgB,SAAQ,WAAW;aAG5B,QAAQ,EAAE,MAAM,GAAG,YAAY;gBAD/C,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAC/C,KAAK,CAAC,EAAE,OAAO;CAOlB;AAED,MAAM,WAAW,oBAAoB;IACnC,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACtC,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,qBAAa,kBAAmB,SAAQ,WAAW;gBACrC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM7C;AAED,qBAAa,eAAgB,SAAQ,WAAW;aAG5B,QAAQ,EAAE,MAAM,GAAG,YAAY;gBAD/C,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAC/C,KAAK,CAAC,EAAE,OAAO;CAOlB;AAED,MAAM,WAAW,oBAAoB;IACnC,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACtC,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC;IACtC,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD,+BAA+B;IAC/B,OAAO,EAAE,sBAAsB,CAAC;IAChC,wCAAwC;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;IACtB,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,MAAM,kBAAkB,CAAC;CAClD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,GAAG,UAAU,CAAC;IAClC,cAAc,EAAE,MAAM,GAAG,YAAY,CAAC;CACvC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview WASI-based FileHandle implementation
|
|
3
3
|
*/
|
|
4
|
-
import type { FileHandle, RawChapter, RawLyrics, RawPicture } from "../../wasm.js";
|
|
4
|
+
import type { FileHandle, RawChapter, RawId3v2Frame, 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";
|
|
@@ -61,6 +61,10 @@ export declare class WasiFileHandle implements FileHandle {
|
|
|
61
61
|
}[]): void;
|
|
62
62
|
getLyrics(): RawLyrics[];
|
|
63
63
|
setLyrics(lyrics: RawLyrics[]): void;
|
|
64
|
+
getId3v2Frames(id: string): RawId3v2Frame[];
|
|
65
|
+
setId3v2Frames(id: string, data: Uint8Array[]): void;
|
|
66
|
+
removeId3v2Frames(id: string): void;
|
|
67
|
+
getStagedId3v2Frames(): Record<string, Uint8Array[]> | undefined;
|
|
64
68
|
destroy(): void;
|
|
65
69
|
}
|
|
66
70
|
//# sourceMappingURL=file-handle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-handle.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/file-handle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"file-handle.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/file-handle.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import { WasmerExecutionError } from "../wasmer-sdk-loader/types.js";
|
|
|
5
5
|
import { decodeTagData } from "../../msgpack/decoder.js";
|
|
6
6
|
import { fromTagLibKey, toTagLibKey } from "../../constants/properties.js";
|
|
7
7
|
import {
|
|
8
|
+
readId3v2FramesFromWasm,
|
|
8
9
|
readTagsFromWasm,
|
|
9
10
|
readTagsFromWasmPath,
|
|
10
11
|
writeTagsToWasm,
|
|
@@ -398,6 +399,39 @@ class WasiFileHandle {
|
|
|
398
399
|
this.checkNotDestroyed();
|
|
399
400
|
this.tagData = { ...this.tagData, lyrics };
|
|
400
401
|
}
|
|
402
|
+
getId3v2Frames(id) {
|
|
403
|
+
this.checkNotDestroyed();
|
|
404
|
+
const filter = id === "" ? void 0 : id;
|
|
405
|
+
const source = this.filePath ?? this.fileData;
|
|
406
|
+
let frames = [];
|
|
407
|
+
if (source) {
|
|
408
|
+
frames = readId3v2FramesFromWasm(this.wasi, source, filter);
|
|
409
|
+
}
|
|
410
|
+
const staged = this.getStagedId3v2Frames();
|
|
411
|
+
if (!staged) return frames;
|
|
412
|
+
const stagedIds = new Set(Object.keys(staged));
|
|
413
|
+
frames = frames.filter((f) => !stagedIds.has(f.id));
|
|
414
|
+
for (const [sid, bodies] of Object.entries(staged)) {
|
|
415
|
+
if (filter && sid !== filter) continue;
|
|
416
|
+
for (const data of bodies) frames.push({ id: sid, data: data.slice() });
|
|
417
|
+
}
|
|
418
|
+
return frames;
|
|
419
|
+
}
|
|
420
|
+
setId3v2Frames(id, data) {
|
|
421
|
+
this.checkNotDestroyed();
|
|
422
|
+
const staged = { ...this.getStagedId3v2Frames() ?? {} };
|
|
423
|
+
staged[id] = data.map((d) => new Uint8Array(d));
|
|
424
|
+
this.tagData = {
|
|
425
|
+
...this.tagData,
|
|
426
|
+
id3v2Frames: staged
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
removeId3v2Frames(id) {
|
|
430
|
+
this.setId3v2Frames(id, []);
|
|
431
|
+
}
|
|
432
|
+
getStagedId3v2Frames() {
|
|
433
|
+
return this.tagData?.id3v2Frames;
|
|
434
|
+
}
|
|
401
435
|
destroy() {
|
|
402
436
|
this.fileData = null;
|
|
403
437
|
this.tagData = null;
|
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { WasiModule } from "../wasmer-sdk-loader/types.js";
|
|
8
8
|
import type { ExtendedTag } from "../../types.js";
|
|
9
|
+
import type { RawId3v2Frame } from "../../wasm.js";
|
|
9
10
|
export declare function readTagsFromWasm(wasi: WasiModule, buffer: Uint8Array): Uint8Array;
|
|
10
11
|
export declare function readTagsFromWasmPath(wasi: WasiModule, path: string): Uint8Array;
|
|
12
|
+
export declare function readId3v2FramesFromWasm(wasi: WasiModule, source: Uint8Array | string, id?: string): RawId3v2Frame[];
|
|
11
13
|
export declare function writeTagsToWasmPath(wasi: WasiModule, path: string, tagData: ExtendedTag): boolean;
|
|
12
14
|
export declare function writeTagsToWasm(wasi: WasiModule, fileData: Uint8Array, tagData: ExtendedTag): Uint8Array | null;
|
|
13
15
|
//# sourceMappingURL=wasm-io.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm-io.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/wasm-io.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"wasm-io.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/wasm-io.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAYhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAKnD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,GACjB,UAAU,CAoCZ;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,GACX,UAAU,CA8BZ;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,EAAE,CAAC,EAAE,MAAM,GACV,aAAa,EAAE,CA8CjB;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,GACnB,OAAO,CA2BT;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,WAAW,GACnB,UAAU,GAAG,IAAI,CA8BnB"}
|