Skip to content

Commit

Permalink
wip: overrider
Browse files Browse the repository at this point in the history
  • Loading branch information
JoanVicens committed Mar 21, 2024
1 parent 65f1342 commit d8408ad
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ContentsId } from '../../../contents/domain/ContentsId';
import { EventBus } from '../../../shared/domain/EventBus';
import { File } from '../../domain/File';
import { FileRepository } from '../../domain/FileRepository';
import { FileSize } from '../../domain/FileSize';
import { FileNotFoundError } from '../../domain/errors/FileNotFoundError';
import { RemoteFileSystem } from '../../domain/file-systems/RemoteFileSystem';

export class FileOverrider {
constructor(
private readonly repository: FileRepository,
private readonly rfs: RemoteFileSystem,
private readonly eventBus: EventBus
) {}

async run(
fileId: File['id'],
contentsId: File['contentsId'],
size: File['size']
): Promise<void> {
const file = await this.repository.searchById(fileId);

if (!file) {
throw new FileNotFoundError(fileId);
}

const newContentsId = new ContentsId(contentsId);
const newSize = new FileSize(size);

file.changeContents(newContentsId, newSize);

this.rfs.override(file);

this.eventBus.publish(file.pullDomainEvents());
}
}
21 changes: 20 additions & 1 deletion src/context/virtual-drive/files/domain/File.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ContentsId } from '../../contents/domain/ContentsId';
import { FileMovedDomainEvent } from './events/FileMovedDomainEvent';
import { FileRenamedDomainEvent } from './events/FileRenamedDomainEvent';
import { FilePlaceholderId, createFilePlaceholderId } from './PlaceholderId';
import { FileOverriddenDomainEvent } from './events/FileOverriddenDomainEvent';

