monorepo/services/mixins/db.mixin.ts

98 lines
2.7 KiB
TypeScript

'use strict'
import { existsSync } from 'fs'
import { sync } from 'mkdirp'
import { Context, Service, ServiceSchema } from 'moleculer'
import DbService from 'moleculer-db'
import MongooseAdapter from 'moleculer-db-adapter-mongoose'
import { Model, Document } from 'mongoose'
import { isNil } from 'ramda'
import { mongooseOptions } from '../util/mongoose.options'
export default class Connection implements Partial<ServiceSchema>, ThisType<Service> {
private cacheCleanEventName: string
private collection: string
private schema: Partial<ServiceSchema> & ThisType<Service>
public constructor(private model: Model<Document>) {
this.collection = model.modelName
this.cacheCleanEventName = `cache.clean.${this.collection}`
this.schema = {
mixins: [DbService],
model: this.model,
events: {
/**
* Subscribe to the cache clean event. If it's triggered
* clean the cache entries for this service.
*/
async [this.cacheCleanEventName](this: DbService.DbService) {
if (this.broker.cacher) {
await this.broker.cacher.clean(`${this.fullName}.*`)
}
}
},
methods: {
/**
* Send a cache clearing event when an entity changed.
* TODO: Granularise?
* @param {String} type
* @param {any} json
* @param {Context} ctx
*/
entityChanged: async (type: string, json: any, ctx: Context) => {
await ctx.broadcast(this.cacheCleanEventName)
},
},
async started() {
/*
* Check the count of items in the DB. If it's empty,
* Call the `seedDB` method of the service.
*/
if (this.seedDB) {
const count = await this.adapter.count()
if (count === 0) {
this.logger.info(`The '${this.collection}' collection is empty. Seeding the collection...`)
await this.seedDB()
this.logger.info('Seeding is done. Number of records:', await this.adapter.count())
}
}
},
}
}
public start () {
/* TODO: Consider using Model.validate on NEDB requests */
this.schema.adapter = this.makeAdapter({
uri: process.env.MONGO_URI,
isTest: !isNil(process.env.TEST) || process.env.NODE_ENV === 'test'
})
return this.schema
}
private ensureDevStorage () {
/* Create data folder */
if (!existsSync('./data')) {
sync('./data')
}
return `./data/${this.collection}.db`
}
private makeAdapter ({ uri, isTest }: {uri: string, isTest: boolean}) {
return uri ? new MongooseAdapter(uri, mongooseOptions) : new DbService.MemoryAdapter({
filename: isTest ? undefined : this.ensureDevStorage()
})
}
public get _collection(): string {
return this.collection
}
public set _collection(value: string) {
this.collection = value
}
}