bakit 2.0.0-alpha.14 → 2.0.0-alpha.16

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.
@@ -2,34 +2,16 @@ import { config } from 'dotenv';
2
2
  import { program } from 'commander';
3
3
  import { fork } from 'child_process';
4
4
  import chokidar from 'chokidar';
5
- import path, { resolve, relative, sep } from 'path';
5
+ import path, { relative, sep } from 'path';
6
6
  import { createJiti } from 'jiti';
7
7
 
8
- // src/bin/bakit.ts
9
- var Module = class {
10
- static jiti = createJiti(process.cwd());
11
- static async import(module, defaultImport = false) {
12
- let path2 = resolve(module);
13
- try {
14
- return await this.jiti.import(path2, { default: defaultImport });
15
- } catch (error) {
16
- return console.error(`[Module] Import failed for ${path2}:`, error), null;
17
- }
18
- }
19
- static isLoaded(module) {
20
- let path2 = resolve(module);
21
- return !!path2 && !!this.jiti.cache[path2];
22
- }
23
- static unload(module) {
24
- let path2 = resolve(module);
25
- return !path2 || !this.jiti.cache[path2] ? false : (delete this.jiti.cache[path2], true);
26
- }
27
- static getTopLevel(path2, entryDir) {
28
- return relative(entryDir, path2).split(sep)[0] ?? null;
29
- }
30
- };
8
+ // src/cli/bin.ts
9
+ createJiti(process.cwd());
10
+ function getTopLevelDirectory(path2, entryDir) {
11
+ return relative(entryDir, path2).split(sep)[0] ?? null;
12
+ }
31
13
 
