stoatx 0.3.0 → 0.5.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/dist/.tsbuildinfo +1 -0
- package/dist/decorators/Events.d.ts +55 -0
- package/dist/decorators/Events.d.ts.map +1 -0
- package/dist/decorators/Events.js +71 -0
- package/dist/decorators/Events.js.map +1 -0
- package/dist/decorators/Guard.d.ts +38 -0
- package/dist/decorators/Guard.d.ts.map +1 -0
- package/dist/decorators/Guard.js +47 -0
- package/dist/decorators/Guard.js.map +1 -0
- package/dist/decorators/SimpleCommand.d.ts +35 -0
- package/dist/decorators/SimpleCommand.d.ts.map +1 -0
- package/dist/decorators/SimpleCommand.js +43 -0
- package/dist/decorators/SimpleCommand.js.map +1 -0
- package/dist/decorators/Stoat.d.ts +30 -0
- package/dist/decorators/Stoat.d.ts.map +1 -0
- package/dist/decorators/Stoat.js +39 -0
- package/dist/decorators/Stoat.js.map +1 -0
- package/dist/decorators/index.d.ts +9 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +10 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/keys.d.ts +10 -0
- package/dist/decorators/keys.d.ts.map +1 -0
- package/dist/decorators/keys.js +10 -0
- package/dist/decorators/keys.js.map +1 -0
- package/dist/decorators/store.d.ts +46 -0
- package/dist/decorators/store.d.ts.map +1 -0
- package/dist/decorators/store.js +70 -0
- package/dist/decorators/store.js.map +1 -0
- package/dist/decorators/utils.d.ts +6 -0
- package/dist/decorators/utils.d.ts.map +1 -0
- package/dist/decorators/utils.js +16 -0
- package/dist/decorators/utils.js.map +1 -0
- package/dist/decorators.d.ts +9 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +21 -0
- package/dist/decorators.js.map +1 -0
- package/dist/handler.d.ts +145 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +355 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.mts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -27
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +38 -25
- package/dist/registry.d.ts +125 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +279 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -11,13 +11,14 @@ var METADATA_KEYS = {
|
|
|
11
11
|
|
|
12
12
|
// src/decorators/store.ts
|
|
13
13
|
var DecoratorStore = class _DecoratorStore {
|
|
14
|
+
static instance;
|
|
15
|
+
/** Stoat classes with their SimpleCommand methods */
|
|
16
|
+
stoatClasses = /* @__PURE__ */ new Map();
|
|
17
|
+
/** Registered commands from @Stoat/@SimpleCommand decorators */
|
|
18
|
+
commands = [];
|
|
19
|
+
/** Whether the store has been initialized */
|
|
20
|
+
initialized = false;
|
|
14
21
|
constructor() {
|
|
15
|
-
/** Stoat classes with their SimpleCommand methods */
|
|
16
|
-
this.stoatClasses = /* @__PURE__ */ new Map();
|
|
17
|
-
/** Registered commands from @Stoat/@SimpleCommand decorators */
|
|
18
|
-
this.commands = [];
|
|
19
|
-
/** Whether the store has been initialized */
|
|
20
|
-
this.initialized = false;
|
|
21
22
|
}
|
|
22
23
|
static getInstance() {
|
|
23
24
|
if (!_DecoratorStore.instance) {
|
|
@@ -161,12 +162,20 @@ import * as path from "path";
|
|
|
161
162
|
import * as fs from "fs/promises";
|
|
162
163
|
import { pathToFileURL } from "url";
|
|
163
164
|
import { glob } from "tinyglobby";
|
|
164
|
-
var
|
|
165
|
+
var CommandRegistry = class _CommandRegistry {
|
|
166
|
+
static DEFAULT_AUTO_DISCOVERY_IGNORES = [
|
|
167
|
+
"**/node_modules/**",
|
|
168
|
+
"**/.git/**",
|
|
169
|
+
"**/*.d.ts",
|
|
170
|
+
"**/*.test.*",
|
|
171
|
+
"**/*.spec.*"
|
|
172
|
+
];
|
|
173
|
+
commands = /* @__PURE__ */ new Map();
|
|
174
|
+
aliases = /* @__PURE__ */ new Map();
|
|
175
|
+
registeredEvents = [];
|
|
176
|
+
extensions;
|
|
177
|
+
processedStoatClasses = /* @__PURE__ */ new Set();
|
|
165
178
|
constructor(extensions = [".js", ".mjs", ".cjs"]) {
|
|
166
|
-
this.commands = /* @__PURE__ */ new Map();
|
|
167
|
-
this.aliases = /* @__PURE__ */ new Map();
|
|
168
|
-
this.registeredEvents = [];
|
|
169
|
-
this.processedStoatClasses = /* @__PURE__ */ new Set();
|
|
170
179
|
this.extensions = extensions;
|
|
171
180
|
}
|
|
172
181
|
/**
|
|
@@ -225,7 +234,7 @@ var _CommandRegistry = class _CommandRegistry {
|
|
|
225
234
|
async isLikelyCommandModule(filePath) {
|
|
226
235
|
try {
|
|
227
236
|
const source = await fs.readFile(filePath, "utf8");
|
|
228
|
-
return source.includes("Stoat") || source.includes("SimpleCommand") || source.includes("
|
|
237
|
+
return source.includes("Stoat") || source.includes("SimpleCommand") || source.includes("stoatx:command");
|
|
229
238
|
} catch {
|
|
230
239
|
return true;
|
|
231
240
|
}
|
|
@@ -414,19 +423,12 @@ var _CommandRegistry = class _CommandRegistry {
|
|
|
414
423
|
return void 0;
|
|
415
424
|
}
|
|
416
425
|
};
|
|
417
|
-
_CommandRegistry.DEFAULT_AUTO_DISCOVERY_IGNORES = [
|
|
418
|
-
"**/node_modules/**",
|
|
419
|
-
"**/.git/**",
|
|
420
|
-
"**/*.d.ts",
|
|
421
|
-
"**/*.test.*",
|
|
422
|
-
"**/*.spec.*"
|
|
423
|
-
];
|
|
424
|
-
var CommandRegistry = _CommandRegistry;
|
|
425
426
|
|
|
426
427
|
// src/handler.ts
|
|
427
428
|
import "reflect-metadata";
|
|
428
|
-
import { Client as StoatClient } from "
|
|
429
|
+
import { Client as StoatClient } from "@stoatx/client";
|
|
429
430
|
var Client = class extends StoatClient {
|
|
431
|
+
handler;
|
|
430
432
|
constructor(options) {
|
|
431
433
|
super();
|
|
432
434
|
this.handler = new StoatxHandler({ ...options, client: this });
|
|
@@ -442,8 +444,15 @@ var Client = class extends StoatClient {
|
|
|
442
444
|
}
|
|
443
445
|
};
|
|
444
446
|
var StoatxHandler = class {
|
|
447
|
+
commandsDir;
|
|
448
|
+
discoveryOptions;
|
|
449
|
+
prefixResolver;
|
|
450
|
+
owners;
|
|
451
|
+
registry;
|
|
452
|
+
cooldowns = /* @__PURE__ */ new Map();
|
|
453
|
+
disableMentionPrefix;
|
|
454
|
+
client;
|
|
445
455
|
constructor(options) {
|
|
446
|
-
this.cooldowns = /* @__PURE__ */ new Map();
|
|
447
456
|
this.client = options.client;
|
|
448
457
|
this.commandsDir = options.commandsDir;
|
|
449
458
|
this.discoveryOptions = options.discovery;
|
|
@@ -479,10 +488,11 @@ var StoatxHandler = class {
|
|
|
479
488
|
);
|
|
480
489
|
}
|
|
481
490
|
};
|
|
491
|
+
const eventName = eventDef.event;
|
|
482
492
|
if (eventDef.type === "once") {
|
|
483
|
-
this.client.once(
|
|
493
|
+
this.client.once(eventName, handler);
|
|
484
494
|
} else {
|
|
485
|
-
this.client.on(
|
|
495
|
+
this.client.on(eventName, handler);
|
|
486
496
|
}
|
|
487
497
|
}
|
|
488
498
|
}
|
|
@@ -551,7 +561,7 @@ var StoatxHandler = class {
|
|
|
551
561
|
const channelId = message.channel.id;
|
|
552
562
|
const serverId = message.server?.id;
|
|
553
563
|
const reply = async (content) => {
|
|
554
|
-
await message.channel.sendMessage(content);
|
|
564
|
+
return await message.channel.sendMessage(content);
|
|
555
565
|
};
|
|
556
566
|
return this.handleMessage(rawContent, message, {
|
|
557
567
|
authorId,
|
|
@@ -725,6 +735,9 @@ var StoatxHandler = class {
|
|
|
725
735
|
commandCooldowns.set(userId, Date.now() + metadata.cooldown);
|
|
726
736
|
}
|
|
727
737
|
};
|
|
738
|
+
|
|
739
|
+
// src/index.ts
|
|
740
|
+
export * from "@stoatx/client";
|
|
728
741
|
export {
|
|
729
742
|
Client,
|
|
730
743
|
CommandRegistry,
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { CommandMetadata } from "./types";
|
|
2
|
+
interface AutoDiscoveryOptions {
|
|
3
|
+
roots?: string[];
|
|
4
|
+
include?: string[];
|
|
5
|
+
ignore?: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Stored command entry from @Stoat/@SimpleCommand registration.
|
|
9
|
+
*/
|
|
10
|
+
export interface RegisteredCommand {
|
|
11
|
+
/** Instance of the @Stoat class */
|
|
12
|
+
instance: object;
|
|
13
|
+
/** Command metadata */
|
|
14
|
+
metadata: CommandMetadata;
|
|
15
|
+
/** Method name to call */
|
|
16
|
+
methodName: string;
|
|
17
|
+
/** The original class constructor (for guard validation) */
|
|
18
|
+
classConstructor: Function;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Stored event entry from @On/@Once registration.
|
|
22
|
+
*/
|
|
23
|
+
export interface RegisteredEvent {
|
|
24
|
+
instance: object;
|
|
25
|
+
methodName: string;
|
|
26
|
+
event: string;
|
|
27
|
+
type: "on" | "once";
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* CommandRegistry - Scans directories and stores commands in a Map
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const registry = new CommandRegistry();
|
|
35
|
+
* await registry.loadFromDirectory('./src/commands');
|
|
36
|
+
*
|
|
37
|
+
* const ping = registry.get('ping');
|
|
38
|
+
* const allCommands = registry.getAll();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class CommandRegistry {
|
|
42
|
+
private static readonly DEFAULT_AUTO_DISCOVERY_IGNORES;
|
|
43
|
+
private readonly commands;
|
|
44
|
+
private readonly aliases;
|
|
45
|
+
private readonly registeredEvents;
|
|
46
|
+
private readonly extensions;
|
|
47
|
+
private readonly processedStoatClasses;
|
|
48
|
+
constructor(extensions?: string[]);
|
|
49
|
+
/**
|
|
50
|
+
* Get the number of registered commands
|
|
51
|
+
*/
|
|
52
|
+
get size(): number;
|
|
53
|
+
/**
|
|
54
|
+
* Load commands from a directory using glob pattern matching
|
|
55
|
+
*/
|
|
56
|
+
loadFromDirectory(directory: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Auto-discover command files across one or more roots.
|
|
59
|
+
*/
|
|
60
|
+
autoDiscover(options?: AutoDiscoveryOptions): Promise<void>;
|
|
61
|
+
private getDefaultAutoDiscoveryPatterns;
|
|
62
|
+
private isLikelyCommandModule;
|
|
63
|
+
/**
|
|
64
|
+
* Register a command instance
|
|
65
|
+
*/
|
|
66
|
+
register(instance: object, metadata: CommandMetadata, classConstructor: Function, methodName: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* Get a command by name or alias
|
|
69
|
+
*/
|
|
70
|
+
get(name: string): RegisteredCommand | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Check if a command exists
|
|
73
|
+
*/
|
|
74
|
+
has(name: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Get all registered commands
|
|
77
|
+
*/
|
|
78
|
+
getAll(): RegisteredCommand[];
|
|
79
|
+
/**
|
|
80
|
+
* Get all command metadata
|
|
81
|
+
*/
|
|
82
|
+
getAllMetadata(): CommandMetadata[];
|
|
83
|
+
/**
|
|
84
|
+
* Get all registered events
|
|
85
|
+
*/
|
|
86
|
+
getEvents(): RegisteredEvent[];
|
|
87
|
+
/**
|
|
88
|
+
* Get commands grouped by category
|
|
89
|
+
*/
|
|
90
|
+
getByCategory(): Map<string, RegisteredCommand[]>;
|
|
91
|
+
/**
|
|
92
|
+
* Clear all commands
|
|
93
|
+
*/
|
|
94
|
+
clear(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Iterate over commands
|
|
97
|
+
*/
|
|
98
|
+
[Symbol.iterator](): IterableIterator<[string, RegisteredCommand]>;
|
|
99
|
+
/**
|
|
100
|
+
* Iterate over command values
|
|
101
|
+
*/
|
|
102
|
+
values(): IterableIterator<RegisteredCommand>;
|
|
103
|
+
/**
|
|
104
|
+
* Iterate over command names
|
|
105
|
+
*/
|
|
106
|
+
keys(): IterableIterator<string>;
|
|
107
|
+
/**
|
|
108
|
+
* Validate that all guards on a command implement the required methods
|
|
109
|
+
* @param commandClass
|
|
110
|
+
* @param commandName
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
private validateGuards;
|
|
114
|
+
/**
|
|
115
|
+
* Load commands from a single file
|
|
116
|
+
*/
|
|
117
|
+
private loadFile;
|
|
118
|
+
private registerStoatClassCommands;
|
|
119
|
+
/**
|
|
120
|
+
* Derive category from file path relative to base directory
|
|
121
|
+
*/
|
|
122
|
+
private getCategoryFromPath;
|
|
123
|
+
}
|
|
124
|
+
export {};
|
|
125
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,QAAQ,EAAE,eAAe,CAAC;IAC1B,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,gBAAgB,EAAE,QAAQ,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAMpD;IAEF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4B;gBAEtD,UAAU,GAAE,MAAM,EAA4B;IAI1D;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACG,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBzD;;OAEG;IACG,YAAY,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCrE,OAAO,CAAC,+BAA+B;YAKzB,qBAAqB;IAenC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAsB3G;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAMhD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAK1B;;OAEG;IACH,MAAM,IAAI,iBAAiB,EAAE;IAI7B;;OAEG;IACH,cAAc,IAAI,eAAe,EAAE;IAInC;;OAEG;IACH,SAAS,IAAI,eAAe,EAAE;IAI9B;;OAEG;IACH,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAajD;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAIlE;;OAEG;IACH,MAAM,IAAI,gBAAgB,CAAC,iBAAiB,CAAC;IAI7C;;OAEG;IACH,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAIhC;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAuBtB;;OAEG;YACW,QAAQ;IAkBtB,OAAO,CAAC,0BAA0B;IA0ClC;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAU5B"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { glob } from "tinyglobby";
|
|
5
|
+
import { buildSimpleCommandMetadata, getSimpleCommands, getEventsMetadata } from "./decorators";
|
|
6
|
+
import { decoratorStore } from "./decorators/store";
|
|
7
|
+
/**
|
|
8
|
+
* CommandRegistry - Scans directories and stores commands in a Map
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const registry = new CommandRegistry();
|
|
13
|
+
* await registry.loadFromDirectory('./src/commands');
|
|
14
|
+
*
|
|
15
|
+
* const ping = registry.get('ping');
|
|
16
|
+
* const allCommands = registry.getAll();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export class CommandRegistry {
|
|
20
|
+
static DEFAULT_AUTO_DISCOVERY_IGNORES = [
|
|
21
|
+
"**/node_modules/**",
|
|
22
|
+
"**/.git/**",
|
|
23
|
+
"**/*.d.ts",
|
|
24
|
+
"**/*.test.*",
|
|
25
|
+
"**/*.spec.*",
|
|
26
|
+
];
|
|
27
|
+
commands = new Map();
|
|
28
|
+
aliases = new Map();
|
|
29
|
+
registeredEvents = [];
|
|
30
|
+
extensions;
|
|
31
|
+
processedStoatClasses = new Set();
|
|
32
|
+
constructor(extensions = [".js", ".mjs", ".cjs"]) {
|
|
33
|
+
this.extensions = extensions;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the number of registered commands
|
|
37
|
+
*/
|
|
38
|
+
get size() {
|
|
39
|
+
return this.commands.size;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Load commands from a directory using glob pattern matching
|
|
43
|
+
*/
|
|
44
|
+
async loadFromDirectory(directory) {
|
|
45
|
+
const patterns = this.extensions.map((ext) => path.join(directory, "**", `*${ext}`).replace(/\\/g, "/"));
|
|
46
|
+
for (const pattern of patterns) {
|
|
47
|
+
const files = await glob(pattern, {
|
|
48
|
+
ignore: ["**/*.d.ts", "**/*.test.ts", "**/*.spec.ts"],
|
|
49
|
+
absolute: true,
|
|
50
|
+
});
|
|
51
|
+
for (const file of files) {
|
|
52
|
+
await this.loadFile(file, directory);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
console.log(`[Stoatx] Loaded ${this.commands.size} command(s) and ${this.registeredEvents.length} event(s)`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Auto-discover command files across one or more roots.
|
|
59
|
+
*/
|
|
60
|
+
async autoDiscover(options = {}) {
|
|
61
|
+
const roots = options.roots?.length ? options.roots : [process.cwd()];
|
|
62
|
+
const includePatterns = options.include?.length ? options.include : this.getDefaultAutoDiscoveryPatterns();
|
|
63
|
+
const patterns = roots.flatMap((root) => includePatterns.map((pattern) => path.join(root, pattern).replace(/\\/g, "/")));
|
|
64
|
+
const files = await glob(patterns, {
|
|
65
|
+
ignore: [...CommandRegistry.DEFAULT_AUTO_DISCOVERY_IGNORES, ...(options.ignore ?? [])],
|
|
66
|
+
absolute: true,
|
|
67
|
+
});
|
|
68
|
+
const uniqueFiles = [...new Set(files)];
|
|
69
|
+
let candidateFiles = 0;
|
|
70
|
+
for (const file of uniqueFiles) {
|
|
71
|
+
if (!(await this.isLikelyCommandModule(file))) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
candidateFiles++;
|
|
75
|
+
const baseDir = roots.find((root) => {
|
|
76
|
+
const relative = path.relative(root, file);
|
|
77
|
+
return relative && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
78
|
+
}) ?? roots[0];
|
|
79
|
+
await this.loadFile(file, baseDir);
|
|
80
|
+
}
|
|
81
|
+
console.log(`[Stoatx] Loaded ${this.commands.size} command(s) and ${this.registeredEvents.length} event(s)`);
|
|
82
|
+
}
|
|
83
|
+
getDefaultAutoDiscoveryPatterns() {
|
|
84
|
+
// discordx-like default: scan broadly, then register only decorated classes
|
|
85
|
+
return this.extensions.map((ext) => `**/*${ext}`);
|
|
86
|
+
}
|
|
87
|
+
async isLikelyCommandModule(filePath) {
|
|
88
|
+
try {
|
|
89
|
+
const source = await fs.readFile(filePath, "utf8");
|
|
90
|
+
return (source.includes("Stoat") ||
|
|
91
|
+
source.includes("SimpleCommand") ||
|
|
92
|
+
source.includes("Command") ||
|
|
93
|
+
source.includes("stoatx:command"));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// If the file can't be pre-read, fall back to attempting import.
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Register a command instance
|
|
102
|
+
*/
|
|
103
|
+
register(instance, metadata, classConstructor, methodName) {
|
|
104
|
+
const name = metadata.name.toLowerCase();
|
|
105
|
+
if (this.commands.has(name)) {
|
|
106
|
+
console.warn(`[Stoatx] Duplicate command name: ${name}. Skipping...`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.validateGuards(classConstructor, metadata.name);
|
|
110
|
+
this.commands.set(name, { instance, metadata, methodName, classConstructor });
|
|
111
|
+
for (const alias of metadata.aliases) {
|
|
112
|
+
const aliasLower = alias.toLowerCase();
|
|
113
|
+
if (this.aliases.has(aliasLower) || this.commands.has(aliasLower)) {
|
|
114
|
+
console.warn(`[Stoatx] Duplicate alias: ${aliasLower}. Skipping...`);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
this.aliases.set(aliasLower, name);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get a command by name or alias
|
|
122
|
+
*/
|
|
123
|
+
get(name) {
|
|
124
|
+
const lowerName = name.toLowerCase();
|
|
125
|
+
const resolvedName = this.aliases.get(lowerName) ?? lowerName;
|
|
126
|
+
return this.commands.get(resolvedName);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if a command exists
|
|
130
|
+
*/
|
|
131
|
+
has(name) {
|
|
132
|
+
const lowerName = name.toLowerCase();
|
|
133
|
+
return this.commands.has(lowerName) || this.aliases.has(lowerName);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get all registered commands
|
|
137
|
+
*/
|
|
138
|
+
getAll() {
|
|
139
|
+
return Array.from(this.commands.values());
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get all command metadata
|
|
143
|
+
*/
|
|
144
|
+
getAllMetadata() {
|
|
145
|
+
return this.getAll().map((c) => c.metadata);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Get all registered events
|
|
149
|
+
*/
|
|
150
|
+
getEvents() {
|
|
151
|
+
return this.registeredEvents;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get commands grouped by category
|
|
155
|
+
*/
|
|
156
|
+
getByCategory() {
|
|
157
|
+
const categories = new Map();
|
|
158
|
+
for (const cmd of this.commands.values()) {
|
|
159
|
+
const category = cmd.metadata.category;
|
|
160
|
+
const existing = categories.get(category) ?? [];
|
|
161
|
+
existing.push(cmd);
|
|
162
|
+
categories.set(category, existing);
|
|
163
|
+
}
|
|
164
|
+
return categories;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Clear all commands
|
|
168
|
+
*/
|
|
169
|
+
clear() {
|
|
170
|
+
this.commands.clear();
|
|
171
|
+
this.aliases.clear();
|
|
172
|
+
this.registeredEvents.length = 0;
|
|
173
|
+
this.processedStoatClasses.clear();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Iterate over commands
|
|
177
|
+
*/
|
|
178
|
+
[Symbol.iterator]() {
|
|
179
|
+
return this.commands.entries();
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Iterate over command values
|
|
183
|
+
*/
|
|
184
|
+
values() {
|
|
185
|
+
return this.commands.values();
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Iterate over command names
|
|
189
|
+
*/
|
|
190
|
+
keys() {
|
|
191
|
+
return this.commands.keys();
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Validate that all guards on a command implement the required methods
|
|
195
|
+
* @param commandClass
|
|
196
|
+
* @param commandName
|
|
197
|
+
* @private
|
|
198
|
+
*/
|
|
199
|
+
validateGuards(commandClass, commandName) {
|
|
200
|
+
const guards = Reflect.getMetadata("stoatx:command:guards", commandClass) || [];
|
|
201
|
+
for (const GuardClass of guards) {
|
|
202
|
+
const guardInstance = new GuardClass();
|
|
203
|
+
if (typeof guardInstance.run !== "function") {
|
|
204
|
+
console.error(`[Stoatx] FATAL: Guard "${GuardClass.name}" on command "${commandName}" does not have a run() method.`);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
if (typeof guardInstance.guardFail !== "function") {
|
|
208
|
+
console.error(`[Stoatx] FATAL: Guard "${GuardClass.name}" on command "${commandName}" does not have a guardFail() method.`);
|
|
209
|
+
console.error(`[Stoatx] All guards must implement guardFail() to handle failed checks.`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Load commands from a single file
|
|
216
|
+
*/
|
|
217
|
+
async loadFile(filePath, baseDir) {
|
|
218
|
+
try {
|
|
219
|
+
const knownStoatClasses = new Set(decoratorStore.getStoatClasses().keys());
|
|
220
|
+
const fileUrl = pathToFileURL(filePath).href;
|
|
221
|
+
await import(fileUrl);
|
|
222
|
+
const allStoatClasses = decoratorStore.getStoatClasses();
|
|
223
|
+
for (const [stoatClass, stoatInstance] of allStoatClasses.entries()) {
|
|
224
|
+
if (knownStoatClasses.has(stoatClass) || this.processedStoatClasses.has(stoatClass)) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
this.registerStoatClassCommands(stoatClass, stoatInstance, filePath, baseDir);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
console.error(`[Stoatx] Failed to load command file: ${filePath}`, error);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
registerStoatClassCommands(stoatClass, instance, filePath, baseDir) {
|
|
235
|
+
const simpleCommands = getSimpleCommands(stoatClass);
|
|
236
|
+
const events = getEventsMetadata(stoatClass);
|
|
237
|
+
const category = this.getCategoryFromPath(filePath, baseDir);
|
|
238
|
+
if (simpleCommands.length === 0 && events.length === 0) {
|
|
239
|
+
console.warn(`[Stoatx] Class ${stoatClass.name} is decorated with @Stoat but has no @SimpleCommand, @On or @Once methods. Skipping...`);
|
|
240
|
+
this.processedStoatClasses.add(stoatClass);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
for (const cmdDef of simpleCommands) {
|
|
244
|
+
const method = instance[cmdDef.methodName];
|
|
245
|
+
if (typeof method !== "function") {
|
|
246
|
+
console.warn(`[Stoatx] Method ${cmdDef.methodName} not found on ${stoatClass.name}. Skipping...`);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const metadata = buildSimpleCommandMetadata(cmdDef.options, cmdDef.methodName, category);
|
|
250
|
+
this.register(instance, metadata, stoatClass, cmdDef.methodName);
|
|
251
|
+
}
|
|
252
|
+
for (const eventDef of events) {
|
|
253
|
+
const method = instance[eventDef.methodName];
|
|
254
|
+
if (typeof method !== "function") {
|
|
255
|
+
console.warn(`[Stoatx] Method ${eventDef.methodName} not found on ${stoatClass.name}. Skipping...`);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
this.registeredEvents.push({
|
|
259
|
+
instance,
|
|
260
|
+
methodName: eventDef.methodName,
|
|
261
|
+
event: eventDef.event,
|
|
262
|
+
type: eventDef.type,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
this.processedStoatClasses.add(stoatClass);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Derive category from file path relative to base directory
|
|
269
|
+
*/
|
|
270
|
+
getCategoryFromPath(filePath, baseDir) {
|
|
271
|
+
const relative = path.relative(baseDir, filePath);
|
|
272
|
+
const parts = relative.split(path.sep);
|
|
273
|
+
if (parts.length > 1) {
|
|
274
|
+
return parts[0];
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAiCpD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,eAAe;IAClB,MAAM,CAAU,8BAA8B,GAAG;QACvD,oBAAoB;QACpB,YAAY;QACZ,WAAW;QACX,aAAa;QACb,aAAa;KACd,CAAC;IAEe,QAAQ,GAAmC,IAAI,GAAG,EAAE,CAAC;IACrD,OAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;IACzC,gBAAgB,GAAsB,EAAE,CAAC;IACzC,UAAU,CAAW;IACrB,qBAAqB,GAAkB,IAAI,GAAG,EAAE,CAAC;IAElE,YAAY,aAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;QACxD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,SAAiB;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAEzG,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE;gBAChC,MAAM,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,cAAc,CAAC;gBACrD,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,QAAQ,CAAC,IAAI,mBAAmB,IAAI,CAAC,gBAAgB,CAAC,MAAM,WAAW,CAAC,CAAC;IAC/G,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,UAAgC,EAAE;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACtE,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC;QAE3G,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACtC,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAC/E,CAAC;QAEF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;YACjC,MAAM,EAAE,CAAC,GAAG,eAAe,CAAC,8BAA8B,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACtF,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC9C,SAAS;YACX,CAAC;YACD,cAAc,EAAE,CAAC;YAEjB,MAAM,OAAO,GACX,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC3C,OAAO,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC9E,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;YACjB,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,QAAQ,CAAC,IAAI,mBAAmB,IAAI,CAAC,gBAAgB,CAAC,MAAM,WAAW,CAAC,CAAC;IAC/G,CAAC;IAEO,+BAA+B;QACrC,4EAA4E;QAC5E,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,QAAgB;QAClD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACnD,OAAO,CACL,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACxB,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;gBAChC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAC1B,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAClC,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,QAAgB,EAAE,QAAyB,EAAE,gBAA0B,EAAE,UAAkB;QAClG,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEzC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,oCAAoC,IAAI,eAAe,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAErD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAE9E,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAClE,OAAO,CAAC,IAAI,CAAC,6BAA6B,UAAU,eAAe,CAAC,CAAC;gBACrE,SAAS;YACX,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAAY;QACd,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;QAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAAY;QACd,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,aAAa;QACX,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;QAE1D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACK,cAAc,CAAC,YAAsB,EAAE,WAAmB;QAChE,MAAM,MAAM,GAAe,OAAO,CAAC,WAAW,CAAC,uBAAuB,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC;QAE5F,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;YAChC,MAAM,aAAa,GAAG,IAAK,UAAkB,EAAE,CAAC;YAEhD,IAAI,OAAO,aAAa,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CACX,0BAA0B,UAAU,CAAC,IAAI,iBAAiB,WAAW,iCAAiC,CACvG,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,IAAI,OAAO,aAAa,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;gBAClD,OAAO,CAAC,KAAK,CACX,0BAA0B,UAAU,CAAC,IAAI,iBAAiB,WAAW,uCAAuC,CAC7G,CAAC;gBACF,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;gBACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,OAAe;QACtD,IAAI,CAAC;YACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3E,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;YAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;YAEtB,MAAM,eAAe,GAAG,cAAc,CAAC,eAAe,EAAE,CAAC;YACzD,KAAK,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;gBACpE,IAAI,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;oBACpF,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,0BAA0B,CAAC,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yCAAyC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAEO,0BAA0B,CAAC,UAAoB,EAAE,QAAgB,EAAE,QAAgB,EAAE,OAAe;QAC1G,MAAM,cAAc,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE7D,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,IAAI,CACV,kBAAkB,UAAU,CAAC,IAAI,wFAAwF,CAC1H,CAAC;YACF,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;YACpC,MAAM,MAAM,GAAI,QAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACpD,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,UAAU,iBAAiB,UAAU,CAAC,IAAI,eAAe,CAAC,CAAC;gBAClG,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,0BAA0B,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACzF,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QACnE,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAI,QAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YACtD,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,mBAAmB,QAAQ,CAAC,UAAU,iBAAiB,UAAU,CAAC,IAAI,eAAe,CAAC,CAAC;gBACpG,SAAS;YACX,CAAC;YAED,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;gBACzB,QAAQ;gBACR,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACK,mBAAmB,CAAC,QAAgB,EAAE,OAAe;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEvC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Client as StoatClient, Message } from "stoat.js";
|
|
2
|
+
/**
|
|
3
|
+
* Permission types for commands
|
|
4
|
+
*/
|
|
5
|
+
export type Permission = "SendMessages" | "ManageMessages" | "ManageChannels" | "ManageServer" | "KickMembers" | "BanMembers" | "Administrator" | (string & {});
|
|
6
|
+
/**
|
|
7
|
+
* Simple command options passed to @SimpleCommand decorator
|
|
8
|
+
* Used with @Stoat() decorated classes for method-based commands
|
|
9
|
+
*/
|
|
10
|
+
export interface SimpleCommandOptions {
|
|
11
|
+
/** Command name (defaults to method name) */
|
|
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
|
+
/**
|
|
29
|
+
* Resolved command metadata with required fields
|
|
30
|
+
*/
|
|
31
|
+
export interface CommandMetadata {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
aliases: string[];
|
|
35
|
+
permissions: Permission[];
|
|
36
|
+
category: string;
|
|
37
|
+
cooldown: number;
|
|
38
|
+
nsfw: boolean;
|
|
39
|
+
ownerOnly: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Command execution context
|
|
43
|
+
*/
|
|
44
|
+
export interface CommandContext {
|
|
45
|
+
/** The client instance */
|
|
46
|
+
client: StoatClient;
|
|
47
|
+
/** The raw message content */
|
|
48
|
+
content: string;
|
|
49
|
+
/** The author ID */
|
|
50
|
+
authorId: string;
|
|
51
|
+
/** The channel ID */
|
|
52
|
+
channelId: string;
|
|
53
|
+
/** The server/guild ID (if applicable) */
|
|
54
|
+
serverId?: string;
|
|
55
|
+
/** Parsed command arguments */
|
|
56
|
+
args: string[];
|
|
57
|
+
/** The prefix used */
|
|
58
|
+
prefix: string;
|
|
59
|
+
/** The command name used (could be an alias) */
|
|
60
|
+
commandName: string;
|
|
61
|
+
/** Reply to the message */
|
|
62
|
+
reply: (content: string) => Promise<Message>;
|
|
63
|
+
/** The original message object (platform-specific) */
|
|
64
|
+
message: Message;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Optional lifecycle hooks for @Stoat() class instances
|
|
68
|
+
*/
|
|
69
|
+
export interface StoatLifecycle {
|
|
70
|
+
/** Optional: Called when an error occurs during command execution */
|
|
71
|
+
onError?(ctx: CommandContext, error: Error): Promise<void>;
|
|
72
|
+
/** Optional: Called when a cooldown is active */
|
|
73
|
+
onCooldown?(ctx: CommandContext, remaining: number): Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
export interface StoatxGuard {
|
|
76
|
+
run(ctx: CommandContext): Promise<boolean> | boolean;
|
|
77
|
+
guardFail?(ctx: CommandContext): Promise<void> | void;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Discovery options for automatic command module loading
|
|
81
|
+
*/
|
|
82
|
+
export interface StoatxDiscoveryOptions {
|
|
83
|
+
/** Root directories to scan (default: [process.cwd()]) */
|
|
84
|
+
roots?: string[];
|
|
85
|
+
/** Glob patterns relative to each root */
|
|
86
|
+
include?: string[];
|
|
87
|
+
/** Additional ignore patterns */
|
|
88
|
+
ignore?: string[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handler options
|
|
92
|
+
*/
|
|
93
|
+
export interface StoatxHandlerOptions {
|
|
94
|
+
/** The client instance */
|
|
95
|
+
client: StoatClient;
|
|
96
|
+
/** Directory to scan for command modules (absolute path) */
|
|
97
|
+
commandsDir?: string;
|
|
98
|
+
/** Auto-discovery options used when commandsDir is not provided */
|
|
99
|
+
discovery?: StoatxDiscoveryOptions;
|
|
100
|
+
/** Command prefix or prefix resolver function */
|
|
101
|
+
prefix: string | ((ctx: {
|
|
102
|
+
serverId?: string;
|
|
103
|
+
}) => string | Promise<string>);
|
|
104
|
+
/** Owner IDs for owner-only commands */
|
|
105
|
+
owners?: string[];
|
|
106
|
+
/** File extensions to load (default: ['.js', '.mjs', '.cjs']) */
|
|
107
|
+
extensions?: string[];
|
|
108
|
+
/** Disable mention prefix support (default: false) */
|
|
109
|
+
disableMentionPrefix?: boolean;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|