Skip to content

Commit

Permalink
feat(clone): domain
Browse files Browse the repository at this point in the history
  • Loading branch information
kgajowy committed Oct 8, 2021
1 parent 8236900 commit 5610427
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Export } from '../domain/export/export';
import { ResourceId } from '../domain/export/resource.id';

export abstract class ExportRepository {
abstract save(exportInstance: Export): Promise<void>;

abstract find(projectId: ResourceId): Promise<Export | undefined>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ResourceId } from '../domain/export/resource.id';
import { ResourceKind } from '../domain/export/resource.kind';
import { ClonePart } from '../domain/export/clone-part/clone-part';
import { Export } from '../domain/export/export';
import { ExportId } from '../domain/export/export.id';

import { ExportRepository } from './export-repository.port';
import { ResourcePieces } from './resource-pieces.port';

export class RequestExport {
constructor(
private readonly resourcePieces: ResourcePieces,
private readonly exportRepository: ExportRepository,
) {}

async export(id: ResourceId, kind: ResourceKind): Promise<ExportId> {
const parts: ClonePart[] = await this.resourcePieces.resolveFor(id, kind);
const exportInstance = Export.project(id, parts);
await this.exportRepository.save(exportInstance);
return exportInstance.id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ResourceId } from '../domain/export/resource.id';
import { ResourceKind } from '../domain/export/resource.kind';
import { ClonePart } from '../domain/export/clone-part/clone-part';

export abstract class ResourcePieces {
abstract resolveFor(id: ResourceId, kind: ResourceKind): Promise<ClonePart[]>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IEvent } from '@nestjs/cqrs';

import { ExportId } from '../export/export.id';
import { ArchiveLocation } from '../export/archive-location';

export class ArchiveReady implements IEvent {
constructor(
public readonly exportId: ExportId,
public readonly archiveLocation: ArchiveLocation,
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IEvent } from '@nestjs/cqrs';

import { ExportId } from '../export/export.id';
import { PieceId } from '../export/clone-part/piece.id';
import { ResourceId } from '../export/resource.id';
import { ClonePiece } from '../../../shared-kernel/clone-piece';

export class ClonePartRequested implements IEvent {
constructor(
public readonly exportId: ExportId,
public readonly pieceId: PieceId,
public readonly resourceId: ResourceId,
public readonly piece: ClonePiece,
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IEvent } from '@nestjs/cqrs';
import { ExportId } from '../export/export.id';

export class ClonePartsFinished implements IEvent {
constructor(public readonly exportId: ExportId) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TinyTypeOf } from 'tiny-types';

/**
* a URI pointing at exported project/scenario archive
*/
export class ArchiveLocation extends TinyTypeOf<string>() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { v4 } from 'uuid';
import { ClonePiece } from '../../../../shared-kernel/clone-piece';
import { ResourceId } from '../resource.id';
import { PieceId } from './piece.id';
import { PieceLocation } from './piece-location';

export class ClonePart {
private constructor(
readonly id: PieceId,
readonly piece: ClonePiece,
readonly resourceId: ResourceId,
private finished: boolean = false,
private uri?: PieceLocation,
) {}

static newOne(resourceId: ResourceId, piece: ClonePiece): ClonePart {
return new ClonePart(new PieceId(v4()), piece, resourceId);
}

finish(location: PieceLocation) {
this.finished = true;
this.uri = location;
}

isReady() {
return this.finished;
}

// TODO
toSnapshot() {
return {};
}

// TODO
static fromSnapshot() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TinyTypeOf } from 'tiny-types';

/**
* a URI pointing at the given Piece, whatever format it is
*/
export class PieceLocation extends TinyTypeOf<string>() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TinyTypeOf } from 'tiny-types';

export class PieceId extends TinyTypeOf<string>() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TinyTypeOf } from 'tiny-types';

export class ExportId extends TinyTypeOf<string>() {}
78 changes: 78 additions & 0 deletions api/apps/api/src/modules/clone/export/domain/export/export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { v4 } from 'uuid';
import { AggregateRoot } from '@nestjs/cqrs';

import { ResourceKind } from './resource.kind';
import { ExportId } from './export.id';
import { ResourceId } from './resource.id';
import { ArchiveLocation } from './archive-location';

import { ClonePartRequested } from '../events/clone-part-requested.event';
import { ClonePartsFinished } from '../events/clone-parts-finished.event';
import { ArchiveReady } from '../events/archive-ready.event';

import { PieceLocation } from './clone-part/piece-location';
import { ClonePart } from './clone-part/clone-part';
import { PieceId } from './clone-part/piece.id';

export class Export extends AggregateRoot {
private constructor(
public readonly id: ExportId,
public readonly resourceId: ResourceId,
public readonly resourceKind: ResourceKind,
public readonly pieces: ClonePart[],
private archiveLocation?: ArchiveLocation,
) {
super();
}

static project(id: ResourceId, parts: ClonePart[]): Export {
const exportRequest = new Export(
new ExportId(v4()),
id,
ResourceKind.Project,
parts,
);

exportRequest.apply(
parts
.filter((part) => !part.isReady())
.map(
(part) =>
new ClonePartRequested(
exportRequest.id,
part.id,
part.resourceId,
part.piece,
),
),
);

return exportRequest;
}

completePiece(id: PieceId, pieceLocation: PieceLocation) {
const piece = this.pieces.find((piece) => piece.id.equals(id));

// TODO throw
piece?.finish(pieceLocation);

if (this.#allPiecesReady()) {
this.apply(new ClonePartsFinished(this.id));
}
}

complete(archiveLocation: ArchiveLocation) {
this.archiveLocation = archiveLocation;
this.apply(new ArchiveReady(this.id, this.archiveLocation));
}

toSnapshot() {
//
}

static fromSnapshot() {
//
}

#allPiecesReady = () => this.pieces.every((piece) => piece.isReady());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TinyTypeOf } from 'tiny-types';

export class ResourceId extends TinyTypeOf<string>() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum ResourceKind {
Project = 'project',
Scenario = 'scenario',
}
9 changes: 9 additions & 0 deletions api/apps/api/src/modules/clone/shared-kernel/clone-piece.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export enum ClonePiece {
ProjectMetadata = 'project-metadata',
PlanningAreaGAdm = 'planning-area-gadm',
PlanningAreaCustom = 'planning-area-shapefile',
PlanningAreaGridConfig = 'planning-area-grid-config',
PlanningAreaGridCustom = 'planning-area-grid-shapefile',
ScenarioMetadata = 'scenario-metadata',
MarxanSettings = 'marxan-settings',
}

0 comments on commit 5610427

Please sign in to comment.