stoatx 0.5.0 → 0.5.2
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 +2 -2
- package/dist/index.d.mts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -5
- package/dist/index.mjs.map +1 -0
- package/package.json +4 -10
- package/dist/.tsbuildinfo +0 -1
- package/dist/decorators/Events.d.ts +0 -55
- package/dist/decorators/Events.d.ts.map +0 -1
- package/dist/decorators/Events.js +0 -71
- package/dist/decorators/Events.js.map +0 -1
- package/dist/decorators/Guard.d.ts +0 -38
- package/dist/decorators/Guard.d.ts.map +0 -1
- package/dist/decorators/Guard.js +0 -47
- package/dist/decorators/Guard.js.map +0 -1
- package/dist/decorators/SimpleCommand.d.ts +0 -35
- package/dist/decorators/SimpleCommand.d.ts.map +0 -1
- package/dist/decorators/SimpleCommand.js +0 -43
- package/dist/decorators/SimpleCommand.js.map +0 -1
- package/dist/decorators/Stoat.d.ts +0 -30
- package/dist/decorators/Stoat.d.ts.map +0 -1
- package/dist/decorators/Stoat.js +0 -39
- package/dist/decorators/Stoat.js.map +0 -1
- package/dist/decorators/index.d.ts +0 -9
- package/dist/decorators/index.d.ts.map +0 -1
- package/dist/decorators/index.js +0 -10
- package/dist/decorators/index.js.map +0 -1
- package/dist/decorators/keys.d.ts +0 -10
- package/dist/decorators/keys.d.ts.map +0 -1
- package/dist/decorators/keys.js +0 -10
- package/dist/decorators/keys.js.map +0 -1
- package/dist/decorators/store.d.ts +0 -46
- package/dist/decorators/store.d.ts.map +0 -1
- package/dist/decorators/store.js +0 -70
- package/dist/decorators/store.js.map +0 -1
- package/dist/decorators/utils.d.ts +0 -6
- package/dist/decorators/utils.d.ts.map +0 -1
- package/dist/decorators/utils.js +0 -16
- package/dist/decorators/utils.js.map +0 -1
- package/dist/decorators.d.ts +0 -9
- package/dist/decorators.d.ts.map +0 -1
- package/dist/decorators.js +0 -21
- package/dist/decorators.js.map +0 -1
- package/dist/handler.d.ts +0 -145
- package/dist/handler.d.ts.map +0 -1
- package/dist/handler.js +0 -355
- package/dist/handler.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/registry.d.ts +0 -125
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -279
- package/dist/registry.js.map +0 -1
- package/dist/types.d.ts +0 -111
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# stoatx
|
|
2
2
|
|
|
3
|
-
A high-performance, decorator-based command handler for
|
|
3
|
+
A high-performance, decorator-based command handler for Stoat bots. Inspired by [discordx](https://github.com/discordx-ts/discordx).
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -204,4 +204,4 @@ All commands are defined through `@Stoat()` classes and `@SimpleCommand()` metho
|
|
|
204
204
|
|
|
205
205
|
## License
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
MIT © [Stoatx / Stoatx Team]
|
package/dist/index.d.mts
CHANGED
|
@@ -53,7 +53,7 @@ interface CommandContext {
|
|
|
53
53
|
/** The channel ID */
|
|
54
54
|
channelId: string;
|
|
55
55
|
/** The server/guild ID (if applicable) */
|
|
56
|
-
serverId?: string;
|
|
56
|
+
serverId?: string | undefined;
|
|
57
57
|
/** Parsed command arguments */
|
|
58
58
|
args: string[];
|
|
59
59
|
/** The prefix used */
|
|
@@ -101,7 +101,7 @@ interface StoatxHandlerOptions {
|
|
|
101
101
|
discovery?: StoatxDiscoveryOptions;
|
|
102
102
|
/** Command prefix or prefix resolver function */
|
|
103
103
|
prefix: string | ((ctx: {
|
|
104
|
-
serverId?: string;
|
|
104
|
+
serverId?: string | undefined;
|
|
105
105
|
}) => string | Promise<string>);
|
|
106
106
|
/** Owner IDs for owner-only commands */
|
|
107
107
|
owners?: string[];
|
|
@@ -456,7 +456,7 @@ declare class StoatxHandler {
|
|
|
456
456
|
parseMessage(rawContent: string, message: Message, meta: {
|
|
457
457
|
authorId: string;
|
|
458
458
|
channelId: string;
|
|
459
|
-
serverId?: string;
|
|
459
|
+
serverId?: string | undefined;
|
|
460
460
|
reply: (content: string) => Promise<Message>;
|
|
461
461
|
}): Promise<CommandContext | null>;
|
|
462
462
|
/**
|
|
@@ -470,7 +470,7 @@ declare class StoatxHandler {
|
|
|
470
470
|
* });
|
|
471
471
|
* ```
|
|
472
472
|
*/
|
|
473
|
-
handle(message:
|
|
473
|
+
handle(message: Message): Promise<boolean>;
|
|
474
474
|
/**
|
|
475
475
|
* Handle a raw message string with metadata
|
|
476
476
|
*
|
|
@@ -490,9 +490,9 @@ declare class StoatxHandler {
|
|
|
490
490
|
handleMessage(rawContent: string, message: Message, meta: {
|
|
491
491
|
authorId: string;
|
|
492
492
|
channelId: string;
|
|
493
|
-
serverId?: string;
|
|
493
|
+
serverId?: string | undefined;
|
|
494
494
|
reply: (content: string) => Promise<Message>;
|
|
495
|
-
}): Promise<
|
|
495
|
+
}): Promise<void>;
|
|
496
496
|
/**
|
|
497
497
|
* Execute a command with the given context
|
|
498
498
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ interface CommandContext {
|
|
|
53
53
|
/** The channel ID */
|
|
54
54
|
channelId: string;
|
|
55
55
|
/** The server/guild ID (if applicable) */
|
|
56
|
-
serverId?: string;
|
|
56
|
+
serverId?: string | undefined;
|
|
57
57
|
/** Parsed command arguments */
|
|
58
58
|
args: string[];
|
|
59
59
|
/** The prefix used */
|
|
@@ -101,7 +101,7 @@ interface StoatxHandlerOptions {
|
|
|
101
101
|
discovery?: StoatxDiscoveryOptions;
|
|
102
102
|
/** Command prefix or prefix resolver function */
|
|
103
103
|
prefix: string | ((ctx: {
|
|
104
|
-
serverId?: string;
|
|
104
|
+
serverId?: string | undefined;
|
|
105
105
|
}) => string | Promise<string>);
|
|
106
106
|
/** Owner IDs for owner-only commands */
|
|
107
107
|
owners?: string[];
|
|
@@ -456,7 +456,7 @@ declare class StoatxHandler {
|
|
|
456
456
|
parseMessage(rawContent: string, message: Message, meta: {
|
|
457
457
|
authorId: string;
|
|
458
458
|
channelId: string;
|
|
459
|
-
serverId?: string;
|
|
459
|
+
serverId?: string | undefined;
|
|
460
460
|
reply: (content: string) => Promise<Message>;
|
|
461
461
|
}): Promise<CommandContext | null>;
|
|
462
462
|
/**
|
|
@@ -470,7 +470,7 @@ declare class StoatxHandler {
|
|
|
470
470
|
* });
|
|
471
471
|
* ```
|
|
472
472
|
*/
|
|
473
|
-
handle(message:
|
|
473
|
+
handle(message: Message): Promise<boolean>;
|
|
474
474
|
/**
|
|
475
475
|
* Handle a raw message string with metadata
|
|
476
476
|
*
|
|
@@ -490,9 +490,9 @@ declare class StoatxHandler {
|
|
|
490
490
|
handleMessage(rawContent: string, message: Message, meta: {
|
|
491
491
|
authorId: string;
|
|
492
492
|
channelId: string;
|
|
493
|
-
serverId?: string;
|
|
493
|
+
serverId?: string | undefined;
|
|
494
494
|
reply: (content: string) => Promise<Message>;
|
|
495
|
-
}): Promise<
|
|
495
|
+
}): Promise<void>;
|
|
496
496
|
/**
|
|
497
497
|
* Execute a command with the given context
|
|
498
498
|
*/
|
package/dist/index.js
CHANGED
|
@@ -610,14 +610,15 @@ var StoatxHandler = class {
|
|
|
610
610
|
const channelId = message.channel.id;
|
|
611
611
|
const serverId = message.server?.id;
|
|
612
612
|
const reply = async (content) => {
|
|
613
|
-
return await message.channel.
|
|
613
|
+
return await message.channel.send(content);
|
|
614
614
|
};
|
|
615
|
-
|
|
615
|
+
await this.handleMessage(rawContent, message, {
|
|
616
616
|
authorId,
|
|
617
617
|
channelId,
|
|
618
618
|
serverId,
|
|
619
619
|
reply
|
|
620
620
|
});
|
|
621
|
+
return true;
|
|
621
622
|
}
|
|
622
623
|
/**
|
|
623
624
|
* Handle a raw message string with metadata
|
|
@@ -638,9 +639,9 @@ var StoatxHandler = class {
|
|
|
638
639
|
async handleMessage(rawContent, message, meta) {
|
|
639
640
|
const ctx = await this.parseMessage(rawContent, message, meta);
|
|
640
641
|
if (!ctx) {
|
|
641
|
-
return
|
|
642
|
+
return;
|
|
642
643
|
}
|
|
643
|
-
|
|
644
|
+
await this.execute(ctx);
|
|
644
645
|
}
|
|
645
646
|
/**
|
|
646
647
|
* Execute a command with the given context
|
|
@@ -690,7 +691,6 @@ var StoatxHandler = class {
|
|
|
690
691
|
await instance.onError(ctx, error);
|
|
691
692
|
} else {
|
|
692
693
|
console.error(`[Stoatx] Error in command ${metadata.name}:`, error);
|
|
693
|
-
await ctx.reply(`An error occurred: ${error.message}`);
|
|
694
694
|
}
|
|
695
695
|
return false;
|
|
696
696
|
}
|
|
@@ -804,3 +804,4 @@ __reExport(index_exports, require("@stoatx/client"), module.exports);
|
|
|
804
804
|
isStoatClass,
|
|
805
805
|
...require("@stoatx/client")
|
|
806
806
|
});
|
|
807
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,aAAa;AACb,cAAc,cAAc,CAAC;AAE7B,WAAW;AACX,cAAc,YAAY,CAAC;AAE3B,UAAU;AACV,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/decorators/Stoat.ts","../src/decorators/keys.ts","../src/decorators/store.ts","../src/decorators/SimpleCommand.ts","../src/decorators/Guard.ts","../src/decorators/Events.ts","../src/decorators/utils.ts","../src/registry.ts","../src/handler.ts"],"sourcesContent":["// Types\nexport * from \"./types\";\n\n// Decorators\nexport * from \"./decorators\";\n\n// Registry\nexport * from \"./registry\";\n\n// Handler\nexport { Client } from \"./handler\";\nexport type { StoatxHandler } from \"./handler\";\nexport * from \"@stoatx/client\";\n","import \"reflect-metadata\";\nimport { METADATA_KEYS } from \"./keys\";\nimport { decoratorStore } from \"./store\";\n\n/**\n * @Stoat\n * Marks a class as a Stoat command container.\n * Use this decorator on classes that contain @SimpleCommand methods.\n *\n * @example\n * ```ts\n * import { Stoat, SimpleCommand, CommandContext } from 'stoatx';\n *\n * @Stoat()\n * class ModerationCommands {\n * @SimpleCommand({ name: 'ban', description: 'Ban a user' })\n * async ban(ctx: CommandContext) {\n * await ctx.reply('User banned!');\n * }\n *\n * @SimpleCommand({ name: 'kick', description: 'Kick a user' })\n * async kick(ctx: CommandContext) {\n * await ctx.reply('User kicked!');\n * }\n * }\n * ```\n */\nexport function Stoat(): ClassDecorator {\n return (target: Function) => {\n Reflect.defineMetadata(METADATA_KEYS.IS_STOAT_CLASS, true, target);\n decoratorStore.registerStoatClass(target);\n };\n}\n\n/**\n * Check if a class is decorated with @Stoat\n */\nexport function isStoatClass(target: Function): boolean {\n return Reflect.getMetadata(METADATA_KEYS.IS_STOAT_CLASS, target) === true;\n}\n","/**\n * Metadata keys used by decorators\n */\nexport const METADATA_KEYS = {\n IS_STOAT_CLASS: Symbol(\"stoatx:stoat:isClass\"),\n SIMPLE_COMMANDS: Symbol(\"stoatx:stoat:simpleCommands\"),\n GUARDS: \"stoatx:command:guards\",\n EVENTS: Symbol(\"stoatx:stoat:events\"),\n} as const;\n","import type { RegisteredCommand } from \"../registry\";\n\n/**\n * Global store for all decorated classes and commands\n * This allows automatic registration without directory scanning\n */\nexport class DecoratorStore {\n private static instance: DecoratorStore;\n\n /** Stoat classes with their SimpleCommand methods */\n private stoatClasses: Map<Function, object> = new Map();\n\n /** Registered commands from @Stoat/@SimpleCommand decorators */\n private commands: RegisteredCommand[] = [];\n\n /** Whether the store has been initialized */\n private initialized = false;\n\n private constructor() {}\n\n static getInstance(): DecoratorStore {\n if (!DecoratorStore.instance) {\n DecoratorStore.instance = new DecoratorStore();\n }\n return DecoratorStore.instance;\n }\n\n /**\n * Register a @Stoat decorated class\n */\n registerStoatClass(classConstructor: Function): void {\n if (!this.stoatClasses.has(classConstructor)) {\n // Create instance immediately when decorated\n const instance = new (classConstructor as new () => object)();\n this.stoatClasses.set(classConstructor, instance);\n }\n }\n\n /**\n * Get all registered Stoat classes with their instances\n */\n getStoatClasses(): Map<Function, object> {\n return this.stoatClasses;\n }\n\n /**\n * Add a registered command\n */\n addCommand(command: RegisteredCommand): void {\n this.commands.push(command);\n }\n\n /**\n * Get all registered commands\n */\n getCommands(): RegisteredCommand[] {\n return this.commands;\n }\n\n /**\n * Clear all registered classes (useful for testing)\n */\n clear(): void {\n this.stoatClasses.clear();\n this.commands = [];\n this.initialized = false;\n }\n\n /**\n * Mark as initialized\n */\n markInitialized(): void {\n this.initialized = true;\n }\n\n /**\n * Check if initialized\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n}\n\nexport const decoratorStore = DecoratorStore.getInstance();\n","import \"reflect-metadata\";\nimport type { SimpleCommandOptions } from \"../types\";\nimport { METADATA_KEYS } from \"./keys\";\n\n/**\n * Stored simple command metadata from method decorator\n */\nexport interface SimpleCommandDefinition {\n methodName: string;\n options: SimpleCommandOptions;\n}\n\n/**\n * @SimpleCommand\n * Marks a method as a simple command within a @Stoat() decorated class.\n *\n * @example\n * ```ts\n * @Stoat()\n * class Example {\n * @SimpleCommand({ name: 'ping', description: 'Replies with Pong!' })\n * async ping(ctx: CommandContext) {\n * await ctx.reply('Pong!');\n * }\n *\n * @SimpleCommand({ aliases: ['perm'], name: 'permission' })\n * async permission(ctx: CommandContext) {\n * await ctx.reply('Access granted');\n * }\n * }\n * ```\n */\nexport function SimpleCommand(options: SimpleCommandOptions = {}): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n\n // Get existing simple commands or create new array\n const existingCommands: SimpleCommandDefinition[] =\n Reflect.getMetadata(METADATA_KEYS.SIMPLE_COMMANDS, constructor) || [];\n\n // Add this command definition\n existingCommands.push({\n methodName: String(propertyKey),\n options,\n });\n\n Reflect.defineMetadata(METADATA_KEYS.SIMPLE_COMMANDS, existingCommands, constructor);\n\n return descriptor;\n };\n}\n\n/**\n * Get all simple command definitions from a @Stoat class\n */\nexport function getSimpleCommands(target: Function): SimpleCommandDefinition[] {\n return Reflect.getMetadata(METADATA_KEYS.SIMPLE_COMMANDS, target) || [];\n}\n","import \"reflect-metadata\";\nimport { METADATA_KEYS } from \"./keys\";\n\n/**\n * @Guard\n * Runs before a command to check if it should execute.\n * Should return true to allow execution, false to block.\n * Applied on @Stoat classes to guard all contained @SimpleCommand methods.\n *\n * @example\n * ```ts\n * import { Guard, Stoat, SimpleCommand, CommandContext } from 'stoatx';\n *\n * // Define a guard\n * class NotBot implements StoatxGuard {\n * run(ctx: CommandContext): boolean {\n * return !ctx.message.author.bot;\n * }\n *\n * guardFail(ctx: CommandContext): void {\n * ctx.reply(\"Bots cannot use this command!\");\n * }\n * }\n *\n * @Stoat()\n * @Guard(NotBot)\n * class AdminCommands {\n * @SimpleCommand({ name: 'admin', description: 'Admin only command' })\n * async admin(ctx: CommandContext) {\n * ctx.reply(\"You passed the guard check!\");\n * }\n * }\n * ```\n */\nexport function Guard(guardClass: Function): ClassDecorator {\n return (target: Function) => {\n const existingGuards: Function[] = Reflect.getMetadata(METADATA_KEYS.GUARDS, target) || [];\n existingGuards.push(guardClass);\n Reflect.defineMetadata(METADATA_KEYS.GUARDS, existingGuards, target);\n };\n}\n\n/**\n * Get all guards from a decorated class\n */\nexport function getGuards(target: Function): Function[] {\n return Reflect.getMetadata(METADATA_KEYS.GUARDS, target) || [];\n}\n","import \"reflect-metadata\";\nimport { METADATA_KEYS } from \"./keys\";\n\nexport interface EventDefinition {\n methodName: string;\n event: string;\n type: \"on\" | \"once\";\n}\n\nfunction createEventDecorator(event: string, type: \"on\" | \"once\"): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n\n // Retrieve existing events or initialize a fresh array\n const existingEvents: EventDefinition[] = Reflect.getMetadata(METADATA_KEYS.EVENTS, constructor) || [];\n\n existingEvents.push({\n methodName: String(propertyKey),\n event,\n type,\n });\n\n Reflect.defineMetadata(METADATA_KEYS.EVENTS, existingEvents, constructor);\n\n return descriptor;\n };\n}\n\n/**\n * @On\n * Triggered on every occurrence of the event.\n * Marks a method to be executed whenever the specified client event is emitted.\n *\n * @example\n * ```ts\n * import { Stoat, On } from 'stoatx';\n * import { Message, Client } from 'stoat.js';\n *\n * @Stoat()\n * class BotEvents {\n * @On('messageCreate')\n * async onMessage(message: Message, client: Client) {\n * console.log('New message received:', message.content);\n * }\n * }\n * ```\n *\n * @param event The name of the client event to listen to\n */\nexport function On(event: string): MethodDecorator {\n return createEventDecorator(event, \"on\");\n}\n\n/**\n * @Once\n * Triggered only fully once.\n * Marks a method to be executed only the FIRST time the specified client event is emitted.\n *\n * @example\n * ```ts\n * import { Stoat, Once } from 'stoatx';\n * import { Client } from 'stoat.js';\n *\n * @Stoat()\n * class BotEvents {\n * @Once('ready')\n * async onReady(client: Client) {\n * console.log('Bot successfully started and logged in!');\n * }\n * }\n * ```\n *\n * @param event The name of the client event to listen to\n */\nexport function Once(event: string): MethodDecorator {\n return createEventDecorator(event, \"once\");\n}\n\n/**\n * Get all event definitions from a @Stoat class\n */\nexport function getEventsMetadata(target: Function): EventDefinition[] {\n return Reflect.getMetadata(METADATA_KEYS.EVENTS, target) || [];\n}\n","import type { CommandMetadata, SimpleCommandOptions } from \"../types\";\n\n/**\n * Build CommandMetadata from SimpleCommandOptions\n */\nexport function buildSimpleCommandMetadata(\n options: SimpleCommandOptions,\n methodName: string,\n category?: string,\n): CommandMetadata {\n return {\n name: options.name ?? methodName.toLowerCase(),\n description: options.description ?? \"No description provided\",\n aliases: options.aliases ?? [],\n permissions: options.permissions ?? [],\n category: options.category ?? category ?? \"uncategorized\",\n cooldown: options.cooldown ?? 0,\n nsfw: options.nsfw ?? false,\n ownerOnly: options.ownerOnly ?? false,\n };\n}\n","import * as path from \"node:path\";\nimport * as fs from \"node:fs/promises\";\nimport { pathToFileURL } from \"node:url\";\nimport { glob } from \"tinyglobby\";\nimport { buildSimpleCommandMetadata, getSimpleCommands, getEventsMetadata } from \"./decorators\";\nimport { decoratorStore } from \"./decorators/store\";\nimport type { CommandMetadata } from \"./types\";\n\ninterface AutoDiscoveryOptions {\n roots?: string[];\n include?: string[];\n ignore?: string[];\n}\n\n/**\n * Stored command entry from @Stoat/@SimpleCommand registration.\n */\nexport interface RegisteredCommand {\n /** Instance of the @Stoat class */\n instance: object;\n /** Command metadata */\n metadata: CommandMetadata;\n /** Method name to call */\n methodName: string;\n /** The original class constructor (for guard validation) */\n classConstructor: Function;\n}\n\n/**\n * Stored event entry from @On/@Once registration.\n */\nexport interface RegisteredEvent {\n instance: object;\n methodName: string;\n event: string;\n type: \"on\" | \"once\";\n}\n\n/**\n * CommandRegistry - Scans directories and stores commands in a Map\n *\n * @example\n * ```ts\n * const registry = new CommandRegistry();\n * await registry.loadFromDirectory('./src/commands');\n *\n * const ping = registry.get('ping');\n * const allCommands = registry.getAll();\n * ```\n */\nexport class CommandRegistry {\n private static readonly DEFAULT_AUTO_DISCOVERY_IGNORES = [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/*.d.ts\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n ];\n\n private readonly commands: Map<string, RegisteredCommand> = new Map();\n private readonly aliases: Map<string, string> = new Map();\n private readonly registeredEvents: RegisteredEvent[] = [];\n private readonly extensions: string[];\n private readonly processedStoatClasses: Set<Function> = new Set();\n\n constructor(extensions: string[] = [\".js\", \".mjs\", \".cjs\"]) {\n this.extensions = extensions;\n }\n\n /**\n * Get the number of registered commands\n */\n get size(): number {\n return this.commands.size;\n }\n\n /**\n * Load commands from a directory using glob pattern matching\n */\n async loadFromDirectory(directory: string): Promise<void> {\n const patterns = this.extensions.map((ext) => path.join(directory, \"**\", `*${ext}`).replace(/\\\\/g, \"/\"));\n\n for (const pattern of patterns) {\n const files = await glob(pattern, {\n ignore: [\"**/*.d.ts\", \"**/*.test.ts\", \"**/*.spec.ts\"],\n absolute: true,\n });\n\n for (const file of files) {\n await this.loadFile(file, directory);\n }\n }\n\n console.log(`[Stoatx] Loaded ${this.commands.size} command(s) and ${this.registeredEvents.length} event(s)`);\n }\n\n /**\n * Auto-discover command files across one or more roots.\n */\n async autoDiscover(options: AutoDiscoveryOptions = {}): Promise<void> {\n const roots = options.roots?.length ? options.roots : [process.cwd()];\n const includePatterns = options.include?.length ? options.include : this.getDefaultAutoDiscoveryPatterns();\n\n const patterns = roots.flatMap((root) =>\n includePatterns.map((pattern) => path.join(root, pattern).replace(/\\\\/g, \"/\")),\n );\n\n const files = await glob(patterns, {\n ignore: [...CommandRegistry.DEFAULT_AUTO_DISCOVERY_IGNORES, ...(options.ignore ?? [])],\n absolute: true,\n });\n\n const uniqueFiles = [...new Set(files)];\n let candidateFiles = 0;\n for (const file of uniqueFiles) {\n if (!(await this.isLikelyCommandModule(file))) {\n continue;\n }\n candidateFiles++;\n\n const baseDir =\n roots.find((root) => {\n const relative = path.relative(root, file);\n return relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n }) ?? roots[0]!;\n await this.loadFile(file, baseDir);\n }\n\n console.log(`[Stoatx] Loaded ${this.commands.size} command(s) and ${this.registeredEvents.length} event(s)`);\n }\n\n private getDefaultAutoDiscoveryPatterns(): string[] {\n // discordx-like default: scan broadly, then register only decorated classes\n return this.extensions.map((ext) => `**/*${ext}`);\n }\n\n private async isLikelyCommandModule(filePath: string): Promise<boolean> {\n try {\n const source = await fs.readFile(filePath, \"utf8\");\n return source.includes(\"Stoat\") || source.includes(\"SimpleCommand\") || source.includes(\"stoatx:command\");\n } catch {\n // If the file can't be pre-read, fall back to attempting import.\n return true;\n }\n }\n\n /**\n * Register a command instance\n */\n register(instance: object, metadata: CommandMetadata, classConstructor: Function, methodName: string): void {\n const name = metadata.name.toLowerCase();\n\n if (this.commands.has(name)) {\n console.warn(`[Stoatx] Duplicate command name: ${name}. Skipping...`);\n return;\n }\n\n this.validateGuards(classConstructor, metadata.name);\n\n this.commands.set(name, { instance, metadata, methodName, classConstructor });\n\n for (const alias of metadata.aliases) {\n const aliasLower = alias.toLowerCase();\n if (this.aliases.has(aliasLower) || this.commands.has(aliasLower)) {\n console.warn(`[Stoatx] Duplicate alias: ${aliasLower}. Skipping...`);\n continue;\n }\n this.aliases.set(aliasLower, name);\n }\n }\n\n /**\n * Get a command by name or alias\n */\n get(name: string): RegisteredCommand | undefined {\n const lowerName = name.toLowerCase();\n const resolvedName = this.aliases.get(lowerName) ?? lowerName;\n return this.commands.get(resolvedName);\n }\n\n /**\n * Check if a command exists\n */\n has(name: string): boolean {\n const lowerName = name.toLowerCase();\n return this.commands.has(lowerName) || this.aliases.has(lowerName);\n }\n\n /**\n * Get all registered commands\n */\n getAll(): RegisteredCommand[] {\n return Array.from(this.commands.values());\n }\n\n /**\n * Get all command metadata\n */\n getAllMetadata(): CommandMetadata[] {\n return this.getAll().map((c) => c.metadata);\n }\n\n /**\n * Get all registered events\n */\n getEvents(): RegisteredEvent[] {\n return this.registeredEvents;\n }\n\n /**\n * Get commands grouped by category\n */\n getByCategory(): Map<string, RegisteredCommand[]> {\n const categories = new Map<string, RegisteredCommand[]>();\n\n for (const cmd of this.commands.values()) {\n const category = cmd.metadata.category;\n const existing = categories.get(category) ?? [];\n existing.push(cmd);\n categories.set(category, existing);\n }\n\n return categories;\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands.clear();\n this.aliases.clear();\n this.registeredEvents.length = 0;\n this.processedStoatClasses.clear();\n }\n\n /**\n * Iterate over commands\n */\n [Symbol.iterator](): IterableIterator<[string, RegisteredCommand]> {\n return this.commands.entries();\n }\n\n /**\n * Iterate over command values\n */\n values(): IterableIterator<RegisteredCommand> {\n return this.commands.values();\n }\n\n /**\n * Iterate over command names\n */\n keys(): IterableIterator<string> {\n return this.commands.keys();\n }\n\n /**\n * Validate that all guards on a command implement the required methods\n * @param commandClass\n * @param commandName\n * @private\n */\n private validateGuards(commandClass: Function, commandName: string): void {\n const guards: Function[] = Reflect.getMetadata(\"stoatx:command:guards\", commandClass) || [];\n\n for (const GuardClass of guards) {\n const guardInstance = new (GuardClass as any)();\n\n if (typeof guardInstance.run !== \"function\") {\n console.error(\n `[Stoatx] FATAL: Guard \"${GuardClass.name}\" on command \"${commandName}\" does not have a run() method.`,\n );\n process.exit(1);\n }\n\n if (typeof guardInstance.guardFail !== \"function\") {\n console.error(\n `[Stoatx] FATAL: Guard \"${GuardClass.name}\" on command \"${commandName}\" does not have a guardFail() method.`,\n );\n console.error(`[Stoatx] All guards must implement guardFail() to handle failed checks.`);\n process.exit(1);\n }\n }\n }\n\n /**\n * Load commands from a single file\n */\n private async loadFile(filePath: string, baseDir: string): Promise<void> {\n try {\n const knownStoatClasses = new Set(decoratorStore.getStoatClasses().keys());\n const fileUrl = pathToFileURL(filePath).href;\n await import(fileUrl);\n\n const allStoatClasses = decoratorStore.getStoatClasses();\n for (const [stoatClass, stoatInstance] of allStoatClasses.entries()) {\n if (knownStoatClasses.has(stoatClass) || this.processedStoatClasses.has(stoatClass)) {\n continue;\n }\n this.registerStoatClassCommands(stoatClass, stoatInstance, filePath, baseDir);\n }\n } catch (error) {\n console.error(`[Stoatx] Failed to load command file: ${filePath}`, error);\n }\n }\n\n private registerStoatClassCommands(stoatClass: Function, instance: object, filePath: string, baseDir: string): void {\n const simpleCommands = getSimpleCommands(stoatClass);\n const events = getEventsMetadata(stoatClass);\n const category = this.getCategoryFromPath(filePath, baseDir);\n\n if (simpleCommands.length === 0 && events.length === 0) {\n console.warn(\n `[Stoatx] Class ${stoatClass.name} is decorated with @Stoat but has no @SimpleCommand, @On or @Once methods. Skipping...`,\n );\n this.processedStoatClasses.add(stoatClass);\n return;\n }\n\n for (const cmdDef of simpleCommands) {\n const method = (instance as any)[cmdDef.methodName];\n if (typeof method !== \"function\") {\n console.warn(`[Stoatx] Method ${cmdDef.methodName} not found on ${stoatClass.name}. Skipping...`);\n continue;\n }\n\n const metadata = buildSimpleCommandMetadata(cmdDef.options, cmdDef.methodName, category);\n this.register(instance, metadata, stoatClass, cmdDef.methodName);\n }\n\n for (const eventDef of events) {\n const method = (instance as any)[eventDef.methodName];\n if (typeof method !== \"function\") {\n console.warn(`[Stoatx] Method ${eventDef.methodName} not found on ${stoatClass.name}. Skipping...`);\n continue;\n }\n\n this.registeredEvents.push({\n instance,\n methodName: eventDef.methodName,\n event: eventDef.event,\n type: eventDef.type,\n });\n }\n\n this.processedStoatClasses.add(stoatClass);\n }\n\n /**\n * Derive category from file path relative to base directory\n */\n private getCategoryFromPath(filePath: string, baseDir: string): string | undefined {\n const relative = path.relative(baseDir, filePath);\n const parts = relative.split(path.sep);\n\n if (parts.length > 1) {\n return parts[0];\n }\n\n return undefined;\n }\n}\n","import \"reflect-metadata\";\nimport { CommandRegistry, RegisteredCommand } from \"./registry\";\nimport type { CommandContext, CommandMetadata, StoatxDiscoveryOptions, StoatxHandlerOptions } from \"./types\";\nimport { Client as StoatClient, ClientEvents, Message } from \"@stoatx/client\";\n\n/**\n * Client - An extended Client that integrates StoatxHandler directly\n *\n * @example\n * ```ts\n * import { Client } from 'stoatx';\n *\n * const client = new Client({\n * prefix: '!',\n * owners: ['owner-user-id'],\n * });\n *\n * await client.initCommands();\n * ```\n */\nexport class Client extends StoatClient {\n public readonly handler: StoatxHandler;\n\n constructor(options: Omit<StoatxHandlerOptions, \"client\">) {\n super();\n this.handler = new StoatxHandler({ ...options, client: this });\n\n // Automatically hook up the message handler\n this.on(\"messageCreate\", async (message) => {\n await this.handler.handle(message);\n });\n }\n\n /**\n * Initialize the StoatxHandler commands\n */\n async initCommands(): Promise<void> {\n await this.handler.init();\n }\n}\n\n/**\n * StoatxHandler - The execution engine for commands\n *\n * Handles message parsing, middleware execution, and command dispatching\n *\n * @internal This class is not intended to be instantiated directly. Use the `Client` from `stoatx` instead.\n */\nexport class StoatxHandler {\n private readonly commandsDir: string | undefined;\n private readonly discoveryOptions: StoatxDiscoveryOptions | undefined;\n private readonly prefixResolver: string | ((ctx: { serverId?: string | undefined }) => string | Promise<string>);\n private readonly owners: Set<string>;\n private readonly registry: CommandRegistry;\n private readonly cooldowns: Map<string, Map<string, number>> = new Map();\n private readonly disableMentionPrefix: boolean;\n private readonly client: StoatClient;\n constructor(options: StoatxHandlerOptions) {\n this.client = options.client;\n this.commandsDir = options.commandsDir;\n this.discoveryOptions = options.discovery;\n this.prefixResolver = options.prefix;\n this.owners = new Set(options.owners ?? []);\n this.registry = new CommandRegistry(options.extensions);\n this.disableMentionPrefix = options.disableMentionPrefix ?? false;\n }\n\n /**\n * Initialize the handler - load all commands\n */\n async init(): Promise<void> {\n if (this.commandsDir) {\n await this.registry.loadFromDirectory(this.commandsDir);\n } else {\n await this.registry.autoDiscover(this.discoveryOptions);\n }\n\n this.attachEvents();\n }\n\n /**\n * Attach registered events to the client\n */\n private attachEvents(): void {\n const events = this.registry.getEvents();\n\n for (const eventDef of events) {\n const handler = async (...args: any[]) => {\n try {\n await (eventDef.instance as any)[eventDef.methodName](...args, this.client);\n } catch (error) {\n console.error(\n `[Stoatx] Event Handler Error in @${eventDef.type === \"on\" ? \"On\" : \"Once\"}('${eventDef.event}'):`,\n error,\n );\n }\n };\n\n const eventName = eventDef.event as keyof ClientEvents;\n if (eventDef.type === \"once\") {\n this.client.once(eventName, handler);\n } else {\n this.client.on(eventName, handler);\n }\n }\n }\n\n /**\n * Parse a raw message into command context\n */\n async parseMessage(\n rawContent: string,\n message: Message,\n meta: {\n authorId: string;\n channelId: string;\n serverId?: string | undefined;\n reply: (content: string) => Promise<Message>;\n },\n ): Promise<CommandContext | null> {\n const prefix = await this.resolvePrefix(meta.serverId);\n let usedPrefix = prefix;\n let withoutPrefix = \"\";\n\n // Check for string prefix\n if (rawContent.startsWith(prefix)) {\n withoutPrefix = rawContent.slice(prefix.length).trim();\n usedPrefix = prefix;\n }\n // Check for mention prefix (e.g., \"<@bot-id> command\") - unless disabled\n else if (!this.disableMentionPrefix && rawContent.match(/^<@!?[\\w]+>/)) {\n const mentionMatch = rawContent.match(/^<@!?([\\w]+)>\\s*/);\n if (mentionMatch) {\n const mentionedId = mentionMatch[1];\n const botId = this.client.user?.id;\n\n // Only process if mentioned user is the bot\n if (botId && mentionedId === botId) {\n usedPrefix = mentionMatch[0];\n withoutPrefix = rawContent.slice(mentionMatch[0].length).trim();\n } else {\n }\n }\n }\n\n if (!withoutPrefix) {\n return null;\n }\n\n const [commandName, ...args] = withoutPrefix.split(/\\s+/);\n\n if (!commandName) {\n return null;\n }\n\n return {\n client: this.client,\n content: rawContent,\n authorId: meta.authorId,\n channelId: meta.channelId,\n serverId: meta.serverId,\n args,\n prefix: usedPrefix,\n commandName: commandName.toLowerCase(),\n reply: meta.reply,\n message,\n };\n }\n\n /**\n * Handle a message object using the configured message adapter\n *\n * @example\n * ```ts\n * // With message adapter configured\n * client.on('messageCreate', (message) => {\n * handler.handle(message);\n * });\n * ```\n */\n async handle(message: Message): Promise<boolean> {\n if (!message.channel || !message.author) {\n return false;\n }\n\n // Skip messages from bots\n if (message.author.bot) {\n return false;\n }\n\n const rawContent = message.content;\n const authorId = message.author.id;\n const channelId = message.channel.id;\n const serverId = message.server?.id;\n const reply = async (content: string) => {\n return await message.channel!.send(content);\n };\n\n // rawContent won't be null since a command will be invoked with a prefix\n await this.handleMessage(rawContent!, message, {\n authorId,\n channelId,\n serverId,\n reply,\n });\n\n return true;\n }\n\n /**\n * Handle a raw message string with metadata\n *\n * @example\n * ```ts\n * // Manual usage without message adapter\n * client.on('messageCreate', (message) => {\n * handler.handleMessage(message.content, message, {\n * authorId: message.author.id,\n * channelId: message.channel.id,\n * serverId: message.server?.id,\n * reply: (content) => message.channel.sendMessage(content),\n * });\n * });\n * ```\n */\n async handleMessage(\n rawContent: string,\n message: Message,\n meta: {\n authorId: string;\n channelId: string;\n serverId?: string | undefined;\n reply: (content: string) => Promise<Message>;\n },\n ): Promise<void> {\n const ctx = await this.parseMessage(rawContent, message, meta);\n\n if (!ctx) {\n return;\n }\n\n await this.execute(ctx);\n }\n\n /**\n * Execute a command with the given context\n */\n async execute(ctx: CommandContext): Promise<boolean> {\n const registered = this.registry.get(ctx.commandName);\n\n if (!registered) {\n return false;\n }\n\n const { instance, metadata, methodName, classConstructor } = registered;\n\n // Owner-only check\n if (metadata.ownerOnly && !this.owners.has(ctx.authorId)) {\n await ctx.reply(\"This command is owner-only.\");\n return false;\n }\n\n // Guard checks - use classConstructor for guard metadata\n const guards: Function[] = Reflect.getMetadata(\"stoatx:command:guards\", classConstructor) || [];\n for (const guardClass of guards) {\n const guardInstance = new (guardClass as any)();\n if (typeof guardInstance.run === \"function\") {\n const guardResult = await guardInstance.run(ctx);\n if (!guardResult) {\n if (typeof guardInstance.guardFail === \"function\") {\n await guardInstance.guardFail(ctx);\n } else {\n console.error(\"[Stoatx] Guard check failed but no guardFail method defined on\", guardClass.name);\n }\n return false;\n }\n }\n }\n\n // Cooldown check\n if (!this.checkCooldown(ctx.authorId, metadata)) {\n const remaining = this.getRemainingCooldown(ctx.authorId, metadata);\n\n // For method-based commands, check if instance has onCooldown\n if (typeof (instance as any).onCooldown === \"function\") {\n await (instance as any).onCooldown(ctx, remaining);\n } else {\n await ctx.reply(`Please wait ${(remaining / 1000).toFixed(1)} seconds before using this command again.`);\n }\n return false;\n }\n\n try {\n await (instance as any)[methodName](ctx);\n\n // Set cooldown after successful execution\n if (metadata.cooldown > 0) {\n this.setCooldown(ctx.authorId, metadata);\n }\n\n return true;\n } catch (error) {\n // Handle errors\n if (typeof (instance as any).onError === \"function\") {\n await (instance as any).onError(ctx, error as Error);\n } else {\n console.error(`[Stoatx] Error in command ${metadata.name}:`, error);\n }\n return false;\n }\n }\n\n /**\n * Get the command registry\n */\n getRegistry(): CommandRegistry {\n return this.registry;\n }\n\n /**\n * Get a command by name or alias\n */\n getCommand(name: string): RegisteredCommand | undefined {\n return this.registry.get(name);\n }\n\n /**\n * Get all commands\n */\n getCommands(): RegisteredCommand[] {\n return this.registry.getAll();\n }\n\n /**\n * Reload all commands\n */\n async reload(): Promise<void> {\n this.registry.clear();\n this.cooldowns.clear();\n if (this.commandsDir) {\n await this.registry.loadFromDirectory(this.commandsDir);\n return;\n }\n\n await this.registry.autoDiscover(this.discoveryOptions);\n }\n\n /**\n * Check if a user is an owner\n */\n isOwner(userId: string): boolean {\n return this.owners.has(userId);\n }\n\n /**\n * Add an owner\n */\n addOwner(userId: string): void {\n this.owners.add(userId);\n }\n\n /**\n * Remove an owner\n */\n removeOwner(userId: string): void {\n this.owners.delete(userId);\n }\n\n /**\n * Resolve the prefix for a context\n */\n private async resolvePrefix(serverId?: string | undefined): Promise<string> {\n if (typeof this.prefixResolver === \"function\") {\n return this.prefixResolver({ serverId });\n }\n return this.prefixResolver;\n }\n\n /**\n * Check if user is on cooldown\n */\n private checkCooldown(userId: string, metadata: CommandMetadata): boolean {\n if (metadata.cooldown <= 0) return true;\n\n const commandCooldowns = this.cooldowns.get(metadata.name);\n if (!commandCooldowns) return true;\n\n const userCooldown = commandCooldowns.get(userId);\n if (!userCooldown) return true;\n\n return Date.now() >= userCooldown;\n }\n\n /**\n * Get remaining cooldown time in ms\n */\n private getRemainingCooldown(userId: string, metadata: CommandMetadata): number {\n const commandCooldowns = this.cooldowns.get(metadata.name);\n if (!commandCooldowns) return 0;\n\n const userCooldown = commandCooldowns.get(userId);\n if (!userCooldown) return 0;\n\n return Math.max(0, userCooldown - Date.now());\n }\n\n /**\n * Set cooldown for a user\n */\n private setCooldown(userId: string, metadata: CommandMetadata): void {\n if (!this.cooldowns.has(metadata.name)) {\n this.cooldowns.set(metadata.name, new Map());\n }\n\n const commandCooldowns = this.cooldowns.get(metadata.name)!;\n commandCooldowns.set(userId, Date.now() + metadata.cooldown);\n }\n}\n"],"mappings":"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","names":["import_reflect_metadata","import_reflect_metadata","import_reflect_metadata","relative","import_reflect_metadata","StoatClient"]}
|
package/dist/index.mjs
CHANGED
|
@@ -561,14 +561,15 @@ var StoatxHandler = class {
|
|
|
561
561
|
const channelId = message.channel.id;
|
|
562
562
|
const serverId = message.server?.id;
|
|
563
563
|
const reply = async (content) => {
|
|
564
|
-
return await message.channel.
|
|
564
|
+
return await message.channel.send(content);
|
|
565
565
|
};
|
|
566
|
-
|
|
566
|
+
await this.handleMessage(rawContent, message, {
|
|
567
567
|
authorId,
|
|
568
568
|
channelId,
|
|
569
569
|
serverId,
|
|
570
570
|
reply
|
|
571
571
|
});
|
|
572
|
+
return true;
|
|
572
573
|
}
|
|
573
574
|
/**
|
|
574
575
|
* Handle a raw message string with metadata
|
|
@@ -589,9 +590,9 @@ var StoatxHandler = class {
|
|
|
589
590
|
async handleMessage(rawContent, message, meta) {
|
|
590
591
|
const ctx = await this.parseMessage(rawContent, message, meta);
|
|
591
592
|
if (!ctx) {
|
|
592
|
-
return
|
|
593
|
+
return;
|
|
593
594
|
}
|
|
594
|
-
|
|
595
|
+
await this.execute(ctx);
|
|
595
596
|
}
|
|
596
597
|
/**
|
|
597
598
|
* Execute a command with the given context
|
|
@@ -641,7 +642,6 @@ var StoatxHandler = class {
|
|
|
641
642
|
await instance.onError(ctx, error);
|
|
642
643
|
} else {
|
|
643
644
|
console.error(`[Stoatx] Error in command ${metadata.name}:`, error);
|
|
644
|
-
await ctx.reply(`An error occurred: ${error.message}`);
|
|
645
645
|
}
|
|
646
646
|
return false;
|
|
647
647
|
}
|
|
@@ -753,3 +753,4 @@ export {
|
|
|
753
753
|
getSimpleCommands,
|
|
754
754
|
isStoatClass
|
|
755
755
|
};
|
|
756
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/decorators/Stoat.ts","../src/decorators/keys.ts","../src/decorators/store.ts","../src/decorators/SimpleCommand.ts","../src/decorators/Guard.ts","../src/decorators/Events.ts","../src/decorators/utils.ts","../src/registry.ts","../src/handler.ts","../src/index.ts"],"sourcesContent":["import \"reflect-metadata\";\nimport { METADATA_KEYS } from \"./keys\";\nimport { decoratorStore } from \"./store\";\n\n/**\n * @Stoat\n * Marks a class as a Stoat command container.\n * Use this decorator on classes that contain @SimpleCommand methods.\n *\n * @example\n * ```ts\n * import { Stoat, SimpleCommand, CommandContext } from 'stoatx';\n *\n * @Stoat()\n * class ModerationCommands {\n * @SimpleCommand({ name: 'ban', description: 'Ban a user' })\n * async ban(ctx: CommandContext) {\n * await ctx.reply('User banned!');\n * }\n *\n * @SimpleCommand({ name: 'kick', description: 'Kick a user' })\n * async kick(ctx: CommandContext) {\n * await ctx.reply('User kicked!');\n * }\n * }\n * ```\n */\nexport function Stoat(): ClassDecorator {\n return (target: Function) => {\n Reflect.defineMetadata(METADATA_KEYS.IS_STOAT_CLASS, true, target);\n decoratorStore.registerStoatClass(target);\n };\n}\n\n/**\n * Check if a class is decorated with @Stoat\n */\nexport function isStoatClass(target: Function): boolean {\n return Reflect.getMetadata(METADATA_KEYS.IS_STOAT_CLASS, target) === true;\n}\n","/**\n * Metadata keys used by decorators\n */\nexport const METADATA_KEYS = {\n IS_STOAT_CLASS: Symbol(\"stoatx:stoat:isClass\"),\n SIMPLE_COMMANDS: Symbol(\"stoatx:stoat:simpleCommands\"),\n GUARDS: \"stoatx:command:guards\",\n EVENTS: Symbol(\"stoatx:stoat:events\"),\n} as const;\n","import type { RegisteredCommand } from \"../registry\";\n\n/**\n * Global store for all decorated classes and commands\n * This allows automatic registration without directory scanning\n */\nexport class DecoratorStore {\n private static instance: DecoratorStore;\n\n /** Stoat classes with their SimpleCommand methods */\n private stoatClasses: Map<Function, object> = new Map();\n\n /** Registered commands from @Stoat/@SimpleCommand decorators */\n private commands: RegisteredCommand[] = [];\n\n /** Whether the store has been initialized */\n private initialized = false;\n\n private constructor() {}\n\n static getInstance(): DecoratorStore {\n if (!DecoratorStore.instance) {\n DecoratorStore.instance = new DecoratorStore();\n }\n return DecoratorStore.instance;\n }\n\n /**\n * Register a @Stoat decorated class\n */\n registerStoatClass(classConstructor: Function): void {\n if (!this.stoatClasses.has(classConstructor)) {\n // Create instance immediately when decorated\n const instance = new (classConstructor as new () => object)();\n this.stoatClasses.set(classConstructor, instance);\n }\n }\n\n /**\n * Get all registered Stoat classes with their instances\n */\n getStoatClasses(): Map<Function, object> {\n return this.stoatClasses;\n }\n\n /**\n * Add a registered command\n */\n addCommand(command: RegisteredCommand): void {\n this.commands.push(command);\n }\n\n /**\n * Get all registered commands\n */\n getCommands(): RegisteredCommand[] {\n return this.commands;\n }\n\n /**\n * Clear all registered classes (useful for testing)\n */\n clear(): void {\n this.stoatClasses.clear();\n this.commands = [];\n this.initialized = false;\n }\n\n /**\n * Mark as initialized\n */\n markInitialized(): void {\n this.initialized = true;\n }\n\n /**\n * Check if initialized\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n}\n\nexport const decoratorStore = DecoratorStore.getInstance();\n","import \"reflect-metadata\";\nimport type { SimpleCommandOptions } from \"../types\";\nimport { METADATA_KEYS } from \"./keys\";\n\n/**\n * Stored simple command metadata from method decorator\n */\nexport interface SimpleCommandDefinition {\n methodName: string;\n options: SimpleCommandOptions;\n}\n\n/**\n * @SimpleCommand\n * Marks a method as a simple command within a @Stoat() decorated class.\n *\n * @example\n * ```ts\n * @Stoat()\n * class Example {\n * @SimpleCommand({ name: 'ping', description: 'Replies with Pong!' })\n * async ping(ctx: CommandContext) {\n * await ctx.reply('Pong!');\n * }\n *\n * @SimpleCommand({ aliases: ['perm'], name: 'permission' })\n * async permission(ctx: CommandContext) {\n * await ctx.reply('Access granted');\n * }\n * }\n * ```\n */\nexport function SimpleCommand(options: SimpleCommandOptions = {}): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n\n // Get existing simple commands or create new array\n const existingCommands: SimpleCommandDefinition[] =\n Reflect.getMetadata(METADATA_KEYS.SIMPLE_COMMANDS, constructor) || [];\n\n // Add this command definition\n existingCommands.push({\n methodName: String(propertyKey),\n options,\n });\n\n Reflect.defineMetadata(METADATA_KEYS.SIMPLE_COMMANDS, existingCommands, constructor);\n\n return descriptor;\n };\n}\n\n/**\n * Get all simple command definitions from a @Stoat class\n */\nexport function getSimpleCommands(target: Function): SimpleCommandDefinition[] {\n return Reflect.getMetadata(METADATA_KEYS.SIMPLE_COMMANDS, target) || [];\n}\n","import \"reflect-metadata\";\nimport { METADATA_KEYS } from \"./keys\";\n\n/**\n * @Guard\n * Runs before a command to check if it should execute.\n * Should return true to allow execution, false to block.\n * Applied on @Stoat classes to guard all contained @SimpleCommand methods.\n *\n * @example\n * ```ts\n * import { Guard, Stoat, SimpleCommand, CommandContext } from 'stoatx';\n *\n * // Define a guard\n * class NotBot implements StoatxGuard {\n * run(ctx: CommandContext): boolean {\n * return !ctx.message.author.bot;\n * }\n *\n * guardFail(ctx: CommandContext): void {\n * ctx.reply(\"Bots cannot use this command!\");\n * }\n * }\n *\n * @Stoat()\n * @Guard(NotBot)\n * class AdminCommands {\n * @SimpleCommand({ name: 'admin', description: 'Admin only command' })\n * async admin(ctx: CommandContext) {\n * ctx.reply(\"You passed the guard check!\");\n * }\n * }\n * ```\n */\nexport function Guard(guardClass: Function): ClassDecorator {\n return (target: Function) => {\n const existingGuards: Function[] = Reflect.getMetadata(METADATA_KEYS.GUARDS, target) || [];\n existingGuards.push(guardClass);\n Reflect.defineMetadata(METADATA_KEYS.GUARDS, existingGuards, target);\n };\n}\n\n/**\n * Get all guards from a decorated class\n */\nexport function getGuards(target: Function): Function[] {\n return Reflect.getMetadata(METADATA_KEYS.GUARDS, target) || [];\n}\n","import \"reflect-metadata\";\nimport { METADATA_KEYS } from \"./keys\";\n\nexport interface EventDefinition {\n methodName: string;\n event: string;\n type: \"on\" | \"once\";\n}\n\nfunction createEventDecorator(event: string, type: \"on\" | \"once\"): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n\n // Retrieve existing events or initialize a fresh array\n const existingEvents: EventDefinition[] = Reflect.getMetadata(METADATA_KEYS.EVENTS, constructor) || [];\n\n existingEvents.push({\n methodName: String(propertyKey),\n event,\n type,\n });\n\n Reflect.defineMetadata(METADATA_KEYS.EVENTS, existingEvents, constructor);\n\n return descriptor;\n };\n}\n\n/**\n * @On\n * Triggered on every occurrence of the event.\n * Marks a method to be executed whenever the specified client event is emitted.\n *\n * @example\n * ```ts\n * import { Stoat, On } from 'stoatx';\n * import { Message, Client } from 'stoat.js';\n *\n * @Stoat()\n * class BotEvents {\n * @On('messageCreate')\n * async onMessage(message: Message, client: Client) {\n * console.log('New message received:', message.content);\n * }\n * }\n * ```\n *\n * @param event The name of the client event to listen to\n */\nexport function On(event: string): MethodDecorator {\n return createEventDecorator(event, \"on\");\n}\n\n/**\n * @Once\n * Triggered only fully once.\n * Marks a method to be executed only the FIRST time the specified client event is emitted.\n *\n * @example\n * ```ts\n * import { Stoat, Once } from 'stoatx';\n * import { Client } from 'stoat.js';\n *\n * @Stoat()\n * class BotEvents {\n * @Once('ready')\n * async onReady(client: Client) {\n * console.log('Bot successfully started and logged in!');\n * }\n * }\n * ```\n *\n * @param event The name of the client event to listen to\n */\nexport function Once(event: string): MethodDecorator {\n return createEventDecorator(event, \"once\");\n}\n\n/**\n * Get all event definitions from a @Stoat class\n */\nexport function getEventsMetadata(target: Function): EventDefinition[] {\n return Reflect.getMetadata(METADATA_KEYS.EVENTS, target) || [];\n}\n","import type { CommandMetadata, SimpleCommandOptions } from \"../types\";\n\n/**\n * Build CommandMetadata from SimpleCommandOptions\n */\nexport function buildSimpleCommandMetadata(\n options: SimpleCommandOptions,\n methodName: string,\n category?: string,\n): CommandMetadata {\n return {\n name: options.name ?? methodName.toLowerCase(),\n description: options.description ?? \"No description provided\",\n aliases: options.aliases ?? [],\n permissions: options.permissions ?? [],\n category: options.category ?? category ?? \"uncategorized\",\n cooldown: options.cooldown ?? 0,\n nsfw: options.nsfw ?? false,\n ownerOnly: options.ownerOnly ?? false,\n };\n}\n","import * as path from \"node:path\";\nimport * as fs from \"node:fs/promises\";\nimport { pathToFileURL } from \"node:url\";\nimport { glob } from \"tinyglobby\";\nimport { buildSimpleCommandMetadata, getSimpleCommands, getEventsMetadata } from \"./decorators\";\nimport { decoratorStore } from \"./decorators/store\";\nimport type { CommandMetadata } from \"./types\";\n\ninterface AutoDiscoveryOptions {\n roots?: string[];\n include?: string[];\n ignore?: string[];\n}\n\n/**\n * Stored command entry from @Stoat/@SimpleCommand registration.\n */\nexport interface RegisteredCommand {\n /** Instance of the @Stoat class */\n instance: object;\n /** Command metadata */\n metadata: CommandMetadata;\n /** Method name to call */\n methodName: string;\n /** The original class constructor (for guard validation) */\n classConstructor: Function;\n}\n\n/**\n * Stored event entry from @On/@Once registration.\n */\nexport interface RegisteredEvent {\n instance: object;\n methodName: string;\n event: string;\n type: \"on\" | \"once\";\n}\n\n/**\n * CommandRegistry - Scans directories and stores commands in a Map\n *\n * @example\n * ```ts\n * const registry = new CommandRegistry();\n * await registry.loadFromDirectory('./src/commands');\n *\n * const ping = registry.get('ping');\n * const allCommands = registry.getAll();\n * ```\n */\nexport class CommandRegistry {\n private static readonly DEFAULT_AUTO_DISCOVERY_IGNORES = [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/*.d.ts\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n ];\n\n private readonly commands: Map<string, RegisteredCommand> = new Map();\n private readonly aliases: Map<string, string> = new Map();\n private readonly registeredEvents: RegisteredEvent[] = [];\n private readonly extensions: string[];\n private readonly processedStoatClasses: Set<Function> = new Set();\n\n constructor(extensions: string[] = [\".js\", \".mjs\", \".cjs\"]) {\n this.extensions = extensions;\n }\n\n /**\n * Get the number of registered commands\n */\n get size(): number {\n return this.commands.size;\n }\n\n /**\n * Load commands from a directory using glob pattern matching\n */\n async loadFromDirectory(directory: string): Promise<void> {\n const patterns = this.extensions.map((ext) => path.join(directory, \"**\", `*${ext}`).replace(/\\\\/g, \"/\"));\n\n for (const pattern of patterns) {\n const files = await glob(pattern, {\n ignore: [\"**/*.d.ts\", \"**/*.test.ts\", \"**/*.spec.ts\"],\n absolute: true,\n });\n\n for (const file of files) {\n await this.loadFile(file, directory);\n }\n }\n\n console.log(`[Stoatx] Loaded ${this.commands.size} command(s) and ${this.registeredEvents.length} event(s)`);\n }\n\n /**\n * Auto-discover command files across one or more roots.\n */\n async autoDiscover(options: AutoDiscoveryOptions = {}): Promise<void> {\n const roots = options.roots?.length ? options.roots : [process.cwd()];\n const includePatterns = options.include?.length ? options.include : this.getDefaultAutoDiscoveryPatterns();\n\n const patterns = roots.flatMap((root) =>\n includePatterns.map((pattern) => path.join(root, pattern).replace(/\\\\/g, \"/\")),\n );\n\n const files = await glob(patterns, {\n ignore: [...CommandRegistry.DEFAULT_AUTO_DISCOVERY_IGNORES, ...(options.ignore ?? [])],\n absolute: true,\n });\n\n const uniqueFiles = [...new Set(files)];\n let candidateFiles = 0;\n for (const file of uniqueFiles) {\n if (!(await this.isLikelyCommandModule(file))) {\n continue;\n }\n candidateFiles++;\n\n const baseDir =\n roots.find((root) => {\n const relative = path.relative(root, file);\n return relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n }) ?? roots[0]!;\n await this.loadFile(file, baseDir);\n }\n\n console.log(`[Stoatx] Loaded ${this.commands.size} command(s) and ${this.registeredEvents.length} event(s)`);\n }\n\n private getDefaultAutoDiscoveryPatterns(): string[] {\n // discordx-like default: scan broadly, then register only decorated classes\n return this.extensions.map((ext) => `**/*${ext}`);\n }\n\n private async isLikelyCommandModule(filePath: string): Promise<boolean> {\n try {\n const source = await fs.readFile(filePath, \"utf8\");\n return source.includes(\"Stoat\") || source.includes(\"SimpleCommand\") || source.includes(\"stoatx:command\");\n } catch {\n // If the file can't be pre-read, fall back to attempting import.\n return true;\n }\n }\n\n /**\n * Register a command instance\n */\n register(instance: object, metadata: CommandMetadata, classConstructor: Function, methodName: string): void {\n const name = metadata.name.toLowerCase();\n\n if (this.commands.has(name)) {\n console.warn(`[Stoatx] Duplicate command name: ${name}. Skipping...`);\n return;\n }\n\n this.validateGuards(classConstructor, metadata.name);\n\n this.commands.set(name, { instance, metadata, methodName, classConstructor });\n\n for (const alias of metadata.aliases) {\n const aliasLower = alias.toLowerCase();\n if (this.aliases.has(aliasLower) || this.commands.has(aliasLower)) {\n console.warn(`[Stoatx] Duplicate alias: ${aliasLower}. Skipping...`);\n continue;\n }\n this.aliases.set(aliasLower, name);\n }\n }\n\n /**\n * Get a command by name or alias\n */\n get(name: string): RegisteredCommand | undefined {\n const lowerName = name.toLowerCase();\n const resolvedName = this.aliases.get(lowerName) ?? lowerName;\n return this.commands.get(resolvedName);\n }\n\n /**\n * Check if a command exists\n */\n has(name: string): boolean {\n const lowerName = name.toLowerCase();\n return this.commands.has(lowerName) || this.aliases.has(lowerName);\n }\n\n /**\n * Get all registered commands\n */\n getAll(): RegisteredCommand[] {\n return Array.from(this.commands.values());\n }\n\n /**\n * Get all command metadata\n */\n getAllMetadata(): CommandMetadata[] {\n return this.getAll().map((c) => c.metadata);\n }\n\n /**\n * Get all registered events\n */\n getEvents(): RegisteredEvent[] {\n return this.registeredEvents;\n }\n\n /**\n * Get commands grouped by category\n */\n getByCategory(): Map<string, RegisteredCommand[]> {\n const categories = new Map<string, RegisteredCommand[]>();\n\n for (const cmd of this.commands.values()) {\n const category = cmd.metadata.category;\n const existing = categories.get(category) ?? [];\n existing.push(cmd);\n categories.set(category, existing);\n }\n\n return categories;\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands.clear();\n this.aliases.clear();\n this.registeredEvents.length = 0;\n this.processedStoatClasses.clear();\n }\n\n /**\n * Iterate over commands\n */\n [Symbol.iterator](): IterableIterator<[string, RegisteredCommand]> {\n return this.commands.entries();\n }\n\n /**\n * Iterate over command values\n */\n values(): IterableIterator<RegisteredCommand> {\n return this.commands.values();\n }\n\n /**\n * Iterate over command names\n */\n keys(): IterableIterator<string> {\n return this.commands.keys();\n }\n\n /**\n * Validate that all guards on a command implement the required methods\n * @param commandClass\n * @param commandName\n * @private\n */\n private validateGuards(commandClass: Function, commandName: string): void {\n const guards: Function[] = Reflect.getMetadata(\"stoatx:command:guards\", commandClass) || [];\n\n for (const GuardClass of guards) {\n const guardInstance = new (GuardClass as any)();\n\n if (typeof guardInstance.run !== \"function\") {\n console.error(\n `[Stoatx] FATAL: Guard \"${GuardClass.name}\" on command \"${commandName}\" does not have a run() method.`,\n );\n process.exit(1);\n }\n\n if (typeof guardInstance.guardFail !== \"function\") {\n console.error(\n `[Stoatx] FATAL: Guard \"${GuardClass.name}\" on command \"${commandName}\" does not have a guardFail() method.`,\n );\n console.error(`[Stoatx] All guards must implement guardFail() to handle failed checks.`);\n process.exit(1);\n }\n }\n }\n\n /**\n * Load commands from a single file\n */\n private async loadFile(filePath: string, baseDir: string): Promise<void> {\n try {\n const knownStoatClasses = new Set(decoratorStore.getStoatClasses().keys());\n const fileUrl = pathToFileURL(filePath).href;\n await import(fileUrl);\n\n const allStoatClasses = decoratorStore.getStoatClasses();\n for (const [stoatClass, stoatInstance] of allStoatClasses.entries()) {\n if (knownStoatClasses.has(stoatClass) || this.processedStoatClasses.has(stoatClass)) {\n continue;\n }\n this.registerStoatClassCommands(stoatClass, stoatInstance, filePath, baseDir);\n }\n } catch (error) {\n console.error(`[Stoatx] Failed to load command file: ${filePath}`, error);\n }\n }\n\n private registerStoatClassCommands(stoatClass: Function, instance: object, filePath: string, baseDir: string): void {\n const simpleCommands = getSimpleCommands(stoatClass);\n const events = getEventsMetadata(stoatClass);\n const category = this.getCategoryFromPath(filePath, baseDir);\n\n if (simpleCommands.length === 0 && events.length === 0) {\n console.warn(\n `[Stoatx] Class ${stoatClass.name} is decorated with @Stoat but has no @SimpleCommand, @On or @Once methods. Skipping...`,\n );\n this.processedStoatClasses.add(stoatClass);\n return;\n }\n\n for (const cmdDef of simpleCommands) {\n const method = (instance as any)[cmdDef.methodName];\n if (typeof method !== \"function\") {\n console.warn(`[Stoatx] Method ${cmdDef.methodName} not found on ${stoatClass.name}. Skipping...`);\n continue;\n }\n\n const metadata = buildSimpleCommandMetadata(cmdDef.options, cmdDef.methodName, category);\n this.register(instance, metadata, stoatClass, cmdDef.methodName);\n }\n\n for (const eventDef of events) {\n const method = (instance as any)[eventDef.methodName];\n if (typeof method !== \"function\") {\n console.warn(`[Stoatx] Method ${eventDef.methodName} not found on ${stoatClass.name}. Skipping...`);\n continue;\n }\n\n this.registeredEvents.push({\n instance,\n methodName: eventDef.methodName,\n event: eventDef.event,\n type: eventDef.type,\n });\n }\n\n this.processedStoatClasses.add(stoatClass);\n }\n\n /**\n * Derive category from file path relative to base directory\n */\n private getCategoryFromPath(filePath: string, baseDir: string): string | undefined {\n const relative = path.relative(baseDir, filePath);\n const parts = relative.split(path.sep);\n\n if (parts.length > 1) {\n return parts[0];\n }\n\n return undefined;\n }\n}\n","import \"reflect-metadata\";\nimport { CommandRegistry, RegisteredCommand } from \"./registry\";\nimport type { CommandContext, CommandMetadata, StoatxDiscoveryOptions, StoatxHandlerOptions } from \"./types\";\nimport { Client as StoatClient, ClientEvents, Message } from \"@stoatx/client\";\n\n/**\n * Client - An extended Client that integrates StoatxHandler directly\n *\n * @example\n * ```ts\n * import { Client } from 'stoatx';\n *\n * const client = new Client({\n * prefix: '!',\n * owners: ['owner-user-id'],\n * });\n *\n * await client.initCommands();\n * ```\n */\nexport class Client extends StoatClient {\n public readonly handler: StoatxHandler;\n\n constructor(options: Omit<StoatxHandlerOptions, \"client\">) {\n super();\n this.handler = new StoatxHandler({ ...options, client: this });\n\n // Automatically hook up the message handler\n this.on(\"messageCreate\", async (message) => {\n await this.handler.handle(message);\n });\n }\n\n /**\n * Initialize the StoatxHandler commands\n */\n async initCommands(): Promise<void> {\n await this.handler.init();\n }\n}\n\n/**\n * StoatxHandler - The execution engine for commands\n *\n * Handles message parsing, middleware execution, and command dispatching\n *\n * @internal This class is not intended to be instantiated directly. Use the `Client` from `stoatx` instead.\n */\nexport class StoatxHandler {\n private readonly commandsDir: string | undefined;\n private readonly discoveryOptions: StoatxDiscoveryOptions | undefined;\n private readonly prefixResolver: string | ((ctx: { serverId?: string | undefined }) => string | Promise<string>);\n private readonly owners: Set<string>;\n private readonly registry: CommandRegistry;\n private readonly cooldowns: Map<string, Map<string, number>> = new Map();\n private readonly disableMentionPrefix: boolean;\n private readonly client: StoatClient;\n constructor(options: StoatxHandlerOptions) {\n this.client = options.client;\n this.commandsDir = options.commandsDir;\n this.discoveryOptions = options.discovery;\n this.prefixResolver = options.prefix;\n this.owners = new Set(options.owners ?? []);\n this.registry = new CommandRegistry(options.extensions);\n this.disableMentionPrefix = options.disableMentionPrefix ?? false;\n }\n\n /**\n * Initialize the handler - load all commands\n */\n async init(): Promise<void> {\n if (this.commandsDir) {\n await this.registry.loadFromDirectory(this.commandsDir);\n } else {\n await this.registry.autoDiscover(this.discoveryOptions);\n }\n\n this.attachEvents();\n }\n\n /**\n * Attach registered events to the client\n */\n private attachEvents(): void {\n const events = this.registry.getEvents();\n\n for (const eventDef of events) {\n const handler = async (...args: any[]) => {\n try {\n await (eventDef.instance as any)[eventDef.methodName](...args, this.client);\n } catch (error) {\n console.error(\n `[Stoatx] Event Handler Error in @${eventDef.type === \"on\" ? \"On\" : \"Once\"}('${eventDef.event}'):`,\n error,\n );\n }\n };\n\n const eventName = eventDef.event as keyof ClientEvents;\n if (eventDef.type === \"once\") {\n this.client.once(eventName, handler);\n } else {\n this.client.on(eventName, handler);\n }\n }\n }\n\n /**\n * Parse a raw message into command context\n */\n async parseMessage(\n rawContent: string,\n message: Message,\n meta: {\n authorId: string;\n channelId: string;\n serverId?: string | undefined;\n reply: (content: string) => Promise<Message>;\n },\n ): Promise<CommandContext | null> {\n const prefix = await this.resolvePrefix(meta.serverId);\n let usedPrefix = prefix;\n let withoutPrefix = \"\";\n\n // Check for string prefix\n if (rawContent.startsWith(prefix)) {\n withoutPrefix = rawContent.slice(prefix.length).trim();\n usedPrefix = prefix;\n }\n // Check for mention prefix (e.g., \"<@bot-id> command\") - unless disabled\n else if (!this.disableMentionPrefix && rawContent.match(/^<@!?[\\w]+>/)) {\n const mentionMatch = rawContent.match(/^<@!?([\\w]+)>\\s*/);\n if (mentionMatch) {\n const mentionedId = mentionMatch[1];\n const botId = this.client.user?.id;\n\n // Only process if mentioned user is the bot\n if (botId && mentionedId === botId) {\n usedPrefix = mentionMatch[0];\n withoutPrefix = rawContent.slice(mentionMatch[0].length).trim();\n } else {\n }\n }\n }\n\n if (!withoutPrefix) {\n return null;\n }\n\n const [commandName, ...args] = withoutPrefix.split(/\\s+/);\n\n if (!commandName) {\n return null;\n }\n\n return {\n client: this.client,\n content: rawContent,\n authorId: meta.authorId,\n channelId: meta.channelId,\n serverId: meta.serverId,\n args,\n prefix: usedPrefix,\n commandName: commandName.toLowerCase(),\n reply: meta.reply,\n message,\n };\n }\n\n /**\n * Handle a message object using the configured message adapter\n *\n * @example\n * ```ts\n * // With message adapter configured\n * client.on('messageCreate', (message) => {\n * handler.handle(message);\n * });\n * ```\n */\n async handle(message: Message): Promise<boolean> {\n if (!message.channel || !message.author) {\n return false;\n }\n\n // Skip messages from bots\n if (message.author.bot) {\n return false;\n }\n\n const rawContent = message.content;\n const authorId = message.author.id;\n const channelId = message.channel.id;\n const serverId = message.server?.id;\n const reply = async (content: string) => {\n return await message.channel!.send(content);\n };\n\n // rawContent won't be null since a command will be invoked with a prefix\n await this.handleMessage(rawContent!, message, {\n authorId,\n channelId,\n serverId,\n reply,\n });\n\n return true;\n }\n\n /**\n * Handle a raw message string with metadata\n *\n * @example\n * ```ts\n * // Manual usage without message adapter\n * client.on('messageCreate', (message) => {\n * handler.handleMessage(message.content, message, {\n * authorId: message.author.id,\n * channelId: message.channel.id,\n * serverId: message.server?.id,\n * reply: (content) => message.channel.sendMessage(content),\n * });\n * });\n * ```\n */\n async handleMessage(\n rawContent: string,\n message: Message,\n meta: {\n authorId: string;\n channelId: string;\n serverId?: string | undefined;\n reply: (content: string) => Promise<Message>;\n },\n ): Promise<void> {\n const ctx = await this.parseMessage(rawContent, message, meta);\n\n if (!ctx) {\n return;\n }\n\n await this.execute(ctx);\n }\n\n /**\n * Execute a command with the given context\n */\n async execute(ctx: CommandContext): Promise<boolean> {\n const registered = this.registry.get(ctx.commandName);\n\n if (!registered) {\n return false;\n }\n\n const { instance, metadata, methodName, classConstructor } = registered;\n\n // Owner-only check\n if (metadata.ownerOnly && !this.owners.has(ctx.authorId)) {\n await ctx.reply(\"This command is owner-only.\");\n return false;\n }\n\n // Guard checks - use classConstructor for guard metadata\n const guards: Function[] = Reflect.getMetadata(\"stoatx:command:guards\", classConstructor) || [];\n for (const guardClass of guards) {\n const guardInstance = new (guardClass as any)();\n if (typeof guardInstance.run === \"function\") {\n const guardResult = await guardInstance.run(ctx);\n if (!guardResult) {\n if (typeof guardInstance.guardFail === \"function\") {\n await guardInstance.guardFail(ctx);\n } else {\n console.error(\"[Stoatx] Guard check failed but no guardFail method defined on\", guardClass.name);\n }\n return false;\n }\n }\n }\n\n // Cooldown check\n if (!this.checkCooldown(ctx.authorId, metadata)) {\n const remaining = this.getRemainingCooldown(ctx.authorId, metadata);\n\n // For method-based commands, check if instance has onCooldown\n if (typeof (instance as any).onCooldown === \"function\") {\n await (instance as any).onCooldown(ctx, remaining);\n } else {\n await ctx.reply(`Please wait ${(remaining / 1000).toFixed(1)} seconds before using this command again.`);\n }\n return false;\n }\n\n try {\n await (instance as any)[methodName](ctx);\n\n // Set cooldown after successful execution\n if (metadata.cooldown > 0) {\n this.setCooldown(ctx.authorId, metadata);\n }\n\n return true;\n } catch (error) {\n // Handle errors\n if (typeof (instance as any).onError === \"function\") {\n await (instance as any).onError(ctx, error as Error);\n } else {\n console.error(`[Stoatx] Error in command ${metadata.name}:`, error);\n }\n return false;\n }\n }\n\n /**\n * Get the command registry\n */\n getRegistry(): CommandRegistry {\n return this.registry;\n }\n\n /**\n * Get a command by name or alias\n */\n getCommand(name: string): RegisteredCommand | undefined {\n return this.registry.get(name);\n }\n\n /**\n * Get all commands\n */\n getCommands(): RegisteredCommand[] {\n return this.registry.getAll();\n }\n\n /**\n * Reload all commands\n */\n async reload(): Promise<void> {\n this.registry.clear();\n this.cooldowns.clear();\n if (this.commandsDir) {\n await this.registry.loadFromDirectory(this.commandsDir);\n return;\n }\n\n await this.registry.autoDiscover(this.discoveryOptions);\n }\n\n /**\n * Check if a user is an owner\n */\n isOwner(userId: string): boolean {\n return this.owners.has(userId);\n }\n\n /**\n * Add an owner\n */\n addOwner(userId: string): void {\n this.owners.add(userId);\n }\n\n /**\n * Remove an owner\n */\n removeOwner(userId: string): void {\n this.owners.delete(userId);\n }\n\n /**\n * Resolve the prefix for a context\n */\n private async resolvePrefix(serverId?: string | undefined): Promise<string> {\n if (typeof this.prefixResolver === \"function\") {\n return this.prefixResolver({ serverId });\n }\n return this.prefixResolver;\n }\n\n /**\n * Check if user is on cooldown\n */\n private checkCooldown(userId: string, metadata: CommandMetadata): boolean {\n if (metadata.cooldown <= 0) return true;\n\n const commandCooldowns = this.cooldowns.get(metadata.name);\n if (!commandCooldowns) return true;\n\n const userCooldown = commandCooldowns.get(userId);\n if (!userCooldown) return true;\n\n return Date.now() >= userCooldown;\n }\n\n /**\n * Get remaining cooldown time in ms\n */\n private getRemainingCooldown(userId: string, metadata: CommandMetadata): number {\n const commandCooldowns = this.cooldowns.get(metadata.name);\n if (!commandCooldowns) return 0;\n\n const userCooldown = commandCooldowns.get(userId);\n if (!userCooldown) return 0;\n\n return Math.max(0, userCooldown - Date.now());\n }\n\n /**\n * Set cooldown for a user\n */\n private setCooldown(userId: string, metadata: CommandMetadata): void {\n if (!this.cooldowns.has(metadata.name)) {\n this.cooldowns.set(metadata.name, new Map());\n }\n\n const commandCooldowns = this.cooldowns.get(metadata.name)!;\n commandCooldowns.set(userId, Date.now() + metadata.cooldown);\n }\n}\n","// Types\nexport * from \"./types\";\n\n// Decorators\nexport * from \"./decorators\";\n\n// Registry\nexport * from \"./registry\";\n\n// Handler\nexport { Client } from \"./handler\";\nexport type { StoatxHandler } from \"./handler\";\nexport * from \"@stoatx/client\";\n"],"mappings":"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","names":["relative"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stoatx",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "A high-performance, decorator-based command handler for the Stoat ecosystem.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,20 +30,14 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"reflect-metadata": "^0.2.2",
|
|
32
32
|
"tinyglobby": "^0.2.10",
|
|
33
|
-
"@stoatx/client": "0.1
|
|
34
|
-
},
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@types/node": "^20.0.0",
|
|
37
|
-
"tsup": "^8.0.0",
|
|
38
|
-
"typescript": "^5.0.0",
|
|
39
|
-
"prettier": "^3.8.1"
|
|
33
|
+
"@stoatx/client": "0.2.1"
|
|
40
34
|
},
|
|
41
35
|
"peerDependencies": {
|
|
42
36
|
"reflect-metadata": "^0.2.0"
|
|
43
37
|
},
|
|
44
38
|
"scripts": {
|
|
45
|
-
"build": "tsup
|
|
46
|
-
"dev": "tsup
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"dev": "tsup --watch",
|
|
47
41
|
"lint": "eslint src/**/*.ts"
|
|
48
42
|
}
|
|
49
43
|
}
|