meocord 3.2.2 → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +160 -28
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/cjs/_shared/{controller.decorator-eT0oHb8D.cjs → controller.decorator-9nIxOp9y.cjs} +1 -1
  5. package/dist/cjs/_shared/{metadata-key.enum-DITxfZlw.cjs → metadata-key.enum-aABGdodb.cjs} +0 -4
  6. package/dist/cjs/_shared/{theme-EmG1ZEwV.cjs → theme-BXdSoifk.cjs} +4 -15
  7. package/dist/cjs/common/index.cjs +1 -5
  8. package/dist/cjs/core/index.cjs +67 -5
  9. package/dist/cjs/decorator/index.cjs +2 -2
  10. package/dist/cjs/enum/index.cjs +1 -1
  11. package/dist/cjs/testing/index.cjs +2 -6
  12. package/dist/esm/bin/app-template/meocord.config.ts.template +8 -13
  13. package/dist/esm/bin/app-template/package.json.template +12 -12
  14. package/dist/esm/bin/app-template/vitest.config.ts.template +6 -2
  15. package/dist/esm/bin/builder-template/builder/context-menu.builder.template +2 -2
  16. package/dist/esm/bin/builder-template/builder/primary-entry-point.builder.template +2 -2
  17. package/dist/esm/bin/builder-template/builder/slash.builder.template +2 -2
  18. package/dist/esm/bin/builder-template/controller/autocomplete.controller.template +4 -3
  19. package/dist/esm/bin/builder-template/controller/context-menu.controller.template +2 -2
  20. package/dist/esm/bin/builder-template/controller/primary-entry-point.controller.template +2 -2
  21. package/dist/esm/bin/builder-template/controller/slash.controller.template +2 -2
  22. package/dist/esm/bin/helper/controller-generator.helper.js +43 -26
  23. package/dist/esm/bin/helper/guard-generator.helper.js +8 -2
  24. package/dist/esm/bin/helper/service-generator.helper.js +8 -2
  25. package/dist/esm/bin/meocord.js +160 -140
  26. package/dist/esm/build/native-addons.js +235 -0
  27. package/dist/esm/build/rsbuild-config.js +169 -0
  28. package/dist/esm/common/decorator.js +0 -4
  29. package/dist/esm/common/theme.js +1 -5
  30. package/dist/esm/core/meocord-factory.js +4 -0
  31. package/dist/esm/enum/controller.enum.js +1 -5
  32. package/dist/esm/enum/metadata-key.enum.js +0 -4
  33. package/dist/esm/package.json.js +1 -1
  34. package/dist/esm/testing/mock-fn.js +1 -5
  35. package/dist/esm/util/generator-cli.util.js +54 -10
  36. package/dist/esm/util/json.util.js +0 -4
  37. package/dist/esm/util/meocord-config-loader.util.js +14 -2
  38. package/dist/esm/util/platform.util.js +66 -0
  39. package/dist/esm/util/runtime.util.js +20 -7
  40. package/dist/esm/util/tsconfig.util.js +1 -1
  41. package/dist/esm/util/wait.util.js +1 -5
  42. package/dist/types/common/index.d.ts +0 -16
  43. package/dist/types/core/index.d.ts +0 -12
  44. package/dist/types/decorator/index.d.ts +1 -31
  45. package/dist/types/enum/index.d.ts +0 -5
  46. package/dist/types/interface/index.d.ts +46 -57
  47. package/dist/types/testing/index.d.ts +4 -19
  48. package/meocord.eslint.cjs +0 -6
  49. package/meocord.eslint.d.ts +0 -6
  50. package/meocord.eslint.mjs +0 -6
  51. package/package.json +19 -23
  52. package/webpack.config.js +0 -147
