jefer94/choco

View on GitHub
services/graphql-gateway/src/nats.ts

Summary

Maintainability
B
5 hrs
Test Coverage
import { connect, JSONCodec, Msg as NatsMsg } from 'nats'
import { Request } from './middlewares/authorization'

const connection = connect(process.env.BROKER ?
  { servers: process.env.BROKER } : {})

// const nc = connect(process.env.BROKER ?
//   { url: process.env.BROKER } : {})
// { payload: Payload.JSON, url: process.env.BROKER } : { payload: 'json' })

export enum activityRefs {
  addActivityLog = 'add activity log',
  addOnceActivity = 'add once activity',
  addOnceService = 'add once service',
  deleteService = 'delete service',
  fetchActivities = 'fetch activities',
  fetchAllActivities = 'fetch all activities'
}

export enum authenticatorRefs {
  checkToken = 'check token',
  generateToken = 'generate token',
  register = 'register',
  addScope = 'add scope',
  deleteScope = 'delete scope'
}

export enum cacheRefs {
  get = 'get',
  set = 'set',
  getObject = 'get object',
  setObject = 'set object'
}

export enum projectsRefs {
  addCode = 'add code',
  addProject = 'add project',
  addProjectPermission = 'add project permission',
  deleteCode = 'delete code',
  deleteProject = 'delete project',
  deleteProjectPermission = 'delete project permission',
  fetchAllProjects = 'fetch all projects',
  fetchOwnCodes = 'fetch own codes',
  fetchOwnProjects = 'fetch own projects',
  fetchShareCodes = 'fetch share codes',
  fetchShareProjects = 'fetch share projects',
  getCode = 'get code',
  getProject = 'get project',
  getProjectPermission = 'get project permission',
  updateCode = 'update code',
  updateProject = 'update project',
  updateProjectPermission = 'update project permission'
}

export enum statusRefs {
  success = 'Success',
  reject = 'Reject',
  notFound = 'Not found'
}

export enum serviceRefs {
  activity = 'activity',
  authenticator = 'authenticator',
  cache = 'cache',
  projects = 'projects',
}

type SubscribeRequest<T> = {
  readonly data?: T
  readonly error?: string
}

export async function SendCommand<T>(service: string, action: string, message: Msg):
  Promise<T> {
  const nc = await connection
  let msg: NatsMsg

  // eslint-disable-next-line functional/no-loop-statement
  while (true) {
    try {
      // eslint-disable-next-line no-await-in-loop
      msg = await nc.request(service, JSONCodec().encode({ type: action, ...message }))
      break
    }
    catch {}
  }

  const data: SubscribeRequest<T> = JSONCodec().decode(msg.data)

  if (data.error) throw new Error(data.error)
  return data.data
}

type Msg = Record<string, unknown>
type FetchMsg = (_: unknown, message: Msg, ctx: Request) => Promise<Msg>

type Input = {
  readonly id?: string
  readonly input?: Record<string, unknown>
}
type Mutate = (_: unknown, message: Input, ctx: Request) => Promise<Msg>

export function fetchMsg(service: string, project: string): FetchMsg {
  return async (_, message) => SendCommand(service, project, message)
}

export function fetchMsgWithAuth(service: string, project: string): FetchMsg {
  return async (_, message, ctx) => {
    if (ctx.auth?.user) {
      return SendCommand(service, project, message)
    }
    throw new Error(ctx.error)
  }
}

export function fetchMsgWithAuthUser(service: string, project: string): FetchMsg {
  return async (_, message, ctx) => {
    if (ctx.auth?.user) {
      console.log('====================================')
      console.log(SendCommand(service, project, message))
      console.log(ctx.auth?.user)
      return SendCommand(service, project, message)
    }
    throw new Error(ctx.error)
  }
}

export function mutate(service: string, project: string): Mutate {
  return async (_, message) => SendCommand(service, project, { ...message.input, id: message.id })
}

export function mutateWithAuth(service: string, project: string): Mutate {
  return async (_, message, ctx) => {
    if (ctx.auth?.user) {
      return SendCommand(service, project, { ...message.input, id: message.id })
    }
    throw new Error(ctx.error)
  }
}

export function mutateWithAuthUser(service: string, project: string): Mutate {
  return async (_, message, ctx) => {
    if (ctx.auth?.user) {
      return SendCommand(service, project, { ...message.input, id: message.id })
    }
    throw new Error(ctx.error)
  }
}