Socket
Socket
Sign inDemoInstall

file-type

Package Overview
Dependencies
11
Maintainers
1
Versions
142
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 18.6.0 to 18.7.0

105

core.d.ts

@@ -156,2 +156,3 @@ import type {Readable as ReadableStream} from 'node:stream';

| 'icc'
| 'fbx'
; // eslint-disable-line semi-style

@@ -306,2 +307,3 @@

| 'application/vnd.iccprofile'
| 'application/x.autodesk.fbx'
; // eslint-disable-line semi-style

@@ -332,4 +334,4 @@

@param buffer - An Uint8Array or Buffer representing file data. It works best if the buffer contains the entire file, it may work with a smaller portion as well.
@returns The detected file type and MIME type, or `undefined` when there is no match.
@param buffer - An Uint8Array or Buffer representing file data. It works best if the buffer contains the entire file. It may work with a smaller portion as well.
@returns The detected file type, or `undefined` when there is no match.
*/

@@ -344,3 +346,3 @@ export function fileTypeFromBuffer(buffer: Uint8Array | ArrayBuffer): Promise<FileTypeResult | undefined>;

@param stream - A readable stream representing file data.
@returns The detected file type and MIME type, or `undefined` when there is no match.
@returns The detected file type, or `undefined` when there is no match.
*/

@@ -357,3 +359,3 @@ export function fileTypeFromStream(stream: ReadableStream): Promise<FileTypeResult | undefined>;

@param tokenizer - File source implementing the tokenizer interface.
@returns The detected file type and MIME type, or `undefined` when there is no match.
@returns The detected file type, or `undefined` when there is no match.

