taglib-wasm 2.2.1 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -3
  3. package/dist/disc-folder.d.ts +3 -1
  4. package/dist/disc-folder.d.ts.map +1 -1
  5. package/dist/disc-folder.js +187 -152
  6. package/dist/index.browser.js +17 -10
  7. package/dist/index.d.ts +1 -1
  8. package/dist/simple.browser.js +13 -8
  9. package/dist/src/constants/properties.d.ts +2 -2
  10. package/dist/src/constants/specialized-properties.d.ts +2 -2
  11. package/dist/src/constants/specialized-properties.js +2 -2
  12. package/dist/src/folder-api/album-corroborate.d.ts +13 -0
  13. package/dist/src/folder-api/album-corroborate.d.ts.map +1 -0
  14. package/dist/src/folder-api/album-corroborate.js +36 -0
  15. package/dist/src/folder-api/album-discs.d.ts +13 -0
  16. package/dist/src/folder-api/album-discs.d.ts.map +1 -0
  17. package/dist/src/folder-api/album-discs.js +122 -0
  18. package/dist/src/folder-api/album-grouping.d.ts +24 -0
  19. package/dist/src/folder-api/album-grouping.d.ts.map +1 -0
  20. package/dist/src/folder-api/album-grouping.js +118 -0
  21. package/dist/src/folder-api/album-identity.d.ts +27 -0
  22. package/dist/src/folder-api/album-identity.d.ts.map +1 -0
  23. package/dist/src/folder-api/album-identity.js +151 -0
  24. package/dist/src/folder-api/{group-albums.d.ts → album-types.d.ts} +55 -26
  25. package/dist/src/folder-api/album-types.d.ts.map +1 -0
  26. package/dist/src/folder-api/album-types.js +0 -0
  27. package/dist/src/folder-api/folder-disc.d.ts +24 -0
  28. package/dist/src/folder-api/folder-disc.d.ts.map +1 -0
  29. package/dist/src/folder-api/folder-disc.js +169 -0
  30. package/dist/src/folder-api/index.d.ts +3 -1
  31. package/dist/src/folder-api/index.d.ts.map +1 -1
  32. package/dist/src/folder-api/index.js +2 -4
  33. package/dist/src/folder-api/scan-for-albums.d.ts +1 -1
  34. package/dist/src/folder-api/scan-for-albums.d.ts.map +1 -1
  35. package/dist/src/folder-api/scan-for-albums.js +1 -3
  36. package/dist/src/runtime/detector.d.ts +16 -1
  37. package/dist/src/runtime/detector.d.ts.map +1 -1
  38. package/dist/src/runtime/detector.js +58 -52
  39. package/dist/src/runtime/platform-io.d.ts +8 -0
  40. package/dist/src/runtime/platform-io.d.ts.map +1 -1
  41. package/dist/src/runtime/platform-io.js +11 -11
  42. package/dist/src/runtime/unified-loader/module-selection.d.ts +2 -2
  43. package/dist/src/runtime/unified-loader/module-selection.d.ts.map +1 -1
  44. package/dist/src/runtime/unified-loader/module-selection.js +3 -5
  45. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts +20 -0
  46. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts.map +1 -0
  47. package/dist/src/runtime/wasi-adapter/audio-properties.js +85 -0
  48. package/dist/src/runtime/wasi-adapter/file-handle.d.ts +5 -19
  49. package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
  50. package/dist/src/runtime/wasi-adapter/file-handle.js +67 -389
  51. package/dist/src/runtime/wasi-adapter/handle-state.d.ts +28 -0
  52. package/dist/src/runtime/wasi-adapter/handle-state.d.ts.map +1 -0
  53. package/dist/src/runtime/wasi-adapter/handle-state.js +58 -0
  54. package/dist/src/runtime/wasi-adapter/mp4-items.d.ts +34 -0
  55. package/dist/src/runtime/wasi-adapter/mp4-items.d.ts.map +1 -0
  56. package/dist/src/runtime/wasi-adapter/mp4-items.js +80 -0
  57. package/dist/src/runtime/wasi-adapter/property-surface.d.ts +25 -0
  58. package/dist/src/runtime/wasi-adapter/property-surface.d.ts.map +1 -0
  59. package/dist/src/runtime/wasi-adapter/property-surface.js +104 -0
  60. package/dist/src/runtime/wasi-adapter/structured-fields.d.ts +44 -0
  61. package/dist/src/runtime/wasi-adapter/structured-fields.d.ts.map +1 -0
  62. package/dist/src/runtime/wasi-adapter/structured-fields.js +139 -0
  63. package/dist/src/runtime/wasi-adapter/tag-keys.d.ts +28 -0
  64. package/dist/src/runtime/wasi-adapter/tag-keys.d.ts.map +1 -0
  65. package/dist/src/runtime/wasi-adapter/tag-keys.js +46 -0
  66. package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
  67. package/dist/src/taglib/audio-file-impl.js +2 -2
  68. package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
  69. package/dist/src/taglib/embind-adapter.js +4 -1
  70. package/dist/src/taglib/id3v2-frames.d.ts.map +1 -1
  71. package/dist/src/taglib/id3v2-frames.js +2 -2
  72. package/dist/src/types/audio-formats.d.ts +5 -5
  73. package/dist/src/types/audio-formats.d.ts.map +1 -1
  74. package/dist/src/types/format-property-keys.d.ts +1 -1
  75. package/dist/src/types/format-property-keys.d.ts.map +1 -1
  76. package/dist/src/types/tags.d.ts +8 -1
  77. package/dist/src/types/tags.d.ts.map +1 -1
  78. package/dist/src/utils/tag-mapping.d.ts.map +1 -1
  79. package/dist/src/utils/tag-mapping.js +2 -0
  80. package/dist/src/version.d.ts +1 -1
  81. package/dist/src/version.js +1 -1
  82. package/dist/src/web-utils/data-url.d.ts.map +1 -1
  83. package/dist/src/web-utils/data-url.js +4 -2
  84. package/dist/taglib-wasi.wasm +0 -0
  85. package/dist/taglib-web.wasm +0 -0
  86. package/package.json +8 -13
  87. package/dist/src/folder-api/group-albums.d.ts.map +0 -1
  88. package/dist/src/folder-api/group-albums.js +0 -544
