file-type 10.7.1 → 10.11.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.
Files changed (4) hide show
  1. package/index.d.ts +191 -0
  2. package/index.js +45 -6
  3. package/package.json +13 -8
  4. package/readme.md +46 -11
package/index.d.ts ADDED
@@ -0,0 +1,191 @@
1
+ /// <reference types="node"/>
2
+ import {Readable as ReadableStream} from 'stream';
3
+
4
+ declare namespace fileType {
5
+ type FileType =
6
+ | 'jpg'
7
+ | 'png'
8
+ | 'gif'
9
+ | 'webp'
10
+ | 'flif'
11
+ | 'cr2'
12
+ | 'tif'
13
+ | 'bmp'
14
+ | 'jxr'
15
+ | 'psd'
16
+ | 'zip'
17
+ | 'tar'
18
+ | 'rar'
19
+ | 'gz'
20
+ | 'bz2'
21
+ | '7z'
22
+ | 'dmg'
23
+ | 'mp4'
24
+ | 'm4v'
25
+ | 'mid'
26
+ | 'mkv'
27
+ | 'webm'
28
+ | 'mov'
29
+ | 'avi'
30
+ | 'wmv'
31
+ | 'mpg'
32
+ | 'mp2'
33
+ | 'mp3'
34
+ | 'm4a'
35
+ | 'ogg'
36
+ | 'opus'
37
+ | 'flac'
38
+ | 'wav'
39
+ | 'qcp'
40
+ | 'amr'
41
+ | 'pdf'
42
+ | 'epub'
43
+ | 'mobi'
44
+ | 'exe'
45
+ | 'swf'
46
+ | 'rtf'
47
+ | 'woff'
48
+ | 'woff2'
49
+ | 'eot'
50
+ | 'ttf'
51
+ | 'otf'
52
+ | 'ico'
53
+ | 'flv'
54
+ | 'ps'
55
+ | 'xz'
56
+ | 'sqlite'
57
+ | 'nes'
58
+ | 'crx'
59
+ | 'xpi'
60
+ | 'cab'
61
+ | 'deb'
62
+ | 'ar'
63
+ | 'rpm'
64
+ | 'Z'
65
+ | 'lz'
66
+ | 'msi'
67
+ | 'mxf'
68
+ | 'mts'
69
+ | 'wasm'
70
+ | 'blend'
71
+ | 'bpg'
72
+ | 'docx'
73
+ | 'pptx'
74
+ | 'xlsx'
75
+ | '3gp'
76
+ | 'jp2'
77
+ | 'jpm'
78
+ | 'jpx'
79
+ | 'mj2'
80
+ | 'aif'
81
+ | 'odt'
82
+ | 'ods'
83
+ | 'odp'
84
+ | 'xml'
85
+ | 'heic'
86
+ | 'cur'
87
+ | 'ktx'
88
+ | 'ape'
89
+ | 'wv'
90
+ | 'asf'
91
+ | 'wma'
92
+ | 'wmv'
93
+ | 'dcm'
94
+ | 'mpc'
95
+ | 'ics'
96
+ | 'glb'
97
+ | 'pcap';
98
+
99
+ interface FileTypeResult {
100
+ /**
101
+ One of the supported [file types](https://github.com/sindresorhus/file-type#supported-file-types).
102
+ */
103
+ ext: FileType;
104
+
105
+ /**
106
+ The detected [MIME type](https://en.wikipedia.org/wiki/Internet_media_type).
107
+ */
108
+ mime: string;
109
+ }
110
+
111
+ type ReadableStreamWithFileType = ReadableStream & {
112
+ readonly fileType: FileTypeResult | null;
113
+ };
114
+ }
115
+
116
+ declare const fileType: {
117
+ /**
118
+ Detect the file type of a `Buffer`/`Uint8Array`/`ArrayBuffer`. 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.
119
+
120
+ @param buffer - It only needs the first `.minimumBytes` bytes. The exception is detection of `docx`, `pptx`, and `xlsx` which potentially requires reading the whole file.
121
+ @returns An object with the detected file type and MIME type or `null` when there was no match.
122
+
123
+ @example
124
+ ```
125
+ import readChunk = require('read-chunk');
126
+ import fileType = require('file-type');
127
+
128
+ const buffer = readChunk.sync('unicorn.png', 0, fileType.minimumBytes);
129
+
130
+ fileType(buffer);
131
+ //=> {ext: 'png', mime: 'image/png'}
132
+
133
+
134
+ // Or from a remote location:
135
+
136
+ import * as http from 'http';
137
+
138
+ const url = 'https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif';
139
+
140
+ http.get(url, response => {
141
+ response.on('readable', () => {
142
+ const chunk = response.read(fileType.minimumBytes);
143
+ response.destroy();
144
+ console.log(fileType(chunk));
145
+ //=> {ext: 'gif', mime: 'image/gif'}
146
+ });
147
+ });
148
+ ```
149
+ */
150
+ (buffer: Buffer | Uint8Array | ArrayBuffer): fileType.FileTypeResult | null;
151
+
152
+ /**
153
+ The minimum amount of bytes needed to detect a file type. Currently, it's 4100 bytes, but it can change, so don't hard-code it.
154
+ */
155
+ readonly minimumBytes: number;
156
+
157
+ /**
158
+ Detect the file type of a readable stream.
159
+
160
+ @param readableStream - A readable stream containing a file to examine, see: [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable).
161
+ @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 `fileType()`.
162
+
163
+ @example
164
+ ```
165
+ import * as fs from 'fs';
166
+ import * as crypto from 'crypto';
167
+ import fileType = require('file-type');
168
+
169
+ (async () => {
170
+ const read = fs.createReadStream('encrypted.enc');
171
+ const decipher = crypto.createDecipheriv(alg, key, iv);
172
+
173
+ const stream = await fileType.stream(read.pipe(decipher));
174
+
175
+ console.log(stream.fileType);
176
+ //=> {ext: 'mov', mime: 'video/quicktime'}
177
+
178
+ const write = fs.createWriteStream(`decrypted.${stream.fileType.ext}`);
179
+ stream.pipe(write);
180
+ })();
181
+ ```
182
+ */
183
+ readonly stream: (
184
+ readableStream: ReadableStream
185
+ ) => Promise<fileType.ReadableStreamWithFileType>;
186
+
187
+ // TODO: Remove this for the next major release
188
+ readonly default: typeof fileType;
189
+ };
190
+
191
+ export = fileType;
package/index.js CHANGED
@@ -12,12 +12,13 @@ function readUInt64LE(buf, offset = 0) {
12
12
  mul *= 0x100;
13
13
  n += buf[offset + i] * mul;
14
14
  }
