UNPKG

meocord

Version:

MeoCord is a lightweight and modular framework for building scalable Discord bots using TypeScript and Discord.js. It simplifies bot development with an extensible architecture, TypeScript-first approach, and powerful CLI tools.

146 lines (130 loc) 4.87 kB
/* * MeoCord Framework * Copyright (C) 2025 Ukasyah Rahmatullah Zada * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ import path from 'path' import NodeExternals from 'webpack-node-externals' import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin' import TerserPlugin from 'terser-webpack-plugin' import { loadMeoCordConfig } from './dist/util/meocord-config-loader.util.js' import { prepareModifiedTsConfig } from './dist/util/tsconfig.util.js' const CWD = process.cwd() const IS_PRODUCTION = process.env.NODE_ENV === 'production' const SRC_DIR = path.resolve(CWD, 'src') const DIST_DIR = path.resolve(CWD, 'dist') const meocordConfig = loadMeoCordConfig() const tsConfigPath = prepareModifiedTsConfig() const baseRules = [ { test: /\.ts$/, loader: 'ts-loader', options: { configFile: tsConfigPath, transpileOnly: true, }, exclude: /node_modules/, }, ] /** * Merges two arrays returning unique elements */ const mergeUnique = (base = [], additions = []) => Array.from(new Set([...base, ...additions])) /** * Creates webpack configuration with framework defaults */ const createWebpackConfig = (overrides = {}) => { const baseConfig = { mode: overrides.mode ?? (IS_PRODUCTION ? 'production' : 'development'), entry: overrides.entry ?? path.resolve(SRC_DIR, 'main.ts'), target: 'node', externals: mergeUnique([NodeExternals({ importType: 'module' })], overrides.externals), module: { ...overrides.module, rules: mergeUnique(baseRules, overrides.module?.rules), }, resolve: { ...overrides.resolve, extensions: mergeUnique(['.ts', '.js'], overrides.resolve?.extensions), plugins: mergeUnique([new TsconfigPathsPlugin({ configFile: tsConfigPath })], overrides.resolve?.plugins), }, output: { filename: 'main.js', path: DIST_DIR, publicPath: path.join(process.cwd(), 'dist/'), library: { type: 'module' }, ...overrides.output, }, experiments: { outputModule: true, ...overrides.experiments, }, stats: overrides.stats ?? (IS_PRODUCTION ? 'normal' : 'errors-warnings'), devtool: overrides.devtool ?? (IS_PRODUCTION ? 'source-map' : 'eval-source-map'), performance: { hints: overrides.performance?.hints ?? (IS_PRODUCTION ? 'warning' : false), ...overrides.performance, }, ...overrides, optimization: { ...overrides.optimization, minimize: overrides.optimization?.minimize ?? IS_PRODUCTION, minimizer: [], }, } const finalMinimizerArray = [] const shouldMinimize = baseConfig.optimization.minimize if (shouldMinimize) { const userProvidedMinimizers = overrides.optimization?.minimizer let lastTerserInstance = null const otherMinimizers = [] if (Array.isArray(userProvidedMinimizers)) { for (let i = userProvidedMinimizers.length - 1; i >= 0; i--) { const minimizer = userProvidedMinimizers[i] if (minimizer?.constructor?.name === 'TerserPlugin') { if (!lastTerserInstance) { lastTerserInstance = minimizer } } else if (minimizer) { otherMinimizers.unshift(minimizer) } } } finalMinimizerArray.push(...otherMinimizers) let terserPluginToUse if (lastTerserInstance) { terserPluginToUse = new TerserPlugin({ test: lastTerserInstance.options?.test, include: lastTerserInstance.options?.include, exclude: lastTerserInstance.options?.exclude, extractComments: lastTerserInstance.options?.extractComments, parallel: lastTerserInstance.options?.parallel, minify: lastTerserInstance.options?.minify, terserOptions: { ...(lastTerserInstance.options?.terserOptions || {}), keep_classnames: true, }, }) } else { terserPluginToUse = new TerserPlugin({ terserOptions: { keep_classnames: true } }) } finalMinimizerArray.push(terserPluginToUse) } baseConfig.optimization.minimizer = finalMinimizerArray return baseConfig } const initialConfig = createWebpackConfig() const userModifiedConfig = meocordConfig?.webpack?.(initialConfig) export default createWebpackConfig(userModifiedConfig ?? {})