Skip to content

Commit

Permalink
revert: "feat(#131): hmr on commands and events files"
Browse files Browse the repository at this point in the history
This reverts commit 69f6887.
  • Loading branch information
barthofu committed Feb 20, 2024
1 parent 23b8acd commit 5ad11b4
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 116 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ Talking about features, here are some of the core features of the template:
This template is also developer friendly and follow strict design patterns to ease its maintenance:
- Written in **Typescript**
- Built around the **Dependency Injection** and **Singleton** patterns
- **HMR** on events and commands for a faster development
- Use of battle-tested **libraries** under the hood (*discordx* and *discord.js*)
- **Linting** and **formatting** thanks to a top-notch ESLint config
- Typesafe and validated **environment variables**
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"install:plugins": "installoop --rootDir=./build/plugins",
"type:check": "tsc --pretty --skipLibCheck --noEmit",
"start": "cross-env NODE_ENV=production node build/main.js",
"dev": "cross-env NODE_ENV=development nodemon --exec ts-node --transpile-only src/main.ts",
"dev": "cross-env NODE_ENV=development nodemon --exec node -r ts-node/register/transpile-only src/main.ts",
"dev:start": "cross-env NODE_ENV=production node -r ts-node/register/transpile-only src/main.ts",
"i18n": "typesafe-i18n",
"migration:create": "npx mikro-orm migration:create",
"migration:up": "npx mikro-orm migration:up",
Expand Down Expand Up @@ -128,8 +129,7 @@
},
"nodemonConfig": {
"ignore": [
"src/i18n/**/!(i18n-types.ts)",
"src/{events,commands}/**/*.{ts,js}"
"src/i18n/**/!(i18n-types.ts)"
]
}
}
105 changes: 15 additions & 90 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,40 @@
import 'reflect-metadata'
import 'dotenv/config'
import 'reflect-metadata'

import path from 'node:path'
import process from 'node:process'

import { resolve } from '@discordx/importer'
import { importx } from '@discordx/importer'
import { RequestContext } from '@mikro-orm/core'
import chalk from 'chalk'
import chokidar from 'chokidar'
import discordLogs from 'discord-logs'
import { Client, DIService, MetadataStorage, tsyringeDependencyRegistryEngine } from 'discordx'
import { Client, DIService, tsyringeDependencyRegistryEngine } from 'discordx'
import { container } from 'tsyringe'

import { Server } from '@/api/server'
import { apiConfig, generalConfig } from '@/configs'
import { checkEnvironmentVariables, env } from '@/env'
import { NoBotTokenError } from '@/errors'
import { Database, ErrorHandler, EventManager, ImagesUpload, Logger, PluginsManager, Store } from '@/services'
import { initDataTable, resolveDependency } from '@/utils/functions'

import { clientConfig } from './client'

// eslint-disable-next-line node/no-path-concat
const importPattern = `${__dirname}/{events,commands}/**/*.{ts,js}`

/**
* Import files
* @param path glob pattern
*/
async function loadFiles(path: string): Promise<void> {
const files = await resolve(path)
await Promise.all(
// eslint-disable-next-line array-callback-return
files.map((file) => {
const newFileName = file.replace('file://', '')
delete require.cache[newFileName]
import(newFileName)
})
)
}

/**
* Hot reload
*/
async function reload(client: Client) {
const store = await resolveDependency(Store)
store.set('botHasBeenReloaded', true)

const logger = await resolveDependency(Logger)
console.log('\n')
logger.startSpinner('Hot reloading...')

// remove events
client.removeEvents()

// cleanup
MetadataStorage.clear()
DIService.engine.clearAllServices()

// transfer store instance to the new container in order to keep the same states
container.registerInstance(Store, store)

// reload files
await loadFiles(importPattern)

// rebuild
await MetadataStorage.instance.build()
await client.initApplicationCommands()
client.initEvents()

// re-init services

// plugins
const pluginManager = await resolveDependency(PluginsManager)
await pluginManager.loadPlugins()

// database
const db = await resolveDependency(Database)
await db.initialize(false)
const importPattern = path.join(__dirname, '{events,commands}', '**', '*.{ts,js}')

logger.log(chalk.whiteBright('Hot reloaded'))
}

