commandkit 0.1.11-dev.20250306152436 → 0.1.11-dev.20250307192025

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/index.js CHANGED
@@ -1011,81 +1011,6 @@ var init_components = __esm({
1011
1011
  }
1012
1012
  });
1013
1013
 
1014
- // src/app/i18n/DefaultLocalizationStrategy.ts
1015
- var import_promises, import_node_path, _DefaultLocalizationStrategy, DefaultLocalizationStrategy;
1016
- var init_DefaultLocalizationStrategy = __esm({
1017
- "src/app/i18n/DefaultLocalizationStrategy.ts"() {
1018
- "use strict";
1019
- init_cjs_shims();
1020
- import_promises = require("fs/promises");
1021
- import_node_path = require("path");
1022
- _DefaultLocalizationStrategy = class _DefaultLocalizationStrategy {
1023
- constructor(commandkit) {
1024
- this.commandkit = commandkit;
1025
- }
1026
- translations = /* @__PURE__ */ new Map();
1027
- async locateTranslation(scope, locale) {
1028
- const localesPath = this.commandkit.getPath("locales");
1029
- if (!localesPath) return null;
1030
- const path3 = (0, import_node_path.join)(localesPath, locale, `${scope}.json`);
1031
- try {
1032
- const data = await (0, import_promises.readFile)(path3, "utf-8");
1033
- return JSON.parse(data);
1034
- } catch {
1035
- return null;
1036
- }
1037
- }
1038
- async getTranslationStrict(scope, locale) {
1039
- const key = `${scope}:${locale}`;
1040
- if (!this.translations.has(key)) {
1041
- const translation = await this.locateTranslation(scope, locale);
1042
- if (!translation) {
1043
- throw new Error(`Translation not found for ${key}`);
1044
- }
1045
- this.translations.set(key, translation);
1046
- return translation;
1047
- }
1048
- return this.translations.get(key);
1049
- }
1050
- async getTranslation(scope, locale) {
1051
- try {
1052
- return this.getTranslationStrict(scope, locale);
1053
- } catch (e) {
1054
- return null;
1055
- }
1056
- }
1057
- async translate(request) {
1058
- const { scope, key, args, locale } = request;
1059
- const translation = await this.getTranslation(scope, locale);
1060
- if (!translation) return `${scope}.${key}`;
1061
- const value = translation.translations[key];
1062
- const translated = this.applyTranslation(value, args);
1063
- return translated || `${scope}.${key}`;
1064
- }
1065
- applyTranslation(translation, args) {
1066
- if (!translation || !args) return translation;
1067
- return translation.replace(/{([^}]+)}/g, (_, key) => {
1068
- return String(args[key] ?? `{${key}}`);
1069
- });
1070
- }
1071
- };
1072
- __name(_DefaultLocalizationStrategy, "DefaultLocalizationStrategy");
1073
- DefaultLocalizationStrategy = _DefaultLocalizationStrategy;
1074
- }
1075
- });
1076
-
1077
- // src/utils/constants.ts
1078
- var COMMANDKIT_CACHE_TAG, COMMANDKIT_IS_DEV, COMMANDKIT_IS_TEST;
1079
- var init_constants = __esm({
1080
- "src/utils/constants.ts"() {
1081
- "use strict";
1082
- init_cjs_shims();
1083
- COMMANDKIT_CACHE_TAG = Symbol("kCommandKitCacheTag");
1084
- COMMANDKIT_IS_DEV = !!process.env.COMMANDKIT_IS_DEV;
1085
- COMMANDKIT_IS_TEST = process.env.COMMANDKIT_IS_TEST === "true";
1086
- }
1087
- });
1088
-
1089
1014
  // src/plugins/PluginCommon.ts
1090
1015
  var _PluginCommon, PluginCommon;
