music-metadata 11.6.1 → 11.7.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.
- package/README.md +60 -47
- package/lib/core.js +7 -5
- package/lib/ogg/OggParser.js +5 -2
- package/lib/ogg/OggToken.d.ts +4 -0
- package/lib/ogg/flac/FlacStream.d.ts +1 -0
- package/lib/ogg/flac/FlacStream.js +1 -0
- package/lib/ogg/opus/OpusStream.js +1 -0
- package/lib/ogg/speex/SpeexStream.d.ts +1 -2
- package/lib/ogg/speex/SpeexStream.js +1 -2
- package/lib/ogg/theora/TheoraStream.d.ts +2 -2
- package/lib/ogg/theora/TheoraStream.js +2 -2
- package/lib/ogg/vorbis/VorbisStream.d.ts +1 -0
- package/lib/ogg/vorbis/VorbisStream.js +1 -0
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -43,30 +43,30 @@ If you find this project useful and would like to support its development, consi
|
|
|
43
43
|
|
|
44
44
|
### Support for audio file types
|
|
45
45
|
|
|
46
|
-
| Audio format
|
|
47
|
-
|
|
48
|
-
| AIFF / AIFF-C
|
|
49
|
-
| AAC
|
|
50
|
-
| APE
|
|
51
|
-
| ASF
|
|
52
|
-
| BWF
|
|
53
|
-
| DSDIFF
|
|
54
|
-
| DSF
|
|
55
|
-
| FLAC
|
|
56
|
-
| MP2
|
|
57
|
-
| Matroska
|
|
58
|
-
| MP3
|
|
59
|
-
| MPC
|
|
60
|
-
| MPEG 4
|
|
61
|
-
| Ogg
|
|
62
|
-
| Opus
|
|
63
|
-
| Speex
|
|
64
|
-
| Theora
|
|
65
|
-
| Vorbis
|
|
66
|
-
| WAV
|
|
67
|
-
| WebM
|
|
68
|
-
| WV
|
|
69
|
-
| WMA
|
|
46
|
+
| Audio format | Description | Logo |
|
|
47
|
+
|---------------------------------------------------------------------------|-----------------------------------------------------------|--------------------------------------------------------------------------------------------------|
|
|
48
|
+
| [AIFF / AIFF-C](https://wikipedia.org/wiki/Audio_Interchange_File_Format) | Audio Interchange File Format | <img src="./image/logo-Apple_Computer_Logo_rainbow.svg" width="40" alt="Apple rainbow logo"> |
|
|
49
|
+
| [AAC](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) | ADTS / Advanced Audio Coding | <img src="./image/logo-AAC_original.svg" width="40" alt="AAC logo"> |
|
|
50
|
+
| [APE](https://wikipedia.org/wiki/Monkey's_Audio) | Monkey's Audio | <img src="./image/logo-APE-AI.svg" width="40" alt="Monkey's Audio logo"> |
|
|
51
|
+
| [ASF](https://wikipedia.org/wiki/Advanced_Systems_Format) | Advanced Systems Format | |
|
|
52
|
+
| [BWF](https://en.wikipedia.org/wiki/Broadcast_Wave_Format) | Extended WAV format for broadcast and archiving | |
|
|
53
|
+
| [DSDIFF](https://wikipedia.org/wiki/Direct_Stream_Digital) | Philips DSDIFF | <img src="./image/logo-DSD.svg" width="80" alt="DSD logo"> |
|
|
54
|
+
| [DSF](https://wikipedia.org/wiki/Direct_Stream_Digital) | Sony's DSD Stream File | <img src="./image/logo-DSD.svg" width="80" alt="DSD logo"> |
|
|
55
|
+
| [FLAC](https://wikipedia.org/wiki/FLAC) | Free Lossless Audio Codec | <img src="./image/logo-FLAC.svg" width="80" alt="FLAC logo"> |
|
|
56
|
+
| [MP2](https://wikipedia.org/wiki/MPEG-1_Audio_Layer_II) | MPEG-1 Audio Layer II (predecessor to MP3) | |
|
|
57
|
+
| [Matroska](https://wikipedia.org/wiki/Matroska) | Matroska (EBML), mka, mkv | <img src="./image/logo-Matroska_2010.svg" width="80" alt="Matroska logo"> |
|
|
58
|
+
| [MP3](https://wikipedia.org/wiki/MP3) | MPEG-1 / MPEG-2 Audio Layer III | <img src="./image/logo-Mp3.svg" width="80" alt="MP3 logo"> |
|
|
59
|
+
| [MPC](https://wikipedia.org/wiki/Musepack) | Musepack SV7 | <img src="./image/logo-Musepack.svg" width="80" alt="musepack logo"> |
|
|
60
|
+
| [MPEG 4](https://wikipedia.org/wiki/MPEG-4) | mp4, m4a, m4v | <img src="./image/logo-MPEG4-350581.svg" width="80" alt="mpeg 4 logo"> |
|
|
61
|
+
| [Ogg](https://en.wikipedia.org/wiki/Ogg) | Open container format | <img src="./image/logo-Ogg.svg" width="80" alt="Ogg logo"> |
|
|
62
|
+
| [Opus](https://wikipedia.org/wiki/Opus_(audio_format)) | Low-latency, high-quality codec for speech and music | <img src="./image/logo-Opus.svg" width="80" alt="Opus logo"> |
|
|
63
|
+
| [Speex](https://wikipedia.org/wiki/Speex) | Open-source speech codec optimized for VoIP | <img src="./image/logo-Speex_2006.svg" width="80" alt="Speex logo"> |
|
|
64
|
+
| [Theora](https://en.wikipedia.org/wiki/Theora) | Open video compression format (typically paired with Ogg) | <img src="./image/logo-Theora_2007.svg" width="70" alt="Theora logo"> |
|
|
65
|
+
| [Vorbis](https://wikipedia.org/wiki/Ogg_Vorbis) | Vorbis audio compression | <img src="./image/logo-Vorbis_many_fish_2005.svg" width="70" alt="Vorbis logo"> |
|
|
66
|
+
| [WAV](https://wikipedia.org/wiki/WAV) | Uncompressed PCM audio in RIFF container | |
|
|
67
|
+
| [WebM](https://wikipedia.org/wiki/WebM) | WebM | <img src="./image/logo-WebM.svg" width="80" alt="Matroska logo"> |
|
|
68
|
+
| [WV](https://wikipedia.org/wiki/WavPack) | WavPack | <img src="./image/logo-wavpack.svg" width="60" alt="WavPack logo"> |
|
|
69
|
+
| [WMA](https://wikipedia.org/wiki/Windows_Media_Audio) | Windows Media Audio | <img src="./image/logo-Windows_Media_Player_simplified.svg" width="40" alt="Windows Media logo"> |
|
|
70
70
|
|
|
71
71
|
### Supported tag headers
|
|
72
72
|
|
|
@@ -179,11 +179,11 @@ parseFile(filePath: string, options?: IOptions): Promise<IAudioMetadata>
|
|
|
179
179
|
The following example demonstrates how to use the parseFile function to read metadata from an audio file:
|
|
180
180
|
```js
|
|
181
181
|
import { parseFile } from 'music-metadata';
|
|
182
|
-
import { inspect } from 'util';
|
|
182
|
+
import { inspect } from 'node:util';
|
|
183
183
|
|
|
184
184
|
(async () => {
|
|
185
185
|
try {
|
|
186
|
-
const filePath = '
|
|
186
|
+
const filePath = 'test/samples/MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.3].V2.mp3';
|
|
187
187
|
const metadata = await parseFile(filePath);
|
|
188
188
|
|
|
189
189
|
// Output the parsed metadata to the console in a readable format
|
|
@@ -322,19 +322,24 @@ Here’s an example of how to use the `parseWebStream` function to extract metad
|
|
|
322
322
|
import { parseWebStream } from 'music-metadata';
|
|
323
323
|
|
|
324
324
|
(async () => {
|
|
325
|
-
try {
|
|
326
|
-
//
|
|
327
|
-
const response = await fetch('https://
|
|
328
|
-
|
|
325
|
+
try {
|
|
326
|
+
// Fetch the audio file
|
|
327
|
+
const response = await fetch('https://github.com/Borewit/test-audio/raw/refs/heads/master/Various%20Artists%20-%202008%20-%20netBloc%20Vol%2013%20-%20Color%20in%20a%20World%20of%20Monochrome%20%5BAAC-40%5D/1.02.%20Solid%20Ground.m4a');
|
|
328
|
+
|
|
329
|
+
// Extract the Content-Length header and convert it to a number
|
|
330
|
+
const contentLength = response.headers.get('Content-Length');
|
|
331
|
+
const size = contentLength ? parseInt(contentLength, 10) : undefined;
|
|
329
332
|
|
|
330
333
|
// Parse the metadata from the web stream
|
|
331
|
-
const metadata = await parseWebStream(
|
|
334
|
+
const metadata = await parseWebStream(response.body, {
|
|
335
|
+
mimeType: response.headers.get('Content-Type'),
|
|
336
|
+
size // Important to pass the content-length
|
|
337
|
+
});
|
|
332
338
|
|
|
333
|
-
// Log the parsed metadata
|
|
334
339
|
console.log(metadata);
|
|
335
|
-
} catch (error) {
|
|
336
|
-
console.error('Error parsing metadata:', error.message);
|
|
337
|
-
}
|
|
340
|
+
} catch (error) {
|
|
341
|
+
console.error('Error parsing metadata:', error.message);
|
|
342
|
+
}
|
|
338
343
|
})();
|
|
339
344
|
```
|
|
340
345
|
|
|
@@ -591,23 +596,31 @@ Returns a list of supported MIME-types. This may include some MIME-types which a
|
|
|
591
596
|
### `IOptions` Interface
|
|
592
597
|
- `duration`: `boolean` (default: `false`)
|
|
593
598
|
|
|
594
|
-
|
|
595
|
-
This
|
|
599
|
+
When `true`, the parser will read the entire media file _if necessary_ to determine the duration.
|
|
600
|
+
This is only applicable in cases where duration cannot be reliably inferred without full file analysis.
|
|
601
|
+
Note that enabling this option **does not guarantee** that duration will be available,
|
|
602
|
+
only that the parser will attempt to calculate it when possible, even if it requires reading the full file.
|
|
603
|
+
|
|
604
|
+
- `mkvUseIndex`: `boolean` (default: `false`)
|
|
605
|
+
|
|
606
|
+
When `true`, the parser uses the SeekHead index in Matroska (MKV) files to skip segment and cluster elements.
|
|
607
|
+
This experimental feature can improve performance, but:
|
|
608
|
+
- Metadata not listed in the SeekHead may be skipped.
|
|
609
|
+
- If the SeekHead is missing, this option has no effect.
|
|
596
610
|
|
|
597
611
|
- `observer`: `(update: MetadataEvent) => void;`:
|
|
598
612
|
|
|
599
|
-
|
|
600
|
-
|
|
613
|
+
Callback function triggered when common tags or format properties are updated during parsing.
|
|
614
|
+
Allows real-time monitoring of metadata as it becomes available.
|
|
601
615
|
|
|
602
616
|
- `skipCovers`: `boolean` (default: `false`)
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
617
|
+
|
|
618
|
+
When `true`, embedded cover art (images) will not be extracted.
|
|
619
|
+
Useful for reducing memory and processing when cover images are unnecessary.
|
|
606
620
|
|
|
607
|
-
- `
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
If the SeekHead element is absent in the Matroska file, this flag has no effect.
|
|
621
|
+
- `skipPostHeaders`: `boolean` (default: `false`)
|
|
622
|
+
When `true`, tag headers located at the end of the file will not be read.
|
|
623
|
+
This is particularly beneficial for streaming input, as it avoids the need to read the entire stream.
|
|
611
624
|
|
|
612
625
|
> [!NOTE]
|
|
613
626
|
> - The `duration` option is typically included in most cases, but setting it to true ensures that the entire file is parsed if necessary to get an accurate duration.
|
|
@@ -857,4 +870,4 @@ This is the case using Next.js. See [issue #2370](https://github.com/Borewit/mus
|
|
|
857
870
|
|
|
858
871
|
## Licence
|
|
859
872
|
|
|
860
|
-
This project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.
|
|
873
|
+
This project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.
|
package/lib/core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Primary entry point, Node.js specific entry point is MusepackParser.ts
|
|
3
3
|
*/
|
|
4
|
-
import { fromWebStream, fromBuffer } from 'strtok3';
|
|
4
|
+
import { fromWebStream, fromBuffer, fromBlob } from 'strtok3';
|
|
5
5
|
import { ParserFactory } from './ParserFactory.js';
|
|
6
6
|
import { APEv2Parser } from './apev2/APEv2Parser.js';
|
|
7
7
|
import { hasID3v1Header } from './id3v1/ID3v1Parser.js';
|
|
@@ -17,11 +17,13 @@ export * from './ParseError.js';
|
|
|
17
17
|
* @returns Metadata
|
|
18
18
|
*/
|
|
19
19
|
export async function parseBlob(blob, options = {}) {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const tokenizer = fromBlob(blob);
|
|
21
|
+
try {
|
|
22
|
+
return await parseFromTokenizer(tokenizer, options);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await tokenizer.close();
|
|
23
26
|
}
|
|
24
|
-
return parseWebStream(blob.stream(), fileInfo, options);
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Parse audio from Web Stream.Readable
|
package/lib/ogg/OggParser.js
CHANGED
|
@@ -28,6 +28,7 @@ class OggStream {
|
|
|
28
28
|
const pageData = await tokenizer.readToken(new Token.Uint8ArrayType(segmentTable.totalPageSize));
|
|
29
29
|
debug('firstPage=%s, lastPage=%s, continued=%s', header.headerType.firstPage, header.headerType.lastPage, header.headerType.continued);
|
|
30
30
|
if (header.headerType.firstPage) {
|
|
31
|
+
this.metadata.setFormat('container', 'Ogg');
|
|
31
32
|
const idData = pageData.slice(0, 7); // Copy this portion
|
|
32
33
|
const asciiId = Array.from(idData)
|
|
33
34
|
.filter(b => b >= 32 && b <= 126) // Keep only printable ASCII
|
|
@@ -83,20 +84,22 @@ export class OggParser extends BasicParser {
|
|
|
83
84
|
*/
|
|
84
85
|
async parse() {
|
|
85
86
|
this.streams = new Map();
|
|
86
|
-
debug('pos=%s, parsePage()', this.tokenizer.position);
|
|
87
87
|
let header;
|
|
88
88
|
try {
|
|
89
89
|
do {
|
|
90
90
|
header = await this.tokenizer.readToken(PageHeader);
|
|
91
91
|
if (header.capturePattern !== 'OggS')
|
|
92
92
|
throw new OggContentError('Invalid Ogg capture pattern');
|
|
93
|
-
this.metadata.setFormat('container', 'Ogg');
|
|
94
93
|
let stream = this.streams.get(header.streamSerialNumber);
|
|
95
94
|
if (!stream) {
|
|
96
95
|
stream = new OggStream(this.metadata, header.streamSerialNumber, this.options);
|
|
97
96
|
this.streams.set(header.streamSerialNumber, stream);
|
|
98
97
|
}
|
|
99
98
|
await stream.parsePage(this.tokenizer, header);
|
|
99
|
+
if (stream.pageNumber > 12 && !(this.options.duration && [...this.streams.values()].find(stream => stream.pageConsumer?.durationOnLastPage))) {
|
|
100
|
+
debug("Stop processing Ogg stream");
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
100
103
|
} while (![...this.streams.values()].every(item => item.closed));
|
|
101
104
|
}
|
|
102
105
|
catch (err) {
|
package/lib/ogg/OggToken.d.ts
CHANGED
|
@@ -62,6 +62,10 @@ export declare class SegmentTable implements IGetToken<ISegmentTable> {
|
|
|
62
62
|
get(buf: Uint8Array, off: number): ISegmentTable;
|
|
63
63
|
}
|
|
64
64
|
export interface IPageConsumer {
|
|
65
|
+
/**
|
|
66
|
+
* Need to parse to end to be able to calculate the duration
|
|
67
|
+
*/
|
|
68
|
+
durationOnLastPage: boolean;
|
|
65
69
|
/**
|
|
66
70
|
* Parse Ogg page
|
|
67
71
|
* @param header Ogg page header
|
|
@@ -11,6 +11,7 @@ export declare class FlacStream implements Ogg.IPageConsumer {
|
|
|
11
11
|
private options;
|
|
12
12
|
private tokenizer;
|
|
13
13
|
private flacParser;
|
|
14
|
+
durationOnLastPage: boolean;
|
|
14
15
|
constructor(metadata: INativeMetadataCollector, options: IOptions, tokenizer: ITokenizer);
|
|
15
16
|
/**
|
|
16
17
|
* Vorbis 1 parser
|
|
@@ -10,6 +10,7 @@ const debug = initDebug('music-metadata:parser:ogg:theora');
|
|
|
10
10
|
*/
|
|
11
11
|
export class FlacStream {
|
|
12
12
|
constructor(metadata, options, tokenizer) {
|
|
13
|
+
this.durationOnLastPage = false;
|
|
13
14
|
this.metadata = metadata;
|
|
14
15
|
this.options = options;
|
|
15
16
|
this.tokenizer = tokenizer;
|
|
@@ -10,8 +10,7 @@ import type { INativeMetadataCollector } from '../../common/MetadataCollector.js
|
|
|
10
10
|
* - https://tools.ietf.org/html/rfc5574
|
|
11
11
|
*/
|
|
12
12
|
export declare class SpeexStream extends VorbisStream {
|
|
13
|
-
|
|
14
|
-
constructor(metadata: INativeMetadataCollector, options: IOptions, tokenizer: ITokenizer);
|
|
13
|
+
constructor(metadata: INativeMetadataCollector, options: IOptions, _tokenizer: ITokenizer);
|
|
15
14
|
/**
|
|
16
15
|
* Parse first Speex Ogg page
|
|
17
16
|
* @param {IPageHeader} header
|
|
@@ -9,9 +9,8 @@ const debug = initDebug('music-metadata:parser:ogg:speex');
|
|
|
9
9
|
* - https://tools.ietf.org/html/rfc5574
|
|
10
10
|
*/
|
|
11
11
|
export class SpeexStream extends VorbisStream {
|
|
12
|
-
constructor(metadata, options,
|
|
12
|
+
constructor(metadata, options, _tokenizer) {
|
|
13
13
|
super(metadata, options);
|
|
14
|
-
this.tokenizer = tokenizer;
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
16
|
* Parse first Speex Ogg page
|
|
@@ -8,8 +8,8 @@ import type { INativeMetadataCollector } from '../../common/MetadataCollector.js
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class TheoraStream implements Ogg.IPageConsumer {
|
|
10
10
|
private metadata;
|
|
11
|
-
|
|
12
|
-
constructor(metadata: INativeMetadataCollector, _options: IOptions,
|
|
11
|
+
durationOnLastPage: boolean;
|
|
12
|
+
constructor(metadata: INativeMetadataCollector, _options: IOptions, _tokenizer: ITokenizer);
|
|
13
13
|
/**
|
|
14
14
|
* Vorbis 1 parser
|
|
15
15
|
* @param header Ogg Page Header
|
|
@@ -6,9 +6,9 @@ const debug = initDebug('music-metadata:parser:ogg:theora');
|
|
|
6
6
|
* - https://theora.org/doc/Theora.pdf
|
|
7
7
|
*/
|
|
8
8
|
export class TheoraStream {
|
|
9
|
-
constructor(metadata, _options,
|
|
9
|
+
constructor(metadata, _options, _tokenizer) {
|
|
10
|
+
this.durationOnLastPage = false;
|
|
10
11
|
this.metadata = metadata;
|
|
11
|
-
this.tokenizer = tokenizer;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Vorbis 1 parser
|
|
@@ -25,6 +25,7 @@ export declare class VorbisStream implements IPageConsumer {
|
|
|
25
25
|
protected metadata: INativeMetadataCollector;
|
|
26
26
|
protected options: IOptions;
|
|
27
27
|
protected lastPageHeader?: IPageHeader;
|
|
28
|
+
durationOnLastPage: boolean;
|
|
28
29
|
constructor(metadata: INativeMetadataCollector, options: IOptions);
|
|
29
30
|
/**
|
|
30
31
|
* Vorbis 1 parser
|
|
@@ -13,6 +13,7 @@ export class VorbisContentError extends makeUnexpectedFileContentError('Vorbis')
|
|
|
13
13
|
export class VorbisStream {
|
|
14
14
|
constructor(metadata, options) {
|
|
15
15
|
this.pageSegments = [];
|
|
16
|
+
this.durationOnLastPage = true;
|
|
16
17
|
this.metadata = metadata;
|
|
17
18
|
this.options = options;
|
|
18
19
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "music-metadata",
|
|
3
3
|
"description": "Music metadata parser for Node.js, supporting virtual any audio and tag format.",
|
|
4
|
-
"version": "11.
|
|
4
|
+
"version": "11.7.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Borewit",
|
|
7
7
|
"url": "https://github.com/Borewit"
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"compile-test": "tsc -p test",
|
|
94
94
|
"compile-doc": "tsc -p doc-gen",
|
|
95
95
|
"compile": "yarn run compile-src && yarn compile-test && yarn compile-doc",
|
|
96
|
-
"lint:ts": "biome check
|
|
96
|
+
"lint:ts": "biome check",
|
|
97
97
|
"lint:md": "yarn run remark -u remark-preset-lint-consistent .",
|
|
98
98
|
"lint": "yarn run lint:ts && yarn run lint:md",
|
|
99
99
|
"test": "mocha",
|
|
@@ -102,7 +102,8 @@
|
|
|
102
102
|
"test-coverage": "c8 yarn run test",
|
|
103
103
|
"send-codacy": "c8 report --reporter=text-lcov | codacy-coverage",
|
|
104
104
|
"doc-gen": "yarn node doc-gen/gen.js",
|
|
105
|
-
"typecheck": "tsc --project ./lib/tsconfig.json --noEmit && tsc --project ./test/tsconfig.json --noEmit"
|
|
105
|
+
"typecheck": "tsc --project ./lib/tsconfig.json --noEmit && tsc --project ./test/tsconfig.json --noEmit",
|
|
106
|
+
"update-biome": "yarn add -D --exact @biomejs/biome && npx @biomejs/biome migrate --write"
|
|
106
107
|
},
|
|
107
108
|
"dependencies": {
|
|
108
109
|
"@tokenizer/token": "^0.3.0",
|
|
@@ -110,21 +111,21 @@
|
|
|
110
111
|
"debug": "^4.4.1",
|
|
111
112
|
"file-type": "^21.0.0",
|
|
112
113
|
"media-typer": "^1.1.0",
|
|
113
|
-
"strtok3": "^10.3.
|
|
114
|
+
"strtok3": "^10.3.2",
|
|
114
115
|
"token-types": "^6.0.3",
|
|
115
116
|
"uint8array-extras": "^1.4.0"
|
|
116
117
|
},
|
|
117
118
|
"devDependencies": {
|
|
118
|
-
"@biomejs/biome": "2.
|
|
119
|
+
"@biomejs/biome": "2.1.2",
|
|
119
120
|
"@types/chai": "^5.2.2",
|
|
120
121
|
"@types/chai-as-promised": "^8.0.2",
|
|
121
122
|
"@types/content-type": "^1.1.9",
|
|
122
123
|
"@types/debug": "^4.1.12",
|
|
123
124
|
"@types/media-typer": "^1.1.3",
|
|
124
125
|
"@types/mocha": "^10.0.10",
|
|
125
|
-
"@types/node": "^24.0.
|
|
126
|
+
"@types/node": "^24.0.14",
|
|
126
127
|
"c8": "^10.1.3",
|
|
127
|
-
"chai": "^5.2.
|
|
128
|
+
"chai": "^5.2.1",
|
|
128
129
|
"chai-as-promised": "^8.0.1",
|
|
129
130
|
"del-cli": "^6.0.0",
|
|
130
131
|
"mime": "^4.0.7",
|