meocord 3.2.2 → 4.0.0-beta.1

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 (55) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +161 -29
  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-Dqwlnz0m.cjs +124 -0
  7. package/dist/cjs/common/index.cjs +2 -6
  8. package/dist/cjs/core/index.cjs +69 -7
  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 +165 -142
  26. package/dist/esm/build/native-addons.js +274 -0
  27. package/dist/esm/build/rsbuild-config.js +176 -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 +5 -1
  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/common.util.js +3 -3
  36. package/dist/esm/util/generator-cli.util.js +54 -10
  37. package/dist/esm/util/json.util.js +0 -4
  38. package/dist/esm/util/meocord-config-loader.util.js +19 -51
  39. package/dist/esm/util/meocord-source-config.util.js +55 -0
  40. package/dist/esm/util/platform.util.js +66 -0
  41. package/dist/esm/util/runtime.util.js +20 -7
  42. package/dist/esm/util/tsconfig.util.js +1 -1
  43. package/dist/esm/util/wait.util.js +1 -5
  44. package/dist/types/common/index.d.ts +0 -16
  45. package/dist/types/core/index.d.ts +0 -12
  46. package/dist/types/decorator/index.d.ts +1 -31
  47. package/dist/types/enum/index.d.ts +0 -5
  48. package/dist/types/interface/index.d.ts +46 -57
  49. package/dist/types/testing/index.d.ts +4 -19
  50. package/meocord.eslint.cjs +0 -6
  51. package/meocord.eslint.d.ts +0 -6
  52. package/meocord.eslint.mjs +0 -6
  53. package/package.json +20 -24
  54. package/dist/cjs/_shared/theme-EmG1ZEwV.cjs +0 -179
  55. package/webpack.config.js +0 -147
package/package.json CHANGED
@@ -1,10 +1,10 @@
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.1",
5
5
  "type": "module",
6
6
  "engines": {
7
- "node": ">=22"
7
+ "node": ">=22.13"
8
8
  },