File without changes
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Disc-folder name recognition (pure grammar, taglib-ys7m split).
3
+ *
4
+ * Standalone recognizer: classifies a directory name as a disc folder and
5
+ * corroborates gated names against siblings. No Wasm, no I/O — this module
6
+ * is part of the disc-folder subpath's pure graph (taglib-cd7b).
7
+ */
8
+ import type { DiscConfidence, DiscFolderInfo, DiscParse } from "./album-types.js";
9
+ export declare function dirname(path: string): string;
10
+ /**
11
+ * Parse a directory name as a disc folder. Returns undefined for non-disc
12
+ * names. Plain "Bonus" and "Extras" are NEVER discs by name (tuneup rule;
13
+ * the low-tier table's "Extras" row was the flagged divergence).
14
+ */
15
+ export declare function parseDiscName(name: string): DiscParse | undefined;
16
+ export declare function baseConfidence(parse: DiscParse): DiscConfidence;
17
+ /**
18
+ * Recognize a directory name as a disc folder. Standalone — it only
19
+ * classifies the name; it does not resolve the folder to its parent (use
20
+ * the album result's per-file `albumDir` for that). Returns undefined for
21
+ * non-disc names. Plain "Bonus" and "Extras" are never discs by name.
22
+ */
23
+ export declare function discFolderInfo(name: string): DiscFolderInfo | undefined;
24
+ //# sourceMappingURL=folder-disc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-disc.d.ts","sourceRoot":"","sources":["../../../src/folder-api/folder-disc.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,SAAS,EACV,MAAM,kBAAkB,CAAC;AAE1B,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5C;AAyED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CA6GjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CAa/D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAYvE"}
@@ -0,0 +1,169 @@
1
+ function dirname(path) {
2
+ const i = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
3
+ return i === -1 ? path : path.slice(0, i);
4
+ }
5
+ const UNCONDITIONAL_MARKERS = [
6
+ "cd",
7
+ "disc",
8
+ "disk",
9
+ "dvd",
10
+ "sacd",
11
+ "blu-ray",
12
+ "bd",
13
+ "digital media"
14
+ ];
15
+ const GATED_MARKERS = ["tape", "vinyl", "cassette", "lp", "record"];
16
+ const MARKERS = [...UNCONDITIONAL_MARKERS, ...GATED_MARKERS];
17
+ const GATED_MARKER_SET = new Set(GATED_MARKERS);
18
+ const WORD_NUMBERS = {
19
+ one: 1,
20
+ two: 2,
21
+ three: 3,
22
+ four: 4,
23
+ five: 5,
24
+ six: 6,
25
+ seven: 7,
26
+ eight: 8,
27
+ nine: 9,
28
+ ten: 10,
29
+ eleven: 11,
30
+ twelve: 12
31
+ };
32
+ function romanToInt(s) {
33
+ const values = {
34
+ i: 1,
35
+ v: 5,
36
+ x: 10,
37
+ l: 50,
38
+ c: 100,
39
+ d: 500,
40
+ m: 1e3
41
+ };
42
+ let total = 0;
43
+ let prev = 0;
44
+ for (let i = s.length - 1; i >= 0; i--) {
45
+ const v = values[s[i]];
46
+ if (v === void 0) return NaN;
47
+ total += v < prev ? -v : v;
48
+ prev = v;
49
+ }
50
+ return total;
51
+ }
52
+ function parseNumberToken(token) {
53
+ if (/^\d+$/.test(token)) return parseInt(token, 10);
54
+ const word = WORD_NUMBERS[token.toLowerCase()];
55
+ if (word) return word;
56
+ const roman = romanToInt(token.toLowerCase());
57
+ return Number.isFinite(roman) ? roman : void 0;
58
+ }
59
+ const SEP = String.raw`[\s._#-]*`;
60
+ const NUM = String.raw`(?:\d+|(?:[ivxlcdm]+|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|[a-z])(?![a-z]))`;
61
+ function parseDiscName(name) {
62
+ const trimmed = name.trim();
63
+ if (/^(?:extras?|bonus)$/i.test(trimmed)) return void 0;
64
+ for (const marker of MARKERS) {
65
+ const left = String.raw`(?:^|[^a-z0-9])`;
66
+ const esc = marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
67
+ const re = new RegExp(
68
+ left + String.raw`(${esc})(?![a-z])${SEP}(${NUM})`,
69
+ "i"
70
+ );
71
+ const m = trimmed.match(re);
72
+ if (!m) continue;
73
+ const sideLetter = /^[a-z]$/i.test(m[2]);
74
+ const number = sideLetter ? void 0 : parseNumberToken(m[2]);
75
+ if (number === void 0 && !sideLetter) continue;
76
+ if (!sideLetter && /^[ivxlcdm]{2,}$/i.test(m[2]) && (number ?? 0) > 100) continue;
77
+ const isGated = GATED_MARKER_SET.has(marker.toLowerCase()) || sideLetter;
78
+ const markerStart = m.index + m[1].length - marker.length;
79
+ const rawPrefix = trimmed.slice(0, markerStart).trim();
80
+ const title = rawPrefix.replace(/[()[\]]/g, "").replace(/[\s._#-]+$/, "") || void 0;
81
+ const isExact = title === void 0;
82
+ const after = trimmed.slice(m.index + m[0].length).trim();
83
+ const discTitle = after.replace(/^[()[\],:;\-–—\s]+/, "").replace(/[)\]\[,:;\-–—\s]+$/, "").trim() || void 0;
84
+ const ofMatch = after.trim().match(/^of\s+(\d+)\b/i);
85
+ const total = ofMatch ? parseInt(ofMatch[1], 10) : void 0;
86
+ return {
87
+ kind: isExact ? "exact" : "embedded",
88
+ number: sideLetter ? void 0 : number,
89
+ total,
90
+ title,
91
+ discTitle,
92
+ gated: isGated,
93
+ sideLetter,
94
+ digit: /^\d+$/.test(m[2])
95
+ };
96
+ }
97
+ const volume = trimmed.match(
98
+ /^(?:volume|vol\.?|part|pt\.?)\s*(\d+)(?:\s*of\s*(\d+))?$/i
99
+ );
100
+ if (volume) {
101
+ return {
102
+ kind: "volume",
103
+ number: parseInt(volume[1], 10),
104
+ total: volume[2] ? parseInt(volume[2], 10) : void 0,
105
+ title: void 0,
106
+ discTitle: void 0,
107
+ gated: false,
108
+ sideLetter: false,
109
+ digit: true
110
+ };
111
+ }
112
+ if (/^bonus\s+disc$/i.test(trimmed)) {
113
+ return {
114
+ kind: "bonus",
115
+ number: void 0,
116
+ total: void 0,
117
+ title: void 0,
118
+ discTitle: void 0,
119
+ gated: true,
120
+ sideLetter: false,
121
+ digit: false
122
+ };
123
+ }
124
+ if (/^(?:\d+|v\d+|p\d+|[ab])$/i.test(trimmed)) {
125
+ return {
126
+ kind: "bare",
127
+ number: /^\d+$/i.test(trimmed) ? parseInt(trimmed, 10) : void 0,
128
+ total: void 0,
129
+ title: void 0,
130
+ discTitle: void 0,
131
+ gated: true,
132
+ sideLetter: false,
133
+ digit: false
134
+ };
135
+ }
136
+ return void 0;
137
+ }
138
+ function baseConfidence(parse) {
139
+ switch (parse.kind) {
140
+ case "exact":
141
+ return parse.digit ? "high" : "low";
142
+ case "embedded":
143
+ return "medium";
144
+ case "volume":
145
+ return "medium";
146
+ case "bonus":
147
+ case "bare":
148
+ return "low";
149
+ }
150
+ }
151
+ function discFolderInfo(name) {
152
+ const parse = parseDiscName(name);
153
+ if (!parse) return void 0;
154
+ return {
155
+ kind: parse.kind,
156
+ gated: parse.gated,
157
+ number: parse.number,
158
+ total: parse.total,
159
+ title: parse.title,
160
+ discTitle: parse.discTitle,
161
+ confidence: parse.gated ? "low" : baseConfidence(parse)
162
+ };
163
+ }
164
+ export {
165
+ baseConfidence,
166
+ dirname,
167
+ discFolderInfo,
168
+ parseDiscName
169
+ };
@@ -5,6 +5,8 @@
5
5
  export type { AudioDynamics, AudioFileMetadata, DuplicateGroup, FolderScanItem, FolderScanOptions, FolderScanResult, } from "./types.js";
6
6
  export { scanFolder } from "./scan-operations.js";
7
7
  export { exportFolderMetadata, findDuplicates } from "./folder-operations.js";
8
- export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type DiscConfidence, type DiscFolderInfo, discFolderInfo, groupAlbums, type GroupAlbumsOptions, } from "./group-albums.js";
8
+ export { type AlbumDisc, type AlbumGroup, type AlbumGroupingResult, type AlbumGroupItem, type AlbumGroupKey, type DiscConfidence, type DiscFolderInfo, type GroupAlbumsOptions, } from "./album-types.js";
9
+ export { discFolderInfo } from "./folder-disc.js";
10
+ export { groupAlbums } from "./album-grouping.js";
9
11
  export { scanForAlbums, type ScanForAlbumsOptions } from "./scan-for-albums.js";
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/folder-api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,cAAc,EACd,WAAW,EACX,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/folder-api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,9 +1,7 @@
1
1
  import { scanFolder } from "./scan-operations.js";
