file-type 19.2.0 → 19.4.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/core.d.ts +18 -0
- package/core.js +54 -0
- package/index.d.ts +6 -7
- package/index.js +8 -4
- package/package.json +17 -6
- package/readme.md +8 -6
- package/supported.js +2 -0
package/core.d.ts
CHANGED
|
@@ -164,6 +164,7 @@ export type FileExtension =
|
|
|
164
164
|
| 'avro'
|
|
165
165
|
| 'icc'
|
|
166
166
|
| 'fbx'
|
|
167
|
+
| 'vsdx'
|
|
167
168
|
; // eslint-disable-line semi-style
|
|
168
169
|
|
|
169
170
|
export type MimeType =
|
|
@@ -314,6 +315,7 @@ export type MimeType =
|
|
|
314
315
|
| 'application/avro'
|
|
315
316
|
| 'application/vnd.iccprofile'
|
|
316
317
|
| 'application/x.autodesk.fbx'
|
|
318
|
+
| 'application/vnd.visio'
|
|
317
319
|
; // eslint-disable-line semi-style
|
|
318
320
|
|
|
319
321
|
export type FileTypeResult = {
|
|
@@ -473,6 +475,17 @@ export declare class TokenizerPositionError extends Error {
|
|
|
473
475
|
constructor(message?: string);
|
|
474
476
|
}
|
|
475
477
|
|
|
478
|
+
export type AnyWebReadableByteStreamWithFileType = AnyWebReadableStream<Uint8Array> & {
|
|
479
|
+
readonly fileType?: FileTypeResult;
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
484
|
+
|
|
485
|
+
This method can be handy to put in a stream pipeline, but it comes with a price. Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample, to determine the file type. The sample size impacts the file detection resolution. A smaller sample size will result in lower probability of the best file type detection.
|
|
486
|
+
*/
|
|
487
|
+
export function fileTypeStream(webStream: AnyWebReadableStream<Uint8Array>, options?: StreamOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
488
|
+
|
|
476
489
|
export declare class FileTypeParser {
|
|
477
490
|
detectors: Iterable<Detector>;
|
|
478
491
|
|
|
@@ -492,4 +505,9 @@ export declare class FileTypeParser {
|
|
|
492
505
|
Works the same way as {@link fileTypeFromBlob}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
493
506
|
*/
|
|
494
507
|
fromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
Works the same way as {@link fileTypeStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
511
|
+
*/
|
|
512
|
+
toDetectionStream(webStream: AnyWebReadableStream<Uint8Array>, options?: StreamOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
495
513
|
}
|
package/core.js
CHANGED
|
@@ -51,6 +51,10 @@ export async function fileTypeFromTokenizer(tokenizer) {
|
|
|
51
51
|
return new FileTypeParser().fromTokenizer(tokenizer);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
export async function fileTypeStream(webStream) {
|
|
55
|
+
return new FileTypeParser().toDetectionStream(webStream);
|
|
56
|
+
}
|
|
57
|
+
|
|
54
58
|
export class FileTypeParser {
|
|
55
59
|
constructor(options) {
|
|
56
60
|
this.detectors = options?.customDetectors;
|
|
@@ -104,6 +108,51 @@ export class FileTypeParser {
|
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
110
|
|
|
111
|
+
async toDetectionStream(stream, options) {
|
|
112
|
+
const {sampleSize = reasonableDetectionSizeInBytes} = options;
|
|
113
|
+
let detectedFileType;
|
|
114
|
+
let firstChunk;
|
|
115
|
+
|
|
116
|
+
const reader = stream.getReader({mode: 'byob'});
|
|
117
|
+
try {
|
|
118
|
+
// Read the first chunk from the stream
|
|
119
|
+
const {value: chunk, done} = await reader.read(new Uint8Array(sampleSize));
|
|
120
|
+
firstChunk = chunk;
|
|
121
|
+
if (!done && chunk) {
|
|
122
|
+
try {
|
|
123
|
+
// Attempt to detect the file type from the chunk
|
|
124
|
+
detectedFileType = await this.fromBuffer(chunk.slice(0, sampleSize));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (!(error instanceof strtok3.EndOfStreamError)) {
|
|
127
|
+
throw error; // Re-throw non-EndOfStreamError
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
detectedFileType = undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
firstChunk = chunk;
|
|
135
|
+
} finally {
|
|
136
|
+
reader.releaseLock(); // Ensure the reader is released
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create a new ReadableStream to manage locking issues
|
|
140
|
+
const transformStream = new TransformStream({
|
|
141
|
+
async start(controller) {
|
|
142
|
+
controller.enqueue(firstChunk); // Enqueue the initial chunk
|
|
143
|
+
},
|
|
144
|
+
transform(chunk, controller) {
|
|
145
|
+
// Pass through the chunks without modification
|
|
146
|
+
controller.enqueue(chunk);
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const newStream = stream.pipeThrough(transformStream);
|
|
151
|
+
newStream.fileType = detectedFileType;
|
|
152
|
+
|
|
153
|
+
return newStream;
|
|
154
|
+
}
|
|
155
|
+
|
|
107
156
|
check(header, options) {
|
|
108
157
|
return _check(this.buffer, header, options);
|
|
109
158
|
}
|
|
@@ -381,6 +430,11 @@ export class FileTypeParser {
|
|
|
381
430
|
ext: 'xlsx',
|
|
382
431
|
mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
383
432
|
};
|
|
433
|
+
case 'visio':
|
|
434
|
+
return {
|
|
435
|
+
ext: 'vsdx',
|
|
436
|
+
mime: 'application/vnd.visio',
|
|
437
|
+
};
|
|
384
438
|
default:
|
|
385
439
|
break;
|
|
386
440
|
}
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ Typings for Node.js specific entry point.
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type {Readable as NodeReadableStream} from 'node:stream';
|
|
6
|
-
import type {FileTypeResult, StreamOptions, AnyWebReadableStream, Detector} from './core.js';
|
|
6
|
+
import type {FileTypeResult, StreamOptions, AnyWebReadableStream, Detector, AnyWebReadableByteStreamWithFileType} from './core.js';
|
|
7
7
|
import {FileTypeParser} from './core.js';
|
|
8
8
|
|
|
9
9
|
export type ReadableStreamWithFileType = NodeReadableStream & {
|
|
@@ -25,6 +25,7 @@ export declare class NodeFileTypeParser extends FileTypeParser {
|
|
|
25
25
|
Works the same way as {@link fileTypeStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
26
26
|
*/
|
|
27
27
|
toDetectionStream(readableStream: NodeReadableStream, options?: StreamOptions): Promise<ReadableStreamWithFileType>;
|
|
28
|
+
toDetectionStream(webStream: AnyWebReadableStream<Uint8Array>, options?: StreamOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
/**
|
|
@@ -64,11 +65,8 @@ Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample
|
|
|
64
65
|
The sample size impacts the file detection resolution.
|
|
65
66
|
A smaller sample size will result in lower probability of the best file type detection.
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@param readableStream - A [readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable) containing a file to examine.
|
|
71
|
-
@param options - Maybe used to override the default sample-size.
|
|
68
|
+
@param readableStream - A [web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) or [Node.js `stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable), streaming a file to examine.
|
|
69
|
+
@param options - May be used to override the default sample size.
|
|
72
70
|
@returns A `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
73
71
|
|
|
74
72
|
@example
|
|
@@ -85,7 +83,8 @@ if (stream2.fileType?.mime === 'image/jpeg') {
|
|
|
85
83
|
// stream2 can be used to stream the JPEG image (from the very beginning of the stream)
|
|
86
84
|
}
|
|
87
85
|
```
|
|
88
|
-
|
|
86
|
+
*/
|
|
89
87
|
export function fileTypeStream(readableStream: NodeReadableStream, options?: StreamOptions): Promise<ReadableStreamWithFileType>;
|
|
88
|
+
export function fileTypeStream(webStream: AnyWebReadableStream<Uint8Array>, options?: StreamOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
90
89
|
|
|
91
90
|
export * from './core.js';
|
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Node.js specific entry point.
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {ReadableStream as WebReadableStream} from 'node:stream/web';
|
|
6
|
+
import {pipeline, PassThrough} from 'node:stream';
|
|
6
7
|
import * as strtok3 from 'strtok3';
|
|
7
8
|
import {FileTypeParser, reasonableDetectionSizeInBytes} from './core.js';
|
|
8
9
|
|
|
@@ -26,7 +27,10 @@ export class NodeFileTypeParser extends FileTypeParser {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
async toDetectionStream(readableStream, options = {}) {
|
|
29
|
-
|
|
30
|
+
if (readableStream instanceof WebReadableStream) {
|
|
31
|
+
return super.toDetectionStream(readableStream, options);
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
const {sampleSize = reasonableDetectionSizeInBytes} = options;
|
|
31
35
|
|
|
32
36
|
return new Promise((resolve, reject) => {
|
|
@@ -36,8 +40,8 @@ export class NodeFileTypeParser extends FileTypeParser {
|
|
|
36
40
|
(async () => {
|
|
37
41
|
try {
|
|
38
42
|
// Set up output stream
|
|
39
|
-
const pass = new
|
|
40
|
-
const outputStream =
|
|
43
|
+
const pass = new PassThrough();
|
|
44
|
+
const outputStream = pipeline ? pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
41
45
|
|
|
42
46
|
// Read the input stream and detect the filetype
|
|
43
47
|
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? new Uint8Array(0);
|
|
@@ -70,7 +74,7 @@ export async function fileTypeFromStream(stream, fileTypeOptions) {
|
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
export async function fileTypeStream(readableStream, options = {}) {
|
|
73
|
-
return new NodeFileTypeParser().toDetectionStream(readableStream, options);
|
|
77
|
+
return new NodeFileTypeParser(options).toDetectionStream(readableStream, options);
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
export {fileTypeFromTokenizer, fileTypeFromBuffer, fileTypeFromBlob, FileTypeParser, supportedMimeTypes, supportedExtensions} from './core.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-type",
|
|
3
|
-
"version": "19.
|
|
4
|
-
"description": "Detect the file type of a
|
|
3
|
+
"version": "19.4.0",
|
|
4
|
+
"description": "Detect the file type of a file, stream, or data",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/file-type",
|
|
7
7
|
"funding": "https://github.com/sindresorhus/file-type?sponsor=1",
|
|
@@ -13,10 +13,19 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
|
-
"node":
|
|
17
|
-
|
|
16
|
+
"node": {
|
|
17
|
+
"types": "./index.d.ts",
|
|
18
|
+
"import": "./index.js"
|
|
19
|
+
},
|
|
20
|
+
"default": {
|
|
21
|
+
"types": "./core.d.ts",
|
|
22
|
+
"import": "./core.js"
|
|
23
|
+
}
|
|
18
24
|
},
|
|
19
|
-
"./core":
|
|
25
|
+
"./core": {
|
|
26
|
+
"types": "./core.d.ts",
|
|
27
|
+
"import": "./core.js"
|
|
28
|
+
}
|
|
20
29
|
},
|
|
21
30
|
"sideEffects": false,
|
|
22
31
|
"engines": {
|
|
@@ -205,9 +214,11 @@
|
|
|
205
214
|
"ace",
|
|
206
215
|
"avro",
|
|
207
216
|
"icc",
|
|
208
|
-
"fbx"
|
|
217
|
+
"fbx",
|
|
218
|
+
"vsdx"
|
|
209
219
|
],
|
|
210
220
|
"dependencies": {
|
|
221
|
+
"get-stream": "^9.0.1",
|
|
211
222
|
"strtok3": "^8.0.0",
|
|
212
223
|
"token-types": "^6.0.0",
|
|
213
224
|
"uint8array-extras": "^1.3.0"
|
package/readme.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center" title="file-type">
|
|
2
|
+
<img src="media/logo.jpg" alt="file-type logo">
|
|
3
|
+
</h1>
|
|
2
4
|
|
|
3
|
-
> Detect the file type of a
|
|
5
|
+
> Detect the file type of a file, stream, or data
|
|
4
6
|
|
|
5
7
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
6
8
|
|
|
@@ -168,7 +170,7 @@ Or `undefined` when there is no match.
|
|
|
168
170
|
|
|
169
171
|
#### stream
|
|
170
172
|
|
|
171
|
-
Type: [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable)
|
|
173
|
+
Type: [Web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) or [Node.js `stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable)
|
|
172
174
|
|
|
173
175
|
A readable stream representing file data.
|
|
174
176
|
|
|
@@ -265,7 +267,7 @@ Type: [`ITokenizer`](https://github.com/Borewit/strtok3#tokenizer)
|
|
|
265
267
|
|
|
266
268
|
A file source implementing the [tokenizer interface](https://github.com/Borewit/strtok3#tokenizer).
|
|
267
269
|
|
|
268
|
-
### fileTypeStream(
|
|
270
|
+
### fileTypeStream(webStream, options?)
|
|
269
271
|
|
|
270
272
|
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
271
273
|
|
|
@@ -274,8 +276,7 @@ Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample
|
|
|
274
276
|
The sample size impacts the file detection resolution.
|
|
275
277
|
A smaller sample size will result in lower probability of the best file type detection.
|
|
276
278
|
|
|
277
|
-
**Note:**
|
|
278
|
-
**Note:** Requires Node.js 14 or later.
|
|
279
|
+
**Note:** When using Node.js, a `stream.Readable` may be provided as well.
|
|
279
280
|
|
|
280
281
|
#### readableStream
|
|
281
282
|
|
|
@@ -505,6 +506,7 @@ console.log(fileType);
|
|
|
505
506
|
- [`ttf`](https://en.wikipedia.org/wiki/TrueType) - TrueType font
|
|
506
507
|
- [`vcf`](https://en.wikipedia.org/wiki/VCard) - vCard
|
|
507
508
|
- [`voc`](https://wiki.multimedia.cx/index.php/Creative_Voice) - Creative Voice File
|
|
509
|
+
- [`vsdx`](https://en.wikipedia.org/wiki/Microsoft_Visio) - Microsoft Visio File
|
|
508
510
|
- [`wasm`](https://en.wikipedia.org/wiki/WebAssembly) - WebAssembly intermediate compiled format
|
|
509
511
|
- [`wav`](https://en.wikipedia.org/wiki/WAV) - Waveform Audio file
|
|
510
512
|
- [`webm`](https://en.wikipedia.org/wiki/WebM) - Web video file
|
package/supported.js
CHANGED
|
@@ -151,6 +151,7 @@ export const extensions = [
|
|
|
151
151
|
'avro',
|
|
152
152
|
'icc',
|
|
153
153
|
'fbx',
|
|
154
|
+
'vsdx',
|
|
154
155
|
];
|
|
155
156
|
|
|
156
157
|
export const mimeTypes = [
|
|
@@ -301,4 +302,5 @@ export const mimeTypes = [
|
|
|
301
302
|
'application/avro',
|
|
302
303
|
'application/vnd.iccprofile',
|
|
303
304
|
'application/x.autodesk.fbx', // Invented by us
|
|
305
|
+
'application/vnd.visio',
|
|
304
306
|
];
|