meocord 3.2.1 → 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.
- package/CHANGELOG.md +69 -0
- package/LICENSE +1 -1
- package/README.md +167 -52
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/cjs/_shared/{controller.decorator-MUHA_A3z.cjs → controller.decorator-9nIxOp9y.cjs} +1 -1
- package/dist/cjs/_shared/{metadata-key.enum-BzzvGUId.cjs → metadata-key.enum-aABGdodb.cjs} +0 -4
- package/dist/cjs/_shared/{theme-Bz-D4RbT.cjs → theme-BXdSoifk.cjs} +4 -15
- package/dist/cjs/common/index.cjs +1 -5
- package/dist/cjs/core/index.cjs +67 -5
- package/dist/cjs/decorator/index.cjs +2 -2
- package/dist/cjs/enum/index.cjs +1 -1
- package/dist/cjs/testing/index.cjs +2 -6
- package/dist/esm/bin/app-template/meocord.config.ts.template +8 -13
- package/dist/esm/bin/app-template/package.json.template +12 -12
- package/dist/esm/bin/app-template/vitest.config.ts.template +6 -2
- package/dist/esm/bin/builder-template/builder/context-menu.builder.template +2 -2
- package/dist/esm/bin/builder-template/builder/primary-entry-point.builder.template +2 -2
- package/dist/esm/bin/builder-template/builder/slash.builder.template +2 -2
- package/dist/esm/bin/builder-template/controller/autocomplete.controller.template +4 -3
- package/dist/esm/bin/builder-template/controller/context-menu.controller.template +2 -2
- package/dist/esm/bin/builder-template/controller/primary-entry-point.controller.template +2 -2
- package/dist/esm/bin/builder-template/controller/slash.controller.template +2 -2
- package/dist/esm/bin/helper/controller-generator.helper.js +43 -26
- package/dist/esm/bin/helper/guard-generator.helper.js +8 -2
- package/dist/esm/bin/helper/service-generator.helper.js +8 -2
- package/dist/esm/bin/meocord.js +166 -142
- package/dist/esm/build/native-addons.js +235 -0
- package/dist/esm/build/rsbuild-config.js +169 -0
- package/dist/esm/common/decorator.js +0 -4
- package/dist/esm/common/theme.js +1 -5
- package/dist/esm/core/meocord-factory.js +4 -0
- package/dist/esm/enum/controller.enum.js +1 -5
- package/dist/esm/enum/metadata-key.enum.js +0 -4
- package/dist/esm/package.json.js +1 -1
- package/dist/esm/testing/mock-fn.js +1 -5
- package/dist/esm/util/generator-cli.util.js +54 -10
- package/dist/esm/util/json.util.js +0 -4
- package/dist/esm/util/meocord-cli.util.js +1 -1
- package/dist/esm/util/meocord-config-loader.util.js +14 -2
- package/dist/esm/util/platform.util.js +66 -0
- package/dist/esm/util/runtime.util.js +20 -7
- package/dist/esm/util/tsconfig.util.js +1 -1
- package/dist/esm/util/wait.util.js +1 -5
- package/dist/types/common/index.d.ts +0 -16
- package/dist/types/core/index.d.ts +0 -12
- package/dist/types/decorator/index.d.ts +1 -31
- package/dist/types/enum/index.d.ts +0 -5
- package/dist/types/interface/index.d.ts +46 -57
- package/dist/types/testing/index.d.ts +4 -19
- package/meocord.eslint.cjs +0 -6
- package/meocord.eslint.d.ts +0 -6
- package/meocord.eslint.mjs +0 -6
- package/package.json +25 -27
- package/webpack.config.js +0 -147
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# meocord
|
|
2
|
+
|
|
3
|
+
## 4.0.0-beta.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#22](https://github.com/l7aromeo/meocord/pull/22) [`4deb96f`](https://github.com/l7aromeo/meocord/commit/4deb96fd73f86a29c46b9bb080c13e6267246cb1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Build with [Rsbuild](https://rsbuild.rs) instead of webpack. Production builds are several times
|
|
8
|
+
faster, and webpack and its four loader and plugin packages are no longer installed with MeoCord.
|
|
9
|
+
The output is unchanged: `dist/main.js`, assets under `dist/assets/` with the same names, and the
|
|
10
|
+
same source maps.
|
|
11
|
+
|
|
12
|
+
**Breaking:** the `webpack` hook in `meocord.config.ts` is replaced by `rsbuild`, which receives
|
|
13
|
+
Rsbuild's configuration. A config that still declares `webpack` stops the build with a message
|
|
14
|
+
saying so. `MeoCordWebpackConfig` is removed; import `RsbuildConfig` from `meocord/interface`
|
|
15
|
+
instead. The [migration guide](https://github.com/l7aromeo/meocord/blob/main/docs/MIGRATING.md#2-replace-the-webpack-hook-with-rsbuild) shows where each
|
|
16
|
+
webpack setting goes.
|
|
17
|
+
|
|
18
|
+
- [#19](https://github.com/l7aromeo/meocord/pull/19) [`204c7be`](https://github.com/l7aromeo/meocord/commit/204c7bec74886c931732cb771d9178b47fbec5e8) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Require dotenv 18. The `dotenv` peer dependency moves from `^17.4.2` to `^18.0.3`, so install
|
|
19
|
+
`dotenv@18` alongside MeoCord 4. No application code changes — `import 'dotenv/config'` behaves
|
|
20
|
+
the same. See the [migration guide](https://github.com/l7aromeo/meocord/blob/main/docs/MIGRATING.md#1-upgrade-dotenv-to-18).
|
|
21
|
+
|
|
22
|
+
### Minor Changes
|
|
23
|
+
|
|
24
|
+
- [#22](https://github.com/l7aromeo/meocord/pull/22) [`4deb96f`](https://github.com/l7aromeo/meocord/commit/4deb96fd73f86a29c46b9bb080c13e6267246cb1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Add `bundleDependencies`, which puts everything a bot needs inside `dist`, so it deploys without
|
|
25
|
+
`node_modules` or an install step. Plain JavaScript dependencies are bundled into `main.js`. Native
|
|
26
|
+
addons such as `sharp` are found while building and copied, with their platform binary, into
|
|
27
|
+
`dist/node_modules` — nothing has to be listed.
|
|
28
|
+
|
|
29
|
+
A build carrying native addons records its platform in `dist/meocord.platform.json`, and a bot
|
|
30
|
+
started on another platform stops before going online with a message naming both. Build on the
|
|
31
|
+
platform you deploy to. See
|
|
32
|
+
[Self-contained builds](https://github.com/l7aromeo/meocord#self-contained-builds).
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- [#22](https://github.com/l7aromeo/meocord/pull/22) [`4deb96f`](https://github.com/l7aromeo/meocord/commit/4deb96fd73f86a29c46b9bb080c13e6267246cb1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Read `meocord.config.ts` on every build. `meocord build` read the compiled `dist/meocord.config.mjs`
|
|
37
|
+
left by the previous build, so a config edit took effect one build late, and the watcher's reload
|
|
38
|
+
on a config change reloaded nothing.
|
|
39
|
+
|
|
40
|
+
- [#22](https://github.com/l7aromeo/meocord/pull/22) [`4deb96f`](https://github.com/l7aromeo/meocord/commit/4deb96fd73f86a29c46b9bb080c13e6267246cb1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Start the bot with `bun --no-install` from `meocord start`. Without it, bun downloads any package it
|
|
41
|
+
cannot find while the bot runs, which a bot deployed without `node_modules` would do in
|
|
42
|
+
production. If you start `dist/main.js` with bun yourself, pass the flag too.
|
|
43
|
+
|
|
44
|
+
- [#25](https://github.com/l7aromeo/meocord/pull/25) [`2179f85`](https://github.com/l7aromeo/meocord/commit/2179f85c2912d45e3fefbf996ca267c19a1a773c) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Stop `meocord generate` overwriting files. Slash, context-menu and primary entry point controllers
|
|
45
|
+
all wrote one shared `builders/sample.builder.ts`, so generating a second controller replaced a
|
|
46
|
+
builder you had already edited. Each controller now gets its own `builders/<name>.builder.ts`
|
|
47
|
+
exporting `<Name>CommandBuilder`, and registers a command named after it — `admin/ban` registers
|
|
48
|
+
`admin-ban` — rather than every one registering `sample-slash`. Generating a controller, service or
|
|
49
|
+
guard refuses if any file it would write already exists.
|
|
50
|
+
|
|
51
|
+
- [#24](https://github.com/l7aromeo/meocord/pull/24) [`5e2a54b`](https://github.com/l7aromeo/meocord/commit/5e2a54b67a1f9f51c4c3a3e8cf51247de2ac2528) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Type `deleted` on `createMockMessage()`. The mock tracks and documents it, but it was missing from
|
|
52
|
+
the type, so `message.deleted` did not compile.
|
|
53
|
+
|
|
54
|
+
- [#24](https://github.com/l7aromeo/meocord/pull/24) [`5e2a54b`](https://github.com/l7aromeo/meocord/commit/5e2a54b67a1f9f51c4c3a3e8cf51247de2ac2528) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Accept slash command builders that add options. `@CommandBuilder(CommandType.SLASH)` rejected
|
|
55
|
+
`new SlashCommandBuilder().addStringOption(...)`, whose type narrows to
|
|
56
|
+
`SlashCommandOptionsOnlyBuilder`, so the most common builder — one command with an option — did
|
|
57
|
+
not compile.
|
|
58
|
+
|
|
59
|
+
- [#21](https://github.com/l7aromeo/meocord/pull/21) [`bebf116`](https://github.com/l7aromeo/meocord/commit/bebf1168466595546017a317b62acd3707ff2d1c) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Generate applications with current test tooling: vitest and `@vitest/coverage-istanbul` 5,
|
|
60
|
+
`unplugin-swc` 2, and current eslint, prettier and typescript-eslint. A new application's
|
|
61
|
+
`test:coverage` no longer fails on its decorated entry files.
|
|
62
|
+
|
|
63
|
+
## 3.2.2
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- [#13](https://github.com/l7aromeo/meocord/pull/13) [`f8a6b15`](https://github.com/l7aromeo/meocord/commit/f8a6b156e8d22abf88443ba77c605d6d47991ab4) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Update the shipped dependencies — `@clack/prompts` 1.8.0, `@swc/core` 1.16.2, and `webpack`
|
|
68
|
+
5.110.3 — and state the copyright as `2025-present`, including in the notice the CLI prints
|
|
69
|
+
under `--license` and in its help banner.
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 Ukasyah Rahmatullah Zada
|
|
3
|
+
Copyright (c) 2025-present Ukasyah Rahmatullah Zada
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# MeoCord Framework
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/meocord)
|
|
4
|
+
[](https://github.com/l7aromeo/meocord/actions/workflows/release.yml)
|
|
5
|
+
[](https://www.npmjs.com/package/meocord)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
3
8
|
**MeoCord** is a decorator-based Discord bot framework built on top of discord.js. It brings a NestJS-style architecture — controllers, services, guards, and dependency injection — to bot development, with a full CLI, TypeScript-first design, and testing utilities included out of the box.
|
|
4
9
|
|
|
10
|
+
> **Upgrading from 3.x?** Follow the [migration guide](https://github.com/l7aromeo/meocord/blob/main/docs/MIGRATING.md).
|
|
11
|
+
|
|
5
12
|
---
|
|
6
13
|
|
|
7
14
|
## Table of Contents
|
|
@@ -35,10 +42,10 @@
|
|
|
35
42
|
- **Decorator-based controllers** — Handle every Discord interaction type — slash commands and their subcommands, autocomplete, buttons, modals, all five select menus, context menus, activity entry points, messages, and reactions — with `@Command`, `@Autocomplete`, `@Controller`, and `@UseGuard` decorators. No routing boilerplate.
|
|
36
43
|
- **Dependency injection** — Built on Inversify. Services are wired into controllers automatically; no manual instantiation or service locators.
|
|
37
44
|
- **Guard system** — Pre-execution hooks for auth, rate limiting, metrics, and anything else. Apply per-method or per-class with `@UseGuard`. Guards receive the full interaction context.
|
|
38
|
-
- **Full CLI** — `meocord create`, `build`, `start`, `generate`. Scaffolds controllers, services, and guards;
|
|
45
|
+
- **Full CLI** — `meocord create`, `build`, `start`, `generate`. Scaffolds controllers, services, and guards; builds with Rsbuild for both development and production.
|
|
39
46
|
- **Testing utilities** — `MeoCordTestingModule`, `createMockInteraction`, `createMockMessage`, `createMockUser`, `createMockClient`, `createMockGuild`, `createMockChannel`, `createChatInputOptions`, and `overrideGuard` let you test controllers against real guard logic without a Discord connection. Type guards and reply state machines work out of the box.
|
|
40
47
|
- **TypeScript-first** — Strict types throughout. Decorator metadata, `DeepMocked<T>` for test mocks, and typed config interfaces included.
|
|
41
|
-
- **Extensible build** —
|
|
48
|
+
- **Extensible build** — An Rsbuild config hook in `meocord.config.ts` to adjust the build without ejecting, and an option to bundle dependencies so production runs without `node_modules`.
|
|
42
49
|
|
|
43
50
|
---
|
|
44
51
|
|
|
@@ -47,8 +54,9 @@
|
|
|
47
54
|
### Prerequisites
|
|
48
55
|
|
|
49
56
|
- **Runtime**: Node.js 22 or newer, or Bun 1.x+
|
|
50
|
-
- **TypeScript**: 5.0+
|
|
57
|
+
- **TypeScript**: 5.0+ with `skipLibCheck` enabled, as generated apps have it; 5.8+ with it off
|
|
51
58
|
- **Package manager**: npm, yarn, pnpm, or bun
|
|
59
|
+
- **Peer dependencies**: `discord.js` 14 and `dotenv` 18 — `meocord create` installs both
|
|
52
60
|
|
|
53
61
|
MeoCord ships dual ESM/CJS builds. New projects generated by the CLI are preconfigured for ESM.
|
|
54
62
|
|
|
@@ -152,6 +160,9 @@ export class App {}
|
|
|
152
160
|
|
|
153
161
|
## Project Structure
|
|
154
162
|
|
|
163
|
+
<details>
|
|
164
|
+
<summary><b>The generated file tree</b></summary>
|
|
165
|
+
|
|
155
166
|
```
|
|
156
167
|
.
|
|
157
168
|
├── README.md
|
|
@@ -200,13 +211,15 @@ export class App {}
|
|
|
200
211
|
└── sample.service.spec.ts
|
|
201
212
|
```
|
|
202
213
|
|
|
214
|
+
</details>
|
|
215
|
+
|
|
203
216
|
---
|
|
204
217
|
|
|
205
218
|
## Configuration
|
|
206
219
|
|
|
207
220
|
### `meocord.config.ts`
|
|
208
221
|
|
|
209
|
-
The top-level config file. At minimum it needs `discordToken`. The `
|
|
222
|
+
The top-level config file. At minimum it needs `discordToken`. The `rsbuild` hook lets you adjust the build without ejecting.
|
|
210
223
|
|
|
211
224
|
```typescript
|
|
212
225
|
import { type MeoCordConfig } from 'meocord/interface'
|
|
@@ -214,15 +227,50 @@ import { type MeoCordConfig } from 'meocord/interface'
|
|
|
214
227
|
export default {
|
|
215
228
|
appName: 'MyBot',
|
|
216
229
|
discordToken: process.env.TOKEN!,
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
})
|
|
230
|
+
rsbuild: config => {
|
|
231
|
+
// Import .md and .html files as their text.
|
|
232
|
+
config.tools ??= {}
|
|
233
|
+
config.tools.rspack = (_rspackConfig, { addRules }) => {
|
|
234
|
+
addRules([{ test: /\.(md|html)$/i, type: 'asset/source' }])
|
|
235
|
+
}
|
|
221
236
|
return config
|
|
222
237
|
},
|
|
223
238
|
} satisfies MeoCordConfig
|
|
224
239
|
```
|
|
225
240
|
|
|
241
|
+
MeoCord builds with [Rsbuild](https://rsbuild.rs). The hook receives its configuration and returns it, modified. A few things it handles for you, so you do not need rules for them:
|
|
242
|
+
|
|
243
|
+
- **Images, fonts, svg and media** are emitted to `dist/assets/`, and importing one gives you its absolute path on disk — ready for `fs`, canvas, or a Discord attachment. Nothing is ever inlined as a data URI, whatever its size.
|
|
244
|
+
- **Custom asset paths** — `output.filename.image` (and `svg`, `font`, `media`) accept a function, for when two files share a name in different folders:
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import path from 'node:path'
|
|
248
|
+
|
|
249
|
+
// ...
|
|
250
|
+
rsbuild: config => {
|
|
251
|
+
config.output ??= {}
|
|
252
|
+
config.output.filename = {
|
|
253
|
+
...config.output.filename,
|
|
254
|
+
// Keep the folder a file came from, so image/star.webp and image/hsr/star.webp do not collide.
|
|
255
|
+
// The result is relative to dist/assets/, and uses / on every platform.
|
|
256
|
+
image: ({ filename }) => path.relative('src/assets', filename ?? '').split(path.sep).join('/'),
|
|
257
|
+
}
|
|
258
|
+
return config
|
|
259
|
+
},
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
- **Raw bundler rules** go through `tools.rspack`, which takes a webpack-shaped configuration.
|
|
263
|
+
|
|
264
|
+
| Option | Default | Description |
|
|
265
|
+
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
|
266
|
+
| `discordToken` | — | The bot token. Read it from the environment rather than writing it here. |
|
|
267
|
+
| `appName` | — | Shown in log lines. |
|
|
268
|
+
| `rsbuild` | — | `(config) => config` — adjust the Rsbuild configuration. |
|
|
269
|
+
| `bundleDependencies` | `false` | Put everything the bot needs inside `dist`, native addons included, so it runs without `node_modules`. |
|
|
270
|
+
| `externals` | `[]` | Modules to keep out of the bundle. Native addons are found without being listed. |
|
|
271
|
+
|
|
272
|
+
See [Self-contained builds](#self-contained-builds) for when to turn on `bundleDependencies`.
|
|
273
|
+
|
|
226
274
|
### ESLint
|
|
227
275
|
|
|
228
276
|
MeoCord exports a base ESLint config from `meocord/eslint`. Extend it as needed:
|
|
@@ -258,7 +306,7 @@ npx meocord --help
|
|
|
258
306
|
| Command | Alias | Description |
|
|
259
307
|
| ---------- | ----- | -------------------------------------- |
|
|
260
308
|
| `create` | — | Scaffold a new MeoCord application |
|
|
261
|
-
| `build` | — | Compile the application via
|
|
309
|
+
| `build` | — | Compile the application via Rsbuild |
|
|
262
310
|
| `start` | — | Start the application |
|
|
263
311
|
| `generate` | `g` | Scaffold controllers, services, guards |
|
|
264
312
|
| `show` | — | Display framework info |
|
|
@@ -307,11 +355,15 @@ Each one lands in its own directory, named after the type:
|
|
|
307
355
|
src/controllers/<type>/
|
|
308
356
|
├── <name>.<type>.controller.ts
|
|
309
357
|
├── <name>.<type>.controller.spec.ts
|
|
310
|
-
└── builders
|
|
358
|
+
└── builders/<name>.builder.ts # slash, context-menu and primary-entry-point only
|
|
311
359
|
```
|
|
312
360
|
|
|
313
361
|
A builder is generated only for the three types Discord registers by name. Everything else is addressed by `customId` or, for autocomplete, by the command path it completes — there is nothing to register.
|
|
314
362
|
|
|
363
|
+
Each controller gets its own builder, `<Name>CommandBuilder`, and registers a command named after it: `npx meocord g co slash Greeting` registers `/greeting`. A nested name uses its whole path, so `admin/ban` registers `/admin-ban` — Discord command names are global to the application, while folders only keep files apart. An autocomplete controller completes the slash command of the same name.
|
|
364
|
+
|
|
365
|
+
Generating never overwrites. If any file it would write already exists, it refuses, names the files, and writes nothing.
|
|
366
|
+
|
|
315
367
|
`<name>` may contain `/` to nest: `npx meocord g co button "admin/ban"` writes into `src/controllers/button/admin/`.
|
|
316
368
|
|
|
317
369
|
Directory layout is organisational only. Controllers are wired up by the `controllers` array on `@MeoCord()`, not by where they sit on disk.
|
|
@@ -405,7 +457,8 @@ preceded and followed by "/" or by the ends of the pattern. Write "a/{uuid}" rat
|
|
|
405
457
|
than "a-{uuid}".
|
|
406
458
|
```
|
|
407
459
|
|
|
408
|
-
|
|
460
|
+
<details>
|
|
461
|
+
<summary><b>Why the rule exists</b></summary>
|
|
409
462
|
|
|
410
463
|
A parameter matches anything up to the next `/`, so an identifier you do not control is captured whole — a hyphen inside a uuid is data, not structure:
|
|
411
464
|
|
|
@@ -425,7 +478,10 @@ Segment counts then keep neighbours apart on their own:
|
|
|
425
478
|
|
|
426
479
|
Each id matches exactly one of them.
|
|
427
480
|
|
|
428
|
-
|
|
481
|
+
</details>
|
|
482
|
+
|
|
483
|
+
<details>
|
|
484
|
+
<summary><b>Overlapping patterns</b></summary>
|
|
429
485
|
|
|
430
486
|
Two patterns with the same segment count can still both match. The one spelling out more literal text wins, so declaration order and file layout never decide it:
|
|
431
487
|
|
|
@@ -438,7 +494,10 @@ Ties between equally literal patterns go to the one with fewer parameters. The r
|
|
|
438
494
|
|
|
439
495
|
Where two patterns trade a literal for a parameter in opposite positions — `a/{x}/c` and `a/b/{y}` both take `a/b/c` — neither is more literal, and MeoCord logs a warning at startup naming the pair.
|
|
440
496
|
|
|
441
|
-
|
|
497
|
+
</details>
|
|
498
|
+
|
|
499
|
+
<details>
|
|
500
|
+
<summary><b>When nothing matches</b></summary>
|
|
442
501
|
|
|
443
502
|
An unroutable interaction replies "Command not found!" to the user and logs a warning naming the `customId` or command that failed to match. If a control appears dead, that log line is the first place to look.
|
|
444
503
|
|
|
@@ -446,12 +505,17 @@ Autocomplete cannot be replied to, so an unclaimed option is answered with an em
|
|
|
446
505
|
|
|
447
506
|
A handler that throws is logged and gets the same treatment — except when it had already replied or deferred, in which case MeoCord leaves the response alone rather than sending a second one Discord would reject.
|
|
448
507
|
|
|
449
|
-
|
|
508
|
+
</details>
|
|
509
|
+
|
|
510
|
+
<details>
|
|
511
|
+
<summary><b>Failures never take the bot down</b></summary>
|
|
450
512
|
|
|
451
513
|
discord.js calls event listeners without awaiting them, so anything that rejects out of one is an unhandled rejection — which terminates the process by default. MeoCord wraps every listener it registers, so one bad interaction, one unresolvable controller, or one reaction on a deleted message costs that event and nothing else. The error is logged against the event that produced it, so a genuine misconfiguration still shows up on the first interaction rather than staying hidden.
|
|
452
514
|
|
|
453
515
|
Where the failure happened before the handler ran, the user is still told: a command interaction gets the error reply, an autocomplete gets its window closed. A reaction whose message can no longer be fetched — deleted, or in a channel the bot lost access to — is skipped quietly, since that is an ordinary outcome rather than a fault.
|
|
454
516
|
|
|
517
|
+
</details>
|
|
518
|
+
|
|
455
519
|
---
|
|
456
520
|
|
|
457
521
|
## Subcommands
|
|
@@ -642,7 +706,8 @@ const module = MeoCordTestingModule.create({
|
|
|
642
706
|
const controller = module.get(GreetingSlashController)
|
|
643
707
|
```
|
|
644
708
|
|
|
645
|
-
|
|
709
|
+
<details>
|
|
710
|
+
<summary><b><code>createMockInteraction</code></b></summary>
|
|
646
711
|
|
|
647
712
|
Creates a smart mock instance of any discord.js class. The full prototype chain is preserved so `instanceof` checks pass at every level.
|
|
648
713
|
|
|
@@ -713,7 +778,10 @@ const contextMenu = createMockInteraction(UserContextMenuCommandInteraction, {
|
|
|
713
778
|
|
|
714
779
|
The override record is typed as `MockProps<T>`, exported from `meocord/testing`. Every key is optional, and a misspelled property name is a compile error.
|
|
715
780
|
|
|
716
|
-
|
|
781
|
+
</details>
|
|
782
|
+
|
|
783
|
+
<details>
|
|
784
|
+
<summary><b><code>createChatInputOptions</code></b></summary>
|
|
717
785
|
|
|
718
786
|
Builds a typed options resolver from a plain record. Type routing mirrors the real `CommandInteractionOptionResolver`: wrong-type access returns `null`, `required=true` throws if the option is absent.
|
|
719
787
|
|
|
@@ -764,7 +832,10 @@ Omit it and `getFocused` throws, the same as the real resolver does when no opti
|
|
|
764
832
|
|
|
765
833
|
All methods are mock functions — override any per test with `.mockReturnValue()`.
|
|
766
834
|
|
|
767
|
-
|
|
835
|
+
</details>
|
|
836
|
+
|
|
837
|
+
<details>
|
|
838
|
+
<summary><b><code>createMockUser</code> / <code>createMockClient</code> / <code>createMockGuild</code> / <code>createMockChannel</code></b></summary>
|
|
768
839
|
|
|
769
840
|
Convenience wrappers for common discord.js classes. All methods are auto-stubbed as mock functions. Nested managers (`client.users`, `guild.members`, etc.) are independent nested stubs.
|
|
770
841
|
|
|
@@ -783,7 +854,10 @@ await (client.users as any).fetch('user-123')
|
|
|
783
854
|
expect((client.users as any).fetch).toHaveBeenCalledWith('user-123')
|
|
784
855
|
```
|
|
785
856
|
|
|
786
|
-
|
|
857
|
+
</details>
|
|
858
|
+
|
|
859
|
+
<details>
|
|
860
|
+
<summary><b><code>createMockMessage</code></b></summary>
|
|
787
861
|
|
|
788
862
|
Creates a smart mock `Message`. Tracks a `deleted` boolean — `delete()`, `edit()`, `reply()`, `react()`, `pin()`, and `unpin()` throw if the message has already been deleted. `edit()` and `reply()` resolve to a new mock `Message` instance. All methods are mock functions.
|
|
789
863
|
|
|
@@ -806,7 +880,10 @@ edited.delete // → a mock fn
|
|
|
806
880
|
expect(msg.delete).toHaveBeenCalledTimes(1)
|
|
807
881
|
```
|
|
808
882
|
|
|
809
|
-
|
|
883
|
+
</details>
|
|
884
|
+
|
|
885
|
+
<details>
|
|
886
|
+
<summary><b><code>createMock</code></b></summary>
|
|
810
887
|
|
|
811
888
|
Mocks any type without a runtime class — use it for the services a controller depends on. `createMockInteraction` needs a class to build a prototype chain from, which is what makes `instanceof` and the real type guards work; a service double needs none of that, and an injected dependency may be an interface that does not exist at runtime at all.
|
|
812
889
|
|
|
@@ -829,7 +906,10 @@ expect(greetingService.buildGreeting).toHaveBeenCalledWith('Alice')
|
|
|
829
906
|
|
|
830
907
|
Nested access works without declaring the shape first — `cache.store.flush()` is a mock fn on a mock fn. Properties passed as `createMock<T>({ ... })` are used exactly as given rather than wrapped, so call assertions do not apply to those.
|
|
831
908
|
|
|
832
|
-
|
|
909
|
+
</details>
|
|
910
|
+
|
|
911
|
+
<details>
|
|
912
|
+
<summary><b><code>overrideGuard</code></b></summary>
|
|
833
913
|
|
|
834
914
|
Replaces a guard class in the DI container with a stub. No guard dependencies need to be provided.
|
|
835
915
|
|
|
@@ -840,14 +920,17 @@ const module = MeoCordTestingModule.create({
|
|
|
840
920
|
})
|
|
841
921
|
.overrideGuard(MetricsGuard)
|
|
842
922
|
.useValue({ canActivate: () => true })
|
|
843
|
-
.overrideGuard(
|
|
923
|
+
.overrideGuard(RateLimitGuard)
|
|
844
924
|
.useValue({ canActivate: () => true })
|
|
845
925
|
.compile()
|
|
846
926
|
```
|
|
847
927
|
|
|
848
928
|
`canActivate: () => true` allows the method to run. `() => false` blocks it. Multiple guards chain fluently.
|
|
849
929
|
|
|
850
|
-
|
|
930
|
+
</details>
|
|
931
|
+
|
|
932
|
+
<details>
|
|
933
|
+
<summary><b><code>overrideProvider</code></b></summary>
|
|
851
934
|
|
|
852
935
|
Replaces a provider already registered on the module. The value is typed as `Partial<T>`, so a double only has to cover the methods the test exercises — a class with a private member could never be satisfied by a full object literal anyway. A misspelled method name is still a compile error.
|
|
853
936
|
|
|
@@ -861,7 +944,10 @@ const module = MeoCordTestingModule.create({
|
|
|
861
944
|
.compile()
|
|
862
945
|
```
|
|
863
946
|
|
|
864
|
-
|
|
947
|
+
</details>
|
|
948
|
+
|
|
949
|
+
<details>
|
|
950
|
+
<summary><b>Full example</b></summary>
|
|
865
951
|
|
|
866
952
|
```typescript
|
|
867
953
|
import {
|
|
@@ -887,7 +973,7 @@ describe('GreetingSlashController', () => {
|
|
|
887
973
|
controllers: [GreetingSlashController],
|
|
888
974
|
providers: [{ provide: GreetingService, useValue: greetingService }],
|
|
889
975
|
})
|
|
890
|
-
.overrideGuard(
|
|
976
|
+
.overrideGuard(RateLimitGuard)
|
|
891
977
|
.useValue({ canActivate: () => true })
|
|
892
978
|
.compile()
|
|
893
979
|
|
|
@@ -908,6 +994,8 @@ describe('GreetingSlashController', () => {
|
|
|
908
994
|
})
|
|
909
995
|
```
|
|
910
996
|
|
|
997
|
+
</details>
|
|
998
|
+
|
|
911
999
|
---
|
|
912
1000
|
|
|
913
1001
|
## Deployment
|
|
@@ -943,6 +1031,47 @@ Start in production:
|
|
|
943
1031
|
npx meocord start --prod
|
|
944
1032
|
```
|
|
945
1033
|
|
|
1034
|
+
### Self-contained builds
|
|
1035
|
+
|
|
1036
|
+
By default `dist/main.js` imports its dependencies at runtime, which is why the server needs `node_modules`. Set `bundleDependencies` and the build puts everything the bot needs inside `dist` instead:
|
|
1037
|
+
|
|
1038
|
+
```typescript
|
|
1039
|
+
import { type MeoCordConfig } from 'meocord/interface'
|
|
1040
|
+
|
|
1041
|
+
export default {
|
|
1042
|
+
discordToken: process.env.TOKEN!,
|
|
1043
|
+
bundleDependencies: true,
|
|
1044
|
+
} satisfies MeoCordConfig
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
Deploying is then copying `dist/` — no `node_modules` beside it, no install step:
|
|
1048
|
+
|
|
1049
|
+
```
|
|
1050
|
+
dist/
|
|
1051
|
+
├── main.js
|
|
1052
|
+
├── assets/
|
|
1053
|
+
├── node_modules/ (native addons only, if you use any)
|
|
1054
|
+
├── package.json
|
|
1055
|
+
└── meocord.platform.json (if there are native addons)
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
Plain JavaScript dependencies are bundled into `main.js`. **Native addons** — packages that ship a compiled `.node` binary, like `sharp`, canvas bindings or database drivers — cannot be inlined into JavaScript, so MeoCord finds them itself while building, keeps them out of the bundle, and copies each one, with its platform binary and what it needs at runtime, into `dist/node_modules`. There is nothing to list: the build tells you which it packed.
|
|
1059
|
+
|
|
1060
|
+
```
|
|
1061
|
+
Native addons packed into dist: meo-canvas, sharp
|
|
1062
|
+
dist/node_modules holds 7 packages; nothing else to install.
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
**Build on the platform you deploy to.** A compiled binary only loads on the operating system, CPU and C library it was built for — a build made on a Mac carries macOS binaries, and a Debian (glibc) binary does not load on Alpine (musl). For a container, run `meocord build` inside the image. The build records its platform in `meocord.platform.json`, and a bot started somewhere else stops before going online with a message naming both, instead of failing on the first command that renders an image.
|
|
1066
|
+
|
|
1067
|
+
Use `externals` for anything you want kept out of the bundle for another reason; those are copied into `dist/node_modules` too. discord.js's optional accelerators — `zlib-sync`, `bufferutil`, `utf-8-validate` — are never bundled, are packed if you installed them, and are simply skipped by discord.js if you did not.
|
|
1068
|
+
|
|
1069
|
+
**On bun, keep it from installing at runtime.** With no `node_modules` in reach, bun downloads any package the moment something imports it. `meocord start` passes `--no-install` for you. If you launch the bundle yourself, pass it too:
|
|
1070
|
+
|
|
1071
|
+
```dockerfile
|
|
1072
|
+
CMD ["bun", "--no-install", "dist/main.js"]
|
|
1073
|
+
```
|
|
1074
|
+
|
|
946
1075
|
### Which runtime the bot runs on
|
|
947
1076
|
|
|
948
1077
|
`start` runs the bot on **the runtime you launched it with**. There is nothing to configure and no config key to set — if you typed `bun`, you get a bun process:
|
|
@@ -958,7 +1087,8 @@ That matters for more than tidiness. Pinning `node` would oblige a bun-only imag
|
|
|
958
1087
|
|
|
959
1088
|
Development works the same way. The watcher runs the bundle through the same command production does, so a runtime that works in `--dev` cannot quietly differ from the one that ships.
|
|
960
1089
|
|
|
961
|
-
|
|
1090
|
+
<details>
|
|
1091
|
+
<summary><b>Running the CLI itself on bun</b></summary>
|
|
962
1092
|
|
|
963
1093
|
The resolution above decides what the _bot_ runs on. The CLI process is decided earlier,
|
|
964
1094
|
by the interpreter line `#!/usr/bin/env node`, which nothing in the package can influence
|
|
@@ -991,7 +1121,10 @@ bun = true
|
|
|
991
1121
|
|
|
992
1122
|
Then plain `bun run start` runs the CLI and the bot on bun, and node need not exist.
|
|
993
1123
|
|
|
994
|
-
|
|
1124
|
+
</details>
|
|
1125
|
+
|
|
1126
|
+
<details>
|
|
1127
|
+
<summary><b>Pinning a specific binary</b></summary>
|
|
995
1128
|
|
|
996
1129
|
To override both signals — a particular install, or a different runtime for comparison — set `MEOCORD_RUNTIME`:
|
|
997
1130
|
|
|
@@ -999,44 +1132,26 @@ To override both signals — a particular install, or a different runtime for co
|
|
|
999
1132
|
MEOCORD_RUNTIME=/usr/local/bin/bun npm run start
|
|
1000
1133
|
```
|
|
1001
1134
|
|
|
1135
|
+
</details>
|
|
1136
|
+
|
|
1002
1137
|
---
|
|
1003
1138
|
|
|
1004
1139
|
## Contributing
|
|
1005
1140
|
|
|
1006
|
-
|
|
1007
|
-
2. Create a feature branch: `git checkout -b feat/your-feature`
|
|
1008
|
-
3. Commit with conventional commits: `git commit -m "feat: add X"`
|
|
1009
|
-
4. Run `bun run lint` and `bun run test` before pushing
|
|
1010
|
-
5. If you touched anything under `src/bin/`, also run `bun run build && bun run verify:generated`
|
|
1011
|
-
6. Push and open a pull request against `main`
|
|
1012
|
-
|
|
1013
|
-
Include a description of what changed and why, and add tests for any new behaviour.
|
|
1014
|
-
|
|
1015
|
-
`verify:generated` generates one controller of every type through the built CLI — flat and nested, in separate throwaway projects — and typechecks the result against the published package. Rendering a template says nothing about whether the code it produces compiles, and two bugs lived behind exactly that gap. It runs in CI as part of the Build job, so you do not have to remember it; running it locally is just faster than waiting.
|
|
1016
|
-
|
|
1017
|
-
### Commit messages and releases
|
|
1141
|
+
Issues, questions, and pull requests are welcome. [CONTRIBUTING.md](./CONTRIBUTING.md) covers getting set up, what each check exists to catch, and how releases work — a change that reaches the published package carries a [changeset](https://github.com/changesets/changesets), and merging the release pull request is what publishes it.
|
|
1018
1142
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
| Prefix | Release |
|
|
1022
|
-
| ------------------------------ | ------- |
|
|
1023
|
-
| `feat:` | minor |
|
|
1024
|
-
| `fix:` | patch |
|
|
1025
|
-
| `perf:` | patch |
|
|
1026
|
-
| `BREAKING CHANGE:` in the body | major |
|
|
1027
|
-
|
|
1028
|
-
Everything else — `docs:`, `test:`, `ci:`, `chore:`, `refactor:`, `style:` — lands on `main` without publishing and ships with whatever releasable commit comes next.
|
|
1029
|
-
|
|
1030
|
-
Pick the prefix by what reaches the installed package, not by which file you edited. JSDoc is compiled into the published `.d.ts` and is what a user reads in their editor, so correcting a wrong `@example` is a `fix:` even though you only touched a comment. A README-only change is `docs:`.
|
|
1143
|
+
Participation is governed by the [Code of Conduct](./CODE_OF_CONDUCT.md). For vulnerabilities, follow [SECURITY.md](./SECURITY.md) rather than opening an issue.
|
|
1031
1144
|
|
|
1032
1145
|
---
|
|
1033
1146
|
|
|
1034
1147
|
## Release Notes
|
|
1035
1148
|
|
|
1036
|
-
|
|
1149
|
+
Every release is recorded in [CHANGELOG.md](./CHANGELOG.md) and on the [GitHub Releases](https://github.com/l7aromeo/meocord/releases) page. Moving between major versions: the [migration guide](https://github.com/l7aromeo/meocord/blob/main/docs/MIGRATING.md).
|
|
1037
1150
|
|
|
1038
1151
|
---
|
|
1039
1152
|
|
|
1040
1153
|
## License
|
|
1041
1154
|
|
|
1042
|
-
|
|
1155
|
+
MeoCord is released under the [MIT License](./LICENSE), which covers the whole repository.
|
|
1156
|
+
|
|
1157
|
+
It builds on open-source packages under their own licenses, listed in [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
MeoCord is licensed under the [MIT License](./LICENSE). It depends on the open-source packages
|
|
4
|
+
below, each under its own license.
|
|
5
|
+
|
|
6
|
+
None of their code is copied into MeoCord's published package: npm installs each one alongside
|
|
7
|
+
MeoCord, with its own license file. This list is a record of what MeoCord relies on, and of the
|
|
8
|
+
terms those packages are offered under.
|
|
9
|
+
|
|
10
|
+
## Dependencies
|
|
11
|
+
|
|
12
|
+
Installed with MeoCord.
|
|
13
|
+
|
|
14
|
+
| Package | License | Source |
|
|
15
|
+
| ------------------------------------------------------------------ | ---------- | -------------------------------------------- |
|
|
16
|
+
| [@clack/prompts](https://www.npmjs.com/package/@clack/prompts) | MIT | https://github.com/bombshell-dev/clack |
|
|
17
|
+
| [@rsbuild/core](https://www.npmjs.com/package/@rsbuild/core) | MIT | https://github.com/web-infra-dev/rsbuild |
|
|
18
|
+
| [chalk](https://www.npmjs.com/package/chalk) | MIT | https://github.com/chalk/chalk |
|
|
19
|
+
| [cli-table3](https://www.npmjs.com/package/cli-table3) | MIT | https://github.com/cli-table/cli-table3 |
|
|
20
|
+
| [commander](https://www.npmjs.com/package/commander) | MIT | https://github.com/tj/commander.js |
|
|
21
|
+
| [dayjs](https://www.npmjs.com/package/dayjs) | MIT | https://github.com/iamkun/dayjs |
|
|
22
|
+
| [inversify](https://www.npmjs.com/package/inversify) | MIT | https://github.com/inversify/monorepo |
|
|
23
|
+
| [jiti](https://www.npmjs.com/package/jiti) | MIT | https://github.com/unjs/jiti |
|
|
24
|
+
| [lodash-es](https://www.npmjs.com/package/lodash-es) | MIT | https://github.com/lodash/lodash |
|
|
25
|
+
| [reflect-metadata](https://www.npmjs.com/package/reflect-metadata) | Apache-2.0 | https://github.com/rbuckton/reflect-metadata |
|
|
26
|
+
| [simple-git](https://www.npmjs.com/package/simple-git) | MIT | https://github.com/steveukx/git-js |
|
|
27
|
+
|
|
28
|
+
## Peer dependencies
|
|
29
|
+
|
|
30
|
+
Installed by the application using MeoCord.
|
|
31
|
+
|
|
32
|
+
| Package | License | Source |
|
|
33
|
+
| ------------------------------------------------------ | ------------ | --------------------------------------- |
|
|
34
|
+
| [discord.js](https://www.npmjs.com/package/discord.js) | Apache-2.0 | https://github.com/discordjs/discord.js |
|
|
35
|
+
| [dotenv](https://www.npmjs.com/package/dotenv) | BSD-2-Clause | https://github.com/motdotla/dotenv |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
Generated by `scripts/third-party-notices.ts` from the installed packages. Run
|
|
40
|
+
`bun run notices` after adding or removing a dependency.
|
package/dist/cjs/_shared/{controller.decorator-MUHA_A3z.cjs → controller.decorator-9nIxOp9y.cjs}
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require('reflect-metadata');
|
|
4
4
|
var inversify = require('inversify');
|
|
5
5
|
var enum_index = require('../enum/index.cjs');
|
|
6
|
-
var metadataKey_enum = require('./metadata-key.enum-
|
|
6
|
+
var metadataKey_enum = require('./metadata-key.enum-aABGdodb.cjs');
|
|
7
7
|
var discord_js = require('discord.js');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* MeoCord Framework
|
|
5
|
-
* Copyright (c) 2025 Ukasyah Rahmatullah Zada
|
|
6
|
-
* SPDX-License-Identifier: MIT
|
|
7
|
-
*/ /**
|
|
8
4
|
* Centralised metadata keys used across the framework's `Reflect` calls.
|
|
9
5
|
*
|
|
10
6
|
* Keeping them here prevents typos, documents the Inversify 8 key rename,
|
|
@@ -11,10 +11,6 @@ var chalk = require('chalk');
|
|
|
11
11
|
|
|
12
12
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
13
13
|
/**
|
|
14
|
-
* MeoCord Framework
|
|
15
|
-
* Copyright (c) 2025 Ukasyah Rahmatullah Zada
|
|
16
|
-
* SPDX-License-Identifier: MIT
|
|
17
|
-
*/ /**
|
|
18
14
|
* Helper function to fix common JSON formatting issues in tsconfig.json, such as:
|
|
19
15
|
* - Removing single-line comments.
|
|
20
16
|
* - Removing trailing commas.
|
|
@@ -55,7 +51,7 @@ let configLoaded = false;
|
|
|
55
51
|
const compiledPath = path.resolve(process.cwd(), 'dist', 'meocord.config.mjs');
|
|
56
52
|
if (!fs.existsSync(compiledPath)) return undefined;
|
|
57
53
|
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-
|
|
54
|
+
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-BXdSoifk.cjs', document.baseURI).href)), {
|
|
59
55
|
interopDefault: true
|
|
60
56
|
});
|
|
61
57
|
return jiti$1(compiledPath);
|
|
@@ -64,10 +60,7 @@ let configLoaded = false;
|
|
|
64
60
|
return undefined;
|
|
65
61
|
}
|
|
66
62
|
}
|
|
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() {
|
|
63
|
+
function loadSourceConfig() {
|
|
71
64
|
const configPath = path.resolve(process.cwd(), 'meocord.config.ts');
|
|
72
65
|
if (!fs.existsSync(configPath)) return undefined;
|
|
73
66
|
try {
|
|
@@ -83,7 +76,7 @@ let configLoaded = false;
|
|
|
83
76
|
}
|
|
84
77
|
}
|
|
85
78
|
}
|
|
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-
|
|
79
|
+
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-BXdSoifk.cjs', document.baseURI).href)), {
|
|
87
80
|
interopDefault: true,
|
|
88
81
|
alias: aliases,
|
|
89
82
|
moduleCache: false
|
|
@@ -163,11 +156,7 @@ class Logger {
|
|
|
163
156
|
}
|
|
164
157
|
}
|
|
165
158
|
|
|
166
|
-
|
|
167
|
-
* MeoCord Framework
|
|
168
|
-
* Copyright (c) 2025 Ukasyah Rahmatullah Zada
|
|
169
|
-
* SPDX-License-Identifier: MIT
|
|
170
|
-
*/ class Theme {
|
|
159
|
+
class Theme {
|
|
171
160
|
}
|
|
172
161
|
Theme.successColor = '#28A745';
|
|
173
162
|
Theme.infoColor = '#17A2B8';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var theme = require('../_shared/theme-
|
|
3
|
+
var theme = require('../_shared/theme-BXdSoifk.cjs');
|
|
4
4
|
require('node:util');
|
|
5
5
|
require('dayjs');
|
|
6
6
|
require('dayjs/plugin/utc.js');
|
|
@@ -11,10 +11,6 @@ require('jiti');
|
|
|
11
11
|
require('chalk');
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* MeoCord Framework
|
|
15
|
-
* Copyright (c) 2025 Ukasyah Rahmatullah Zada
|
|
16
|
-
* SPDX-License-Identifier: MIT
|
|
17
|
-
*/ /**
|
|
18
14
|
* Composes multiple class or method decorators into a single decorator.
|
|
19
15
|
*
|
|
20
16
|
* @example
|