@@ -429,4 +431,7 @@ An example is [`@tokenizer/http`](https://github.com/Borewit/tokenizer-http), which requests data using [HTTP-range-requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests). A difference with a conventional stream and the [*tokenizer*](https://github.com/Borewit/strtok3#tokenizer), is that it is able to *ignore* (seek, fast-forward) in the stream. For example, you may only need and read the first 6 bytes, and the last 128 bytes, which may be an advantage in case reading the entire file would take longer.

/**
Detect the file type of a [`Blob`](https://nodejs.org/api/buffer.html#class-blob).
Detect the file type of a [`Blob`](https://nodejs.org/api/buffer.html#class-blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).
@param blob - The [`Blob`](https://nodejs.org/api/buffer.html#class-blob) used for file detection.
@returns The detected file type, or `undefined` when there is no match.
@example

@@ -437,3 +442,3 @@ ```

const blob = new Blob(['<?xml version="1.0" encoding="ISO-8859-1" ?>'], {
type: 'plain/text',
type: 'text/plain',
endings: 'native'

@@ -443,5 +448,91 @@ });

console.log(await fileTypeFromBlob(blob));
//=> {ext: 'txt', mime: 'plain/text'}
//=> {ext: 'txt', mime: 'text/plain'}
```
*/
export declare function fileTypeFromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
/**
Function that allows specifying custom detection mechanisms.
An iterable of detectors can be provided via the `fileTypeOptions` argument for the {@link FileTypeParser.constructor}.
The detectors are called before the default detections in the provided order.
Custom detectors can be used to add new `FileTypeResults` or to modify return behavior of existing `FileTypeResult` detections.
If the detector returns `undefined`, there are 2 possible scenarios:
1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
Example detector array which can be extended and provided via the fileTypeOptions argument:
```
import {FileTypeParser} from 'file-type';
const customDetectors = [
async tokenizer => {
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
const buffer = Buffer.alloc(7);
await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
if (unicornHeader.every((value, index) => value === buffer[index])) {
return {ext: 'unicorn', mime: 'application/unicorn'};
}
return undefined;
},
];
const buffer = Buffer.from('UNICORN');
const parser = new FileTypeParser({customDetectors});
const fileType = await parser.fromBuffer(buffer);
console.log(fileType);
```
@param tokenizer - The [tokenizer](https://github.com/Borewit/strtok3#tokenizer) used to read the file content from.
@param fileType - The file type detected by the standard detections or a previous custom detection, or `undefined`` if no matching file type could be found.
@returns The detected file type, or `undefined` when there is no match.
*/
export type Detector = (tokenizer: ITokenizer, fileType?: FileTypeResult) => Promise<FileTypeResult | undefined>;
export type FileTypeOptions = {
customDetectors?: Iterable<Detector>;
};
export declare class TokenizerPositionError extends Error {
constructor(message?: string);
}
export declare class FileTypeParser {
detectors: Iterable<Detector>;
constructor(options?: {customDetectors?: Iterable<Detector>});
/**
Works the same way as {@link fileTypeFromBuffer}, additionally taking into account custom detectors (if any were provided to the constructor).
*/
fromBuffer(buffer: Uint8Array | ArrayBuffer): Promise<FileTypeResult | undefined>;
/**
Works the same way as {@link fileTypeFromStream}, additionally taking into account custom detectors (if any were provided to the constructor).
*/
fromStream(stream: ReadableStream): Promise<FileTypeResult | undefined>;
/**
Works the same way as {@link fileTypeFromTokenizer}, additionally taking into account custom detectors (if any were provided to the constructor).
*/
fromTokenizer(tokenizer: ITokenizer): Promise<FileTypeResult | undefined>;
/**
Works the same way as {@link fileTypeFromBlob}, additionally taking into account custom detectors (if any were provided to the constructor).
*/
fromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
/**
Works the same way as {@link fileTypeStream}, additionally taking into account custom detectors (if any were provided to the constructor).
*/
toDetectionStream(readableStream: ReadableStream, options?: StreamOptions): Promise<FileTypeResult | undefined>;
}

162

core.js

@@ -14,27 +14,11 @@ import {Buffer} from 'node:buffer';

export async function fileTypeFromStream(stream) {
const tokenizer = await strtok3.fromStream(stream);
try {
return await fileTypeFromTokenizer(tokenizer);
} finally {
await tokenizer.close();
}
return new FileTypeParser().fromStream(stream);
}
export async function fileTypeFromBuffer(input) {
if (!(input instanceof Uint8Array || input instanceof ArrayBuffer)) {
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
}
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
if (!(buffer?.length > 1)) {
return;
}
return fileTypeFromTokenizer(strtok3.fromBuffer(buffer));
return new FileTypeParser().fromBuffer(input);
}
export async function fileTypeFromBlob(blob) {
const buffer = await blob.arrayBuffer();
return fileTypeFromBuffer(new Uint8Array(buffer));
return new FileTypeParser().fromBlob(blob);
}

@@ -64,12 +48,94 @@

export async function fileTypeFromTokenizer(tokenizer) {
try {
return new FileTypeParser().parse(tokenizer);
} catch (error) {
if (!(error instanceof strtok3.EndOfStreamError)) {
throw error;
return new FileTypeParser().fromTokenizer(tokenizer);
}
export class FileTypeParser {
constructor(options) {
this.detectors = options?.customDetectors;
this.fromTokenizer = this.fromTokenizer.bind(this);
this.fromBuffer = this.fromBuffer.bind(this);
this.parse = this.parse.bind(this);
}
async fromTokenizer(tokenizer) {
const initialPosition = tokenizer.position;
for (const detector of this.detectors || []) {
const fileType = await detector(tokenizer);
if (fileType) {
return fileType;
}
if (initialPosition !== tokenizer.position) {
return undefined; // Cannot proceed scanning of the tokenizer is at an arbitrary position
}
}
return this.parse(tokenizer);
}
}
class FileTypeParser {
async fromBuffer(input) {
if (!(input instanceof Uint8Array || input instanceof ArrayBuffer)) {
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
}
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
if (!(buffer?.length > 1)) {
return;
}
return this.fromTokenizer(strtok3.fromBuffer(buffer));
}
async fromBlob(blob) {
const buffer = await blob.arrayBuffer();
return this.fromBuffer(new Uint8Array(buffer));
}
async fromStream(stream) {
const tokenizer = await strtok3.fromStream(stream);
try {
return await this.fromTokenizer(tokenizer);
} finally {
await tokenizer.close();
}
}
async toDetectionStream(readableStream, options = {}) {
const {default: stream} = await import('node:stream');
const {sampleSize = minimumBytes} = options;
return new Promise((resolve, reject) => {
readableStream.on('error', reject);
readableStream.once('readable', () => {
(async () => {
try {
// Set up output stream
const pass = new stream.PassThrough();
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
// Read the input stream and detect the filetype
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
try {
pass.fileType = await this.fromBuffer(chunk);
} catch (error) {
if (error instanceof strtok3.EndOfStreamError) {
pass.fileType = undefined;
} else {
reject(error);
}
}
resolve(outputStream);
} catch (error) {
reject(error);
}
})();
});
});
}
check(header, options) {

@@ -216,3 +282,3 @@ return _check(this.buffer, header, options);

await tokenizer.ignore(id3HeaderLength);
return fileTypeFromTokenizer(tokenizer); // Skip ID3 header, recursion
return this.fromTokenizer(tokenizer); // Skip ID3 header, recursion
}

@@ -1446,2 +1512,9 @@

if (this.checkString('Kaydara FBX Binary \u0000')) {
return {
ext: 'fbx',
mime: 'application/x.autodesk.fbx', // Invented by us
};
}
if (

@@ -1616,35 +1689,4 @@ this.check([0x4C, 0x50], {offset: 34})

export async function fileTypeStream(readableStream, {sampleSize = minimumBytes} = {}) {
const {default: stream} = await import('node:stream');
return new Promise((resolve, reject) => {
readableStream.on('error', reject);
readableStream.once('readable', () => {
(async () => {
try {
// Set up output stream
const pass = new stream.PassThrough();
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
// Read the input stream and detect the filetype
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
try {
const fileType = await fileTypeFromBuffer(chunk);
pass.fileType = fileType;
} catch (error) {
if (error instanceof strtok3.EndOfStreamError) {
pass.fileType = undefined;
} else {
reject(error);
}
}
resolve(outputStream);
} catch (error) {
reject(error);
}
})();
});
});
export async function fileTypeStream(readableStream, options = {}) {
return new FileTypeParser().toDetectionStream(readableStream, options);
}

@@ -1651,0 +1693,0 @@

import * as strtok3 from 'strtok3';
import {fileTypeFromTokenizer} from './core.js';
import {FileTypeParser} from './core.js';
export async function fileTypeFromFile(path) {
export async function fileTypeFromFile(path, fileTypeOptions) {
const tokenizer = await strtok3.fromFile(path);
try {
return await fileTypeFromTokenizer(tokenizer);
const parser = new FileTypeParser(fileTypeOptions);
return await parser.fromTokenizer(tokenizer);
} finally {

@@ -9,0 +10,0 @@ await tokenizer.close();

{
"name": "file-type",
"version": "18.6.0",
"version": "18.7.0",
"description": "Detect the file type of a Buffer/Uint8Array/ArrayBuffer",

@@ -21,2 +21,3 @@ "license": "MIT",

},
"sideEffects": false,
"engines": {

@@ -209,3 +210,4 @@ "node": ">=14.16"

"avro",
"icc"
"icc",
"fbx"
],

@@ -212,0 +214,0 @@ "dependencies": {

@@ -116,3 +116,3 @@ # file-type

Returns a `Promise` for an object with the detected file type and MIME type:
Returns a `Promise` for an object with the detected file type:

@@ -128,3 +128,3 @@ - `ext` - One of the [supported file types](#supported-file-types)

A buffer representing file data. It works best if the buffer contains the entire file, it may work with a smaller portion as well.
A buffer representing file data. It works best if the buffer contains the entire file. It may work with a smaller portion as well.

@@ -137,3 +137,3 @@ ### fileTypeFromFile(filePath)

Returns a `Promise` for an object with the detected file type and MIME type:
Returns a `Promise` for an object with the detected file type:

@@ -157,3 +157,3 @@ - `ext` - One of the [supported file types](#supported-file-types)

Returns a `Promise` for an object with the detected file type and MIME type:
Returns a `Promise` for an object with the detected file type:

@@ -177,3 +177,3 @@ - `ext` - One of the [supported file types](#supported-file-types)

Returns a `Promise` for an object with the detected file type and MIME type:
Returns a `Promise` for an object with the detected file type:

@@ -189,3 +189,3 @@ - `ext` - One of the [supported file types](#supported-file-types)

const blob = new Blob(['<?xml version="1.0" encoding="ISO-8859-1" ?>'], {
type: 'plain/text',
type: 'text/plain',
endings: 'native'

@@ -195,5 +195,9 @@ });

console.log(await fileTypeFromBlob(blob));
//=> {ext: 'txt', mime: 'plain/text'}
//=> {ext: 'txt', mime: 'text/plain'}
```
#### blob
Type: [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
### fileTypeFromTokenizer(tokenizer)

@@ -207,3 +211,3 @@

Returns a `Promise` for an object with the detected file type and MIME type:
Returns a `Promise` for an object with the detected file type:

@@ -316,2 +320,45 @@ - `ext` - One of the [supported file types](#supported-file-types)

## Custom detectors
A custom detector is a function that allows specifying custom detection mechanisms.
An iterable of detectors can be provided via the `fileTypeOptions` argument for the `FileTypeParser` constructor.
The detectors are called before the default detections in the provided order.
Custom detectors can be used to add new `FileTypeResults` or to modify return behaviour of existing `FileTypeResult` detections.
If the detector returns `undefined`, there are 2 possible scenarios:
1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
Example detector array which can be extended and provided to each public method via the `fileTypeOptions` argument:
```js
import {FileTypeParser} from 'file-type';
const customDetectors = [
async tokenizer => {
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
const buffer = Buffer.alloc(7);
await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
if (unicornHeader.every((value, index) => value === buffer[index])) {
return {ext: 'unicorn', mime: 'application/unicorn'};
}
return undefined;
},
];
const buffer = Buffer.from('UNICORN');
const parser = new FileTypeParser({customDetectors});
const fileType = await parser.fromBuffer(buffer);
console.log(fileType);
```
## Supported file types

@@ -347,3 +394,3 @@

- [`cab`](https://en.wikipedia.org/wiki/Cabinet_(file_format)) - Cabinet file
- [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format) - Compount File Binary Format
- [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format) - Compound File Binary Format
- [`chm`](https://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help) - Microsoft Compiled HTML Help

@@ -360,3 +407,3 @@ - [`class`](https://en.wikipedia.org/wiki/Java_class_file) - Java class file

- [`dng`](https://en.wikipedia.org/wiki/Digital_Negative) - Adobe Digital Negative image file
- [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word
- [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word document
- [`dsf`](https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf) - Sony DSD Stream File (DSF)

@@ -373,2 +420,3 @@ - [`dwg`](https://en.wikipedia.org/wiki/.dwg) - Autodesk CAD file

- [`f4v`](https://en.wikipedia.org/wiki/Flash_Video) - ISO base media file format used by Adobe Flash Player
- [`fbx`](https://en.wikipedia.org/wiki/FBX) - Filmbox is a proprietary file format used to provide interoperability between digital content creation apps.
- [`flac`](https://en.wikipedia.org/wiki/FLAC) - Free Lossless Audio Codec

@@ -397,3 +445,3 @@ - [`flif`](https://en.wikipedia.org/wiki/Free_Lossless_Image_Format) - Free Lossless Image Format

- [`lnk`](https://en.wikipedia.org/wiki/Shortcut_%28computing%29#Microsoft_Windows) - Microsoft Windows file shortcut
- [`lz`](https://en.wikipedia.org/wiki/Lzip) - Arhive file
- [`lz`](https://en.wikipedia.org/wiki/Lzip) - Archive file
- [`lzh`](https://en.wikipedia.org/wiki/LHA_(file_format)) - LZH archive

@@ -437,3 +485,3 @@ - [`m4a`](https://en.wikipedia.org/wiki/M4A) - Audio-only MPEG-4 files

- [`png`](https://en.wikipedia.org/wiki/Portable_Network_Graphics) - Portable Network Graphics
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint document
- [`ps`](https://en.wikipedia.org/wiki/Postscript) - Postscript

@@ -468,3 +516,3 @@ - [`psd`](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) - Adobe Photoshop document

- [`xcf`](https://en.wikipedia.org/wiki/XCF_(file_format)) - eXperimental Computing Facility
- [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel
- [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel document
- [`xm`](https://wiki.openmpt.org/Manual:_Module_formats#The_FastTracker_2_format_.28.xm.29) - Audio module format: FastTracker 2

@@ -477,3 +525,3 @@ - [`xml`](https://en.wikipedia.org/wiki/XML) - eXtensible Markup Language

*Pull requests are welcome for additional commonly used file types.*
*[Pull requests](.github/pull_request_template.md) are welcome for additional commonly used file types.*

@@ -489,5 +537,20 @@ The following file types will not be accepted:

#### tokenizer
Type: [`ITokenizer`](https://github.com/Borewit/strtok3#tokenizer)
Usable as source of the examined file.
#### fileType
Type: `FileTypeResult`
An object having an `ext` (extension) and `mime` (mime type) property.
Detected by the standard detections or a previous custom detection. Undefined if no matching fileTypeResult could be found.
## Related
- [file-type-cli](https://github.com/sindresorhus/file-type-cli) - CLI for this module
- [image-dimensions](https://github.com/sindresorhus/image-dimensions) - Get the dimensions of an image

@@ -498,6 +561,1 @@ ## Maintainers

- [Borewit](https://github.com/Borewit)
**Former**
- [Mikael Finstad](https://github.com/mifi)
- [Ben Brook](https://github.com/bencmbrook)

@@ -153,2 +153,3 @@ export const extensions = [

'icc',
'fbx',
];

@@ -303,2 +304,3 @@

'application/vnd.iccprofile',
'application/x.autodesk.fbx', // Invented by us
];
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc