commandkit 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/README.md +1 -1
  2. package/cache.cjs +2 -0
  3. package/cache.d.ts +1 -0
  4. package/dist/{ActionRow-Bt9qi0Mb.d.ts → ActionRow-DSh9roc5.d.ts} +2 -3
  5. package/dist/{Button-DxJLcZIU.d.ts → Button-BPsE5ju0.d.ts} +5 -6
  6. package/dist/{ButtonKit-BfcyvWfj.d.ts → ButtonKit-CNPmVg3h.d.ts} +2 -3
  7. package/dist/{ChannelSelectMenuKit-DYkudikb.d.ts → ChannelSelectMenuKit-CcOdaLQ6.d.ts} +3 -4
  8. package/dist/CommandTree-qu-8oAEV.d.ts +55 -0
  9. package/dist/CommandsRouter-Co225Ae5.d.ts +242 -0
  10. package/dist/{EventInterceptor-D9JKMcfi.d.ts → EventInterceptor-wg378vJp.d.ts} +1 -2
  11. package/dist/{EventsRouter-EuuSu6NH.d.ts → EventsRouter-Bt63ZuEF.d.ts} +21 -2
  12. package/dist/{MentionableSelectMenuKit-Mu4xqP6B.d.ts → MentionableSelectMenuKit-8_Nkgn_a.d.ts} +3 -4
  13. package/dist/{MessageCommandParser-DPCbHXCS.d.ts → MessageCommandParser-BYbxHOSK.d.ts} +7 -2
  14. package/dist/{Modal-v9rrcMl-.d.ts → Modal-DbWK6VmV.d.ts} +5 -6
  15. package/dist/{ModalKit-XJSM65SV.d.ts → ModalKit-CnmUVpw-.d.ts} +2 -3
  16. package/dist/{RoleSelectMenuKit-CCjcp3HY.d.ts → RoleSelectMenuKit-Bei7DHqD.d.ts} +3 -4
  17. package/dist/{SelectMenu-CY0vvoSu.d.ts → SelectMenu-Bce_PClo.d.ts} +8 -9
  18. package/dist/{StringSelectMenuKit-G5nBTicX.d.ts → StringSelectMenuKit-CBeB9HqT.d.ts} +3 -4
  19. package/dist/TreeArtifact-D6FZ5SVd.d.ts +27 -0
  20. package/dist/{UserSelectMenuKit-D3SO_fXA.d.ts → UserSelectMenuKit-DZmeZ_Tp.d.ts} +3 -4
  21. package/dist/analytics/analytics-engine.d.ts +1 -1
  22. package/dist/analytics/analytics-engine.js +1 -1
  23. package/dist/analytics/analytics-provider.d.ts +1 -1
  24. package/dist/analytics/constants.js +0 -1
  25. package/dist/analytics/constants.js.map +1 -1
  26. package/dist/analytics/utils.js +1 -1
  27. package/dist/{analytics-engine-DnRsHBId.d.ts → analytics-engine-Bz1p7ud3.d.ts} +178 -30
  28. package/dist/app/commands/AppCommandRunner.d.ts +1 -1
  29. package/dist/app/commands/AppCommandRunner.js +1 -1
  30. package/dist/app/commands/Context.d.ts +1 -1
  31. package/dist/app/commands/Context.js +1 -1
  32. package/dist/app/commands/MessageCommandParser.d.ts +1 -1
  33. package/dist/app/commands/MessageCommandParser.js +79 -71
  34. package/dist/app/commands/MessageCommandParser.js.map +1 -1
  35. package/dist/app/commands/helpers.d.ts +1 -1
  36. package/dist/app/commands/helpers.js +0 -1
  37. package/dist/app/commands/helpers.js.map +1 -1
  38. package/dist/app/events/EventWorkerContext.d.ts +3 -3
  39. package/dist/app/events/EventWorkerContext.js +0 -1
  40. package/dist/app/events/EventWorkerContext.js.map +1 -1
  41. package/dist/app/handlers/AppCommandHandler.d.ts +1 -1
  42. package/dist/app/handlers/AppCommandHandler.js +1 -1
  43. package/dist/app/handlers/AppEventsHandler.d.ts +1 -1
  44. package/dist/app/handlers/AppEventsHandler.js +1 -1
  45. package/dist/app/index.d.ts +5 -5
  46. package/dist/app/index.js +1 -1
  47. package/dist/app/interrupt/signals.d.ts +1 -1
  48. package/dist/app/interrupt/signals.js.map +1 -1
  49. package/dist/app/middlewares/permissions.d.ts +1 -2
  50. package/dist/app/middlewares/permissions.js +1 -1
  51. package/dist/app/register/CommandRegistrar.d.ts +1 -1
  52. package/dist/app/register/CommandRegistrar.js +1 -1
  53. package/dist/app/router/CommandTree.d.ts +2 -0
  54. package/dist/app/router/CommandTree.js +1 -0
  55. package/dist/app/router/CommandsRouter.d.ts +2 -2
  56. package/dist/app/router/CommandsRouter.js +445 -24
  57. package/dist/app/router/CommandsRouter.js.map +1 -1
  58. package/dist/app/router/EventsRouter.d.ts +2 -2
  59. package/dist/app/router/EventsRouter.js +56 -3
  60. package/dist/app/router/EventsRouter.js.map +1 -1
  61. package/dist/app/router/TreeArtifact.d.ts +2 -0
  62. package/dist/app/router/TreeArtifact.js +87 -0
  63. package/dist/app/router/TreeArtifact.js.map +1 -0
  64. package/dist/app/router/index.d.ts +6 -3
  65. package/dist/app/router/index.js +8 -1
  66. package/dist/checkbox-DoR0Pcxm.d.ts +27 -0
  67. package/dist/cli/app-process.d.ts +2 -3
  68. package/dist/cli/app-process.js +15 -4
  69. package/dist/cli/app-process.js.map +1 -1
  70. package/dist/cli/build.d.ts +4 -9
  71. package/dist/cli/build.js +33 -5
  72. package/dist/cli/build.js.map +1 -1
  73. package/dist/cli/common.d.ts +3 -6
  74. package/dist/cli/common.js +2 -2
  75. package/dist/cli/common.js.map +1 -1
  76. package/dist/cli/development.d.ts +5 -6
  77. package/dist/cli/development.js +12 -12
  78. package/dist/cli/development.js.map +1 -1
  79. package/dist/cli/env.js.map +1 -1
  80. package/dist/cli/generators.js +0 -1
  81. package/dist/cli/generators.js.map +1 -1
  82. package/dist/cli/information.js +5 -5
  83. package/dist/cli/information.js.map +1 -1
  84. package/dist/cli/init.d.ts +1 -3
  85. package/dist/cli/init.js +37 -12
  86. package/dist/cli/init.js.map +1 -1
  87. package/dist/cli/production.d.ts +1 -3
  88. package/dist/cli/production.js +4 -4
  89. package/dist/cli/production.js.map +1 -1
  90. package/dist/cli/type-checker.js +0 -1
  91. package/dist/cli/type-checker.js.map +1 -1
  92. package/dist/cli/utils.d.ts +0 -1
  93. package/dist/cli/utils.js.map +1 -1
  94. package/dist/{commandkit-Bh7C1_c7.js → commandkit-DNbfLwyR.js} +786 -200
  95. package/dist/commandkit-DNbfLwyR.js.map +1 -0
  96. package/dist/commandkit.d.ts +1 -1
  97. package/dist/commandkit.js +1 -1
  98. package/dist/{common-CCvvgnxi.d.ts → common-CIbPzguv.d.ts} +2 -3
  99. package/dist/components/common/EventInterceptor.d.ts +1 -1
  100. package/dist/components/common/EventInterceptor.js +1 -0
  101. package/dist/components/common/EventInterceptor.js.map +1 -1
  102. package/dist/components/common/element.d.ts +1 -1
  103. package/dist/components/common/element.js +1 -1
  104. package/dist/components/common/types.d.ts +1 -1
  105. package/dist/components/display/common.d.ts +0 -1
  106. package/dist/components/display/common.js +1 -1
  107. package/dist/components/display/container.d.ts +1 -1
  108. package/dist/components/display/container.js +1 -1
  109. package/dist/components/display/file.d.ts +1 -1
  110. package/dist/components/display/file.js +0 -1
  111. package/dist/components/display/file.js.map +1 -1
  112. package/dist/components/display/index.d.ts +9 -8
  113. package/dist/components/display/index.js +1 -1
  114. package/dist/components/display/label.d.ts +1 -1
  115. package/dist/components/display/label.js +1 -1
  116. package/dist/components/display/media-gallery.d.ts +1 -1
  117. package/dist/components/display/media-gallery.js +1 -1
  118. package/dist/components/display/poll.d.ts +1 -1
  119. package/dist/components/display/poll.js +4 -10
  120. package/dist/components/display/poll.js.map +1 -1
  121. package/dist/components/display/section.d.ts +1 -1
  122. package/dist/components/display/section.js +1 -1
  123. package/dist/components/display/separator.d.ts +1 -1
  124. package/dist/components/display/separator.js +0 -1
  125. package/dist/components/display/separator.js.map +1 -1
  126. package/dist/components/display/text-display.d.ts +1 -1
  127. package/dist/components/display/text-display.js +0 -1
  128. package/dist/components/display/text-display.js.map +1 -1
  129. package/dist/components/index.d.ts +26 -23
  130. package/dist/components/index.js +6 -1
  131. package/dist/components/interactive/action-row/ActionRow.d.ts +1 -1
  132. package/dist/components/interactive/action-row/ActionRow.js +0 -1
  133. package/dist/components/interactive/action-row/ActionRow.js.map +1 -1
  134. package/dist/components/interactive/button/Button.d.ts +1 -1
  135. package/dist/components/interactive/button/Button.js +1 -1
  136. package/dist/components/interactive/button/ButtonKit.d.ts +1 -1
  137. package/dist/components/interactive/button/ButtonKit.js +1 -1
  138. package/dist/components/interactive/checkbox/checkbox.d.ts +2 -0
  139. package/dist/components/interactive/checkbox/checkbox.js +6 -0
  140. package/dist/components/interactive/modal/Modal.d.ts +1 -1
  141. package/dist/components/interactive/modal/Modal.js +1 -1
  142. package/dist/components/interactive/modal/ModalKit.d.ts +1 -1
  143. package/dist/components/interactive/modal/ModalKit.js +1 -1
  144. package/dist/components/interactive/radio/radio.d.ts +2 -0
  145. package/dist/components/interactive/radio/radio.js +5 -0
  146. package/dist/components/interactive/select-menu/ChannelSelectMenuKit.d.ts +1 -1
  147. package/dist/components/interactive/select-menu/ChannelSelectMenuKit.js +1 -1
  148. package/dist/components/interactive/select-menu/MentionableSelectMenuKit.d.ts +1 -1
  149. package/dist/components/interactive/select-menu/MentionableSelectMenuKit.js +1 -1
  150. package/dist/components/interactive/select-menu/RoleSelectMenuKit.d.ts +1 -1
  151. package/dist/components/interactive/select-menu/RoleSelectMenuKit.js +1 -1
  152. package/dist/components/interactive/select-menu/SelectMenu.d.ts +1 -1
  153. package/dist/components/interactive/select-menu/SelectMenu.js +1 -1
  154. package/dist/components/interactive/select-menu/StringSelectMenuKit.d.ts +1 -1
  155. package/dist/components/interactive/select-menu/StringSelectMenuKit.js +1 -1
  156. package/dist/components/interactive/select-menu/UserSelectMenuKit.d.ts +1 -1
  157. package/dist/components/interactive/select-menu/UserSelectMenuKit.js +1 -1
  158. package/dist/components/interactive/select-menu/common.d.ts +1 -1
  159. package/dist/config/config.d.ts +1 -2
  160. package/dist/config/config.js +1 -1
  161. package/dist/config/default.d.ts +1 -2
  162. package/dist/config/default.js +1 -1
  163. package/dist/config/loader.d.ts +1 -2
  164. package/dist/config/loader.js +1 -1
  165. package/dist/config/types.d.ts +2 -2
  166. package/dist/config/utils.d.ts +1 -1
  167. package/dist/config/utils.js.map +1 -1
  168. package/dist/{constants-DqtJY0t-.d.ts → constants-B7AfnOFa.d.ts} +1 -1
  169. package/dist/{constants-DwxpkIeH.d.ts → constants-kWgE3L9F.d.ts} +15 -2
  170. package/dist/{container-CYojOA9d.d.ts → container-NVgblXmw.d.ts} +1 -2
  171. package/dist/context/async-context.d.ts +1 -1
  172. package/dist/context/async-context.js +1 -1
  173. package/dist/context/environment.d.ts +1 -1
  174. package/dist/context/environment.js +1 -1
  175. package/dist/{element-DeLvTMfZ.d.ts → element-BMZYAAQ-.d.ts} +3 -4
  176. package/dist/events/CommandKitEventsChannel.d.ts +1 -1
  177. package/dist/events/CommandKitEventsChannel.js +3 -2
  178. package/dist/events/CommandKitEventsChannel.js.map +1 -1
  179. package/dist/{file-DLO1zEcH.d.ts → file-DYAmr697.d.ts} +1 -2
  180. package/dist/flags/FlagProvider.d.ts +1 -1
  181. package/dist/flags/FlagProvider.js +1 -0
  182. package/dist/flags/FlagProvider.js.map +1 -1
  183. package/dist/flags/feature-flags.d.ts +1 -1
  184. package/dist/flags/feature-flags.js +1 -1
  185. package/dist/flags/store.d.ts +1 -1
  186. package/dist/flags/store.js +0 -1
  187. package/dist/flags/store.js.map +1 -1
  188. package/dist/{helpers-zmC44Mcu.d.ts → helpers-vlnRvNJv.d.ts} +1 -2
  189. package/dist/index-CAFaKBs_.d.ts +8 -0
  190. package/dist/index-COt7nfC9.d.ts +2 -0
  191. package/dist/index-DvqHpiuh.d.ts +16 -0
  192. package/dist/index.d.ts +37 -31
  193. package/dist/index.js +14 -2
  194. package/dist/kv/constants.d.ts +1 -1
  195. package/dist/kv/constants.js.map +1 -1
  196. package/dist/kv/dotprops.js.map +1 -1
  197. package/dist/kv/kv.d.ts +0 -1
  198. package/dist/kv/kv.js +1 -1
  199. package/dist/kv/kv.js.map +1 -1
  200. package/dist/kv/serde.d.ts +1 -2
  201. package/dist/kv/serde.js +27 -27
  202. package/dist/kv/serde.js.map +1 -1
  203. package/dist/{label-DqGRqodo.d.ts → label-DClaYktn.d.ts} +1 -2
  204. package/dist/logger/DefaultLogger.d.ts +0 -1
  205. package/dist/logger/DefaultLogger.js +1 -1
  206. package/dist/logger/Logger.d.ts +0 -1
  207. package/dist/logger/Logger.js +1 -1
  208. package/dist/logger/NoopLogger.d.ts +0 -1
  209. package/dist/logger/NoopLogger.js.map +1 -1
  210. package/dist/{media-gallery-Ca8es-eB.d.ts → media-gallery-z2Snzz-u.d.ts} +1 -2
  211. package/dist/plugins/CompilerPlugin.d.ts +1 -1
  212. package/dist/plugins/CompilerPlugin.js +2 -2
  213. package/dist/plugins/CompilerPlugin.js.map +1 -1
  214. package/dist/plugins/PluginCommon.d.ts +1 -1
  215. package/dist/plugins/PluginCommon.js +1 -1
  216. package/dist/plugins/PluginCommon.js.map +1 -1
  217. package/dist/plugins/RuntimePlugin.d.ts +1 -1
  218. package/dist/plugins/RuntimePlugin.js +2 -2
  219. package/dist/plugins/RuntimePlugin.js.map +1 -1
  220. package/dist/plugins/index.d.ts +1 -1
  221. package/dist/plugins/index.js +1 -1
  222. package/dist/plugins/plugin-runtime/CommandKitPluginRuntime.d.ts +1 -1
  223. package/dist/plugins/plugin-runtime/CommandKitPluginRuntime.js +1 -1
  224. package/dist/plugins/plugin-runtime/CompilerPluginRuntime.d.ts +1 -1
  225. package/dist/plugins/plugin-runtime/CompilerPluginRuntime.js +1 -1
  226. package/dist/plugins/plugin-runtime/builtin/CommonDirectiveTransformer.d.ts +1 -1
  227. package/dist/plugins/plugin-runtime/builtin/CommonDirectiveTransformer.js +1 -1
  228. package/dist/plugins/plugin-runtime/builtin/MacroPlugin.d.ts +1 -2
  229. package/dist/plugins/plugin-runtime/builtin/MacroPlugin.js +1 -1
  230. package/dist/plugins/plugin-runtime/runtime.d.ts +1 -1
  231. package/dist/plugins/types.d.ts +1 -1
  232. package/dist/{poll-DQ6DX_Tt.d.ts → poll-D2QDStsw.d.ts} +4 -14
  233. package/dist/radio-CJH_N4lq.d.ts +20 -0
  234. package/dist/{section-Q8nwx_-q.d.ts → section-DrFBT5b-.d.ts} +1 -2
  235. package/dist/{separator-B8P-kdIK.d.ts → separator-BVm3w6yd.d.ts} +1 -2
  236. package/dist/{signals-CBXwugBW.d.ts → signals-DRMDrCOn.d.ts} +1 -1
  237. package/dist/{text-display-CL9C2yMc.d.ts → text-display-BG0nNqy3.d.ts} +1 -2
  238. package/dist/{types-DZy7U-Ld.d.ts → types-ur7SvktF.d.ts} +1 -1
  239. package/dist/types.d.ts +1 -1
  240. package/dist/utils/colors.d.ts +1 -3
  241. package/dist/utils/colors.js +0 -1
  242. package/dist/utils/colors.js.map +1 -1
  243. package/dist/utils/constants.d.ts +2 -2
  244. package/dist/utils/constants.js +19 -0
  245. package/dist/utils/constants.js.map +1 -1
  246. package/dist/utils/dev-hooks.d.ts +1 -1
  247. package/dist/utils/dev-hooks.js +1 -1
  248. package/dist/utils/error-codes.js +15 -0
  249. package/dist/utils/error-codes.js.map +1 -1
  250. package/dist/utils/resolve-file-url.js +2 -2
  251. package/dist/utils/resolve-file-url.js.map +1 -1
  252. package/dist/utils/types-package.d.ts +6 -2
  253. package/dist/utils/types-package.js +31 -38
  254. package/dist/utils/types-package.js.map +1 -1
  255. package/dist/utils/useful-stuff/async-queue.js.map +1 -1
  256. package/dist/utils/useful-stuff/mutex.js.map +1 -1
  257. package/dist/utils/useful-stuff/ratelimiter.js +4 -1
  258. package/dist/utils/useful-stuff/ratelimiter.js.map +1 -1
  259. package/dist/utils/useful-stuff/semaphore.js.map +1 -1
  260. package/dist/utils/utilities.js +1 -1
  261. package/dist/utils/warning.d.ts +1 -5
  262. package/dist/utils/warning.js.map +1 -1
  263. package/dist/version.js +1 -1
  264. package/dist/version.js.map +1 -1
  265. package/package.json +17 -17
  266. package/dist/CommandsRouter-DiNoF0dq.d.ts +0 -145
  267. package/dist/commandkit-Bh7C1_c7.js.map +0 -1
  268. package/dist/index-BIsCUWAs.d.ts +0 -1
  269. package/dist/index-CwHYpK-f.d.ts +0 -1
  270. package/dist/index-DHrsNvX1.d.ts +0 -1
  271. /package/dist/{chunk-BE-pF4vm.js → rolldown-runtime-C_NdSu1c.js} +0 -0
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_chunk = require('../../chunk-BE-pF4vm.js');
3
2
  let discord_js = require("discord.js");
