@marshmallow-stoat/mally 0.1.2 → 0.2.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/README.md +32 -23
- package/dist/index.d.mts +41 -123
- package/dist/index.d.ts +41 -123
- package/dist/index.js +160 -124
- package/dist/index.mjs +158 -117
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,15 +38,13 @@ Make sure to enable decorators in your `tsconfig.json`:
|
|
|
38
38
|
import 'reflect-metadata';
|
|
39
39
|
import { Client } from 'stoat.js';
|
|
40
40
|
import { MallyHandler } from '@marshmallow-stoat/mally';
|
|
41
|
-
import { join } from 'path';
|
|
42
41
|
|
|
43
42
|
const client = new Client();
|
|
44
43
|
|
|
45
44
|
const handler = new MallyHandler({
|
|
46
45
|
client,
|
|
47
46
|
prefix: '!',
|
|
48
|
-
owners: ['your-user-id']
|
|
49
|
-
commandsDir: join(__dirname, "commands")
|
|
47
|
+
owners: ['your-user-id']
|
|
50
48
|
});
|
|
51
49
|
|
|
52
50
|
await handler.init();
|
|
@@ -78,7 +76,7 @@ export class GeneralCommands {
|
|
|
78
76
|
}
|
|
79
77
|
```
|
|
80
78
|
|
|
81
|
-
That's it! No manual imports needed -
|
|
79
|
+
That's it! No manual imports needed - decorated command classes are auto-discovered.
|
|
82
80
|
|
|
83
81
|
## Decorators
|
|
84
82
|
|
|
@@ -165,12 +163,20 @@ interface Context {
|
|
|
165
163
|
```typescript
|
|
166
164
|
interface MallyHandlerOptions {
|
|
167
165
|
client: Client;
|
|
168
|
-
commandsDir
|
|
166
|
+
commandsDir?: string; // Legacy mode: explicitly scan this directory
|
|
167
|
+
discovery?: {
|
|
168
|
+
roots?: string[]; // Default: [process.cwd()]
|
|
169
|
+
include?: string[]; // Glob patterns per root
|
|
170
|
+
ignore?: string[]; // Additional ignore globs
|
|
171
|
+
};
|
|
169
172
|
prefix: string | ((ctx: { serverId?: string }) => string | Promise<string>);
|
|
170
173
|
owners?: string[]; // Owner user IDs
|
|
171
|
-
extensions?: string[]; // File extensions (default: ['.js', '.
|
|
174
|
+
extensions?: string[]; // File extensions (default: ['.js', '.mjs', '.cjs'])
|
|
172
175
|
disableMentionPrefix?: boolean; // Disable @bot prefix
|
|
173
176
|
}
|
|
177
|
+
|
|
178
|
+
// Default auto-discovery is discordx-like: scans broadly under process.cwd(),
|
|
179
|
+
// then registers only files that look like decorated command modules.
|
|
174
180
|
```
|
|
175
181
|
|
|
176
182
|
## Dynamic Prefix
|
|
@@ -178,32 +184,35 @@ interface MallyHandlerOptions {
|
|
|
178
184
|
```typescript
|
|
179
185
|
const handler = new MallyHandler({
|
|
180
186
|
client,
|
|
181
|
-
commandsDir: join(__dirname, 'commands'),
|
|
182
187
|
prefix: async ({ serverId }) => {
|
|
183
188
|
// Fetch from database, etc.
|
|
184
189
|
return serverId ? await getServerPrefix(serverId) : '!';
|
|
185
190
|
},
|
|
186
191
|
});
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Legacy Class-Based Commands
|
|
190
|
-
|
|
191
|
-
You can also use the class-based approach:
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
// Optional: constrain auto-discovery to specific roots/patterns
|
|
194
|
+
const scopedHandler = new MallyHandler({
|
|
195
|
+
client,
|
|
196
|
+
prefix: '!',
|
|
197
|
+
discovery: {
|
|
198
|
+
roots: [process.cwd()],
|
|
199
|
+
include: ['apps/bot/dist/commands/**/*.js'],
|
|
200
|
+
},
|
|
201
|
+
});
|
|
195
202
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
}
|
|
203
|
+
// TypeScript source discovery is opt-in and requires a TS runtime loader (tsx/ts-node)
|
|
204
|
+
const tsRuntimeHandler = new MallyHandler({
|
|
205
|
+
client,
|
|
206
|
+
prefix: '!',
|
|
207
|
+
extensions: ['.ts'],
|
|
208
|
+
discovery: {
|
|
209
|
+
include: ['apps/bot/src/commands/**/*.ts'],
|
|
210
|
+
},
|
|
211
|
+
});
|
|
205
212
|
```
|
|
206
213
|
|
|
214
|
+
All commands are defined through `@Stoat()` classes and `@SimpleCommand()` methods.
|
|
215
|
+
|
|
207
216
|
## License
|
|
208
217
|
|
|
209
218
|
AGPL-3.0-or-later
|
package/dist/index.d.mts
CHANGED
|
@@ -4,27 +4,6 @@ import { Client, Message } from 'stoat.js';
|
|
|
4
4
|
* Permission types for commands
|
|
5
5
|
*/
|
|
6
6
|
type Permission = "SendMessages" | "ManageMessages" | "ManageChannels" | "ManageServer" | "KickMembers" | "BanMembers" | "Administrator" | (string & {});
|
|
7
|
-
/**
|
|
8
|
-
* Command metadata options passed to @Command decorator
|
|
9
|
-
*/
|
|
10
|
-
interface CommandOptions {
|
|
11
|
-
/** Command name (defaults to class name without 'Command' suffix) */
|
|
12
|
-
name?: string;
|
|
13
|
-
/** Command description */
|
|
14
|
-
description?: string;
|
|
15
|
-
/** Command aliases */
|
|
16
|
-
aliases?: string[];
|
|
17
|
-
/** Required permissions to run the command */
|
|
18
|
-
permissions?: Permission[];
|
|
19
|
-
/** Command category (auto-detected from directory if not provided) */
|
|
20
|
-
category?: string;
|
|
21
|
-
/** Cooldown in milliseconds */
|
|
22
|
-
cooldown?: number;
|
|
23
|
-
/** Whether the command is NSFW only */
|
|
24
|
-
nsfw?: boolean;
|
|
25
|
-
/** Whether the command is owner only */
|
|
26
|
-
ownerOnly?: boolean;
|
|
27
|
-
}
|
|
28
7
|
/**
|
|
29
8
|
* Simple command options passed to @SimpleCommand decorator
|
|
30
9
|
* Used with @Stoat() decorated classes for method-based commands
|
|
@@ -86,20 +65,12 @@ interface CommandContext {
|
|
|
86
65
|
message: Message;
|
|
87
66
|
}
|
|
88
67
|
/**
|
|
89
|
-
*
|
|
68
|
+
* Optional lifecycle hooks for @Stoat() class instances
|
|
90
69
|
*/
|
|
91
|
-
interface
|
|
92
|
-
/**
|
|
93
|
-
metadata: CommandMetadata;
|
|
94
|
-
/**
|
|
95
|
-
* Execute the command
|
|
96
|
-
*/
|
|
97
|
-
run(ctx: CommandContext): Promise<void>;
|
|
98
|
-
/**
|
|
99
|
-
* Optional: Called when an error occurs during command execution
|
|
100
|
-
*/
|
|
70
|
+
interface StoatLifecycle {
|
|
71
|
+
/** Optional: Called when an error occurs during command execution */
|
|
101
72
|
onError?(ctx: CommandContext, error: Error): Promise<void>;
|
|
102
|
-
|
|
73
|
+
/** Optional: Called when a cooldown is active */
|
|
103
74
|
onCooldown?(ctx: CommandContext, remaining: number): Promise<void>;
|
|
104
75
|
}
|
|
105
76
|
interface MallyGuard {
|
|
@@ -107,53 +78,33 @@ interface MallyGuard {
|
|
|
107
78
|
guardFail?(ctx: CommandContext): Promise<void> | void;
|
|
108
79
|
}
|
|
109
80
|
/**
|
|
110
|
-
*
|
|
111
|
-
* Extend this class to create commands without boilerplate.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```ts
|
|
115
|
-
* @Command({ name: 'ping', description: 'Replies with Pong!' })
|
|
116
|
-
* export class PingCommand extends BaseCommand {
|
|
117
|
-
* async run(ctx) {
|
|
118
|
-
* await ctx.reply('Pong!');
|
|
119
|
-
* }
|
|
120
|
-
* }
|
|
121
|
-
* ```
|
|
81
|
+
* Discovery options for automatic command module loading
|
|
122
82
|
*/
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
abstract run(ctx: CommandContext): Promise<void>;
|
|
132
|
-
/**
|
|
133
|
-
* Optional: Called when an error occurs during command execution.
|
|
134
|
-
* Override this method to provide custom error handling.
|
|
135
|
-
*/
|
|
136
|
-
onError(ctx: CommandContext, error: Error): Promise<void>;
|
|
83
|
+
interface MallyDiscoveryOptions {
|
|
84
|
+
/** Root directories to scan (default: [process.cwd()]) */
|
|
85
|
+
roots?: string[];
|
|
86
|
+
/** Glob patterns relative to each root */
|
|
87
|
+
include?: string[];
|
|
88
|
+
/** Additional ignore patterns */
|
|
89
|
+
ignore?: string[];
|
|
137
90
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Constructor type for command classes
|
|
140
|
-
*/
|
|
141
|
-
type CommandConstructor = new () => MallyCommand;
|
|
142
91
|
/**
|
|
143
92
|
* Handler options
|
|
144
93
|
*/
|
|
145
94
|
interface MallyHandlerOptions {
|
|
146
95
|
/** The client instance */
|
|
147
96
|
client: Client;
|
|
148
|
-
/** Directory to scan for
|
|
149
|
-
commandsDir
|
|
97
|
+
/** Directory to scan for command modules (absolute path) */
|
|
98
|
+
commandsDir?: string;
|
|
99
|
+
/** Auto-discovery options used when commandsDir is not provided */
|
|
100
|
+
discovery?: MallyDiscoveryOptions;
|
|
150
101
|
/** Command prefix or prefix resolver function */
|
|
151
102
|
prefix: string | ((ctx: {
|
|
152
103
|
serverId?: string;
|
|
153
104
|
}) => string | Promise<string>);
|
|
154
105
|
/** Owner IDs for owner-only commands */
|
|
155
106
|
owners?: string[];
|
|
156
|
-
/** File extensions to load (default: ['.js', '.
|
|
107
|
+
/** File extensions to load (default: ['.js', '.mjs', '.cjs']) */
|
|
157
108
|
extensions?: string[];
|
|
158
109
|
/** Disable mention prefix support (default: false) */
|
|
159
110
|
disableMentionPrefix?: boolean;
|
|
@@ -221,49 +172,11 @@ declare function SimpleCommand(options?: SimpleCommandOptions): MethodDecorator;
|
|
|
221
172
|
*/
|
|
222
173
|
declare function getSimpleCommands(target: Function): SimpleCommandDefinition[];
|
|
223
174
|
|
|
224
|
-
/**
|
|
225
|
-
* @Command
|
|
226
|
-
* Marks a class as a command and attaches metadata.
|
|
227
|
-
* This is the legacy/class-based approach where each command is a separate class.
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* ```ts
|
|
231
|
-
* import { Command, MallyCommand, CommandContext } from '@marshmallow/mally';
|
|
232
|
-
*
|
|
233
|
-
* @Command({
|
|
234
|
-
* description: 'Ban a user from the server',
|
|
235
|
-
* aliases: ['b'],
|
|
236
|
-
* permissions: ['BanMembers']
|
|
237
|
-
* })
|
|
238
|
-
* export class BanCommand implements MallyCommand {
|
|
239
|
-
* metadata!: CommandMetadata;
|
|
240
|
-
*
|
|
241
|
-
* async run(ctx: CommandContext) {
|
|
242
|
-
* const userId = ctx.args[0];
|
|
243
|
-
* await ctx.reply(`Banned user ${userId}`);
|
|
244
|
-
* }
|
|
245
|
-
* }
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
|
-
declare function Command(options?: CommandOptions): ClassDecorator;
|
|
249
|
-
/**
|
|
250
|
-
* Check if a class is decorated with @Command
|
|
251
|
-
*/
|
|
252
|
-
declare function isCommand(target: Function): boolean;
|
|
253
|
-
/**
|
|
254
|
-
* Get command options from a decorated class
|
|
255
|
-
*/
|
|
256
|
-
declare function getCommandOptions(target: Function): CommandOptions | undefined;
|
|
257
|
-
/**
|
|
258
|
-
* Build complete CommandMetadata from options and class name
|
|
259
|
-
*/
|
|
260
|
-
declare function buildCommandMetadata(target: Function, options: CommandOptions, category?: string): CommandMetadata;
|
|
261
|
-
|
|
262
175
|
/**
|
|
263
176
|
* @Guard
|
|
264
177
|
* Runs before a command to check if it should execute.
|
|
265
178
|
* Should return true to allow execution, false to block.
|
|
266
|
-
*
|
|
179
|
+
* Applied on @Stoat classes to guard all contained @SimpleCommand methods.
|
|
267
180
|
*
|
|
268
181
|
* @example
|
|
269
182
|
* ```ts
|
|
@@ -305,23 +218,26 @@ declare function buildSimpleCommandMetadata(options: SimpleCommandOptions, metho
|
|
|
305
218
|
* Metadata keys used by decorators
|
|
306
219
|
*/
|
|
307
220
|
declare const METADATA_KEYS: {
|
|
308
|
-
readonly COMMAND_OPTIONS: symbol;
|
|
309
|
-
readonly IS_COMMAND: symbol;
|
|
310
221
|
readonly IS_STOAT_CLASS: symbol;
|
|
311
222
|
readonly SIMPLE_COMMANDS: symbol;
|
|
312
223
|
readonly GUARDS: "mally:command:guards";
|
|
313
224
|
};
|
|
314
225
|
|
|
226
|
+
interface AutoDiscoveryOptions {
|
|
227
|
+
roots?: string[];
|
|
228
|
+
include?: string[];
|
|
229
|
+
ignore?: string[];
|
|
230
|
+
}
|
|
315
231
|
/**
|
|
316
|
-
* Stored command entry
|
|
232
|
+
* Stored command entry from @Stoat/@SimpleCommand registration.
|
|
317
233
|
*/
|
|
318
234
|
interface RegisteredCommand {
|
|
319
|
-
/** Instance of the
|
|
320
|
-
instance:
|
|
235
|
+
/** Instance of the @Stoat class */
|
|
236
|
+
instance: object;
|
|
321
237
|
/** Command metadata */
|
|
322
238
|
metadata: CommandMetadata;
|
|
323
|
-
/** Method name to call
|
|
324
|
-
methodName
|
|
239
|
+
/** Method name to call */
|
|
240
|
+
methodName: string;
|
|
325
241
|
/** The original class constructor (for guard validation) */
|
|
326
242
|
classConstructor: Function;
|
|
327
243
|
}
|
|
@@ -338,9 +254,11 @@ interface RegisteredCommand {
|
|
|
338
254
|
* ```
|
|
339
255
|
*/
|
|
340
256
|
declare class CommandRegistry {
|
|
257
|
+
private static readonly DEFAULT_AUTO_DISCOVERY_IGNORES;
|
|
341
258
|
private readonly commands;
|
|
342
259
|
private readonly aliases;
|
|
343
260
|
private readonly extensions;
|
|
261
|
+
private readonly processedStoatClasses;
|
|
344
262
|
constructor(extensions?: string[]);
|
|
345
263
|
/**
|
|
346
264
|
* Get the number of registered commands
|
|
@@ -350,10 +268,16 @@ declare class CommandRegistry {
|
|
|
350
268
|
* Load commands from a directory using glob pattern matching
|
|
351
269
|
*/
|
|
352
270
|
loadFromDirectory(directory: string): Promise<void>;
|
|
271
|
+
/**
|
|
272
|
+
* Auto-discover command files across one or more roots.
|
|
273
|
+
*/
|
|
274
|
+
autoDiscover(options?: AutoDiscoveryOptions): Promise<void>;
|
|
275
|
+
private getDefaultAutoDiscoveryPatterns;
|
|
276
|
+
private isLikelyCommandModule;
|
|
353
277
|
/**
|
|
354
278
|
* Register a command instance
|
|
355
279
|
*/
|
|
356
|
-
register(instance:
|
|
280
|
+
register(instance: object, metadata: CommandMetadata, classConstructor: Function, methodName: string): void;
|
|
357
281
|
/**
|
|
358
282
|
* Get a command by name or alias
|
|
359
283
|
*/
|
|
@@ -397,17 +321,11 @@ declare class CommandRegistry {
|
|
|
397
321
|
* @private
|
|
398
322
|
*/
|
|
399
323
|
private validateGuards;
|
|
400
|
-
/**
|
|
401
|
-
* Validate that commands with cooldowns implement the onCooldown method
|
|
402
|
-
* @param instance
|
|
403
|
-
* @param metadata
|
|
404
|
-
* @private
|
|
405
|
-
*/
|
|
406
|
-
private validateCooldown;
|
|
407
324
|
/**
|
|
408
325
|
* Load commands from a single file
|
|
409
326
|
*/
|
|
410
327
|
private loadFile;
|
|
328
|
+
private registerStoatClassCommands;
|
|
411
329
|
/**
|
|
412
330
|
* Derive category from file path relative to base directory
|
|
413
331
|
*/
|
|
@@ -428,7 +346,6 @@ declare class CommandRegistry {
|
|
|
428
346
|
*
|
|
429
347
|
* const handler = new MallyHandler({
|
|
430
348
|
* client,
|
|
431
|
-
* commandsDir: path.join(__dirname, 'commands'),
|
|
432
349
|
* prefix: '!',
|
|
433
350
|
* owners: ['owner-user-id'],
|
|
434
351
|
* });
|
|
@@ -441,7 +358,8 @@ declare class CommandRegistry {
|
|
|
441
358
|
* ```
|
|
442
359
|
*/
|
|
443
360
|
declare class MallyHandler {
|
|
444
|
-
private readonly commandsDir
|
|
361
|
+
private readonly commandsDir?;
|
|
362
|
+
private readonly discoveryOptions?;
|
|
445
363
|
private readonly prefixResolver;
|
|
446
364
|
private readonly owners;
|
|
447
365
|
private readonly registry;
|
|
@@ -546,4 +464,4 @@ declare class MallyHandler {
|
|
|
546
464
|
private setCooldown;
|
|
547
465
|
}
|
|
548
466
|
|
|
549
|
-
export {
|
|
467
|
+
export { type CommandContext, type CommandMetadata, CommandRegistry, type CommandContext as Context, Guard, METADATA_KEYS, type MallyDiscoveryOptions, type MallyGuard, MallyHandler, type MallyHandlerOptions, type Permission, type RegisteredCommand, SimpleCommand, type SimpleCommandDefinition, type SimpleCommandOptions, Stoat, type StoatLifecycle, buildSimpleCommandMetadata, getGuards, getSimpleCommands, isStoatClass };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,27 +4,6 @@ import { Client, Message } from 'stoat.js';
|
|
|
4
4
|
* Permission types for commands
|
|
5
5
|
*/
|
|
6
6
|
type Permission = "SendMessages" | "ManageMessages" | "ManageChannels" | "ManageServer" | "KickMembers" | "BanMembers" | "Administrator" | (string & {});
|
|
7
|
-
/**
|
|
8
|
-
* Command metadata options passed to @Command decorator
|
|
9
|
-
*/
|
|
10
|
-
interface CommandOptions {
|
|
11
|
-
/** Command name (defaults to class name without 'Command' suffix) */
|
|
12
|
-
name?: string;
|
|
13
|
-
/** Command description */
|
|
14
|
-
description?: string;
|
|
15
|
-
/** Command aliases */
|
|
16
|
-
aliases?: string[];
|
|
17
|
-
/** Required permissions to run the command */
|
|
18
|
-
permissions?: Permission[];
|
|
19
|
-
/** Command category (auto-detected from directory if not provided) */
|
|
20
|
-
category?: string;
|
|
21
|
-
/** Cooldown in milliseconds */
|
|
22
|
-
cooldown?: number;
|
|
23
|
-
/** Whether the command is NSFW only */
|
|
24
|
-
nsfw?: boolean;
|
|
25
|
-
/** Whether the command is owner only */
|
|
26
|
-
ownerOnly?: boolean;
|
|
27
|
-
}
|
|
28
7
|
/**
|
|
29
8
|
* Simple command options passed to @SimpleCommand decorator
|
|
30
9
|
* Used with @Stoat() decorated classes for method-based commands
|
|
@@ -86,20 +65,12 @@ interface CommandContext {
|
|
|
86
65
|
message: Message;
|
|
87
66
|
}
|
|
88
67
|
/**
|
|
89
|
-
*
|
|
68
|
+
* Optional lifecycle hooks for @Stoat() class instances
|
|
90
69
|
*/
|
|
91
|
-
interface
|
|
92
|
-
/**
|
|
93
|
-
metadata: CommandMetadata;
|
|
94
|
-
/**
|
|
95
|
-
* Execute the command
|
|
96
|
-
*/
|
|
97
|
-
run(ctx: CommandContext): Promise<void>;
|
|
98
|
-
/**
|
|
99
|
-
* Optional: Called when an error occurs during command execution
|
|
100
|
-
*/
|
|
70
|
+
interface StoatLifecycle {
|
|
71
|
+
/** Optional: Called when an error occurs during command execution */
|
|
101
72
|
onError?(ctx: CommandContext, error: Error): Promise<void>;
|
|
102
|
-
|
|
73
|
+
/** Optional: Called when a cooldown is active */
|
|
103
74
|
onCooldown?(ctx: CommandContext, remaining: number): Promise<void>;
|
|
104
75
|
}
|
|
105
76
|
interface MallyGuard {
|
|
@@ -107,53 +78,33 @@ interface MallyGuard {
|
|
|
107
78
|
guardFail?(ctx: CommandContext): Promise<void> | void;
|
|
108
79
|
}
|
|
109
80
|
/**
|
|
110
|
-
*
|
|
111
|
-
* Extend this class to create commands without boilerplate.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```ts
|
|
115
|
-
* @Command({ name: 'ping', description: 'Replies with Pong!' })
|
|
116
|
-
* export class PingCommand extends BaseCommand {
|
|
117
|
-
* async run(ctx) {
|
|
118
|
-
* await ctx.reply('Pong!');
|
|
119
|
-
* }
|
|
120
|
-
* }
|
|
121
|
-
* ```
|
|
81
|
+
* Discovery options for automatic command module loading
|
|
122
82
|
*/
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
abstract run(ctx: CommandContext): Promise<void>;
|
|
132
|
-
/**
|
|
133
|
-
* Optional: Called when an error occurs during command execution.
|
|
134
|
-
* Override this method to provide custom error handling.
|
|
135
|
-
*/
|
|
136
|
-
onError(ctx: CommandContext, error: Error): Promise<void>;
|
|
83
|
+
interface MallyDiscoveryOptions {
|
|
84
|
+
/** Root directories to scan (default: [process.cwd()]) */
|
|
85
|
+
roots?: string[];
|
|
86
|
+
/** Glob patterns relative to each root */
|
|
87
|
+
include?: string[];
|
|
88
|
+
/** Additional ignore patterns */
|
|
89
|
+
ignore?: string[];
|
|
137
90
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Constructor type for command classes
|
|
140
|
-
*/
|
|
141
|
-
type CommandConstructor = new () => MallyCommand;
|
|
142
91
|
/**
|
|
143
92
|
* Handler options
|
|
144
93
|
*/
|
|
145
94
|
interface MallyHandlerOptions {
|
|
146
95
|
/** The client instance */
|
|
147
96
|
client: Client;
|
|
148
|
-
/** Directory to scan for
|
|
149
|
-
commandsDir
|
|
97
|
+
/** Directory to scan for command modules (absolute path) */
|
|
98
|
+
commandsDir?: string;
|
|
99
|
+
/** Auto-discovery options used when commandsDir is not provided */
|
|
100
|
+
discovery?: MallyDiscoveryOptions;
|
|
150
101
|
/** Command prefix or prefix resolver function */
|
|
151
102
|
prefix: string | ((ctx: {
|
|
152
103
|
serverId?: string;
|
|
153
104
|
}) => string | Promise<string>);
|
|
154
105
|
/** Owner IDs for owner-only commands */
|
|
155
106
|
owners?: string[];
|
|
156
|
-
/** File extensions to load (default: ['.js', '.
|
|
107
|
+
/** File extensions to load (default: ['.js', '.mjs', '.cjs']) */
|
|
157
108
|
extensions?: string[];
|
|
158
109
|
/** Disable mention prefix support (default: false) */
|
|
159
110
|
disableMentionPrefix?: boolean;
|
|
@@ -221,49 +172,11 @@ declare function SimpleCommand(options?: SimpleCommandOptions): MethodDecorator;
|
|
|
221
172
|
*/
|
|
222
173
|
declare function getSimpleCommands(target: Function): SimpleCommandDefinition[];
|
|
223
174
|
|
|
224
|
-
/**
|
|
225
|
-
* @Command
|
|
226
|
-
* Marks a class as a command and attaches metadata.
|
|
227
|
-
* This is the legacy/class-based approach where each command is a separate class.
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* ```ts
|
|
231
|
-
* import { Command, MallyCommand, CommandContext } from '@marshmallow/mally';
|
|
232
|
-
*
|
|
233
|
-
* @Command({
|
|
234
|
-
* description: 'Ban a user from the server',
|
|
235
|
-
* aliases: ['b'],
|
|
236
|
-
* permissions: ['BanMembers']
|
|
237
|
-
* })
|
|
238
|
-
* export class BanCommand implements MallyCommand {
|
|
239
|
-
* metadata!: CommandMetadata;
|
|
240
|
-
*
|
|
241
|
-
* async run(ctx: CommandContext) {
|
|
242
|
-
* const userId = ctx.args[0];
|
|
243
|
-
* await ctx.reply(`Banned user ${userId}`);
|
|
244
|
-
* }
|
|
245
|
-
* }
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
|
-
declare function Command(options?: CommandOptions): ClassDecorator;
|
|
249
|
-
/**
|
|
250
|
-
* Check if a class is decorated with @Command
|
|
251
|
-
*/
|
|
252
|
-
declare function isCommand(target: Function): boolean;
|
|
253
|
-
/**
|
|
254
|
-
* Get command options from a decorated class
|
|
255
|
-
*/
|
|
256
|
-
declare function getCommandOptions(target: Function): CommandOptions | undefined;
|
|
257
|
-
/**
|
|
258
|
-
* Build complete CommandMetadata from options and class name
|
|
259
|
-
*/
|
|
260
|
-
declare function buildCommandMetadata(target: Function, options: CommandOptions, category?: string): CommandMetadata;
|
|
261
|
-
|
|
262
175
|
/**
|
|
263
176
|
* @Guard
|
|
264
177
|
* Runs before a command to check if it should execute.
|
|
265
178
|
* Should return true to allow execution, false to block.
|
|
266
|
-
*
|
|
179
|
+
* Applied on @Stoat classes to guard all contained @SimpleCommand methods.
|
|
267
180
|
*
|
|
268
181
|
* @example
|
|
269
182
|
* ```ts
|
|
@@ -305,23 +218,26 @@ declare function buildSimpleCommandMetadata(options: SimpleCommandOptions, metho
|
|
|
305
218
|
* Metadata keys used by decorators
|
|
306
219
|
*/
|
|
307
220
|
declare const METADATA_KEYS: {
|
|
308
|
-
readonly COMMAND_OPTIONS: symbol;
|
|
309
|
-
readonly IS_COMMAND: symbol;
|
|
310
221
|
readonly IS_STOAT_CLASS: symbol;
|
|
311
222
|
readonly SIMPLE_COMMANDS: symbol;
|
|
312
223
|
readonly GUARDS: "mally:command:guards";
|
|
313
224
|
};
|
|
314
225
|
|
|
226
|
+
interface AutoDiscoveryOptions {
|
|
227
|
+
roots?: string[];
|
|
228
|
+
include?: string[];
|
|
229
|
+
ignore?: string[];
|
|
230
|
+
}
|
|
315
231
|
/**
|
|
316
|
-
* Stored command entry
|
|
232
|
+
* Stored command entry from @Stoat/@SimpleCommand registration.
|
|
317
233
|
*/
|
|
318
234
|
interface RegisteredCommand {
|
|
319
|
-
/** Instance of the
|
|
320
|
-
instance:
|
|
235
|
+
/** Instance of the @Stoat class */
|
|
236
|
+
instance: object;
|
|
321
237
|
/** Command metadata */
|
|
322
238
|
metadata: CommandMetadata;
|
|
323
|
-
/** Method name to call
|
|
324
|
-
methodName
|
|
239
|
+
/** Method name to call */
|
|
240
|
+
methodName: string;
|
|
325
241
|
/** The original class constructor (for guard validation) */
|
|
326
242
|
classConstructor: Function;
|
|
327
243
|
}
|
|
@@ -338,9 +254,11 @@ interface RegisteredCommand {
|
|
|
338
254
|
* ```
|
|
339
255
|
*/
|
|
340
256
|
declare class CommandRegistry {
|
|
257
|
+
private static readonly DEFAULT_AUTO_DISCOVERY_IGNORES;
|
|
341
258
|
private readonly commands;
|
|
342
259
|
private readonly aliases;
|
|
343
260
|
private readonly extensions;
|
|
261
|
+
private readonly processedStoatClasses;
|
|
344
262
|
constructor(extensions?: string[]);
|
|
345
263
|
/**
|
|
346
264
|
* Get the number of registered commands
|
|
@@ -350,10 +268,16 @@ declare class CommandRegistry {
|
|
|
350
268
|
* Load commands from a directory using glob pattern matching
|
|
351
269
|
*/
|
|
352
270
|
loadFromDirectory(directory: string): Promise<void>;
|
|
271
|
+
/**
|
|
272
|
+
* Auto-discover command files across one or more roots.
|
|
273
|
+
*/
|
|
274
|
+
autoDiscover(options?: AutoDiscoveryOptions): Promise<void>;
|
|
275
|
+
private getDefaultAutoDiscoveryPatterns;
|
|
276
|
+
private isLikelyCommandModule;
|
|
353
277
|
/**
|
|
354
278
|
* Register a command instance
|
|
355
279
|
*/
|
|
356
|
-
register(instance:
|
|
280
|
+
register(instance: object, metadata: CommandMetadata, classConstructor: Function, methodName: string): void;
|
|
357
281
|
/**
|
|
358
282
|
* Get a command by name or alias
|
|
359
283
|
*/
|
|
@@ -397,17 +321,11 @@ declare class CommandRegistry {
|
|
|
397
321
|
* @private
|
|
398
322
|
*/
|
|
399
323
|
private validateGuards;
|
|
400
|
-
/**
|
|
401
|
-
* Validate that commands with cooldowns implement the onCooldown method
|
|
402
|
-
* @param instance
|
|
403
|
-
* @param metadata
|
|
404
|
-
* @private
|
|
405
|
-
*/
|
|
406
|
-
private validateCooldown;
|
|
407
324
|
/**
|
|
408
325
|
* Load commands from a single file
|
|
409
326
|
*/
|
|
410
327
|
private loadFile;
|
|
328
|
+
private registerStoatClassCommands;
|
|
411
329
|
/**
|
|
412
330
|
* Derive category from file path relative to base directory
|
|
413
331
|
*/
|
|
@@ -428,7 +346,6 @@ declare class CommandRegistry {
|
|
|
428
346
|
*
|
|
429
347
|
* const handler = new MallyHandler({
|
|
430
348
|
* client,
|
|
431
|
-
* commandsDir: path.join(__dirname, 'commands'),
|
|
432
349
|
* prefix: '!',
|
|
433
350
|
* owners: ['owner-user-id'],
|
|
434
351
|
* });
|
|
@@ -441,7 +358,8 @@ declare class CommandRegistry {
|
|
|
441
358
|
* ```
|
|
442
359
|
*/
|
|
443
360
|
declare class MallyHandler {
|
|
444
|
-
private readonly commandsDir
|
|
361
|
+
private readonly commandsDir?;
|
|
362
|
+
private readonly discoveryOptions?;
|
|
445
363
|
private readonly prefixResolver;
|
|
446
364
|
private readonly owners;
|
|
447
365
|
private readonly registry;
|
|
@@ -546,4 +464,4 @@ declare class MallyHandler {
|
|
|
546
464
|
private setCooldown;
|
|
547
465
|
}
|
|
548
466
|
|
|
549
|
-
export {
|
|
467
|
+
export { type CommandContext, type CommandMetadata, CommandRegistry, type CommandContext as Context, Guard, METADATA_KEYS, type MallyDiscoveryOptions, type MallyGuard, MallyHandler, type MallyHandlerOptions, type Permission, type RegisteredCommand, SimpleCommand, type SimpleCommandDefinition, type SimpleCommandOptions, Stoat, type StoatLifecycle, buildSimpleCommandMetadata, getGuards, getSimpleCommands, isStoatClass };
|