2
2
  import { exportFolderMetadata, findDuplicates } from "./folder-operations.js";
3
- import {
4
- discFolderInfo,
5
- groupAlbums
6
- } from "./group-albums.js";
3
+ import { discFolderInfo } from "./folder-disc.js";
4
+ import { groupAlbums } from "./album-grouping.js";
7
5
  import { scanForAlbums } from "./scan-for-albums.js";
8
6
  export {
9
7
  discFolderInfo,
@@ -4,7 +4,7 @@
4
4
  * and runtime-agnostic.
5
5
  */
6
6
  import type { FolderScanOptions } from "./types.js";
7
- import { type AlbumGroupingResult, type GroupAlbumsOptions } from "./group-albums.js";
7
+ import type { AlbumGroupingResult, GroupAlbumsOptions } from "./album-types.js";
8
8
  export type ScanForAlbumsOptions = FolderScanOptions & GroupAlbumsOptions;
9
9
  /**
10
10
  * Scan a folder and group the result into albums with disc subdivisions.
@@ -1 +1 @@
1
- {"version":3,"file":"scan-for-albums.d.ts","sourceRoot":"","sources":["../../../src/folder-api/scan-for-albums.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EACL,KAAK,mBAAmB,EAExB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAE1E;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAc9B"}
1
+ {"version":3,"file":"scan-for-albums.d.ts","sourceRoot":"","sources":["../../../src/folder-api/scan-for-albums.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGhF,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAE1E;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAc9B"}
@@ -1,7 +1,5 @@
1
1
  import { scanFolder } from "./scan-operations.js";
2
- import {
3
- groupAlbums
4
- } from "./group-albums.js";
2
+ import { groupAlbums } from "./album-grouping.js";
5
3
  async function scanForAlbums(folderPath, options = {}) {
6
4
  const {
7
5
  minFolderConfidence,
@@ -7,6 +7,21 @@ export interface RuntimeDetectionResult {
7
7
  supportsStreaming: boolean;
8
8
  performanceTier: 1 | 2 | 3;
9
9
  }
10
+ /**
11
+ * The pure per-environment backend configuration. `detectRuntime()` is the
12
+ * only sniffer in the codebase; every downstream decision (backend choice,
13
+ * PlatformIO creation, WASI availability) derives from this table so it can
14
+ * be exercised with synthetic environments instead of real runtimes
15
+ * (taglib-2b4).
16
+ */
17
+ export interface EnvironmentProfile {
18
+ wasmType: WasmBinaryType;
19
+ supportsFilesystem: boolean;
20
+ supportsStreaming: boolean;
21
+ performanceTier: 1 | 2 | 3;
22
+ }
23
+ /** Pure environment -> backend configuration lookup (taglib-2b4). */
24
+ export declare function environmentProfile(env: RuntimeEnvironment): EnvironmentProfile;
10
25
  /**
11
26
  * Check if a Node.js version meets the minimum requirement (v22.6.0+).
12
27
  * Returns an error message string if the version is too old, or undefined if OK.
@@ -22,5 +37,5 @@ export declare function detectRuntime(): RuntimeDetectionResult;
22
37
  */
23
38
  export declare function supportsExnref(): boolean;
24
39
  export declare function getEnvironmentDescription(env: RuntimeEnvironment): string;
25
- export declare function canLoadWasmType(wasmType: WasmBinaryType): boolean;
40
+ export declare function canLoadWasmType(wasmType: WasmBinaryType, env?: RuntimeEnvironment): boolean;
26
41
  //# sourceMappingURL=detector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/runtime/detector.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,WAAW,GACX,UAAU,GACV,SAAS,GACT,iBAAiB,GACjB,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,YAAY,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC5B;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAepB;AAuCD,qFAAqF;AACrF,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED,wBAAgB,aAAa,IAAI,sBAAsB,CA8EtD;AAWD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAmBzE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAQjE"}
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/runtime/detector.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,WAAW,GACX,UAAU,GACV,SAAS,GACT,iBAAiB,GACjB,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,YAAY,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC5B;AA+CD,qEAAqE;AACrE,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,kBAAkB,GACtB,kBAAkB,CAEpB;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAepB;AAuCD,qFAAqF;AACrF,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED,wBAAgB,aAAa,IAAI,sBAAsB,CAuCtD;AAWD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAmBzE;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,GAAG,GAAE,kBAAgD,GACpD,OAAO,CAKT"}
@@ -1,3 +1,50 @@
1
+ const ENVIRONMENT_PROFILES = {
2
+ "deno-wasi": {
3
+ wasmType: "wasi",
4
+ supportsFilesystem: true,
5
+ supportsStreaming: true,
6
+ performanceTier: 1
7
+ },
8
+ "node-wasi": {
9
+ wasmType: "wasi",
10
+ supportsFilesystem: true,
11
+ supportsStreaming: true,
12
+ performanceTier: 1
13
+ },
14
+ "bun-wasi": {
15
+ wasmType: "wasi",
16
+ supportsFilesystem: true,
17
+ supportsStreaming: true,
18
+ performanceTier: 1
19
+ },
20
+ browser: {
21
+ wasmType: "emscripten",
22
+ supportsFilesystem: false,
23
+ supportsStreaming: true,
24
+ performanceTier: 2
25
+ },
26
+ worker: {
27
+ wasmType: "emscripten",
28
+ supportsFilesystem: false,
29
+ supportsStreaming: true,
30
+ performanceTier: 2
31
+ },
32
+ cloudflare: {
33
+ wasmType: "emscripten",
34
+ supportsFilesystem: false,
35
+ supportsStreaming: false,
36
+ performanceTier: 3
37
+ },
38
+ "node-emscripten": {
39
+ wasmType: "emscripten",
40
+ supportsFilesystem: true,
41
+ supportsStreaming: true,
42
+ performanceTier: 3
43
+ }
44
+ };
45
+ function environmentProfile(env) {
46
+ return ENVIRONMENT_PROFILES[env];
47
+ }
1
48
  const g = globalThis;
2
49
  const MIN_NODE_MAJOR = 22;
3
50
  const MIN_NODE_MINOR = 6;
@@ -38,73 +85,32 @@ function isDeno() {
38
85
  }
39
86
  function detectRuntime() {
40
87
  if (isDeno() && hasWASISupport()) {
41
- return {
42
- environment: "deno-wasi",
43
- wasmType: "wasi",
44
- supportsFilesystem: true,
45
- supportsStreaming: true,
46
- performanceTier: 1
47
- };
88
+ return { environment: "deno-wasi", ...environmentProfile("deno-wasi") };
48
89
  }
49
90
  if (isBun()) {
50
- return {
51
- environment: "bun-wasi",
52
- wasmType: "wasi",
53
- supportsFilesystem: true,
54
- supportsStreaming: true,
55
- performanceTier: 1
56
- };
91
+ return { environment: "bun-wasi", ...environmentProfile("bun-wasi") };
57
92
  }
58
93
  if (isNode() && hasWASISupport()) {
59
- return {
60
- environment: "node-wasi",
61
- wasmType: "wasi",
62
- supportsFilesystem: true,
63
- supportsStreaming: true,
64
- performanceTier: 1
65
- };
94
+ return { environment: "node-wasi", ...environmentProfile("node-wasi") };
66
95
  }
67
96
  if (isBrowser()) {
68
- return {
69
- environment: "browser",
70
- wasmType: "emscripten",
71
- supportsFilesystem: false,
72
- supportsStreaming: true,
73
- performanceTier: 2
74
- };
97
+ return { environment: "browser", ...environmentProfile("browser") };
75
98
  }
76
99
  if (isWebWorker()) {
77
- return {
78
- environment: "worker",
79
- wasmType: "emscripten",
80
- supportsFilesystem: false,
81
- supportsStreaming: true,
82
- performanceTier: 2
83
- };
100
+ return { environment: "worker", ...environmentProfile("worker") };
84
101
  }
85
102
  if (isCloudflareWorker()) {
86
- return {
87
- environment: "cloudflare",
88
- wasmType: "emscripten",
89
- supportsFilesystem: false,
90
- supportsStreaming: false,
91
- performanceTier: 3
92
- };
103
+ return { environment: "cloudflare", ...environmentProfile("cloudflare") };
93
104
  }
94
105
  if (isNode()) {
95
106
  return {
96
107
  environment: "node-emscripten",
97
- wasmType: "emscripten",
98
- supportsFilesystem: true,
99
- supportsStreaming: true,
100
- performanceTier: 3
108
+ ...environmentProfile("node-emscripten")
101
109
  };
102
110
  }
103
111
  return {
104
112
  environment: "browser",
105
- wasmType: "emscripten",
106
- supportsFilesystem: false,
107
- supportsStreaming: true,
113
+ ...environmentProfile("browser"),
108
114
  performanceTier: 3
109
115
  };
110
116
  }
@@ -158,10 +164,9 @@ function getEnvironmentDescription(env) {
158
164
  return "Unknown environment";
159
165
  }
160
166
  }
