Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@openfin/multer-s3

Package Overview
Dependencies
Maintainers
10
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@openfin/multer-s3 - npm Package Compare versions

Comparing version 1.0.2 to 2.0.0

.env

104

build/index.d.ts
/// <reference types="node" />
/// <reference types="express" />
import * as fs from "fs";
import * as Stream from "stream";
import { ReadStream } from "fs";
import { PassThrough, Transform } from "stream";
import * as express from "express";
import * as aws from "aws-sdk";
import * as AWS from "aws-sdk";
declare global {

@@ -11,4 +11,3 @@ namespace Express {

interface File {
key: string;
stream: fs.ReadStream;
stream: ReadStream;
}

@@ -18,28 +17,5 @@ }

}
export declare type valuerFunc = (file: Express.Multer.File, storage: S3Storage, req: express.Request) => Promise<string | Buffer | null | {
[key: string]: string;
}>;
export interface S3StorageOpts {
s3: aws.S3;
bucket?: string | valuerFunc;
acl?: string | valuerFunc;
key?: valuerFunc;
serverSideEncryptionKMSKeyId?: string | valuerFunc;
serverSideEncryption?: string | valuerFunc;
storageClass?: string | valuerFunc;
cacheControl?: string | valuerFunc;
contentDisposition?: string | valuerFunc;
metadata?: {
[key: string]: any;
} | valuerFunc;
contentType?: string | valuerFunc;
serverSideEncryptionCustomerKey?: string | Buffer | valuerFunc;
serverSideEncryptionCustomerKeyMD5?: string | valuerFunc;
serverSideEncryptionCustomerAlgorithm?: string | valuerFunc;
onUpload?: (req: express.Request, storage: S3Storage, file: S3File) => any;
detectContentType?: boolean;
}
export declare function detectContentType(filestream: fs.ReadStream): Promise<{
export declare function detectContentType(filestream: ReadStream): Promise<{
contentType: string;
reStream: Stream.PassThrough;
reStream: PassThrough;
}>;

@@ -64,4 +40,7 @@ export interface S3File extends Express.Multer.File {

etag: string;
[i: string]: any;
}
export declare type multerStorageFns = (req: express.Request, file: Express.Multer.File, cb: (err: Error | null, S3File: S3File) => void) => void;
export interface multerStorageFns {
(req: express.Request, file: Express.Multer.File, cb: (err: Error | null, File: File) => void): void;
}
export interface MulterStorage {

@@ -71,22 +50,53 @@ _removeFile: multerStorageFns;

}
export interface PromisedFn<T> {
(f: Express.Multer.File, s3Storage: S3Storage, req: express.Request): Promise<T>;
}
export interface TransformFuncs {
(file: Express.Multer.File, s3Storage: S3Storage, req: express.Request): Promise<Transform>;
}
export interface S3StorageOpts {
s3?: AWS.S3;
bucket: string | PromisedFn<string>;
acl?: string | PromisedFn<string>;
key?: PromisedFn<string>;
serverSideEncryptionKMSKeyId?: string | PromisedFn<string>;
serverSideEncryption?: string | PromisedFn<string>;
storageClass?: string | PromisedFn<string>;
cacheControl?: string | PromisedFn<string>;
contentDisposition?: string | PromisedFn<string>;
metadata?: {
[key: string]: any;
} | PromisedFn<{
[key: string]: any;
}>;
contentType?: PromisedFn<string>;
serverSideEncryptionCustomerKey?: string | Buffer | PromisedFn<string | Buffer>;
serverSideEncryptionCustomerKeyMD5?: string | PromisedFn<string>;
serverSideEncryptionCustomerAlgorithm?: string | PromisedFn<string>;
onUpload?: (req: express.Request, storage: S3Storage, file: S3File) => any;
streamTransformers?: TransformFuncs[];
detectContentType?: boolean;
}
export default class S3Storage implements MulterStorage {
bucket: valuerFunc;
acl: valuerFunc;
key: valuerFunc;
serverSideEncryptionKMSKeyId: valuerFunc;
serverSideEncryption: valuerFunc;
serverSideEncryptionCustomerKey: valuerFunc;
serverSideEncryptionCustomerAlgorithm: valuerFunc;
serverSideEncryptionCustomerKeyMD5: valuerFunc;
storageClass: valuerFunc;
cacheControl: valuerFunc;
contentDisposition: valuerFunc;
metadata: valuerFunc;
contentType: valuerFunc;
detectContentType: boolean;
s3: AWS.S3;
onUpload: (req: express.Request, storage: S3Storage, file: S3File) => any;
detectContentType: boolean;
bucket: PromisedFn<string>;
key: PromisedFn<string>;
acl: PromisedFn<string>;
serverSideEncryptionKMSKeyId: PromisedFn<string>;
serverSideEncryption: PromisedFn<string>;
storageClass: PromisedFn<string>;
cacheControl: PromisedFn<string>;
contentDisposition: PromisedFn<string>;
metadata: PromisedFn<{
[key: string]: any;
}> | PromisedFn<null>;
contentType: PromisedFn<string>;
serverSideEncryptionCustomerKey: PromisedFn<string | Buffer>;
serverSideEncryptionCustomerKeyMD5: PromisedFn<string>;
serverSideEncryptionCustomerAlgorithm: PromisedFn<string>;
streamTransformers: TransformFuncs[];
constructor(opts: S3StorageOpts);
_handleFile(req: express.Request, file: Express.Multer.File, cb: (error: Error, data?: any) => void): Promise<void>;
_removeFile(req: express.Request, file: S3File, cb: (error: Error, data: any) => void): void;
_handleFile(req: express.Request, file: S3File, cb: (error: Error, data?: any) => void): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fileType = require("file-type");
const Stream = require("stream");
const kindOf = require("kind-of");
const STORAGE_DEFAULTS = {
acl: () => Promise.resolve("private"),
contentType: () => Promise.resolve("application/octet-stream"),
metadata: () => Promise.resolve(null),
contentDisposition: () => Promise.resolve(null),
storageClass: () => Promise.resolve("STANDARD"),
serverSideEncryption: () => Promise.resolve(null),
serverSideEncryptionKMSKeyId: () => Promise.resolve(null),
cacheControl: () => Promise.resolve(null),
serverSideEncryptionCustomerKey: () => Promise.resolve(null),
serverSideEncryptionCustomerKeyMD5: () => Promise.resolve(null),
onUpload: function (req, storage, file) { },
detectContentType: false
};
const stream_1 = require("stream");
const AWS = require("aws-sdk");
const pProps = require("p-props");
const crypto_1 = require("crypto");
function detectContentType(filestream) {

@@ -25,3 +13,3 @@ return new Promise((resolve, reject) => {

const type = fileType(chunk);
const reStream = new Stream.PassThrough();
const reStream = new stream_1.PassThrough();
reStream.write(chunk);

@@ -43,155 +31,153 @@ filestream.pipe(reStream);

exports.detectContentType = detectContentType;
function promisify(s) {
return () => Promise.resolve(s);
}
function keyGen() {
return Promise.resolve(crypto_1.randomBytes(8).toString("hex"));
}
class S3Storage {
constructor(opts) {
const vopts = Object.assign({}, STORAGE_DEFAULTS, opts);
this.s3 = vopts.s3;
if (kindOf(vopts.bucket) === "string") {
this.bucket = () => Promise.resolve(vopts.bucket);
this.s3 = opts.s3 ? new AWS.S3() : opts.s3;
const defaults = {
bucket: "",
acl: promisify("private"),
cacheControl: promisify(null),
contentDisposition: promisify(null),
serverSideEncryption: promisify("AES256"),
serverSideEncryptionKMSKeyId: promisify(null),
serverSideEncryptionCustomerAlgorithm: promisify(null),
serverSideEncryptionCustomerKeyMD5: promisify(null),
storageClass: promisify("STANDARD")
};
opts = Object.assign(defaults, opts);
if (typeof opts.bucket === "string") {
this.bucket = promisify(opts.bucket);
}
else if (kindOf(vopts.bucket) == "function") {
this.bucket = vopts.bucket;
}
else {
throw new Error("bucket must be a string or a function");
this.bucket = opts.bucket;
}
if (kindOf(vopts.acl) === "string") {
this.acl = () => Promise.resolve(vopts.acl);
if (typeof opts.acl === "string") {
this.acl = promisify(opts.acl);
}
else if (kindOf(vopts.acl) == "function") {
this.acl = vopts.acl;
}
else {
throw new Error("acl must be a string, function or null/undefined");
this.acl = opts.acl;
}
if (kindOf(vopts.contentType) === "string") {
this.contentType = () => Promise.resolve(vopts.contentType);
this.key = opts.key == null ? keyGen : opts.key;
if (typeof opts.serverSideEncryptionKMSKeyId === "string") {
this.serverSideEncryptionKMSKeyId = promisify(opts.serverSideEncryptionKMSKeyId);
}
else if (kindOf(vopts.contentType) == "function") {
this.contentType = vopts.contentType;
}
else {
throw new Error("contentType must be a string, function or null/undefined");
this.serverSideEncryptionKMSKeyId = opts.serverSideEncryptionKMSKeyId;
}
if (kindOf(vopts.key) === "function") {
this.key = vopts.key;
if (typeof opts.serverSideEncryption === "string") {
this.serverSideEncryption = promisify(opts.serverSideEncryption);
}
else {
throw new Error("key must be a function");
this.serverSideEncryption = opts.serverSideEncryption;
}
if (kindOf(vopts.serverSideEncryption) === "function") {
this.serverSideEncryption = vopts.serverSideEncryption;
if (typeof opts.storageClass === "string") {
this.storageClass = promisify(opts.storageClass);
}
else if (kindOf(vopts.serverSideEncryption) === "string") {
this.serverSideEncryption = () => Promise.resolve(vopts.serverSideEncryption);
}
else if (vopts.serverSideEncryption == null) {
this.serverSideEncryption = () => Promise.resolve(null);
}
else {
throw new Error("serverSideEncryption must be a string, function or null/undefined");
this.storageClass = opts.storageClass;
}
if (kindOf(vopts.serverSideEncryptionCustomerKeyMD5) === "function") {
this.serverSideEncryptionCustomerKeyMD5 = vopts.serverSideEncryptionCustomerKeyMD5;
if (typeof opts.cacheControl === "string") {
this.cacheControl = promisify(opts.cacheControl);
}
else if (kindOf(vopts.serverSideEncryptionCustomerKeyMD5) === "string") {
this.serverSideEncryptionCustomerKeyMD5 = () => Promise.resolve(vopts.serverSideEncryptionCustomerKeyMD5);
}
else if (vopts.serverSideEncryptionCustomerKeyMD5 == null) {
this.serverSideEncryptionCustomerKeyMD5 = () => Promise.resolve(null);
}
else {
throw new Error("serverSideEncryptionCustomerKeyMD5 must be a string, function or null/undefined");
this.cacheControl = opts.cacheControl;
}
if (kindOf(vopts.serverSideEncryptionCustomerAlgorithm) === "function") {
this.serverSideEncryptionCustomerAlgorithm = vopts.serverSideEncryptionCustomerAlgorithm;
if (typeof opts.contentDisposition === "string") {
this.contentDisposition = promisify(opts.contentDisposition);
}
else if (kindOf(vopts.serverSideEncryptionCustomerAlgorithm) === "string") {
this.serverSideEncryptionCustomerAlgorithm = () => Promise.resolve(vopts.serverSideEncryptionCustomerAlgorithm);
}
else if (vopts.serverSideEncryptionCustomerAlgorithm == null) {
this.serverSideEncryptionCustomerAlgorithm = () => Promise.resolve(null);
}
else {
throw new Error("serverSideEncryptionCustomerAlgorithm must be a string, function or null/undefined");
this.contentDisposition = opts.contentDisposition;
}
if (kindOf(vopts.serverSideEncryptionKMSKeyId) === "function") {
this.serverSideEncryptionKMSKeyId = vopts.serverSideEncryptionKMSKeyId;
if (typeof opts.metadata === "object") {
this.metadata = promisify(opts.metadata);
}
else if (kindOf(vopts.serverSideEncryptionKMSKeyId) === "string") {
this.serverSideEncryptionKMSKeyId = () => Promise.resolve(vopts.serverSideEncryptionKMSKeyId);
else if (opts.metadata == null) {
this.metadata = promisify(opts.metadata);
}
else if (vopts.serverSideEncryptionKMSKeyId == null) {
this.serverSideEncryptionKMSKeyId = () => Promise.resolve(null);
}
else {
throw new Error("serverSideEncryptionKMSKeyId must be a string, function or null/undefined");
this.metadata = opts.metadata;
}
if (kindOf(vopts.serverSideEncryptionKMSKeyId) === "function") {
this.serverSideEncryptionKMSKeyId = vopts.serverSideEncryptionKMSKeyId;
this.contentType =
opts.contentType == null ? promisify("") : opts.contentType;
if (typeof opts.serverSideEncryptionCustomerKey === "string" ||
Buffer.isBuffer(opts.serverSideEncryptionCustomerKey)) {
this.serverSideEncryptionCustomerKey = promisify(opts.serverSideEncryptionCustomerKey);
}
else if (kindOf(vopts.serverSideEncryptionKMSKeyId) === "string") {
this.serverSideEncryptionKMSKeyId = () => Promise.resolve(vopts.serverSideEncryptionKMSKeyId);
}
else if (vopts.serverSideEncryptionKMSKeyId == null) {
this.serverSideEncryptionKMSKeyId = () => Promise.resolve(null);
}
else {
throw new Error("serverSideEncryptionKMSKeyId must be a string, function or null/undefined");
this.serverSideEncryptionCustomerKey = promisify(null);
}
if (kindOf(vopts.serverSideEncryptionCustomerKey) === "function") {
this.serverSideEncryptionCustomerKey = vopts.serverSideEncryptionCustomerKey;
if (typeof opts.serverSideEncryptionCustomerKeyMD5 === "string") {
this.serverSideEncryptionCustomerKeyMD5 = promisify(opts.serverSideEncryptionCustomerKeyMD5);
}
else if (kindOf(vopts.serverSideEncryptionCustomerKey) === "string") {
this.serverSideEncryptionCustomerKey = () => Promise.resolve(vopts.serverSideEncryptionCustomerKey);
}
else if (Buffer.isBuffer(vopts.serverSideEncryptionCustomerKey)) {
this.serverSideEncryptionCustomerKey = () => Promise.resolve(vopts.serverSideEncryptionCustomerKey);
}
else if (vopts.serverSideEncryptionCustomerKey == null) {
this.serverSideEncryptionCustomerKey = () => Promise.resolve(null);
}
else {
throw new Error("serverSideEncryptionCustomerKey must be a string, function, buffer or null/undefined");
this.serverSideEncryptionCustomerKeyMD5 =
opts.serverSideEncryptionCustomerKeyMD5;
}
if (kindOf(vopts.storageClass) === "string") {
this.storageClass = () => Promise.resolve(vopts.storageClass);
if (typeof opts.serverSideEncryptionCustomerAlgorithm === "string") {
this.serverSideEncryptionCustomerAlgorithm = promisify(opts.serverSideEncryptionCustomerAlgorithm);
}
else if (kindOf(vopts.storageClass) == "function") {
this.storageClass = vopts.storageClass;
}
else {
throw new Error("storageClass must be a string or a function");
this.serverSideEncryptionCustomerAlgorithm =
opts.serverSideEncryptionCustomerAlgorithm;
}
if (kindOf(vopts.cacheControl) === "string") {
this.cacheControl = () => Promise.resolve(vopts.cacheControl);
this.streamTransformers = opts.streamTransformers || [];
}
async _handleFile(req, file, cb) {
try {
const args = (await pProps({
bucket: this.bucket(file, this, req),
acl: this.acl(file, this, req),
cacheControl: this.cacheControl(file, this, req),
contentDisposition: this.contentDisposition(file, this, req),
contentType: this.contentType(file, this, req),
key: this.key(file, this, req),
metadata: this.metadata(file, this, req),
serverSideEncryption: this.serverSideEncryption(file, this, req),
serverSideEncryptionKMSKeyId: this.serverSideEncryptionKMSKeyId(file, this, req),
serverSideEncryptionCustomerAlgorithm: this.serverSideEncryptionCustomerAlgorithm(file, this, req),
serverSideEncryptionCustomerKey: this.serverSideEncryptionCustomerKey(file, this, req),
serverSideEncryptionCustomerKeyMD5: this.serverSideEncryptionCustomerKeyMD5(file, this, req),
storageClass: this.storageClass(file, this, req)
}));
const { contentType, reStream } = await detectContentType(file.stream);
const transfomers = await Promise.all(this.streamTransformers.map(x => x(file, this, req)));
const fileStream = transfomers.reduce((fileStream, transformer) => {
return fileStream.pipe(transformer);
}, reStream);
const upload = this.s3.upload({
Bucket: args.bucket,
ACL: args.acl,
CacheControl: args.cacheControl,
ContentDisposition: args.contentDisposition,
ContentType: args.contentType,
Key: args.key,
Metadata: args.metadata,
ServerSideEncryption: args.serverSideEncryption,
SSEKMSKeyId: args.serverSideEncryptionKMSKeyId,
SSECustomerAlgorithm: args.serverSideEncryptionCustomerAlgorithm,
SSECustomerKey: args.serverSideEncryptionCustomerKey,
SSECustomerKeyMD5: args.serverSideEncryptionCustomerKeyMD5,
StorageClass: args.storageClass,
Body: fileStream
});
const results = await new Promise((resolve, reject) => {
upload.send((err, data) => {
if (err)
return reject(err);
resolve(Object.assign({}, args, {
location: data.Location,
etag: data.ETag
}));
});
});
cb(null, results);
}
else if (kindOf(vopts.cacheControl) == "function") {
this.cacheControl = vopts.cacheControl;
catch (err) {
return cb(err);
}
else {
throw new Error("cacheControl must be a string or a function");
}
if (kindOf(vopts.contentDisposition) === "string") {
this.contentDisposition = () => Promise.resolve(vopts.contentDisposition);
}
else if (kindOf(vopts.contentDisposition) == "function") {
this.contentDisposition = vopts.contentDisposition;
}
else {
throw new Error("contentDisposition must be a string or a function");
}
if (kindOf(vopts.metadata) === "function") {
this.metadata = vopts.metadata;
}
else if (kindOf(vopts.metadata) == "object") {
this.metadata = () => Promise.resolve(vopts.metadata);
}
else {
throw new Error("metadata must be a object or a function");
}
if (kindOf(vopts.onUpload) !== "function" && vopts.onUpload != null) {
throw new Error("onUpload must be a function or empty");
}
this.onUpload = vopts.onUpload;
this.detectContentType = vopts.detectContentType === true;
}

@@ -204,92 +190,4 @@ _removeFile(req, file, cb) {

}
_handleFile(req, file, cb) {
Promise.all([
this.bucket(file, this, req),
this.acl(file, this, req),
this.cacheControl(file, this, req),
this.contentDisposition(file, this, req),
this.contentType(file, this, req),
this.key(file, this, req),
this.metadata(file, this, req),
this.serverSideEncryption(file, this, req),
this.serverSideEncryptionKMSKeyId(file, this, req),
this.serverSideEncryptionCustomerAlgorithm(file, this, req),
this.serverSideEncryptionCustomerKey(file, this, req),
this.serverSideEncryptionCustomerKeyMD5(file, this, req),
this.storageClass(file, this, req)
])
.then(args => {
const resolvedParams = {
bucket: args[0],
acl: args[1],
cacheControl: args[2],
contentDisposition: args[3],
contentType: args[4],
key: args[5],
metadata: args[6],
serverSideEncryption: args[7],
serverSideEncryptionKMSKeyId: args[8],
serverSideEncryptionCustomerAlgorithm: args[9],
serverSideEncryptionCustomerKey: args[10],
serverSideEncryptionCustomerKeyMD5: args[11],
storageClass: args[12]
};
return detectContentType(file.stream).then(d => {
const upload = this.s3.upload({
Bucket: resolvedParams.bucket,
ACL: resolvedParams.acl,
CacheControl: resolvedParams.cacheControl,
ContentDisposition: resolvedParams.contentDisposition,
ContentType: resolvedParams.contentType,
Key: resolvedParams.key,
Metadata: resolvedParams.metadata,
ServerSideEncryption: resolvedParams.serverSideEncryption,
SSEKMSKeyId: resolvedParams.serverSideEncryptionKMSKeyId,
SSECustomerAlgorithm: resolvedParams.serverSideEncryptionCustomerAlgorithm,
SSECustomerKey: resolvedParams.serverSideEncryptionCustomerKey,
SSECustomerKeyMD5: resolvedParams.serverSideEncryptionCustomerKeyMD5,
StorageClass: resolvedParams.storageClass,
Body: d.reStream
});
return {
contentType: resolvedParams.contentType || d.contentType,
upload,
resolvedParams
};
});
})
.then(({ contentType, upload, resolvedParams }) => {
let currentSize = 0;
upload.on("httpUploadProgress", p => {
if (p.total)
currentSize = p.total;
});
upload.send((err, data) => {
if (err)
return cb(err);
const fileData = {
bucket: resolvedParams.bucket,
acl: resolvedParams.acl,
cacheControl: resolvedParams.cacheControl,
contentDisposition: resolvedParams.contentDisposition,
contentType: resolvedParams.contentType,
key: resolvedParams.key,
metadata: resolvedParams.metadata,
serverSideEncryption: resolvedParams.serverSideEncryption,
serverSideEncryptionKMSKeyId: resolvedParams.serverSideEncryptionKMSKeyId,
serverSideEncryptionCustomerAlgorithm: resolvedParams.serverSideEncryptionCustomerAlgorithm,
serverSideEncryptionCustomerKey: resolvedParams.serverSideEncryptionCustomerKey,
serverSideEncryptionCustomerKeyMD5: resolvedParams.serverSideEncryptionCustomerKeyMD5,
storageClass: resolvedParams.storageClass,
location: data.Location,
etag: data.ETag
};
this.onUpload(req, this, Object.assign({}, file, fileData));
cb(null, fileData);
});
})
.catch(cb);
}
}
exports.default = S3Storage;
//# sourceMappingURL=index.js.map
{
"name": "@openfin/multer-s3",
"version": "1.0.2",
"version": "2.0.0",
"description": "",

@@ -8,11 +8,17 @@ "main": "build/index.js",

"dependencies": {
"file-type": "^7.2.0",
"kind-of": "^6.0.0"
"@types/p-props": "^1.0.1",
"file-type": "8.0.0",
"kind-of": "6.0.2",
"p-props": "^1.2.0"
},
"devDependencies": {
"@types/express": "^4.0.39",
"@types/multer": "^1.3.5",
"ava": "^0.23.0",
"aws-sdk": "^2.141.0",
"typescript": "^2.5.3"
"@types/express": "4.11.1",
"@types/multer": "1.3.6",
"@types/supertest": "^2.0.4",
"ava": "0.25.0",
"aws-sdk": "2.245.1",
"express": "^4.16.3",
"multer": "^1.3.0",
"supertest": "^3.1.0",
"typescript": "2.8.3"
},

@@ -23,3 +29,3 @@ "scripts": {

"build:watch": "tsc -w",
"prepublish": "npm run build"
"prepublishOnly": "npm run build"
},

@@ -26,0 +32,0 @@ "ava": {

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