9
9
  "scripts": {
10
10
  "format": "prettier --write \"**/*.md\" \"src/bin/app-template/**/*.template\"",
@@ -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
@@ -1,179 +0,0 @@
1
- 'use strict';
2
-
3
- var node_util = require('node:util');
4
- var dayjs = require('dayjs');
5
- var utc = require('dayjs/plugin/utc.js');
6
- var timezone = require('dayjs/plugin/timezone.js');
7
- var path = require('path');
8
- var fs = require('fs');
9
- var jiti = require('jiti');
10
- var chalk = require('chalk');
11
-
12
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
13
- /**
14
- * MeoCord Framework
15
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
16
- * SPDX-License-Identifier: MIT
17
- */ /**
18
- * Helper function to fix common JSON formatting issues in tsconfig.json, such as:
19
- * - Removing single-line comments.
20
- * - Removing trailing commas.
21
- * - Stripping newlines.
22
- *
23
- * @param {string} jsonString - The raw JSON string to fix.
24
- * @returns {string} The corrected JSON string.
25
- */ function fixJSON(jsonString) {
26
- return jsonString.replace(/\/\/.*$/gm, '') // Remove single-line comments
27
- .replace(/,(\s*[}\]])/g, '$1') // Remove trailing commas before } or ]
28
- .replace(/,\s*$/, '') // Remove trailing commas at the end of the file
29
- .replace(/^\s*[\r\n]/gm, '') // Replace empty lines only
30
- ;
31
- }
32
-
33
- let cachedConfig;
34
- let configLoaded = false;
35
- /**
36
- * Loads the MeoCord configuration, checking compiled output first then falling back to source.
37
- *
38
- * Resolution order:
39
- * 1. `dist/meocord.config.mjs` — pre-compiled by `meocord build`, no tsconfig or source files needed
40
- * 2. `meocord.config.ts` — loaded via jiti with tsconfig path aliases (dev mode)
41
- *
42
- * The result is cached after the first successful load.
43
- *
44
- * @returns {MeoCordConfig | undefined} The loaded configuration object, or undefined if loading fails.
45
- */ function loadMeoCordConfig() {
46
- if (configLoaded) return cachedConfig;
47
- configLoaded = true;
48
- cachedConfig = loadCompiledConfig() ?? loadSourceConfig();
49
- return cachedConfig;
50
- }
51
- /**
52
- * Loads the pre-compiled config from dist/meocord.config.mjs.
53
- * This file is generated by `meocord build` and requires no tsconfig or source files.
54
- */ function loadCompiledConfig() {
55
- const compiledPath = path.resolve(process.cwd(), 'dist', 'meocord.config.mjs');
56
- if (!fs.existsSync(compiledPath)) return undefined;
57
- try {
58
- const jiti$1 = jiti.createJiti((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('_shared/theme-EmG1ZEwV.cjs', document.baseURI).href)), {
59
- interopDefault: true
60
- });
61
- return jiti$1(compiledPath);
62
- } catch {
63
- // Fall through to source config
64
- return undefined;
65
- }
66
- }
67
- /**
68
- * Loads the source config from meocord.config.ts via jiti with tsconfig path alias resolution.
69
- * Used in development mode where source files and tsconfig.json are available.
70
- */ function loadSourceConfig() {
71
- const configPath = path.resolve(process.cwd(), 'meocord.config.ts');
72
- if (!fs.existsSync(configPath)) return undefined;
73
- try {
74
- const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json');
75
- const aliases = {};
76
- if (fs.existsSync(tsConfigPath)) {
77
- const tsConfig = JSON.parse(fixJSON(fs.readFileSync(tsConfigPath, 'utf-8')));
78
- const paths = tsConfig?.compilerOptions?.paths;
79
- if (paths) {
80
- for (const [key, values] of Object.entries(paths)){
81
- const aliasKey = key.replace('/*', '');
82
- aliases[aliasKey] = path.resolve(process.cwd(), values[0].replace('/*', ''));
83
- }
84
- }
85
- }
86
- const jiti$1 = jiti.createJiti((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('_shared/theme-EmG1ZEwV.cjs', document.baseURI).href)), {
87
- interopDefault: true,
88
- alias: aliases,
89
- moduleCache: false
90
- });
91
- return jiti$1(configPath);
92
- } catch (error) {
93
- if (error instanceof Error) {
94
- console.error(`[MeoCord] Failed to load config: ${error.message}`);
95
- } else {
96
- console.error(`[MeoCord] Failed to load config: Unknown error`);
97
- }
98
- return undefined;
99
- }
100
- }
101
-
102
- dayjs.extend(utc);
103
- dayjs.extend(timezone);
104
- class Logger {
105
- log(...args) {
106
- this.logWithContext('log', args);
107
- }
108
- info(...args) {
109
- this.logWithContext('log', args);
110
- }
111
- warn(...args) {
112
- this.logWithContext('warn', args);
113
- }
114
- error(...args) {
115
- this.logWithContext('error', args);
116
- }
117
- debug(...args) {
118
- this.logWithContext('debug', args);
119
- }
120
- verbose(...args) {
121
- this.logWithContext('log', args);
122
- }
123
- formatMessage(message, logType) {
124
- if (typeof message === 'object' && message !== null) {
125
- return node_util.inspect(message, {
126
- showHidden: true,
127
- depth: null,
128
- colors: true,
129
- compact: false,
130
- showProxy: true
131
- });
132
- }
133
- return (this.colorMap[logType] || ((msg)=>msg))(message);
134
- }
135
- logWithContext(logLevel, messages) {
136
- if (messages.length === 0) return;
137
- const config = loadMeoCordConfig();
138
- const logType = logLevel.toUpperCase();
139
- const applyColor = this.colorMap[logType] || ((msg)=>msg);
140
- const formattedMessages = messages.map((message)=>this.formatMessage(message, logType));
141
- const coloredAppName = config?.appName ? applyColor(chalk.bold(`[${config.appName}]`)) : undefined;
142
- const timestamp = chalk.bold(dayjs().format('dddd, MMMM D, YYYY HH:mm:ss [UTC]Z'));
143
- const coloredLogLevel = applyColor(chalk.bold(`[${logType}]`));
144
- const coloredContext = this.context ? chalk.yellow.bold(`[${this.context}]`) : '';
145
- const logTexts = [
146
- coloredAppName,
147
- timestamp,
148
- coloredLogLevel,
149
- coloredContext,
150
- ...formattedMessages
151
- ].filter((log)=>!!log);
152
- console[logLevel](...logTexts);
153
- }
154
- constructor(context){
155
- this.context = context;
156
- this.colorMap = {
157
- LOG: chalk.green,
158
- INFO: chalk.cyan,
159
- WARN: chalk.yellow,
160
- ERROR: chalk.red,
161
- DEBUG: chalk.magenta
162
- };
163
- }
164
- }
165
-
166
- /**
167
- * MeoCord Framework
168
- * Copyright (c) 2025-present Ukasyah Rahmatullah Zada
169
- * SPDX-License-Identifier: MIT
170
- */ class Theme {
171
- }
172
- Theme.successColor = '#28A745';
173
- Theme.infoColor = '#17A2B8';
174
- Theme.errorColor = '#DC3545';
175
- Theme.warningColor = '#FFC107';
176
-
177
- exports.Logger = Logger;
178
- exports.Theme = Theme;
179
- exports.loadMeoCordConfig = loadMeoCordConfig;
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 ?? {})