161
- function canLoadWasmType(wasmType) {
162
- const result = detectRuntime();
167
+ function canLoadWasmType(wasmType, env = detectRuntime().environment) {
163
168
  if (wasmType === "wasi") {
164
- return result.environment === "deno-wasi" || result.environment === "node-wasi" || result.environment === "bun-wasi";
169
+ return environmentProfile(env).wasmType === "wasi";
165
170
  }
166
171
  return true;
167
172
  }
@@ -169,6 +174,7 @@ export {
169
174
  canLoadWasmType,
170
175
  checkNodeVersion,
171
176
  detectRuntime,
177
+ environmentProfile,
172
178
  getEnvironmentDescription,
173
179
  isDeno,
174
180
  supportsExnref
@@ -1,3 +1,4 @@
1
+ import { type RuntimeEnvironment } from "./detector.js";
1
2
  export type PlatformIO = {
2
3
  readFile(path: string): Promise<Uint8Array>;
3
4
  writeFile(path: string, data: Uint8Array): Promise<void>;
@@ -11,6 +12,13 @@ export type PlatformIO = {
11
12
  }>;
12
13
  readPartial?: (path: string, headerSize: number, footerSize: number) => Promise<Uint8Array>;
13
14
  };
15
+ /**
16
+ * Pure environment -> PlatformIO selection (taglib-2b4): each environment's
17
+ * factory is chosen without sniffing, so the routing is testable with a
18
+ * synthetic environment. Factories are lazy — nothing touches the runtime
19
+ * until a method is called, so calling this under any runtime is safe.
20
+ */
21
+ export declare function createPlatformIOFor(env: RuntimeEnvironment): PlatformIO;
14
22
  export declare function getPlatformIO(): PlatformIO;
15
23
  /** @internal */
16
24
  export declare function _setPlatformIOForTesting(io: PlatformIO): void;
@@ -1 +1 @@
1
- {"version":3,"file":"platform-io.d.ts","sourceRoot":"","sources":["../../../src/runtime/platform-io.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,OAAO,CACL,IAAI,EAAE,MAAM,GACX,cAAc,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B,CAAC;AA0LF,wBAAgB,aAAa,IAAI,UAAU,CAyB1C;AAED,gBAAgB;AAChB,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,CAE7D;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"platform-io.d.ts","sourceRoot":"","sources":["../../../src/runtime/platform-io.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,OAAO,CACL,IAAI,EAAE,MAAM,GACX,cAAc,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B,CAAC;AA0LF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,GAAG,UAAU,CAgBvE;AAED,wBAAgB,aAAa,IAAI,UAAU,CAM1C;AAED,gBAAgB;AAChB,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,CAE7D;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
@@ -152,27 +152,26 @@ function createBunIO() {
152
152
  }
153
153
  };
154
154
  }
155
- function getPlatformIO() {
156
- if (platformIO) return platformIO;
157
- const runtime = detectRuntime();
158
- switch (runtime.environment) {
155
+ function createPlatformIOFor(env) {
156
+ switch (env) {
159
157
  case "deno-wasi":
160
- platformIO = createDenoIO();
161
- break;
158
+ return createDenoIO();
162
159
  case "bun-wasi":
163
- platformIO = createBunIO();
164
- break;
160
+ return createBunIO();
165
161
  case "node-wasi":
166
162
  case "node-emscripten":
167
- platformIO = createNodeIO();
168
- break;
163
+ return createNodeIO();
169
164
  default:
170
165
  throw new EnvironmentError(
171
- runtime.environment,
166
+ env,
172
167
  "does not support filesystem operations",
173
168
  "filesystem access"
174
169
  );
175
170
  }
171
+ }
172
+ function getPlatformIO() {
173
+ if (platformIO) return platformIO;
174
+ platformIO = createPlatformIOFor(detectRuntime().environment);
176
175
  return platformIO;
177
176
  }
178
177
  function _setPlatformIOForTesting(io) {
@@ -184,5 +183,6 @@ function _resetPlatformIO() {
184
183
  export {
185
184
  _resetPlatformIO,
186
185
  _setPlatformIOForTesting,
186
+ createPlatformIOFor,
187
187
  getPlatformIO
188
188
  };
@@ -1,6 +1,6 @@
1
1
  import { type RuntimeDetectionResult } from "../detector.js";
2
2
  import type { UnifiedLoaderOptions } from "./types.js";
3
3
  export declare function selectWasmType(runtime: RuntimeDetectionResult, options: UnifiedLoaderOptions): "wasi" | "emscripten";
4
- export declare function isWasiAvailable(): boolean;
5
- export declare function getRecommendedConfig(): UnifiedLoaderOptions;
4
+ export declare function isWasiAvailable(runtime?: RuntimeDetectionResult): boolean;
5
+ export declare function getRecommendedConfig(runtime?: RuntimeDetectionResult): UnifiedLoaderOptions;
6
6
  //# sourceMappingURL=module-selection.d.ts.map
@@ -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,CAqBvB;AAED,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED,wBAAgB,oBAAoB,IAAI,oBAAoB,CAoB3D"}
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,CAC7B,OAAO,GAAE,sBAAwC,GAChD,OAAO,CAET;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,sBAAwC,GAChD,oBAAoB,CAqBtB"}
@@ -14,19 +14,17 @@ function selectWasmType(runtime, options) {
14
14
  }
15
15
  return "emscripten";
16
16
  }
17
- function isWasiAvailable() {
18
- const runtime = detectRuntime();
17
+ function isWasiAvailable(runtime = detectRuntime()) {
19
18
  return runtime.wasmType === "wasi" && runtime.supportsFilesystem;
20
19
  }
21
- function getRecommendedConfig() {
22
- const runtime = detectRuntime();
20
+ function getRecommendedConfig(runtime = detectRuntime()) {
23
21
  if (runtime.environment === "browser") {
24
22
  return {
25
23
  forceWasmType: "emscripten",
26
24
  disableOptimizations: false
27
25
  };
28
26
  }
29
- if (runtime.supportsFilesystem) {
27
+ if (runtime.wasmType === "wasi" && runtime.supportsFilesystem) {
30
28
  return {
31
29
  forceWasmType: "wasi",
32
30
  disableOptimizations: false
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Audio metrics and format detection over the WASI tag-data snapshot.
3
+ *
4
+ * Pure functions over (tagData, fileData): the WasiFileHandle wrappers add
5
+ * destruction guards and pass their fields. Extracted from file-handle.ts in
6
+ * the taglib-1dfc split.
7
+ */
8
+ import type { AudioProperties } from "../../types.js";
9
+ /** The audio-properties block of the C++ snapshot, null when absent. */
10
+ export declare function getAudioProperties(tagData: Record<string, unknown> | null): AudioProperties | null;
11
+ /** OGG codec sniffing: "OpusHead" in the first page payload, else OGG. */
12
+ export declare function detectOggCodec(fileData: Uint8Array): string;
13
+ /**
14
+ * Format detection: container-based first (works for path and buffer modes),
15
+ * magic-byte fallback for buffers.
16
+ */
17
+ export declare function getFormat(tagData: Record<string, unknown> | null, fileData: Uint8Array | null): string;
18
+ /** MP4 detection: containerFormat (path mode) or ftyp box (buffer mode). */
19
+ export declare function isMP4(tagData: Record<string, unknown> | null, fileData: Uint8Array | null): boolean;
20
+ //# sourceMappingURL=audio-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-properties.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/audio-properties.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AAgBxB,wEAAwE;AACxE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,eAAe,GAAG,IAAI,CA4BxB;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAe3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,MAAM,CAuDR;AAED,4EAA4E;AAC5E,wBAAgB,KAAK,CACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,OAAO,CAYT"}