1091
1016
  var init_PluginCommon = __esm({
@@ -1157,11 +1082,83 @@ var init_CompilerPlugin = __esm({
1157
1082
  });
1158
1083
 
1159
1084
  // src/plugins/RuntimePlugin.ts
1085
+ function isRuntimePlugin(plugin) {
1086
+ return plugin instanceof RuntimePlugin;
1087
+ }
1088
+ var _RuntimePlugin, RuntimePlugin;
1160
1089
  var init_RuntimePlugin = __esm({
1161
1090
  "src/plugins/RuntimePlugin.ts"() {
1162
1091
  "use strict";
1163
1092
  init_cjs_shims();
1164
1093
  init_PluginCommon();
1094
+ _RuntimePlugin = class _RuntimePlugin extends PluginCommon {
1095
+ /**
1096
+ * Called before commands are loaded
1097
+ */
1098
+ async onBeforeCommandsLoad(ctx) {
1099
+ }
1100
+ /**
1101
+ * Called after commands are loaded
1102
+ */
1103
+ async onAfterCommandsLoad(ctx) {
1104
+ }
1105
+ /**
1106
+ * Called before events are loaded
1107
+ */
1108
+ async onBeforeEventsLoad(ctx) {
1109
+ }
1110
+ /**
1111
+ * Called after events are loaded
1112
+ */
1113
+ async onAfterEventsLoad(ctx) {
1114
+ }
1115
+ /**
1116
+ * Called before the client logs in
1117
+ */
1118
+ async onBeforeClientLogin(ctx) {
1119
+ }
1120
+ /**
1121
+ * Called after the client logs in
1122
+ */
1123
+ async onAfterClientLogin(ctx) {
1124
+ }
1125
+ /**
1126
+ * Called before interaction is handled
1127
+ * @param interaction The interaction
1128
+ */
1129
+ async onBeforeInteraction(ctx, interaction) {
1130
+ }
1131
+ /**
1132
+ * Called after interaction is handled
1133
+ * @param interaction The interaction that was handled
1134
+ */
1135
+ async onAfterInteraction(ctx, interaction) {
1136
+ }
1137
+ /**
1138
+ * Called before message command is processed
1139
+ * @param message The message
1140
+ */
1141
+ async onBeforeMessageCommand(ctx, message) {
1142
+ }
1143
+ /**
1144
+ * Called before message update command is processed
1145
+ * @param message The message
1146
+ */
1147
+ async onBeforeMessageUpdateCommand(ctx, oldMessage, newMessage) {
1148
+ }
1149
+ /**
1150
+ * Called before command is executed. This method can execute the command itself.
1151
+ * @param source The source that triggered the command
1152
+ * @param command The command
1153
+ * @param execute The function that executes the command
1154
+ */
1155
+ async executeCommand(ctx, source, command, execute) {
1156
+ return false;
1157
+ }
1158
+ };
1159
+ __name(_RuntimePlugin, "RuntimePlugin");
1160
+ RuntimePlugin = _RuntimePlugin;
1161
+ __name(isRuntimePlugin, "isRuntimePlugin");
1165
1162
  }
1166
1163
  });
1167
1164
 
@@ -1386,6 +1383,18 @@ var init_CommandKitPluginRuntime = __esm({
1386
1383
  getPlugin(pluginName) {
1387
1384
  return this.plugins.get(pluginName) ?? null;
1388
1385
  }
1386
+ async softRegisterPlugin(plugin) {
1387
+ const pluginName = plugin.name;
1388
+ if (this.plugins.has(pluginName)) return;
1389
+ try {
1390
+ await plugin.activate(this);
1391
+ this.plugins.set(pluginName, plugin);
1392
+ } catch (e) {
1393
+ throw new Error(
1394
+ `Failed to activate plugin "${pluginName}": ${(e == null ? void 0 : e.stack) || e}`
1395
+ );
1396
+ }
1397
+ }
1389
1398
  async registerPlugin(plugin) {
1390
1399
  const pluginName = plugin.name;
1391
1400
  if (this.plugins.has(pluginName)) {
@@ -1467,12 +1476,12 @@ function fromEsbuildPlugin(plugin) {
1467
1476
  let EsbuildPluginCompat = _EsbuildPluginCompat;
1468
1477
  return EsbuildPluginCompat;
1469
1478
  }
1470
- var import_promises2, pattern, _CompilerPluginRuntime, CompilerPluginRuntime;
1479
+ var import_promises, pattern, _CompilerPluginRuntime, CompilerPluginRuntime;
1471
1480
  var init_CompilerPluginRuntime = __esm({
1472
1481
  "src/plugins/runtime/CompilerPluginRuntime.ts"() {
1473
1482
  "use strict";
1474
1483
  init_cjs_shims();
1475
- import_promises2 = require("fs/promises");
1484
+ import_promises = require("fs/promises");
1476
1485
  init_plugins();
1477
1486
  pattern = /\.(c|m)?(t|j)sx?$/;
1478
1487
  _CompilerPluginRuntime = class _CompilerPluginRuntime {
@@ -1485,7 +1494,7 @@ var init_CompilerPluginRuntime = __esm({
1485
1494
  }
1486
1495
  async onLoad(args) {
1487
1496
  var _a;
1488
- const source = await (0, import_promises2.readFile)(args.path, "utf8");
1497
+ const source = await (0, import_promises.readFile)(args.path, "utf8");
1489
1498
  let contents = source, loader = args.path.split(".").pop();
1490
1499
  for (const plugin of this.plugins) {
1491
1500
  try {
@@ -1956,6 +1965,134 @@ var init_config = __esm({
1956
1965
  }
1957
1966
  });
1958
1967
 
1968
+ // src/app/i18n/DefaultLocalizationStrategy.ts
1969
+ var import_promises2, import_node_path, import_node_fs, _DefaultLocalizationStrategy, DefaultLocalizationStrategy;
1970
+ var init_DefaultLocalizationStrategy = __esm({
1971
+ "src/app/i18n/DefaultLocalizationStrategy.ts"() {
1972
+ "use strict";
1973
+ init_cjs_shims();
1974
+ import_promises2 = require("fs/promises");
1975
+ import_node_path = require("path");
1976
+ init_config();
1977
+ import_node_fs = require("fs");
1978
+ _DefaultLocalizationStrategy = class _DefaultLocalizationStrategy {
1979
+ constructor(commandkit) {
1980
+ this.commandkit = commandkit;
1981
+ }
1982
+ translations = /* @__PURE__ */ new Map();
1983
+ async locateTranslation(scope, locale) {
1984
+ const localesPath = this.commandkit.getPath("locales");
1985
+ if (!localesPath) return null;
1986
+ const path3 = (0, import_node_path.join)(localesPath, locale, `${scope}.json`);
1987
+ try {
1988
+ const data = await (0, import_promises2.readFile)(path3, "utf-8");
1989
+ const localeData = JSON.parse(data);
1990
+ await this.generateLocaleTypes(localeData);
1991
+ return localeData;
1992
+ } catch {
1993
+ return null;
1994
+ }
1995
+ }
1996
+ async generateLocaleTypes(localeData) {
1997
+ const { typedLocales } = getConfig();
1998
+ if (!typedLocales) return;
1999
+ const file = (0, import_node_path.join)(
2000
+ process.cwd(),
2001
+ "node_modules",
2002
+ "commandkit-types",
2003
+ "locale_types.d.ts"
2004
+ );
2005
+ const header = `// auto generated file do not edit
2006
+ declare module 'commandkit' {
2007
+ export interface CommandLocalizationTypeData {
2008
+ `;
2009
+ const footer = ` }
2010
+ }`;
2011
+ const generateType = /* @__PURE__ */ __name((locale) => {
2012
+ return `"${locale.command}": ${JSON.stringify(
2013
+ Object.entries(locale.translations).map(([key, value]) => {
2014
+ const args = value.match(/{([^}]+)}/g);
2015
+ if (!args) return `${JSON.stringify(key)}: null`;
2016
+ return `${JSON.stringify(key)}: ${args.map((arg) => arg.slice(1, -1)).join(" | ")}`;
2017
+ }),
2018
+ null,
2019
+ 2
2020
+ )}`;
2021
+ }, "generateType");
2022
+ if (!(0, import_node_fs.existsSync)(file)) {
2023
+ const generated = generateType(localeData);
2024
+ await (0, import_promises2.writeFile)(file, `${header}${generated}${footer}`);
2025
+ } else {
2026
+ const data = await (0, import_promises2.readFile)(file, "utf-8");
2027
+ const lines = data.split("\n");
2028
+ const index = lines.findIndex(
2029
+ (line) => line.includes("CommandLocalizationTypeData")
2030
+ );
2031
+ if (index === -1) {
2032
+ for (const locale of this.translations.values()) {
2033
+ const generated2 = generateType(locale);
2034
+ await (0, import_promises2.writeFile)(file, `${header}${generated2}${footer}`);
2035
+ }
2036
+ return;
2037
+ }
2038
+ const start = index + 2;
2039
+ const end = lines.findIndex((line) => line.includes("}"));
2040
+ const generated = generateType(localeData);
2041
+ lines.splice(start, end - start, generated);
2042
+ await (0, import_promises2.writeFile)(file, lines.join("\n"));
2043
+ }
2044
+ }
2045
+ async getTranslationStrict(scope, locale) {
2046
+ const key = `${scope}:${locale}`;
2047
+ if (!this.translations.has(key)) {
2048
+ const translation = await this.locateTranslation(scope, locale);
2049
+ if (!translation) {
2050
+ throw new Error(`Translation not found for ${key}`);
2051
+ }
2052
+ this.translations.set(key, translation);
2053
+ return translation;
2054
+ }
2055
+ return this.translations.get(key);
2056
+ }
2057
+ async getTranslation(scope, locale) {
2058
+ try {
2059
+ return this.getTranslationStrict(scope, locale);
2060
+ } catch (e) {
2061
+ return null;
2062
+ }
2063
+ }
2064
+ async translate(request) {
2065
+ const { scope, key, args, locale } = request;
2066
+ const translation = await this.getTranslation(scope, locale);
2067
+ if (!translation) return `${scope}.${key}`;
2068
+ const value = translation.translations[key];
2069
+ const translated = this.applyTranslation(value, args);
2070
+ return translated || `${scope}.${key}`;
2071
+ }
2072
+ applyTranslation(translation, args) {
2073
+ if (!translation || !args) return translation;
2074
+ return translation.replace(/{([^}]+)}/g, (_, key) => {
2075
+ return String(args[key] ?? `{${key}}`);
2076
+ });
2077
+ }
2078
+ };
2079
+ __name(_DefaultLocalizationStrategy, "DefaultLocalizationStrategy");
2080
+ DefaultLocalizationStrategy = _DefaultLocalizationStrategy;
2081
+ }
2082
+ });
2083
+
2084
+ // src/utils/constants.ts
2085
+ var COMMANDKIT_CACHE_TAG, COMMANDKIT_IS_DEV, COMMANDKIT_IS_TEST;
2086
+ var init_constants = __esm({
2087
+ "src/utils/constants.ts"() {
2088
+ "use strict";
2089
+ init_cjs_shims();
2090
+ COMMANDKIT_CACHE_TAG = Symbol("kCommandKitCacheTag");
2091
+ COMMANDKIT_IS_DEV = !!process.env.COMMANDKIT_IS_DEV;
2092
+ COMMANDKIT_IS_TEST = process.env.COMMANDKIT_IS_TEST === "true";
2093
+ }
2094
+ });
2095
+
1959
2096
  // src/utils/utilities.ts
1960
2097
  function findAppDirectory() {
1961
2098
  if (appDir) return appDir;
@@ -1963,10 +2100,10 @@ function findAppDirectory() {
1963
2100
  process.cwd(),
1964
2101
  COMMANDKIT_IS_DEV ? ".commandkit" : getConfig().distDir
1965
2102
  );
1966
- if (!(0, import_node_fs.existsSync)(root)) root = process.cwd();
2103
+ if (!(0, import_node_fs2.existsSync)(root)) root = process.cwd();
1967
2104
  const dirs = ["app"].map((dir) => (0, import_node_path2.join)(root, dir));
1968
2105
  for (const dir of dirs) {
1969
- if ((0, import_node_fs.existsSync)(dir)) {
2106
+ if ((0, import_node_fs2.existsSync)(dir)) {
1970
2107
  appDir = dir;
1971
2108
  return dir;
1972
2109
  }
@@ -1994,12 +2131,12 @@ function debounce(fn, ms2) {
1994
2131
  });
1995
2132
  };
1996
2133
  }
1997
- var import_node_fs, import_node_path2, appDir;
2134
+ var import_node_fs2, import_node_path2, appDir;
1998
2135
  var init_utilities = __esm({
1999
2136
  "src/utils/utilities.ts"() {
2000
2137
  "use strict";
2001
2138
  init_cjs_shims();
2002
- import_node_fs = require("fs");
2139
+ import_node_fs2 = require("fs");
2003
2140
  import_node_path2 = require("path");
2004
2141
  init_constants();
2005
2142
  init_config();
@@ -3635,256 +3772,243 @@ var init_AppCommandHandler = __esm({
3635
3772
  });
3636
3773
 
3637
3774
  // src/app/router/CommandsRouter.ts
3638
- var import_discord11, import_node_fs2, import_promises3, import_node_path3, import_node_crypto3, _CommandsRouter, CommandsRouter;
3775
+ var import_discord11, import_node_fs3, import_promises3, import_posix, _CommandsRouter, CommandsRouter;
3639
3776
  var init_CommandsRouter = __esm({
3640
3777
  "src/app/router/CommandsRouter.ts"() {
3641
3778
  "use strict";
3642
3779
  init_cjs_shims();
3643
3780
  import_discord11 = require("discord.js");
3644
- import_node_fs2 = require("fs");
3781
+ import_node_fs3 = require("fs");
3645
3782
  import_promises3 = require("fs/promises");
3646
- import_node_path3 = __toESM(require("path"));
3647
- import_node_crypto3 = require("crypto");
3783
+ import_posix = __toESM(require("path/posix"));
3648
3784
  _CommandsRouter = class _CommandsRouter {
3649
3785
  constructor(options) {
3650
3786
  this.options = options;
3651
3787
  }
3652
3788
  commands = new import_discord11.Collection();
3653
- subcommands = new import_discord11.Collection();
3654
3789
  middlewares = new import_discord11.Collection();
3790
+ subcommands = new import_discord11.Collection();
3791
+ isValidPath() {
3792
+ return (0, import_node_fs3.existsSync)(this.entrypoint);
3793
+ }
3655
3794
  get entrypoint() {
3656
3795
  return this.options.entrypoint;
3657
3796
  }
3658
- isValidPath() {
3659
- return (0, import_node_fs2.existsSync)(this.entrypoint);
3797
+ clear() {
3798
+ this.commands.clear();
3799
+ this.middlewares.clear();
3800
+ this.subcommands.clear();
3801
+ }
3802
+ async reload() {
3803
+ this.clear();
3804
+ return this.scan();
3805
+ }
3806
+ visualize() {
3807
+ let output = "";
3808
+ const commands = [...this.commands.values()];
3809
+ commands.forEach((command, index) => {
3810
+ const isLast = index === commands.length - 1;
3811
+ const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
3812
+ const childPrefix = isLast ? " " : "\u2502 ";
3813
+ const categoryPrefix = command.category ? `[${command.category}] ` : "";
3814
+ output += `${prefix} ${categoryPrefix}${command.name}
3815
+ `;
3816
+ const subcommands = command.subcommands.map((id) => this.subcommands.get(id)).filter(Boolean);
3817
+ const groupedSubs = /* @__PURE__ */ new Map();
3818
+ subcommands.forEach((sub) => {
3819
+ if (!groupedSubs.has(sub.group)) {
3820
+ groupedSubs.set(sub.group, []);
3821
+ }
3822
+ groupedSubs.get(sub.group).push(sub);
3823
+ });
3824
+ const groups = [...groupedSubs.entries()];
3825
+ groups.forEach(([group, subs], groupIndex) => {
3826
+ const isLastGroup = groupIndex === groups.length - 1;
3827
+ if (group) {
3828
+ const groupPrefix = isLastGroup ? `${childPrefix}\u2514\u2500` : `${childPrefix}\u251C\u2500`;
3829
+ output += `${groupPrefix} Group: ${group}
3830
+ `;
3831
+ }
3832
+ const subPrefix = group ? `${childPrefix}${isLastGroup ? " " : "\u2502 "}` : childPrefix;
3833
+ subs.forEach((subcommand, subIndex) => {
3834
+ const isLastSub = subIndex === subs.length - 1;
3835
+ const subCommandPrefix = isLastSub ? `${subPrefix}\u2514\u2500` : `${subPrefix}\u251C\u2500`;
3836
+ output += `${subCommandPrefix} ${subcommand.name}
3837
+ `;
3838
+ const middlewares = subcommand.middlewares.map((id) => this.middlewares.get(id)).filter(Boolean);
3839
+ middlewares.forEach((middleware, mwIndex) => {
3840
+ const isLastMw = mwIndex === middlewares.length - 1;
3841
+ const mwPrefix = isLastMw ? `${subPrefix}${isLastSub ? " " : "\u2502 "}\u2514\u2500` : `${subPrefix}${isLastSub ? " " : "\u2502 "}\u251C\u2500`;
3842
+ output += `${mwPrefix} \u2699\uFE0F ${middleware.name}
3843
+ `;
3844
+ });
3845
+ });
3846
+ });
3847
+ const commandMiddlewares = command.middlewares.map((id) => this.middlewares.get(id)).filter(Boolean);
3848
+ if (commandMiddlewares.length > 0) {
3849
+ output += `${childPrefix}\u2514\u2500 Middlewares:
3850
+ `;
3851
+ commandMiddlewares.forEach((middleware, mwIndex) => {
3852
+ const isLastMw = mwIndex === commandMiddlewares.length - 1;
3853
+ const mwPrefix = isLastMw ? `${childPrefix} \u2514\u2500` : `${childPrefix} \u251C\u2500`;
3854
+ output += `${mwPrefix} \u2699\uFE0F ${middleware.name}
3855
+ `;
3856
+ });
3857
+ }
3858
+ output += "\n";
3859
+ });
3860
+ return output;
3660
3861
  }
3661
3862
  getData() {
3662
3863
  return {
3663
3864
  commands: this.commands,
3664
- subcommands: this.subcommands,
3665
- middlewares: this.middlewares
3865
+ middlewares: this.middlewares,
3866
+ subcommands: this.subcommands
3666
3867
  };
3667
3868
  }
3668
3869
  toJSON() {
3669
3870
  return {
3670
3871
  commands: Object.fromEntries(this.commands.entries()),
3671
- subcommands: Object.fromEntries(this.subcommands.entries()),
3672
- middlewares: Object.fromEntries(this.middlewares.entries())
3872
+ middlewares: Object.fromEntries(this.middlewares.entries()),
3873
+ subcommands: Object.fromEntries(this.subcommands.entries())
3673
3874
  };
3674
3875
  }
3675
- clear() {
3676
- this.commands.clear();
3677
- this.subcommands.clear();
3678
- this.middlewares.clear();
3679
- }
3680
- async reload() {
3681
- this.clear();
3682
- return this.scan();
3683
- }
3684
3876
  async scan() {
3685
- await this.scanDirectory(this.entrypoint);
3877
+ if (!this.isValidPath()) return this.toJSON();
3878
+ const root = this.entrypoint;
3879
+ await this.scanDeep(root);
3686
3880
  return this.toJSON();
3687
3881
  }
3688
- async scanDirectory(dir, parentPath = "", categories = []) {
3689
- const entries = await (0, import_promises3.readdir)(dir);
3690
- const directoryStats = /* @__PURE__ */ new Map();
3691
- for (const entry of entries) {
3692
- if (entry.startsWith("_")) continue;
3693
- const fullPath = import_node_path3.default.join(dir, entry);
3694
- const stats = await (0, import_promises3.stat)(fullPath);
3695
- directoryStats.set(entry, stats.isDirectory());
3696
- }
3697
- await this.processMiddlewares(dir, entries, parentPath, categories);
3698
- for (const entry of entries) {
3699
- if (entry.startsWith("_")) continue;
3700
- if (entry.includes(".middleware.")) continue;
3701
- const fullPath = import_node_path3.default.join(dir, entry);
3702
- const isDirectory = directoryStats.get(entry) || false;
3703
- if (isDirectory) {
3704
- const { name, parsedCategories } = this.parseNameAndCategory(entry);
3705
- const newCategories = [...categories, ...parsedCategories];
3706
- const isCategoryContainer = /^\([^)]+\)$/.test(entry);
3707
- if (isCategoryContainer) {
3708
- await this.scanDirectory(fullPath, parentPath, newCategories);
3709
- } else {
3710
- const newParentPath = parentPath ? `${parentPath}/${name}` : name;
3711
- await this.processCommandDirectory(
3712
- fullPath,
3713
- name,
3714
- newParentPath,
3715
- newCategories
3716
- );
3882
+ async scanDeep(entry, currentDepth = 2) {
3883
+ const normalizedPath = import_posix.default.normalize(entry);
3884
+ const content = await (0, import_promises3.readdir)(normalizedPath, { withFileTypes: true });
3885
+ for (const item of content) {
3886
+ const itemPath = import_posix.default.join(normalizedPath, item.name);
3887
+ if (this.shouldIgnore(itemPath, item.isDirectory())) continue;
3888
+ if (item.isDirectory()) {
3889
+ const isCategoryDir = this.isCategoryDirectory(item.name);
3890
+ if (currentDepth > 0 || isCategoryDir) {
3891
+ const nextDepth = isCategoryDir ? currentDepth : currentDepth - 1;
3892
+ await this.scanDeep(itemPath, nextDepth);
3717
3893
  }
3718
3894
  } else {
3719
- if (!/\.(m|c)?(j|t)sx?$/.test(entry)) {
3720
- continue;
3721
- }
3722
- const extname = import_node_path3.default.extname(entry);
3723
- const basename = import_node_path3.default.basename(entry, extname);
3724
- if (basename === "index") {
3725
- continue;
3726
- }
3727
- const { name, parsedCategories } = this.parseNameAndCategory(basename);
3728
- const newCategories = [...categories, ...parsedCategories];
3729
- if (parentPath) {
3730
- await this.processSubCommand(
3731
- fullPath,
3732
- name,
3733
- parentPath,
3734
- newCategories
3895
+ const isInnerSubCommand = currentDepth === 0;
3896
+ const isSubCommandGroup = currentDepth === 1;
3897
+ const category = this.extractCategory(itemPath);
3898
+ const fileName = this.extractName(itemPath);
3899
+ const isIndexFile = fileName === "index" && normalizedPath !== this.entrypoint;
3900
+ if (this.isMiddleware(itemPath)) {
3901
+ this.processMiddleware(itemPath, category);
3902
+ } else if (isInnerSubCommand || isSubCommandGroup) {
3903
+ this.processSubcommand(
3904
+ itemPath,
3905
+ import_posix.default.basename(normalizedPath),
3906
+ isSubCommandGroup,
3907
+ isIndexFile
3735
3908
  );
3736
3909
  } else {
3737
- await this.processCommand(fullPath, name, newCategories);
3910
+ this.processCommand(
3911
+ itemPath,
3912
+ category,
3913
+ isIndexFile ? normalizedPath : null
3914
+ );
3738
3915
  }
3739
3916
  }
3740
3917
  }
3741
3918
  }
3742
- async processMiddlewares(dir, entries, parentPath, categories) {
3743
- for (const entry of entries) {
3744
- if (entry.startsWith("_")) continue;
3745
- if (!entry.includes(".middleware.")) continue;
3746
- const fullPath = import_node_path3.default.join(dir, entry);
3747
- const stats = await (0, import_promises3.stat)(fullPath);
3748
- if (stats.isDirectory()) continue;
3749
- if (!/\.(m|c)?(j|t)sx?$/.test(entry)) {
3750
- continue;
3751
- }
3752
- const extname = import_node_path3.default.extname(entry);
3753
- const basename = import_node_path3.default.basename(entry, extname);
3754
- const middlewareSegments = basename.split(".middleware");
3755
- const middlewareName = middlewareSegments[0];
3756
- const { name, parsedCategories } = this.parseNameAndCategory(middlewareName);
3757
- const newCategories = [...categories, ...parsedCategories];
3758
- const category = newCategories.length ? newCategories.join(":") : null;
3759
- const middleware = {
3760
- name,
3761
- id: (0, import_node_crypto3.randomUUID)(),
3762
- // Using randomUUID for unique ID generation
3763
- path: fullPath,
3764
- category
3765
- };
3766
- this.middlewares.set(middleware.id, middleware);
3767
- }
3919
+ processMiddleware(filePath, category) {
3920
+ const middleware = {
3921
+ id: crypto.randomUUID(),
3922
+ name: this.getAppropriateFileName(filePath),
3923
+ path: filePath,
3924
+ relativePath: this.getRelativePath(filePath),
3925
+ category
3926
+ };
3927
+ this.middlewares.set(middleware.id, middleware);
3928
+ this.applyMiddlewareToCommands(middleware);
3768
3929
  }
3769
- async processCommand(filePath, name, categories) {
3770
- const category = categories.length ? categories.join(":") : null;
3771
- const id = (0, import_node_crypto3.randomUUID)();
3772
- const middlewares = this.findAssociatedMiddlewares(name, category);
3773
- const command = {
3774
- id,
3775
- name,
3930
+ processSubcommand(filePath, parentDirName, isGrouped, isIndexFile = false) {
3931
+ const subcommand = {
3932
+ id: crypto.randomUUID(),
3933
+ name: isIndexFile ? this.getDirectoryName(filePath) : this.extractName(filePath),
3934
+ group: isGrouped ? parentDirName : null,
3935
+ middlewares: [],
3776
3936
  path: filePath,
3777
- category,
3778
- subcommands: [],
3779
- middlewares
3937
+ relativePath: this.getRelativePath(filePath)
3780
3938
  };
3781
- this.commands.set(id, command);
3782
- }
3783
- async processCommandDirectory(dirPath, name, parentPath, categories) {
3784
- const category = categories.length ? categories.join(":") : null;
3785
- const id = (0, import_node_crypto3.randomUUID)();
3786
- let indexFile = null;
3787
- const possibleExtensions = [
3788
- ".js",
3789
- ".ts",
3790
- ".jsx",
3791
- ".tsx",
3792
- ".mjs",
3793
- ".cjs",
3794
- ".mts",
3795
- ".cts"
3796
- ];
3797
- for (const ext of possibleExtensions) {
3798
- const testPath = import_node_path3.default.join(dirPath, `index${ext}`);
3799
- if ((0, import_node_fs2.existsSync)(testPath)) {
3800
- indexFile = testPath;
3801
- break;
3802
- }
3803
- }
3804
- const middlewares = this.findAssociatedMiddlewares(name, category);
3805
- const entries = await (0, import_promises3.readdir)(dirPath);
3806
- const subcommands = [];
3807
- for (const entry of entries) {
3808
- if (entry.startsWith("_") || entry.startsWith("index.")) continue;
3809
- const fullPath = import_node_path3.default.join(dirPath, entry);
3810
- const stats = await (0, import_promises3.stat)(fullPath);
3811
- const isDirectory = stats.isDirectory();
3812
- if (!isDirectory && !/\.(m|c)?(j|t)sx?$/.test(entry)) {
3813
- continue;
3814
- }
3815
- if (!isDirectory || isDirectory && !entry.includes(".")) {
3816
- const extname = isDirectory ? "" : import_node_path3.default.extname(entry);
3817
- const baseName = isDirectory ? entry : import_node_path3.default.basename(entry, extname);
3818
- if (!baseName.includes(".middleware")) {
3819
- const { name: subName } = this.parseNameAndCategory(baseName);
3820
- subcommands.push(subName);
3821
- }
3822
- }
3823
- }
3939
+ this.subcommands.set(subcommand.id, subcommand);
3940
+ this.applySubcommandToCommands(subcommand);
3941
+ }
3942
+ processCommand(filePath, category, parentPath = null) {
3824
3943
  const command = {
3825
- id,
3826
- name,
3827
- path: indexFile,
3828
- // This can be null if no index file exists
3944
+ id: crypto.randomUUID(),
3945
+ name: parentPath ? this.getDirectoryName(parentPath) : this.extractName(filePath),
3946
+ path: filePath,
3947
+ relativePath: this.getRelativePath(filePath),
3829
3948
  category,
3830
- subcommands,
3831
- middlewares
3949
+ middlewares: [],
3950
+ subcommands: []
3832
3951
  };
3833
- this.commands.set(id, command);
3834
- await this.scanDirectory(dirPath, id, categories);
3952
+ this.commands.set(command.id, command);
3835
3953
  }
3836
- async processSubCommand(filePath, name, parentPath, categories) {
3837
- if (!/\.(m|c)?(j|t)sx?$/.test(filePath)) {
3838
- return;
3954
+ /**
3955
+ * Gets the appropriate file name, handling index files specially
3956
+ * For index files, it returns the parent directory name (excluding category markers)
3957
+ */
3958
+ getAppropriateFileName(filePath) {
3959
+ const fileName = this.extractName(filePath);
3960
+ if (fileName === "index" && import_posix.default.dirname(filePath) !== this.entrypoint) {
3961
+ return this.getDirectoryName(filePath);
3839
3962
  }
3840
- const pathSegments = parentPath.split("/");
3841
- let group = null;
3842
- if (pathSegments.length > 1) {
3843
- group = pathSegments[1];
3963
+ return fileName;
3964
+ }
3965
+ /**
3966
+ * Extract the clean directory name, removing any category markers
3967
+ */
3968
+ getDirectoryName(filePath) {
3969
+ const dirName = import_posix.default.basename(import_posix.default.dirname(filePath));
3970
+ return dirName.replace(/^\((\w+)\)$/, "$1");
3971
+ }
3972
+ // Helper method to identify category directories
3973
+ isCategoryDirectory(dirName) {
3974
+ return /^\(\w+\)$/.test(dirName);
3975
+ }
3976
+ applyMiddlewareToCommands(middleware) {
3977
+ for (const command of this.commands.values()) {
3978
+ const middlewareFileName = import_posix.default.basename(middleware.path);
3979
+ const match = middlewareFileName.startsWith(command.name) || middlewareFileName === "middleware";
3980
+ if (!match) continue;
3981
+ if (command.middlewares.includes(middleware.id)) continue;
3982
+ command.middlewares.push(middleware.id);
3844
3983
  }
3845
- const category = categories.length ? categories.join(":") : null;
3846
- const id = (0, import_node_crypto3.randomUUID)();
3847
- const middlewares = this.findAssociatedMiddlewares(name, category);
3848
- const subcommand = {
3849
- id,
3850
- name,
3851
- path: filePath,
3852
- category,
3853
- group,
3854
- middlewares
3855
- };
3856
- this.subcommands.set(id, subcommand);
3857
- }
3858
- parseNameAndCategory(name) {
3859
- const parsedCategories = [];
3860
- const regex = /\(([^)]+)\)/g;
3861
- let match;
3862
- let cleanName = name;
3863
- while ((match = regex.exec(name)) !== null) {
3864
- parsedCategories.push(match[1]);
3865
- cleanName = cleanName.replace(match[0], "");
3984
+ }
3985
+ applySubcommandToCommands(subcommand) {
3986
+ for (const command of this.commands.values()) {
3987
+ if (!subcommand.path.startsWith(command.path)) continue;
3988
+ if (command.subcommands.includes(subcommand.id)) continue;
3989
+ command.subcommands.push(subcommand.id);
3866
3990
  }
3867
- return {
3868
- name: cleanName.trim(),
3869
- parsedCategories
3870
- };
3871
3991
  }
3872
- findAssociatedMiddlewares(commandName, category) {
3873
- const middlewares = [];
3874
- this.middlewares.forEach((middleware) => {
3875
- if (middleware.name === "middleware") {
3876
- middlewares.push(middleware.id);
3877
- return;
3878
- }
3879
- if (middleware.name === commandName) {
3880
- middlewares.push(middleware.id);
3881
- return;
3882
- }
3883
- if (category && middleware.category === category) {
3884
- middlewares.push(middleware.id);
3885
- }
3886
- });
3887
- return middlewares;
3992
+ extractCategory(entry) {
3993
+ return entry.split(import_posix.default.sep).map((segment) => {
3994
+ const match = segment.match(/^\((\w+)\)$/);
3995
+ return match ? match[1] : null;
3996
+ }).filter(Boolean).join(":");
3997
+ }
3998
+ getRelativePath(entry) {
3999
+ return import_posix.default.relative(this.entrypoint, entry);
4000
+ }
4001
+ isMiddleware(entry) {
4002
+ return !this.shouldIgnore(entry) && ["middleware", ".middleware."].some((ext) => entry.includes(ext));
4003
+ }
4004
+ shouldIgnore(entry, dir = false) {
4005
+ const fileName = import_posix.default.basename(entry);
4006
+ if (fileName.startsWith("_")) return true;
4007
+ if (!dir) return !/.(c|m)?(j|t)sx?$/.test(fileName);
4008
+ return false;
4009
+ }
4010
+ extractName(entry) {
4011
+ return import_posix.default.basename(entry).replace(/\.(c|m)?(j|t)sx?$/, "");
3888
4012
  }
3889
4013
  };
3890
4014
  __name(_CommandsRouter, "CommandsRouter");
@@ -3893,14 +4017,14 @@ var init_CommandsRouter = __esm({
3893
4017
  });
3894
4018
 
3895
4019
  // src/app/router/EventsRouter.ts
3896
- var import_node_fs3, import_promises4, import_node_path4, _EventsRouter, EventsRouter;
4020
+ var import_node_fs4, import_promises4, import_node_path3, _EventsRouter, EventsRouter;
3897
4021
  var init_EventsRouter = __esm({
3898
4022
  "src/app/router/EventsRouter.ts"() {
3899
4023
  "use strict";
3900
4024
  init_cjs_shims();
3901
- import_node_fs3 = require("fs");
4025
+ import_node_fs4 = require("fs");
3902
4026
  import_promises4 = require("fs/promises");
3903
- import_node_path4 = require("path");
4027
+ import_node_path3 = require("path");
3904
4028
  _EventsRouter = class _EventsRouter {
3905
4029
  /**
3906
4030
  * Creates a new EventsRouter instance
@@ -3934,7 +4058,7 @@ var init_EventsRouter = __esm({
3934
4058
  * Checks if the entrypoint path is valid
3935
4059
  */
3936
4060
  isValidPath() {
3937
- return (0, import_node_fs3.existsSync)(this.entrypoint);
4061
+ return (0, import_node_fs4.existsSync)(this.entrypoint);
3938
4062
  }
3939
4063
  /**
3940
4064
  * Clear all parsed events
@@ -3958,7 +4082,7 @@ var init_EventsRouter = __esm({
3958
4082
  const dirs = await (0, import_promises4.readdir)(this.entrypoint, { withFileTypes: true });
3959
4083
  for (const dir of dirs) {
3960
4084
  if (dir.isDirectory()) {
3961
- const path3 = (0, import_node_path4.join)(this.entrypoint, dir.name);
4085
+ const path3 = (0, import_node_path3.join)(this.entrypoint, dir.name);
3962
4086
  const event = await this.scanEvent(dir.name, path3);
3963
4087
  this.events.set(event.event, event);
3964
4088
  }
@@ -3985,12 +4109,12 @@ var init_EventsRouter = __esm({
3985
4109
  for (const file of files) {
3986
4110
  if (/node_modules/.test(file.name)) continue;
3987
4111
  if (file.isDirectory()) {
3988
- const nextPath = (0, import_node_path4.join)(path3, file.name);
4112
+ const nextPath = (0, import_node_path3.join)(path3, file.name);
3989
4113
  await this.scanEvent(event, nextPath, listeners);
3990
4114
  continue;
3991
4115
  }
3992
4116
  if (file.isFile() && /\.(m|c)?(j|t)sx?$/.test(file.name)) {
3993
- listeners.push((0, import_node_path4.join)(file.parentPath, file.name));
4117
+ listeners.push((0, import_node_path3.join)(file.parentPath, file.name));
3994
4118
  }
3995
4119
  }
3996
4120
  const maybeNamespace = path3.replace(this.entrypoint, "").replaceAll("\\", "/").split("/").shift();
@@ -4042,7 +4166,10 @@ var init_AppEventsHandler = __esm({
4042
4166
  `Event handler for ${event.event}${event.namespace ? ` of namespace ${event.namespace}` : ""} does not have a default export or is not a function`
4043
4167
  );
4044
4168
  }
4045
- listeners.push(handler.default);
4169
+ listeners.push({
4170
+ handler: handler.default,
4171
+ once: !!handler.once
4172
+ });
4046
4173
  }
4047
4174
  const len = listeners.length;
4048
4175
  if (!len) {
@@ -4070,11 +4197,28 @@ var init_AppEventsHandler = __esm({
4070
4197
  registerAllClientEvents() {
4071
4198
  const client = this.commandkit.client;
4072
4199
  for (const [key, data] of this.loadedEvents.entries()) {
4073
- const { name, listeners, namespace, mainListener } = data;
4074
- const main = mainListener || (async (...args) => {
4075
- for (const listener of listeners) {
4200
+ const { name, listeners, namespace } = data;
4201
+ const onceListeners = listeners.filter((listener) => listener.once);
4202
+ const onListeners = listeners.filter((listener) => !listener.once);
4203
+ const executedOnceListeners = /* @__PURE__ */ new Set();
4204
+ const mainHandler = /* @__PURE__ */ __name(async (...args) => {
4205
+ for (const listener of onListeners) {
4206
+ try {
4207
+ await listener.handler(...args);
4208
+ } catch (e) {
4209
+ Logger.error(
4210
+ `Error handling event ${name}${namespace ? ` of namespace ${namespace}` : ""}`,
4211
+ e
4212
+ );
4213
+ }
4214
+ }
4215
+ }, "mainHandler");
4216
+ const onceHandler = /* @__PURE__ */ __name(async (...args) => {
4217
+ for (const listener of onceListeners) {
4076
4218
  try {
4077
- await listener(...args);
4219
+ if (executedOnceListeners.has(listener.handler)) continue;
4220
+ await listener.handler(...args);
4221
+ executedOnceListeners.add(listener.handler);
4078
4222
  } catch (e) {
4079
4223
  Logger.error(
4080
4224
  `Error handling event ${name}${namespace ? ` of namespace ${namespace}` : ""}`,
@@ -4082,16 +4226,35 @@ var init_AppEventsHandler = __esm({
4082
4226
  );
4083
4227
  }
4084
4228
  }
4229
+ if (executedOnceListeners.size === onceListeners.length && onListeners.length === 0) {
4230
+ this.loadedEvents.delete(key);
4231
+ Logger.info(
4232
+ `\u{1F9F9} Cleaned up completed once-only event ${name}${namespace ? ` of namespace ${namespace}` : ""}`
4233
+ );
4234
+ }
4235
+ }, "onceHandler");
4236
+ this.loadedEvents.set(key, {
4237
+ ...data,
4238
+ mainListener: onListeners.length > 0 ? { handler: mainHandler, once: false } : void 0,
4239
+ executedOnceListeners
4085
4240
  });
4086
- if (!mainListener) {
4087
- this.loadedEvents.set(key, {
4088
- ...data,
4089
- mainListener: main
4090
- });
4241
+ if (namespace) {
4242
+ if (onListeners.length > 0) {
4243
+ this.commandkit.events.on(namespace, name, mainHandler);
4244
+ }
4245
+ if (onceListeners.length > 0) {
4246
+ this.commandkit.events.once(namespace, name, onceHandler);
4247
+ }
4248
+ } else {
4249
+ if (onListeners.length > 0) {
4250
+ client.on(name, mainHandler);
4251
+ }
4252
+ if (onceListeners.length > 0) {
4253
+ client.once(name, onceHandler);
4254
+ }
4091
4255
  }
4092
- client.on(name, main);
4093
4256
  Logger.info(
4094
- `\u{1F50C} Registered event ${name}${namespace ? ` of namespace ${namespace}` : ""}`
4257
+ `\u{1F50C} Registered event ${name}${namespace ? ` of namespace ${namespace}` : ""} (${onListeners.length} regular, ${onceListeners.length} once-only)`
4095
4258
  );
4096
4259
  }
4097
4260
  }
@@ -4102,9 +4265,17 @@ var init_AppEventsHandler = __esm({
4102
4265
  { name, mainListener, namespace }
4103
4266
  ] of this.loadedEvents.entries()) {
4104
4267
  if (mainListener) {
4105
- client.off(name, mainListener);
4268
+ if (namespace) {
4269
+ this.commandkit.events.off(namespace, name, mainListener.handler);
4270
+ } else {
4271
+ client.off(name, mainListener.handler);
4272
+ }
4106
4273
  } else {
4107
- client.removeAllListeners(name);
4274
+ if (namespace) {
4275
+ this.commandkit.events.removeAllListeners(namespace, name);
4276
+ } else {
4277
+ client.removeAllListeners(name);
4278
+ }
4108
4279
  }
4109
4280
  this.loadedEvents.delete(key);
4110
4281
  Logger.info(
@@ -4118,6 +4289,54 @@ var init_AppEventsHandler = __esm({
4118
4289
  }
4119
4290
  });
4120
4291
 
4292
+ // src/utils/types-package.ts
4293
+ async function generateTypesPackage() {
4294
+ const location = (0, import_node_path4.join)(process.cwd(), "node_modules", "commandkit-types");
4295
+ const packageJSON = (0, import_node_path4.join)(location, "package.json");
4296
+ const index = (0, import_node_path4.join)(location, "index.js");
4297
+ const types = (0, import_node_path4.join)(location, "index.d.ts");
4298
+ const locale = (0, import_node_path4.join)(location, "locale.d.ts");
4299
+ const command = (0, import_node_path4.join)(location, "command.d.ts");
4300
+ const exists = (0, import_node_fs5.existsSync)(packageJSON);
4301
+ if (exists) return location;
4302
+ const packageJSONContent = {
4303
+ name: "commandkit-types",
4304
+ version: "1.0.0",
4305
+ description: "CommandKit types package",
4306
+ type: "commonjs",
4307
+ main: "index.js",
4308
+ types: "index.d.ts"
4309
+ };
4310
+ const indexContent = `module.exports = {};`;
4311
+ const typesContent = `import { CommandLocalizationTypeData } from './locale.d.ts';
4312
+ import { CommandTypeData } from './command.d.ts';
4313
+
4314
+ declare module 'commandkit' {
4315
+ export interface CommandKitTypeReferences {
4316
+ locale: CommandLocalizationTypeData;
4317
+ command: CommandTypeData;
4318
+ }
4319
+ }`;
4320
+ await (0, import_promises5.mkdir)(location, { recursive: true });
4321
+ await (0, import_promises5.writeFile)(packageJSON, JSON.stringify(packageJSONContent, null, 2));
4322
+ await (0, import_promises5.writeFile)(index, indexContent);
4323
+ await (0, import_promises5.writeFile)(types, typesContent);
4324
+ await (0, import_promises5.writeFile)(locale, "");
4325
+ await (0, import_promises5.writeFile)(command, "");
4326
+ return location;
4327
+ }
4328
+ var import_node_fs5, import_promises5, import_node_path4;
4329
+ var init_types_package = __esm({
4330
+ "src/utils/types-package.ts"() {
4331
+ "use strict";
4332
+ init_cjs_shims();
4333
+ import_node_fs5 = require("fs");
4334
+ import_promises5 = require("fs/promises");
4335
+ import_node_path4 = require("path");
4336
+ __name(generateTypesPackage, "generateTypesPackage");
4337
+ }
4338
+ });
4339
+
4121
4340
  // src/cli/common.ts
4122
4341
  function write(message) {
4123
4342
  process.stdout.write(message);
@@ -4145,7 +4364,7 @@ async function loadConfigFileFromPath(target) {
4145
4364
  const isTs = await ensureTypeScript(target);
4146
4365
  if (isTs && ts) {
4147
4366
  const { transpileModule } = ts;
4148
- const src = import_node_fs4.default.readFileSync(target, "utf8");
4367
+ const src = import_node_fs6.default.readFileSync(target, "utf8");
4149
4368
  const { outputText } = transpileModule(src, {
4150
4369
  compilerOptions: {
4151
4370
  module: ts.ModuleKind.ESNext,
@@ -4154,14 +4373,9 @@ async function loadConfigFileFromPath(target) {
4154
4373
  },
4155
4374
  fileName: target
4156
4375
  });
4157
- const nodeModulesPath = (0, import_node_path5.join)(
4158
- process.cwd(),
4159
- "node_modules",
4160
- ".commandkit_tmp"
4161
- );
4162
- import_node_fs4.default.mkdirSync(nodeModulesPath, { recursive: true });
4376
+ const nodeModulesPath = await generateTypesPackage();
4163
4377
  const tmpFile = (0, import_node_path5.join)(nodeModulesPath, "compiled-commandkit.config.mjs");
4164
- import_node_fs4.default.writeFileSync(tmpFile, outputText);
4378
+ import_node_fs6.default.writeFileSync(tmpFile, outputText);
4165
4379
  target = tmpFile;
4166
4380
  }
4167
4381
  const config = await import(`file://${target}`).then(
@@ -4170,20 +4384,21 @@ async function loadConfigFileFromPath(target) {
4170
4384
  return config;
4171
4385
  }
4172
4386
  async function ensureExists(loc) {
4173
- const exists = import_node_fs4.default.existsSync(loc);
4387
+ const exists = import_node_fs6.default.existsSync(loc);
4174
4388
  if (!exists) {
4175
4389
  throw new Error(`File not found: ${loc}`);
4176
4390
  }
4177
4391
  }
4178
- var import_rimraf, import_node_path5, import_node_fs4, ts;
4392
+ var import_rimraf, import_node_path5, import_node_fs6, ts;
4179
4393
  var init_common = __esm({
4180
4394
  "src/cli/common.ts"() {
4181
4395
  "use strict";
4182
4396
  init_cjs_shims();
4183
4397
  import_rimraf = require("rimraf");
4184
4398
  import_node_path5 = require("path");
4185
- import_node_fs4 = __toESM(require("fs"));
4399
+ import_node_fs6 = __toESM(require("fs"));
4186
4400
  init_colors();
4401
+ init_types_package();
4187
4402
  __name(write, "write");
4188
4403
  __name(panic, "panic");
4189
4404
  __name(ensureTypeScript, "ensureTypeScript");
@@ -4196,7 +4411,7 @@ var init_common = __esm({
4196
4411
  function findConfigFile(cwd) {
4197
4412
  const locations = CONFIG_FILE_NAMES.map((name) => (0, import_node_path6.join)(cwd, name));
4198
4413
  for (const location of locations) {
4199
- if ((0, import_node_fs5.existsSync)(location)) {
4414
+ if ((0, import_node_fs7.existsSync)(location)) {
4200
4415
  return {
4201
4416
  path: location,
4202
4417
  isTypeScript: /\.ts$/.test(location)
@@ -4213,12 +4428,12 @@ async function loadConfigFile(entrypoint = process.cwd()) {
4213
4428
  loadedConfig = config;
4214
4429
  return config;
4215
4430
  }
4216
- var import_node_fs5, import_node_path6, CONFIG_FILE_NAMES, loadedConfig;
4431
+ var import_node_fs7, import_node_path6, CONFIG_FILE_NAMES, loadedConfig;
4217
4432
  var init_loader = __esm({
4218
4433
  "src/config/loader.ts"() {
4219
4434
  "use strict";
4220
4435
  init_cjs_shims();
4221
- import_node_fs5 = require("fs");
4436
+ import_node_fs7 = require("fs");
4222
4437
  import_node_path6 = require("path");
4223
4438
  init_common();
4224
4439
  init_config();
@@ -4267,13 +4482,59 @@ var init_dev_hooks = __esm({
4267
4482
  }
4268
4483
  });
4269
4484
 
4485
+ // src/events/CommandKitEventsChannel.ts
4486
+ var import_node_events, _CommandKitEventsChannel, CommandKitEventsChannel;
4487
+ var init_CommandKitEventsChannel = __esm({
4488
+ "src/events/CommandKitEventsChannel.ts"() {
4489
+ "use strict";
4490
+ init_cjs_shims();
4491
+ import_node_events = __toESM(require("events"));
4492
+ _CommandKitEventsChannel = class _CommandKitEventsChannel {
4493
+ constructor(commandkit) {
4494
+ this.commandkit = commandkit;
4495
+ }
4496
+ emitter = new import_node_events.default();
4497
+ to(namespace) {
4498
+ return {
4499
+ on: this.on.bind(this, namespace),
4500
+ off: this.off.bind(this, namespace),
4501
+ once: this.once.bind(this, namespace),
4502
+ emit: this.emit.bind(this, namespace),
4503
+ removeAllListeners: this.removeAllListeners.bind(this, namespace)
4504
+ };
4505
+ }
4506
+ on(namespace, event, listener) {
4507
+ this.emitter.on(`${namespace}:${event}`, listener);
4508
+ }
4509
+ off(namespace, event, listener) {
4510
+ this.emitter.off(`${namespace}:${event}`, listener);
4511
+ }
4512
+ once(namespace, event, listener) {
4513
+ this.emitter.once(`${namespace}:${event}`, listener);
4514
+ }
4515
+ emit(namespace, event, ...args) {
4516
+ return this.emitter.emit(`${namespace}:${event}`, ...args);
4517
+ }
4518
+ removeAllListeners(namespace, event) {
4519
+ if (event) {
4520
+ this.emitter.removeAllListeners(`${namespace}:${event}`);
4521
+ } else {
4522
+ this.emitter.removeAllListeners(namespace);
4523
+ }
4524
+ }
4525
+ };
4526
+ __name(_CommandKitEventsChannel, "CommandKitEventsChannel");
4527
+ CommandKitEventsChannel = _CommandKitEventsChannel;
4528
+ }
4529
+ });
4530
+
4270
4531
  // src/CommandKit.ts
4271
- var import_node_events, import_discord12, import_node_path7, import_node_fs6, _started, _CommandKit_instances, init_fn, initCommands_fn, initEvents_fn, _CommandKit, CommandKit;
4532
+ var import_node_events2, import_discord12, import_node_path7, _started, _CommandKit_instances, init_fn, initCommands_fn, initEvents_fn, _CommandKit, CommandKit;
4272
4533
  var init_CommandKit = __esm({
4273
4534
  "src/CommandKit.ts"() {
4274
4535
  "use strict";
4275
4536
  init_cjs_shims();
4276
- import_node_events = __toESM(require("events"));
4537
+ import_node_events2 = __toESM(require("events"));
4277
4538
  init_colors();
4278
4539
  init_CacheProvider();
4279
4540
  init_MemoryCache();
@@ -4290,8 +4551,11 @@ var init_CommandKit = __esm({
4290
4551
  init_loader();
4291
4552
  init_constants();
4292
4553
  init_dev_hooks();
4293
- import_node_fs6 = require("fs");
4294
- _CommandKit = class _CommandKit extends import_node_events.default {
4554
+ init_CommandKitEventsChannel();
4555
+ init_plugins();
4556
+ init_types_package();
4557
+ init_Logger();
4558
+ _CommandKit = class _CommandKit extends import_node_events2.default {
4295
4559
  /**
4296
4560
  * Create a new command and event handler with CommandKit.
4297
4561
  *
@@ -4332,6 +4596,7 @@ var init_CommandKit = __esm({
4332
4596
  __publicField(this, "commandHandler", new AppCommandHandler(this));
4333
4597
  __publicField(this, "eventHandler", new AppEventsHandler(this));
4334
4598
  __publicField(this, "plugins");
4599
+ __publicField(this, "events", new CommandKitEventsChannel(this));
4335
4600
  options.debugCommands ??= process.env.NODE_ENV !== "production";
4336
4601
  if (options.cacheProvider !== null && (!options.cacheProvider || !(options.cacheProvider instanceof CacheProvider))) {
4337
4602
  options.cacheProvider = new MemoryCache();
@@ -4347,8 +4612,18 @@ var init_CommandKit = __esm({
4347
4612
  * @param token The application token to connect to the discord gateway. If not provided, it will use the `TOKEN` or `DISCORD_TOKEN` environment variable. If set to `false`, it will not login.
4348
4613
  */
4349
4614
  async start(token) {
4350
- await loadConfigFile();
4351
4615
  if (__privateGet(this, _started)) return;
4616
+ if (COMMANDKIT_IS_DEV) {
4617
+ try {
4618
+ registerDevHooks(this);
4619
+ await generateTypesPackage();
4620
+ } catch (e) {
4621
+ if (process.env.COMMANDKIT_DEBUG_TYPEGEN) {
4622
+ Logger.error(e);
4623
+ }
4624
+ }
4625
+ }
4626
+ await this.loadPlugins();
4352
4627
  await __privateMethod(this, _CommandKit_instances, init_fn).call(this);
4353
4628
  this.incrementClientListenersCount();
4354
4629
  if (token !== false && !this.options.client.isReady()) {
@@ -4357,11 +4632,19 @@ var init_CommandKit = __esm({
4357
4632
  );
4358
4633
  }
4359
4634
  __privateSet(this, _started, true);
4360
- if (COMMANDKIT_IS_DEV) {
4361
- registerDevHooks(this);
4362
- }
4363
4635
  await this.commandHandler.registrar.register();
4364
4636
  }
4637
+ /**
4638
+ * Loads all the plugins.
4639
+ */
4640
+ async loadPlugins() {
4641
+ const config = await loadConfigFile();
4642
+ const plugins = config.plugins.filter((p) => isRuntimePlugin(p));
4643
+ if (!plugins.length) return;
4644
+ for (const plugin of plugins) {
4645
+ await this.plugins.softRegisterPlugin(plugin);
4646
+ }
4647
+ }
4365
4648
  /**
4366
4649
  * Whether or not the commandkit application has started.
4367
4650
  */
@@ -4517,8 +4800,11 @@ var init_CommandKit = __esm({
4517
4800
  }, "#init");
4518
4801
  initCommands_fn = /* @__PURE__ */ __name(async function() {
4519
4802
  if (this.commandsRouter.isValidPath()) {
4520
- const commands = await this.commandsRouter.scan();
4521
- await (0, import_node_fs6.writeFileSync)("./commands.json", JSON.stringify(commands, null, 2));
4803
+ await this.commandsRouter.scan();
4804
+ if (COMMANDKIT_IS_DEV) {
4805
+ const visual = this.commandsRouter.visualize();
4806
+ console.log(visual);
4807
+ }
4522
4808
  }
4523
4809
  await this.commandHandler.loadCommands();
4524
4810
  }, "#initCommands");
@@ -4547,7 +4833,7 @@ var init_version = __esm({
4547
4833
  "use strict";
4548
4834
  init_cjs_shims();
4549
4835
  version = /* @__MACRO__ $version */
4550
- "0.1.11-dev.20250306152436";
4836
+ "0.1.11-dev.20250307192025";
4551
4837
  }
4552
4838
  });
4553
4839
 
@@ -4589,7 +4875,7 @@ function getStdio(supportsCommands) {
4589
4875
  }
4590
4876
  function createAppProcess(fileName, cwd, isDev) {
4591
4877
  var _a, _b;
4592
- if (!(0, import_node_fs7.existsSync)((0, import_node_path8.join)(cwd, fileName))) {
4878
+ if (!(0, import_node_fs8.existsSync)((0, import_node_path8.join)(cwd, fileName))) {
4593
4879
  panic(`Could not locate the entrypoint file: ${fileName}`);
4594
4880
  }
4595
4881
  const stdio = getStdio(isDev);
@@ -4611,7 +4897,7 @@ function createAppProcess(fileName, cwd, isDev) {
4611
4897
  (_b = ps.stderr) == null ? void 0 : _b.pipe(process.stderr);
4612
4898
  return ps;
4613
4899
  }
4614
- var import_node_child_process, import_node_path8, import_node_fs7;
4900
+ var import_node_child_process, import_node_path8, import_node_fs8;
4615
4901
  var init_app_process = __esm({
4616
4902
  "src/cli/app-process.ts"() {
4617
4903
  "use strict";
@@ -4619,7 +4905,7 @@ var init_app_process = __esm({
4619
4905
  import_node_child_process = require("child_process");
4620
4906
  init_env();
4621
4907
  import_node_path8 = require("path");
4622
- import_node_fs7 = require("fs");
4908
+ import_node_fs8 = require("fs");
4623
4909
  init_common();
4624
4910
  __name(getStdio, "getStdio");
4625
4911
  __name(createAppProcess, "createAppProcess");
@@ -4706,9 +4992,9 @@ async function main() {
4706
4992
  await main();
4707
4993
  `;
4708
4994
  const dist = isDev ? ".commandkit" : distDir || "dist";
4709
- await (0, import_promises5.writeFile)((0, import_node_path9.join)(configPath, dist, "index.js"), code);
4995
+ await (0, import_promises6.writeFile)((0, import_node_path9.join)(configPath, dist, "index.js"), code);
4710
4996
  }
4711
- var import_tsup, import_promises5, import_node_path9, envScript, requireScript, antiCrashScript, wrapInAsyncIIFE;
4997
+ var import_tsup, import_promises6, import_node_path9, envScript, requireScript, antiCrashScript, wrapInAsyncIIFE;
4712
4998
  var init_build = __esm({
4713
4999
  "src/cli/build.ts"() {
4714
5000
  "use strict";
@@ -4716,7 +5002,7 @@ var init_build = __esm({
4716
5002
  import_tsup = require("tsup");
4717
5003
  init_plugins();
4718
5004
  init_loader();
4719
- import_promises5 = require("fs/promises");
5005
+ import_promises6 = require("fs/promises");
4720
5006
  import_node_path9 = require("path");
4721
5007
  init_env();
4722
5008
  __name(buildApplication, "buildApplication");
@@ -4861,7 +5147,7 @@ async function bootstrapDevelopmentServer(configPath) {
4861
5147
  watcher.on("add", hmrHandler);
4862
5148
  watcher.on("unlink", hmrHandler);
4863
5149
  watcher.on("unlinkDir", (path3) => {
4864
- const hasChild = (0, import_node_fs8.readdirSync)(path3).length > 0;
5150
+ const hasChild = (0, import_node_fs9.readdirSync)(path3).length > 0;
4865
5151
  if (hasChild) return hmrHandler(path3);
4866
5152
  });
4867
5153
  watcher.on("error", (e) => {
@@ -4880,7 +5166,7 @@ ${colors_default.yellowBright("re")} - Reload all events
4880
5166
  ${colors_default.yellowBright("rl")} - Reload all locales`
4881
5167
  );
4882
5168
  }
4883
- var import_path2, import_chokidar, import_node_fs8, isCommandSource, isEventSource, isLocaleSource;
5169
+ var import_path2, import_chokidar, import_node_fs9, isCommandSource, isEventSource, isLocaleSource;
4884
5170
  var init_development = __esm({
4885
5171
  "src/cli/development.ts"() {
4886
5172
  "use strict";
@@ -4891,7 +5177,7 @@ var init_development = __esm({
4891
5177
  init_app_process();
4892
5178
  init_build();
4893
5179
  import_chokidar = require("chokidar");
4894
- import_node_fs8 = require("fs");
5180
+ import_node_fs9 = require("fs");
4895
5181
  init_utilities();
4896
5182
  init_colors();
4897
5183
  __name(buildAndStart, "buildAndStart");
@@ -4978,7 +5264,7 @@ __export(generators_exports, {
4978
5264
  });
4979
5265
  async function generateCommand(name, customPath) {
4980
5266
  const cmdPath = (0, import_path4.join)(customPath || COMMANDS_DIR, name);
4981
- if (!(0, import_fs2.existsSync)(cmdPath)) await (0, import_promises6.mkdir)(cmdPath, { recursive: true });
5267
+ if (!(0, import_fs2.existsSync)(cmdPath)) await (0, import_promises7.mkdir)(cmdPath, { recursive: true });
4982
5268
  if ((0, import_fs2.existsSync)((0, import_path4.join)(cmdPath, "command.ts"))) {
4983
5269
  panic(`Command ${name} already exists.`);
4984
5270
  }
@@ -4998,7 +5284,7 @@ export const message: MessageCommand = async (ctx) => {
4998
5284
  await ctx.message.reply('Hello from ${name}!');
4999
5285
  };
5000
5286
  `.trim();
5001
- await (0, import_promises6.writeFile)((0, import_path4.join)(cmdPath, "command.ts"), commandFile);
5287
+ await (0, import_promises7.writeFile)((0, import_path4.join)(cmdPath, "command.ts"), commandFile);
5002
5288
  console.log(
5003
5289
  colors_default.green(
5004
5290
  `Command ${colors_default.magenta(name)} created at ${colors_default.blue(formatPath(cmdPath))}/command.ts`
@@ -5007,10 +5293,10 @@ export const message: MessageCommand = async (ctx) => {
5007
5293
  }
5008
5294
  async function generateEvent(name, customPath) {
5009
5295
  const eventPath = (0, import_path4.join)(customPath || EVENTS_DIR, name);
5010
- if (!(0, import_fs2.existsSync)(eventPath)) await (0, import_promises6.mkdir)(eventPath, { recursive: true });
5296
+ if (!(0, import_fs2.existsSync)(eventPath)) await (0, import_promises7.mkdir)(eventPath, { recursive: true });
5011
5297
  let filename = "event.ts";
5012
5298
  if ((0, import_fs2.existsSync)((0, import_path4.join)(eventPath, filename))) {
5013
- const count = (await (0, import_promises6.readdir)(eventPath)).length;
5299
+ const count = (await (0, import_promises7.readdir)(eventPath)).length;
5014
5300
  filename = `${String(count).padStart(2, "0")}_${filename}`;
5015
5301
  }
5016
5302
  const eventFile = `
@@ -5018,7 +5304,7 @@ export default async function on${name[0].toUpperCase() + name.slice(1)}() {
5018
5304
  console.log('${name} event fired!');
5019
5305
  };
5020
5306
  `.trim();
5021
- await (0, import_promises6.writeFile)((0, import_path4.join)(eventPath, filename), eventFile);
5307
+ await (0, import_promises7.writeFile)((0, import_path4.join)(eventPath, filename), eventFile);
5022
5308
  console.log(
5023
5309
  colors_default.green(
5024
5310
  `Event ${colors_default.magenta(name)} created at ${colors_default.blue(formatPath(eventPath))}/${colors_default.magenta(filename)}`
@@ -5036,7 +5322,7 @@ async function generateLocale(locale, commandName, customPath) {
5036
5322
  panic("Command name is required.");
5037
5323
  }
5038
5324
  const localePath = (0, import_path4.join)(customPath || LOCALES_DIR, locale);
5039
- if (!(0, import_fs2.existsSync)(localePath)) await (0, import_promises6.mkdir)(localePath, { recursive: true });
5325
+ if (!(0, import_fs2.existsSync)(localePath)) await (0, import_promises7.mkdir)(localePath, { recursive: true });
5040
5326
  if ((0, import_fs2.existsSync)((0, import_path4.join)(localePath, `${commandName}.json`))) {
5041
5327
  panic(`Locale file for ${commandName} already exists.`);
5042
5328
  }
@@ -5047,7 +5333,7 @@ async function generateLocale(locale, commandName, customPath) {
5047
5333
  },
5048
5334
  translations: {}
5049
5335
  };
5050
- await (0, import_promises6.writeFile)(
5336
+ await (0, import_promises7.writeFile)(
5051
5337
  (0, import_path4.join)(localePath, `${commandName}.json`),
5052
5338
  JSON.stringify(localeFile, null, 2)
5053
5339
  );
@@ -5059,12 +5345,12 @@ async function generateLocale(locale, commandName, customPath) {
5059
5345
  )
5060
5346
  );
5061
5347
  }
5062
- var import_promises6, import_path4, import_discord13, import_fs2, BASE_PATH, COMMANDS_DIR, EVENTS_DIR, LOCALES_DIR, formatPath;
5348
+ var import_promises7, import_path4, import_discord13, import_fs2, BASE_PATH, COMMANDS_DIR, EVENTS_DIR, LOCALES_DIR, formatPath;
5063
5349
  var init_generators = __esm({
5064
5350
  "src/cli/generators.ts"() {
5065
5351
  "use strict";
5066
5352
  init_cjs_shims();
5067
- import_promises6 = require("fs/promises");
5353
+ import_promises7 = require("fs/promises");
5068
5354
  import_path4 = require("path");
5069
5355
  import_discord13 = require("discord.js");
5070
5356
  init_common();