music-metadata 11.0.5 → 11.1.1

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.
@@ -7,6 +7,7 @@ export interface IParserLoader {
7
7
  * Returns a list of supported file extensions
8
8
  */
9
9
  extensions: string[];
10
+ mimeTypes: string[];
10
11
  parserType: ParserType;
11
12
  /**
12
13
  * Lazy load the parser implementation class.
@@ -37,6 +38,7 @@ export declare class ParserFactory {
37
38
  * @return Parser submodule name
38
39
  */
39
40
  findLoaderForExtension(filePath: string | undefined): IParserLoader | undefined;
40
- findLoaderForType(moduleName: ParserType | undefined): IParserLoader | undefined;
41
+ findLoaderForContentType(httpContentType: string): IParserLoader | undefined;
42
+ getSupportedMimeTypes(): string[];
41
43
  }
42
44
  export {};
@@ -62,7 +62,7 @@ export class ParserFactory {
62
62
  if (!parserLoader) {
63
63
  const buf = new Uint8Array(4100);
64
64
  if (tokenizer.fileInfo.mimeType) {
65
- parserLoader = this.findLoaderForType(getParserIdForMimeType(tokenizer.fileInfo.mimeType));
65
+ parserLoader = this.findLoaderForContentType(tokenizer.fileInfo.mimeType);
66
66
  }
67
67
  if (!parserLoader && tokenizer.fileInfo.path) {
68
68
  parserLoader = this.findLoaderForExtension(tokenizer.fileInfo.path);
@@ -76,7 +76,7 @@ export class ParserFactory {
76
76
  throw new CouldNotDetermineFileTypeError('Failed to determine audio format');
77
77
  }
78
78
  debug(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`);
79
- parserLoader = this.findLoaderForType(getParserIdForMimeType(guessedType.mime));
79
+ parserLoader = this.findLoaderForContentType(guessedType.mime);
80
80
  if (!parserLoader) {
81
81
  throw new UnsupportedFileTypeError(`Guessed MIME-type not supported: ${guessedType.mime}`);
82
82
  }
@@ -101,99 +101,33 @@ export class ParserFactory {
101
101
  const extension = getExtension(filePath).toLocaleLowerCase() || filePath;
102
102
  return this.parsers.find(parser => parser.extensions.indexOf(extension) !== -1);
103
103
  }
104
- findLoaderForType(moduleName) {
105
- return moduleName ? this.parsers.find(parser => parser.parserType === moduleName) : undefined;
104
+ findLoaderForContentType(httpContentType) {
105
+ let mime;
106
+ if (!httpContentType)
107
+ return;
108
+ try {
109
+ mime = parseHttpContentType(httpContentType);
110
+ }
111
+ catch (err) {
112
+ debug(`Invalid HTTP Content-Type header value: ${httpContentType}`);
113
+ return;
114
+ }
115
+ const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype;
116
+ return this.parsers.find(parser => parser.mimeTypes.find(loader => loader.indexOf(`${mime.type}/${subType}`) !== -1));
117
+ }
118
+ getSupportedMimeTypes() {
119
+ const mimeTypeSet = new Set();
120
+ this.parsers.forEach(loader => {
121
+ loader.mimeTypes.forEach(mimeType => {
122
+ mimeTypeSet.add(mimeType);
123
+ mimeTypeSet.add(mimeType.replace('/', '/x-'));
124
+ });
125
+ });
126
+ return Array.from(mimeTypeSet);
106
127
  }
107
128
  }
108
129
  function getExtension(fname) {
109
130
  const i = fname.lastIndexOf('.');
110
131
  return i === -1 ? '' : fname.slice(i);
111
132
  }
112
- /**
113
- * @param httpContentType - HTTP Content-Type, extension, path or filename
114
- * @returns Parser submodule name
115
- */
116
- function getParserIdForMimeType(httpContentType) {
117
- let mime;
118
- if (!httpContentType)
119
- return;
120
- try {
121
- mime = parseHttpContentType(httpContentType);
122
- }
123
- catch (err) {
124
- debug(`Invalid HTTP Content-Type header value: ${httpContentType}`);
125
- return;
126
- }
127
- const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype;
128
- switch (mime.type) {
129
- case 'audio':
130
- switch (subType) {
131
- case 'mp3': // Incorrect MIME-type, Chrome, in Web API File object
132
- case 'mpeg':
133
- return 'mpeg';
134
- case 'aac':
135
- case 'aacp':
136
- return 'mpeg'; // adts
137
- case 'flac':
138
- return 'flac';
139
- case 'ape':
140
- case 'monkeys-audio':
141
- return 'apev2';
142
- case 'mp4':
143
- case 'm4a':
144
- return 'mp4';
145
- case 'ogg': // RFC 7845
146
- case 'opus': // RFC 6716
147
- case 'speex': // RFC 5574
148
- return 'ogg';
149
- case 'ms-wma':
150
- case 'ms-wmv':
151
- case 'ms-asf':
152
- return 'asf';
153
- case 'aiff':
154
- case 'aif':
155
- case 'aifc':
156
- return 'aiff';
157
- case 'vnd.wave':
158
- case 'wav':
159
- case 'wave':
160
- return 'riff';
161
- case 'wavpack':
162
- return 'wavpack';
163
- case 'musepack':
164
- return 'musepack';
165
- case 'matroska':
166
- case 'webm':
167
- return 'matroska';
168
- case 'dsf':
169
- return 'dsf';
170
- case 'amr':
171
- return 'amr';
172
- }
173
- break;
174
- case 'video':
175
- switch (subType) {
176
- case 'ms-asf':
177
- case 'ms-wmv':
178
- return 'asf';
179
- case 'm4v':
180
- case 'mp4':
181
- return 'mp4';
182
- case 'ogg':
183
- return 'ogg';
184
- case 'matroska':
185
- case 'webm':
186
- return 'matroska';
187
- }
188
- break;
189
- case 'application':
190
- switch (subType) {
191
- case 'vnd.ms-asf':
192
- return 'asf';
193
- case 'ogg':
194
- return 'ogg';
195
- }
196
- break;
197
- }
198
- }
199
133
  //# sourceMappingURL=ParserFactory.js.map
@@ -1,6 +1,7 @@
1
1
  export const aiffParserLoader = {
2
2
  parserType: 'aiff',
3
3
  extensions: ['.aif', 'aiff', 'aifc'],
4
+ mimeTypes: ['audio/aiff', 'audio/aif', 'audio/aifc', 'application/aiff'],
4
5
  async load() {
5
6
  return (await import('./AiffParser.js')).AIFFParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const apeParserLoader = {
2
2
  parserType: 'apev2',
3
3
  extensions: ['.ape'],
4
+ mimeTypes: ['audio/ape', 'audio/monkeys-audio'],
4
5
  async load() {
5
6
  return (await import('./APEv2Parser.js')).APEv2Parser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const asfParserLoader = {
2
2
  parserType: 'asf',
3
3
  extensions: ['.asf'],
4
+ mimeTypes: ['audio/ms-wma', 'video/ms-wmv', 'audio/ms-asf', 'video/ms-asf', 'application/vnd.ms-asf'],
4
5
  async load() {
5
6
  return (await import('./AsfParser.js')).AsfParser;
6
7
  }
package/lib/core.d.ts CHANGED
@@ -3,10 +3,11 @@
3
3
  */
4
4
  import { type AnyWebByteStream, type IFileInfo, type ITokenizer, type IRandomAccessTokenizer } from 'strtok3';
5
5
  import type { IAudioMetadata, INativeTagDict, IOptions, IPicture, IPrivateOptions, ITag } from './type.js';
6
+ import type { Readable } from 'node:stream';
6
7
  export type { IFileInfo } from 'strtok3';
7
8
  export { type IAudioMetadata, type IOptions, type ITag, type INativeTagDict, type ICommonTagsResult, type IFormat, type IPicture, type IRatio, type IChapter, type ILyricsTag, LyricsContentType, TimestampFormat, IMetadataEventTag, IMetadataEvent } from './type.js';
8
9
  export { CouldNotDetermineFileTypeError, UnsupportedFileTypeError } from './ParseError.js';
9
- export type * from './ParseError.js';
10
+ export * from './ParseError.js';
10
11
  /**
11
12
  * Parse Web API File
12
13
  * Requires Blob to be able to stream using a ReadableStreamBYOBReader, only available since Node.js ≥ 20
@@ -63,3 +64,12 @@ export declare function scanAppendingHeaders(tokenizer: IRandomAccessTokenizer,
63
64
  * This method will throw an Error, always.
64
65
  */
65
66
  export declare function parseFile(filePath: string, options?: IOptions): Promise<IAudioMetadata>;
67
+ /**
68
+ * Implementation only available when loaded as Node.js
69
+ * This method will throw an Error, always.
70
+ */
71
+ export declare function parseStream(stream: Readable, fileInfo?: IFileInfo | string, options?: IOptions): Promise<IAudioMetadata>;
72
+ /**
73
+ * Return a list of supported mime-types
74
+ */
75
+ export declare function getSupportedMimeTypes(): string[];
package/lib/core.js CHANGED
@@ -8,6 +8,7 @@ import { hasID3v1Header } from './id3v1/ID3v1Parser.js';
8
8
  import { getLyricsHeaderLength } from './lyrics3/Lyrics3.js';
9
9
  export { LyricsContentType, TimestampFormat } from './type.js';
10
10
  export { CouldNotDetermineFileTypeError, UnsupportedFileTypeError } from './ParseError.js';
11
+ export * from './ParseError.js';
11
12
  /**
12
13
  * Parse Web API File
13
14
  * Requires Blob to be able to stream using a ReadableStreamBYOBReader, only available since Node.js ≥ 20
@@ -109,6 +110,19 @@ export async function scanAppendingHeaders(tokenizer, options = {}) {
109
110
  * This method will throw an Error, always.
110
111
  */
111
112
  export async function parseFile(filePath, options = {}) {
112
- throw new Error('To load Web API File objects use parseBlob instead. For loading files, you need to import with the "node" condition is set.');
113
+ throw new Error('This function require a Node engine. To load Web API File objects use parseBlob instead.');
114
+ }
115
+ /**
116
+ * Implementation only available when loaded as Node.js
117
+ * This method will throw an Error, always.
118
+ */
119
+ export async function parseStream(stream, fileInfo, options = {}) {
120
+ throw new Error('This function require a Node engine.');
121
+ }
122
+ /**
123
+ * Return a list of supported mime-types
124
+ */
125
+ export function getSupportedMimeTypes() {
126
+ return new ParserFactory().getSupportedMimeTypes();
113
127
  }
114
128
  //# sourceMappingURL=core.js.map
@@ -1,6 +1,7 @@
1
1
  export const dsdiffParserLoader = {
2
2
  parserType: 'dsdiff',
3
3
  extensions: ['.dff'],
4
+ mimeTypes: ['audio/dsf', 'audio/dsd'],
4
5
  async load() {
5
6
  return (await import('./DsdiffParser.js')).DsdiffParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const dsfParserLoader = {
2
2
  parserType: 'dsf',
3
3
  extensions: ['.dsf'],
4
+ mimeTypes: ['audio/dsf'],
4
5
  async load() {
5
6
  return (await import('./DsfParser.js')).DsfParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const flacParserLoader = {
2
2
  parserType: 'flac',
3
3
  extensions: ['.flac'],
4
+ mimeTypes: ['audio/flac'],
4
5
  async load() {
5
6
  return (await import('./FlacParser.js')).FlacParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const matroskaParserLoader = {
2
2
  parserType: 'matroska',
3
3
  extensions: ['.mka', '.mkv', '.mk3d', '.mks', 'webm'],
4
+ mimeTypes: ['audio/matroska', 'audio/webm', 'video/webm'],
4
5
  async load() {
5
6
  return (await import('./MatroskaParser.js')).MatroskaParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const mp4ParserLoader = {
2
2
  parserType: 'mp4',
3
3
  extensions: ['.mp4', '.m4a', '.m4b', '.m4pa', 'm4v', 'm4r', '3gp'],
4
+ mimeTypes: ['audio/mp4', 'audio/m4a', 'video/m4v', 'video/mp4'],
4
5
  async load() {
5
6
  return (await import('./MP4Parser.js')).MP4Parser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const mpegParserLoader = {
2
2
  parserType: 'mpeg',
3
3
  extensions: ['.mp2', '.mp3', '.m2a', '.aac', 'aacp'],
4
+ mimeTypes: ['audio/mpeg', 'audio/mp3', 'audio/aacs', 'audio/aacp'],
4
5
  async load() {
5
6
  return (await import('./MpegParser.js')).MpegParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const musepackParserLoader = {
2
2
  parserType: 'musepack',
3
3
  extensions: ['.mpc'],
4
+ mimeTypes: ['audio/musepack'],
4
5
  async load() {
5
6
  return (await import('./MusepackParser.js')).MusepackParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const oggParserLoader = {
2
2
  parserType: 'ogg',
3
3
  extensions: ['.ogg', '.ogv', '.oga', '.ogm', '.ogx', '.opus', '.spx'],
4
+ mimeTypes: ['audio/ogg', 'audio/opus', 'audio/speex', 'video/ogg'], // RFC 7845, RFC 6716, RFC 5574
4
5
  async load() {
5
6
  return (await import('./OggParser.js')).OggParser;
6
7
  }
package/lib/type.d.ts CHANGED
@@ -521,7 +521,7 @@ export interface IAudioMetadata extends INativeAudioMetadata {
521
521
  /**
522
522
  * Corresponds with parser module name
523
523
  */
524
- export type ParserType = 'mpeg' | 'apev2' | 'mp4' | 'asf' | 'flac' | 'ogg' | 'aiff' | 'wavpack' | 'riff' | 'musepack' | 'dsf' | 'dsdiff' | 'adts' | 'matroska' | 'amr';
524
+ export type ParserType = 'mpeg' | 'apev2' | 'mp4' | 'asf' | 'flac' | 'ogg' | 'aiff' | 'wavpack' | 'riff' | 'musepack' | 'dsf' | 'dsdiff' | 'adts' | 'matroska';
525
525
  export interface IOptions {
526
526
  /**
527
527
  * default: `false`, if set to `true`, it will parse the whole media file if required to determine the duration.
@@ -1,6 +1,7 @@
1
1
  export const riffParserLoader = {
2
2
  parserType: 'riff',
3
3
  extensions: ['.wav', 'wave', '.bwf'],
4
+ mimeTypes: ['audio/vnd.wave', 'audio/wav', 'audio/wave'],
4
5
  async load() {
5
6
  return (await import('./WaveParser.js')).WaveParser;
6
7
  }
@@ -1,6 +1,7 @@
1
1
  export const wavpackParserLoader = {
2
2
  parserType: 'wavpack',
3
3
  extensions: ['.wv', '.wvp'],
4
+ mimeTypes: ['audio/wavpack'],
4
5
  async load() {
5
6
  return (await import('./WavPackParser.js')).WavPackParser;
6
7
  }
package/package.json CHANGED
@@ -1,150 +1,149 @@
1
- {
2
- "name": "music-metadata",
3
- "description": "Music metadata parser for Node.js, supporting virtual any audio and tag format.",
4
- "version": "11.0.5",
5
- "author": {
6
- "name": "Borewit",
7
- "url": "https://github.com/Borewit"
8
- },
9
- "funding": [
10
- {
11
- "type": "github",
12
- "url": "https://github.com/sponsors/Borewit"
13
- },
14
- {
15
- "type": "buymeacoffee",
16
- "url": "https://buymeacoffee.com/borewit"
17
- }
18
- ],
19
- "sideEffects": false,
20
- "type": "module",
21
- "exports": {
22
- "node": {
23
- "import": "./lib/index.js",
24
- "module-sync": "./lib/index.js",
25
- "types": "./lib/index.d.ts"
26
- },
27
- "default": {
28
- "import": "./lib/core.js",
29
- "module-sync": "./lib/core.js",
30
- "types": "./lib/core.d.ts"
31
- }
32
- },
33
- "types": "lib/index.d.ts",
34
- "files": [
35
- "lib/**/*.js",
36
- "lib/**/*.d.ts"
37
- ],
38
- "keywords": [
39
- "music",
40
- "metadata",
41
- "meta",
42
- "audio",
43
- "tag",
44
- "tags",
45
- "duration",
46
- "MusicBrainz",
47
- "Discogs",
48
- "Picard",
49
- "ID3",
50
- "ID3v1",
51
- "ID3v2",
52
- "m4a",
53
- "m4b",
54
- "mp3",
55
- "mp4",
56
- "Vorbis",
57
- "ogg",
58
- "flac",
59
- "Matroska",
60
- "WebM",
61
- "EBML",
62
- "asf",
63
- "wma",
64
- "wmv",
65
- "ape",
66
- "MonkeyAudio",
67
- "aiff",
68
- "wav",
69
- "WavPack",
70
- "Opus",
71
- "speex",
72
- "musepack",
73
- "mpc",
74
- "dsd",
75
- "dsf",
76
- "mpc",
77
- "dff",
78
- "dsdiff",
79
- "aac",
80
- "adts",
81
- "length",
82
- "chapter",
83
- "info",
84
- "parse",
85
- "parser",
86
- "bwf",
87
- "slt",
88
- "lyrics"
89
- ],
90
- "scripts": {
91
- "clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map' 'test/**/*.js' 'test/**/*.js.map' 'doc-gen/**/*.js' 'doc-gen/**/*.js.map'",
92
- "compile-src": "tsc -p lib",
93
- "compile-test": "tsc -p test",
94
- "compile-doc": "tsc -p doc-gen",
95
- "compile": "yarn run compile-src && yarn compile-test && yarn compile-doc",
96
- "lint-ts": "biome check",
97
- "lint-md": "yarn run remark -u remark-preset-lint-consistent .",
98
- "lint": "yarn run lint-ts && yarn run lint-md",
99
- "test": "mocha",
100
- "build": "yarn run clean && yarn compile && yarn run doc-gen",
101
- "test-coverage": "c8 yarn run test",
102
- "send-codacy": "c8 report --reporter=text-lcov | codacy-coverage",
103
- "doc-gen": "yarn node doc-gen/gen.js",
104
- "typecheck": "tsc --project ./lib/tsconfig.json --noEmit && tsc --project ./test/tsconfig.json --noEmit"
105
- },
106
- "dependencies": {
107
- "@tokenizer/token": "^0.3.0",
108
- "content-type": "^1.0.5",
109
- "debug": "^4.4.0",
110
- "file-type": "^19.6.0",
111
- "link": "^2.1.1",
112
- "media-typer": "^1.1.0",
113
- "strtok3": "^10.2.2",
114
- "token-types": "^6.0.0",
115
- "uint8array-extras": "^1.4.0"
116
- },
117
- "devDependencies": {
118
- "@biomejs/biome": "1.9.4",
119
- "@types/chai": "^5.2.1",
120
- "@types/chai-as-promised": "^8.0.2",
121
- "@types/content-type": "^1.1.8",
122
- "@types/debug": "^4.1.12",
123
- "@types/media-typer": "^1.1.3",
124
- "@types/mocha": "^10.0.10",
125
- "@types/node": "^22.13.13",
126
- "c8": "^10.1.3",
127
- "chai": "^5.2.0",
128
- "chai-as-promised": "^8.0.1",
129
- "del-cli": "^6.0.0",
130
- "mime": "^4.0.6",
131
- "mocha": "^11.1.0",
132
- "node-readable-to-web-readable-stream": "^0.4.2",
133
- "remark-cli": "^12.0.1",
134
- "remark-preset-lint-consistent": "^6.0.1",
135
- "ts-node": "^10.9.2",
136
- "typescript": "^5.8.2"
137
- },
138
- "engines": {
139
- "node": ">=18"
140
- },
141
- "repository": {
142
- "type": "git",
143
- "url": "https://github.com/borewit/music-metadata.git"
144
- },
145
- "license": "MIT",
146
- "bugs": {
147
- "url": "https://github.com/Borewit/music-metadata/issues"
148
- },
149
- "packageManager": "yarn@4.8.1"
150
- }
1
+ {
2
+ "name": "music-metadata",
3
+ "description": "Music metadata parser for Node.js, supporting virtual any audio and tag format.",
4
+ "version": "11.1.1",
5
+ "author": {
6
+ "name": "Borewit",
7
+ "url": "https://github.com/Borewit"
8
+ },
9
+ "funding": [
10
+ {
11
+ "type": "github",
12
+ "url": "https://github.com/sponsors/Borewit"
13
+ },
14
+ {
15
+ "type": "buymeacoffee",
16
+ "url": "https://buymeacoffee.com/borewit"
17
+ }
18
+ ],
19
+ "sideEffects": false,
20
+ "type": "module",
21
+ "exports": {
22
+ "node": {
23
+ "import": "./lib/index.js",
24
+ "module-sync": "./lib/index.js",
25
+ "types": "./lib/index.d.ts"
26
+ },
27
+ "default": {
28
+ "import": "./lib/core.js",
29
+ "module-sync": "./lib/core.js",
30
+ "types": "./lib/core.d.ts"
31
+ }
32
+ },
33
+ "types": "lib/index.d.ts",
34
+ "files": [
35
+ "lib/**/*.js",
36
+ "lib/**/*.d.ts"
37
+ ],
38
+ "keywords": [
39
+ "music",
40
+ "metadata",
41
+ "meta",
42
+ "audio",
43
+ "tag",
44
+ "tags",
45
+ "duration",
46
+ "MusicBrainz",
47
+ "Discogs",
48
+ "Picard",
49
+ "ID3",
50
+ "ID3v1",
51
+ "ID3v2",
52
+ "m4a",
53
+ "m4b",
54
+ "mp3",
55
+ "mp4",
56
+ "Vorbis",
57
+ "ogg",
58
+ "flac",
59
+ "Matroska",
60
+ "WebM",
61
+ "EBML",
62
+ "asf",
63
+ "wma",
64
+ "wmv",
65
+ "ape",
66
+ "MonkeyAudio",
67
+ "aiff",
68
+ "wav",
69
+ "WavPack",
70
+ "Opus",
71
+ "speex",
72
+ "musepack",
73
+ "mpc",
74
+ "dsd",
75
+ "dsf",
76
+ "mpc",
77
+ "dff",
78
+ "dsdiff",
79
+ "aac",
80
+ "adts",
81
+ "length",
82
+ "chapter",
83
+ "info",
84
+ "parse",
85
+ "parser",
86
+ "bwf",
87
+ "slt",
88
+ "lyrics"
89
+ ],
90
+ "scripts": {
91
+ "clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map' 'test/**/*.js' 'test/**/*.js.map' 'doc-gen/**/*.js' 'doc-gen/**/*.js.map'",
92
+ "compile-src": "tsc -p lib",
93
+ "compile-test": "tsc -p test",
94
+ "compile-doc": "tsc -p doc-gen",
95
+ "compile": "yarn run compile-src && yarn compile-test && yarn compile-doc",
96
+ "lint-ts": "biome check",
97
+ "lint-md": "yarn run remark -u remark-preset-lint-consistent .",
98
+ "lint": "yarn run lint-ts && yarn run lint-md",
99
+ "test": "mocha",
100
+ "build": "yarn run clean && yarn compile && yarn run doc-gen",
101
+ "test-coverage": "c8 yarn run test",
102
+ "send-codacy": "c8 report --reporter=text-lcov | codacy-coverage",
103
+ "doc-gen": "yarn node doc-gen/gen.js",
104
+ "typecheck": "tsc --project ./lib/tsconfig.json --noEmit && tsc --project ./test/tsconfig.json --noEmit"
105
+ },
106
+ "dependencies": {
107
+ "@tokenizer/token": "^0.3.0",
108
+ "content-type": "^1.0.5",
109
+ "debug": "^4.4.0",
110
+ "file-type": "^19.6.0",
111
+ "link": "^2.1.1",
112
+ "media-typer": "^1.1.0",
113
+ "strtok3": "^10.2.2",
114
+ "token-types": "^6.0.0",
115
+ "uint8array-extras": "^1.4.0"
116
+ },
117
+ "devDependencies": {
118
+ "@biomejs/biome": "1.9.4",
119
+ "@types/chai": "^5.2.1",
120
+ "@types/chai-as-promised": "^8.0.2",
121
+ "@types/content-type": "^1.1.8",
122
+ "@types/debug": "^4.1.12",
123
+ "@types/media-typer": "^1.1.3",
124
+ "@types/mocha": "^10.0.10",
125
+ "@types/node": "^22.14.0",
126
+ "c8": "^10.1.3",
127
+ "chai": "^5.2.0",
128
+ "chai-as-promised": "^8.0.1",
129
+ "del-cli": "^6.0.0",
130
+ "mime": "^4.0.7",
131
+ "mocha": "^11.1.0",
132
+ "node-readable-to-web-readable-stream": "^0.4.2",
133
+ "remark-cli": "^12.0.1",
134
+ "remark-preset-lint-consistent": "^6.0.1",
135
+ "ts-node": "^10.9.2",
136
+ "typescript": "^5.8.2"
137
+ },
138
+ "engines": {
139
+ "node": ">=18"
140
+ },
141
+ "repository": {
142
+ "type": "github:Borewit/music-metadata"
143
+ },
144
+ "license": "MIT",
145
+ "bugs": {
146
+ "url": "https://github.com/Borewit/music-metadata/issues"
147
+ },
148
+ "packageManager": "yarn@4.8.1"
149
+ }