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 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
- **Note:** This method is only available when using Node.js.
68
- **Note:** Requires Node.js 14 or later.
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
- const {default: stream} = await import('node:stream');
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 stream.PassThrough();
40
- const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
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.2.0",
4
- "description": "Detect the file type of a Uint8Array/ArrayBuffer",
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": "./index.js",
17
- "default": "./core.js"
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": "./core.js"
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
- # file-type
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 Uint8Array/ArrayBuffer
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(readableStream, options?)
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:** This method is only available when using Node.js.
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
  ];