New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

nestjs-form-data

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nestjs-form-data - npm Package Compare versions

Comparing version 1.7.1 to 1.8.0

dist/decorators/validation/has-extension.validator.d.ts

10

dist/classes/FormReader.js

@@ -10,2 +10,3 @@ "use strict";

const common_1 = require("@nestjs/common");
const file_type_1 = __importDefault(require("file-type"));
class FormReader {

@@ -87,3 +88,10 @@ constructor(req, config) {

async loadFile(originalName, encoding, mimetype, stream) {
return await this.config['storage'].create(originalName, encoding, mimetype, stream, this.config);
const streamWithFileType = await file_type_1.default.stream(stream);
const storedFile = await this.config['storage'].create({
originalName,
encoding,
mimetype,
}, streamWithFileType, this.config);
storedFile.setFileTypeResult(streamWithFileType.fileType);
return storedFile;
}

@@ -90,0 +98,0 @@ }

9

dist/classes/storage/FileSystemStoredFile.d.ts
/// <reference types="node" />
import { StoredFile } from './StoredFile';
import { FormDataInterceptorConfig } from '../../interfaces/FormDataInterceptorConfig';
import { Readable as ReadableStream } from 'node:stream';
import { ParticleStoredFile } from '../../interfaces/ParticleStoredFile';
export declare class FileSystemStoredFile extends StoredFile {
mimetype: string;
encoding: string;
originalName: string;
path: string;
size: number;
path: string;
static create(originalName: any, encoding: any, mimetype: any, stream: NodeJS.ReadableStream, config: FormDataInterceptorConfig): Promise<FileSystemStoredFile>;
static create(busboyFileMeta: ParticleStoredFile, stream: ReadableStream, config: FormDataInterceptorConfig): Promise<FileSystemStoredFile>;
private static makeFileNameWithSalt;

@@ -12,0 +11,0 @@ delete(): Promise<void>;

@@ -26,3 +26,2 @@ "use strict";

exports.FileSystemStoredFile = void 0;
const class_transformer_1 = require("class-transformer");
const StoredFile_1 = require("./StoredFile");

@@ -33,6 +32,7 @@ const mkdirp_1 = __importDefault(require("mkdirp"));

const uid_1 = require("uid");
const class_transformer_1 = require("class-transformer");
class FileSystemStoredFile extends StoredFile_1.StoredFile {
static async create(originalName, encoding, mimetype, stream, config) {
static async create(busboyFileMeta, stream, config) {
await mkdirp_1.default.native(config.fileSystemStoragePath);
const filePath = path_1.default.resolve(config.fileSystemStoragePath, FileSystemStoredFile.makeFileNameWithSalt(originalName));
const filePath = path_1.default.resolve(config.fileSystemStoragePath, FileSystemStoredFile.makeFileNameWithSalt(busboyFileMeta.originalName));
return new Promise((res, rej) => {

@@ -45,5 +45,5 @@ const outStream = fs.createWriteStream(filePath);

const file = class_transformer_1.plainToClass(FileSystemStoredFile, {
originalName,
encoding,
mimetype,
originalName: busboyFileMeta.originalName,
encoding: busboyFileMeta.encoding,
busBoyMimeType: busboyFileMeta.mimetype,
path: filePath,

@@ -50,0 +50,0 @@ size,

/// <reference types="node" />
import { StoredFile } from './StoredFile';
import { FormDataInterceptorConfig } from '../../interfaces/FormDataInterceptorConfig';
import { Readable as ReadableStream } from 'node:stream';
import { ParticleStoredFile } from '../../interfaces/ParticleStoredFile';
export declare class MemoryStoredFile extends StoredFile {
mimetype: string;
encoding: string;
originalName: string;
size: number;
buffer: Buffer;
static create(originalName: any, encoding: any, mimetype: any, stream: NodeJS.ReadableStream, config: FormDataInterceptorConfig): Promise<MemoryStoredFile>;
static create(busboyFileMeta: ParticleStoredFile, stream: ReadableStream, config: FormDataInterceptorConfig): Promise<MemoryStoredFile>;
delete(): Promise<void>;
}
//# sourceMappingURL=MemoryStoredFile.d.ts.map
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -16,13 +7,13 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

exports.MemoryStoredFile = void 0;
const class_transformer_1 = require("class-transformer");
const StoredFile_1 = require("./StoredFile");
const concat_stream_1 = __importDefault(require("concat-stream"));
const class_transformer_1 = require("class-transformer");
class MemoryStoredFile extends StoredFile_1.StoredFile {
static create(originalName, encoding, mimetype, stream, config) {
static create(busboyFileMeta, stream, config) {
return new Promise((res, rej) => {
stream.pipe(concat_stream_1.default({ encoding: 'buffer' }, (buffer) => {
const file = class_transformer_1.plainToClass(MemoryStoredFile, {
originalName,
encoding,
mimetype,
originalName: busboyFileMeta.originalName,
encoding: busboyFileMeta.encoding,
busBoyMimeType: busboyFileMeta.mimetype,
buffer,

@@ -39,7 +30,3 @@ size: buffer.length,

}
__decorate([
class_transformer_1.Transform((params) => (params.value instanceof Buffer) ? params.value : null),
__metadata("design:type", Buffer)
], MemoryStoredFile.prototype, "buffer", void 0);
exports.MemoryStoredFile = MemoryStoredFile;
//# sourceMappingURL=MemoryStoredFile.js.map
/// <reference types="node" />
import { ParticleStoredFile } from '../../interfaces/ParticleStoredFile';
import { FormDataInterceptorConfig } from '../../interfaces/FormDataInterceptorConfig';
import { Readable as ReadableStream } from 'node:stream';
import { FileTypeResult } from 'file-type/core';
import { MetaFieldSource } from '../../interfaces/MetaFieldSource';
export declare abstract class StoredFile implements ParticleStoredFile {
abstract mimetype: string;
abstract encoding: string;
abstract originalName: string;
encoding: string;
originalName: string;
abstract size: number;
static create(originalName: any, encoding: any, mimetype: any, stream: NodeJS.ReadableStream, config: FormDataInterceptorConfig): Promise<StoredFile>;
protected busBoyMimeType: string;
protected fileType: FileTypeResult;
static create(busboyFileMeta: ParticleStoredFile, stream: ReadableStream, config: FormDataInterceptorConfig): Promise<StoredFile>;
setFileTypeResult(fileType: FileTypeResult): void;
get mimeType(): string;
get mimetype(): string;
get extension(): string;
get mimeTypeWithSource(): MetaFieldSource;
get extensionWithSource(): MetaFieldSource;
abstract delete(): Promise<void>;
}
//# sourceMappingURL=StoredFile.d.ts.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StoredFile = void 0;
const MetaFieldSource_1 = require("../../interfaces/MetaFieldSource");
const path_1 = __importDefault(require("path"));
class StoredFile {
static create(originalName, encoding, mimetype, stream, config) {
static create(busboyFileMeta, stream, config) {
throw new Error(`Static method create must be implemented`);
}
;
setFileTypeResult(fileType) {
this.fileType = fileType;
}
get mimeType() {
var _a;
return ((_a = this.fileType) === null || _a === void 0 ? void 0 : _a.mime) || this.busBoyMimeType;
}
// Compatibility with previous versions
get mimetype() {
return this.mimeType;
}
get extension() {
var _a;
return ((_a = this.fileType) === null || _a === void 0 ? void 0 : _a.ext) || (path_1.default.parse(this.originalName).ext || '').replace('.', '');
}
get mimeTypeWithSource() {
var _a;
const value = this.mimeType;
const source = (!!((_a = this.fileType) === null || _a === void 0 ? void 0 : _a.mime)) ? MetaFieldSource_1.MetaSource.bufferMagicNumber : MetaFieldSource_1.MetaSource.contentType;
return { value, source };
}
get extensionWithSource() {
var _a;
const value = this.extension;
const source = (!!((_a = this.fileType) === null || _a === void 0 ? void 0 : _a.ext)) ? MetaFieldSource_1.MetaSource.bufferMagicNumber : MetaFieldSource_1.MetaSource.contentType;
return { value, source };
}
}
exports.StoredFile = StoredFile;
//# sourceMappingURL=StoredFile.js.map
export * from './form-data';
export * from './validation/has-mime-type.validator';
export * from './validation/is-file.validator';

@@ -7,2 +6,4 @@ export * from './validation/is-files.validator';

export * from './validation/min-file-size.validator';
export * from './validation/has-mime-type.validator';
export * from './validation/has-extension.validator';
//# sourceMappingURL=index.d.ts.map

@@ -14,3 +14,2 @@ "use strict";

__exportStar(require("./form-data"), exports);
__exportStar(require("./validation/has-mime-type.validator"), exports);
__exportStar(require("./validation/is-file.validator"), exports);

@@ -20,2 +19,4 @@ __exportStar(require("./validation/is-files.validator"), exports);

__exportStar(require("./validation/min-file-size.validator"), exports);
__exportStar(require("./validation/has-mime-type.validator"), exports);
__exportStar(require("./validation/has-extension.validator"), exports);
//# sourceMappingURL=index.js.map
import { ValidationOptions } from 'class-validator';
export declare function HasMimeType(allowedMimeTypes: string[], validationOptions?: ValidationOptions): PropertyDecorator;
import { MetaSource } from '../../interfaces/MetaFieldSource';
export declare function HasMimeType(allowedMimeTypes: string[] | string, strictSource?: MetaSource | ValidationOptions, validationOptions?: ValidationOptions): PropertyDecorator;
//# sourceMappingURL=has-mime-type.validator.d.ts.map

@@ -6,3 +6,4 @@ "use strict";

const is_file_validator_1 = require("./is-file.validator");
function HasMimeType(allowedMimeTypes, validationOptions) {
const toArray_1 = require("../../helpers/toArray");
function HasMimeType(allowedMimeTypes, strictSource, validationOptions) {
return class_validator_1.ValidateBy({

@@ -13,5 +14,9 @@ name: 'HasMimeType',

validate(value, args) {
const allowedMimeTypes = args.constraints[0] || [];
const allowedMimeTypes = toArray_1.toArray(args.constraints[0]) || [];
const strictSource = (typeof args.constraints[1] === 'string')
? args.constraints[1]
: undefined;
if (is_file_validator_1.isFile(value)) {
return allowedMimeTypes.includes(value.mimetype);
const mimeWithSource = value.mimeTypeWithSource;
return allowedMimeTypes.includes(mimeWithSource.value) && (!strictSource || strictSource === mimeWithSource.source);
}

@@ -21,9 +26,9 @@ return false;

defaultMessage(validationArguments) {
const allowedMimeTypes = validationArguments.constraints[0] || [];
const allowedMimeTypes = toArray_1.toArray(validationArguments.constraints[0]) || [];
return `File must be of one of the types ${allowedMimeTypes.join(', ')}`;
},
},
}, validationOptions);
}, validationOptions || ((typeof strictSource === 'object') ? strictSource : null));
}
exports.HasMimeType = HasMimeType;
//# sourceMappingURL=has-mime-type.validator.js.map
{
"name": "nestjs-form-data",
"version": "1.7.1",
"version": "1.8.0",
"description": "NestJS middleware for handling multipart/form-data, which is primarily used for uploading files",

@@ -14,3 +14,3 @@ "main": "dist/index",

"prepublish": "npm run test:e2e && npm run build",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config test/jest-e2e.js"
},

@@ -56,2 +56,3 @@ "author": "dmitriy-nz",

"concat-stream": "^2.0.0",
"file-type": "^16.5.4",
"mkdirp": "^1.0.4",

@@ -58,0 +59,0 @@ "type-is": "^1.6.18",

@@ -19,2 +19,4 @@ [![npm version](https://badge.fury.io/js/nestjs-form-data.svg)](https://badge.fury.io/js/nestjs-form-data)

[Changelog](blob/master/CHANGELOG.md)
## Installation

@@ -153,13 +155,59 @@ ```sh

By default, several validators are available with which you can check the file
Note: If you need to validate an array of files for size or otherwise, use `each: true` property from `ValidationOptions`
`@IsFile()` - Checks if the value is an uploaded file
`@IsFiles()` - Checks an array of files
`@MaxFileSize()` - Maximum allowed file size
`@MinFileSize()` - Minimum allowed file size
`@HasMimeType()` - Check the mime type of the file
### IsFile
Checks if the value is an uploaded file
```ts
@IsFile(validationOptions?: ValidationOptions)
```
If you need to validate an array of files for size or otherwise, use `each: true` property from `ValidationOptions`
### IsFiles
Checks an array of files, the same as `@IsFile({ each: true })`
For convenience
```ts
@IsFiles(validationOptions?: ValidationOptions)
```
### MaxFileSize
Maximum allowed file size
```ts
@MaxFileSize(maxSizeBytes: number, validationOptions?: ValidationOptions)
```
### MinFileSize
Minimum allowed file size
```ts
@MinFileSize(minSizeBytes: number, validationOptions?: ValidationOptions)
```
### HasMimeType
Check the mime type of the file
The library uses two sources to get the mime type for the file:
- [file-type](https://www.npmjs.com/package/file-type) library gets mime-type: gets the mime-type from the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) directly from the binary data, it is a reliable source because it checks the file itself but may not return values for some files
- content type header from [busboy](https://www.npmjs.com/package/busboy: is a less trusted source because it can be tampered with
*Priority of receiving mime-type corresponds to the list*
The default is simple mode, which does not check the data source, but you can pass a second argument to strictly check the mime-type and data source.
You can also get the mime type and data source via the `get mimeTypeWithSource():MetaFieldSource` getter on the `StoredFile`
```ts
@HasMimeType(allowedMimeTypes: string[] | string, strictSource?: MetaSource | ValidationOptions, validationOptions?: ValidationOptions)
```
### HasExtension
Check the extension type of the file
The library uses two sources to get the extension for the file:
- [file-type](https://www.npmjs.com/package/file-type) library gets mime-type: gets the extension from the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) directly from the binary data, it is a reliable source because it checks the file itself but may not return values for some files
- value after the last dot in file name: is a less trusted source because it can be tampered with
*Priority of receiving extension corresponds to the list*
The default is simple mode, which does not check the data source, but you can pass a second argument to strictly check the extension and data source.
You can also get the extension and data source via the `get extensionWithSource():MetaFieldSource` getter on the `StoredFile`
```ts
@HasExtension(allowedMimeTypes: string[] | string, strictSource?: MetaSource | ValidationOptions, validationOptions?: ValidationOptions)
```
## Examples

@@ -166,0 +214,0 @@ ### FileSystemStoredFile storage configuration

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc