-
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: fake archive reader adapter * feat: initial archive reader implementation * fix: typo and error handling * feat: added clone pieces data * ref: clone pieces relative paths * feat: import resource pieces * fix: export resource pieces adapter * fix: export resource pieces adapter * fix: removes testing controller * ref: zip file extractor ResourceId constructor validation * fix: ResourceKind validation in archive-reader adapter * fix: import resource pieces adapter * fix: wrong import Co-authored-by: Ángel Higuera Vaquero <angelhiguera@acidtango.com>
- Loading branch information
Showing
34 changed files
with
583 additions
and
286 deletions.
There are no files selected for viewing
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
66 changes: 66 additions & 0 deletions
66
api/apps/api/src/modules/clone/export/adapters/export-resource-pieces.adapter.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,66 @@ | ||
import { ClonePiece, ResourceId, ResourceKind } from '@marxan/cloning/domain'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
import { Repository } from 'typeorm'; | ||
import { Scenario } from '../../../scenarios/scenario.api.entity'; | ||
import { ExportResourcePieces } from '../application/export-resource-pieces.port'; | ||
import { ExportComponent } from '../domain'; | ||
|
||
@Injectable() | ||
export class ExportResourcePiecesAdapter implements ExportResourcePieces { | ||
private resolverMapping: Record< | ||
ResourceKind, | ||
(id: ResourceId, kind: ResourceKind) => Promise<ExportComponent[]> | ||
> = { | ||
project: this.resolveForProject.bind(this), | ||
scenario: this.resolveForScenario.bind(this), | ||
}; | ||
|
||
constructor( | ||
@InjectRepository(Scenario) | ||
private readonly scenarioRepository: Repository<Scenario>, | ||
) {} | ||
|
||
resolveFor(id: ResourceId, kind: ResourceKind): Promise<ExportComponent[]> { | ||
return this.resolverMapping[kind](id, kind); | ||
} | ||
|
||
private async resolveForProject( | ||
id: ResourceId, | ||
kind: ResourceKind, | ||
): Promise<ExportComponent[]> { | ||
const scenarios = await this.scenarioRepository.find({ | ||
where: { projectId: id.value }, | ||
}); | ||
|
||
const scenarioPieces = await Promise.all( | ||
scenarios.map((scenario) => | ||
this.resolveForScenario(new ResourceId(scenario.id), kind), | ||
), | ||
); | ||
|
||
return [ | ||
ExportComponent.newOne(id, ClonePiece.ProjectMetadata), | ||
ExportComponent.newOne(id, ClonePiece.ExportConfig), | ||
ExportComponent.newOne(id, ClonePiece.PlanningAreaCustom), | ||
ExportComponent.newOne(id, ClonePiece.PlanningAreaGAdm), | ||
ExportComponent.newOne(id, ClonePiece.PlanningAreaGridCustom), | ||
...scenarioPieces.flat(), | ||
]; | ||
} | ||
|
||
private async resolveForScenario( | ||
id: ResourceId, | ||
kind: ResourceKind, | ||
): Promise<ExportComponent[]> { | ||
const pieces: ExportComponent[] = [ | ||
ExportComponent.newOne(id, ClonePiece.ScenarioMetadata), | ||
]; | ||
|
||
if (kind === ResourceKind.Scenario) { | ||
pieces.push(ExportComponent.newOne(id, ClonePiece.ExportConfig)); | ||
} | ||
|
||
return pieces; | ||
} | ||
} |
44 changes: 0 additions & 44 deletions
44
api/apps/api/src/modules/clone/export/adapters/resource-pieces.adapter.ts
This file was deleted.
Oops, something went wrong.
46 changes: 0 additions & 46 deletions
46
.../api/src/modules/clone/export/adapters/resource-pieces/project-resource-pieces.adapter.ts
This file was deleted.
Oops, something went wrong.
24 changes: 0 additions & 24 deletions
24
...api/src/modules/clone/export/adapters/resource-pieces/scenario-resource-pieces.adapter.ts
This file was deleted.
Oops, something went wrong.
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
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
2 changes: 1 addition & 1 deletion
2
...xport/application/resource-pieces.port.ts → ...pplication/export-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
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
56 changes: 56 additions & 0 deletions
56
api/apps/api/src/modules/clone/import/adapters/archive-reader.adapter.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,56 @@ | ||
import { | ||
ArchiveLocation, | ||
ClonePiece, | ||
ResourceId, | ||
ResourceKind, | ||
} from '@marxan/cloning/domain'; | ||
import { ClonePieceRelativePaths } from '@marxan/cloning/infrastructure/clone-piece-data'; | ||
import { FileRepository } from '@marxan/files-repository'; | ||
import { fileNotFound } from '@marxan/files-repository/file.repository'; | ||
import { extractFile } from '@marxan/utils'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { Either, isLeft, left, right } from 'fp-ts/lib/Either'; | ||
import { | ||
archiveCorrupted, | ||
ArchiveReader, | ||
Failure, | ||
invalidFiles, | ||
} from '../application/archive-reader.port'; | ||
import { ImportResourcePieces } from '../application/import-resource-pieces.port'; | ||
import { Import } from '../domain'; | ||
|
||
@Injectable() | ||
export class ArchiveReaderAdapter implements ArchiveReader { | ||
constructor( | ||
private readonly fileRepository: FileRepository, | ||
private readonly importResourcePieces: ImportResourcePieces, | ||
) {} | ||
|
||
async get(location: ArchiveLocation): Promise<Either<Failure, Import>> { | ||
const readableOrError = await this.fileRepository.get(location.value); | ||
if (isLeft(readableOrError)) return left(fileNotFound); | ||
|
||
const exportConfigOrError = await extractFile( | ||
readableOrError.right, | ||
new RegExp(ClonePieceRelativePaths[ClonePiece.ExportConfig].config), | ||
); | ||
if (isLeft(exportConfigOrError)) return left(archiveCorrupted); | ||
const exportConfig = JSON.parse(exportConfigOrError.right); | ||
|
||
const resourceId = new ResourceId(exportConfig.resourceId); | ||
const resourceKind = exportConfig.resourceKind; | ||
|
||
const validResourceKind = Object.values(ResourceKind).includes( | ||
resourceKind, | ||
); | ||
if (!validResourceKind) return left(invalidFiles); | ||
|
||
const pieces = await this.importResourcePieces.resolveFor( | ||
resourceId, | ||
resourceKind, | ||
location, | ||
); | ||
|
||
return right(Import.newOne(resourceId, resourceKind, location, pieces)); | ||
} | ||
} |
Oops, something went wrong.