Skip to content

Commit

Permalink
refactor(nestjs-tools-file-storage): update readDir method type for e…
Browse files Browse the repository at this point in the history
…ach storage
  • Loading branch information
getlarge committed Aug 7, 2024
1 parent 6cd4bdd commit 59e516d
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 26 deletions.
19 changes: 10 additions & 9 deletions packages/file-storage/src/lib/file-storage-fs.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
FileStorageLocalSetup,
FileStorageLocalUploadFile,
FileStorageLocalUploadStream,
ReadDirOutput,
} from './file-storage-fs.types';
import { FileStorageWritable, MethodTypes, Request } from './types';

Expand Down Expand Up @@ -136,25 +137,25 @@ export class FileStorageLocal implements FileStorage {
return rm(dirName, options);
}

async readDir<R = string>(args: FileStorageLocalReadDir<R>): Promise<R[]> {
type RawOutput = string[] | Buffer[] | Dirent[];
const defaultSerializer = (v: RawOutput) =>
async readDir<R = string[]>(args: FileStorageLocalReadDir<R>): Promise<R> {
const defaultSerializer = (v: ReadDirOutput) =>
v.map((val) => {
if (val instanceof Buffer) {
return val.toString() as unknown as R;
return val.toString();
} else if (val instanceof Dirent) {
return val.name as unknown as R;
return val.name;
}
return val as unknown as R;
return val;
});
const { dirPath, request, serializer = defaultSerializer, options = {} } = args;
try {
const transformedDirPath = await this.transformFilePath(dirPath, MethodTypes.READ, request);
const result = (await readdir(transformedDirPath, options)) as string[] | Buffer[] | Dirent[];
return serializer(result);
const result = await readdir(transformedDirPath, options);
return serializer(result) as R;
} catch (err) {
if (err && typeof err === 'object' && 'code' in err && err['code'] === 'ENOENT') {
return [];
// ? return undefined or null?
return [] as R;
}
throw err;
}
Expand Down
6 changes: 4 additions & 2 deletions packages/file-storage/src/lib/file-storage-fs.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BigIntOptions, ObjectEncodingOptions, StatOptions, WriteFileOptions } from 'node:fs';
import type { BigIntOptions, Dirent, ObjectEncodingOptions, StatOptions, WriteFileOptions } from 'node:fs';

import type { FileStorageBaseArgs, FileStorageDirBaseArgs, FileStorageReadDirBaseArgs } from './file-storage.class';

Expand Down Expand Up @@ -56,6 +56,8 @@ export interface FileStorageLocalDeleteDir extends FileStorageDirBaseArgs {
options?: { recursive?: boolean; force?: boolean };
}

export interface FileStorageLocalReadDir<R = string> extends FileStorageReadDirBaseArgs<R> {
export type ReadDirOutput = string[] | Buffer[] | Dirent[];

export interface FileStorageLocalReadDir<R = string[], T = ReadDirOutput> extends FileStorageReadDirBaseArgs<R, T> {
options?: { encoding: BufferEncoding; withFileTypes?: boolean; recursive?: boolean } | BufferEncoding;
}
17 changes: 9 additions & 8 deletions packages/file-storage/src/lib/file-storage-google.class.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { File } from '@google-cloud/storage';
import type { File, GetFilesResponse } from '@google-cloud/storage';
import { Injectable } from '@nestjs/common';
import { finished, type Readable } from 'node:stream';

Expand All @@ -20,11 +20,12 @@ import { loadPackage } from './helpers';
import { FileStorageWritable, MethodTypes } from './types';

function config(setup: FileStorageGoogleSetup) {
const { bucketName, maxPayloadSize, projectId } = setup;
const { bucketName, keyFilename, maxPayloadSize, projectId } = setup;
const loaderFn = (): { Storage: typeof import('@google-cloud/storage').Storage } => require('@google-cloud/storage');
const { Storage } = loadPackage('@google-cloud/storage', FileStorageGoogle.name, loaderFn);
const storage = new Storage({
...(projectId ? { projectId } : {}),
...(keyFilename ? { keyFilename } : {}),
});

const filePath = (options: { request?: Request; fileName: string }): string => {
Expand Down Expand Up @@ -132,16 +133,16 @@ export class FileStorageGoogle implements FileStorage {
}

// TODO: make default serializer compliant with the other readDir implementations
async readDir<R = string>(args: FileStorageGoogleReadDir<R>): Promise<R[]> {
const defaultSerializer = (files: File[]) =>
files.map((f) => (prefix ? (f.name.replace(prefix, '').replace('/', '') as R) : (f.name as R)));

async readDir<R = string[]>(args: FileStorageGoogleReadDir<R>): Promise<R> {
const defaultSerializer = (res: GetFilesResponse) => {
return res[0].map((file: File) => file.name) as R;
};
const { storage, bucket } = this.config;
const { dirPath, request, serializer = defaultSerializer, options = {} } = args;
const prefix = await this.transformFilePath(dirPath, MethodTypes.READ, request, options);
const [files] = await storage
const response = await storage
.bucket(bucket)
.getFiles({ includeTrailingDelimiter: false, includeFoldersAsPrefixes: false, ...options, prefix });
return serializer(files);
return serializer(response) as R;
}
}
4 changes: 3 additions & 1 deletion packages/file-storage/src/lib/file-storage-google.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
DownloadOptions,
FileOptions,
GetFilesOptions,
GetFilesResponse,
MoveOptions,
SaveOptions,
Storage,
Expand All @@ -18,6 +19,7 @@ export interface FileStorageGoogleSetup {
maxPayloadSize: number;
projectId?: string;
bucketName: string;
keyFilename?: string;
}

export interface FileStorageGoogleConfig {
Expand Down Expand Up @@ -61,6 +63,6 @@ export interface FileStorageGoogleDeleteDir extends FileStorageDirBaseArgs {
options?: Omit<DeleteFilesOptions, 'prefix'> & FileOptions;
}

export interface FileStorageGoogleReadDir<R = string> extends FileStorageReadDirBaseArgs<R> {
export interface FileStorageGoogleReadDir<R = string[]> extends FileStorageReadDirBaseArgs<R, GetFilesResponse> {
options?: Omit<GetFilesOptions, 'prefix'> & FileOptions;
}
10 changes: 5 additions & 5 deletions packages/file-storage/src/lib/file-storage-s3.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,24 +196,24 @@ export class FileStorageS3 implements FileStorage {
}
}

async readDir<R = string>(args: FileStorageS3ReadDir<R>): Promise<R[]> {
async readDir<R = string[]>(args: FileStorageS3ReadDir<R>): Promise<R> {
const defaultSerializer = (list: ListObjectsCommandOutput) => {
const { CommonPrefixes, Contents, Prefix } = list;
const filesAndFilders: R[] = [];
const filesAndFilders: string[] = [];
// add nested folders, CommonPrefixes contains <prefix>/<next nested dir>
if (CommonPrefixes?.length) {
const folders = CommonPrefixes.map((prefixObject) => {
const prefix = removeTrailingForwardSlash(prefixObject.Prefix) ?? '';
const key = listParams['Prefix'];
// If key exists, we are looking for a nested folder
return (key ? prefix.slice(key.length) : prefix) as R;
return (key ? prefix.slice(key.length) : prefix) as string;
});
filesAndFilders.push(...folders);
}

// adds filenames
if (Contents?.length && Prefix) {
const files = Contents.filter((file) => !!file.Key).map((file) => file.Key?.replace(Prefix, '') as R);
const files = Contents.filter((file) => !!file.Key).map((file) => file.Key?.replace(Prefix, '') as string);
filesAndFilders.push(...files);
}
return filesAndFilders;
Expand All @@ -232,6 +232,6 @@ export class FileStorageS3 implements FileStorage {
listParams.Prefix = addTrailingForwardSlash(Key);
}
const listedObjects = await s3.listObjects(listParams);
return serializer(listedObjects);
return serializer(listedObjects) as R;
}
}
3 changes: 2 additions & 1 deletion packages/file-storage/src/lib/file-storage-s3.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
GetObjectCommandInput,
HeadObjectCommandInput,
ListObjectsCommandInput,
ListObjectsCommandOutput,
PutObjectCommandInput,
S3,
} from '@aws-sdk/client-s3';
Expand Down Expand Up @@ -66,6 +67,6 @@ export interface FileStorageS3DeleteDir extends FileStorageDirBaseArgs {
options?: Omit<DeleteObjectsCommandInput, 'Bucket' | 'Delete'>;
}

export interface FileStorageS3ReadDir<R = string> extends FileStorageReadDirBaseArgs<R> {
export interface FileStorageS3ReadDir<R = string[]> extends FileStorageReadDirBaseArgs<R, ListObjectsCommandOutput> {
options?: Omit<ListObjectsCommandInput, 'Bucket' | 'Delimiter'>;
}

0 comments on commit 59e516d

Please sign in to comment.