4
3
  let node_fs = require("node:fs");
5
4
  let node_path = require("node:path");
6
5
  let node_fs_promises = require("node:fs/promises");
7
6
 
8
7
  //#region src/app/router/CommandsRouter.ts
8
+ const ROOT_NODE_ID = "__commandkit_router_root__";
9
9
  /**
10
10
  * @private
11
11
  * @internal
@@ -32,9 +32,35 @@ const COMMAND_PATTERN = /^([^+().][^().]*)\.(m|c)?(j|t)sx?$/;
32
32
  */
33
33
  const CATEGORY_PATTERN = /^\(.+\)$/;
34
34
  /**
35
+ * @private
36
+ * @internal
37
+ */
38
+ const COMMAND_DIRECTORY_PATTERN = /^\[([^\][\\\/]+)\]$/;
39
+ /**
40
+ * @private
41
+ * @internal
42
+ */
43
+ const GROUP_DIRECTORY_PATTERN = /^\{([^}{\\\/]+)\}$/;
44
+ /**
45
+ * @private
46
+ * @internal
47
+ */
48
+ const COMMAND_DEFINITION_PATTERN = /^command\.(m|c)?(j|t)sx?$/;
49
+ /**
50
+ * @private
51
+ * @internal
52
+ */
53
+ const GROUP_DEFINITION_PATTERN = /^group\.(m|c)?(j|t)sx?$/;
54
+ /**
55
+ * @private
56
+ * @internal
57
+ */
58
+ const SUBCOMMAND_FILE_PATTERN = /^([^+().][^().]*)\.subcommand\.(m|c)?(j|t)sx?$/;
59
+ /**
35
60
  * Handles discovery and parsing of command and middleware files in the filesystem.
36
61
  */
