Skip to content

Commit

Permalink
Merge pull request #90 from getlarge/78-featfile-storage-add-methods-…
Browse files Browse the repository at this point in the history
…to-read-and-update-file-metadata

feat: add methods to read and update file metadata
  • Loading branch information
getlarge committed Aug 7, 2024
2 parents fb79ace + 65694fe commit 03280b5
Show file tree
Hide file tree
Showing 15 changed files with 450 additions and 154 deletions.
15 changes: 13 additions & 2 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -114,7 +124,8 @@ 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
PREFIX: ${{ matrix.node-version }}
run: npx nx affected -t lint,test,build --parallel=2

- name: Upload coverage
uses: actions/upload-artifact@v4
Expand Down
38 changes: 30 additions & 8 deletions packages/file-storage/src/lib/file-storage-fs.class.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -131,6 +137,22 @@ export class FileStorageLocal implements FileStorage {
);
}

async getFileMeta(
args: FileStorageLocalGetFileMeta & {
options: { bigint: false | undefined };
},
): Promise<Stats>;
async getFileMeta(
args: FileStorageLocalGetFileMeta & {
options: { bigint: true };
},
): Promise<BigIntStats>;
async getFileMeta(args: FileStorageLocalGetFileMeta): Promise<Stats | BigIntStats> {
const { filePath, options, request } = args;
const fileName = await this.transformFilePath(filePath, MethodTypes.READ, request);
return statPromise(fileName, options);
}

async deleteDir(args: FileStorageLocalDeleteDir): Promise<void> {
const { options = { recursive: true, force: true }, dirPath, request } = args;
const dirName = await this.transformFilePath(dirPath, MethodTypes.DELETE, request);
Expand Down
50 changes: 37 additions & 13 deletions packages/file-storage/src/lib/file-storage-fs.types.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -20,44 +39,49 @@ 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 {
options:
export interface FileStorageLocalDownloadFile extends FileStorageDownloadFile {
options?:
| { encoding?: null; flag?: string }
| { encoding: BufferEncoding; flag?: string }
| BufferEncoding
| (ObjectEncodingOptions & { flag?: string })
| undefined
| null;
// options?: Record<string, any> | 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<R = string[], T = ReadDirOutput> extends FileStorageReadDirBaseArgs<R, T> {
export interface FileStorageLocalReadDir<R = string[], T = ReadDirOutput> extends FileStorageReadDir<R, T> {
options?: { encoding: BufferEncoding; withFileTypes?: boolean; recursive?: boolean } | BufferEncoding;
}
15 changes: 13 additions & 2 deletions packages/file-storage/src/lib/file-storage-google.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ 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,
FileStorageGoogleDeleteFile,
FileStorageGoogleDownloadFile,
FileStorageGoogleDownloadStream,
FileStorageGoogleFileExists,
FileStorageGoogleGetFileMeta,
FileStorageGoogleGetFileMetaOutput,
FileStorageGoogleMoveFile,
FileStorageGoogleReadDir,
FileStorageGoogleSetup,
Expand Down Expand Up @@ -125,6 +128,14 @@ export class FileStorageGoogle implements FileStorage {
}
}

async getFileMeta(args: FileStorageGoogleGetFileMeta): Promise<FileStorageGoogleGetFileMetaOutput> {
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<void> {
const { storage, bucket } = this.config;
const { options = {}, request } = args;
Expand All @@ -135,7 +146,7 @@ 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 = (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;
Expand Down
46 changes: 33 additions & 13 deletions packages/file-storage/src/lib/file-storage-google.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,32 @@ import type {
CreateWriteStreamOptions,
DeleteFilesOptions,
DownloadOptions,
FileMetadata,
FileOptions,
GetFilesOptions,
GetFilesResponse,
MoveOptions,
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 {
Expand All @@ -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<DeleteFilesOptions, 'prefix'> & FileOptions;
}

export interface FileStorageGoogleReadDir<R = string[]> extends FileStorageReadDirBaseArgs<R, GetFilesResponse> {
export interface FileStorageGoogleReadDir<R = string[]> extends FileStorageReadDir<R, GetFilesResponse> {
options?: Omit<GetFilesOptions, 'prefix'> & FileOptions;
}
12 changes: 11 additions & 1 deletion packages/file-storage/src/lib/file-storage-s3.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ 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,
FileStorageS3DeleteFile,
FileStorageS3DownloadFile,
FileStorageS3DownloadStream,
FileStorageS3FileExists,
FileStorageS3GetFileMeta,
FileStorageS3GetFileMetaOutput,
FileStorageS3MoveFile,
FileStorageS3ReadDir,
FileStorageS3Setup,
Expand Down Expand Up @@ -166,6 +169,13 @@ export class FileStorageS3 implements FileStorage {
return true;
}

async getFileMeta(args: FileStorageS3GetFileMeta): Promise<FileStorageS3GetFileMetaOutput> {
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<void> {
const { dirPath, options = {}, request } = args;
const { s3, bucket: Bucket } = this.config;
Expand Down
Loading

0 comments on commit 03280b5

Please sign in to comment.