diff --git a/server/src/entities/connection/connection.module.ts b/server/src/entities/connection/connection.module.ts index a128922e..dd2d94d6 100644 --- a/server/src/entities/connection/connection.module.ts +++ b/server/src/entities/connection/connection.module.ts @@ -1,6 +1,8 @@ import { Module } from "@nestjs/common"; import { MongooseModule } from "@nestjs/mongoose"; import { Connection, ConnectionSchema } from "./connection.model"; +import { ConnectionResolver } from "./connection.resolver"; +import { ConnectionService } from "./connection.service"; @Module({ imports: [ @@ -8,6 +10,7 @@ import { Connection, ConnectionSchema } from "./connection.model"; { name: Connection.name, schema: ConnectionSchema }, ]), ], - exports: [MongooseModule], + providers: [ConnectionService, ConnectionResolver], + exports: [MongooseModule, ConnectionService], }) export class ConnectionModule {} diff --git a/server/src/entities/connection/connection.resolver.ts b/server/src/entities/connection/connection.resolver.ts new file mode 100644 index 00000000..5865afc4 --- /dev/null +++ b/server/src/entities/connection/connection.resolver.ts @@ -0,0 +1,14 @@ +import { Args, Mutation, Resolver } from "@nestjs/graphql"; +import { Connection } from "./connection.model"; +import { ConnectionService } from "./connection.service"; +import { CreateConnection } from "./dto/create-connection.dto"; + +@Resolver() +export class ConnectionResolver { + constructor(private connectionService: ConnectionService) {} + + @Mutation(() => Connection) + async createConnection(@Args("connection") connection: CreateConnection) { + return this.connectionService.create(connection); + } +} diff --git a/server/src/entities/connection/connection.service.ts b/server/src/entities/connection/connection.service.ts new file mode 100644 index 00000000..cc298f16 --- /dev/null +++ b/server/src/entities/connection/connection.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from "@nestjs/common"; +import { InjectModel } from "@nestjs/mongoose"; +import { pick } from "lodash"; +import { Model } from "mongoose"; +import { Connection, ConnectionDocument } from "./connection.model"; +import { CreateConnection } from "./dto/create-connection.dto"; + +/** + * Main concern of this service is to maintain the two-way connection graph by + * keeping two mirrored connections in sync for each wormhole. This enables use + * of the `$graphLookup` aggregation stage to traverse the graph and build map + * trees. + */ +@Injectable() +export class ConnectionService { + constructor( + @InjectModel(Connection.name) private connectionModel: Model, + ) {} + + /** Create `Connection` and its linked reverse `Connection`. */ + async create(connection: CreateConnection): Promise { + const created = await this.connectionModel.create(connection); + + const duplicateFields = pick(created.toObject(), [ + "massStatus", + "eol", + "eolAt", + "type", + ]); + + const reverse = await this.connectionModel.create({ + ...duplicateFields, + from: created.to, + to: created.from, + k162: created.type && !created.k162, + reverse: created, + }); + + created.reverse = reverse; + await created.save(); + + return created.populate("reverse"); + } +} diff --git a/server/src/entities/connection/dto/create-connection.dto.ts b/server/src/entities/connection/dto/create-connection.dto.ts new file mode 100644 index 00000000..f23d1530 --- /dev/null +++ b/server/src/entities/connection/dto/create-connection.dto.ts @@ -0,0 +1,26 @@ +import { Field, InputType } from "@nestjs/graphql"; +import MassStatus from "../mass-status.enum"; + +@InputType() +export class CreateConnection { + @Field() + from: string; + + @Field({ nullable: true }) + to: string; + + @Field({ nullable: true }) + type: string; + + @Field() + k162: boolean; + + @Field() + eol: boolean; + + @Field((type) => Date, { nullable: true }) + eolAt?: Date; + + @Field((type) => MassStatus) + massStatus: MassStatus; +}