@@ -1,13 +1,8 @@
1
- import { SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder, ContextMenuCommandBuilder, RESTPostAPIPrimaryEntryPointApplicationCommandJSONBody, ChatInputCommandInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, PrimaryEntryPointCommandInteraction, ButtonInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, RoleSelectMenuInteraction, MentionableSelectMenuInteraction, ChannelSelectMenuInteraction, ModalSubmitInteraction, User, PartialUser, BaseInteraction, Message, MessageReaction } from 'discord.js';
2
- import { Configuration } from 'webpack';
1
+ import { SlashCommandBuilder, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandsOnlyBuilder, ContextMenuCommandBuilder, RESTPostAPIPrimaryEntryPointApplicationCommandJSONBody, ChatInputCommandInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, PrimaryEntryPointCommandInteraction, ButtonInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, RoleSelectMenuInteraction, MentionableSelectMenuInteraction, ChannelSelectMenuInteraction, ModalSubmitInteraction, User, PartialUser, BaseInteraction, Message, MessageReaction } from 'discord.js';
2
+ import { RsbuildConfig } from '@rsbuild/core';
3
+ export { RsbuildConfig } from '@rsbuild/core';
3
4
  import { CommandType, ReactionHandlerAction } from '../enum/index.js';
4
5
 
5
- /**
6
- * MeoCord Framework
7
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
8
- * SPDX-License-Identifier: MIT
9
- */
10
-
11
6
  /**
12
7
  * The command types that are registered with Discord, and so need a builder.
13
8
  *
@@ -28,11 +23,16 @@ type PrimaryEntryPointCommandData = RESTPostAPIPrimaryEntryPointApplicationComma
28
23
  /**
29
24
  * The payload `build()` returns for a given command type.
30
25
  *
26
+ * A slash command's builder changes type as it is chained: adding an option narrows
27
+ * `SlashCommandBuilder` to `SlashCommandOptionsOnlyBuilder`, adding a subcommand to
28
+ * `SlashCommandSubcommandsOnlyBuilder`. All three are accepted; the options form is the most
29
+ * common builder there is, one command with an option.
30
+ *
31
31
  * `PRIMARY_ENTRY_POINT` yields a raw REST body rather than a builder because
32
32
  * `@discordjs/builders` ships none for it; `ApplicationCommandManager#set` accepts the
33
33
  * JSON body directly, so nothing is lost.
34
34
  */
35
- type CommandBuildResult<T extends BuildableCommandType> = T extends CommandType.SLASH ? SlashCommandBuilder | SlashCommandSubcommandsOnlyBuilder : T extends CommandType.CONTEXT_MENU ? ContextMenuCommandBuilder : T extends CommandType.PRIMARY_ENTRY_POINT ? PrimaryEntryPointCommandData : never;
35
+ type CommandBuildResult<T extends BuildableCommandType> = T extends CommandType.SLASH ? SlashCommandBuilder | SlashCommandOptionsOnlyBuilder | SlashCommandSubcommandsOnlyBuilder : T extends CommandType.CONTEXT_MENU ? ContextMenuCommandBuilder : T extends CommandType.PRIMARY_ENTRY_POINT ? PrimaryEntryPointCommandData : never;
36
36
  /**
37
37
  * Base interface for a command builder.
38
38
  */
@@ -88,12 +88,6 @@ interface ComponentInteractionMap {
88
88
  }
89
89
  type CommandInteractionType<CBC extends BuildableCommandType, T extends CommandBuilderConstructor<CBC> | CommandType> = T extends CommandBuilderConstructor<CommandType.SLASH> ? ChatInputCommandInteraction : T extends CommandBuilderConstructor<CommandType.CONTEXT_MENU> ? UserContextMenuCommandInteraction | MessageContextMenuCommandInteraction : T extends CommandBuilderConstructor<CommandType.PRIMARY_ENTRY_POINT> ? PrimaryEntryPointCommandInteraction : T extends keyof ComponentInteractionMap ? ComponentInteractionMap[T] : never;
90
90
 
