🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

@s1seven/nestjs-tools-file-storage

Package Overview
Dependencies
Maintainers
5
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@s1seven/nestjs-tools-file-storage

File storage modules

0.8.0
latest
npm
Version published
Weekly downloads
0
-100%
Maintainers
5
Weekly downloads
 
Created
Source

File-storage

npm

File storage classes for :

  • Node FileSystem
  • Amazon S3

NOTE: release @s1seven/nestjs-tools-file-storage@0.6.2 has some breaking changes as we now use AWS SDK v3:

  • accessKeyId and secretAccessKey should be passed to FileStorageS3Setup as properties of a credentials object.
  • The s3BucketEndpoint property has been removed.
  • In AWS SDK v3, the endpoint property has been replaced by region. For compatibility, we currently extract the region from an endpoint url if it is present and the region property is not, but you should update to region as this may change in future updates.

Installation

$ npm install --save @s1seven/nestjs-tools-file-storage

Example

import { AppConfigService } from '@app/env';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { SymmetricCipher } from '@bigchaindb/wallet-plugins';
import {
  FileStorage,
  FileStorageConfig,
  FileStorageLocal,
  FileStorageLocalSetup,
  FileStorageS3,
  FileStorageS3Config,
  FileStorageS3Setup,
} from '@s1seven/nestjs-tools-file-storage';
import { S3 } from '@aws-sdk/client-s3';
import { Upload } from '@aws-sdk/lib-storage';
import { Request } from 'express';
import { isBase64 } from 'class-validator';
import chalk from 'chalk';
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { join, resolve } from 'path';
import { decodeBase64 } from 'tweetnacl-util';

function fileStorageConfigFactory(setup: FileStorageLocalSetup & { secretKeyPath: string }): FileStorageConfig {
  const { maxPayloadSize, storagePath, secretKeyPath } = setup;
  const filePath = (options: { req?: Request; fileName: string }): string => {
    const { fileName } = options;
    if (!existsSync(storagePath)) {
      mkdirSync(storagePath, { recursive: true });
    }
    const path = resolve(join(storagePath, fileName));
    if (!existsSync(path) && fileName === secretKeyPath) {
      writeFileSync(path, '');
    }
    return path;
  };
  const limits = { fileSize: maxPayloadSize * 1024 * 1024 };
  return { filePath, limits };
}

function s3StorageConfigFactory(
  setup: FileStoragS3Setup & { secretKeyPath: string },
): FileStorageConfig & FileStorageS3Config {
  const { bucket, maxPayloadSize, credentials, region } = setup;
  const s3 = new S3({
    credentials,
    region,
  });
  const filePath = async (options: { request?: Request; fileName: string }): Promise<string> => {
    const { fileName } = options;
    const fileExists = await s3
      .headObject({ Key: fileName, Bucket: bucket })
      .promise()
      .then(() => true)
      .catch(() => false);
    if (!fileExists && fileName === secretKeyPath) {
      await new Upload({
        client: s3,
        params: { Bucket: bucket, Key: fileName, Body: '' },
      }).done();
    }
    return `${fileName}`;
  };

  const limits = { fileSize: maxPayloadSize * 1024 * 1024 };
  return {
    s3,
    bucket,
    filePath,
    limits,
  };
}

@Injectable()
export class StorageService {
  readonly logger = new Logger(StorageService.name);
  readonly fileStorage: FileStorage;

  constructor(@Inject(ConfigService) private readonly configService: AppConfigService) {
    const environment = this.configService.get<Environment>('NODE_ENV');
    if (!environment || environment === 'development' || environment === 'test') {
      const setup: FileStorageLocalSetup = {
        secretKeyPath: configService.get<string>('SECRET_KEY_PATH'),
        storagePath: configService.get<string>('STORAGE_PATH'),
        maxPayloadSize: configService.get<number>('MAX_PAYLOAD_SIZE'),
      };
      this.fileStorage = new FileStorageLocal(setup, fileStorageConfigFactory);
    } else {
      const setup: FileStorageS3Setup = {
        secretKeyPath: configService.get<string>('SECRET_KEY_PATH'),
        maxPayloadSize: configService.get<number>('MAX_PAYLOAD_SIZE'),
        region: configService.get<string>('S3_REGION'),
        bucket: configService.get<string>('S3_BUCKET'),
        credentials: {
          secretAccessKey: configService.get<string>('S3_SECRET_ACCESS_KEY'),
          accessKeyId: configService.get<string>('S3_ACCESS_KEY_ID'),
        },
      };
      this.fileStorage = new FileStorageS3(setup, s3StorageConfigFactory);
    }
  }

  async getSecret(): Promise<Uint8Array> {
    const secretKey = this.configService.get('SECRET_KEY');
    const secretKeyPath = this.configService.get('SECRET_KEY_PATH');
    const secretBase64 = secretKey
      ? secretKey
      : await this.fileStorage.downloadFile({
          filePath: secretKeyPath,
        });
    if (secretBase64?.length) {
      return decodeBase64(secretBase64.toString());
    }
    return Promise.reject(new Error('Secret file not found'));
  }

  setSecret(secret: string): Promise<void> {
    if (!isBase64(secret)) {
      return Promise.reject(new Error('Secret should be a base64 encoded string'));
    }
    return this.fileStorage.uploadFile({
      filePath: this.configService.get('SECRET_KEY_PATH'),
      content: secret,
    });
  }
}

Troubleshooting

If, after upgrading, you get the following error:

/usr/local/bin/node[57897]: ../src/node_http_parser.cc:517:static void node::(anonymous namespace)::Parser::Execute(const FunctionCallbackInfo<v8::Value> &): Assertion `parser->current_buffer_.IsEmpty()' failed.

You need to update to node v18.6 or higher. This is due to an issue with the node http module. More information can be found here and here.

FAQs

Package last updated on 11 Oct 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts