Skip to content

Commit

Permalink
chore: adjustments on mutate and lookup pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
tnramalho committed Sep 18, 2024
1 parent 3f10b32 commit a80adfc
Show file tree
Hide file tree
Showing 17 changed files with 299 additions and 84 deletions.
1 change: 1 addition & 0 deletions packages/nestjs-file/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@concepta/nestjs-exception": "^5.0.0-alpha.3",
"@concepta/nestjs-typeorm-ext": "^5.0.0-alpha.3",
"@concepta/ts-common": "^5.0.0-alpha.3",
"@concepta/ts-core": "^5.0.0-alpha.3",
"@concepta/typeorm-common": "^5.0.0-alpha.3",
"@nestjs/common": "^10.4.1",
"@nestjs/config": "^3.2.3",
Expand Down
6 changes: 3 additions & 3 deletions packages/nestjs-file/src/__fixtures__/aws-storage.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FileInterface } from '@concepta/ts-common';
import { FileCreatableInterface } from '@concepta/ts-common';
import { FileStorageServiceInterface } from '../interfaces/file-storage-service.interface';
import {
AWS_KEY_FIXTURE,
Expand All @@ -9,11 +9,11 @@ import {
export class AwsStorageService implements FileStorageServiceInterface {
KEY: string = AWS_KEY_FIXTURE;

getUploadUrl(_file: FileInterface): string {
getUploadUrl(_file: FileCreatableInterface): string {
return UPLOAD_URL_FIXTURE;
}

getDownloadUrl(_file: FileInterface): string {
getDownloadUrl(_file: FileCreatableInterface): string {
// make a call to aws to get signed download url
return DOWNLOAD_URL_FIXTURE;
}
Expand Down
16 changes: 7 additions & 9 deletions packages/nestjs-file/src/exceptions/file-create.exception.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { HttpStatus } from '@nestjs/common';
import { RuntimeException } from '@concepta/nestjs-exception';
import {
RuntimeException,
RuntimeExceptionOptions,
} from '@concepta/nestjs-exception';

export class FileCreateException extends RuntimeException {
constructor(
message = 'Error while trying to create a file',
originalError: unknown,
) {
constructor(options?: RuntimeExceptionOptions) {
super({
message,
originalError,
httpStatus: HttpStatus.INTERNAL_SERVER_ERROR,
message: 'Error while trying to create a file',
...options,
});

this.errorCode = 'FILE_CREATE_ERROR';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { HttpStatus } from '@nestjs/common';
import {
RuntimeException,
RuntimeExceptionOptions,
} from '@concepta/nestjs-exception';

export class FileDownloadUrlMissingException extends RuntimeException {
constructor(options?: RuntimeExceptionOptions) {
super({
message: 'Error trying to generate signed download url',
httpStatus: HttpStatus.BAD_REQUEST,
...options,
});

this.errorCode = 'FILE_DOWNLOAD_URL_ERROR';
}
}
17 changes: 17 additions & 0 deletions packages/nestjs-file/src/exceptions/file-name-missing.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { HttpStatus } from '@nestjs/common';
import {
RuntimeException,
RuntimeExceptionOptions,
} from '@concepta/nestjs-exception';

export class FilenameMissingException extends RuntimeException {
constructor(options?: RuntimeExceptionOptions) {
super({
message: 'Filename is missing.',
httpStatus: HttpStatus.BAD_REQUEST,
...options,
});

this.errorCode = 'FILENAME_MISSING_ERROR';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { HttpStatus } from '@nestjs/common';
import {
RuntimeException,
RuntimeExceptionOptions,
} from '@concepta/nestjs-exception';

export class FileServiceKeyMissingException extends RuntimeException {
constructor(options?: RuntimeExceptionOptions) {
super({
message: 'Service key is missing.',
httpStatus: HttpStatus.BAD_REQUEST,
...options,
});

this.errorCode = 'SERVICE_KEY_MISSING_ERROR';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { HttpStatus } from '@nestjs/common';
import {
RuntimeException,
RuntimeExceptionOptions,
} from '@concepta/nestjs-exception';

export class FileUploadUrlMissingException extends RuntimeException {
constructor(options?: RuntimeExceptionOptions) {
super({
message: 'Error trying to generate signed upload url',
httpStatus: HttpStatus.BAD_REQUEST,
...options,
});

this.errorCode = 'FILE_UPLOAD_URL_ERROR';
}
}
6 changes: 6 additions & 0 deletions packages/nestjs-file/src/file.module-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { FileService } from './services/file.service';
import { FileStrategyService } from './services/file-strategy.service';

import { fileDefaultConfig } from './config/file-default.config';
import { FileMutateService } from './services/file-mutate.service';
import { FileLookupService } from './services/file-lookup.service';

const RAW_OPTIONS_TOKEN = Symbol('__FILE_MODULE_RAW_OPTIONS_TOKEN__');

Expand Down Expand Up @@ -82,6 +84,10 @@ export function createFileProviders(options: {
...(options.providers ?? []),
createFileSettingsProvider(options.overrides),
createStrategyServiceProvider(options.overrides),
// TODO: move to be overwrittable
FileMutateService,
// TODO: move to be overwrittable
FileLookupService,
FileStrategyService,
FileService,
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FileCreatableInterface, FileInterface } from '@concepta/ts-common';
import { LookupIdInterface, ReferenceId } from '@concepta/ts-core';
import { QueryOptionsInterface } from '@concepta/typeorm-common';

export interface FileLookupServiceInterface
extends LookupIdInterface<ReferenceId, FileInterface, QueryOptionsInterface> {
getUniqueFile(
org: Pick<FileCreatableInterface, 'serviceKey' | 'fileName'>,
queryOptions?: QueryOptionsInterface,
): Promise<FileInterface | null>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FileCreatableInterface } from '@concepta/ts-common';
import { CreateOneInterface } from '@concepta/ts-core';
import { FileEntityInterface } from './file-entity.interface';

export interface FileMutateServiceInterface
extends CreateOneInterface<FileCreatableInterface, FileEntityInterface> {}
7 changes: 4 additions & 3 deletions packages/nestjs-file/src/interfaces/file-service.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FileInterface } from '@concepta/ts-common';
import { FileCreatableInterface, FileInterface } from '@concepta/ts-common';
import { ReferenceIdInterface } from '@concepta/ts-core';

export interface FileServiceInterface {
push(file: Omit<FileInterface, 'id'>): Promise<FileInterface>;
fetch(file: Omit<FileInterface, 'serviceKey'>): Promise<FileInterface>;
push(file: FileCreatableInterface): Promise<FileInterface>;
fetch(file: ReferenceIdInterface): Promise<FileInterface>;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { FileInterface } from '@concepta/ts-common';
import { FileCreatableInterface } from '@concepta/ts-common';
import { FileStorageServiceInterface } from './file-storage-service.interface';

export interface FileStrategyServiceInterface {
getUploadUrl(file: FileInterface): Promise<string>;
getDownloadUrl(file: FileInterface): Promise<string>;
resolveStorageService(file: FileInterface): FileStorageServiceInterface;
getUploadUrl(file: FileCreatableInterface): Promise<string>;
getDownloadUrl(file: FileCreatableInterface): Promise<string>;
resolveStorageService(
file: FileCreatableInterface,
): FileStorageServiceInterface;
}
47 changes: 47 additions & 0 deletions packages/nestjs-file/src/services/file-lookup.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { InjectDynamicRepository } from '@concepta/nestjs-typeorm-ext';
import { LookupService, QueryOptionsInterface } from '@concepta/typeorm-common';
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';

import { FILE_MODULE_FILE_ENTITY_KEY } from '../file.constants';
import { FileEntityInterface } from '../interfaces/file-entity.interface';
import { FileLookupServiceInterface } from '../interfaces/file-lookup-service.interface';
import { FileInterface } from '@concepta/ts-common';
import { FileServiceKeyMissingException } from '../exceptions/file-service-key-missing.exception';
import { FilenameMissingException } from '../exceptions/file-name-missing.exception';

/**
* File lookup service
*/
@Injectable()
export class FileLookupService
extends LookupService<FileEntityInterface>
implements FileLookupServiceInterface
{
constructor(
@InjectDynamicRepository(FILE_MODULE_FILE_ENTITY_KEY)
repo: Repository<FileEntityInterface>,
) {
super(repo);
}
async getUniqueFile(
file: Pick<FileInterface, 'serviceKey' | 'fileName'>,
queryOptions?: QueryOptionsInterface,
) {
if (!file.serviceKey) {
throw new FileServiceKeyMissingException();
}
if (!file.fileName) {
throw new FilenameMissingException();
}
return this.findOne(
{
where: {
serviceKey: file.serviceKey,
fileName: file.fileName,
},
},
queryOptions,
);
}
}
38 changes: 38 additions & 0 deletions packages/nestjs-file/src/services/file-mutate.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Repository } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { MutateService } from '@concepta/typeorm-common';
import { InjectDynamicRepository } from '@concepta/nestjs-typeorm-ext';
import { FileCreatableInterface } from '@concepta/ts-common';
import { FileEntityInterface } from '../interfaces/file-entity.interface';

import { FileCreateDto } from '../dto/file-create.dto';
import { FileMutateServiceInterface } from '../interfaces/file-mutate-service.interface';
import { FILE_MODULE_FILE_ENTITY_KEY } from '../file.constants';

/**
* File mutate service
*/
@Injectable()
export class FileMutateService
extends MutateService<
FileEntityInterface,
FileCreatableInterface,
FileCreatableInterface
>
implements FileMutateServiceInterface
{
protected createDto = FileCreateDto;
protected updateDto = FileCreateDto;

/**
* Constructor
*
* @param repo - instance of the file repo
*/
constructor(
@InjectDynamicRepository(FILE_MODULE_FILE_ENTITY_KEY)
repo: Repository<FileEntityInterface>,
) {
super(repo);
}
}
17 changes: 15 additions & 2 deletions packages/nestjs-file/src/services/file-strategy.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FileCreatableInterface } from '@concepta/ts-common';
import { FileStrategyServiceInterface } from '../interfaces/file-strategy-service.interface';
import { FileStorageServiceInterface } from '../interfaces/file-storage-service.interface';
import { FileStorageServiceNotFoundException } from '../exceptions/file-storage-service-not-found.exception';
import { FileDownloadUrlMissingException } from '../exceptions/file-download-url-missing.exception';

export class FileStrategyService implements FileStrategyServiceInterface {
private readonly storageServices: FileStorageServiceInterface[] = [];
Expand All @@ -11,11 +12,23 @@ export class FileStrategyService implements FileStrategyServiceInterface {
}

async getUploadUrl(file: FileCreatableInterface): Promise<string> {
return this.resolveStorageService(file).getUploadUrl(file);
try {
return this.resolveStorageService(file).getUploadUrl(file);
} catch (err) {
throw new FileDownloadUrlMissingException({
originalError: err,
});
}
}

async getDownloadUrl(file: FileCreatableInterface): Promise<string> {
return this.resolveStorageService(file).getDownloadUrl(file);
try {
return this.resolveStorageService(file).getDownloadUrl(file);
} catch (err) {
throw new FileDownloadUrlMissingException({
originalError: err,
});
}
}

resolveStorageService(
Expand Down
Loading

0 comments on commit a80adfc

Please sign in to comment.