91
- /**
92
- * MeoCord Framework
93
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
94
- * SPDX-License-Identifier: MIT
95
- */
96
-
97
91
  /**
98
92
  * Interface for Guard classes.
99
93
  * Guards are used to handle permission checks before executing a method.
@@ -119,45 +113,10 @@ interface ReactionHandlerOptions {
119
113
  /** The action performed on the reaction, such as adding or removing it. */
120
114
  action: ReactionHandlerAction;
121
115
  }
122
- /**
123
- * Interface representing the Webpack configuration for the MeoCord framework.
124
- * This interface extends the base Webpack Configuration and provides stricter type definitions
125
- * with additional required properties to ensure a complete and valid Webpack setup.
126
- */
127
- interface MeoCordWebpackConfig extends Omit<Configuration, 'externals'> {
128
- /** Defines the mode of the Webpack build process (e.g., 'development' or 'production'). */
129
- mode: NonNullable<Configuration['mode']>;
130
- /** The entry point file path(s) for the application. Represents the starting point(s) of the build. */
131
- entry: string;
132
- /** Configuration for build optimization settings, such as code splitting and minimization. */
133
- optimization: NonNullable<Configuration['optimization']>;
134
- /**
135
- * Specifies external dependencies to exclude from the output bundle.
136
- * Can be used to exclude libraries from being bundled, like `node_modules`.
137
- */
138
- externals: Extract<NonNullable<Configuration['externals']>, any[]>;
139
- /**
140
- * Rules and configurations for handling module files during the build process.
141
- * Includes loaders for processing various file types.
142
- */
143
- module: NonNullable<Configuration['module']>;
144
- /**
145
- * Configuration for module resolution, including resolving extensions and alias paths.
146
- * Determines how imported files are resolved.
147
- */
148
- resolve: NonNullable<Configuration['resolve']>;
149
- /**
150
- * Specifies output settings for the Webpack build, excluding path, publicPath, and filename.
151
- * Defines properties like asset management and global settings.
152
- */
153
- output: Omit<NonNullable<Configuration['output']>, 'path' | 'publicPath' | 'filename'>;
154
- /** Configures the stats object to control the output of build process logs. */
155
- stats: NonNullable<Configuration['stats']>;
156
- }
157
116
  /**
158
117
  * Configuration interface for the MeoCord application.
159
118
  * This interface defines optional configurations for the application, including
160
- * metadata, authentication tokens, and Webpack configuration overrides.
119
+ * metadata, authentication tokens, and bundler configuration overrides.
161
120
  */
162
121
  interface MeoCordConfig {
163
122
  /**
@@ -170,12 +129,42 @@ interface MeoCordConfig {
170
129
  */
171
130
  discordToken: string;
172
131
  /**
173
- * Function to customize the Webpack configuration.
174
- * Allows overriding and extending the default Webpack setup for the application.
175
- * @param config - A callback function to modify the existing Webpack configuration.
176
- * @returns A modified Webpack configuration or `undefined` if no customization is needed.
132
+ * Put everything the bot needs inside `dist`, so it runs without `node_modules`.
133
+ *
134
+ * Off by default, matching how the build has always behaved: dependencies stay runtime imports,
135
+ * so `dist` needs `node_modules` beside it. Turn it on to deploy `dist` alone.
136
+ *
137
+ * Plain JavaScript is bundled into `main.js`. Native addons -- packages shipping a compiled
138
+ * `.node` binary, like `sharp` -- are found while building, kept out of the bundle, and copied
139
+ * with their platform binary into `dist/node_modules`. Such a build only runs on the platform it
140
+ * was built on; it records that platform, and refuses to start anywhere else.
141
+ */
142
+ bundleDependencies?: boolean;
143
+ /**
144
+ * Modules to keep out of the bundle.
145
+ *
146
+ * Native addons need not be listed; they are found and packed on their own. Anything listed here
147
+ * as a package name is also copied into `dist/node_modules` when {@link bundleDependencies} is on.
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * // Loaded by the runtime rather than bundled, e.g. for instrumentation.
152
+ * externals: ['@opentelemetry/api']
153
+ * ```
154
+ */
155
+ externals?: (string | RegExp)[];
156
+ /**
157
+ * Function to customize the Rsbuild configuration.
158
+ * Allows overriding and extending the default bundler setup for the application.
159
+ *
160
+ * Rsbuild handles images, fonts, svg and media itself, so they need no rules;
161
+ * `output.distPath` controls where they land. Raw bundler rules go through `tools.rspack`,
162
+ * which takes a webpack-shaped config.
163
+ *
164
+ * @param config - The configuration to modify.
165
+ * @returns A modified configuration, or `undefined` to keep the default.
177
166
  */
178
- webpack?: (config: MeoCordWebpackConfig) => MeoCordWebpackConfig | undefined;
167
+ rsbuild?: (config: RsbuildConfig) => RsbuildConfig | undefined;
179
168
  }