async function init() {
async function run() {
// init logger, plugins manager and error handler
const logger = await resolveDependency(Logger)

// check environment variables
checkEnvironmentVariables()

// init error handler
await resolveDependency(ErrorHandler)

// init plugins
const pluginManager = await resolveDependency(PluginsManager)

// load plugins and import translations
await pluginManager.loadPlugins()
await pluginManager.syncTranslations()

// strart spinner
// start spinner
console.log('\n')
logger.startSpinner('Starting...')

Expand All @@ -112,13 +51,11 @@ async function init() {
container.registerInstance(Client, client)

// import all the commands and events
await loadFiles(importPattern)
await importx(importPattern)
await pluginManager.importCommands()
await pluginManager.importEvents()

RequestContext.create(db.orm.em, async () => {
const watcher = chokidar.watch(importPattern)

// init the data table if it doesn't exist
await initDataTable()

Expand All @@ -129,31 +66,19 @@ async function init() {
await pluginManager.execMains()

// log in with the bot token
if (!env.BOT_TOKEN) {
if (!process.env.BOT_TOKEN) {
throw new NoBotTokenError()
}

client.login(env.BOT_TOKEN)
client.login(process.env.BOT_TOKEN)
.then(async () => {
if (env.NODE_ENV === 'development') {
// reload commands and events when a file changes
watcher.on('change', () => reload(client))

// reload commands and events when a file is added
watcher.on('add', () => reload(client))

// reload commands and events when a file is deleted
watcher.on('unlink', () => reload(client))
}

// start the api server
if (apiConfig.enabled) {
const server = await resolveDependency(Server)
await server.start()
}

// upload images to imgur if configured
if (env.IMGUR_CLIENT_ID && generalConfig.automaticUploadImagesToImgur) {
if (process.env.IMGUR_CLIENT_ID && generalConfig.automaticUploadImagesToImgur) {
const imagesUpload = await resolveDependency(ImagesUpload)
await imagesUpload.syncWithDatabase()
}
Expand All @@ -179,4 +104,4 @@ async function init() {
})
}

init()
run()
23 changes: 11 additions & 12 deletions src/services/Database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export class Database {

constructor(
@inject(delay(() => Logger)) private logger: Logger
) {}
) { }

async initialize(migrate = true) {
async initialize() {
const pluginsManager = await resolveDependency(PluginsManager)

// get config
Expand All @@ -33,18 +33,17 @@ export class Database {
// initialize the ORM using the configuration exported in `mikro-orm.config.ts`
this._orm = await MikroORM.init(config)

if (migrate) {
const migrator = this._orm.getMigrator()
const migrator = this._orm.getMigrator()

// create migration if no one is present in the migrations folder
const pendingMigrations = await migrator.getPendingMigrations()
const executedMigrations = await migrator.getExecutedMigrations()
if (pendingMigrations.length === 0 && executedMigrations.length === 0)
await migrator.createInitialMigration()

// migrate to the latest migration
await this._orm.getMigrator().up()
// create migration if no one is present in the migrations folder
const pendingMigrations = await migrator.getPendingMigrations()
const executedMigrations = await migrator.getExecutedMigrations()
if (pendingMigrations.length === 0 && executedMigrations.length === 0) {
await migrator.createInitialMigration()
}

// migrate to the latest migration
await this._orm.getMigrator().up()
}

async refreshConnection() {
Expand Down
14 changes: 6 additions & 8 deletions src/services/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { locales } from '@/i18n'
import { Pastebin, PluginsManager, Scheduler, Store } from '@/services'
import { fileOrDirectoryExists, formatDate, getTypeOfInteraction, numberAlign, oneLine, resolveAction, resolveChannel, resolveDependency, resolveGuild, resolveUser, validString } from '@/utils/functions'

const defaultConsole = { ...console }
@singleton()
export class Logger {

Expand All @@ -45,7 +44,7 @@ export class Logger {
}

private spinner = ora()

private defaultConsole: typeof console
private lastLogsTail: string[] = []

constructor(
Expand All @@ -55,11 +54,10 @@ export class Logger {
@inject(delay(() => Pastebin)) private pastebin: Pastebin,
@inject(delay(() => PluginsManager)) private pluginsManager: PluginsManager
) {
if (!this.store.get('botHasBeenReloaded')) {
console.info = (...args) => this.baseLog('info', ...args)
console.warn = (...args) => this.baseLog('warn', ...args)
console.error = (...args) => this.baseLog('error', ...args)
}
this.defaultConsole = { ...console }
console.info = (...args) => this.baseLog('info', ...args)
console.warn = (...args) => this.baseLog('warn', ...args)
console.error = (...args) => this.baseLog('error', ...args)
}

// =================================
Expand Down Expand Up @@ -99,7 +97,7 @@ export class Logger {
if (level === 'error')
templatedMessage = chalk.red(templatedMessage)

defaultConsole[level](templatedMessage)
this.defaultConsole[level](templatedMessage)

// save the last logs tail queue
if (this.lastLogsTail.length >= logsConfig.logTailMaxSize)
Expand Down
2 changes: 0 additions & 2 deletions src/services/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { apiConfig } from '@/configs'
interface State {

authorizedAPITokens: string[]
botHasBeenReloaded: boolean
ready: {
bot: boolean | null
api: boolean | null
Expand All @@ -16,7 +15,6 @@ interface State {
const initialState: State = {

authorizedAPITokens: [],
botHasBeenReloaded: false,
ready: {
bot: false,
api: apiConfig.enabled ? false : null,
Expand Down

0 comments on commit 5ad11b4

Please sign in to comment.