32
- // src/base/process/DevProcessManager.ts
14
+ // src/cli/process/DevProcessManager.ts
33
15
  var DevProcessManager = class {
34
16
  constructor(options) {
35
17
  this.options = options;
@@ -74,7 +56,7 @@ var DevProcessManager = class {
74
56
  onFileChanged(file) {
75
57
  if (!this.child)
76
58
  return;
77
- let top = Module.getTopLevel(file, this.options.rootDir);
59
+ let top = getTopLevelDirectory(file, this.options.rootDir);
78
60
  if (top && this.options.hotDirs.includes(top)) {
79
61
  this.child.connected && this.child.send({ type: `hmr:${top}`, file });
80
62
  return;
@@ -88,7 +70,7 @@ var DevProcessManager = class {
88
70
  }
89
71
  };
90
72
 
91
- // src/bin/bakit.ts
73
+ // src/cli/bin.ts
92
74
  program.name("bakit");
93
75
  program.command("dev").action(() => {
94
76
  config({ path: [".env.local", ".env"], quiet: true }), new DevProcessManager({
package/dist/index.d.ts CHANGED
@@ -1,52 +1,41 @@
1
1
  import * as discord_js from 'discord.js';
2
- import { GatewayIntentBits, ClientOptions, ChatInputCommandInteraction, CacheType, Message, User, MessageCreateOptions, InteractionReplyOptions, Awaitable, Collection, Events, IntentsBitField, ClientEvents, Client } from 'discord.js';
3
- import z$1, { z } from 'zod';
4
- import * as jiti from 'jiti';
2
+ import { ChatInputCommandInteraction, CacheType, Message, User, MessageCreateOptions, InteractionReplyOptions, Awaitable, Collection, Events, IntentsBitField, ClientEvents, Client, ClientOptions } from 'discord.js';
5
3
  import { inspect } from 'node:util';
4
+ import z from 'zod';
6
5
 
7
- declare const ProjectConfigSchema: z.ZodObject<{
8
- intents: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBigInt, z.ZodArray<z.ZodEnum<typeof GatewayIntentBits>>]>>;
9
- clientOptions: z.ZodOptional<z.ZodCustom<Omit<ClientOptions, "intents">, Omit<ClientOptions, "intents">>>;
10
- prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
11
- token: z.ZodString;
12
- }, z.core.$strip>;
13
- type ProjectConfigInput = z.input<typeof ProjectConfigSchema>;
14
- type ProjectConfig = z.output<typeof ProjectConfigSchema>;
15
- /**
16
- * Define config object for your project. This is just a cleaner way to define config.
17
- * @param config The partial version of project config.
18
- * @returns The same config you provided earlier.
19
- */
20
- declare function defineConfig(config: ProjectConfigInput): ProjectConfigInput;
21
- /**
22
- * Load the config file and save them for later usage.
23
- * @param cwd The location of the config file, uses root by default.
24
- * @returns The complete config with default values from the validation.
25
- */
26
- declare function loadConfig(cwd?: string): Promise<ProjectConfig>;
27
- /**
28
- * Get the loaded config of the project.
29
- * @returns The project config.
30
- */
31
- declare function getConfig(): ProjectConfig;
32
-
33
- declare const EVENT_INTENT_MAPPING: Record<string, number[]>;
34
-
35
- declare function tokenize(content: string): string[];
36
- /**
37
- * Extracts a valid Discord Snowflake (User ID, Channel ID, etc.) from a string.
38
- * @param input The raw string to parse
39
- * @returns The extracted ID string, or null if invalid
40
- */
41
- declare function extractSnowflakeId(input: string): string | null;
42
-
43
- declare class Module {
44
- static jiti: jiti.Jiti;
45
- static import<T>(module: string, defaultImport?: boolean): Promise<T | null>;
46
- static isLoaded(module: string): boolean;
47
- static unload(module: string): boolean;
48
- static getTopLevel(path: string, entryDir: string): string | null;
6
+ declare enum ParamUserType {
7
+ Bot = "bot",
8
+ Normal = "normal",
9
+ Any = "any"
49
10
  }
11
+ declare const BaseParamSchema: z.ZodObject<{
12
+ name: z.ZodString;
13
+ description: z.ZodOptional<z.ZodString>;
14
+ required: z.ZodDefault<z.ZodBoolean>;
15
+ }, z.z.core.$strip>;
16
+ declare const StringParamSchema: z.ZodObject<{
17
+ name: z.ZodString;
18
+ description: z.ZodOptional<z.ZodString>;
19
+ required: z.ZodDefault<z.ZodBoolean>;
20
+ maxLength: z.ZodOptional<z.ZodNumber>;
21
+ minLength: z.ZodOptional<z.ZodNumber>;
22
+ }, z.z.core.$strip>;
23
+ declare const NumberParamSchema: z.ZodObject<{
24
+ name: z.ZodString;
25
+ description: z.ZodOptional<z.ZodString>;
26
+ required: z.ZodDefault<z.ZodBoolean>;
27
+ maxValue: z.ZodOptional<z.ZodNumber>;
28
+ minValue: z.ZodOptional<z.ZodNumber>;
29
+ }, z.z.core.$strip>;
30
+ declare const UserParamSchema: z.ZodObject<{
31
+ name: z.ZodString;
32
+ description: z.ZodOptional<z.ZodString>;
33
+ required: z.ZodDefault<z.ZodBoolean>;
34
+ }, z.z.core.$strip>;
35
+ type BaseParamOptions = z.input<typeof BaseParamSchema>;
36
+ type StringOptions = z.input<typeof StringParamSchema>;
37
+ type NumberOptions = z.input<typeof NumberParamSchema>;
38
+ type UserOptions = z.input<typeof UserParamSchema>;
50
39
 
51
40
  declare class Context {
52
41
  canceled: boolean;
@@ -82,68 +71,6 @@ declare class MessageContext<Cached extends boolean = boolean, InGuild extends b
82
71
  }
83
72
  type CommandContext<Cached extends boolean = boolean, InGuild extends boolean = boolean> = ChatInputContext<Cached, InGuild> | MessageContext<Cached, InGuild>;
84
73
 
85
- declare enum HookState {
86
- Pre = "PRE",
87
- Main = "MAIN",
88
- Post = "POST",
89
- Error = "ERROR"
90
- }
91
- declare enum HookOrder {
92
- First = 0,
93
- Last = 1
94
- }
95
- type MainHookCallback<C extends Context, Args extends unknown[]> = (context: C, ...args: Args) => Awaitable<void>;
96
- type ErrorHookCallback<C extends Context, Args extends unknown[]> = (context: C, error: unknown, ...args: Args) => Awaitable<void>;
97
- declare class LifecycleManager<C extends Context, Args extends unknown[]> {
98
- id: string;
99
- private readonly hooks;
100
- constructor(id: string);
101
- getName(name: string): string;
102
- setHook(name: string, state: HookState.Post, callback: MainHookCallback<C, Args>, order?: HookOrder): this;
103
- setHook(name: string, state: HookState.Main, callback: MainHookCallback<C, Args>, order?: HookOrder): this;
104
- setHook(name: string, state: HookState.Pre, callback: MainHookCallback<C, Args>, order?: HookOrder): this;
105
- setHook(name: string, state: HookState.Error, callback: ErrorHookCallback<C, Args>, order?: HookOrder): this;
106
- main(callback: MainHookCallback<C, Args>): this;
107
- pre(callback: MainHookCallback<C, Args>): this;
108
- post(callback: MainHookCallback<C, Args>): this;
109
- error(callback: ErrorHookCallback<C, Args>): this;
110
- execute(context: C, ...args: Args): Promise<void>;
111
- }
112
-
113
- declare enum ParamUserType {
114
- Bot = "bot",
115
- Normal = "normal",
116
- Any = "any"
117
- }
118
- declare const BaseParamSchema: z.ZodObject<{
119
- name: z.ZodString;
120
- description: z.ZodOptional<z.ZodString>;
121
- required: z.ZodDefault<z.ZodBoolean>;
122
- }, z.core.$strip>;
123
- declare const StringParamSchema: z.ZodObject<{
124
- name: z.ZodString;
125
- description: z.ZodOptional<z.ZodString>;
126
- required: z.ZodDefault<z.ZodBoolean>;
127
- maxLength: z.ZodOptional<z.ZodNumber>;
128
- minLength: z.ZodOptional<z.ZodNumber>;
129
- }, z.core.$strip>;
130
- declare const NumberParamSchema: z.ZodObject<{
131
- name: z.ZodString;
132
- description: z.ZodOptional<z.ZodString>;
133
- required: z.ZodDefault<z.ZodBoolean>;
134
- maxValue: z.ZodOptional<z.ZodNumber>;
135
- minValue: z.ZodOptional<z.ZodNumber>;
136
- }, z.core.$strip>;
137
- declare const UserParamSchema: z.ZodObject<{
138
- name: z.ZodString;
139
- description: z.ZodOptional<z.ZodString>;
140
- required: z.ZodDefault<z.ZodBoolean>;
141
- }, z.core.$strip>;
142
- type BaseParamOptions = z.input<typeof BaseParamSchema>;
143
- type StringOptions = z.input<typeof StringParamSchema>;
144
- type NumberOptions = z.input<typeof NumberParamSchema>;
145
- type UserOptions = z.input<typeof UserParamSchema>;
146
-
147
74
  type ParamResolvedOutputType<OutputType, Required extends boolean = true> = Required extends true ? OutputType : OutputType | null;
148
75
  declare abstract class BaseParam<Options extends BaseParamOptions, OutputType, Required extends boolean = true> {
149
76
  private schema;
@@ -159,7 +86,7 @@ declare abstract class BaseParam<Options extends BaseParamOptions, OutputType, R
159
86
  * @internal
160
87
  */
161
88
  readonly _type: Required extends true ? OutputType : OutputType | null;
162
- constructor(options: Options, schema: z$1.ZodObject);
89
+ constructor(options: Options, schema: z.ZodObject);
163
90
  protected setOption(key: keyof Options, value: any): this;
164
91
  name(value: string): this;
165
92
  description(value: string): this;
@@ -223,6 +150,34 @@ type InferParamTuple<T extends readonly BaseParam<any, any, any>[]> = {
223
150
  [K in keyof T]: T[K] extends AnyParam<any> ? InferParamValue<T[K]> : never;
224
151
  };
225
152
 
153
+ declare enum HookState {
154
+ Pre = "PRE",
155
+ Main = "MAIN",
156
+ Post = "POST",
157
+ Error = "ERROR"
158
+ }
159
+ declare enum HookOrder {
160
+ First = 0,
161
+ Last = 1
162
+ }
163
+ type MainHookCallback<C extends Context, Args extends unknown[]> = (context: C, ...args: Args) => Awaitable<void>;
164
+ type ErrorHookCallback<C extends Context, Args extends unknown[]> = (context: C, error: unknown, ...args: Args) => Awaitable<void>;
165
+ declare class LifecycleManager<C extends Context, Args extends unknown[]> {
166
+ id: string;
167
+ private readonly hooks;
168
+ constructor(id: string);
169
+ getName(name: string): string;
170
+ setHook(name: string, state: HookState.Post, callback: MainHookCallback<C, Args>, order?: HookOrder): this;
171
+ setHook(name: string, state: HookState.Main, callback: MainHookCallback<C, Args>, order?: HookOrder): this;
172
+ setHook(name: string, state: HookState.Pre, callback: MainHookCallback<C, Args>, order?: HookOrder): this;
173
+ setHook(name: string, state: HookState.Error, callback: ErrorHookCallback<C, Args>, order?: HookOrder): this;
174
+ main(callback: MainHookCallback<C, Args>): this;
175
+ pre(callback: MainHookCallback<C, Args>): this;
176
+ post(callback: MainHookCallback<C, Args>): this;
177
+ error(callback: ErrorHookCallback<C, Args>): this;
178
+ execute(context: C, ...args: Args): Promise<void>;
179
+ }
180
+
226
181
  declare function validateParamsOrder(params: readonly AnyParam<boolean>[]): boolean;
227
182
  declare const CommandOptionsSchema: z.ZodPipe<z.ZodObject<{
228
183
  name: z.ZodReadonly<z.ZodString>;
@@ -238,7 +193,7 @@ declare const CommandOptionsSchema: z.ZodPipe<z.ZodObject<{
238
193
  required?: boolean | undefined;
239
194
  }, unknown, boolean>>>>>;
240
195
  quotes: z.ZodReadonly<z.ZodDefault<z.ZodBoolean>>;
241
- }, z.core.$strip>, z.ZodTransform<{
196
+ }, z.z.core.$strip>, z.ZodTransform<{
242
197
  description: string;
243
198
  name: string;
244
199
  nsfw: boolean;
@@ -321,6 +276,7 @@ declare class CommandManager extends BaseClientManager {
321
276
  * @returns The command object if unloaded successfully.
322
277
  */
323
278
  unload(path: string): Promise<Command | undefined>;
279
+ reload(path: string): Promise<Command<any[]> | undefined>;
324
280
  /**
325
281
  * Add a command to the registry.
326
282
  * @param command Command to add.
@@ -340,11 +296,11 @@ declare class CommandManager extends BaseClientManager {
340
296
  get(name: string): Command<any[]> | undefined;
341
297
  }
342
298
 
343
- declare const ListenerOptionsSchema: z$1.ZodObject<{
344
- name: z$1.ZodEnum<typeof Events>;
345
- once: z$1.ZodDefault<z$1.ZodBoolean>;
346
- }, z$1.z.core.$strip>;
347
- type ListenerOptions<K extends EventKey = EventKey> = Omit<z$1.input<typeof ListenerOptionsSchema>, "name"> & {
299
+ declare const ListenerOptionsSchema: z.ZodObject<{
300
+ name: z.ZodEnum<typeof Events>;
301
+ once: z.ZodDefault<z.ZodBoolean>;
302
+ }, z.z.core.$strip>;
303
+ type ListenerOptions<K extends EventKey = EventKey> = Omit<z.input<typeof ListenerOptionsSchema>, "name"> & {
348
304
  name: K;
349
305
  };
350
306
  type EventKey = keyof BakitClientEvents;
@@ -373,6 +329,7 @@ declare class ListenerManager extends BaseClientManager {
373
329
  * @returns The listener object if unloaded successfully.
374
330
  */
375
331
  unload(path: string): Promise<Listener | undefined>;
332
+ reload(path: string): Promise<Listener<keyof BakitClientEvents> | undefined>;
376
333
  /**
377
334
  * Add a listener to the registry and create a listener for client.
378
335
  * @param listener Listener to add.
@@ -470,23 +427,7 @@ declare const Params: {
470
427
  }) => UserParam<Required>;
471
428
  };
472
429
 
473
- interface DevManagerOptions {
474
- rootDir: string;
475
- entry: string;
476
- hotDirs: string[];
477
- }
478
- declare class DevProcessManager {
479
- private options;
480
- private child;
481
- private restartTimer;
482
- constructor(options: DevManagerOptions);
483
- start(): void;
484
- private startChild;
485
- private restartChild;
486
- private startWatcher;
487
- private onFileChanged;
488
- private scheduleRestart;
489
- }
430
+ declare const EVENT_INTENT_MAPPING: Record<string, number[]>;
490
431
 
491
432
  declare class BakitError extends Error {
492
433
  constructor(message: string);
@@ -498,4 +439,21 @@ declare class ArgumentError extends BakitError {
498
439
  constructor(target: string, reason: string);
499
440
  }
500
441
 
501
- export { type AnyParam, ArgumentError, BakitClient, type BakitClientEvents, BakitError, BaseClientManager, BaseCommandContext, BaseParam, type BaseParamOptions, BaseParamSchema, ChatInputContext, type ChatInputContextSendOptions, Command, type CommandContext, CommandManager, type CommandOptions, type CommandOptionsInput, CommandOptionsSchema, Context, type ContextSendOptions, DevProcessManager, EVENT_INTENT_MAPPING, type ErrorHookCallback, type GetPrefixFunction, HookOrder, HookState, type InferParamTuple, type InferParamValue, Instance, LifecycleManager, Listener, ListenerManager, type ListenerOptions, ListenerOptionsSchema, type MainHookCallback, MessageContext, type MessageContextSendOptions, Module, type NumberOptions, NumberParam, NumberParamSchema, type ParamResolvedOutputType, ParamUserType, Params, ProjectCacheManager, type ProjectConfig, type ProjectConfigInput, ProjectConfigSchema, type StringOptions, StringParam, StringParamSchema, type UserOptions, UserParam, UserParamSchema, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, loadConfig, tokenize, useApp, validateParamsOrder };
442
+ declare function tokenize(content: string): string[];
443
+ /**
444
+ * Extracts a valid Discord Snowflake (User ID, Channel ID, etc.) from a string.
445
+ * @param input The raw string to parse
446
+ * @returns The extracted ID string, or null if invalid
447
+ */
448
+ declare function extractSnowflakeId(input: string): string | null;
449
+
450
+ declare function importModule<T>(modulePath: string, defaultImport?: boolean): Promise<T | null>;
451
+ declare function isModuleLoaded(modulePath: string): boolean;
452
+ declare function unloadModule(modulePath: string): boolean;
453
+ declare function getTopLevelDirectory(path: string, entryDir: string): string | null;
454
+
455
+ declare const messageCommandHandler: Listener<Events.MessageCreate>;
456
+ declare const chatInputCommandHandler: Listener<Events.InteractionCreate>;
457
+ declare const registerCommandsHandler: Listener<Events.ClientReady>;
458
+
459
+ export { type AnyParam, ArgumentError, BakitClient, type BakitClientEvents, BakitError, BaseClientManager, BaseCommandContext, BaseParam, type BaseParamOptions, BaseParamSchema, ChatInputContext, type ChatInputContextSendOptions, Command, type CommandContext, CommandManager, type CommandOptions, type CommandOptionsInput, CommandOptionsSchema, Context, type ContextSendOptions, EVENT_INTENT_MAPPING, type ErrorHookCallback, type GetPrefixFunction, HookOrder, HookState, type InferParamTuple, type InferParamValue, Instance, LifecycleManager, Listener, ListenerManager, type ListenerOptions, ListenerOptionsSchema, type MainHookCallback, MessageContext, type MessageContextSendOptions, type NumberOptions, NumberParam, NumberParamSchema, type ParamResolvedOutputType, ParamUserType, Params, ProjectCacheManager, type StringOptions, StringParam, StringParamSchema, type UserOptions, UserParam, UserParamSchema, chatInputCommandHandler, defineCommand, defineListener, extractSnowflakeId, getTopLevelDirectory, importModule, isModuleLoaded, messageCommandHandler, registerCommandsHandler, tokenize, unloadModule, useApp, validateParamsOrder };
package/dist/index.js CHANGED
@@ -1,16 +1,25 @@
1
1
  import { GatewayIntentBits, Events, Client, Collection, IntentsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandNumberOption, SlashCommandUserOption, ChatInputCommandInteraction, Message } from 'discord.js';
2
- import z4, { z } from 'zod';
2
+ import { inspect } from 'util';
3
+ import { posix, resolve, relative, sep, join, dirname } from 'path';
3
4
  import glob from 'tiny-glob';
5
+ import z4 from 'zod';
4
6
  import { createJiti } from 'jiti';
5
- import path, { resolve, relative, sep, posix, join, dirname } from 'path';
6
- import { inspect } from 'util';
7
- import { fork } from 'child_process';
8
- import chokidar from 'chokidar';
9
7
  import { existsSync, mkdirSync, rmSync } from 'fs';
10
8
  import { mkdir, writeFile, readFile, rm } from 'fs/promises';
11
9
  import { createHash } from 'crypto';
12
10
 
13
- // src/config.ts
11
+ // src/core/client/BakitClient.ts
12
+ var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z4.object({
13
+ name: z4.string(),
14
+ description: z4.string().optional(),
15
+ required: z4.boolean().default(true)
16
+ }), StringParamSchema = BaseParamSchema.extend({
17
+ maxLength: z4.number().min(1).optional(),
18
+ minLength: z4.number().min(1).optional()
19
+ }), NumberParamSchema = BaseParamSchema.extend({
20
+ maxValue: z4.number().optional(),
21
+ minValue: z4.number().optional()
22
+ }), UserParamSchema = BaseParamSchema.extend({});
14
23
  var INTENT_GROUPS = {
15
24
  [GatewayIntentBits.Guilds]: [
16
25
  Events.GuildCreate,
@@ -107,7 +116,23 @@ for (let [intentStr, events] of Object.entries(INTENT_GROUPS)) {
107
116
  EVENT_INTENT_MAPPING[event] ??= [], EVENT_INTENT_MAPPING[event].includes(intent) || EVENT_INTENT_MAPPING[event].push(intent);
108
117
  }
109
118
 
110
- // src/utils/string.ts
119
+ // src/lib/errors/BakitError.ts
120
+ var BakitError = class extends Error {
121
+ constructor(message) {
122
+ super(message), this.name = this.constructor.name, Object.setPrototypeOf(this, new.target.prototype);
123
+ }
124
+ };
125
+
126
+ // src/lib/errors/ArgumentError.ts
127
+ var ArgumentError = class extends BakitError {
128
+ constructor(target, reason) {
129
+ super(`Invalid argument for '${target}': ${reason}`);
130
+ this.target = target;
131
+ this.reason = reason;
132
+ }
133
+ };
134
+
135
+ // src/lib/utils/string.ts
111
136
  function tokenize(content) {
112
137
  let args = [], current = "", quoteChar = null, isEscaped = false;
113
138
  for (let i = 0; i < content.length; i++) {
@@ -134,247 +159,28 @@ function extractSnowflakeId(input) {
134
159
  let idMatch = /^(\d{17,20})$/.exec(input);
135
160
  return idMatch?.[1] ? idMatch[1] : null;
136
161
  }
137
- var Module = class {
138
- static jiti = createJiti(process.cwd());
139
- static async import(module, defaultImport = false) {
140
- let path2 = resolve(module);
141
- try {
142
- return await this.jiti.import(path2, { default: defaultImport });
143
- } catch (error) {
144
- return console.error(`[Module] Import failed for ${path2}:`, error), null;
145
- }
146
- }
147
- static isLoaded(module) {
148
- let path2 = resolve(module);
149
- return !!path2 && !!this.jiti.cache[path2];
150
- }
151
- static unload(module) {
152
- let path2 = resolve(module);
153
- return !path2 || !this.jiti.cache[path2] ? false : (delete this.jiti.cache[path2], true);
154
- }
155
- static getTopLevel(path2, entryDir) {
156
- return relative(entryDir, path2).split(sep)[0] ?? null;
162
+ var jiti = createJiti(process.cwd());
163
+ async function importModule(modulePath, defaultImport = false) {
164
+ let path = resolve(modulePath);
165
+ try {
166
+ return await jiti.import(path, { default: defaultImport });
167
+ } catch (error) {
168
+ return console.error(`[Module] Import failed for ${path}:`, error), null;
157
169
  }
158
- };
159
-
160
- // src/config.ts
161
- var ProjectConfigSchema = z.object({
162
- /**
163
- * The gateway intents to use for the Discord client.
164
- *
165
- * - `auto` — automatically determine the required intents.
166
- * - bigint — a raw bitfield value representing the combined intents.
167
- * - array — a list of individual intent flags from `GatewayIntentBits`.
168
- *
169
- * @defaultvalue `auto`
170
- */
171
- intents: z.union([z.literal("auto"), z.bigint(), z.array(z.enum(GatewayIntentBits))]).default("auto"),
172
- /**
173
- * Optional custom client options for Discord.js (excluding `intents`).
174
- *
175
- * These are passed directly to the `Client` constructor when initializing the bot.
176
- *
177
- * @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
178
- */
179
- clientOptions: z.custom().optional(),
180
- prefixes: z.array(z.string()).default([]),
181
- token: z.string()
182
- });
183
- function defineConfig(config) {
184
- return config;
185
170
  }
186
- var _config;
187
- async function loadConfig(cwd = process.cwd()) {
188
- if (_config)
189
- return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
190
- let globPattern = `bakit.config.{${["ts", "js"].join(",")}}`, [configPath, other] = await glob(globPattern, {
191
- cwd: cwd.replace(/\\/g, "/"),
192
- // ensure the path uses `/` instead of `\` on Windows
193
- absolute: true
194
- });
195
- if (!configPath)
196
- throw new Error("Missing config file");
197
- other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
198
- let config = await Module.import(configPath, true);
199
- return _config = Object.freeze(await ProjectConfigSchema.parseAsync(config)), _config;
171
+ function isModuleLoaded(modulePath) {
172
+ let path = resolve(modulePath);
173
+ return !!path && !!jiti.cache[path];
200
174
  }
201
- function getConfig() {
202
- if (!_config)
203
- throw new Error("Project config is not loaded.");
204
- return _config;
175
+ function unloadModule(modulePath) {
176
+ let path = resolve(modulePath);
177
+ return !path || !jiti.cache[path] ? false : (delete jiti.cache[path], true);
178
+ }
179
+ function getTopLevelDirectory(path, entryDir) {
180
+ return relative(entryDir, path).split(sep)[0] ?? null;
205
181
  }
206
182
 
207
- // src/base/lifecycle/Context.ts
208
- var Context = class {
209
- canceled = false;
210
- cancel() {
211
- this.canceled = true;
212
- }
213
- };
214
-
215
- // src/base/command/CommandContext.ts
216
- var BaseCommandContext = class extends Context {
217
- constructor(source) {
218
- super();
219
- this.source = source;
220
- }
221
- get client() {
222
- return this.source.client;
223
- }
224
- get channel() {
225
- return this.source.channel;
226
- }
227
- get channelId() {
228
- return this.source.channelId;
229
- }
230
- get guild() {
231
- return this.source.guild;
232
- }
233
- get guildId() {
234
- return this.source.guildId;
235
- }
236
- get member() {
237
- return this.source.member;
238
- }
239
- inGuild() {
240
- return !!this.guildId;
241
- }
242
- inCachedGuild() {
243
- if (this.isChatInput())
244
- return this.source.inCachedGuild();
245
- if (this.isMessage())
246
- return this.source.inGuild();
247
- throw new Error("Invalid source");
248
- }
249
- get user() {
250
- if (this.isChatInput())
251
- return this.source.user;
252
- if (this.isMessage())
253
- return this.source.author;
254
- throw new Error("Invalid source");
255
- }
256
- isChatInput() {
257
- return this.source instanceof ChatInputCommandInteraction;
258
- }
259
- isMessage() {
260
- return this.source instanceof Message;
261
- }
262
- }, ChatInputContext = class extends BaseCommandContext {
263
- async send(options) {
264
- typeof options == "string" && (options = { content: options });
265
- let sendOptions = {
266
- ...options,
267
- withResponse: true
268
- };
269
- return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
270
- }
271
- }, MessageContext = class extends BaseCommandContext {
272
- async send(options) {
273
- let { channel } = this;
274
- if (!channel?.isSendable())
275
- throw new Error("Invalid channel or channel is not sendable");
276
- return await channel.send(options);
277
- }
278
- };
279
- var HookState = /* @__PURE__ */ ((HookState2) => (HookState2.Pre = "PRE", HookState2.Main = "MAIN", HookState2.Post = "POST", HookState2.Error = "ERROR", HookState2))(HookState || {}), HookOrder = /* @__PURE__ */ ((HookOrder2) => (HookOrder2[HookOrder2.First = 0] = "First", HookOrder2[HookOrder2.Last = 1] = "Last", HookOrder2))(HookOrder || {}), LifecycleManager = class {
280
- constructor(id) {
281
- this.id = id;
282
- }
283
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
284
- hooks = {
285
- MAIN: new Collection(),
286
- PRE: new Collection(),
287
- POST: new Collection(),
288
- ERROR: new Collection()
289
- };
290
- getName(name) {
291
- return `${this.id}:${name}`;
292
- }
293
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
294
- setHook(name, state, callback, order = 1 /* Last */) {
295
- let currentHooks = this.hooks[state], key = this.getName(name);
296
- if (currentHooks.has(key) && console.warn(`Overriding duplicate hook '${key}' for state '${state}'`), order === 1 /* Last */)
297
- currentHooks.set(key, callback);
298
- else {
299
- let existingEntries = [...currentHooks.entries()].filter(([k]) => k !== key);
300
- currentHooks.clear(), currentHooks.set(key, callback);
301
- for (let [k, v] of existingEntries)
302
- currentHooks.set(k, v);
303
- }
304
- return this;
305
- }
306
- main(callback) {
307
- return this.setHook("main", "MAIN" /* Main */, callback);
308
- }
309
- pre(callback) {
310
- return this.setHook("pre", "PRE" /* Pre */, callback);
311
- }
312
- post(callback) {
313
- return this.setHook("post", "POST" /* Post */, callback);
314
- }
315
- error(callback) {
316
- return this.setHook("error", "ERROR" /* Error */, callback);
317
- }
318
- async execute(context, ...args) {
319
- let pipeline = [
320
- ...this.hooks.PRE.values(),
321
- ...this.hooks.MAIN.values(),
322
- ...this.hooks.POST.values()
323
- ], error;
324
- for (let hook of pipeline) {
325
- if (context.canceled)
326
- break;
327
- try {
328
- await hook(context, ...args);
329
- } catch (e) {
330
- error = e;
331
- break;
332
- }
333
- }
334
- if (!error)
335
- return;
336
- if (!this.hooks.ERROR.size)
337
- throw error;
338
- for (let [key, callback] of this.hooks.ERROR.entries()) {
339
- if (context.canceled)
340
- break;
341
- try {
342
- await callback(context, error, ...args);
343
- } catch (innerError) {
344
- console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
345
- }
346
- }
347
- }
348
- };
349
- var ParamUserType = /* @__PURE__ */ ((ParamUserType2) => (ParamUserType2.Bot = "bot", ParamUserType2.Normal = "normal", ParamUserType2.Any = "any", ParamUserType2))(ParamUserType || {}), BaseParamSchema = z.object({
350
- name: z.string(),
351
- description: z.string().optional(),
352
- required: z.boolean().default(true)
353
- }), StringParamSchema = BaseParamSchema.extend({
354
- maxLength: z.number().min(1).optional(),
355
- minLength: z.number().min(1).optional()
356
- }), NumberParamSchema = BaseParamSchema.extend({
357
- maxValue: z.number().optional(),
358
- minValue: z.number().optional()
359
- }), UserParamSchema = BaseParamSchema.extend({});
360
-
361
- // src/errors/BakitError.ts
362
- var BakitError = class extends Error {
363
- constructor(message) {
364
- super(message), this.name = this.constructor.name, Object.setPrototypeOf(this, new.target.prototype);
365
- }
366
- };
367
-
368
- // src/errors/ArgumentError.ts
369
- var ArgumentError = class extends BakitError {
370
- constructor(target, reason) {
371
- super(`Invalid argument for '${target}': ${reason}`);
372
- this.target = target;
373
- this.reason = reason;
374
- }
375
- };
376
-
377
- // src/base/command/param/Param.ts
183
+ // src/core/structures/param/Param.ts
378
184
  var BaseParam = class {
379
185
  constructor(options, schema) {
380
186
  this.schema = schema;
@@ -511,6 +317,78 @@ var BaseParam = class {
511
317
  return context.source.options.getUser(name, required);
512
318
  }
513
319
  };
320
+ var HookState = /* @__PURE__ */ ((HookState2) => (HookState2.Pre = "PRE", HookState2.Main = "MAIN", HookState2.Post = "POST", HookState2.Error = "ERROR", HookState2))(HookState || {}), HookOrder = /* @__PURE__ */ ((HookOrder2) => (HookOrder2[HookOrder2.First = 0] = "First", HookOrder2[HookOrder2.Last = 1] = "Last", HookOrder2))(HookOrder || {}), LifecycleManager = class {
321
+ constructor(id) {
322
+ this.id = id;
323
+ }
324
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
325
+ hooks = {
326
+ MAIN: new Collection(),
327
+ PRE: new Collection(),
328
+ POST: new Collection(),
329
+ ERROR: new Collection()
330
+ };
331
+ getName(name) {
332
+ return `${this.id}:${name}`;
333
+ }
334
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
335
+ setHook(name, state, callback, order = 1 /* Last */) {
336
+ let currentHooks = this.hooks[state], key = this.getName(name);
337
+ if (currentHooks.has(key) && console.warn(`Overriding duplicate hook '${key}' for state '${state}'`), order === 1 /* Last */)
338
+ currentHooks.set(key, callback);
339
+ else {
340
+ let existingEntries = [...currentHooks.entries()].filter(([k]) => k !== key);
341
+ currentHooks.clear(), currentHooks.set(key, callback);
342
+ for (let [k, v] of existingEntries)
343
+ currentHooks.set(k, v);
344
+ }
345
+ return this;
346
+ }
347
+ main(callback) {
348
+ return this.setHook("main", "MAIN" /* Main */, callback);
349
+ }
350
+ pre(callback) {
351
+ return this.setHook("pre", "PRE" /* Pre */, callback);
352
+ }
353
+ post(callback) {
354
+ return this.setHook("post", "POST" /* Post */, callback);
355
+ }
356
+ error(callback) {
357
+ return this.setHook("error", "ERROR" /* Error */, callback);
358
+ }
359
+ async execute(context, ...args) {
360
+ let pipeline = [
361
+ ...this.hooks.PRE.values(),
362
+ ...this.hooks.MAIN.values(),
363
+ ...this.hooks.POST.values()
364
+ ], error;
365
+ for (let hook of pipeline) {
366
+ if (context.canceled)
367
+ break;
368
+ try {
369
+ await hook(context, ...args);
370
+ } catch (e) {
371
+ error = e;
372
+ break;
373
+ }
374
+ }
375
+ if (!error)
376
+ return;
377
+ if (!this.hooks.ERROR.size)
378
+ throw error;
379
+ for (let [key, callback] of this.hooks.ERROR.entries()) {
380
+ if (context.canceled)
381
+ break;
382
+ try {
383
+ await callback(context, error, ...args);
384
+ } catch (innerError) {
385
+ console.error(`[Lifecycle] Error handler for '${key}' failed:`, innerError);
386
+ }
387
+ }
388
+ }
389
+ };
390
+
391
+ // src/core/structures/Command.ts
514
392
  function validateParamsOrder(params) {
515
393
  let seenOptional = false;
516
394
  for (let param of params)
@@ -521,12 +399,12 @@ function validateParamsOrder(params) {
521
399
  seenOptional = true;
522
400
  return true;
523
401
  }
524
- var CommandOptionsSchema = z.object({
525
- name: z.string().readonly(),
526
- description: z.string().min(1).max(100).optional().readonly(),
527
- nsfw: z.boolean().default(false).readonly(),
528
- params: z.array(z.instanceof(BaseParam)).default([]).readonly(),
529
- quotes: z.boolean().default(true).readonly()
402
+ var CommandOptionsSchema = z4.object({
403
+ name: z4.string().readonly(),
404
+ description: z4.string().min(1).max(100).optional().readonly(),
405
+ nsfw: z4.boolean().default(false).readonly(),
406
+ params: z4.array(z4.instanceof(BaseParam)).default([]).readonly(),
407
+ quotes: z4.boolean().default(true).readonly()
530
408
  }).transform((data) => ({
531
409
  ...data,
532
410
  description: data.description ?? `Command ${data.name}`
@@ -577,48 +455,54 @@ function defineCommand(options) {
577
455
  return new Command(options);
578
456
  }
579
457
 
580
- // src/base/client/BaseClientManager.ts
458
+ // src/core/managers/BaseClientManager.ts
581
459
  var BaseClientManager = class {
582
460
  constructor(client) {
583
461
  this.client = client;
584
462
  }
585
463
  };
586
464
 
587
- // src/base/command/CommandManager.ts
465
+ // src/core/managers/CommandManager.ts
588
466
  var CommandManager = class extends BaseClientManager {
589
467
  commands = new Collection();
590
468
  entries = new Collection();
591
469
  async loadModules(entryDir) {
592
470
  let pattern = posix.join(posix.resolve(entryDir), "commands", "**/*.{ts,js}"), files = await glob(pattern, { cwd: process.cwd() }), filtered = (await Promise.all(files.map((file) => this.load(file)))).filter((c) => !!c);
593
- return console.log(`[Loader] Loaded ${filtered.length}/${files.length}`), filtered;
471
+ return console.log(`[Loader] Loaded ${filtered.length}/${files.length} command(s)`), filtered;
594
472
  }
595
473
  /**
596
474
  * Load the file and add the command to the registry.
597
475
  * @param path The path to the command file.
598
476
  * @returns The command object if added successfully.
599
477
  */
600
- async load(path2) {
601
- let command = await Module.import(path2, true);
478
+ async load(path) {
479
+ let command = await importModule(path, true);
602
480
  if (!command) {
603
- console.warn(`[Loader] File has no default export: ${path2}`);
481
+ console.warn(`[Loader] File has no default export: ${path}`);
604
482
  return;
605
483
  }
606
484
  if (!(command instanceof Command)) {
607
- console.warn(`[Loader] Default export is not a Command: ${path2}`);
485
+ console.warn(`[Loader] Default export is not a Command: ${path}`);
608
486
  return;
609
487
  }
610
- return this.add(command), this.entries.set(path2, command), command;
488
+ return this.add(command), this.entries.set(path, command), command;
611
489
  }
612
490
  /**
613
491
  * Unload the file and remove the command from the registry.
614
492
  * @param path The path to the command file.
615
493
  * @returns The command object if unloaded successfully.
616
494
  */
617
- async unload(path2) {
618
- let command = this.entries.get(path2);
619
- if (Module.isLoaded(path2) && (command ??= await Module.import(path2, true), Module.unload(path2)), this.entries.delete(path2), !!command)
495
+ async unload(path) {
496
+ let command = this.entries.get(path);
497
+ if (isModuleLoaded(path) && (command ??= await importModule(path, true), unloadModule(path)), this.entries.delete(path), !!command)
620
498
  return this.remove(command);
621
499
  }
500
+ async reload(path) {
501
+ await this.unload(path);
502
+ let command = await this.load(path);
503
+ if (command)
504
+ return console.log(`[Loader] Reloaded command '${command.options.name}' at '${path}'`), command;
505
+ }
622
506
  /**
623
507
  * Add a command to the registry.
624
508
  * @param command Command to add.
@@ -667,41 +551,57 @@ var ListenerOptionsSchema = z4.object({
667
551
  function defineListener(options) {
668
552
  return new Listener(options);
669
553
  }
554
+
555
+ // src/core/context/Context.ts
556
+ var Context = class {
557
+ canceled = false;
558
+ cancel() {
559
+ this.canceled = true;
560
+ }
561
+ };
562
+
563
+ // src/core/managers/ListenerManager.ts
670
564
  var ListenerManager = class extends BaseClientManager {
671
565
  listeners = [];
672
566
  entries = new Collection();
673
567
  executors = /* @__PURE__ */ new WeakMap();
674
568
  async loadModules(entryDir) {
675
569
  let pattern = posix.join(posix.resolve(entryDir), "listeners", "**/*.{ts,js}"), files = await glob(pattern, { cwd: process.cwd() }), filtered = (await Promise.all(files.map((file) => this.load(file)))).filter((l) => !!l);
676
- return console.log(`[Loader] Loaded ${filtered.length}/${files.length}`), filtered;
570
+ return console.log(`[Loader] Loaded ${filtered.length}/${files.length} listener(s)`), filtered;
677
571
  }
678
572
  /**
679
573
  * Load the file and add the listener to the registry.
680
574
  * @param path The path to the listener file.
681
575
  * @returns The listener object if added successfully.
682
576
  */
683
- async load(path2) {
684
- let listener = await Module.import(path2, true);
577
+ async load(path) {
578
+ let listener = await importModule(path, true);
685
579
  if (!listener) {
686
- console.warn(`[Loader] File has no default export: ${path2}`);
580
+ console.warn(`[Loader] File has no default export: ${path}`);
687
581
  return;
688
582
  }
689
583
  if (!(listener instanceof Listener)) {
690
- console.warn(`[Loader] Default export is not a Listener: ${path2}`);
584
+ console.warn(`[Loader] Default export is not a Listener: ${path}`);
691
585
  return;
692
586
  }
693
- return this.add(listener), this.entries.set(path2, listener), listener;
587
+ return this.add(listener), this.entries.set(path, listener), listener;
694
588
  }
695
589
  /**
696
590
  * Unload the file and remove the listener from the registry.
697
591
  * @param path The path to the listener file.
698
592
  * @returns The listener object if unloaded successfully.
699
593
  */
700
- async unload(path2) {
701
- let listener = this.entries.get(path2);
702
- if (Module.isLoaded(path2) && (listener ??= await Module.import(path2, true), Module.unload(path2)), this.entries.delete(path2), !!listener)
594
+ async unload(path) {
595
+ let listener = this.entries.get(path);
596
+ if (isModuleLoaded(path) && (listener ??= await importModule(path, true), unloadModule(path)), this.entries.delete(path), !!listener)
703
597
  return this.remove(listener)?.[0];
704
598
  }
599
+ async reload(path) {
600
+ await this.unload(path);
601
+ let listener = await this.load(path);
602
+ if (listener)
603
+ return console.log(`[Loader] Reloaded listener '${listener.options.name}' at '${path}'`), listener;
604
+ }
705
605
  /**
706
606
  * Add a listener to the registry and create a listener for client.
707
607
  * @param listener Listener to add.
@@ -750,8 +650,8 @@ var ListenerManager = class extends BaseClientManager {
750
650
  }
751
651
  };
752
652
 
753
- // src/base/client/BakitClient.ts
754
- var BakitClient2 = class extends Client {
653
+ // src/core/client/BakitClient.ts
654
+ var BakitClient = class extends Client {
755
655
  constructor(options, instance) {
756
656
  super(options);
757
657
  this.instance = instance;
@@ -793,73 +693,111 @@ var BakitClient2 = class extends Client {
793
693
  return `${this.constructor.name} {}`;
794
694
  }
795
695
  };
796
-
797
- // src/base/command/param/Params.ts
798
- function createFactory(ctor) {
799
- return (...args) => new ctor(...args);
800
- }
801
- var Params = {
802
- string: createFactory(StringParam),
803
- number: createFactory(NumberParam),
804
- user: createFactory(UserParam)
805
- };
806
- var DevProcessManager = class {
807
- constructor(options) {
808
- this.options = options;
809
- }
810
- child = null;
811
- restartTimer = null;
812
- start() {
813
- console.log("Starting bakit in dev mode..."), this.startChild(), this.startWatcher();
814
- }
815
- startChild() {
816
- if (this.child) return;
817
- let entry = path.resolve(this.options.entry);
818
- this.child = fork(entry, {
819
- execArgv: ["--import", "tsx"],
820
- stdio: "inherit",
821
- env: {
822
- ...process.env,
823
- NODE_ENV: "development"
824
- }
825
- }), this.child.on("exit", () => {
826
- this.child = null;
827
- });
696
+ var BaseCommandContext = class extends Context {
697
+ constructor(source) {
698
+ super();
699
+ this.source = source;
828
700
  }
829
- restartChild() {
830
- if (!this.child)
831
- return this.startChild();
832
- let old = this.child;
833
- old.once("exit", () => {
834
- this.child = null, this.startChild();
835
- }), old.kill("SIGTERM");
836
- }
837
- startWatcher() {
838
- let { rootDir } = this.options;
839
- chokidar.watch(rootDir, {
840
- ignoreInitial: true,
841
- awaitWriteFinish: {
842
- stabilityThreshold: 200,
843
- pollInterval: 50
844
- }
845
- }).on("change", (file) => this.onFileChanged(file));
701
+ get client() {
702
+ return this.source.client;
846
703
  }
847
- onFileChanged(file) {
848
- if (!this.child)
849
- return;
850
- let top = Module.getTopLevel(file, this.options.rootDir);
851
- if (top && this.options.hotDirs.includes(top)) {
852
- this.child.connected && this.child.send({ type: `hmr:${top}`, file });
853
- return;
854
- }
855
- this.scheduleRestart();
704
+ get channel() {
705
+ return this.source.channel;
856
706
  }
857
- scheduleRestart() {
858
- this.restartTimer && clearTimeout(this.restartTimer), this.restartTimer = setTimeout(() => {
859
- console.log("Detected changes, restarting..."), this.restartChild(), this.restartTimer = null;
860
- }, 150);
707
+ get channelId() {
708
+ return this.source.channelId;
709
+ }
710
+ get guild() {
711
+ return this.source.guild;
712
+ }
713
+ get guildId() {
714
+ return this.source.guildId;
715
+ }
716
+ get member() {
717
+ return this.source.member;
718
+ }
719
+ inGuild() {
720
+ return !!this.guildId;
721
+ }
722
+ inCachedGuild() {
723
+ if (this.isChatInput())
724
+ return this.source.inCachedGuild();
725
+ if (this.isMessage())
726
+ return this.source.inGuild();
727
+ throw new Error("Invalid source");
728
+ }
729
+ get user() {
730
+ if (this.isChatInput())
731
+ return this.source.user;
732
+ if (this.isMessage())
733
+ return this.source.author;
734
+ throw new Error("Invalid source");
735
+ }
736
+ isChatInput() {
737
+ return this.source instanceof ChatInputCommandInteraction;
738
+ }
739
+ isMessage() {
740
+ return this.source instanceof Message;
741
+ }
742
+ }, ChatInputContext = class extends BaseCommandContext {
743
+ async send(options) {
744
+ typeof options == "string" && (options = { content: options });
745
+ let sendOptions = {
746
+ ...options,
747
+ withResponse: true
748
+ };
749
+ return this.source.deferred || this.source.replied ? await this.source.followUp(sendOptions) : (await this.source.reply(sendOptions)).resource?.message;
750
+ }
751
+ }, MessageContext = class extends BaseCommandContext {
752
+ async send(options) {
753
+ let { channel } = this;
754
+ if (!channel?.isSendable())
755
+ throw new Error("Invalid channel or channel is not sendable");
756
+ return await channel.send(options);
861
757
  }
862
758
  };
759
+ var ProjectConfigSchema = z4.object({
760
+ /**
761
+ * The gateway intents to use for the Discord client.
762
+ *
763
+ * - `auto` — automatically determine the required intents.
764
+ * - bigint — a raw bitfield value representing the combined intents.
765
+ * - array — a list of individual intent flags from `GatewayIntentBits`.
766
+ *
767
+ * @defaultvalue `auto`
768
+ */
769
+ intents: z4.union([z4.literal("auto"), z4.bigint(), z4.array(z4.enum(GatewayIntentBits))]).default("auto"),
770
+ /**
771
+ * Optional custom client options for Discord.js (excluding `intents`).
772
+ *
773
+ * These are passed directly to the `Client` constructor when initializing the bot.
774
+ *
775
+ * @see {@link https://discord.js.org/docs/packages/discord.js/main/ClientOptions:Interface}
776
+ */
777
+ clientOptions: z4.custom().optional(),
778
+ prefixes: z4.array(z4.string()).default([]),
779
+ token: z4.string()
780
+ });
781
+ var _config;
782
+ async function loadConfig(cwd = process.cwd()) {
783
+ if (_config)
784
+ return console.warn("loadConfig() was called more than once. This shouldn't happen."), _config;
785
+ let globPattern = `bakit.config.{${["ts", "js"].join(",")}}`, [configPath, other] = await glob(globPattern, {
786
+ cwd: cwd.replace(/\\/g, "/"),
787
+ // ensure the path uses `/` instead of `\` on Windows
788
+ absolute: true
789
+ });
790
+ if (!configPath)
791
+ throw new Error("Missing config file");
792
+ other && console.warn(`Multiple config files found in ${cwd}. Using ${configPath}.`);
793
+ let config = await importModule(configPath, true);
794
+ return _config = Object.freeze(await ProjectConfigSchema.parseAsync(config)), _config;
795
+ }
796
+ function getConfig() {
797
+ if (!_config)
798
+ throw new Error("Project config is not loaded.");
799
+ return _config;
800
+ }
863
801
  var messageCommandHandler = defineListener(Events.MessageCreate), chatInputCommandHandler = defineListener(Events.InteractionCreate), registerCommandsHandler = defineListener({
864
802
  name: Events.ClientReady,
865
803
  once: true
@@ -929,14 +867,14 @@ var ProjectCacheManager = class {
929
867
  getHash(data) {
930
868
  return createHash("sha256").update(JSON.stringify(data)).digest("hex");
931
869
  }
932
- async write(path2, data) {
933
- let fullPath = join(this.rootDir, path2), dir = dirname(fullPath);
870
+ async write(path, data) {
871
+ let fullPath = join(this.rootDir, path), dir = dirname(fullPath);
934
872
  await mkdir(dir, { recursive: true });
935
873
  let content = typeof data == "string" ? data : JSON.stringify(data);
936
874
  await writeFile(fullPath, content, "utf-8");
937
875
  }
938
- async read(path2) {
939
- let fullPath = join(this.rootDir, path2);
876
+ async read(path) {
877
+ let fullPath = join(this.rootDir, path);
940
878
  try {
941
879
  let content = await readFile(fullPath, "utf-8");
942
880
  return JSON.parse(content);
@@ -952,7 +890,7 @@ var ProjectCacheManager = class {
952
890
  }
953
891
  };
954
892
 
955
- // src/base/process/Instance.ts
893
+ // src/core/internal/Instance.ts
956
894
  var Instance = class {
957
895
  client;
958
896
  cache;
@@ -962,7 +900,7 @@ var Instance = class {
962
900
  async start() {
963
901
  await loadConfig();
964
902
  let config = getConfig();
965
- this.client = new BakitClient2(
903
+ this.client = new BakitClient(
966
904
  {
967
905
  intents: [],
968
906
  ...config.clientOptions
@@ -989,10 +927,10 @@ var Instance = class {
989
927
  let target = type.split(":")[1], { listeners, commands } = this.client.managers;
990
928
  switch (target) {
991
929
  case "listeners":
992
- listeners.unload(file), await listeners.load(file);
930
+ await listeners.reload(file);
993
931
  break;
994
932
  case "commands":
995
- commands.unload(file), await listeners.load(file);
933
+ await commands.reload(file);
996
934
  break;
997
935
  }
998
936
  }
@@ -1001,4 +939,14 @@ function useApp() {
1001
939
  return new Instance();
1002
940
  }
1003
941
 
1004
- export { ArgumentError, BakitClient2 as BakitClient, BakitError, BaseClientManager, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Context, DevProcessManager, EVENT_INTENT_MAPPING, HookOrder, HookState, Instance, LifecycleManager, Listener, ListenerManager, ListenerOptionsSchema, MessageContext, Module, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectCacheManager, ProjectConfigSchema, StringParam, StringParamSchema, UserParam, UserParamSchema, defineCommand, defineConfig, defineListener, extractSnowflakeId, getConfig, loadConfig, tokenize, useApp, validateParamsOrder };
942
+ // src/core/structures/param/Params.ts
943
+ function createFactory(ctor) {
944
+ return (...args) => new ctor(...args);
945
+ }
946
+ var Params = {
947
+ string: createFactory(StringParam),
948
+ number: createFactory(NumberParam),
949
+ user: createFactory(UserParam)
950
+ };
951
+
952
+ export { ArgumentError, BakitClient, BakitError, BaseClientManager, BaseCommandContext, BaseParam, BaseParamSchema, ChatInputContext, Command, CommandManager, CommandOptionsSchema, Context, EVENT_INTENT_MAPPING, HookOrder, HookState, Instance, LifecycleManager, Listener, ListenerManager, ListenerOptionsSchema, MessageContext, NumberParam, NumberParamSchema, ParamUserType, Params, ProjectCacheManager, StringParam, StringParamSchema, UserParam, UserParamSchema, chatInputCommandHandler, defineCommand, defineListener, extractSnowflakeId, getTopLevelDirectory, importModule, isModuleLoaded, messageCommandHandler, registerCommandsHandler, tokenize, unloadModule, useApp, validateParamsOrder };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bakit",
3
- "version": "2.0.0-alpha.14",
3
+ "version": "2.0.0-alpha.16",
4
4
  "description": "A framework for discord.js",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -11,7 +11,7 @@
11
11
  "test": "vitest run --pass-with-no-tests"
12
12
  },
13
13
  "bin": {
14
- "bakit": "./dist/bin/bakit.js"
14
+ "bakit": "./dist/cli.js"
15
15
  },
16
16
  "files": [
17
17
  "dist"
@@ -41,7 +41,6 @@
41
41
  "commander": "^14.0.2",
42
42
  "dotenv": "^17.2.1",
43
43
  "jiti": "^2.6.1",
44
- "nodemon": "^3.1.11",
45
44
  "tiny-glob": "^0.2.9",
46
45
  "type-fest": "^4.41.0",
47
46
  "zod": "^4.1.12"