import { Collection , ComponentRequestTable , ConceptDb , ConceptServer , ConceptServerBuilder , Config , Context , getReturnFields } from '@deja-vu/concept-server' ; import { IResolvers } from 'graphql-tools' ; import * as _ from 'lodash' ; import { v4 as uuid } from 'uuid' ; import { AllocationDoc , Assignment , ConsumerOfResourceInput , CreateAllocationInput , DeleteResourceInput , EditConsumerOfResourceInput } from './schema' ; const componentRequestTable = { 'create-allocation' : ( extraInfo ) => `
    mutation CreateAllocation($input: CreateAllocationInput!) {
      createAllocation (input: $input) ${ getReturnFields ( extraInfo ) }
    }
  ` , 'delete-resource' : ( extraInfo ) => `
    mutation DeleteResource($input: DeleteResourceInput!) {
      deleteResource (input: $input) ${ getReturnFields ( extraInfo ) }
    }
  ` , 'edit-consumer' : ( extraInfo ) => { switch ( extraInfo . action ) { case 'edit' : return `
          mutation EditConsumerOfResource(
            $input: EditConsumerOfResourceInput!) {
            editConsumerOfResource (input: $input) ${ getReturnFields ( extraInfo ) }
          }
        ` ; case 'consumer' : return `
          query ConsumerOfResource($input: ConsumerOfResourceInput!) {
            consumerOfResource(input: $input) ${ getReturnFields ( extraInfo ) }
          }
        ` ; default : throw new Error ( 'Need to specify extraInfo.action' ) ; } } , 'show-consumer' : ( extraInfo ) => `
    query ConsumerOfResource($input: ConsumerOfResourceInput!) {
      consumerOfResource(input: $input) ${ getReturnFields ( extraInfo ) }
    }
  ` } ; function resolvers ( db , _config ) { const allocations = db . collection ( 'allocations' ) ; return { Query : { allocation : async ( _root , { id } ) => allocations . findOne ( { id : id } ) , consumerOfResource : async ( _root , { input : { resourceId , allocationId } } ) => { const alloc = await allocations . findOne ( { id : allocationId , 'assignments.resourceId' : resourceId } , { projection : { 'assignments.$.consumerId' : 1 } } ) ; return alloc . assignments [ 0 ] . consumerId ; } } , Allocation : { id : ( allocation ) => allocation . id , resourceIds : ( allocation ) => allocation . resourceIds , consumerIds : ( allocation ) => allocation . consumerIds } , Mutation : { editConsumerOfResource : async ( _root , { input : { resourceId , allocationId , newConsumerId } } , context ) => { const updateOp = { $set : { 'assignments.$.consumerId' : newConsumerId } } ; const allocFilter = { id : allocationId , 'assignments.resourceId' : resourceId } ; return await allocations . updateOne ( context , allocFilter , updateOp ) ; } , createAllocation : async ( _root , { input : { id , resourceIds , consumerIds } } , context ) => { const assignments = [ ] ; if ( ! _ . isEmpty ( consumerIds ) ) { let currentConsumerIndex = 0 ; for ( const resourceId of resourceIds ) { const consumerId = consumerIds [ currentConsumerIndex ] ; console . log ( `Allocating ${ resourceId } to ${ consumerId }` ) ; assignments . push ( { resourceId : resourceId , consumerId : consumerId } ) ; currentConsumerIndex = ( currentConsumerIndex + 1 ) % consumerIds . length ; } } const newAllocation = { id : id ? id : uuid ( ) , resourceIds : resourceIds , consumerIds : consumerIds , assignments : assignments } ; return await allocations . insertOne ( context , newAllocation ) ; } , deleteResource : async ( _root , { input : { resourceId , allocationId } } , context ) => { const updateOp = { $pull : { resourceIds : resourceId , assignments : { resourceId : resourceId } } } ; const allocationIdFilter = { id : allocationId } ; return await allocations . updateOne ( context , allocationIdFilter , updateOp ) ; } } } ; } const allocatorConcept = new ConceptServerBuilder ( 'allocator' ) . initDb ( ( db , _config ) : Promise < any > => { const allocations = db . collection ( 'allocations' ) ; return Promise . all ( [ allocations . createIndex ( { id : 1 } , { unique : true } ) , allocations . createIndex ( { id : 1 , 'assignments.resourceId' : 1 } , { unique : true } ) ] ) ; } ) . componentRequestTable ( componentRequestTable ) . resolvers ( resolvers ) . build ( ) ; allocatorConcept . start ( ) ;