export type FileAttributes = {
id: number;
Expand All @@ -32,7 +33,7 @@ export class File extends AggregateRoot {
private _contentsId: ContentsId,
private _folderId: number,
private _path: FilePath,
private readonly _size: FileSize,
private _size: FileSize,
public createdAt: Date,
public updatedAt: Date,
private _status: FileStatus
Expand Down Expand Up @@ -174,6 +175,24 @@ export class File extends AggregateRoot {
);
}

changeContents(contentsId: ContentsId, contentsSize: FileSize) {
const previousContentsId = this.contentsId;
const previousSize = this.size;

this._contentsId = contentsId;
this._size = contentsSize;

this.record(
new FileOverriddenDomainEvent({
aggregateId: this.contentsId,
previousContentsId,
previousSize,
currentContentsId: contentsId.value,
currentSize: contentsSize.value,
})
);
}

hasParent(id: number): boolean {
return this.folderId === id;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export class FileNotFoundError extends Error {
constructor(id: string) {
constructor(id: string | number) {
super(`File ${id} not found`);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { DomainEvent } from '../../../../shared/domain/DomainEvent';

export class FileOverriddenDomainEvent extends DomainEvent {
static readonly EVENT_NAME = 'file.overridden';

readonly previousContentsId: string;
readonly previousSize: number;

readonly currentContentsId: string;
readonly currentSize: number;

constructor({
aggregateId,
previousContentsId,
previousSize,
currentContentsId,
currentSize,
}: {
aggregateId: string;
previousContentsId: string;
previousSize: number;
currentContentsId: string;
currentSize: number;
}) {
super({
eventName: FileOverriddenDomainEvent.EVENT_NAME,
aggregateId,
});

this.previousContentsId = previousContentsId;
this.previousSize = previousSize;

this.currentContentsId = currentContentsId;
this.currentSize = currentSize;
}

toPrimitives() {
return {
aggregateId: this.aggregateId,
previousContentsId: this.previousContentsId,
previousSize: this.previousSize,
currentContentsId: this.currentContentsId,
currentSize: this.currentSize,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ export interface RemoteFileSystem {
move(file: File): Promise<void>;

rename(file: File): Promise<void>;

override(file: File): Promise<void>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,11 @@ export class SDKRemoteFileSystem implements RemoteFileSystem {
bucketId: this.bucket,
});
}

async override(file: File): Promise<void> {
await this.sdk.replaceFile('b81849d9-e45e-5e00-9e4e-b9cc3b1c1687', {
fileId: file.contentsId,
size: file.size,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class ContentsIdMother {
return new ContentsId(raw);
}

static raw(): string {
static primitive(): string {
return chance.string({ length: ContentsId.VALID_LENGTH });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('Environment Content File Uploader', () => {
describe('event emitter', () => {
it('emits an event on start', async () => {
const strategy = createUploadStrategy((opts) => {
opts.finishedCallback(null, ContentsIdMother.raw());
opts.finishedCallback(null, ContentsIdMother.primitive());
});

const uploader = new EnvironmentContentFileUploader(strategy, bucket);
Expand All @@ -25,7 +25,7 @@ describe('Environment Content File Uploader', () => {
});

it('emits an event with an id when a file is uploaded', async () => {
const uploadedFileId = ContentsIdMother.raw();
const uploadedFileId = ContentsIdMother.primitive();
const strategy = createUploadStrategy((opts) => {
opts.finishedCallback(null, uploadedFileId);
});
Expand All @@ -44,7 +44,7 @@ describe('Environment Content File Uploader', () => {
opts.progressCallback(25, 1, 4);
opts.progressCallback(50, 2, 4);
opts.progressCallback(75, 3, 4);
opts.finishedCallback(null, ContentsIdMother.raw());
opts.finishedCallback(null, ContentsIdMother.primitive());
});

const uploader = new EnvironmentContentFileUploader(strategy, bucket);
Expand All @@ -61,7 +61,7 @@ describe('Environment Content File Uploader', () => {
it('emits an event when there is a progress update and finish on the end', async () => {
const strategy = createUploadStrategy((opts) => {
opts.progressCallback(50, 2, 4);
opts.finishedCallback(null, ContentsIdMother.raw());
opts.finishedCallback(null, ContentsIdMother.primitive());
});

const uploader = new EnvironmentContentFileUploader(strategy, bucket);
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('Environment Content File Uploader', () => {
const strategy = createUploadStrategy((opts) => {
setTimeout(() => opts.progressCallback(50, 1, 4), 20);
setTimeout(
() => opts.finishedCallback(null, ContentsIdMother.raw()),
() => opts.finishedCallback(null, ContentsIdMother.primitive()),
100
);
});
Expand All @@ -122,7 +122,7 @@ describe('Environment Content File Uploader', () => {
const delay = 1000;
const strategy = createUploadStrategy((opts) => {
setTimeout(
() => opts.finishedCallback(null, ContentsIdMother.raw()),
() => opts.finishedCallback(null, ContentsIdMother.primitive()),
delay
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class RemoteFileSystemMock implements RemoteFileSystem {
public readonly trashMock = jest.fn();
public readonly moveMock = jest.fn();
public readonly renameMock = jest.fn();
public readonly overrideMock = jest.fn();

persist(offline: OfflineFile): Promise<FileAttributes> {
return this.persistMock(offline);
Expand All @@ -26,4 +27,8 @@ export class RemoteFileSystemMock implements RemoteFileSystem {
rename(file: File): Promise<void> {
return this.renameMock(file);
}

override(file: File): Promise<void> {
return this.overrideMock(file);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { FileCreator } from '../../../../../src/context/virtual-drive/files/application/FileCreator';
import { FileDeleter } from '../../../../../src/context/virtual-drive/files/application/FileDeleter';
import { File } from '../../../../../src/context/virtual-drive/files/domain/File';
import { FileRepository } from '../../../../../src/context/virtual-drive/files/domain/FileRepository';
import { SyncFileMessenger } from '../../../../../src/context/virtual-drive/files/domain/SyncFileMessenger';
import { RemoteFileSystem } from '../../../../../src/context/virtual-drive/files/domain/file-systems/RemoteFileSystem';
import { ParentFolderFinder } from '../../../../../src/context/virtual-drive/folders/application/ParentFolderFinder';
import { EventBus } from '../../../../../src/context/virtual-drive/shared/domain/EventBus';

export class FileCreatorTestClass extends FileCreator {
public readonly mock = jest.fn();

constructor() {
super(
{} as RemoteFileSystem,
{} as FileRepository,
{} as ParentFolderFinder,
{} as FileDeleter,
{} as EventBus,
{} as SyncFileMessenger
);
}

run(path: string, contentsId: string, size: number): Promise<File> {
return this.mock(path, contentsId, size);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FileToOverrideProvider } from '../../../../../src/context/virtual-drive/files/application/FileToOverrideProvider';
import { File } from '../../../../../src/context/virtual-drive/files/domain/File';
import { FileRepository } from '../../../../../src/context/virtual-drive/files/domain/FileRepository';
import { EventRepository } from '../../../../../src/context/virtual-drive/shared/domain/EventRepository';
import { Optional } from '../../../../../src/shared/types/Optional';

export class FileToOverrideProviderTestClass extends FileToOverrideProvider {
readonly mock = jest.fn();

constructor() {
super({} as EventRepository, {} as FileRepository);
}

run(): Promise<Optional<File>> {
return this.mock();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('File Deleter', () => {
});

it('does not nothing if the file its not found', async () => {
const contentsId = ContentsIdMother.raw();
const contentsId = ContentsIdMother.primitive();

repository.searchByContentsIdMock.mockReturnValueOnce(undefined);
jest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { CreateFileOnOfflineFileUploaded } from '../../../../../../src/context/virtual-drive/files/application/event-subsribers/CreateFileOnOfflineFileUplodaded';
import { Optional } from '../../../../../../src/shared/types/Optional';
import { FileCreatorTestClass } from '../../__test-class__/FileCreatorTestClass';
import { FileToOverrideProviderTestClass } from '../../__test-class__/FileToOverrideProviderTestClass';
import { FileMother } from '../../domain/FileMother';
import { OfflineContentsUploadedDomainEventMother } from '../../domain/events/OfflineContentsUploadedDomainEventMother';

describe('Create File On Offline File Uploaded', () => {
it('creates a new file when no file to be overridden is found', async () => {
const creator = new FileCreatorTestClass();
const toOverride = new FileToOverrideProviderTestClass();
const uploadedEvent = OfflineContentsUploadedDomainEventMother.any();

const sut = new CreateFileOnOfflineFileUploaded(creator, toOverride);

toOverride.mock.mockReturnValueOnce(Optional.empty());

await sut.on(uploadedEvent);

expect(creator.mock).toBeCalledWith(
uploadedEvent.path,
uploadedEvent.aggregateId,
uploadedEvent.size
);
});

it('does not create a new file an overridden file is provided', async () => {
const creator = new FileCreatorTestClass();
const toOverride = new FileToOverrideProviderTestClass();
const uploadedEvent = OfflineContentsUploadedDomainEventMother.any();

const sut = new CreateFileOnOfflineFileUploaded(creator, toOverride);

toOverride.mock.mockReturnValueOnce(Optional.of(FileMother.any()));

await sut.on(uploadedEvent);

expect(creator.mock).not.toBeCalled();
});
});
Loading

0 comments on commit d8408ad

Please sign in to comment.