-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(clone): export domain/app (#560)
* feat(clone): domain * feat(clone): domain snapshots and intentions return values * feat(clone): rename clone-piece to export-component * refactor(clone): replace hardcoded project export
- Loading branch information
Showing
17 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
8 changes: 8 additions & 0 deletions
8
api/apps/api/src/modules/clone/export/application/export-repository.port.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>; | ||
} |
33 changes: 33 additions & 0 deletions
33
api/apps/api/src/modules/clone/export/application/request-export.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { EventPublisher } from '@nestjs/cqrs'; | ||
|
||
import { ResourceId } from '../domain/export/resource.id'; | ||
import { ResourceKind } from '../domain/export/resource.kind'; | ||
import { ExportComponent } from '../domain/export/export-component/export-component'; | ||
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, | ||
private readonly eventPublisher: EventPublisher, | ||
) {} | ||
|
||
async export(id: ResourceId, kind: ResourceKind): Promise<ExportId> { | ||
const pieces: ExportComponent[] = await this.resourcePieces.resolveFor( | ||
id, | ||
kind, | ||
); | ||
const exportInstance = this.eventPublisher.mergeObjectContext( | ||
Export.newOne(id, kind, pieces), | ||
); | ||
await this.exportRepository.save(exportInstance); | ||
|
||
exportInstance.commit(); | ||
|
||
return exportInstance.id; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
api/apps/api/src/modules/clone/export/application/resource-pieces.port.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { ResourceId } from '../domain/export/resource.id'; | ||
import { ResourceKind } from '../domain/export/resource.kind'; | ||
import { ExportComponent } from '../domain/export/export-component/export-component'; | ||
|
||
export abstract class ResourcePieces { | ||
abstract resolveFor( | ||
id: ResourceId, | ||
kind: ResourceKind, | ||
): Promise<ExportComponent[]>; | ||
} |
11 changes: 11 additions & 0 deletions
11
api/apps/api/src/modules/clone/export/domain/events/archive-ready.event.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
) {} | ||
} |
6 changes: 6 additions & 0 deletions
6
api/apps/api/src/modules/clone/export/domain/events/export-component-finished.event.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ExportComponentFinished implements IEvent { | ||
constructor(public readonly exportId: ExportId) {} | ||
} |
15 changes: 15 additions & 0 deletions
15
api/apps/api/src/modules/clone/export/domain/events/export-component-requested.event.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 { ComponentId } from '../export/export-component/component.id'; | ||
import { ResourceId } from '../export/resource.id'; | ||
import { ClonePiece } from '../../../shared-kernel/clone-piece'; | ||
|
||
export class ExportComponentRequested implements IEvent { | ||
constructor( | ||
public readonly exportId: ExportId, | ||
public readonly componentId: ComponentId, | ||
public readonly resourceId: ResourceId, | ||
public readonly piece: ClonePiece, | ||
) {} | ||
} |
6 changes: 6 additions & 0 deletions
6
api/apps/api/src/modules/clone/export/domain/export/archive-location.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>() {} |
9 changes: 9 additions & 0 deletions
9
api/apps/api/src/modules/clone/export/domain/export/export-component.snapshot.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { ClonePiece } from '../../../shared-kernel/clone-piece'; | ||
|
||
export interface ExportComponentSnapshot { | ||
readonly id: string; | ||
readonly piece: ClonePiece; | ||
readonly resourceId: string; | ||
readonly finished: boolean; | ||
readonly uri?: string; | ||
} |
6 changes: 6 additions & 0 deletions
6
api/apps/api/src/modules/clone/export/domain/export/export-component/component-location.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ComponentLocation extends TinyTypeOf<string>() {} |
3 changes: 3 additions & 0 deletions
3
api/apps/api/src/modules/clone/export/domain/export/export-component/component.id.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { TinyTypeOf } from 'tiny-types'; | ||
|
||
export class ComponentId extends TinyTypeOf<string>() {} |
51 changes: 51 additions & 0 deletions
51
api/apps/api/src/modules/clone/export/domain/export/export-component/export-component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { v4 } from 'uuid'; | ||
import { ClonePiece } from '../../../../shared-kernel/clone-piece'; | ||
|
||
import { ResourceId } from '../resource.id'; | ||
import { ExportComponentSnapshot } from '../export-component.snapshot'; | ||
|
||
import { ComponentId } from './component.id'; | ||
import { ComponentLocation } from './component-location'; | ||
|
||
export class ExportComponent { | ||
private constructor( | ||
readonly id: ComponentId, | ||
readonly piece: ClonePiece, | ||
readonly resourceId: ResourceId, | ||
private finished: boolean = false, | ||
private uri?: ComponentLocation, | ||
) {} | ||
|
||
static newOne(resourceId: ResourceId, piece: ClonePiece): ExportComponent { | ||
return new ExportComponent(new ComponentId(v4()), piece, resourceId); | ||
} | ||
|
||
finish(location: ComponentLocation) { | ||
this.finished = true; | ||
this.uri = location; | ||
} | ||
|
||
isReady() { | ||
return this.finished; | ||
} | ||
|
||
toSnapshot(): ExportComponentSnapshot { | ||
return { | ||
id: this.id.value, | ||
piece: this.piece, | ||
resourceId: this.resourceId.value, | ||
finished: this.finished, | ||
uri: this.uri?.value, | ||
}; | ||
} | ||
|
||
static fromSnapshot(snapshot: ExportComponentSnapshot) { | ||
return new ExportComponent( | ||
new ComponentId(snapshot.id), | ||
snapshot.piece, | ||
new ResourceId(snapshot.resourceId), | ||
snapshot.finished, | ||
snapshot.uri ? new ComponentLocation(snapshot.uri) : undefined, | ||
); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
api/apps/api/src/modules/clone/export/domain/export/export.id.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>() {} |
10 changes: 10 additions & 0 deletions
10
api/apps/api/src/modules/clone/export/domain/export/export.snapshot.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { ResourceKind } from './resource.kind'; | ||
import { ExportComponentSnapshot } from './export-component.snapshot'; | ||
|
||
export interface ExportSnapshot { | ||
id: string; | ||
resourceId: string; | ||
resourceKind: ResourceKind; | ||
archiveLocation?: string; | ||
exportPieces: ExportComponentSnapshot[]; | ||
} |
106 changes: 106 additions & 0 deletions
106
api/apps/api/src/modules/clone/export/domain/export/export.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { v4 } from 'uuid'; | ||
import { AggregateRoot } from '@nestjs/cqrs'; | ||
import { Either, left, right } from 'fp-ts/Either'; | ||
|
||
import { ResourceKind } from './resource.kind'; | ||
import { ExportId } from './export.id'; | ||
import { ResourceId } from './resource.id'; | ||
import { ArchiveLocation } from './archive-location'; | ||
|
||
import { ExportComponentRequested } from '../events/export-component-requested.event'; | ||
import { ExportComponentFinished } from '../events/export-component-finished.event'; | ||
import { ArchiveReady } from '../events/archive-ready.event'; | ||
|
||
import { ComponentLocation } from './export-component/component-location'; | ||
import { ExportComponent } from './export-component/export-component'; | ||
import { ComponentId } from './export-component/component.id'; | ||
import { ExportSnapshot } from './export.snapshot'; | ||
|
||
export const pieceNotFound = Symbol('export piece not found'); | ||
export const notReady = Symbol('some pieces of export are not yet ready'); | ||
|
||
export class Export extends AggregateRoot { | ||
private constructor( | ||
public readonly id: ExportId, | ||
public readonly resourceId: ResourceId, | ||
public readonly resourceKind: ResourceKind, | ||
public readonly pieces: ExportComponent[], | ||
private archiveLocation?: ArchiveLocation, | ||
) { | ||
super(); | ||
} | ||
|
||
static newOne( | ||
id: ResourceId, | ||
kind: ResourceKind, | ||
parts: ExportComponent[], | ||
): Export { | ||
const exportRequest = new Export(new ExportId(v4()), id, kind, parts); | ||
|
||
exportRequest.apply( | ||
parts | ||
.filter((part) => !part.isReady()) | ||
.map( | ||
(part) => | ||
new ExportComponentRequested( | ||
exportRequest.id, | ||
part.id, | ||
part.resourceId, | ||
part.piece, | ||
), | ||
), | ||
); | ||
|
||
return exportRequest; | ||
} | ||
|
||
completeComponent( | ||
id: ComponentId, | ||
pieceLocation: ComponentLocation, | ||
): Either<typeof pieceNotFound, true> { | ||
const piece = this.pieces.find((piece) => piece.id.equals(id)); | ||
if (!piece) { | ||
return left(pieceNotFound); | ||
} | ||
piece.finish(pieceLocation); | ||
|
||
if (this.#allPiecesReady()) { | ||
this.apply(new ExportComponentFinished(this.id)); | ||
} | ||
|
||
return right(true); | ||
} | ||
|
||
complete(archiveLocation: ArchiveLocation): Either<typeof notReady, true> { | ||
if (!this.#allPiecesReady()) { | ||
return left(notReady); | ||
} | ||
this.archiveLocation = archiveLocation; | ||
this.apply(new ArchiveReady(this.id, this.archiveLocation)); | ||
return right(true); | ||
} | ||
|
||
toSnapshot(): ExportSnapshot { | ||
return { | ||
id: this.id.value, | ||
resourceId: this.resourceId.value, | ||
resourceKind: this.resourceKind, | ||
exportPieces: this.pieces.map((piece) => piece.toSnapshot()), | ||
archiveLocation: this.archiveLocation?.value, | ||
}; | ||
} | ||
|
||
static fromSnapshot(snapshot: ExportSnapshot): Export { | ||
return new Export( | ||
new ExportId(snapshot.id), | ||
new ResourceId(snapshot.resourceId), | ||
snapshot.resourceKind, | ||
snapshot.exportPieces.map((piece) => ExportComponent.fromSnapshot(piece)), | ||
snapshot.archiveLocation | ||
? new ArchiveLocation(snapshot.archiveLocation) | ||
: undefined, | ||
); | ||
} | ||
|
||
#allPiecesReady = () => this.pieces.every((piece) => piece.isReady()); | ||
} |
3 changes: 3 additions & 0 deletions
3
api/apps/api/src/modules/clone/export/domain/export/resource.id.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>() {} |
4 changes: 4 additions & 0 deletions
4
api/apps/api/src/modules/clone/export/domain/export/resource.kind.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export enum ResourceKind { | ||
Project = 'project', | ||
Scenario = 'scenario', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
} |