From 8994c6d4ece9bf7695672436d5111fb87e0626c8 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 05:46:57 +0200 Subject: [PATCH 1/8] ci: add redis service --- .github/workflows/node.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index 7c6892c..13dff6c 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -49,7 +49,7 @@ jobs: services: rabbitmq: - image: rabbitmq:3.12-management-alpine + image: rabbitmq:3.13-management-alpine options: >- --health-cmd "rabbitmq-diagnostics status" --health-interval 10s @@ -58,6 +58,16 @@ jobs: ports: - 5672:5672 + redis: + image: redis:7.4-alpine + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 + steps: - name: Check out repository code uses: actions/checkout@v4 @@ -114,7 +124,7 @@ jobs: S3_REGION: ${{ env.S3_REGION }} GC_BUCKET: ${{ env.GC_BUCKET }} GC_PROJECT_ID: ${{ env.GC_PROJECT_ID }} - run: npx nx affected -t lint,test,build --parallel=3 + run: npx nx affected -t lint,test,build --parallel=2 - name: Upload coverage uses: actions/upload-artifact@v4 From 1cbe974bdcef61ba6a91c99b689fe4b3d7765fbf Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 06:42:30 +0200 Subject: [PATCH 2/8] refactor(nestjs-tools-file-storage): separate base types --- .../src/lib/file-storage.class.ts | 87 ++++++------------- .../src/lib/file-storage.types.ts | 77 ++++++++++++++++ packages/file-storage/src/lib/types.ts | 3 +- 3 files changed, 105 insertions(+), 62 deletions(-) create mode 100644 packages/file-storage/src/lib/file-storage.types.ts diff --git a/packages/file-storage/src/lib/file-storage.class.ts b/packages/file-storage/src/lib/file-storage.class.ts index 8b285ed..859eb65 100644 --- a/packages/file-storage/src/lib/file-storage.class.ts +++ b/packages/file-storage/src/lib/file-storage.class.ts @@ -2,45 +2,24 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import type { Readable } from 'node:stream'; -import { FileStorageWritable, MethodTypes, Request } from './types'; - -export interface FileStorageConfig { - filePath?: (options: { - request?: Request; - fileName: string; - methodType: MethodTypes; - [key: string]: unknown; - }) => string | Promise; - limits?: { fileSize: number }; -} - -export type FileStorageConfigFactory, S extends Record> = ( - setup: S, -) => T & FileStorageConfig; +import { + FileStorageBaseArgs, + FileStorageConfig, + FileStorageDirBaseArgs, + FileStorageDownloadFile, + FileStorageDownloadStream, + FileStorageFileExists, + FileStorageGetFileMeta, + FileStorageMoveFile, + FileStorageReadDir, + FileStorageTransformPath, + FileStorageUploadFile, + FileStorageUploadStream, +} from './file-storage.types'; +import { FileStorageWritable } from './types'; const defaultErrorMessage = 'Funtion must be implemented'; -export interface FileStorageBaseArgs { - filePath: string; - request?: Request; -} - -export interface FileStorageDirBaseArgs { - dirPath: string; - request?: Request; -} - -export interface FileStorageReadDirBaseArgs extends FileStorageDirBaseArgs { - serializer?: (data: T) => R; -} - -export type FileStorageTransformPath = ( - fileName: string, - methodType: MethodTypes, - request?: Request, - options?: any, -) => string | Promise; - export abstract class FileStorage { readonly config?: FileStorageConfig & Record; @@ -53,45 +32,27 @@ export abstract class FileStorage { throw new Error(defaultErrorMessage); }; - fileExists(args: FileStorageBaseArgs & { options?: string | any }): Promise { + fileExists(args: FileStorageFileExists): Promise { throw new Error(defaultErrorMessage); } - moveFile( - args: FileStorageBaseArgs & { - newFilePath: string; - options?: string | any; - }, - ): Promise { + moveFile(args: FileStorageMoveFile): Promise { throw new Error(defaultErrorMessage); } - uploadFile( - args: FileStorageBaseArgs & { - content: Buffer | Uint8Array | string; - options?: string | any; - }, - ): Promise { + uploadFile(args: FileStorageUploadFile): Promise { throw new Error(defaultErrorMessage); } - uploadStream( - args: FileStorageBaseArgs & { - options?: string | any; - }, - ): Promise { + uploadStream(args: FileStorageUploadStream): Promise { throw new Error(defaultErrorMessage); } - downloadFile(args: FileStorageBaseArgs & { options?: string | any }): Promise { + downloadFile(args: FileStorageDownloadFile): Promise { throw new Error(defaultErrorMessage); } - downloadStream( - args: FileStorageBaseArgs & { - options?: string | any; - }, - ): Promise { + downloadStream(args: FileStorageDownloadStream): Promise { throw new Error(defaultErrorMessage); } @@ -99,6 +60,10 @@ export abstract class FileStorage { throw new Error(defaultErrorMessage); } + getFileMeta(args: FileStorageGetFileMeta): Promise { + throw new Error(defaultErrorMessage); + } + // TODO: // createDir(args: FileStorageDirBaseArgs): Promise { // throw new Error(defaultErrorMessage); @@ -108,7 +73,7 @@ export abstract class FileStorage { throw new Error(defaultErrorMessage); } - readDir(args: FileStorageReadDirBaseArgs): Promise { + readDir(args: FileStorageReadDir): Promise { throw new Error(defaultErrorMessage); } } diff --git a/packages/file-storage/src/lib/file-storage.types.ts b/packages/file-storage/src/lib/file-storage.types.ts new file mode 100644 index 0000000..f25fc31 --- /dev/null +++ b/packages/file-storage/src/lib/file-storage.types.ts @@ -0,0 +1,77 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { MethodTypes, Request } from './types'; + +export interface FileStorageConfig { + filePath?: (options: { + request?: Request; + fileName: string; + methodType: MethodTypes; + [key: string]: unknown; + }) => string | Promise; + limits?: { fileSize: number }; +} + +export type FileStorageConfigFactory, S extends Record> = ( + setup: S, +) => T & FileStorageConfig; + +export type FileStorageTransformPath = ( + fileName: string, + methodType: MethodTypes, + request?: Request, + options?: any, +) => string | Promise; + +export interface FileStorageBaseArgs { + filePath: string; + request?: Request; +} + +type Options = string | any; + +export interface FileStorageFileExists extends FileStorageBaseArgs { + options?: Options; +} + +export interface FileStorageMoveFile extends FileStorageBaseArgs { + newFilePath: string; + options?: Options; +} + +export interface FileStorageUploadFile extends FileStorageBaseArgs { + content: Buffer | Uint8Array | string; + options?: Options; +} + +export interface FileStorageUploadStream extends FileStorageBaseArgs { + options?: Options; +} + +export interface FileStorageDownloadFile extends FileStorageBaseArgs { + options?: Options; +} + +export interface FileStorageDownloadStream extends FileStorageBaseArgs { + options?: Options; +} + +export interface FileStorageDeleteFile extends FileStorageBaseArgs { + options?: Options; +} + +export interface FileStorageGetFileMeta extends FileStorageBaseArgs { + options?: Options; +} + +export interface FileStorageDirBaseArgs { + dirPath: string; + request?: Request; +} + +export interface FileStorageReadDir extends FileStorageDirBaseArgs { + serializer?: (data: T) => R; +} + +export interface FileStorageDeleteDir extends FileStorageDirBaseArgs { + options?: Options; +} diff --git a/packages/file-storage/src/lib/types.ts b/packages/file-storage/src/lib/types.ts index 1eb99a4..d675152 100644 --- a/packages/file-storage/src/lib/types.ts +++ b/packages/file-storage/src/lib/types.ts @@ -1,7 +1,8 @@ import type { InjectionToken, ModuleMetadata } from '@nestjs/common'; import type { Stream } from 'node:stream'; -import type { FileStorage, FileStorageConfigFactory } from './file-storage.class'; +import type { FileStorage } from './file-storage.class'; +import type { FileStorageConfigFactory } from './file-storage.types'; import type { FileStorageLocalSetup } from './file-storage-fs.types'; import type { FileStorageGoogleConfig, FileStorageGoogleSetup } from './file-storage-google.types'; import type { FileStorageS3Config, FileStorageS3Setup } from './file-storage-s3.types'; From f7266eba93f4812311c3d4b335732f450556d4d6 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 06:44:48 +0200 Subject: [PATCH 3/8] feat(nestjs-tools-file-storage): implement `getFileMeta` methods --- .../src/lib/file-storage-fs.class.ts | 38 +++++++++++---- .../src/lib/file-storage-fs.types.ts | 47 ++++++++++++++----- .../src/lib/file-storage-google.class.ts | 13 ++++- .../src/lib/file-storage-google.types.ts | 46 +++++++++++++----- .../src/lib/file-storage-s3.class.ts | 12 ++++- .../src/lib/file-storage-s3.types.ts | 40 +++++++++++----- 6 files changed, 150 insertions(+), 46 deletions(-) diff --git a/packages/file-storage/src/lib/file-storage-fs.class.ts b/packages/file-storage/src/lib/file-storage-fs.class.ts index c89ce32..83dd45f 100644 --- a/packages/file-storage/src/lib/file-storage-fs.class.ts +++ b/packages/file-storage/src/lib/file-storage-fs.class.ts @@ -1,19 +1,25 @@ -import { createReadStream, createWriteStream, Dirent, ObjectEncodingOptions, stat, unlink } from 'node:fs'; -import { access, mkdir, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises'; +import { + BigIntStats, + createReadStream, + createWriteStream, + Dirent, + ObjectEncodingOptions, + stat, + Stats, + unlink, +} from 'node:fs'; +import { access, mkdir, readdir, readFile, rename, rm, stat as statPromise, writeFile } from 'node:fs/promises'; import { normalize, resolve as resolvePath, sep } from 'node:path'; import { finished, Readable } from 'node:stream'; -import type { - FileStorage, - FileStorageBaseArgs, - FileStorageConfig, - FileStorageConfigFactory, -} from './file-storage.class'; +import type { FileStorage } from './file-storage.class'; +import type { FileStorageBaseArgs, FileStorageConfig, FileStorageConfigFactory } from './file-storage.types'; import type { FileStorageLocalDeleteDir, FileStorageLocalDownloadFile, FileStorageLocalDownloadStream, FileStorageLocalFileExists, + FileStorageLocalGetFileMeta, FileStorageLocalReadDir, FileStorageLocalSetup, FileStorageLocalUploadFile, @@ -131,6 +137,22 @@ export class FileStorageLocal implements FileStorage { ); } + async getFileMeta( + args: FileStorageLocalGetFileMeta & { + options: { bigint: false | undefined }; + }, + ): Promise; + async getFileMeta( + args: FileStorageLocalGetFileMeta & { + options: { bigint: true }; + }, + ): Promise; + async getFileMeta(args: FileStorageLocalGetFileMeta): Promise { + const { filePath, options, request } = args; + const fileName = await this.transformFilePath(filePath, MethodTypes.READ, request); + return statPromise(fileName, options); + } + async deleteDir(args: FileStorageLocalDeleteDir): Promise { const { options = { recursive: true, force: true }, dirPath, request } = args; const dirName = await this.transformFilePath(dirPath, MethodTypes.DELETE, request); diff --git a/packages/file-storage/src/lib/file-storage-fs.types.ts b/packages/file-storage/src/lib/file-storage-fs.types.ts index b395d1c..e1b5f1d 100644 --- a/packages/file-storage/src/lib/file-storage-fs.types.ts +++ b/packages/file-storage/src/lib/file-storage-fs.types.ts @@ -1,6 +1,25 @@ -import type { BigIntOptions, Dirent, ObjectEncodingOptions, StatOptions, WriteFileOptions } from 'node:fs'; +import type { + BigIntOptions, + BigIntStats, + Dirent, + ObjectEncodingOptions, + StatOptions, + Stats, + WriteFileOptions, +} from 'node:fs'; -import type { FileStorageBaseArgs, FileStorageDirBaseArgs, FileStorageReadDirBaseArgs } from './file-storage.class'; +import type { + FileStorageBaseArgs, + FileStorageDeleteDir, + FileStorageDownloadFile, + FileStorageDownloadStream, + FileStorageFileExists, + FileStorageGetFileMeta, + FileStorageMoveFile, + FileStorageReadDir, + FileStorageUploadFile, + FileStorageUploadStream, +} from './file-storage.types'; export type StreamOptions = { flags?: string; @@ -20,24 +39,23 @@ export type FileStorageLocalSetup = { [key: string]: unknown; }; -export interface FileStorageLocalFileExists extends FileStorageBaseArgs { +export interface FileStorageLocalFileExists extends FileStorageFileExists { options?: StatOptions | BigIntOptions; } -export interface FileStorageLocalMoveFile extends FileStorageBaseArgs { +export interface FileStorageLocalMoveFile extends FileStorageMoveFile { newFilePath: string; } -export interface FileStorageLocalUploadFile extends FileStorageBaseArgs { - content: string | Uint8Array | Buffer; +export interface FileStorageLocalUploadFile extends FileStorageUploadFile { options?: WriteFileOptions; } -export interface FileStorageLocalUploadStream extends FileStorageBaseArgs { +export interface FileStorageLocalUploadStream extends FileStorageUploadStream { options?: BufferEncoding | StreamOptions; } -export interface FileStorageLocalDownloadFile extends FileStorageBaseArgs { +export interface FileStorageLocalDownloadFile extends FileStorageDownloadFile { options: | { encoding?: null; flag?: string } | { encoding: BufferEncoding; flag?: string } @@ -48,16 +66,23 @@ export interface FileStorageLocalDownloadFile extends FileStorageBaseArgs { // options?: Record | BufferEncoding | null; } -export interface FileStorageLocalDownloadStream extends FileStorageBaseArgs { +export interface FileStorageLocalDownloadStream extends FileStorageDownloadStream { options?: BufferEncoding | StreamOptions; } -export interface FileStorageLocalDeleteDir extends FileStorageDirBaseArgs { +export type FileStorageLocalDeleteFile = FileStorageBaseArgs; + +export interface FileStorageLocalGetFileMeta extends FileStorageGetFileMeta { + options?: { bigint?: boolean | undefined }; +} +export type FileStorageLocalGetFileMetaOutput = Stats | BigIntStats; + +export interface FileStorageLocalDeleteDir extends FileStorageDeleteDir { options?: { recursive?: boolean; force?: boolean }; } export type ReadDirOutput = string[] | Buffer[] | Dirent[]; -export interface FileStorageLocalReadDir extends FileStorageReadDirBaseArgs { +export interface FileStorageLocalReadDir extends FileStorageReadDir { options?: { encoding: BufferEncoding; withFileTypes?: boolean; recursive?: boolean } | BufferEncoding; } diff --git a/packages/file-storage/src/lib/file-storage-google.class.ts b/packages/file-storage/src/lib/file-storage-google.class.ts index 2d634f0..c721aec 100644 --- a/packages/file-storage/src/lib/file-storage-google.class.ts +++ b/packages/file-storage/src/lib/file-storage-google.class.ts @@ -2,7 +2,8 @@ import type { File, GetFilesResponse } from '@google-cloud/storage'; import { Injectable } from '@nestjs/common'; import { finished, type Readable } from 'node:stream'; -import type { FileStorage, FileStorageConfig, FileStorageConfigFactory } from './file-storage.class'; +import type { FileStorage } from './file-storage.class'; +import type { FileStorageConfig, FileStorageConfigFactory } from './file-storage.types'; import type { FileStorageGoogleConfig, FileStorageGoogleDeleteDir, @@ -10,6 +11,8 @@ import type { FileStorageGoogleDownloadFile, FileStorageGoogleDownloadStream, FileStorageGoogleFileExists, + FileStorageGoogleGetFileMeta, + FileStorageGoogleGetFileMetaOutput, FileStorageGoogleMoveFile, FileStorageGoogleReadDir, FileStorageGoogleSetup, @@ -125,6 +128,14 @@ export class FileStorageGoogle implements FileStorage { } } + async getFileMeta(args: FileStorageGoogleGetFileMeta): Promise { + const { storage, bucket } = this.config; + const { options = {}, request } = args; + const filePath = await this.transformFilePath(args.filePath, MethodTypes.READ, request, options); + const [metadata] = await storage.bucket(bucket).file(filePath).getMetadata(options); + return metadata; + } + async deleteDir(args: FileStorageGoogleDeleteDir): Promise { const { storage, bucket } = this.config; const { options = {}, request } = args; diff --git a/packages/file-storage/src/lib/file-storage-google.types.ts b/packages/file-storage/src/lib/file-storage-google.types.ts index b1c1b79..f78afb6 100644 --- a/packages/file-storage/src/lib/file-storage-google.types.ts +++ b/packages/file-storage/src/lib/file-storage-google.types.ts @@ -3,6 +3,7 @@ import type { CreateWriteStreamOptions, DeleteFilesOptions, DownloadOptions, + FileMetadata, FileOptions, GetFilesOptions, GetFilesResponse, @@ -10,9 +11,24 @@ import type { SaveOptions, Storage, } from '@google-cloud/storage'; -import type { DeleteOptions, ExistsOptions } from '@google-cloud/storage/build/cjs/src/nodejs-common/service-object'; +import type { + DeleteOptions, + ExistsOptions, + GetMetadataOptions, +} from '@google-cloud/storage/build/cjs/src/nodejs-common/service-object'; -import type { FileStorageBaseArgs, FileStorageDirBaseArgs, FileStorageReadDirBaseArgs } from './file-storage.class'; +import type { + FileStorageDeleteDir, + FileStorageDeleteFile, + FileStorageDownloadFile, + FileStorageDownloadStream, + FileStorageFileExists, + FileStorageGetFileMeta, + FileStorageMoveFile, + FileStorageReadDir, + FileStorageUploadFile, + FileStorageUploadStream, +} from './file-storage.types'; // TODO: add authentication options export interface FileStorageGoogleSetup { @@ -29,40 +45,44 @@ export interface FileStorageGoogleConfig { [key: string]: any; } -export interface FileStorageGoogleFileExists extends FileStorageBaseArgs { +export interface FileStorageGoogleFileExists extends FileStorageFileExists { options?: ExistsOptions & FileOptions; } -export interface FileStorageGoogleMoveFile extends FileStorageBaseArgs { - newFilePath: string; +export interface FileStorageGoogleMoveFile extends FileStorageMoveFile { options?: FileOptions & MoveOptions; } -export interface FileStorageGoogleUploadFile extends FileStorageBaseArgs { - content: string | Uint8Array | Buffer; +export interface FileStorageGoogleUploadFile extends FileStorageUploadFile { options?: FileOptions & SaveOptions; } -export interface FileStorageGoogleUploadStream extends FileStorageBaseArgs { +export interface FileStorageGoogleUploadStream extends FileStorageUploadStream { options?: CreateWriteStreamOptions & FileOptions; } -export interface FileStorageGoogleDownloadFile extends FileStorageBaseArgs { +export interface FileStorageGoogleDownloadFile extends FileStorageDownloadFile { options?: DownloadOptions & FileOptions; } -export interface FileStorageGoogleDownloadStream extends FileStorageBaseArgs { +export interface FileStorageGoogleDownloadStream extends FileStorageDownloadStream { options?: CreateReadStreamOptions & FileOptions; } -export interface FileStorageGoogleDeleteFile extends FileStorageBaseArgs { +export interface FileStorageGoogleDeleteFile extends FileStorageDeleteFile { options?: DeleteOptions & FileOptions; } -export interface FileStorageGoogleDeleteDir extends FileStorageDirBaseArgs { +export interface FileStorageGoogleGetFileMeta extends FileStorageGetFileMeta { + options?: GetMetadataOptions & FileOptions; +} + +export type FileStorageGoogleGetFileMetaOutput = FileMetadata; + +export interface FileStorageGoogleDeleteDir extends FileStorageDeleteDir { options?: Omit & FileOptions; } -export interface FileStorageGoogleReadDir extends FileStorageReadDirBaseArgs { +export interface FileStorageGoogleReadDir extends FileStorageReadDir { options?: Omit & FileOptions; } diff --git a/packages/file-storage/src/lib/file-storage-s3.class.ts b/packages/file-storage/src/lib/file-storage-s3.class.ts index 0beda3d..403b7f7 100644 --- a/packages/file-storage/src/lib/file-storage-s3.class.ts +++ b/packages/file-storage/src/lib/file-storage-s3.class.ts @@ -2,7 +2,8 @@ import type { DeleteObjectsCommandInput, ListObjectsCommandInput, ListObjectsCom import type { Options as UploadOptions } from '@aws-sdk/lib-storage'; import { PassThrough, Readable } from 'node:stream'; -import type { FileStorage, FileStorageConfig, FileStorageConfigFactory } from './file-storage.class'; +import type { FileStorage } from './file-storage.class'; +import type { FileStorageConfig, FileStorageConfigFactory } from './file-storage.types'; import type { FileStorageS3Config, FileStorageS3DeleteDir, @@ -10,6 +11,8 @@ import type { FileStorageS3DownloadFile, FileStorageS3DownloadStream, FileStorageS3FileExists, + FileStorageS3GetFileMeta, + FileStorageS3GetFileMetaOutput, FileStorageS3MoveFile, FileStorageS3ReadDir, FileStorageS3Setup, @@ -166,6 +169,13 @@ export class FileStorageS3 implements FileStorage { return true; } + async getFileMeta(args: FileStorageS3GetFileMeta): Promise { + const { filePath, options = {}, request } = args; + const Key = await this.transformFilePath(filePath, MethodTypes.READ, request, options); + const { s3, bucket: Bucket } = this.config; + return s3.headObject({ ...options, Bucket, Key }); + } + async deleteDir(args: FileStorageS3DeleteDir): Promise { const { dirPath, options = {}, request } = args; const { s3, bucket: Bucket } = this.config; diff --git a/packages/file-storage/src/lib/file-storage-s3.types.ts b/packages/file-storage/src/lib/file-storage-s3.types.ts index 0adddc5..a1d188b 100644 --- a/packages/file-storage/src/lib/file-storage-s3.types.ts +++ b/packages/file-storage/src/lib/file-storage-s3.types.ts @@ -3,13 +3,25 @@ import type { DeleteObjectsCommandInput, GetObjectCommandInput, HeadObjectCommandInput, + HeadObjectCommandOutput, ListObjectsCommandInput, ListObjectsCommandOutput, PutObjectCommandInput, S3, } from '@aws-sdk/client-s3'; -import type { FileStorageBaseArgs, FileStorageDirBaseArgs, FileStorageReadDirBaseArgs } from './file-storage.class'; +import type { + FileStorageDeleteDir, + FileStorageDeleteFile, + FileStorageDownloadFile, + FileStorageDownloadStream, + FileStorageFileExists, + FileStorageGetFileMeta, + FileStorageMoveFile, + FileStorageReadDir, + FileStorageUploadFile, + FileStorageUploadStream, +} from './file-storage.types'; /** * Either region or endpoint must be provided @@ -33,40 +45,44 @@ export interface FileStorageS3Config { [key: string]: any; } -export interface FileStorageS3FileExists extends FileStorageBaseArgs { +export interface FileStorageS3FileExists extends FileStorageFileExists { options?: Omit; } -export interface FileStorageS3MoveFile extends FileStorageBaseArgs { - newFilePath: string; +export interface FileStorageS3MoveFile extends FileStorageMoveFile { options?: Omit; } -export interface FileStorageS3UploadFile extends FileStorageBaseArgs { - content: string | Uint8Array | Buffer; +export interface FileStorageS3UploadFile extends FileStorageUploadFile { options?: Omit; } -export interface FileStorageS3UploadStream extends FileStorageBaseArgs { +export interface FileStorageS3UploadStream extends FileStorageUploadStream { options?: Omit; } -export interface FileStorageS3DownloadFile extends FileStorageBaseArgs { +export interface FileStorageS3DownloadFile extends FileStorageDownloadFile { options?: Omit; } -export interface FileStorageS3DownloadStream extends FileStorageBaseArgs { +export interface FileStorageS3DownloadStream extends FileStorageDownloadStream { options?: Omit; } -export interface FileStorageS3DeleteFile extends FileStorageBaseArgs { +export interface FileStorageS3DeleteFile extends FileStorageDeleteFile { options?: Omit; } -export interface FileStorageS3DeleteDir extends FileStorageDirBaseArgs { +export interface FileStorageS3GetFileMeta extends FileStorageGetFileMeta { + options?: Omit; +} + +export type FileStorageS3GetFileMetaOutput = HeadObjectCommandOutput; + +export interface FileStorageS3DeleteDir extends FileStorageDeleteDir { options?: Omit; } -export interface FileStorageS3ReadDir extends FileStorageReadDirBaseArgs { +export interface FileStorageS3ReadDir extends FileStorageReadDir { options?: Omit; } From 5ff2500ba338481f19a71d8690b7965da64e6628 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 06:45:15 +0200 Subject: [PATCH 4/8] feat(nestjs-tools-file-storage): update FileStorageService --- .../src/lib/file-storage.service.ts | 146 +++++++++++++++--- 1 file changed, 124 insertions(+), 22 deletions(-) diff --git a/packages/file-storage/src/lib/file-storage.service.ts b/packages/file-storage/src/lib/file-storage.service.ts index 807322b..f0b2072 100644 --- a/packages/file-storage/src/lib/file-storage.service.ts +++ b/packages/file-storage/src/lib/file-storage.service.ts @@ -1,11 +1,27 @@ import { Injectable } from '@nestjs/common'; import type { Readable } from 'node:stream'; -import type { FileStorage, FileStorageBaseArgs, FileStorageDirBaseArgs } from './file-storage.class'; +import type { FileStorage } from './file-storage.class'; +import { + FileStorageDeleteDir, + FileStorageDeleteFile, + FileStorageDownloadFile, + FileStorageDownloadStream, + FileStorageFileExists, + FileStorageGetFileMeta, + FileStorageMoveFile, + FileStorageReadDir, + FileStorageUploadFile, + FileStorageUploadStream, +} from './file-storage.types'; import type { + FileStorageLocalDeleteDir, + FileStorageLocalDeleteFile, FileStorageLocalDownloadFile, FileStorageLocalDownloadStream, FileStorageLocalFileExists, + FileStorageLocalGetFileMeta, + FileStorageLocalGetFileMetaOutput, FileStorageLocalMoveFile, FileStorageLocalReadDir, FileStorageLocalUploadFile, @@ -17,6 +33,8 @@ import type { FileStorageGoogleDownloadFile, FileStorageGoogleDownloadStream, FileStorageGoogleFileExists, + FileStorageGoogleGetFileMeta, + FileStorageGoogleGetFileMetaOutput, FileStorageGoogleMoveFile, FileStorageGoogleReadDir, FileStorageGoogleUploadFile, @@ -28,61 +46,145 @@ import type { FileStorageS3DownloadFile, FileStorageS3DownloadStream, FileStorageS3FileExists, + FileStorageS3GetFileMeta, + FileStorageS3GetFileMetaOutput, FileStorageS3MoveFile, FileStorageS3ReadDir, FileStorageS3UploadFile, FileStorageS3UploadStream, } from './file-storage-s3.types'; import { InjectFileStorageStrategy } from './inject-file-storage.decorator'; -import type { FileStorageWritable } from './types'; +import type { FileStorageWritable, StorageType } from './types'; + +type FileExistsArgs = S extends StorageType.S3 + ? FileStorageS3FileExists + : S extends StorageType.GC + ? FileStorageGoogleFileExists + : S extends StorageType.FS + ? FileStorageLocalFileExists + : FileStorageFileExists; + +type MoveFileArgs = S extends StorageType.S3 + ? FileStorageS3MoveFile + : S extends StorageType.GC + ? FileStorageGoogleMoveFile + : S extends StorageType.FS + ? FileStorageLocalMoveFile + : FileStorageMoveFile; + +type UploadFileArgs = S extends StorageType.S3 + ? FileStorageS3UploadFile + : S extends StorageType.GC + ? FileStorageGoogleUploadFile + : S extends StorageType.FS + ? FileStorageLocalUploadFile + : FileStorageUploadFile; + +type UploadStreamArgs = S extends StorageType.S3 + ? FileStorageS3UploadStream + : S extends StorageType.GC + ? FileStorageGoogleUploadStream + : S extends StorageType.FS + ? FileStorageLocalUploadStream + : FileStorageUploadStream; + +type DownloadFileArgs = S extends StorageType.S3 + ? FileStorageS3DownloadFile + : S extends StorageType.GC + ? FileStorageGoogleDownloadFile + : S extends StorageType.FS + ? FileStorageLocalDownloadFile + : FileStorageDownloadFile; + +type DownloadStreamArgs = S extends StorageType.S3 + ? FileStorageS3DownloadStream + : S extends StorageType.GC + ? FileStorageGoogleDownloadStream + : S extends StorageType.FS + ? FileStorageLocalDownloadStream + : FileStorageDownloadStream; + +type DeleteFileArgs = S extends StorageType.S3 + ? FileStorageS3DeleteFile + : S extends StorageType.GC + ? FileStorageGoogleDeleteFile + : S extends StorageType.FS + ? FileStorageLocalDeleteFile + : FileStorageDeleteFile; + +type GetFileMetaArgs = S extends StorageType.S3 + ? FileStorageS3GetFileMeta + : S extends StorageType.GC + ? FileStorageGoogleGetFileMeta + : S extends StorageType.FS + ? FileStorageLocalGetFileMeta + : FileStorageGetFileMeta; + +type GetFileMetaResult = S extends StorageType.S3 + ? FileStorageS3GetFileMetaOutput + : S extends StorageType.GC + ? FileStorageGoogleGetFileMetaOutput + : S extends StorageType.FS + ? FileStorageLocalGetFileMetaOutput + : object; + +type ReadDirArgs = S extends StorageType.S3 + ? FileStorageS3ReadDir + : S extends StorageType.GC + ? FileStorageGoogleReadDir + : S extends StorageType.FS + ? FileStorageLocalReadDir + : FileStorageReadDir; + +type DeleteDirArgs = S extends StorageType.S3 + ? FileStorageS3DeleteDir + : S extends StorageType.GC + ? FileStorageGoogleDeleteDir + : S extends StorageType.FS + ? FileStorageLocalDeleteDir + : FileStorageDeleteDir; @Injectable() -export class FileStorageService implements Omit { +export class FileStorageService implements Omit { constructor(@InjectFileStorageStrategy() private readonly fileStorage: FileStorage) {} - fileExists( - args: FileStorageLocalFileExists | FileStorageS3FileExists | FileStorageGoogleFileExists, - ): Promise { + fileExists(args: FileExistsArgs): Promise { return this.fileStorage.fileExists(args); } - moveFile(args: FileStorageLocalMoveFile | FileStorageS3MoveFile | FileStorageGoogleMoveFile): Promise { + moveFile(args: MoveFileArgs): Promise { return this.fileStorage.moveFile(args); } - uploadFile(args: FileStorageLocalUploadFile | FileStorageS3UploadFile | FileStorageGoogleUploadFile): Promise { + uploadFile(args: UploadFileArgs): Promise { return this.fileStorage.uploadFile(args); } - uploadStream( - args: FileStorageLocalUploadStream | FileStorageS3UploadStream | FileStorageGoogleUploadStream, - ): Promise { + uploadStream(args: UploadStreamArgs): Promise { return this.fileStorage.uploadStream(args); } - downloadFile( - args: FileStorageLocalDownloadFile | FileStorageS3DownloadFile | FileStorageGoogleDownloadFile, - ): Promise { + downloadFile(args: DownloadFileArgs): Promise { return this.fileStorage.downloadFile(args); } - downloadStream( - args: FileStorageLocalDownloadStream | FileStorageS3DownloadStream | FileStorageGoogleDownloadStream, - ): Promise { + downloadStream(args: DownloadStreamArgs): Promise { return this.fileStorage.downloadStream(args); } - deleteFile(args: FileStorageBaseArgs | FileStorageS3DeleteFile | FileStorageGoogleDeleteFile): Promise { + deleteFile(args: DeleteFileArgs): Promise { return this.fileStorage.deleteFile(args); } - readDir( - args: FileStorageLocalReadDir | FileStorageS3ReadDir | FileStorageGoogleReadDir, - ): Promise { + getFileMeta(args: GetFileMetaArgs): Promise> { + return this.fileStorage.getFileMeta(args); + } + + readDir(args: ReadDirArgs): Promise { return this.fileStorage.readDir(args); } - deleteDir(args: FileStorageDirBaseArgs | FileStorageS3DeleteDir | FileStorageGoogleDeleteDir): Promise { + deleteDir(args: DeleteDirArgs): Promise { return this.fileStorage.deleteDir(args); } } From 56b74175c965632355ee4f149077d0efc57baa75 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 07:07:47 +0200 Subject: [PATCH 5/8] test(nestjs-tools-file-storage): add tests for `getFileMeta` --- .../file-storage/src/lib/file-storage-fs.types.ts | 3 +-- .../file-storage/src/lib/file-storage.service.ts | 9 +++++++-- packages/file-storage/test/file-storage-cases.ts | 8 ++++---- packages/file-storage/test/file-storage-fs.spec.ts | 12 ++++++++++-- .../file-storage/test/file-storage-google.spec.ts | 12 ++++++++++-- packages/file-storage/test/file-storage-s3.spec.ts | 12 ++++++++++-- 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/packages/file-storage/src/lib/file-storage-fs.types.ts b/packages/file-storage/src/lib/file-storage-fs.types.ts index e1b5f1d..6f028fc 100644 --- a/packages/file-storage/src/lib/file-storage-fs.types.ts +++ b/packages/file-storage/src/lib/file-storage-fs.types.ts @@ -56,14 +56,13 @@ export interface FileStorageLocalUploadStream extends FileStorageUploadStream { } export interface FileStorageLocalDownloadFile extends FileStorageDownloadFile { - options: + options?: | { encoding?: null; flag?: string } | { encoding: BufferEncoding; flag?: string } | BufferEncoding | (ObjectEncodingOptions & { flag?: string }) | undefined | null; - // options?: Record | BufferEncoding | null; } export interface FileStorageLocalDownloadStream extends FileStorageDownloadStream { diff --git a/packages/file-storage/src/lib/file-storage.service.ts b/packages/file-storage/src/lib/file-storage.service.ts index f0b2072..d946cb1 100644 --- a/packages/file-storage/src/lib/file-storage.service.ts +++ b/packages/file-storage/src/lib/file-storage.service.ts @@ -54,7 +54,7 @@ import type { FileStorageS3UploadStream, } from './file-storage-s3.types'; import { InjectFileStorageStrategy } from './inject-file-storage.decorator'; -import type { FileStorageWritable, StorageType } from './types'; +import type { FileStorageWritable, MethodTypes, StorageType } from './types'; type FileExistsArgs = S extends StorageType.S3 ? FileStorageS3FileExists @@ -145,9 +145,14 @@ type DeleteDirArgs = S extends StorageType.S3 : FileStorageDeleteDir; @Injectable() -export class FileStorageService implements Omit { +export class FileStorageService implements FileStorage { constructor(@InjectFileStorageStrategy() private readonly fileStorage: FileStorage) {} + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transformFilePath(fileName: string, methodType: MethodTypes, request?: any, options?: any): string | Promise { + return this.fileStorage.transformFilePath(fileName, methodType, request, options); + } + fileExists(args: FileExistsArgs): Promise { return this.fileStorage.fileExists(args); } diff --git a/packages/file-storage/test/file-storage-cases.ts b/packages/file-storage/test/file-storage-cases.ts index a10a66e..0203c73 100644 --- a/packages/file-storage/test/file-storage-cases.ts +++ b/packages/file-storage/test/file-storage-cases.ts @@ -3,7 +3,7 @@ import { randomUUID } from 'node:crypto'; import { resolve } from 'node:path'; import { setTimeout } from 'node:timers/promises'; -import { FileStorage, StorageType } from '../src'; +import { FileStorageService, StorageType } from '../src'; dotenv.config({ path: resolve(__dirname, '../.env.test') }); @@ -99,7 +99,7 @@ export async function retry( throw new Error('Max retries exceeded'); } -export function fileExists(storage: FileStorage, filePath: string, exists = true): Promise { +export function fileExists(storage: FileStorageService, filePath: string, exists = true): Promise { return retry( () => storage.fileExists({ filePath }), (result) => result === exists, @@ -107,7 +107,7 @@ export function fileExists(storage: FileStorage, filePath: string, exists = true ); } -export function readDir(storage: FileStorage, dirPath: string, exists = true): Promise { +export function readDir(storage: FileStorageService, dirPath: string, exists = true): Promise { return retry( () => storage.readDir({ dirPath }), (result) => (result as string[]).length > 0 === exists, @@ -122,7 +122,7 @@ export const delay = async (ms = 100) => { }; export const createDummyFile = async ( - fileStorage: FileStorage, + fileStorage: FileStorageService, options: { filePath?: string; content?: string; deleteAfter?: boolean } = {}, ): Promise< AsyncDisposable & { diff --git a/packages/file-storage/test/file-storage-fs.spec.ts b/packages/file-storage/test/file-storage-fs.spec.ts index 3c68dc5..329b96e 100644 --- a/packages/file-storage/test/file-storage-fs.spec.ts +++ b/packages/file-storage/test/file-storage-fs.spec.ts @@ -6,14 +6,14 @@ import { mkdir, rm } from 'node:fs/promises'; import { once, Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; -import { FileStorage, FileStorageModule } from '../src'; +import { FileStorageModule, FileStorageService, StorageType } from '../src'; import { FILE_STORAGE_STRATEGY_TOKEN } from '../src/lib/constants'; import { createDummyFile, fsStoragePath, testMap } from './file-storage-cases'; const { description, storageType, options } = testMap[0]; describe(description, () => { - let fileStorage: FileStorage; + let fileStorage: FileStorageService; beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -137,6 +137,14 @@ describe(description, () => { } }); + it('getFileMeta returns file metadata', async () => { + await using file = await createDummyFile(fileStorage); + // + const meta = await fileStorage.getFileMeta({ filePath: file.filePath }); + // + expect(meta.size).toBe(file.content.length); + }); + it('readDir returns an array of files and folders in a directory', async () => { const dirPath = ''; const filePath = randomUUID(); diff --git a/packages/file-storage/test/file-storage-google.spec.ts b/packages/file-storage/test/file-storage-google.spec.ts index 3f75370..33f0a8f 100644 --- a/packages/file-storage/test/file-storage-google.spec.ts +++ b/packages/file-storage/test/file-storage-google.spec.ts @@ -5,14 +5,14 @@ import { randomBytes, randomUUID } from 'node:crypto'; import { once, Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; -import { FileStorage, FileStorageModule } from '../src'; +import { FileStorageModule, FileStorageService, StorageType } from '../src'; import { FILE_STORAGE_STRATEGY_TOKEN } from '../src/lib/constants'; import { createDummyFile, delay, fileExists, readDir, testMap } from './file-storage-cases'; const { description, storageType, options } = testMap[2]; describe(description, () => { - let fileStorage: FileStorage; + let fileStorage: FileStorageService; beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -133,6 +133,14 @@ describe(description, () => { } }); + it('getFileMeta returns file metadata', async () => { + await using file = await createDummyFile(fileStorage); + // + const meta = await fileStorage.getFileMeta({ filePath: file.filePath }); + // + expect(Number(meta.size)).toEqual(file.content.length); + }); + it('readDir returns an array of files and folders in a directory', async () => { const dirPath = ''; const filePath = randomUUID(); diff --git a/packages/file-storage/test/file-storage-s3.spec.ts b/packages/file-storage/test/file-storage-s3.spec.ts index a09ba6f..50f4c78 100644 --- a/packages/file-storage/test/file-storage-s3.spec.ts +++ b/packages/file-storage/test/file-storage-s3.spec.ts @@ -5,14 +5,14 @@ import { randomBytes, randomUUID } from 'node:crypto'; import { once, Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; -import { FileStorage, FileStorageModule } from '../src'; +import { FileStorageModule, FileStorageService, StorageType } from '../src'; import { FILE_STORAGE_STRATEGY_TOKEN } from '../src/lib/constants'; import { createDummyFile, delay, fileExists, readDir, testMap } from './file-storage-cases'; const { description, storageType, options } = testMap[1]; describe(description, () => { - let fileStorage: FileStorage; + let fileStorage: FileStorageService; beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -133,6 +133,14 @@ describe(description, () => { } }); + it('getFileMeta returns file metadata', async () => { + await using file = await createDummyFile(fileStorage); + // + const meta = await fileStorage.getFileMeta({ filePath: file.filePath }); + // + expect(meta.ContentLength).toBe(file.content.length); + }); + it('readDir returns an array of files and folders in a directory', async () => { const dirPath = ''; const filePath = randomUUID(); From e78b1c1afe034048cb0182a076c2b812bf197e56 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 07:23:53 +0200 Subject: [PATCH 6/8] fix(nestjs-tools-file-storage): restore GC serializer --- packages/file-storage/src/lib/file-storage-google.class.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/file-storage/src/lib/file-storage-google.class.ts b/packages/file-storage/src/lib/file-storage-google.class.ts index c721aec..96db655 100644 --- a/packages/file-storage/src/lib/file-storage-google.class.ts +++ b/packages/file-storage/src/lib/file-storage-google.class.ts @@ -146,7 +146,7 @@ export class FileStorageGoogle implements FileStorage { // TODO: make default serializer compliant with the other readDir implementations async readDir(args: FileStorageGoogleReadDir): Promise { const defaultSerializer = (res: GetFilesResponse) => { - return res[0].map((file: File) => file.name) as R; + return res[0].map((file: File) => (prefix ? file.name.replace(`${prefix}/`, '') : file.name)) as R; }; const { storage, bucket } = this.config; const { dirPath, request, serializer = defaultSerializer, options = {} } = args; From 1db218384e3fdd37ed3728a3da01e25bbb691b28 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 07:27:03 +0200 Subject: [PATCH 7/8] test(nestjs-tools-file-storage): increase delay --- packages/file-storage/test/file-storage-google.spec.ts | 2 +- packages/file-storage/test/file-storage-s3.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/file-storage/test/file-storage-google.spec.ts b/packages/file-storage/test/file-storage-google.spec.ts index 33f0a8f..da77d5e 100644 --- a/packages/file-storage/test/file-storage-google.spec.ts +++ b/packages/file-storage/test/file-storage-google.spec.ts @@ -148,7 +148,7 @@ describe(description, () => { const content = randomBytes(1024); await fileStorage.uploadFile({ filePath, content }); await fileStorage.uploadFile({ filePath: nestedFilePath, content }); - await delay(1000); + await delay(1500); // const result = await fileStorage.readDir({ dirPath }); // diff --git a/packages/file-storage/test/file-storage-s3.spec.ts b/packages/file-storage/test/file-storage-s3.spec.ts index 50f4c78..4345932 100644 --- a/packages/file-storage/test/file-storage-s3.spec.ts +++ b/packages/file-storage/test/file-storage-s3.spec.ts @@ -148,7 +148,7 @@ describe(description, () => { const content = randomBytes(1024); await fileStorage.uploadFile({ filePath, content }); await fileStorage.uploadFile({ filePath: nestedFilePath, content }); - await delay(1000); + await delay(1500); // const result = await fileStorage.readDir({ dirPath }); // From 65694fea07fce1584c02d9d20c62e1396c486f68 Mon Sep 17 00:00:00 2001 From: getlarge Date: Wed, 7 Aug 2024 07:51:04 +0200 Subject: [PATCH 8/8] test(nestjs-tools-file-storage): solve race conditions --- .github/workflows/node.yml | 1 + packages/file-storage/test/file-storage-cases.ts | 1 + packages/file-storage/test/file-storage-fs.spec.ts | 3 +-- .../file-storage/test/file-storage-google.spec.ts | 11 +++++++---- packages/file-storage/test/file-storage-s3.spec.ts | 11 ++++++++--- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index 13dff6c..7a18de6 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -124,6 +124,7 @@ jobs: S3_REGION: ${{ env.S3_REGION }} GC_BUCKET: ${{ env.GC_BUCKET }} GC_PROJECT_ID: ${{ env.GC_PROJECT_ID }} + PREFIX: ${{ matrix.node-version }} run: npx nx affected -t lint,test,build --parallel=2 - name: Upload coverage diff --git a/packages/file-storage/test/file-storage-cases.ts b/packages/file-storage/test/file-storage-cases.ts index 0203c73..71e290e 100644 --- a/packages/file-storage/test/file-storage-cases.ts +++ b/packages/file-storage/test/file-storage-cases.ts @@ -23,6 +23,7 @@ declare global { GC_BUCKET: string; GC_PROJECT_ID?: string; CI?: string; + PREFIX?: string; } } } diff --git a/packages/file-storage/test/file-storage-fs.spec.ts b/packages/file-storage/test/file-storage-fs.spec.ts index 329b96e..49b0e9b 100644 --- a/packages/file-storage/test/file-storage-fs.spec.ts +++ b/packages/file-storage/test/file-storage-fs.spec.ts @@ -7,7 +7,6 @@ import { once, Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; import { FileStorageModule, FileStorageService, StorageType } from '../src'; -import { FILE_STORAGE_STRATEGY_TOKEN } from '../src/lib/constants'; import { createDummyFile, fsStoragePath, testMap } from './file-storage-cases'; const { description, storageType, options } = testMap[0]; @@ -20,7 +19,7 @@ describe(description, () => { imports: [FileStorageModule.forRoot(storageType, options)], }).compile(); - fileStorage = module.get(FILE_STORAGE_STRATEGY_TOKEN); + fileStorage = module.get(FileStorageService); await mkdir(fsStoragePath, { recursive: true }); }); diff --git a/packages/file-storage/test/file-storage-google.spec.ts b/packages/file-storage/test/file-storage-google.spec.ts index da77d5e..60648e7 100644 --- a/packages/file-storage/test/file-storage-google.spec.ts +++ b/packages/file-storage/test/file-storage-google.spec.ts @@ -6,7 +6,6 @@ import { once, Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; import { FileStorageModule, FileStorageService, StorageType } from '../src'; -import { FILE_STORAGE_STRATEGY_TOKEN } from '../src/lib/constants'; import { createDummyFile, delay, fileExists, readDir, testMap } from './file-storage-cases'; const { description, storageType, options } = testMap[2]; @@ -19,8 +18,12 @@ describe(description, () => { imports: [FileStorageModule.forRoot(storageType, options)], }).compile(); - fileStorage = module.get(FILE_STORAGE_STRATEGY_TOKEN); - + fileStorage = module.get(FileStorageService); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + fileStorage['fileStorage'].config!.filePath = (options: { request?: Request; fileName: string }): string => { + const { fileName } = options; + return process.env.PREFIX ? `${process.env.PREFIX}/${fileName}` : fileName; + }; await fileStorage.deleteDir({ dirPath: '' }); }); @@ -148,7 +151,7 @@ describe(description, () => { const content = randomBytes(1024); await fileStorage.uploadFile({ filePath, content }); await fileStorage.uploadFile({ filePath: nestedFilePath, content }); - await delay(1500); + await delay(500); // const result = await fileStorage.readDir({ dirPath }); // diff --git a/packages/file-storage/test/file-storage-s3.spec.ts b/packages/file-storage/test/file-storage-s3.spec.ts index 4345932..dd124f5 100644 --- a/packages/file-storage/test/file-storage-s3.spec.ts +++ b/packages/file-storage/test/file-storage-s3.spec.ts @@ -6,7 +6,6 @@ import { once, Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; import { FileStorageModule, FileStorageService, StorageType } from '../src'; -import { FILE_STORAGE_STRATEGY_TOKEN } from '../src/lib/constants'; import { createDummyFile, delay, fileExists, readDir, testMap } from './file-storage-cases'; const { description, storageType, options } = testMap[1]; @@ -19,7 +18,13 @@ describe(description, () => { imports: [FileStorageModule.forRoot(storageType, options)], }).compile(); - fileStorage = module.get(FILE_STORAGE_STRATEGY_TOKEN); + fileStorage = module.get(FileStorageService); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + fileStorage['fileStorage'].config!.filePath = (options: { request?: Request; fileName: string }): string => { + const { fileName } = options; + const prefix = process.env.PREFIX ? `${process.env.PREFIX}/` : 'public/'; + return `${prefix}${fileName}`; + }; await fileStorage.deleteDir({ dirPath: '' }); }); @@ -148,7 +153,7 @@ describe(description, () => { const content = randomBytes(1024); await fileStorage.uploadFile({ filePath, content }); await fileStorage.uploadFile({ filePath: nestedFilePath, content }); - await delay(1500); + await delay(500); // const result = await fileStorage.readDir({ dirPath }); //