15
+
15
16
  return n;
16
17
  }
17
18
 
18
- module.exports = input => {
19
- if (!(input instanceof Uint8Array || Buffer.isBuffer(input))) {
20
- throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\`, got \`${typeof input}\``);
19
+ const fileType = input => {
20
+ if (!(input instanceof Uint8Array || input instanceof ArrayBuffer || Buffer.isBuffer(input))) {
21
+ throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
21
22
  }
22
23
 
23
24
  const buf = input instanceof Uint8Array ? input : new Uint8Array(input);
@@ -344,12 +345,14 @@ module.exports = input => {
344
345
  mime: 'video/vnd.avi'
345
346
  };
346
347
  }
348
+
347
349
  if (check([0x57, 0x41, 0x56, 0x45], {offset: 8})) {
348
350
  return {
349
351
  ext: 'wav',
350
352
  mime: 'audio/vnd.wave'
351
353
  };
352
354
  }
355
+
353
356
  // QLCM, QCP file
354
357
  if (check([0x51, 0x4C, 0x43, 0x4D], {offset: 8})) {
355
358
  return {
@@ -386,6 +389,7 @@ module.exports = input => {
386
389
 
387
390
  break;
388
391
  }
392
+
389
393
  offset += objectSize;
390
394
  } while (offset + 24 <= buf.length);
391
395
 
@@ -454,8 +458,7 @@ module.exports = input => {
454
458
  }
455
459
 
456
460
  if (
457
- check([0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41], {offset: 4}) ||
458
- check([0x4D, 0x34, 0x41, 0x20])
461
+ check([0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41], {offset: 4})
459
462
  ) {
460
463
  return { // MPEG-4 layer 3 (audio)
461
464
  ext: 'm4a',
@@ -482,6 +485,7 @@ module.exports = input => {
482
485
  mime: 'video/ogg'
483
486
  };
484
487
  }
488
+
485
489
  // If '\x01video' in header.
486
490
  if (check([0x01, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x00], {offset: 28})) {
487
491
  return {
@@ -489,6 +493,7 @@ module.exports = input => {
489
493
  mime: 'video/ogg'
490
494
  };
491
495
  }
496
+
492
497
  // If ' FLAC' in header https://xiph.org/flac/faq.html
493
498
  if (check([0x7F, 0x46, 0x4C, 0x41, 0x43], {offset: 28})) {
494
499
  return {
@@ -908,7 +913,41 @@ module.exports = input => {
908
913
  };
909
914
  }
910
915
 
916
+ if (check([0xD4, 0xC3, 0xB2, 0xA1]) || check([0xA1, 0xB2, 0xC3, 0xD4])) {
917
+ return {
918
+ ext: 'pcap',
919
+ mime: 'application/vnd.tcpdump.pcap'
920
+ };
921
+ }
922
+
911
923
  return null;
912
924
  };
913
925
 
914
- Object.defineProperty(module.exports, 'minimumBytes', {value: 4100});
926
+ module.exports = fileType;
927
+ // TODO: Remove this for the next major release
928
+ module.exports.default = fileType;
929
+
930
+ Object.defineProperty(fileType, 'minimumBytes', {value: 4100});
931
+
932
+ module.exports.stream = readableStream => new Promise((resolve, reject) => {
933
+ // Using `eval` to work around issues when bundling with Webpack
934
+ const stream = eval('require')('stream'); // eslint-disable-line no-eval
935
+
936
+ readableStream.once('readable', () => {
937
+ const pass = new stream.PassThrough();
938
+ const chunk = readableStream.read(module.exports.minimumBytes) || readableStream.read();
939
+ try {
940
+ pass.fileType = fileType(chunk);
941
+ } catch (error) {
942
+ reject(error);
943
+ }
944
+
945
+ readableStream.unshift(chunk);
946
+
947
+ if (stream.pipeline) {
948
+ resolve(stream.pipeline(readableStream, pass, () => {}));
949
+ } else {
950
+ resolve(readableStream.pipe(pass));
951
+ }
952
+ });
953
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "file-type",
3
- "version": "10.7.1",
4
- "description": "Detect the file type of a Buffer/Uint8Array",
3
+ "version": "10.11.0",
4
+ "description": "Detect the file type of a Buffer/Uint8Array/ArrayBuffer",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/file-type",
7
7
  "author": {
@@ -13,10 +13,11 @@
13
13
  "node": ">=6"
14
14
  },
15
15
  "scripts": {
16
- "test": "xo && ava"
16
+ "test": "xo && ava && tsd"
17
17
  },
18
18
  "files": [
19
- "index.js"
19
+ "index.js",
20
+ "index.d.ts"
20
21
  ],
21
22
  "keywords": [
22
23
  "mime",
@@ -116,11 +117,15 @@
116
117
  "heic",
117
118
  "wma",
118
119
  "ics",
119
- "glb"
120
+ "glb",
121
+ "pcap"
120
122
  ],
121
123
  "devDependencies": {
122
- "ava": "^1.0.1",
123
- "read-chunk": "^3.0.0",
124
- "xo": "^0.23.0"
124
+ "@types/node": "^11.12.2",
125
+ "ava": "^1.4.1",
126
+ "pify": "^4.0.1",
127
+ "read-chunk": "^3.2.0",
128
+ "tsd": "^0.7.1",
129
+ "xo": "^0.24.0"
125
130
  }
126
131
  }
package/readme.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # file-type [![Build Status](https://travis-ci.org/sindresorhus/file-type.svg?branch=master)](https://travis-ci.org/sindresorhus/file-type)
2
2
 
3
- > Detect the file type of a Buffer/Uint8Array
3
+ > Detect the file type of a Buffer/Uint8Array/ArrayBuffer
4
4
 
5
- The file type is detected by checking the [magic number](http://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
5
+ 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
6
 
7
7
 
8
8
  ## Install
@@ -36,7 +36,7 @@ Or from a remote location:
36
36
  const http = require('http');
37
37
  const fileType = require('file-type');
38
38
 
39
- const url = 'http://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif';
39
+ const url = 'https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif';
40
40
 
41
41
  http.get(url, response => {
42
42
  response.on('readable', () => {
@@ -48,6 +48,28 @@ http.get(url, response => {
48
48
  });
49
49
  ```
50
50
 
51
+ Or from a stream:
52
+
53
+ ```js
54
+ const fs = require('fs');
55
+ const crypto = require('crypto');
56
+ const fileType = require('file-type');
57
+
58
+ (async () => {
59
+ const read = fs.createReadStream('encrypted.enc');
60
+ const decipher = crypto.createDecipheriv(alg, key, iv);
61
+
62
+ const stream = await fileType.stream(read.pipe(decipher));
63
+
64
+ console.log(stream.fileType);
65
+ //=> {ext: 'mov', mime: 'video/quicktime'}
66
+
67
+ const write = fs.createWriteStream(`decrypted.${stream.fileType.ext}`);
68
+ stream.pipe(write);
69
+ })();
70
+ ```
71
+
72
+
51
73
  ##### Browser
52
74
 
53
75
  ```js
@@ -71,13 +93,13 @@ xhr.send();
71
93
  Returns an `Object` with:
72
94
 
73
95
  - `ext` - One of the [supported file types](#supported-file-types)
74
- - `mime` - The [MIME type](http://en.wikipedia.org/wiki/Internet_media_type)
96
+ - `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
75
97
 
76
- Or `null` when no match.
98
+ Or `null` when there is no match.
77
99
 
78
100
  #### input
79
101
 
80
- Type: `Buffer` `Uint8Array`
102
+ Type: `Buffer | Uint8Array | ArrayBuffer`
81
103
 
82
104
  It only needs the first `.minimumBytes` bytes. The exception is detection of `docx`, `pptx`, and `xlsx` which potentially requires reading the whole file.
83
105
 
@@ -87,6 +109,18 @@ Type: `number`
87
109
 
88
110
  The minimum amount of bytes needed to detect a file type. Currently, it's 4100 bytes, but it can change, so don't hardcode it.
89
111
 
112
+ ### fileType.stream(readableStream)
113
+
114
+ Detect the file type of a readable stream.
115
+
116
+ 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 `fileType()`.
117
+
118
+ *Note:* This method is only for Node.js.
119
+
120
+ #### readableStream
121
+
122
+ Type: [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable)
123
+
90
124
 
91
125
  ## Supported file types
92
126
 
@@ -95,7 +129,7 @@ The minimum amount of bytes needed to detect a file type. Currently, it's 4100 b
95
129
  - [`gif`](https://en.wikipedia.org/wiki/GIF)
96
130
  - [`webp`](https://en.wikipedia.org/wiki/WebP)
97
131
  - [`flif`](https://en.wikipedia.org/wiki/Free_Lossless_Image_Format)
98
- - [`cr2`](http://fileinfo.com/extension/cr2)
132
+ - [`cr2`](https://fileinfo.com/extension/cr2)
99
133
  - [`tif`](https://en.wikipedia.org/wiki/Tagged_Image_File_Format)
100
134
  - [`bmp`](https://en.wikipedia.org/wiki/BMP_file_format)
101
135
  - [`jxr`](https://en.wikipedia.org/wiki/JPEG_XR)
@@ -141,14 +175,14 @@ The minimum amount of bytes needed to detect a file type. Currently, it's 4100 b
141
175
  - [`ps`](https://en.wikipedia.org/wiki/Postscript)
142
176
  - [`xz`](https://en.wikipedia.org/wiki/Xz)
143
177
  - [`sqlite`](https://www.sqlite.org/fileformat2.html)
144
- - [`nes`](http://fileinfo.com/extension/nes)
178
+ - [`nes`](https://fileinfo.com/extension/nes)
145
179
  - [`crx`](https://developer.chrome.com/extensions/crx)
146
180
  - [`xpi`](https://en.wikipedia.org/wiki/XPInstall)
147
181
  - [`cab`](https://en.wikipedia.org/wiki/Cabinet_(file_format))
148
182
  - [`deb`](https://en.wikipedia.org/wiki/Deb_(file_format))
149
183
  - [`ar`](https://en.wikipedia.org/wiki/Ar_(Unix))
150
- - [`rpm`](http://fileinfo.com/extension/rpm)
151
- - [`Z`](http://fileinfo.com/extension/z)
184
+ - [`rpm`](https://fileinfo.com/extension/rpm)
185
+ - [`Z`](https://fileinfo.com/extension/z)
152
186
  - [`lz`](https://en.wikipedia.org/wiki/Lzip)
153
187
  - [`msi`](https://en.wikipedia.org/wiki/Windows_Installer)
154
188
  - [`mxf`](https://en.wikipedia.org/wiki/Material_Exchange_Format)
@@ -169,7 +203,7 @@ The minimum amount of bytes needed to detect a file type. Currently, it's 4100 b
169
203
  - [`ods`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for spreadsheets
170
204
  - [`odp`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for presentations
171
205
  - [`xml`](https://en.wikipedia.org/wiki/XML)
172
- - [`heic`](http://nokiatech.github.io/heif/technical.html)
206
+ - [`heic`](https://nokiatech.github.io/heif/technical.html)
173
207
  - [`cur`](https://en.wikipedia.org/wiki/ICO_(file_format))
174
208
  - [`ktx`](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/)
175
209
  - [`ape`](https://en.wikipedia.org/wiki/Monkey%27s_Audio) - Monkey's Audio
@@ -181,6 +215,7 @@ The minimum amount of bytes needed to detect a file type. Currently, it's 4100 b
181
215
  - [`mpc`](https://en.wikipedia.org/wiki/Musepack) - Musepack (SV7 & SV8)
182
216
  - [`ics`](https://en.wikipedia.org/wiki/ICalendar#Data_format) - iCalendar
183
217
  - [`glb`](https://github.com/KhronosGroup/glTF) - GL Transmission Format
218
+ - [`pcap`](https://wiki.wireshark.org/Development/LibpcapFileFormat) - Libpcap File Format
184
219
 
185
220
  *SVG isn't included as it requires the whole file to be read, but you can get it [here](https://github.com/sindresorhus/is-svg).*
186
221