From f21a4facce8fb6addc8641d5ae651babf3f59892 Mon Sep 17 00:00:00 2001 From: barthofu Date: Tue, 20 Feb 2024 19:49:29 +0000 Subject: [PATCH] revert: "feat(#131): hmr on `commands` and `events` files" This reverts commit 69f68873ac06b0bca2e6291dd17fb19f792e253f. --- package.json | 6 +-- src/main.ts | 105 ++++++--------------------------------- src/services/Database.ts | 23 ++++----- src/services/Logger.ts | 14 +++--- src/services/Store.ts | 2 - 5 files changed, 35 insertions(+), 115 deletions(-) diff --git a/package.json b/package.json index c6da7446..bfe3b252 100644 --- a/package.json +++ b/package.json @@ -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", @@ -128,8 +129,7 @@ }, "nodemonConfig": { "ignore": [ - "src/i18n/**/!(i18n-types.ts)", - "src/{events,commands}/**/*.{ts,js}" + "src/i18n/**/!(i18n-types.ts)" ] } } diff --git a/src/main.ts b/src/main.ts index 7e4b9145..9fda44bb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -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 { - 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...') @@ -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() @@ -129,23 +66,11 @@ 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) @@ -153,7 +78,7 @@ async function init() { } // 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() } @@ -179,4 +104,4 @@ async function init() { }) } -init() +run() diff --git a/src/services/Database.ts b/src/services/Database.ts index 399546e5..22dd1b1f 100644 --- a/src/services/Database.ts +++ b/src/services/Database.ts @@ -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 @@ -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() { diff --git a/src/services/Logger.ts b/src/services/Logger.ts index b3c7c0c8..5fe77d23 100644 --- a/src/services/Logger.ts +++ b/src/services/Logger.ts @@ -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 { @@ -45,7 +44,7 @@ export class Logger { } private spinner = ora() - + private defaultConsole: typeof console private lastLogsTail: string[] = [] constructor( @@ -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) } // ================================= @@ -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) diff --git a/src/services/Store.ts b/src/services/Store.ts index 23f56ab0..2bee5fe0 100644 --- a/src/services/Store.ts +++ b/src/services/Store.ts @@ -6,7 +6,6 @@ import { apiConfig } from '@/configs' interface State { authorizedAPITokens: string[] - botHasBeenReloaded: boolean ready: { bot: boolean | null api: boolean | null @@ -16,7 +15,6 @@ interface State { const initialState: State = { authorizedAPITokens: [], - botHasBeenReloaded: false, ready: { bot: false, api: apiConfig.enabled ? false : null,