meocord 1.8.4-beta.1 → 2.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.
package/README.md CHANGED
@@ -337,7 +337,21 @@ async ban(interaction: ChatInputCommandInteraction) { ... }
337
337
 
338
338
  ## Testing
339
339
 
340
- MeoCord ships a `meocord/testing` entry point with utilities for testing controllers in isolation — no real Discord connection required.
340
+ MeoCord ships a `meocord/testing` entry point with utilities for testing controllers in isolation — no real Discord connection required. The framework repo runs tests with [Vitest](https://vitest.dev/); the mocks themselves are **framework-agnostic** and work with Vitest or Jest assertions (see below).
341
+
342
+ ### Running tests
343
+
344
+ From the MeoCord repo root:
345
+
346
+ ```shell
347
+ bun run test # run once
348
+ bun run test:watch # watch mode
349
+ bun run test:coverage # coverage report
350
+ bun run test:typecheck # tsc -p tsconfig.test.json
351
+ bun run lint # eslint --fix + tsc
352
+ ```
353
+
354
+ In your own bot project, add Vitest (or keep Jest) plus a `vitest.config.ts` with SWC if you use decorator metadata — see this repo's config for reference. Generated apps include `*.spec.ts` stubs but not a test runner config yet.
341
355
 
342
356
  ### `MeoCordTestingModule`
343
357
 
@@ -364,7 +378,7 @@ Creates a smart mock instance of any discord.js class. The full prototype chain
364
378
 
365
379
  **Reply state machine** — for repliable interactions, `replied` and `deferred` start as `false`. Calling `reply()` or `deferReply()` twice throws, just like a real interaction. `followUp()`, `editReply()`, and `deleteReply()` throw if called before any reply. The ephemeral flag is tracked on `interaction.ephemeral`. All reply methods are still mock functions so call assertions work normally.
366
380
 
367
- > **Framework-agnostic** — the mocks returned here are plain mock functions that stamp `_isMockFunction` and expose `.mock.calls`, the exact contract both `jest` and `vitest` check. Use them with either framework's `expect(...).toHaveBeenCalledWith(...)` / `toHaveBeenCalledTimes(...)` — no jest or vitest import is required to produce them.
381
+ > **Framework-agnostic** — the mocks returned here are plain mock functions that stamp `_isMockFunction` and expose `.mock.calls`, the exact contract both `jest` and `vitest` check. Use them with either framework's `expect(...).toHaveBeenCalledWith(...)` / `toHaveBeenCalledTimes(...)` — no jest or vitest import is required to produce them. For typed stubs in your own code, import `MockedFunction`, `createMockFn`, and `DeepMocked` from `meocord/testing`.
368
382
 
369
383
  ```typescript
370
384
  import { createMockInteraction } from 'meocord/testing'
@@ -429,8 +443,13 @@ All methods are mock functions — override any per test with `.mockReturnValue(
429
443
  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.
430
444
 
431
445
  ```typescript
432
- import { vi } from 'vitest'
433
- import { createMockUser, createMockClient, createMockGuild, createMockChannel } from 'meocord/testing'
446
+ import {
447
+ createMockFn,
448
+ createMockUser,
449
+ createMockClient,
450
+ createMockGuild,
451
+ createMockChannel,
452
+ } from 'meocord/testing'
434
453
  import { TextChannel } from 'discord.js'
435
454
 
436
455
  const user = createMockUser()
@@ -438,8 +457,8 @@ const client = createMockClient()
438
457
  const guild = createMockGuild()
439
458
  const channel = createMockChannel(TextChannel)
440
459
 
441
- // override nested manager methods per test
442
- ;(client.users as any).fetch = vi.fn(() => Promise.resolve(user))
460
+ // override nested manager methods per test (createMockFn works with vitest and jest matchers)
461
+ ;(client.users as any).fetch = createMockFn(() => Promise.resolve(user))
443
462
  await (client.users as any).fetch('user-123')
444
463
  expect((client.users as any).fetch).toHaveBeenCalledWith('user-123')
445
464
  ```
@@ -486,8 +505,13 @@ const module = MeoCordTestingModule.create({
486
505
  ### Full example
487
506
 
488
507
  ```typescript
489
- import { vi, type MockedFunction } from 'vitest'
490
- import { MeoCordTestingModule, createMockInteraction, createChatInputOptions } from 'meocord/testing'
508
+ import {
509
+ MeoCordTestingModule,
510
+ createMockFn,
511
+ createMockInteraction,
512
+ createChatInputOptions,
513
+ type MockedFunction,
514
+ } from 'meocord/testing'
491
515
  import { ChatInputCommandInteraction } from 'discord.js'
492
516
  import { GreetingSlashController } from '@src/controllers/slash/greeting.slash.controller.js'
493
517
  import { GreetingService } from '@src/services/greeting.service.js'
@@ -498,7 +522,7 @@ describe('GreetingSlashController', () => {
498
522
  let greetingService: { buildGreeting: MockedFunction<GreetingService['buildGreeting']> }
499
523
 
500
524
  beforeEach(() => {
501
- greetingService = { buildGreeting: vi.fn() }
525
+ greetingService = { buildGreeting: createMockFn() }
502
526
 
503
527
  const module = MeoCordTestingModule.create({
504
528
  controllers: [GreetingSlashController],
@@ -566,9 +590,10 @@ npx meocord start --prod
566
590
  1. Fork the repository
567
591
  2. Create a feature branch: `git checkout -b feat/your-feature`
568
592
  3. Commit with conventional commits: `git commit -m "feat: add X"`
569
- 4. Push and open a pull request against `main`
593
+ 4. Run `bun run lint` and `bun run test` before pushing
594
+ 5. Push and open a pull request against `main`
570
595
 
571
- Include a description of what changed and why, and add tests for any new behaviour.
596
+ Include a description of what changed and why, and add tests for any new behaviour. Use `fix:` / `feat:` / `docs:` prefixes so [semantic-release](https://semantic-release.gitbook.io/) can version correctly — `test:` commits do not trigger a release.
572
597
 
573
598
  ---
574
599
 
@@ -22,7 +22,13 @@ function isValueProvider(p) {
22
22
  * Builder returned by `MeoCordTestingModule.create()`.
23
23
  * Call `.compile()` to get the resolved `TestingModule`.
24
24
  */ class TestingModuleBuilder {
25
- overrideProvider(token) {
25
+ /**
26
+ * A double covers the methods under test, not the whole class — and a class
27
+ * with any private member (a service holding a logger, say) can never be
28
+ * satisfied by an object literal at all. `Partial<T>` still rejects a
29
+ * misspelled method name, which is the check that actually earns its keep.
30
+ * Matches `overrideGuard`, which has always taken `Partial<GuardInterface>`.
31
+ */ overrideProvider(token) {
26
32
  return {
27
33
  useValue: (value)=>{
28
34
  this.overrides.set(token, {
@@ -97,10 +103,12 @@ function isValueProvider(p) {
97
103
  *
98
104
  * @example
99
105
  * ```typescript
106
+ * import { MeoCordTestingModule, createMockFn } from 'meocord/testing'
107
+ *
100
108
  * const module = MeoCordTestingModule.create({
101
109
  * controllers: [PingController],
102
110
  * providers: [
103
- * { provide: PingService, useValue: { handlePing: vi.fn().mockResolvedValue('pong') } },
111
+ * { provide: PingService, useValue: { handlePing: createMockFn().mockResolvedValue('pong') } },
104
112
  * ],
105
113
  * }).compile()
106
114
  *
@@ -126,6 +134,12 @@ function isValueProvider(p) {
126
134
  // `fn.mock.calls` — so a mock produced here is recognized by assertions in
127
135
  // either framework.
128
136
  // ---------------------------------------------------------------------------
137
+ /**
138
+ * Type guard that recognises mocks produced by `createMockFn` as well as
139
+ * native `jest.fn()` / `vi.fn()` mocks — all stamp `_isMockFunction = true`.
140
+ */ function isMockFunction(fn) {
141
+ return typeof fn === 'function' && '_isMockFunction' in fn && fn._isMockFunction === true;
142
+ }
129
143
  /**
130
144
  * Creates a framework-agnostic mock function. Callable; records calls on
131
145
  * `.mock.calls`; supports the mock-return/resolved/rejected/implementation
@@ -347,8 +361,17 @@ function stubDeep(instance, externalStubs) {
347
361
  stubs.set(key, stub);
348
362
  return stub;
349
363
  },
364
+ // defineProperty rather than assignment: many discord.js properties are
365
+ // prototype getters with no setter (targetUser, targetMessage, createdAt),
366
+ // and a plain write against one of those is a silent no-op. Defining an own
367
+ // data property shadows the accessor, which is what test setup means.
350
368
  set (target, prop, value) {
351
- Reflect.set(target, prop, value, target);
369
+ Object.defineProperty(target, prop, {
370
+ value,
371
+ writable: true,
372
+ enumerable: true,
373
+ configurable: true
374
+ });
352
375
  return true;
353
376
  }
354
377
  });
@@ -473,7 +496,7 @@ function findPrototypeMethod(instance, name) {
473
496
  * interaction.replied // → true
474
497
  * await interaction.reply({}) // throws — already replied
475
498
  * ```
476
- */ function createMockInteraction(Class) {
499
+ */ function createMockInteraction(Class, props) {
477
500
  const instance = Object.create(Class.prototype);
478
501
  const stubs = new Map();
479
502
  // Set type fields so all prototype type-guard methods compute the right value
@@ -543,6 +566,19 @@ function findPrototypeMethod(instance, name) {
543
566
  }));
544
567
  }
545
568
  }
569
+ // Applied last so an explicit prop wins over the type fields and the reply
570
+ // state machine. defineProperty rather than assignment for the same reason the
571
+ // Proxy uses it: several of these shadow a getter-only prototype accessor.
572
+ if (props !== undefined) {
573
+ for (const [key, value] of Object.entries(props)){
574
+ Object.defineProperty(instance, key, {
575
+ value,
576
+ writable: true,
577
+ enumerable: true,
578
+ configurable: true
579
+ });
580
+ }
581
+ }
546
582
  return stubDeep(instance, stubs);
547
583
  }
548
584
  // ---------------------------------------------------------------------------
@@ -752,7 +788,9 @@ exports.TestingModuleBuilder = TestingModuleBuilder;
752
788
  exports.createChatInputOptions = createChatInputOptions;
753
789
  exports.createMockChannel = createMockChannel;
754
790
  exports.createMockClient = createMockClient;
791
+ exports.createMockFn = createMockFn;
755
792
  exports.createMockGuild = createMockGuild;
756
793
  exports.createMockInteraction = createMockInteraction;
757
794
  exports.createMockMessage = createMockMessage;
758
795
  exports.createMockUser = createMockUser;
796
+ exports.isMockFunction = isMockFunction;
@@ -1,4 +1,4 @@
1
- var version = "1.2.6";
1
+ var version = "0.0.0-development";
2
2
  var packageJson = {
3
3
  version: version};
4
4
 
@@ -1,2 +1,3 @@
1
1
  export { MeoCordTestingModule, TestingModule, TestingModuleBuilder } from './meocord-testing-module.js';
2
2
  export { createChatInputOptions, createMockChannel, createMockClient, createMockGuild, createMockInteraction, createMockMessage, createMockUser } from './mock-interaction.js';
3
+ export { createMockFn, isMockFunction } from './mock-fn.js';
@@ -19,7 +19,13 @@ function isValueProvider(p) {
19
19
  * Builder returned by `MeoCordTestingModule.create()`.
20
20
  * Call `.compile()` to get the resolved `TestingModule`.
21
21
  */ class TestingModuleBuilder {
22
- overrideProvider(token) {
22
+ /**
23
+ * A double covers the methods under test, not the whole class — and a class
24
+ * with any private member (a service holding a logger, say) can never be
25
+ * satisfied by an object literal at all. `Partial<T>` still rejects a
26
+ * misspelled method name, which is the check that actually earns its keep.
27
+ * Matches `overrideGuard`, which has always taken `Partial<GuardInterface>`.
28
+ */ overrideProvider(token) {
23
29
  return {
24
30
  useValue: (value)=>{
25
31
  this.overrides.set(token, {
@@ -94,10 +100,12 @@ function isValueProvider(p) {
94
100
  *
95
101
  * @example
96
102
  * ```typescript
103
+ * import { MeoCordTestingModule, createMockFn } from 'meocord/testing'
104
+ *
97
105
  * const module = MeoCordTestingModule.create({
98
106
  * controllers: [PingController],
99
107
  * providers: [
100
- * { provide: PingService, useValue: { handlePing: vi.fn().mockResolvedValue('pong') } },
108
+ * { provide: PingService, useValue: { handlePing: createMockFn().mockResolvedValue('pong') } },
101
109
  * ],
102
110
  * }).compile()
103
111
  *
@@ -12,6 +12,12 @@
12
12
  // `fn.mock.calls` — so a mock produced here is recognized by assertions in
13
13
  // either framework.
14
14
  // ---------------------------------------------------------------------------
15
+ /**
16
+ * Type guard that recognises mocks produced by `createMockFn` as well as
17
+ * native `jest.fn()` / `vi.fn()` mocks — all stamp `_isMockFunction = true`.
18
+ */ function isMockFunction(fn) {
19
+ return typeof fn === 'function' && '_isMockFunction' in fn && fn._isMockFunction === true;
20
+ }
15
21
  /**
16
22
  * Creates a framework-agnostic mock function. Callable; records calls on
17
23
  * `.mock.calls`; supports the mock-return/resolved/rejected/implementation
@@ -187,4 +193,4 @@
187
193
  return mockFn;
188
194
  }
189
195
 
190
- export { createMockFn };
196
+ export { createMockFn, isMockFunction };
@@ -48,8 +48,17 @@ function stubDeep(instance, externalStubs) {
48
48
  stubs.set(key, stub);
49
49
  return stub;
50
50
  },
51
+ // defineProperty rather than assignment: many discord.js properties are
52
+ // prototype getters with no setter (targetUser, targetMessage, createdAt),
53
+ // and a plain write against one of those is a silent no-op. Defining an own
54
+ // data property shadows the accessor, which is what test setup means.
51
55
  set (target, prop, value) {
52
- Reflect.set(target, prop, value, target);
56
+ Object.defineProperty(target, prop, {
57
+ value,
58
+ writable: true,
59
+ enumerable: true,
60
+ configurable: true
61
+ });
53
62
  return true;
54
63
  }
55
64
  });
@@ -174,7 +183,7 @@ function findPrototypeMethod(instance, name) {
174
183
  * interaction.replied // → true
175
184
  * await interaction.reply({}) // throws — already replied
176
185
  * ```
177
- */ function createMockInteraction(Class) {
186
+ */ function createMockInteraction(Class, props) {
178
187
  const instance = Object.create(Class.prototype);
179
188
  const stubs = new Map();
180
189
  // Set type fields so all prototype type-guard methods compute the right value
@@ -244,6 +253,19 @@ function findPrototypeMethod(instance, name) {
244
253
  }));
245
254
  }
246
255
  }
256
+ // Applied last so an explicit prop wins over the type fields and the reply
257
+ // state machine. defineProperty rather than assignment for the same reason the
258
+ // Proxy uses it: several of these shadow a getter-only prototype accessor.
259
+ if (props !== undefined) {
260
+ for (const [key, value] of Object.entries(props)){
261
+ Object.defineProperty(instance, key, {
262
+ value,
263
+ writable: true,
264
+ enumerable: true,
265
+ configurable: true
266
+ });
267
+ }
268
+ }
247
269
  return stubDeep(instance, stubs);
248
270
  }
249
271
  // ---------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- import { C as CommandType } from '../controller.enum-QA-IuReF.js';
1
+ import { CommandType } from '../enum/index.js';
2
2
  import { SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder, ContextMenuCommandBuilder, ButtonInteraction, StringSelectMenuInteraction, ChatInputCommandInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, ModalSubmitInteraction, OmitPartialGroupDMChannel, Message, MessageReaction, PartialMessageReaction, ClientOptions, ActivityOptions } from 'discord.js';
3
3
  import { ReactionHandlerOptions, GuardInterface } from '../interface/index.js';
4
4
  import { ServiceIdentifier } from 'inversify';
@@ -1,6 +1,6 @@
1
1
  import { User, PartialUser, BaseInteraction, Message, MessageReaction } from 'discord.js';
2
2
  import { Configuration } from 'webpack';
3
- import { R as ReactionHandlerAction } from '../controller.enum-QA-IuReF.js';
3
+ import { ReactionHandlerAction } from '../enum/index.js';
4
4
 
5
5
  /**
6
6
  * MeoCord Framework
@@ -40,8 +40,15 @@ declare class TestingModuleBuilder {
40
40
  private readonly overrides;
41
41
  private readonly guardOverrides;
42
42
  constructor(options: TestingModuleOptions);
43
+ /**
44
+ * A double covers the methods under test, not the whole class — and a class
45
+ * with any private member (a service holding a logger, say) can never be
46
+ * satisfied by an object literal at all. `Partial<T>` still rejects a
47
+ * misspelled method name, which is the check that actually earns its keep.
48
+ * Matches `overrideGuard`, which has always taken `Partial<GuardInterface>`.
49
+ */
43
50
  overrideProvider<T>(token: ServiceIdentifier<T>): {
44
- useValue: (value: T) => TestingModuleBuilder;
51
+ useValue: (value: Partial<T>) => TestingModuleBuilder;
45
52
  };
46
53
  overrideGuard(guard: new (...args: any[]) => GuardInterface): {
47
54
  useValue: (stub: Partial<GuardInterface>) => TestingModuleBuilder;
@@ -53,10 +60,12 @@ declare class TestingModuleBuilder {
53
60
  *
54
61
  * @example
55
62
  * ```typescript
63
+ * import { MeoCordTestingModule, createMockFn } from 'meocord/testing'
64
+ *
56
65
  * const module = MeoCordTestingModule.create({
57
66
  * controllers: [PingController],
58
67
  * providers: [
59
- * { provide: PingService, useValue: { handlePing: vi.fn().mockResolvedValue('pong') } },
68
+ * { provide: PingService, useValue: { handlePing: createMockFn().mockResolvedValue('pong') } },
60
69
  * ],
61
70
  * }).compile()
62
71
  *
@@ -110,6 +119,26 @@ interface MockInstance<T extends (...args: any[]) => any = (...args: any[]) => a
110
119
  * Drop-in replacement for `jest.MockedFunction<T>` / vitest `MockedFunction<T>`.
111
120
  */
112
121
  type MockedFunction<T extends (...args: any[]) => any> = ((...args: Parameters<T>) => ReturnType<T>) & MockInstance<T>;
122
+ /** Alias kept for parity with `jest.Mock` / vitest `Mock`. */
123
+ type Mock<T extends (...args: any[]) => any = (...args: any[]) => any> = MockedFunction<T>;
124
+ /**
125
+ * Type guard that recognises mocks produced by `createMockFn` as well as
126
+ * native `jest.fn()` / `vi.fn()` mocks — all stamp `_isMockFunction = true`.
127
+ */
128
+ declare function isMockFunction(fn: unknown): fn is MockInstance;
129
+ /**
130
+ * Creates a framework-agnostic mock function. Callable; records calls on
131
+ * `.mock.calls`; supports the mock-return/resolved/rejected/implementation
132
+ * API used by the testing utilities and by user assertions.
133
+ *
134
+ * @example
135
+ * const fn = createMockFn<(x: number) => number>((x) => x + 1)
136
+ * fn(2) // → 3
137
+ * fn.mockReturnValue(99)
138
+ * fn(2) // → 99
139
+ * fn.mock.calls // → [[2], [2]]
140
+ */
141
+ declare function createMockFn<T extends (...args: any[]) => any = (...args: any[]) => any>(impl?: T): MockedFunction<T>;
113
142
 
114
143
  /**
115
144
  * MeoCord Framework
@@ -121,10 +150,35 @@ type MockedFunction<T extends (...args: any[]) => any> = ((...args: Parameters<T
121
150
  * Recursively transforms all methods of T into MockedFunction and all
122
151
  * nested objects into DeepMocked. Depth cap at 5 prevents infinite recursion
123
152
  * on circular discord.js types (e.g. Guild ↔ GuildMember).
124
- * -readonly removes readonly modifiers so test setup can write any property.
153
+ *
154
+ * Intersected with `T` so the mock is accepted wherever the real class is
155
+ * expected. A mapped type alone can never be: it iterates `keyof T`, and the
156
+ * private members classes use as brands — discord.js stamps
157
+ * `private readonly _cacheType` on `BaseInteraction` — are not in `keyof T`.
158
+ * Without the intersection every call site has to launder the mock through
159
+ * `as unknown as T`, which defeats the point of typing it at all.
160
+ *
161
+ * The intersection is honest rather than a convenient lie: the object really is
162
+ * `Object.create(Class.prototype)`, so its prototype chain is the real one, and
163
+ * TypeScript `private` is erased at runtime.
164
+ *
165
+ * `readonly` survives from the `T` side, so properties the class declares
166
+ * readonly cannot be assigned after construction. Pass those to the factory as
167
+ * {@link MockProps} instead.
125
168
  */
126
169
  type DeepMocked<T, Depth extends number[] = []> = Depth['length'] extends 5 ? T : {
127
170
  -readonly [K in keyof T]: T[K] extends (...args: infer A) => infer R ? MockedFunction<(...args: A) => R> : T[K] extends object ? DeepMocked<T[K], [...Depth, 0]> : T[K];
171
+ } & T;
172
+ /**
173
+ * Property overrides accepted at construction by the mock factories.
174
+ *
175
+ * Setup belongs here rather than in a post-construction assignment: the returned
176
+ * mock is assignable to the real discord.js class, so anything that class declares
177
+ * `readonly` — `ModalSubmitInteraction#customId`, `#fields`, `MessageComponentInteraction#message`
178
+ * — cannot be written afterwards without a cast.
179
+ */
180
+ type MockProps<T> = {
181
+ -readonly [K in keyof T]?: T[K] extends (...args: any[]) => any ? (...args: any[]) => any : T[K];
128
182
  };
129
183
  interface InteractionClass<T> {
130
184
  prototype: T;
@@ -157,7 +211,7 @@ interface InteractionClass<T> {
157
211
  * await interaction.reply({}) // throws — already replied
158
212
  * ```
159
213
  */
160
- declare function createMockInteraction<T extends object>(Class: InteractionClass<T>): DeepMocked<T>;
214
+ declare function createMockInteraction<T extends object>(Class: InteractionClass<T>, props?: MockProps<T>): DeepMocked<T>;
161
215
  /** Creates a mock {@link User}. All methods are auto-stubbed as a mock fn. */
162
216
  declare const createMockUser: () => DeepMocked<User>;
163
217
  /**
@@ -220,5 +274,5 @@ interface ChatInputOptions {
220
274
  */
221
275
  declare function createChatInputOptions(opts?: ChatInputOptions): DeepMocked<CommandInteractionOptionResolver>;
222
276
 
223
- export { MeoCordTestingModule, TestingModule, TestingModuleBuilder, createChatInputOptions, createMockChannel, createMockClient, createMockGuild, createMockInteraction, createMockMessage, createMockUser };
224
- export type { ChatInputOptions, ClassProvider, DeepMocked, Provider, TestingModuleOptions, ValueProvider };
277
+ export { MeoCordTestingModule, TestingModule, TestingModuleBuilder, createChatInputOptions, createMockChannel, createMockClient, createMockFn, createMockGuild, createMockInteraction, createMockMessage, createMockUser, isMockFunction };
278
+ export type { ChatInputOptions, ClassProvider, DeepMocked, Mock, MockInstance, MockProps, MockResult, MockState, MockedFunction, Provider, TestingModuleOptions, ValueProvider };
package/package.json CHANGED
@@ -1,8 +1,11 @@
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": "1.8.4-beta.1",
4
+ "version": "2.0.0-beta.1",
5
5
  "type": "module",
6
+ "engines": {
7
+ "node": ">=22"
8
+ },
6
9
  "scripts": {
7
10
  "lint": "eslint --fix . && tsc --noEmit && tsc --noEmit --project tsconfig.test.json",
8
11
  "build": "rm -rf ./dist && rollup -c",
@@ -72,13 +75,13 @@
72
75
  ],
73
76
  "dependencies": {
74
77
  "@clack/prompts": "^1.7.0",
75
- "@swc/core": "1.15.43",
76
- "chalk": "^5.6.2",
78
+ "@swc/core": "1.15.47",
79
+ "chalk": "^6.0.0",
77
80
  "cli-table3": "^0.6.5",
78
81
  "commander": "^15.0.0",
79
82
  "dayjs": "^1.11.21",
80
83
  "dotenv": "^17.4.2",
81
- "inversify": "^8.1.1",
84
+ "inversify": "^8.2.3",
82
85
  "jiti": "^2.7.0",
83
86
  "lodash-es": "^4.18.1",
84
87
  "nodemon": "^3.1.14",
@@ -87,7 +90,7 @@
87
90
  "swc-loader": "^0.2.7",
88
91
  "terser-webpack-plugin": "^5.6.1",
89
92
  "tsconfig-paths-webpack-plugin": "^4.2.0",
90
- "webpack": "^5.108.3",
93
+ "webpack": "^5.109.2",
91
94
  "webpack-node-externals": "^3.0.0"
92
95
  },
93
96
  "devDependencies": {
@@ -102,27 +105,27 @@
102
105
  "@semantic-release/release-notes-generator": "^14.1.1",
103
106
  "@types/lodash-es": "^4.17.12",
104
107
  "@types/webpack-node-externals": "^3.0.4",
105
- "@typescript-eslint/parser": "^8.62.1",
106
- "discord.js": "^14.26.4",
107
- "eslint": "^10.6.0",
108
+ "@typescript-eslint/parser": "^8.67.0",
109
+ "discord.js": "^14.27.0",
110
+ "eslint": "^10.8.1",
108
111
  "eslint-config-prettier": "^10.1.8",
109
112
  "eslint-plugin-headers": "^1.3.4",
110
113
  "eslint-plugin-import-x": "^4.17.1",
111
114
  "eslint-plugin-prettier": "^5.5.6",
112
115
  "eslint-plugin-unused-imports": "^4.4.1",
113
- "globals": "^17.7.0",
116
+ "globals": "^17.11.0",
114
117
  "husky": "^9.1.7",
115
- "prettier": "^3.9.4",
116
- "rollup": "^4.62.2",
118
+ "prettier": "^3.9.6",
119
+ "rollup": "^4.62.4",
117
120
  "rollup-plugin-copy": "^3.5.0",
118
- "rollup-plugin-dts": "^6.4.1",
119
- "semantic-release": "^25.0.5",
121
+ "rollup-plugin-dts": "^6.5.1",
122
+ "semantic-release": "^25.0.9",
120
123
  "ts-node": "^10.9.2",
121
124
  "typescript": "^6.0.3",
122
- "typescript-eslint": "^8.62.1",
123
- "@vitest/coverage-istanbul": "^3.2.4",
124
- "unplugin-swc": "^1.5.5",
125
- "vitest": "^3.2.4"
125
+ "typescript-eslint": "^8.67.0",
126
+ "@vitest/coverage-istanbul": "^4.1.10",
127
+ "unplugin-swc": "^1.5.11",
128
+ "vitest": "^4.1.10"
126
129
  },
127
130
  "peerDependencies": {
128
131
  "discord.js": "^14.26.4",