37
62
  var CommandsRouter = class {
63
+ options;
38
64
  /**
39
65
  * @private
40
66
  * @internal
@@ -46,6 +72,21 @@ var CommandsRouter = class {
46
72
  */
47
73
  middlewares = new discord_js.Collection();
48
74
  /**
75
+ * @private
76
+ * @internal
77
+ */
78
+ treeNodes = new discord_js.Collection();
79
+ /**
80
+ * @private
81
+ * @internal
82
+ */
83
+ compiledRoutes = new discord_js.Collection();
84
+ /**
85
+ * @private
86
+ * @internal
87
+ */
88
+ diagnostics = [];
89
+ /**
49
90
  * Creates a new CommandsRouter instance.
50
91
  * @param options - Configuration options for the router
51
92
  */
@@ -53,12 +94,16 @@ var CommandsRouter = class {
53
94
  this.options = options;
54
95
  }
55
96
  /**
56
- * Populates the router with existing command and middleware data.
97
+ * Populates the router with existing command, middleware, and tree data.
57
98
  * @param data - Parsed command data to populate with
58
99
  */
59
100
  populate(data) {
101
+ this.clear();
60
102
  for (const [id, command] of Object.entries(data.commands)) this.commands.set(id, command);
61
103
  for (const [id, middleware] of Object.entries(data.middlewares)) this.middlewares.set(id, middleware);
104
+ for (const [id, node] of Object.entries(data.treeNodes ?? {})) this.treeNodes.set(id, node);
105
+ for (const [key, route] of Object.entries(data.compiledRoutes ?? {})) this.compiledRoutes.set(key, route);
106
+ this.diagnostics = [...data.diagnostics ?? []];
62
107
  }
63
108
  /**
64
109
  * Checks if the configured entrypoint path exists.
@@ -89,64 +134,425 @@ var CommandsRouter = class {
89
134
  return CATEGORY_PATTERN.test(name);
90
135
  }
91
136
  /**
92
- * Clears all loaded commands and middleware.
137
+ * @private
138
+ * @internal
139
+ */
140
+ isCommandDirectory(name) {
141
+ return COMMAND_DIRECTORY_PATTERN.test(name);
142
+ }
143
+ /**
144
+ * @private
145
+ * @internal
146
+ */
147
+ isGroupDirectory(name) {
148
+ return GROUP_DIRECTORY_PATTERN.test(name);
149
+ }
150
+ /**
151
+ * @private
152
+ * @internal
153
+ */
154
+ isCommandDefinition(name) {
155
+ return COMMAND_DEFINITION_PATTERN.test(name);
156
+ }
157
+ /**
158
+ * @private
159
+ * @internal
160
+ */
161
+ isGroupDefinition(name) {
162
+ return GROUP_DEFINITION_PATTERN.test(name);
163
+ }
164
+ /**
165
+ * @private
166
+ * @internal
167
+ */
168
+ isSubcommandFile(name) {
169
+ return SUBCOMMAND_FILE_PATTERN.test(name);
170
+ }
171
+ /**
172
+ * Clears all loaded commands, middleware, and compiled tree data.
93
173
  */
94
174
  clear() {
95
175
  this.commands.clear();
96
176
  this.middlewares.clear();
177
+ this.treeNodes.clear();
178
+ this.compiledRoutes.clear();
179
+ this.diagnostics = [];
97
180
  }
98
181
  /**
99
182
  * Scans the filesystem for commands and middleware files.
100
183
  * @returns Parsed command data
101
184
  */
102
185
  async scan() {
103
- const entries = await (0, node_fs_promises.readdir)(this.options.entrypoint, { withFileTypes: true });
104
- for (const entry of entries) {
105
- if (entry.name.startsWith("_")) continue;
106
- const fullPath = (0, node_path.join)(this.options.entrypoint, entry.name);
107
- if (entry.isDirectory()) {
108
- const category = this.isCategory(entry.name) ? entry.name.slice(1, -1) : null;
109
- await this.traverse(fullPath, category);
110
- } else await this.handle(entry);
111
- }
186
+ this.clear();
187
+ this.initializeRootNode();
188
+ await this.traverseDirectory(this.options.entrypoint, "normal", null, ROOT_NODE_ID);
112
189
  await this.applyMiddlewares();
190
+ this.compileTree();
113
191
  return this.toJSON();
114
192
  }
115
193
  /**
116
- * Gets the raw command and middleware collections.
117
- * @returns Object containing commands and middlewares collections
194
+ * Incrementally updates only the top-level command subtree affected by a file change.
195
+ * Falls back to a full scan when the changed path cannot be safely scoped.
196
+ */
197
+ async scanIncremental(changedPath, _changeType = "change") {
198
+ var _topLevelToken$match;
199
+ const normalizedPath = (0, node_path.normalize)(changedPath);
200
+ if (!this.isWithinPath(this.options.entrypoint, normalizedPath)) return this.toJSON();
201
+ const relativePath = this.replaceEntrypoint(normalizedPath).replace(/^[/\\]/, "").split(/[/\\]/).filter(Boolean);
202
+ if (!relativePath.length) return this.scan();
203
+ const topLevelToken = relativePath[0];
204
+ if (!this.isCommandDirectory(topLevelToken)) return this.scan();
205
+ const commandName = (_topLevelToken$match = topLevelToken.match(COMMAND_DIRECTORY_PATTERN)) === null || _topLevelToken$match === void 0 ? void 0 : _topLevelToken$match[1];
206
+ if (!commandName) return this.scan();
207
+ this.ensureRootNode();
208
+ const commandRootDirectory = (0, node_path.join)(this.options.entrypoint, topLevelToken);
209
+ this.pruneCommandSubtree(commandName, commandRootDirectory);
210
+ if ((0, node_fs.existsSync)(commandRootDirectory)) await this.traverseDirectory(commandRootDirectory, "command", null, ROOT_NODE_ID, commandName);
211
+ await this.applyMiddlewares();
212
+ this.compileTree();
213
+ return this.toJSON();
214
+ }
215
+ /**
216
+ * Gets the raw command, middleware, and compiled tree collections.
217
+ * @returns Object containing router collections
118
218
  */
119
219
  getData() {
120
220
  return {
121
221
  commands: this.commands,
122
- middlewares: this.middlewares
222
+ middlewares: this.middlewares,
223
+ treeNodes: this.treeNodes,
224
+ compiledRoutes: this.compiledRoutes,
225
+ diagnostics: this.diagnostics
226
+ };
227
+ }
228
+ /**
229
+ * Gets only the internal command tree and compiled route data.
230
+ * @returns Object containing tree data
231
+ */
232
+ getTreeData() {
233
+ return {
234
+ treeNodes: this.treeNodes,
235
+ compiledRoutes: this.compiledRoutes,
236
+ diagnostics: this.diagnostics
123
237
  };
124
238
  }
125
239
  /**
126
240
  * Converts the loaded data to a JSON-serializable format.
127
- * @returns Plain object with commands and middlewares
241
+ * @returns Plain object with commands, middleware, and tree data
128
242
  */
129
243
  toJSON() {
130
244
  return {
131
245
  commands: Object.fromEntries(this.commands.entries()),
132
- middlewares: Object.fromEntries(this.middlewares.entries())
246
+ middlewares: Object.fromEntries(this.middlewares.entries()),
247
+ treeNodes: Object.fromEntries(this.treeNodes.entries()),
248
+ compiledRoutes: Object.fromEntries(this.compiledRoutes.entries()),
249
+ diagnostics: this.diagnostics
133
250
  };
134
251
  }
135
252
  /**
136
253
  * @private
137
254
  * @internal
138
255
  */
139
- async traverse(path, category) {
256
+ initializeRootNode() {
257
+ this.treeNodes.set(ROOT_NODE_ID, {
258
+ id: ROOT_NODE_ID,
259
+ source: "root",
260
+ kind: "root",
261
+ token: "",
262
+ route: [],
263
+ category: null,
264
+ parentId: null,
265
+ childIds: [],
266
+ directoryPath: this.options.entrypoint,
267
+ definitionPath: null,
268
+ relativePath: "",
269
+ shorthand: false,
270
+ executable: false
271
+ });
272
+ }
273
+ /**
274
+ * @private
275
+ * @internal
276
+ */
277
+ ensureRootNode() {
278
+ if (!this.treeNodes.has(ROOT_NODE_ID)) this.initializeRootNode();
279
+ }
280
+ /**
281
+ * @private
282
+ * @internal
283
+ */
284
+ pruneCommandSubtree(commandName, commandRootDirectory) {
285
+ const normalizedRootDirectory = (0, node_path.normalize)(commandRootDirectory);
286
+ for (const [id, command] of this.commands.entries()) if (command.name === commandName || this.isWithinPath(normalizedRootDirectory, command.path) || this.isWithinPath(normalizedRootDirectory, command.parentPath)) this.commands.delete(id);
287
+ for (const [id, middleware] of this.middlewares.entries()) if (this.isWithinPath(normalizedRootDirectory, middleware.path) || this.isWithinPath(normalizedRootDirectory, middleware.parentPath)) this.middlewares.delete(id);
288
+ const nodeIdsToDelete = /* @__PURE__ */ new Set();
289
+ for (const [id, node] of this.treeNodes.entries()) {
290
+ if (id === ROOT_NODE_ID) continue;
291
+ if (node.route[0] === commandName || this.isWithinPath(normalizedRootDirectory, node.directoryPath) || node.definitionPath && this.isWithinPath(normalizedRootDirectory, node.definitionPath)) nodeIdsToDelete.add(id);
292
+ }
293
+ if (nodeIdsToDelete.size) {
294
+ for (const id of nodeIdsToDelete) this.treeNodes.delete(id);
295
+ for (const node of this.treeNodes.values()) node.childIds = node.childIds.filter((childId) => {
296
+ return !nodeIdsToDelete.has(childId);
297
+ });
298
+ }
299
+ }
300
+ /**
301
+ * @private
302
+ * @internal
303
+ */
304
+ async traverseDirectory(path, state, category, parentId, token) {
305
+ let node = null;
306
+ if (state === "command") {
307
+ node = this.createTreeNode({
308
+ source: "directory",
309
+ token,
310
+ category,
311
+ parentId,
312
+ directoryPath: path,
313
+ definitionPath: null,
314
+ shorthand: false
315
+ });
316
+ if (!node) return;
317
+ } else if (state === "group") {
318
+ node = this.createTreeNode({
319
+ source: "group",
320
+ token,
321
+ category,
322
+ parentId,
323
+ directoryPath: path,
324
+ definitionPath: null,
325
+ shorthand: false
326
+ });
327
+ if (!node) return;
328
+ }
329
+ const currentNodeId = node ? node.id : parentId;
140
330
  const entries = await (0, node_fs_promises.readdir)(path, { withFileTypes: true });
141
331
  for (const entry of entries) {
142
332
  if (entry.name.startsWith("_")) continue;
333
+ const fullPath = (0, node_path.join)(path, entry.name);
143
334
  if (entry.isFile()) {
144
- if (this.isCommand(entry.name) || this.isMiddleware(entry.name)) await this.handle(entry, category);
145
- } else if (entry.isDirectory() && this.isCategory(entry.name) && category) {
146
- const nestedCategory = this.isCategory(entry.name) ? `${category}:${entry.name.slice(1, -1)}` : null;
147
- await this.traverse((0, node_path.join)(path, entry.name), nestedCategory);
335
+ if (state === "command") {
336
+ if (this.isCommandDefinition(entry.name)) {
337
+ node.definitionPath = fullPath;
338
+ node.relativePath = this.replaceEntrypoint(fullPath);
339
+ continue;
340
+ }
341
+ if (this.isSubcommandFile(entry.name)) {
342
+ this.createTreeNode({
343
+ source: "shorthand",
344
+ token: entry.name.match(SUBCOMMAND_FILE_PATTERN)[1],
345
+ category,
346
+ parentId: currentNodeId,
347
+ directoryPath: path,
348
+ definitionPath: fullPath,
349
+ shorthand: true
350
+ });
351
+ continue;
352
+ }
353
+ if (this.isMiddleware(entry.name)) {
354
+ await this.handle(entry, category);
355
+ continue;
356
+ }
357
+ if (this.isCommand(entry.name)) this.addDiagnostic("UNSUPPORTED_FILE_IN_COMMAND_DIRECTORY", "Only command.ts, middleware files, and subcommand shorthand files are supported inside a command directory.", fullPath);
358
+ } else if (state === "group") {
359
+ if (this.isGroupDefinition(entry.name)) {
360
+ node.definitionPath = fullPath;
361
+ node.relativePath = this.replaceEntrypoint(fullPath);
362
+ continue;
363
+ }
364
+ if (this.isSubcommandFile(entry.name)) {
365
+ this.createTreeNode({
366
+ source: "shorthand",
367
+ token: entry.name.match(SUBCOMMAND_FILE_PATTERN)[1],
368
+ category,
369
+ parentId: currentNodeId,
370
+ directoryPath: path,
371
+ definitionPath: fullPath,
372
+ shorthand: true
373
+ });
374
+ continue;
375
+ }
376
+ if (this.isMiddleware(entry.name)) {
377
+ await this.handle(entry, category);
378
+ continue;
379
+ }
380
+ if (this.isCommand(entry.name)) this.addDiagnostic("UNSUPPORTED_FILE_IN_GROUP_DIRECTORY", "Only group.ts, middleware files, and subcommand shorthand files are supported inside a group directory.", fullPath);
381
+ } else {
382
+ if (this.isSubcommandFile(entry.name)) {
383
+ if (currentNodeId === ROOT_NODE_ID) this.addDiagnostic("ORPHAN_SUBCOMMAND_FILE", "Subcommand shorthand files must be nested inside a command or group directory.", fullPath);
384
+ else this.createTreeNode({
385
+ source: "shorthand",
386
+ token: entry.name.match(SUBCOMMAND_FILE_PATTERN)[1],
387
+ category,
388
+ parentId: currentNodeId,
389
+ directoryPath: path,
390
+ definitionPath: fullPath,
391
+ shorthand: true
392
+ });
393
+ continue;
394
+ }
395
+ if (this.isCommand(entry.name) || this.isMiddleware(entry.name)) {
396
+ const result = await this.handle(entry, category);
397
+ if (result.command) this.createFlatCommandNode(result.command);
398
+ }
399
+ }
400
+ continue;
401
+ }
402
+ if (!entry.isDirectory()) continue;
403
+ if (this.isCommandDirectory(entry.name)) {
404
+ if (state === "command" || state === "group") await this.traverseDirectory(fullPath, "command", category, currentNodeId, entry.name.match(COMMAND_DIRECTORY_PATTERN)[1]);
405
+ else if (currentNodeId !== ROOT_NODE_ID) this.addDiagnostic("NESTED_COMMAND_NOT_ALLOWED", "Command directories cannot be nested under group or subcommand directories unless they are part of a hierarchical structure.", fullPath);
406
+ else await this.traverseDirectory(fullPath, "command", category, ROOT_NODE_ID, entry.name.match(COMMAND_DIRECTORY_PATTERN)[1]);
407
+ continue;
148
408
  }
409
+ if (this.isGroupDirectory(entry.name)) {
410
+ if (currentNodeId === ROOT_NODE_ID) this.addDiagnostic("ROOT_GROUP_NOT_ALLOWED", "Group directories must be nested inside a command directory.", fullPath);
411
+ else await this.traverseDirectory(fullPath, "group", category, currentNodeId, entry.name.match(GROUP_DIRECTORY_PATTERN)[1]);
412
+ continue;
413
+ }
414
+ if (this.isCategory(entry.name)) {
415
+ const nestedCategory = category ? `${category}:${entry.name.slice(1, -1)}` : entry.name.slice(1, -1);
416
+ await this.traverseDirectory(fullPath, "normal", nestedCategory, currentNodeId);
417
+ continue;
418
+ }
419
+ await this.traverseDirectory(fullPath, "normal", category, currentNodeId);
149
420
  }
421
+ if (state === "command" && node && !node.definitionPath) this.addDiagnostic("MISSING_COMMAND_DEFINITION", "Command directories must include a command.ts file.", path);
422
+ else if (state === "group" && node && !node.definitionPath) this.addDiagnostic("MISSING_GROUP_DEFINITION", "Group directories must include a group.ts file.", path);
423
+ }
424
+ /**
425
+ * @private
426
+ * @internal
427
+ */
428
+ createFlatCommandNode(command) {
429
+ this.createTreeNode({
430
+ id: command.id,
431
+ source: "flat",
432
+ token: command.name,
433
+ category: command.category,
434
+ parentId: ROOT_NODE_ID,
435
+ directoryPath: command.parentPath,
436
+ definitionPath: command.path,
437
+ shorthand: false
438
+ });
439
+ }
440
+ /**
441
+ * @private
442
+ * @internal
443
+ */
444
+ createTreeNode(options) {
445
+ const parent = this.treeNodes.get(options.parentId);
446
+ if (!parent) {
447
+ this.addDiagnostic("MISSING_PARENT_NODE", `Unable to create command tree node "${options.token}" because its parent node was not found.`, options.directoryPath);
448
+ return null;
449
+ }
450
+ if (parent.childIds.some((childId) => {
451
+ var _this$treeNodes$get;
452
+ return ((_this$treeNodes$get = this.treeNodes.get(childId)) === null || _this$treeNodes$get === void 0 ? void 0 : _this$treeNodes$get.token) === options.token;
453
+ })) {
454
+ this.addDiagnostic("DUPLICATE_SIBLING_TOKEN", `Duplicate command token "${options.token}" found under the same parent.`, options.definitionPath ?? options.directoryPath);
455
+ return null;
456
+ }
457
+ const route = [...parent.route, options.token];
458
+ const node = {
459
+ id: options.id ?? crypto.randomUUID(),
460
+ source: options.source,
461
+ kind: this.resolveNodeKind(options.source, route.length),
462
+ token: options.token,
463
+ route,
464
+ category: options.category,
465
+ parentId: options.parentId,
466
+ childIds: [],
467
+ directoryPath: options.directoryPath,
468
+ definitionPath: options.definitionPath,
469
+ relativePath: this.replaceEntrypoint(options.definitionPath ?? options.directoryPath),
470
+ shorthand: options.shorthand,
471
+ executable: false
472
+ };
473
+ this.treeNodes.set(node.id, node);
474
+ parent.childIds.push(node.id);
475
+ return node;
476
+ }
477
+ /**
478
+ * @private
479
+ * @internal
480
+ */
481
+ resolveNodeKind(source, depth) {
482
+ switch (source) {
483
+ case "root": return "root";
484
+ case "flat": return "flat";
485
+ case "group": return "group";
486
+ case "shorthand": return "subcommand";
487
+ case "directory": return depth === 1 ? "command" : "subcommand";
488
+ default: return source;
489
+ }
490
+ }
491
+ /**
492
+ * @private
493
+ * @internal
494
+ */
495
+ compileTree() {
496
+ this.compiledRoutes.clear();
497
+ for (const node of this.treeNodes.values()) {
498
+ if (node.id === ROOT_NODE_ID) continue;
499
+ const hasChildren = node.childIds.length > 0;
500
+ node.executable = !!node.definitionPath && node.kind !== "group" && !hasChildren;
501
+ if (hasChildren && node.definitionPath && node.kind !== "group") this.addDiagnostic("NON_LEAF_NODE_MAY_HAVE_HANDLERS", `Hierarchical node "${node.route.join(".")}" has child nodes. Ensure its command.ts file does not export chatInput, message, or autocomplete handlers. Executable handlers must be defined on leaf nodes.`, node.definitionPath);
502
+ if (node.kind === "subcommand" && hasChildren) this.addDiagnostic("SUBCOMMAND_CANNOT_HAVE_CHILDREN", `Subcommand "${node.route.join(".")}" cannot contain child command nodes.`, node.definitionPath ?? node.directoryPath);
503
+ if (node.kind === "command") {
504
+ const childKinds = new Set(node.childIds.map((childId) => {
505
+ var _this$treeNodes$get2;
506
+ return (_this$treeNodes$get2 = this.treeNodes.get(childId)) === null || _this$treeNodes$get2 === void 0 ? void 0 : _this$treeNodes$get2.kind;
507
+ }).filter(Boolean));
508
+ if (childKinds.has("group") && childKinds.has("subcommand")) this.addDiagnostic("MIXED_ROOT_CHILDREN", `Command "${node.route.join(".")}" cannot mix direct subcommands and subcommand groups.`, node.definitionPath ?? node.directoryPath);
509
+ }
510
+ if (!node.executable || !node.definitionPath) continue;
511
+ const key = node.route.join(".");
512
+ const routeKind = node.kind;
513
+ this.compiledRoutes.set(key, {
514
+ id: node.id,
515
+ key,
516
+ kind: routeKind,
517
+ token: node.token,
518
+ route: node.route,
519
+ category: node.category,
520
+ definitionPath: node.definitionPath,
521
+ relativePath: this.replaceEntrypoint(node.definitionPath),
522
+ nodeId: node.id,
523
+ middlewares: this.collectCompiledMiddlewares(node)
524
+ });
525
+ }
526
+ }
527
+ /**
528
+ * @private
529
+ * @internal
530
+ */
531
+ collectCompiledMiddlewares(node) {
532
+ const allMiddlewares = Array.from(this.middlewares.values());
533
+ const globalMiddlewares = allMiddlewares.filter((middleware) => middleware.global).map((middleware) => middleware.id);
534
+ const directoryMiddlewares = allMiddlewares.filter((middleware) => {
535
+ return !middleware.global && !middleware.command && middleware.parentPath === node.directoryPath;
536
+ }).map((middleware) => middleware.id);
537
+ const commandSpecificMiddlewares = allMiddlewares.filter((middleware) => {
538
+ return middleware.command === node.token && middleware.parentPath === node.directoryPath;
539
+ }).map((middleware) => middleware.id);
540
+ return [
541
+ ...globalMiddlewares,
542
+ ...directoryMiddlewares,
543
+ ...commandSpecificMiddlewares
544
+ ];
545
+ }
546
+ /**
547
+ * @private
548
+ * @internal
549
+ */
550
+ addDiagnostic(code, message, path) {
551
+ this.diagnostics.push({
552
+ code,
553
+ message,
554
+ path: (0, node_path.normalize)(path)
555
+ });
150
556
  }
151
557
  /**
152
558
  * @private
@@ -166,7 +572,9 @@ var CommandsRouter = class {
166
572
  middlewares: []
167
573
  };
168
574
  this.commands.set(command.id, command);
169
- } else if (this.isMiddleware(name)) {
575
+ return { command };
576
+ }
577
+ if (this.isMiddleware(name)) {
170
578
  var _name$match;
171
579
  const middleware = {
172
580
  id: crypto.randomUUID(),
@@ -178,7 +586,9 @@ var CommandsRouter = class {
178
586
  command: COMMAND_MIDDLEWARE_PATTERN.test(name) ? ((_name$match = name.match(COMMAND_MIDDLEWARE_PATTERN)) === null || _name$match === void 0 ? void 0 : _name$match[1]) || null : null
179
587
  };
180
588
  this.middlewares.set(middleware.id, middleware);
589
+ return { middleware };
181
590
  }
591
+ return {};
182
592
  }
183
593
  /**
184
594
  * @private
@@ -189,7 +599,9 @@ var CommandsRouter = class {
189
599
  const commandPath = command.parentPath;
190
600
  const allMiddlewares = Array.from(this.middlewares.values());
191
601
  const commandSpecificMiddlewares = allMiddlewares.filter((middleware) => middleware.command === command.name).map((middleware) => middleware.id);
192
- const directorySpecificMiddlewares = allMiddlewares.filter((middleware) => !middleware.global && !middleware.command && middleware.parentPath === commandPath).map((middleware) => middleware.id);
602
+ const directorySpecificMiddlewares = allMiddlewares.filter((middleware) => {
603
+ return !middleware.global && !middleware.command && middleware.parentPath === commandPath;
604
+ }).map((middleware) => middleware.id);
193
605
  command.middlewares = [
194
606
  ...allMiddlewares.filter((middleware) => middleware.global).map((middleware) => middleware.id),
195
607
  ...directorySpecificMiddlewares,
@@ -204,6 +616,15 @@ var CommandsRouter = class {
204
616
  replaceEntrypoint(path) {
205
617
  return (0, node_path.normalize)(path).replace(this.options.entrypoint, "");
206
618
  }
619
+ /**
620
+ * @private
621
+ * @internal
622
+ */
623
+ isWithinPath(basePath, targetPath) {
624
+ const rel = (0, node_path.relative)((0, node_path.normalize)(basePath), (0, node_path.normalize)(targetPath));
625
+ if (!rel) return true;
626
+ return !rel.startsWith("..") && !(0, node_path.isAbsolute)(rel);
627
+ }
207
628
  };
208
629
 
209
630
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"CommandsRouter.js","names":[],"sources":["../../../src/app/router/CommandsRouter.ts"],"sourcesContent":["import { Collection } from 'discord.js';\nimport { Dirent, existsSync } from 'node:fs';\nimport { readdir } from 'node:fs/promises';\nimport { basename, extname, join, normalize } from 'node:path';\n\n/**\n * Represents a command with its metadata and middleware associations.\n */\nexport interface Command {\n id: string;\n name: string;\n path: string;\n relativePath: string;\n parentPath: string;\n middlewares: Array<string>;\n category: string | null;\n}\n\n/**\n * Represents a middleware with its metadata and scope.\n */\nexport interface Middleware {\n id: string;\n name: string;\n path: string;\n relativePath: string;\n parentPath: string;\n global: boolean;\n command: string | null;\n}\n\n/**\n * Data structure containing parsed commands and middleware.\n */\nexport interface ParsedCommandData {\n commands: Record<string, Command>;\n middlewares: Record<string, Middleware>;\n}\n\n/**\n * Configuration options for the commands router.\n */\nexport interface CommandsRouterOptions {\n entrypoint: string;\n}\n\n/**\n * @private\n * @internal\n */\nconst MIDDLEWARE_PATTERN = /^\\+middleware\\.(m|c)?(j|t)sx?$/;\n\n/**\n * @private\n * @internal\n */\nconst COMMAND_MIDDLEWARE_PATTERN =\n /^\\+([^+().][^().]*)\\.middleware\\.(m|c)?(j|t)sx?$/;\n\n/**\n * @private\n * @internal\n */\nconst GLOBAL_MIDDLEWARE_PATTERN = /^\\+global-middleware\\.(m|c)?(j|t)sx?$/;\n\n/**\n * @private\n * @internal\n */\nconst COMMAND_PATTERN = /^([^+().][^().]*)\\.(m|c)?(j|t)sx?$/;\n\n/**\n * @private\n * @internal\n */\nconst CATEGORY_PATTERN = /^\\(.+\\)$/;\n\n/**\n * Handles discovery and parsing of command and middleware files in the filesystem.\n */\nexport class CommandsRouter {\n /**\n * @private\n * @internal\n */\n private commands = new Collection<string, Command>();\n\n /**\n * @private\n * @internal\n */\n private middlewares = new Collection<string, Middleware>();\n\n /**\n * Creates a new CommandsRouter instance.\n * @param options - Configuration options for the router\n */\n public constructor(private readonly options: CommandsRouterOptions) {}\n\n /**\n * Populates the router with existing command and middleware data.\n * @param data - Parsed command data to populate with\n */\n public populate(data: ParsedCommandData) {\n for (const [id, command] of Object.entries(data.commands)) {\n this.commands.set(id, command);\n }\n\n for (const [id, middleware] of Object.entries(data.middlewares)) {\n this.middlewares.set(id, middleware);\n }\n }\n\n /**\n * Checks if the configured entrypoint path exists.\n * @returns True if the path exists\n */\n public isValidPath(): boolean {\n return existsSync(this.options.entrypoint);\n }\n\n /**\n * @private\n * @internal\n */\n private isCommand(name: string): boolean {\n return COMMAND_PATTERN.test(name);\n }\n\n /**\n * @private\n * @internal\n */\n private isMiddleware(name: string): boolean {\n return (\n MIDDLEWARE_PATTERN.test(name) ||\n GLOBAL_MIDDLEWARE_PATTERN.test(name) ||\n COMMAND_MIDDLEWARE_PATTERN.test(name)\n );\n }\n\n /**\n * @private\n * @internal\n */\n private isCategory(name: string): boolean {\n return CATEGORY_PATTERN.test(name);\n }\n\n /**\n * Clears all loaded commands and middleware.\n */\n public clear() {\n this.commands.clear();\n this.middlewares.clear();\n }\n\n /**\n * Scans the filesystem for commands and middleware files.\n * @returns Parsed command data\n */\n public async scan() {\n const entries = await readdir(this.options.entrypoint, {\n withFileTypes: true,\n });\n\n for (const entry of entries) {\n // ignore _ prefixed files\n if (entry.name.startsWith('_')) continue;\n\n const fullPath = join(this.options.entrypoint, entry.name);\n\n if (entry.isDirectory()) {\n const category = this.isCategory(entry.name)\n ? entry.name.slice(1, -1)\n : null;\n\n await this.traverse(fullPath, category);\n } else {\n await this.handle(entry);\n }\n }\n\n await this.applyMiddlewares();\n\n return this.toJSON();\n }\n\n /**\n * Gets the raw command and middleware collections.\n * @returns Object containing commands and middlewares collections\n */\n public getData() {\n return {\n commands: this.commands,\n middlewares: this.middlewares,\n };\n }\n\n /**\n * Converts the loaded data to a JSON-serializable format.\n * @returns Plain object with commands and middlewares\n */\n public toJSON() {\n return {\n commands: Object.fromEntries(this.commands.entries()),\n middlewares: Object.fromEntries(this.middlewares.entries()),\n };\n }\n\n /**\n * @private\n * @internal\n */\n private async traverse(path: string, category: string | null) {\n const entries = await readdir(path, {\n withFileTypes: true,\n });\n\n for (const entry of entries) {\n // ignore _ prefixed files\n if (entry.name.startsWith('_')) continue;\n\n if (entry.isFile()) {\n if (this.isCommand(entry.name) || this.isMiddleware(entry.name)) {\n await this.handle(entry, category);\n }\n } else if (\n entry.isDirectory() &&\n this.isCategory(entry.name) &&\n category\n ) {\n // nested category\n const nestedCategory = this.isCategory(entry.name)\n ? `${category}:${entry.name.slice(1, -1)}`\n : null;\n await this.traverse(join(path, entry.name), nestedCategory);\n }\n\n // TODO: handle subcommands\n }\n }\n\n /**\n * @private\n * @internal\n */\n private async handle(entry: Dirent, category: string | null = null) {\n const name = entry.name;\n const path = join(entry.parentPath, entry.name);\n\n if (this.isCommand(name)) {\n const command: Command = {\n id: crypto.randomUUID(),\n name: basename(path, extname(path)),\n path,\n category,\n parentPath: entry.parentPath,\n relativePath: this.replaceEntrypoint(path),\n middlewares: [],\n };\n\n this.commands.set(command.id, command);\n } else if (this.isMiddleware(name)) {\n const middleware: Middleware = {\n id: crypto.randomUUID(),\n name: basename(path, extname(path)),\n path,\n relativePath: this.replaceEntrypoint(path),\n parentPath: entry.parentPath,\n global: GLOBAL_MIDDLEWARE_PATTERN.test(name),\n command: COMMAND_MIDDLEWARE_PATTERN.test(name)\n ? name.match(COMMAND_MIDDLEWARE_PATTERN)?.[1] || null\n : null,\n };\n\n this.middlewares.set(middleware.id, middleware);\n }\n }\n\n /**\n * @private\n * @internal\n */\n private applyMiddlewares() {\n this.commands.forEach((command) => {\n const commandPath = command.parentPath;\n const allMiddlewares = Array.from(this.middlewares.values());\n\n const commandSpecificMiddlewares = allMiddlewares\n .filter((middleware) => middleware.command === command.name)\n .map((middleware) => middleware.id);\n\n const directorySpecificMiddlewares = allMiddlewares\n .filter(\n (middleware) =>\n !middleware.global &&\n !middleware.command &&\n middleware.parentPath === commandPath,\n )\n .map((middleware) => middleware.id);\n\n const globalMiddlewares = allMiddlewares\n .filter((middleware) => middleware.global)\n .map((middleware) => middleware.id);\n\n command.middlewares = [\n ...globalMiddlewares,\n ...directorySpecificMiddlewares,\n ...commandSpecificMiddlewares,\n ];\n });\n }\n\n /**\n * @private\n * @internal\n */\n private replaceEntrypoint(path: string) {\n const normalized = normalize(path);\n return normalized.replace(this.options.entrypoint, '');\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CommandsRouter.js","names":[],"sources":[],"mappings":""}
@@ -1,2 +1,2 @@
1
- import { i as ParsedEvent, n as EventsRouterOptions, r as EventsTree, t as EventsRouter } from "../../EventsRouter-EuuSu6NH.js";
2
- export { EventsRouter, EventsRouterOptions, EventsTree, ParsedEvent };
1
+ import { a as ParsedEvent, i as EventsTree, n as EventsRouterFileChangeType, r as EventsRouterOptions, t as EventsRouter } from "../../EventsRouter-Bt63ZuEF.js";
2
+ export { EventsRouter, EventsRouterFileChangeType, EventsRouterOptions, EventsTree, ParsedEvent };