bakit 1.0.0-beta.1 → 1.0.0-beta.10

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.
@@ -1,6 +1,3 @@
1
- // src/command/index.ts
2
- import "reflect-metadata";
3
-
4
1
  // src/command/argument/Argument.ts
5
2
  var ArgumentType = /* @__PURE__ */ ((ArgumentType2) => {
6
3
  ArgumentType2["String"] = "string";
@@ -13,233 +10,218 @@ var ArgumentType = /* @__PURE__ */ ((ArgumentType2) => {
13
10
 
14
11
  // src/command/argument/Arg.ts
15
12
  var ARGS_KEY = Symbol("args");
16
- var Arg = class _Arg {
17
- static cache = /* @__PURE__ */ new WeakMap();
18
- static string = _Arg.createArgument("string" /* String */);
19
- static integer = _Arg.createArgument("integer" /* Integer */);
20
- static number = _Arg.createArgument("number" /* Number */);
21
- static user = _Arg.createArgument("user" /* User */);
22
- static member = _Arg.createArgument("member" /* Member */);
23
- static getMethodArguments(method, init = false) {
24
- let args = this.cache.get(method) ?? Reflect.getMetadata(ARGS_KEY, method);
25
- if (!args) {
26
- args = [];
27
- if (init) {
28
- Reflect.defineMetadata(ARGS_KEY, args, method);
29
- this.cache.set(method, args);
30
- }
13
+ var cache = /* @__PURE__ */ new WeakMap();
14
+ function getMethodArguments(method, init = false) {
15
+ let args = cache.get(method) ?? Reflect.getMetadata(ARGS_KEY, method);
16
+ if (!args) {
17
+ args = [];
18
+ if (init) {
19
+ Reflect.defineMetadata(ARGS_KEY, args, method);
20
+ cache.set(method, args);
31
21
  }
32
- return init ? args : Object.freeze([...args]);
33
- }
34
- static format(arg) {
35
- const { name, required, tuple } = arg;
36
- const opening = required ? "<" : "[";
37
- const closing = required ? ">" : "]";
38
- const prefix = tuple ? "..." : "";
39
- return `${opening}${prefix}${name}: ${this.describeArgumentExpectation(arg)}${closing}`;
40
22
  }
41
- static describeArgumentExpectation(arg) {
42
- const parts = [arg.type];
43
- switch (arg.type) {
44
- case "string" /* String */: {
45
- if (arg.minLength && !arg.maxLength) {
46
- parts.push(`\u2265 ${String(arg.minLength)}`);
47
- }
48
- if (!arg.minLength && arg.maxLength) {
49
- parts.push(`\u2264 ${String(arg.maxLength)}`);
50
- }
51
- if (arg.minLength && arg.maxLength) {
52
- parts.push(`${String(arg.minLength)} - ${String(arg.maxLength)}`);
53
- }
54
- break;
23
+ return init ? args : Object.freeze([...args]);
24
+ }
25
+ function createArgument(type) {
26
+ return function(options) {
27
+ const objOptions = typeof options === "string" ? { name: options } : options;
28
+ const fullOptions = { ...objOptions, type };
29
+ if (!fullOptions.description) {
30
+ fullOptions.description = fullOptions.name;
31
+ }
32
+ if (!("required" in fullOptions)) {
33
+ fullOptions.required = true;
34
+ }
35
+ return function(target, key, _index) {
36
+ const method = Object.getOwnPropertyDescriptor(target, key)?.value;
37
+ if (!method) {
38
+ throw new Error("No method found");
55
39
  }
56
- case "number" /* Number */:
57
- case "integer" /* Integer */: {
58
- if (arg.minValue !== void 0 && arg.maxValue === void 0) {
59
- parts.push(`\u2265 ${String(arg.minValue)}`);
60
- }
61
- if (arg.minValue === void 0 && arg.maxValue !== void 0) {
62
- parts.push(`\u2264 ${String(arg.maxValue)}`);
63
- }
64
- if (arg.minValue !== void 0 && arg.maxValue !== void 0) {
65
- parts.push(`${String(arg.minValue)} - ${String(arg.maxValue)}`);
66
- }
67
- break;
40
+ const args = getMethodArguments(method, true);
41
+ args.unshift(fullOptions);
42
+ };
43
+ };
44
+ }
45
+ var string = createArgument("string" /* String */);
46
+ var integer = createArgument("integer" /* Integer */);
47
+ var number = createArgument("number" /* Number */);
48
+ var user = createArgument("user" /* User */);
49
+ var member = createArgument("member" /* Member */);
50
+ function describeArgumentExpectation(arg) {
51
+ const parts = [arg.type];
52
+ switch (arg.type) {
53
+ case "string" /* String */: {
54
+ if (arg.minLength && !arg.maxLength) {
55
+ parts.push(`\u2265 ${String(arg.minLength)}`);
68
56
  }
69
- case "user" /* User */:
70
- case "member" /* Member */: {
71
- break;
57
+ if (!arg.minLength && arg.maxLength) {
58
+ parts.push(`\u2264 ${String(arg.maxLength)}`);
72
59
  }
60
+ if (arg.minLength && arg.maxLength) {
61
+ parts.push(`${String(arg.minLength)} - ${String(arg.maxLength)}`);
62
+ }
63
+ break;
73
64
  }
74
- return parts.join(", ");
75
- }
76
- static createArgument(type) {
77
- return function(options) {
78
- const objOptions = typeof options === "string" ? { name: options } : options;
79
- const fullOptions = { ...objOptions, type };
80
- if (!fullOptions.description) {
81
- fullOptions.description = fullOptions.name;
65
+ case "number" /* Number */:
66
+ case "integer" /* Integer */: {
67
+ if (arg.minValue !== void 0 && arg.maxValue === void 0) {
68
+ parts.push(`\u2265 ${String(arg.minValue)}`);
82
69
  }
83
- if (!("required" in fullOptions)) {
84
- fullOptions.required = true;
70
+ if (arg.minValue === void 0 && arg.maxValue !== void 0) {
71
+ parts.push(`\u2264 ${String(arg.maxValue)}`);
85
72
  }
86
- return function(target, key, _index) {
87
- const method = Object.getOwnPropertyDescriptor(target, key)?.value;
88
- if (!method) {
89
- throw new Error("No method found");
90
- }
91
- const args = _Arg.getMethodArguments(method, true);
92
- args.unshift(fullOptions);
93
- };
94
- };
73
+ if (arg.minValue !== void 0 && arg.maxValue !== void 0) {
74
+ parts.push(`${String(arg.minValue)} - ${String(arg.maxValue)}`);
75
+ }
76
+ break;
77
+ }
78
+ case "user" /* User */:
79
+ case "member" /* Member */: {
80
+ break;
81
+ }
95
82
  }
83
+ return parts.join(", ");
84
+ }
85
+ function format(arg) {
86
+ const { name, required, tuple } = arg;
87
+ const opening = required ? "<" : "[";
88
+ const closing = required ? ">" : "]";
89
+ const prefix = tuple ? "..." : "";
90
+ return `${opening}${prefix}${name}: ${describeArgumentExpectation(arg)}${closing}`;
91
+ }
92
+ var Arg = {
93
+ getMethodArguments,
94
+ createArgument,
95
+ describeArgumentExpectation,
96
+ format,
97
+ string,
98
+ number,
99
+ integer,
100
+ user,
101
+ member
96
102
  };
97
103
 
98
104
  // src/command/CommandEntry.ts
99
105
  import { Collection } from "discord.js";
100
- var HookExecutionState = /* @__PURE__ */ ((HookExecutionState2) => {
101
- HookExecutionState2["Main"] = "main";
102
- HookExecutionState2["Pre"] = "pre";
103
- HookExecutionState2["Post"] = "post";
104
- HookExecutionState2["Error"] = "error";
105
- return HookExecutionState2;
106
- })(HookExecutionState || {});
107
- var HOOKS_KEY = Symbol("hooks");
108
- var BaseCommandEntry = class _BaseCommandEntry {
109
- constructor(options) {
110
- this.options = options;
111
- }
112
- static cache = /* @__PURE__ */ new WeakMap();
113
- main = _BaseCommandEntry.createMainHookDecorator("main" /* Main */, this);
114
- pre = _BaseCommandEntry.createMainHookDecorator("pre" /* Pre */, this);
115
- post = _BaseCommandEntry.createMainHookDecorator("post" /* Post */, this);
116
- error = _BaseCommandEntry.createErrorHookDecorator("error" /* Error */, this);
117
- static getHooks(constructor, init = false) {
118
- let hooks = this.cache.get(constructor) ?? Reflect.getMetadata(HOOKS_KEY, constructor);
119
- if (!hooks) {
120
- hooks = [];
121
- if (init) {
122
- Reflect.defineMetadata(HOOKS_KEY, hooks, constructor);
123
- this.cache.set(constructor, hooks);
124
- }
125
- }
126
- return init ? hooks : Object.freeze([...hooks]);
127
- }
128
- static createMainHookDecorator(state, entry) {
106
+
107
+ // src/base/BaseEntry.ts
108
+ var BaseEntry = class {
109
+ target;
110
+ hooks = {
111
+ ["MAIN" /* Main */]: void 0,
112
+ ["ERROR" /* Error */]: void 0,
113
+ ["POST" /* Post */]: void 0,
114
+ ["PRE" /* Pre */]: void 0
115
+ };
116
+ main;
117
+ pre;
118
+ post;
119
+ error;
120
+ constructor() {
121
+ this.main = this.createMainHookDecorator("MAIN" /* Main */);
122
+ this.pre = this.createMainHookDecorator("PRE" /* Pre */);
123
+ this.post = this.createMainHookDecorator("POST" /* Post */);
124
+ this.error = this.createMainHookDecorator("ERROR" /* Error */);
125
+ }
126
+ setTarget(target) {
127
+ this.target = target;
128
+ }
129
+ createMainHookDecorator(state) {
129
130
  return (target, _key, descriptor) => {
130
- this.addHook(target, state, descriptor.value, entry);
131
+ this.addHook(state, target, descriptor);
131
132
  };
132
133
  }
133
- static createErrorHookDecorator(state, entry) {
134
+ createErrorHookDecorator(state) {
134
135
  return (target, _key, descriptor) => {
135
- this.addHook(target, state, descriptor.value, entry);
136
+ this.addHook(state, target, descriptor);
136
137
  };
137
138
  }
138
- static addHook(target, state, method, entry) {
139
- const { constructor } = target;
140
- const hooks = _BaseCommandEntry.getHooks(constructor, true);
141
- if (typeof method !== "function") {
142
- throw new Error("CommandEntry decorator must be used with a class method.");
143
- }
144
- if (hooks.some((hook) => hook.state === state && hook.entry === entry)) {
145
- throw new Error(`Hook "${state}" is already defined for entry "${entry.options.name}".`);
139
+ addHook(state, target, descriptor) {
140
+ if (this.target && this.target !== target.constructor) {
141
+ throw new Error("Hook is used at wrong constructor.");
146
142
  }
147
- if ("parent" in entry) {
148
- const parentHook = hooks.find(
149
- (hook) => hook.entry === entry.parent && hook.state === "main" /* Main */
150
- );
151
- if (parentHook) {
152
- const parentArgs = Arg.getMethodArguments(parentHook.method);
153
- if (parentArgs.at(-1)?.tuple) {
154
- throw new Error(
155
- `Cannot add hook "${state}" to entry "${entry.options.name}" because its parent "${entry.parent.options.name}" has a tuple argument.`
156
- );
157
- }
158
- }
143
+ const { value: method } = descriptor;
144
+ if (typeof method !== "function") {
145
+ throw new Error("Invalid target method for hook.");
159
146
  }
160
- hooks.push({
147
+ const hook = {
161
148
  state,
162
- entry,
163
- method
164
- });
149
+ method,
150
+ entry: this
151
+ };
152
+ this.hooks[state] = hook;
153
+ }
154
+ };
155
+
156
+ // src/command/CommandEntry.ts
157
+ var BaseCommandEntry = class extends BaseEntry {
158
+ constructor(options) {
159
+ super();
160
+ this.options = options;
165
161
  }
166
162
  };
167
163
  var BaseCommandGroupEntry = class extends BaseCommandEntry {
168
164
  children = new Collection();
169
165
  subcommand(options) {
170
- if (typeof options === "string") {
171
- options = { name: options };
172
- }
173
- if (!options.description) {
174
- options.description = options.name;
175
- }
176
- if (this.children.has(options.name)) {
177
- throw new Error(`Entry with name "${options.name}" already exists.`);
166
+ const fullOptions = typeof options === "string" ? { name: options, description: `${options} command` } : { description: `${options.name} command`, ...options };
167
+ if (this.children.has(fullOptions.name)) {
168
+ throw new Error(`Entry "${fullOptions.name}" is already existed.`);
178
169
  }
179
- if (!(this instanceof CommandGroupEntry) && !(this instanceof RootCommandEntry)) {
180
- throw new Error(`Invalid parent "${this.constructor.name}"`);
170
+ const subcommand = new SubcommandEntry(fullOptions, this);
171
+ this.children.set(fullOptions.name, subcommand);
172
+ return subcommand;
173
+ }
174
+ };
175
+ var RootCommandEntry = class extends BaseCommandGroupEntry {
176
+ group(options) {
177
+ const fullOptions = typeof options === "string" ? { name: options, description: `${options} command` } : { description: `${options.name} command`, ...options };
178
+ if (this.children.has(fullOptions.name)) {
179
+ throw new Error(`Entry "${fullOptions.name}" is already existed.`);
181
180
  }
182
- const entry = new SubcommandEntry(options, this);
183
- this.children.set(entry.options.name, entry);
184
- return entry;
181
+ const group = new CommandGroupEntry(fullOptions, this);
182
+ this.children.set(fullOptions.name, group);
183
+ return group;
185
184
  }
186
185
  };
187
186
  var CommandGroupEntry = class extends BaseCommandGroupEntry {
188
187
  constructor(options, parent) {
189
188
  super(options);
190
- this.options = options;
191
189
  this.parent = parent;
192
190
  }
193
191
  };
194
- var RootCommandEntry = class extends BaseCommandGroupEntry {
195
- constructor(options) {
196
- super(options);
197
- this.options = options;
198
- }
199
- group(options) {
200
- if (typeof options === "string") {
201
- options = { name: options };
202
- }
203
- if (!options.description) {
204
- options.description = options.name;
205
- }
206
- if (this.children.has(options.name)) {
207
- throw new Error(`Entry with name "${options.name}" already exists.`);
208
- }
209
- const entry = new CommandGroupEntry(options, this);
210
- this.children.set(entry.options.name, entry);
211
- return entry;
212
- }
213
- };
214
192
  var SubcommandEntry = class extends BaseCommandEntry {
215
193
  constructor(options, parent) {
216
194
  super(options);
217
- this.options = options;
218
195
  this.parent = parent;
219
196
  }
220
197
  };
221
198
 
222
199
  // src/command/Command.ts
223
- var ROOT_KEY = Symbol("root");
224
- var Command = class {
225
- static create(options) {
226
- if (typeof options === "string") {
227
- options = { name: options };
228
- }
229
- if (!options.description) {
230
- options.description = options.name;
231
- }
232
- return new RootCommandEntry(options);
233
- }
234
- static use(command) {
200
+ var CommandAPI;
201
+ ((CommandAPI2) => {
202
+ const rootEntries = /* @__PURE__ */ new WeakMap();
203
+ function use(root) {
235
204
  return (target) => {
236
- Reflect.defineMetadata(ROOT_KEY, command, target);
205
+ root.setTarget(target);
206
+ rootEntries.set(target, root);
237
207
  };
238
208
  }
239
- static getRoot(constructor) {
240
- return Reflect.getMetadata(ROOT_KEY, constructor);
209
+ CommandAPI2.use = use;
210
+ function getRoot(constructor) {
211
+ return rootEntries.get(constructor);
241
212
  }
242
- };
213
+ CommandAPI2.getRoot = getRoot;
214
+ })(CommandAPI || (CommandAPI = {}));
215
+ function CommandFactory(options) {
216
+ if (typeof options === "string") {
217
+ options = { name: options };
218
+ }
219
+ if (!options.description) {
220
+ options.description = options.name;
221
+ }
222
+ return new RootCommandEntry(options);
223
+ }
224
+ var Command = Object.assign(CommandFactory, CommandAPI);
243
225
 
244
226
  // src/command/CommandRegistry.ts
245
227
  import {
@@ -253,6 +235,10 @@ import { pathToFileURL } from "url";
253
235
  var CommandRegistry = class _CommandRegistry {
254
236
  static constructors = new Collection2();
255
237
  static instances = new Collection2();
238
+ /**
239
+ * Add a command to the registry.
240
+ * @param constructor The command class you want to add.
241
+ */
256
242
  static add(constructor) {
257
243
  const root = Command.getRoot(constructor);
258
244
  if (!root) {
@@ -262,20 +248,13 @@ var CommandRegistry = class _CommandRegistry {
262
248
  this.constructors.set(options.name, constructor);
263
249
  this.instances.set(options.name, new constructor());
264
250
  }
265
- static buildSlashCommand(constructor) {
266
- const builder = new SlashCommandBuilder();
267
- const root = Command.getRoot(constructor);
268
- if (!root) {
269
- throw new Error(`No root found for "${constructor.name}"`);
270
- }
271
- const { options } = root;
272
- builder.setName(options.name);
273
- builder.setDescription(options.description || "");
274
- builder.setNSFW(Boolean(options.nsfw));
275
- this.buildSlashCommandOptions(builder, constructor);
276
- return builder.toJSON();
277
- }
278
- static async loadDirectory(pattern, parallel = true) {
251
+ /**
252
+ * Load and add all commands which matched provided glob pattern to the registry.
253
+ * @param pattern glob pattern to load.
254
+ * @param parallel load all matched results in parallel, enabled by default.
255
+ * @returns All loaded command constructors.
256
+ */
257
+ static async load(pattern, parallel = true) {
279
258
  const files = await glob(pattern);
280
259
  const loaders = files.map(async (file) => {
281
260
  const fileURL = pathToFileURL(file).toString();
@@ -292,72 +271,102 @@ var CommandRegistry = class _CommandRegistry {
292
271
  }
293
272
  return result;
294
273
  }
295
- static buildSlashCommandOptions(builder, constructor) {
274
+ /**
275
+ * Build a command into application command data.
276
+ * @param constructor The command class you want to build.
277
+ * @returns a REST JSON version of the application command data.
278
+ */
279
+ static buildSlashCommand(constructor) {
296
280
  const root = Command.getRoot(constructor);
297
281
  if (!root) {
298
282
  throw new Error(`No root found for "${constructor.name}"`);
299
283
  }
300
- const hooks = new Collection2(
301
- BaseCommandEntry.getHooks(constructor).filter((hook) => hook.state === "main" /* Main */).map((hook) => [hook.entry, hook])
302
- );
303
- const rootHook = hooks.get(root);
304
- if (!root.children.size && hooks.size) {
305
- if (!rootHook) {
306
- return;
307
- }
308
- for (const arg of Arg.getMethodArguments(rootHook.method)) {
309
- this.buildSlashCommandOption(builder, arg);
310
- }
311
- return;
284
+ const { options } = root;
285
+ const builder = new SlashCommandBuilder().setName(options.name).setDescription(options.description).setNSFW(Boolean(options.nsfw));
286
+ const args = this.getMainHookArguments(root);
287
+ if (root.children.size) {
288
+ this.buildSlashCommandSubcommands(builder, root, args);
289
+ } else {
290
+ this.buildSlashCommandOptions(builder, args);
312
291
  }
313
- for (const child of root.children.values()) {
314
- const hook = hooks.get(child);
315
- const inheritedArgs = [];
316
- if (rootHook) {
317
- inheritedArgs.push(...Arg.getMethodArguments(rootHook.method));
318
- }
319
- if (child instanceof SubcommandEntry) {
320
- this.buildSubcommand(builder, child, hook, inheritedArgs);
321
- } else if (child instanceof CommandGroupEntry) {
322
- if (hook) {
323
- inheritedArgs.push(...Arg.getMethodArguments(hook.method));
324
- }
292
+ return builder.toJSON();
293
+ }
294
+ static getMainHookArguments(entry) {
295
+ const { hooks } = entry;
296
+ const mainHook = hooks["MAIN" /* Main */];
297
+ return mainHook ? Arg.getMethodArguments(mainHook.method) : [];
298
+ }
299
+ static buildSlashCommandSubcommands(parent, entry, inheritedArgs) {
300
+ const { children } = entry;
301
+ for (const child of children.values()) {
302
+ if (child instanceof CommandGroupEntry && parent instanceof SlashCommandBuilder) {
325
303
  const { options } = child;
326
304
  const group = new SlashCommandSubcommandGroupBuilder().setName(options.name).setDescription(options.description);
327
- for (const subChild of child.children.values()) {
328
- this.buildSubcommand(group, subChild, hooks.get(subChild), inheritedArgs);
329
- }
330
- builder.addSubcommandGroup(group);
305
+ this.buildSlashCommandSubcommands(group, child, [
306
+ ...inheritedArgs,
307
+ ...this.getMainHookArguments(child)
308
+ ]);
309
+ parent.addSubcommandGroup(group);
310
+ } else if (child instanceof SubcommandEntry) {
311
+ const { options } = child;
312
+ const subcommand = new SlashCommandSubcommandBuilder().setName(options.name).setDescription(options.description);
313
+ this.buildSlashCommandOptions(subcommand, [
314
+ ...inheritedArgs,
315
+ ...this.getMainHookArguments(child)
316
+ ]);
317
+ parent.addSubcommand(subcommand);
331
318
  }
332
319
  }
333
320
  }
334
- static buildSubcommand(parent, entry, hook, inheritedArgs) {
335
- const { options } = entry;
336
- const subcommand = new SlashCommandSubcommandBuilder().setName(options.name).setDescription(options.description);
337
- const args = [...inheritedArgs];
338
- if (hook) {
339
- args.push(...Arg.getMethodArguments(hook.method));
340
- }
341
- for (const arg of args) {
342
- this.buildSlashCommandOption(subcommand, arg);
321
+ static buildSlashCommandOptions(builder, args) {
322
+ const argGroup = Object.groupBy(args, ({ required }) => required ? "required" : "optional");
323
+ const orderedArgs = [...argGroup.required || [], ...argGroup.optional || []];
324
+ for (const arg of orderedArgs) {
325
+ this.attachSlashCommandOption(builder, arg);
343
326
  }
344
- parent.addSubcommand(subcommand);
345
327
  }
346
- static buildSlashCommandOption(builder, arg) {
328
+ static attachSlashCommandOption(builder, arg) {
347
329
  const setupOption = (option) => {
348
330
  return option.setName(arg.name).setDescription(arg.description || arg.name).setRequired(Boolean(arg.required));
349
331
  };
350
332
  switch (arg.type) {
351
333
  case "string" /* String */: {
352
- builder.addStringOption((option) => setupOption(option));
334
+ builder.addStringOption((data) => {
335
+ const option = setupOption(data);
336
+ if (arg.maxLength) {
337
+ option.setMaxLength(arg.maxLength);
338
+ }
339
+ if (arg.minLength) {
340
+ option.setMinLength(arg.minLength);
341
+ }
342
+ return option;
343
+ });
353
344
  break;
354
345
  }
355
346
  case "integer" /* Integer */: {
356
- builder.addIntegerOption((option) => setupOption(option));
347
+ builder.addIntegerOption((data) => {
348
+ const option = setupOption(data);
349
+ if (arg.maxValue) {
350
+ option.setMaxValue(arg.maxValue);
351
+ }
352
+ if (arg.minValue) {
353
+ option.setMinValue(arg.minValue);
354
+ }
355
+ return option;
356
+ });
357
357
  break;
358
358
  }
359
359
  case "number" /* Number */: {
360
- builder.addNumberOption((option) => setupOption(option));
360
+ builder.addNumberOption((data) => {
361
+ const option = setupOption(data);
362
+ if (arg.maxValue) {
363
+ option.setMaxValue(arg.maxValue);
364
+ }
365
+ if (arg.minValue) {
366
+ option.setMinValue(arg.minValue);
367
+ }
368
+ return option;
369
+ });
361
370
  break;
362
371
  }
363
372
  case "user" /* User */:
@@ -454,10 +463,10 @@ export {
454
463
  BaseContext,
455
464
  ChatInputContext,
456
465
  Command,
466
+ CommandAPI,
467
+ CommandFactory,
457
468
  CommandGroupEntry,
458
469
  CommandRegistry,
459
- HOOKS_KEY,
460
- HookExecutionState,
461
470
  MessageContext,
462
471
  RootCommandEntry,
463
472
  SubcommandEntry