prisma-eventify
Version:
Prisma-Eventify is a crucial module designed to facilitate seamless communication between the ORM (Prisma) and the HTTP server (GraphQL | Rest) by employing event-driven development principles.
91 lines (82 loc) • 3.42 kB
text/typescript
import path from 'path'
import { EventBus } from 'ts-bus'
import { EventService } from '../services/eventify.service'
import { PrismaService } from './../services/prisma.service'
import { PrismaAPI } from '../types'
import { Prisma, type PrismaClient } from '@prisma/client'
import { ConfigService } from '../services/config.service'
import { DMMF } from '@prisma/generator-helper'
import { EventifyConfig } from '../types/config'
/**
* @description ** BusHandler **
* Wrapper class of ts-bus EventBus to allow Eventify automation.
* */
export class BusHandler {
private events = {}
private config: Record<string, () => {}>
constructor(
config: EventifyConfig,
schema = Prisma.dmmf as DMMF.Document,
private prismaService = new PrismaService(schema),
private configService = new ConfigService(config),
private eventService = new EventService(),
public bus = new EventBus()
) {}
/**
* @description Imports and subscribes Eventify autogenerated events.
* @returns {Promise<boolean>} subscription status.
*/
public async subscribeConfigEvents(): Promise<boolean> {
try {
/* Dont do this at home :D */
this.events = await import(process.cwd() + '/eventify/events')
this.config = (await import(process.cwd() + '/eventify.config'))?.config
if (!Object.keys(this.events).length)
throw new Error('An error occurred while trying to retrieve generated events.')
if (!Object.keys(this.config).length)
throw new Error('An error occurred while trying to retrieve eventify.config.ts.')
Object.entries(this.config).forEach(([event, callback]) => this.bus.subscribe(this.events[event], callback))
return true
} catch (err) {
console.error(err)
return false
}
}
/**
* @description Given an event name:
* - retrieves that event within auto generated event declarations.
* - retrieves all sub-events (ex. user.email) of the given event (ex. user).
* - publishes every retrieved event.
* @param {string} event target event name.
* @param meta Event metadata injected into the event handler.
* @returns { boolean } publishment status.
*/
public publishEvent(event: string, meta: { prisma: PrismaClient; [x: string]: any }): boolean {
try {
if (!this.events?.[event]?.eventType) return false
const { model, field, hook, method } = this.eventService.destructureEventIdentifiers({
dotCase: this.events[event].eventType,
})
if (!this.configService.modelAllowed(model)) return false
if (model && !field && method && [PrismaAPI.create, PrismaAPI.update, PrismaAPI.delete].includes(method)) {
/* publish also model fields events */
const fields = this.prismaService.getModelFields(model)
fields.forEach(({ name: field }) => {
if (!this.configService.fieldAllowed(model, field)) return
const fieldEvent = this.eventService.composeEventIdentifiers({
model,
field,
hook,
method,
}).camelCase
if (this.events[fieldEvent]) this.bus.publish(this.events[fieldEvent](), meta)
})
}
this.bus.publish(this.events[event](), meta)
return true
} catch (err) {
console.error(err)
return false
}
}
}