180
169
 
181
- export type { AutocompleteMetadata, BuildableCommandType, CommandBuildResult, CommandBuilderBase, CommandBuilderConstructor, CommandInteractionType, CommandMetadata, GuardInterface, MeoCordConfig, MeoCordWebpackConfig, ReactionHandlerOptions };
170
+ export type { AutocompleteMetadata, BuildableCommandType, CommandBuildResult, CommandBuilderBase, CommandBuilderConstructor, CommandInteractionType, CommandMetadata, GuardInterface, MeoCordConfig, ReactionHandlerOptions };
@@ -1,15 +1,9 @@
1
1
  import { ServiceIdentifier, Container } from 'inversify';
2
2
  import { GuardInterface } from '../interface/index.js';
3
3
  import { CacheType, CommandInteractionOptionResolver, Channel, Client, Guild, Message, User } from 'discord.js';
4
- import 'webpack';
4
+ import '@rsbuild/core';
5
5
  import '../controller.enum-DYfhYaat.js';
6
6
 
7
- /**
8
- * MeoCord Framework
9
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
10
- * SPDX-License-Identifier: MIT
11
- */
12
-
13
7
  interface ValueProvider<T = any> {
14
8
  provide: ServiceIdentifier<T>;
15
9
  useValue: T;
@@ -76,11 +70,6 @@ declare class MeoCordTestingModule {
76
70
  static create(options: TestingModuleOptions): TestingModuleBuilder;
77
71
  }
78
72
 
79
- /**
80
- * MeoCord Framework
81
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
82
- * SPDX-License-Identifier: MIT
83
- */
84
73
  interface MockResult<T = unknown> {
85
74
  type: 'return' | 'throw';
86
75
  value: T;
@@ -140,12 +129,6 @@ declare function isMockFunction(fn: unknown): fn is MockInstance;
140
129
  */
141
130
  declare function createMockFn<T extends (...args: any[]) => any = (...args: any[]) => any>(impl?: T): MockedFunction<T>;
142
131
 
143
- /**
144
- * MeoCord Framework
145
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
146
- * SPDX-License-Identifier: MIT
147
- */
148
-
149
132
  /**
150
133
  * Recursively transforms all methods of T into MockedFunction and all
151
134
  * nested objects into DeepMocked. Depth cap at 5 prevents infinite recursion
@@ -273,7 +256,9 @@ declare function createMockGuild(): DeepMocked<Guild>;
273
256
  * - `ThreadChannel`: `messages`, `members`
274
257
  */
275
258
  declare function createMockChannel<T extends Channel>(Class: InteractionClass<T>): DeepMocked<T>;
276
- declare function createMockMessage(): DeepMocked<Message>;
259
+ declare function createMockMessage(): DeepMocked<Message> & {
260
+ deleted: boolean;
261
+ };
277
262
  interface ChatInputOptions {
278
263
  subcommandGroup?: string | null;
279
264
  subcommand?: string | null;
@@ -1,9 +1,3 @@
1
- /**
2
- * MeoCord Framework
3
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
4
- * SPDX-License-Identifier: MIT
5
- */
6
-
7
1
  const { importX } = require('eslint-plugin-import-x')
8
2
  const globals = require('globals')
9
3
  const tsParser = require('@typescript-eslint/parser')
@@ -1,9 +1,3 @@
1
- /**
2
- * MeoCord Framework
3
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
4
- * SPDX-License-Identifier: MIT
5
- */
6
-
7
1
  import type { Linter } from 'eslint'
8
2
 
9
3
  /**
@@ -1,9 +1,3 @@
1
- /**
2
- * MeoCord Framework
3
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
4
- * SPDX-License-Identifier: MIT
5
- */
6
-
7
1
  import { importX } from 'eslint-plugin-import-x'
8
2
  import globals from 'globals'
9
3
  import tsParser from '@typescript-eslint/parser'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "meocord",
3
3
  "description": "Decorator-based Discord bot framework built on discord.js. Brings NestJS-style controllers, dependency injection, guards, and testing utilities to bot development — with a full CLI and TypeScript-first design.",
4
- "version": "3.2.2",
4
+ "version": "4.0.0-beta.0",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=22"
@@ -18,8 +18,10 @@
18
18
  "test:coverage": "vitest run --coverage",
19
19
  "test:typecheck": "tsc --noEmit --project tsconfig.test.json",
20
20
  "changeset": "changeset",
21
- "release:version": "changeset version",
22
- "release:publish": "changeset publish"
21
+ "release:version": "changeset version && prettier --write CHANGELOG.md",
22
+ "release:publish": "changeset publish",
23
+ "notices": "bun scripts/third-party-notices.ts",
24
+ "notices:check": "bun scripts/third-party-notices.ts --check"
23
25
  },
24
26
  "bin": "./dist/esm/bin/meocord.js",
25
27
  "repository": {
@@ -70,7 +72,6 @@
70
72
  },
71
73
  "files": [
72
74
  "dist/**/*",
73
- "webpack.config.js",
74
75
  "meocord.eslint.mjs",
75
76
  "meocord.eslint.cjs",
76
77
  "meocord.eslint.d.ts",
@@ -78,11 +79,12 @@
78
79
  "LICENSE",
79
80
  "AUTHOR.md",
80
81
  "CHANGELOG.md",
82
+ "THIRD_PARTY_NOTICES.md",
81
83
  "README.md"
82
84
  ],
83
85
  "dependencies": {
84
86
  "@clack/prompts": "^1.8.0",
85
- "@swc/core": "1.16.2",
87
+ "@rsbuild/core": "^2.2.8",
86
88
  "chalk": "^6.0.0",
87
89
  "cli-table3": "^0.6.5",
88
90
  "commander": "^15.0.0",
@@ -91,46 +93,40 @@
91
93
  "jiti": "^2.7.0",
92
94
  "lodash-es": "^4.18.1",
93
95
  "reflect-metadata": "^0.2.2",
94
- "simple-git": "^3.36.0",
95
- "swc-loader": "^0.2.7",
96
- "terser-webpack-plugin": "^5.6.1",
97
- "tsconfig-paths-webpack-plugin": "^4.2.0",
98
- "webpack": "^5.110.3",
99
- "webpack-node-externals": "^3.0.0"
96
+ "simple-git": "^3.36.0"
100
97
  },
101
98
  "devDependencies": {
102
99
  "@changesets/changelog-github": "^1.0.1",
103
- "@changesets/cli": "^3.0.2",
100
+ "@changesets/cli": "^3.0.3",
104
101
  "@eslint/js": "^10.0.1",
105
102
  "@rollup/plugin-alias": "^6.0.0",
106
103
  "@rollup/plugin-json": "^6.1.0",
107
104
  "@rollup/plugin-node-resolve": "^16.0.3",
108
105
  "@rollup/plugin-swc": "^0.4.1",
109
106
  "@types/lodash-es": "^4.17.12",
110
- "@types/webpack-node-externals": "^3.0.4",
111
- "@typescript-eslint/parser": "^8.70.0",
107
+ "@typescript-eslint/parser": "^8.70.1",
108
+ "@vitest/coverage-istanbul": "^5.0.1",
112
109
  "discord.js": "^14.27.0",
113
- "eslint": "^10.10.0",
110
+ "dotenv": "^18.0.3",
111
+ "eslint": "^10.11.0",
114
112
  "eslint-config-prettier": "^10.1.8",
115
- "eslint-plugin-headers": "^1.3.4",
116
113
  "eslint-plugin-import-x": "^4.17.1",
117
114
  "eslint-plugin-prettier": "^5.5.6",
118
115
  "eslint-plugin-unused-imports": "^4.4.1",
119
116
  "globals": "^17.12.0",
120
117
  "husky": "^9.1.7",
121
- "prettier": "^3.9.6",
122
- "rollup": "^4.63.1",
118
+ "prettier": "^3.9.8",
119
+ "rollup": "^4.63.4",
123
120
  "rollup-plugin-copy": "^3.5.0",
124
121
  "rollup-plugin-dts": "^6.5.1",
125
122
  "typescript": "^6.0.3",
126
- "typescript-eslint": "^8.70.0",
127
- "@vitest/coverage-istanbul": "^5.0.0",
128
- "unplugin-swc": "^1.6.0",
129
- "vitest": "^5.0.0"
123
+ "typescript-eslint": "^8.70.1",
124
+ "unplugin-swc": "^2.0.0",
125
+ "vitest": "^5.0.1"
130
126
  },
131
127
  "peerDependencies": {
132
128
  "discord.js": "^14.26.4",
133
- "dotenv": "^17.4.2"
129
+ "dotenv": "^18.0.3"
134
130
  },
135
131
  "publishConfig": {
136
132
  "provenance": true
package/webpack.config.js DELETED
@@ -1,147 +0,0 @@
1
- /**
2
- * MeoCord Framework
3
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
4
- * SPDX-License-Identifier: MIT
5
- */
6
-
7
- import path from 'path'
8
- import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'
9
- import TerserPlugin from 'terser-webpack-plugin'
10
- import { loadMeoCordConfig } from './dist/esm/util/meocord-config-loader.util.js'
11
- import { prepareModifiedTsConfig } from './dist/esm/util/tsconfig.util.js'
12
- import nodeExternals from 'webpack-node-externals'
13
-
14
- const CWD = process.cwd()
15
- const IS_PRODUCTION = process.env.NODE_ENV === 'production'
16
- const SRC_DIR = path.resolve(CWD, 'src')
17
- const DIST_DIR = path.resolve(CWD, 'dist')
18
-
19
- // Note: meocordConfig is loaded lazily inside createWebpackConfig()
20
- // to avoid Bun's aggressive module caching issues in Docker containers
21
- const tsConfigPath = prepareModifiedTsConfig()
22
-
23
- const baseRules = [
24
- {
25
- test: /\.ts$/,
26
- use: {
27
- loader: 'swc-loader',
28
- options: {
29
- jsc: {
30
- parser: {
31
- syntax: 'typescript',
32
- tsx: false,
33
- decorators: true,
34
- },
35
- transform: {
36
- decoratorMetadata: true,
37
- legacyDecorator: true,
38
- },
39
- },
40
- },
41
- },
42
- exclude: /node_modules/,
43
- },
44
- ]
45
-
46
- /**
47
- * Merges two arrays returning unique elements
48
- */
49
- const mergeUnique = (base = [], additions = []) => Array.from(new Set([...base, ...additions]))
50
-
51
- /**
52
- * Creates webpack configuration with framework defaults
53
- */
54
- const createWebpackConfig = (overrides = {}) => {
55
- const baseConfig = {
56
- mode: overrides.mode ?? (IS_PRODUCTION ? 'production' : 'development'),
57
- entry: overrides.entry ?? path.resolve(SRC_DIR, 'main.ts'),
58
- target: 'node',
59
- externals: mergeUnique([nodeExternals({ importType: 'module' })], overrides.externals),
60
- module: {
61
- ...overrides.module,
62
- rules: mergeUnique(baseRules, overrides.module?.rules),
63
- },
64
- resolve: {
65
- ...overrides.resolve,
66
- extensions: mergeUnique(['.ts', '.js'], overrides.resolve?.extensions),
67
- plugins: mergeUnique([new TsconfigPathsPlugin({ configFile: tsConfigPath })], overrides.resolve?.plugins),
68
- },
69
- output: {
70
- filename: 'main.js',
71
- path: DIST_DIR,
72
- publicPath: path.join(process.cwd(), 'dist/'),
73
- library: { type: 'module' },
74
- ...overrides.output,
75
- },
76
- experiments: {
77
- outputModule: true,
78
- ...overrides.experiments,
79
- },
80
- stats: overrides.stats ?? (IS_PRODUCTION ? 'normal' : 'errors-warnings'),
81
- devtool: overrides.devtool ?? (IS_PRODUCTION ? 'source-map' : 'eval-source-map'),
82
- performance: {
83
- hints: overrides.performance?.hints ?? (IS_PRODUCTION ? 'warning' : false),
84
- ...overrides.performance,
85
- },
86
- ...overrides,
87
- optimization: {
88
- ...overrides.optimization,
89
- minimize: overrides.optimization?.minimize ?? IS_PRODUCTION,
90
- minimizer: [],
91
- },
92
- }
93
-
94
- const finalMinimizerArray = []
95
- const shouldMinimize = baseConfig.optimization.minimize
96
-
97
- if (shouldMinimize) {
98
- const userProvidedMinimizers = overrides.optimization?.minimizer
99
- let lastTerserInstance = null
100
- const otherMinimizers = []
101
-
102
- if (Array.isArray(userProvidedMinimizers)) {
103
- for (let i = userProvidedMinimizers.length - 1; i >= 0; i--) {
104
- const minimizer = userProvidedMinimizers[i]
105
- if (minimizer?.constructor?.name === 'TerserPlugin') {
106
- if (!lastTerserInstance) {
107
- lastTerserInstance = minimizer
108
- }
109
- } else if (minimizer) {
110
- otherMinimizers.unshift(minimizer)
111
- }
112
- }
113
- }
114
-
115
- finalMinimizerArray.push(...otherMinimizers)
116
-
117
- let terserPluginToUse
118
- if (lastTerserInstance) {
119
- terserPluginToUse = new TerserPlugin({
120
- test: lastTerserInstance.options?.test,
121
- include: lastTerserInstance.options?.include,
122
- exclude: lastTerserInstance.options?.exclude,
123
- extractComments: lastTerserInstance.options?.extractComments,
124
- parallel: lastTerserInstance.options?.parallel,
125
- minify: lastTerserInstance.options?.minify,
126
- terserOptions: {
127
- ...(lastTerserInstance.options?.terserOptions || {}),
128
- keep_classnames: true,
129
- },
130
- })
131
- } else {
132
- terserPluginToUse = new TerserPlugin({ terserOptions: { keep_classnames: true } })
133
- }
134
-
135
- finalMinimizerArray.push(terserPluginToUse)
136
- }
137
-
138
- baseConfig.optimization.minimizer = finalMinimizerArray
139
-
140
- return baseConfig
141
- }
142
-
143
- // Load user config lazily (fixes Bun Docker caching issues)
144
- const meocordConfig = loadMeoCordConfig()
145
- const initialConfig = createWebpackConfig()
146
- const userModifiedConfig = meocordConfig?.webpack?.(initialConfig)
147
- export default createWebpackConfig(userModifiedConfig ?? {})