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.
- package/README.md +1 -1
- package/cache.cjs +2 -0
- package/cache.d.ts +1 -0
- package/dist/{ActionRow-Bt9qi0Mb.d.ts → ActionRow-DSh9roc5.d.ts} +2 -3
- package/dist/{Button-DxJLcZIU.d.ts → Button-BPsE5ju0.d.ts} +5 -6
- package/dist/{ButtonKit-BfcyvWfj.d.ts → ButtonKit-CNPmVg3h.d.ts} +2 -3
- package/dist/{ChannelSelectMenuKit-DYkudikb.d.ts → ChannelSelectMenuKit-CcOdaLQ6.d.ts} +3 -4
- package/dist/CommandTree-qu-8oAEV.d.ts +55 -0
- package/dist/CommandsRouter-Co225Ae5.d.ts +242 -0
- package/dist/{EventInterceptor-D9JKMcfi.d.ts → EventInterceptor-wg378vJp.d.ts} +1 -2
- package/dist/{EventsRouter-EuuSu6NH.d.ts → EventsRouter-Bt63ZuEF.d.ts} +21 -2
- package/dist/{MentionableSelectMenuKit-Mu4xqP6B.d.ts → MentionableSelectMenuKit-8_Nkgn_a.d.ts} +3 -4
- package/dist/{MessageCommandParser-DPCbHXCS.d.ts → MessageCommandParser-BYbxHOSK.d.ts} +7 -2
- package/dist/{Modal-v9rrcMl-.d.ts → Modal-DbWK6VmV.d.ts} +5 -6
- package/dist/{ModalKit-XJSM65SV.d.ts → ModalKit-CnmUVpw-.d.ts} +2 -3
- package/dist/{RoleSelectMenuKit-CCjcp3HY.d.ts → RoleSelectMenuKit-Bei7DHqD.d.ts} +3 -4
- package/dist/{SelectMenu-CY0vvoSu.d.ts → SelectMenu-Bce_PClo.d.ts} +8 -9
- package/dist/{StringSelectMenuKit-G5nBTicX.d.ts → StringSelectMenuKit-CBeB9HqT.d.ts} +3 -4
- package/dist/TreeArtifact-D6FZ5SVd.d.ts +27 -0
- package/dist/{UserSelectMenuKit-D3SO_fXA.d.ts → UserSelectMenuKit-DZmeZ_Tp.d.ts} +3 -4
- package/dist/analytics/analytics-engine.d.ts +1 -1
- package/dist/analytics/analytics-engine.js +1 -1
- package/dist/analytics/analytics-provider.d.ts +1 -1
- package/dist/analytics/constants.js +0 -1
- package/dist/analytics/constants.js.map +1 -1
- package/dist/analytics/utils.js +1 -1
- package/dist/{analytics-engine-DnRsHBId.d.ts → analytics-engine-Bz1p7ud3.d.ts} +178 -30
- package/dist/app/commands/AppCommandRunner.d.ts +1 -1
- package/dist/app/commands/AppCommandRunner.js +1 -1
- package/dist/app/commands/Context.d.ts +1 -1
- package/dist/app/commands/Context.js +1 -1
- package/dist/app/commands/MessageCommandParser.d.ts +1 -1
- package/dist/app/commands/MessageCommandParser.js +79 -71
- package/dist/app/commands/MessageCommandParser.js.map +1 -1
- package/dist/app/commands/helpers.d.ts +1 -1
- package/dist/app/commands/helpers.js +0 -1
- package/dist/app/commands/helpers.js.map +1 -1
- package/dist/app/events/EventWorkerContext.d.ts +3 -3
- package/dist/app/events/EventWorkerContext.js +0 -1
- package/dist/app/events/EventWorkerContext.js.map +1 -1
- package/dist/app/handlers/AppCommandHandler.d.ts +1 -1
- package/dist/app/handlers/AppCommandHandler.js +1 -1
- package/dist/app/handlers/AppEventsHandler.d.ts +1 -1
- package/dist/app/handlers/AppEventsHandler.js +1 -1
- package/dist/app/index.d.ts +5 -5
- package/dist/app/index.js +1 -1
- package/dist/app/interrupt/signals.d.ts +1 -1
- package/dist/app/interrupt/signals.js.map +1 -1
- package/dist/app/middlewares/permissions.d.ts +1 -2
- package/dist/app/middlewares/permissions.js +1 -1
- package/dist/app/register/CommandRegistrar.d.ts +1 -1
- package/dist/app/register/CommandRegistrar.js +1 -1
- package/dist/app/router/CommandTree.d.ts +2 -0
- package/dist/app/router/CommandTree.js +1 -0
- package/dist/app/router/CommandsRouter.d.ts +2 -2
- package/dist/app/router/CommandsRouter.js +445 -24
- package/dist/app/router/CommandsRouter.js.map +1 -1
- package/dist/app/router/EventsRouter.d.ts +2 -2
- package/dist/app/router/EventsRouter.js +56 -3
- package/dist/app/router/EventsRouter.js.map +1 -1
- package/dist/app/router/TreeArtifact.d.ts +2 -0
- package/dist/app/router/TreeArtifact.js +87 -0
- package/dist/app/router/TreeArtifact.js.map +1 -0
- package/dist/app/router/index.d.ts +6 -3
- package/dist/app/router/index.js +8 -1
- package/dist/checkbox-DoR0Pcxm.d.ts +27 -0
- package/dist/cli/app-process.d.ts +2 -3
- package/dist/cli/app-process.js +15 -4
- package/dist/cli/app-process.js.map +1 -1
- package/dist/cli/build.d.ts +4 -9
- package/dist/cli/build.js +33 -5
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/common.d.ts +3 -6
- package/dist/cli/common.js +2 -2
- package/dist/cli/common.js.map +1 -1
- package/dist/cli/development.d.ts +5 -6
- package/dist/cli/development.js +12 -12
- package/dist/cli/development.js.map +1 -1
- package/dist/cli/env.js.map +1 -1
- package/dist/cli/generators.js +0 -1
- package/dist/cli/generators.js.map +1 -1
- package/dist/cli/information.js +5 -5
- package/dist/cli/information.js.map +1 -1
- package/dist/cli/init.d.ts +1 -3
- package/dist/cli/init.js +37 -12
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/production.d.ts +1 -3
- package/dist/cli/production.js +4 -4
- package/dist/cli/production.js.map +1 -1
- package/dist/cli/type-checker.js +0 -1
- package/dist/cli/type-checker.js.map +1 -1
- package/dist/cli/utils.d.ts +0 -1
- package/dist/cli/utils.js.map +1 -1
- package/dist/{commandkit-Bh7C1_c7.js → commandkit-DNbfLwyR.js} +786 -200
- package/dist/commandkit-DNbfLwyR.js.map +1 -0
- package/dist/commandkit.d.ts +1 -1
- package/dist/commandkit.js +1 -1
- package/dist/{common-CCvvgnxi.d.ts → common-CIbPzguv.d.ts} +2 -3
- package/dist/components/common/EventInterceptor.d.ts +1 -1
- package/dist/components/common/EventInterceptor.js +1 -0
- package/dist/components/common/EventInterceptor.js.map +1 -1
- package/dist/components/common/element.d.ts +1 -1
- package/dist/components/common/element.js +1 -1
- package/dist/components/common/types.d.ts +1 -1
- package/dist/components/display/common.d.ts +0 -1
- package/dist/components/display/common.js +1 -1
- package/dist/components/display/container.d.ts +1 -1
- package/dist/components/display/container.js +1 -1
- package/dist/components/display/file.d.ts +1 -1
- package/dist/components/display/file.js +0 -1
- package/dist/components/display/file.js.map +1 -1
- package/dist/components/display/index.d.ts +9 -8
- package/dist/components/display/index.js +1 -1
- package/dist/components/display/label.d.ts +1 -1
- package/dist/components/display/label.js +1 -1
- package/dist/components/display/media-gallery.d.ts +1 -1
- package/dist/components/display/media-gallery.js +1 -1
- package/dist/components/display/poll.d.ts +1 -1
- package/dist/components/display/poll.js +4 -10
- package/dist/components/display/poll.js.map +1 -1
- package/dist/components/display/section.d.ts +1 -1
- package/dist/components/display/section.js +1 -1
- package/dist/components/display/separator.d.ts +1 -1
- package/dist/components/display/separator.js +0 -1
- package/dist/components/display/separator.js.map +1 -1
- package/dist/components/display/text-display.d.ts +1 -1
- package/dist/components/display/text-display.js +0 -1
- package/dist/components/display/text-display.js.map +1 -1
- package/dist/components/index.d.ts +26 -23
- package/dist/components/index.js +6 -1
- package/dist/components/interactive/action-row/ActionRow.d.ts +1 -1
- package/dist/components/interactive/action-row/ActionRow.js +0 -1
- package/dist/components/interactive/action-row/ActionRow.js.map +1 -1
- package/dist/components/interactive/button/Button.d.ts +1 -1
- package/dist/components/interactive/button/Button.js +1 -1
- package/dist/components/interactive/button/ButtonKit.d.ts +1 -1
- package/dist/components/interactive/button/ButtonKit.js +1 -1
- package/dist/components/interactive/checkbox/checkbox.d.ts +2 -0
- package/dist/components/interactive/checkbox/checkbox.js +6 -0
- package/dist/components/interactive/modal/Modal.d.ts +1 -1
- package/dist/components/interactive/modal/Modal.js +1 -1
- package/dist/components/interactive/modal/ModalKit.d.ts +1 -1
- package/dist/components/interactive/modal/ModalKit.js +1 -1
- package/dist/components/interactive/radio/radio.d.ts +2 -0
- package/dist/components/interactive/radio/radio.js +5 -0
- package/dist/components/interactive/select-menu/ChannelSelectMenuKit.d.ts +1 -1
- package/dist/components/interactive/select-menu/ChannelSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/MentionableSelectMenuKit.d.ts +1 -1
- package/dist/components/interactive/select-menu/MentionableSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/RoleSelectMenuKit.d.ts +1 -1
- package/dist/components/interactive/select-menu/RoleSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/SelectMenu.d.ts +1 -1
- package/dist/components/interactive/select-menu/SelectMenu.js +1 -1
- package/dist/components/interactive/select-menu/StringSelectMenuKit.d.ts +1 -1
- package/dist/components/interactive/select-menu/StringSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/UserSelectMenuKit.d.ts +1 -1
- package/dist/components/interactive/select-menu/UserSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/common.d.ts +1 -1
- package/dist/config/config.d.ts +1 -2
- package/dist/config/config.js +1 -1
- package/dist/config/default.d.ts +1 -2
- package/dist/config/default.js +1 -1
- package/dist/config/loader.d.ts +1 -2
- package/dist/config/loader.js +1 -1
- package/dist/config/types.d.ts +2 -2
- package/dist/config/utils.d.ts +1 -1
- package/dist/config/utils.js.map +1 -1
- package/dist/{constants-DqtJY0t-.d.ts → constants-B7AfnOFa.d.ts} +1 -1
- package/dist/{constants-DwxpkIeH.d.ts → constants-kWgE3L9F.d.ts} +15 -2
- package/dist/{container-CYojOA9d.d.ts → container-NVgblXmw.d.ts} +1 -2
- package/dist/context/async-context.d.ts +1 -1
- package/dist/context/async-context.js +1 -1
- package/dist/context/environment.d.ts +1 -1
- package/dist/context/environment.js +1 -1
- package/dist/{element-DeLvTMfZ.d.ts → element-BMZYAAQ-.d.ts} +3 -4
- package/dist/events/CommandKitEventsChannel.d.ts +1 -1
- package/dist/events/CommandKitEventsChannel.js +3 -2
- package/dist/events/CommandKitEventsChannel.js.map +1 -1
- package/dist/{file-DLO1zEcH.d.ts → file-DYAmr697.d.ts} +1 -2
- package/dist/flags/FlagProvider.d.ts +1 -1
- package/dist/flags/FlagProvider.js +1 -0
- package/dist/flags/FlagProvider.js.map +1 -1
- package/dist/flags/feature-flags.d.ts +1 -1
- package/dist/flags/feature-flags.js +1 -1
- package/dist/flags/store.d.ts +1 -1
- package/dist/flags/store.js +0 -1
- package/dist/flags/store.js.map +1 -1
- package/dist/{helpers-zmC44Mcu.d.ts → helpers-vlnRvNJv.d.ts} +1 -2
- package/dist/index-CAFaKBs_.d.ts +8 -0
- package/dist/index-COt7nfC9.d.ts +2 -0
- package/dist/index-DvqHpiuh.d.ts +16 -0
- package/dist/index.d.ts +37 -31
- package/dist/index.js +14 -2
- package/dist/kv/constants.d.ts +1 -1
- package/dist/kv/constants.js.map +1 -1
- package/dist/kv/dotprops.js.map +1 -1
- package/dist/kv/kv.d.ts +0 -1
- package/dist/kv/kv.js +1 -1
- package/dist/kv/kv.js.map +1 -1
- package/dist/kv/serde.d.ts +1 -2
- package/dist/kv/serde.js +27 -27
- package/dist/kv/serde.js.map +1 -1
- package/dist/{label-DqGRqodo.d.ts → label-DClaYktn.d.ts} +1 -2
- package/dist/logger/DefaultLogger.d.ts +0 -1
- package/dist/logger/DefaultLogger.js +1 -1
- package/dist/logger/Logger.d.ts +0 -1
- package/dist/logger/Logger.js +1 -1
- package/dist/logger/NoopLogger.d.ts +0 -1
- package/dist/logger/NoopLogger.js.map +1 -1
- package/dist/{media-gallery-Ca8es-eB.d.ts → media-gallery-z2Snzz-u.d.ts} +1 -2
- package/dist/plugins/CompilerPlugin.d.ts +1 -1
- package/dist/plugins/CompilerPlugin.js +2 -2
- package/dist/plugins/CompilerPlugin.js.map +1 -1
- package/dist/plugins/PluginCommon.d.ts +1 -1
- package/dist/plugins/PluginCommon.js +1 -1
- package/dist/plugins/PluginCommon.js.map +1 -1
- package/dist/plugins/RuntimePlugin.d.ts +1 -1
- package/dist/plugins/RuntimePlugin.js +2 -2
- package/dist/plugins/RuntimePlugin.js.map +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/plugin-runtime/CommandKitPluginRuntime.d.ts +1 -1
- package/dist/plugins/plugin-runtime/CommandKitPluginRuntime.js +1 -1
- package/dist/plugins/plugin-runtime/CompilerPluginRuntime.d.ts +1 -1
- package/dist/plugins/plugin-runtime/CompilerPluginRuntime.js +1 -1
- package/dist/plugins/plugin-runtime/builtin/CommonDirectiveTransformer.d.ts +1 -1
- package/dist/plugins/plugin-runtime/builtin/CommonDirectiveTransformer.js +1 -1
- package/dist/plugins/plugin-runtime/builtin/MacroPlugin.d.ts +1 -2
- package/dist/plugins/plugin-runtime/builtin/MacroPlugin.js +1 -1
- package/dist/plugins/plugin-runtime/runtime.d.ts +1 -1
- package/dist/plugins/types.d.ts +1 -1
- package/dist/{poll-DQ6DX_Tt.d.ts → poll-D2QDStsw.d.ts} +4 -14
- package/dist/radio-CJH_N4lq.d.ts +20 -0
- package/dist/{section-Q8nwx_-q.d.ts → section-DrFBT5b-.d.ts} +1 -2
- package/dist/{separator-B8P-kdIK.d.ts → separator-BVm3w6yd.d.ts} +1 -2
- package/dist/{signals-CBXwugBW.d.ts → signals-DRMDrCOn.d.ts} +1 -1
- package/dist/{text-display-CL9C2yMc.d.ts → text-display-BG0nNqy3.d.ts} +1 -2
- package/dist/{types-DZy7U-Ld.d.ts → types-ur7SvktF.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils/colors.d.ts +1 -3
- package/dist/utils/colors.js +0 -1
- package/dist/utils/colors.js.map +1 -1
- package/dist/utils/constants.d.ts +2 -2
- package/dist/utils/constants.js +19 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/dev-hooks.d.ts +1 -1
- package/dist/utils/dev-hooks.js +1 -1
- package/dist/utils/error-codes.js +15 -0
- package/dist/utils/error-codes.js.map +1 -1
- package/dist/utils/resolve-file-url.js +2 -2
- package/dist/utils/resolve-file-url.js.map +1 -1
- package/dist/utils/types-package.d.ts +6 -2
- package/dist/utils/types-package.js +31 -38
- package/dist/utils/types-package.js.map +1 -1
- package/dist/utils/useful-stuff/async-queue.js.map +1 -1
- package/dist/utils/useful-stuff/mutex.js.map +1 -1
- package/dist/utils/useful-stuff/ratelimiter.js +4 -1
- package/dist/utils/useful-stuff/ratelimiter.js.map +1 -1
- package/dist/utils/useful-stuff/semaphore.js.map +1 -1
- package/dist/utils/utilities.js +1 -1
- package/dist/utils/warning.d.ts +1 -5
- package/dist/utils/warning.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +17 -17
- package/dist/CommandsRouter-DiNoF0dq.d.ts +0 -145
- package/dist/commandkit-Bh7C1_c7.js.map +0 -1
- package/dist/index-BIsCUWAs.d.ts +0 -1
- package/dist/index-CwHYpK-f.d.ts +0 -1
- package/dist/index-DHrsNvX1.d.ts +0 -1
- /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
|
|
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
|
-
*
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
*
|
|
117
|
-
*
|
|
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
|
|
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
|
-
|
|
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 (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
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) =>
|
|
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 {
|
|
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 };
|