commandkit 1.2.1-dev.20260411010608 → 1.2.1-dev.20260411122819
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CommandTree-DwfiCsOl.d.ts +55 -0
- package/dist/{CommandsRouter-DiNoF0dq.d.ts → CommandsRouter-D-b3xv38.d.ts} +102 -25
- package/dist/{EventsRouter-EuuSu6NH.d.ts → EventsRouter-Dyr_oJJD.d.ts} +1 -1
- package/dist/{MessageCommandParser-DPCbHXCS.d.ts → MessageCommandParser-UTKsRvb9.d.ts} +7 -1
- 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/utils.js +1 -1
- package/dist/{analytics-engine-uBNaD2CQ.d.ts → analytics-engine-BimOLPwO.d.ts} +109 -17
- 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 +75 -70
- package/dist/app/commands/MessageCommandParser.js.map +1 -1
- package/dist/app/commands/helpers.d.ts +1 -1
- package/dist/app/events/EventWorkerContext.d.ts +2 -2
- 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 +4 -4
- package/dist/app/index.js +1 -1
- package/dist/app/interrupt/signals.d.ts +1 -1
- package/dist/app/middlewares/permissions.d.ts +1 -1
- 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 +1 -1
- package/dist/app/router/CommandsRouter.js +385 -23
- package/dist/app/router/CommandsRouter.js.map +1 -1
- package/dist/app/router/EventsRouter.d.ts +1 -1
- package/dist/app/router/index.d.ts +4 -3
- package/dist/checkbox-CvQGiyRe.d.ts +28 -0
- package/dist/cli/build.d.ts +1 -1
- package/dist/cli/build.js +1 -1
- package/dist/cli/common.d.ts +1 -1
- package/dist/cli/development.d.ts +1 -1
- package/dist/cli/development.js +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/cli/production.js +1 -1
- package/dist/{commandkit-DNln6BAJ.js → commandkit-D2HMPuRQ.js} +548 -109
- package/dist/commandkit-D2HMPuRQ.js.map +1 -0
- package/dist/commandkit.d.ts +1 -1
- package/dist/commandkit.js +1 -1
- package/dist/components/common/element.js +1 -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/index.d.ts +8 -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/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/text-display.d.ts +1 -1
- package/dist/components/index.d.ts +11 -9
- package/dist/components/index.js +6 -1
- package/dist/components/interactive/button/Button.js +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.js +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.js +1 -1
- package/dist/components/interactive/select-menu/MentionableSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/RoleSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/SelectMenu.js +1 -1
- package/dist/components/interactive/select-menu/StringSelectMenuKit.js +1 -1
- package/dist/components/interactive/select-menu/UserSelectMenuKit.js +1 -1
- package/dist/config/config.d.ts +1 -1
- package/dist/config/config.js +1 -1
- package/dist/config/default.d.ts +1 -1
- package/dist/config/default.js +1 -1
- package/dist/config/loader.d.ts +1 -1
- package/dist/config/loader.js +1 -1
- package/dist/config/types.d.ts +1 -1
- package/dist/config/utils.d.ts +1 -1
- package/dist/{constants-DqtJY0t-.d.ts → constants-D_sgdBHy.d.ts} +1 -1
- package/dist/{constants-DwxpkIeH.d.ts → constants-GWSfiS4h.d.ts} +1 -1
- package/dist/{container-CYojOA9d.d.ts → container-B7Kmw__R.d.ts} +1 -1
- 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/events/CommandKitEventsChannel.d.ts +1 -1
- package/dist/{file-DLO1zEcH.d.ts → file-BP8aoN3A.d.ts} +1 -1
- package/dist/flags/FlagProvider.d.ts +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/{helpers-zmC44Mcu.d.ts → helpers-C5jRrAM1.d.ts} +1 -1
- package/dist/index.d.ts +19 -16
- package/dist/index.js +6 -1
- package/dist/kv/constants.d.ts +1 -1
- package/dist/kv/serde.d.ts +1 -1
- package/dist/{label-DqGRqodo.d.ts → label-CqHiBMXP.d.ts} +1 -1
- package/dist/logger/DefaultLogger.js +1 -1
- package/dist/logger/Logger.js +1 -1
- package/dist/{media-gallery-Ca8es-eB.d.ts → media-gallery-hFfa57Kd.d.ts} +1 -1
- package/dist/plugins/CompilerPlugin.d.ts +1 -1
- package/dist/plugins/PluginCommon.d.ts +1 -1
- package/dist/plugins/RuntimePlugin.d.ts +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 -1
- 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-ElAd5Z2K.d.ts} +1 -1
- package/dist/radio-Dcd4YIZx.d.ts +21 -0
- package/dist/{section-Q8nwx_-q.d.ts → section-BqDLXlp3.d.ts} +1 -1
- package/dist/{separator-B8P-kdIK.d.ts → separator-DSaCa1Tc.d.ts} +1 -1
- package/dist/{signals-CBXwugBW.d.ts → signals-DVOXPkQK.d.ts} +1 -1
- package/dist/{text-display-CL9C2yMc.d.ts → text-display-D-0dD7bR.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/dev-hooks.d.ts +1 -1
- package/dist/utils/dev-hooks.js +1 -1
- package/dist/utils/utilities.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/commandkit-DNln6BAJ.js.map +0 -1
- /package/dist/{index-BIsCUWAs.d.ts → index-CQiOqvUC.d.ts} +0 -0
- /package/dist/{index-CwHYpK-f.d.ts → index-CTLjHn5u.d.ts} +0 -0
- /package/dist/{index-DHrsNvX1.d.ts → index-LKrIp3Oo.d.ts} +0 -0
|
@@ -631,20 +631,30 @@ function findAppDirectory() {
|
|
|
631
631
|
*/
|
|
632
632
|
function debounce(fn, ms) {
|
|
633
633
|
let timer = null;
|
|
634
|
-
let
|
|
634
|
+
let sharedPromise = null;
|
|
635
|
+
let sharedResolve = null;
|
|
636
|
+
let sharedReject = null;
|
|
635
637
|
return ((...args) => {
|
|
636
|
-
if (timer)
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return new Promise((res) => {
|
|
641
|
-
resolve = res;
|
|
642
|
-
timer = setTimeout(() => {
|
|
643
|
-
res(fn(...args));
|
|
644
|
-
timer = null;
|
|
645
|
-
resolve = null;
|
|
646
|
-
}, ms);
|
|
638
|
+
if (timer) clearTimeout(timer);
|
|
639
|
+
if (!sharedPromise) sharedPromise = new Promise((res, rej) => {
|
|
640
|
+
sharedResolve = res;
|
|
641
|
+
sharedReject = rej;
|
|
647
642
|
});
|
|
643
|
+
timer = setTimeout(async () => {
|
|
644
|
+
const currentResolve = sharedResolve;
|
|
645
|
+
const currentReject = sharedReject;
|
|
646
|
+
timer = null;
|
|
647
|
+
sharedPromise = null;
|
|
648
|
+
sharedResolve = null;
|
|
649
|
+
sharedReject = null;
|
|
650
|
+
try {
|
|
651
|
+
const result = await fn(...args);
|
|
652
|
+
if (currentResolve) currentResolve(result);
|
|
653
|
+
} catch (err) {
|
|
654
|
+
if (currentReject) currentReject(err);
|
|
655
|
+
}
|
|
656
|
+
}, ms);
|
|
657
|
+
return sharedPromise;
|
|
648
658
|
});
|
|
649
659
|
}
|
|
650
660
|
/**
|
|
@@ -1579,9 +1589,12 @@ var Context = class Context {
|
|
|
1579
1589
|
* Gets the name of the current command.
|
|
1580
1590
|
*/
|
|
1581
1591
|
get commandName() {
|
|
1592
|
+
const routeKey = this.command.data.command.__routeKey;
|
|
1593
|
+
if (typeof routeKey === "string" && routeKey.length) return routeKey;
|
|
1594
|
+
if (this.command.data.command.name) return this.command.data.command.name;
|
|
1582
1595
|
if (this.isInteraction()) return this.interaction.commandName;
|
|
1583
|
-
const
|
|
1584
|
-
return this.commandkit.commandHandler.resolveMessageCommandName(
|
|
1596
|
+
const parser = this.config.messageCommandParser;
|
|
1597
|
+
return this.commandkit.commandHandler.resolveMessageCommandName(parser.getFullCommand());
|
|
1585
1598
|
}
|
|
1586
1599
|
/**
|
|
1587
1600
|
* Gets the invoked command name (could be an alias for message commands)
|
|
@@ -1675,7 +1688,7 @@ var Context = class Context {
|
|
|
1675
1688
|
*/
|
|
1676
1689
|
getCommandIdentifier() {
|
|
1677
1690
|
if (this.isInteraction()) return this.interaction.commandName;
|
|
1678
|
-
else return this.
|
|
1691
|
+
else return this.commandName;
|
|
1679
1692
|
}
|
|
1680
1693
|
/**
|
|
1681
1694
|
* Returns the locale of the guild where this command was triggered.
|
|
@@ -1787,7 +1800,7 @@ var AppCommandRunner = class {
|
|
|
1787
1800
|
const env = new CommandKitEnvironment(commandkit);
|
|
1788
1801
|
env.setType(CommandKitEnvironmentType.CommandHandler);
|
|
1789
1802
|
env.variables.set("commandHandlerType", "app");
|
|
1790
|
-
env.variables.set("currentCommandName", prepared.command.command.name);
|
|
1803
|
+
env.variables.set("currentCommandName", prepared.command.data.command.__routeKey ?? prepared.command.command.name);
|
|
1791
1804
|
env.variables.set("execHandlerKind", executionMode);
|
|
1792
1805
|
env.variables.set("customHandler", (options === null || options === void 0 ? void 0 : options.handler) ?? null);
|
|
1793
1806
|
try {
|
|
@@ -1827,15 +1840,15 @@ var AppCommandRunner = class {
|
|
|
1827
1840
|
if (fn) try {
|
|
1828
1841
|
const _executeCommand = makeContextAwareFunction(env, async () => {
|
|
1829
1842
|
env.registerDeferredFunction(async (env) => {
|
|
1830
|
-
var _prepared$
|
|
1843
|
+
var _prepared$command3, _prepared$command4;
|
|
1831
1844
|
env.markEnd();
|
|
1832
1845
|
const error = env.getExecutionError();
|
|
1833
1846
|
const marker = env.getMarker();
|
|
1834
1847
|
const time = `${env.getExecutionTime().toFixed(2)}ms`;
|
|
1835
1848
|
if (error) {
|
|
1836
|
-
var _prepared$command;
|
|
1849
|
+
var _prepared$command, _prepared$command2;
|
|
1837
1850
|
Logger.error`[${marker} - ${time}] Error executing command: ${error}`;
|
|
1838
|
-
const commandName = ((_prepared$command = prepared.command) === null || _prepared$command === void 0 || (_prepared$command = _prepared$command.data) === null || _prepared$command === void 0 || (_prepared$command = _prepared$command.command) === null || _prepared$command === void 0 ? void 0 : _prepared$command.name) ?? prepared.command.command.name;
|
|
1851
|
+
const commandName = ((_prepared$command = prepared.command) === null || _prepared$command === void 0 || (_prepared$command = _prepared$command.data) === null || _prepared$command === void 0 || (_prepared$command = _prepared$command.command) === null || _prepared$command === void 0 ? void 0 : _prepared$command.__routeKey) ?? ((_prepared$command2 = prepared.command) === null || _prepared$command2 === void 0 || (_prepared$command2 = _prepared$command2.data) === null || _prepared$command2 === void 0 || (_prepared$command2 = _prepared$command2.command) === null || _prepared$command2 === void 0 ? void 0 : _prepared$command2.name) ?? prepared.command.command.name;
|
|
1839
1852
|
await analytics.track({
|
|
1840
1853
|
name: require_analytics_constants.AnalyticsEvents.COMMAND_EXECUTION,
|
|
1841
1854
|
id: commandName,
|
|
@@ -1849,7 +1862,7 @@ var AppCommandRunner = class {
|
|
|
1849
1862
|
return;
|
|
1850
1863
|
}
|
|
1851
1864
|
Logger.info(`[${marker} - ${time}] Command executed successfully`);
|
|
1852
|
-
const commandName = ((_prepared$
|
|
1865
|
+
const commandName = ((_prepared$command3 = prepared.command) === null || _prepared$command3 === void 0 || (_prepared$command3 = _prepared$command3.data) === null || _prepared$command3 === void 0 || (_prepared$command3 = _prepared$command3.command) === null || _prepared$command3 === void 0 ? void 0 : _prepared$command3.__routeKey) ?? ((_prepared$command4 = prepared.command) === null || _prepared$command4 === void 0 || (_prepared$command4 = _prepared$command4.data) === null || _prepared$command4 === void 0 || (_prepared$command4 = _prepared$command4.command) === null || _prepared$command4 === void 0 ? void 0 : _prepared$command4.name) ?? prepared.command.command.name;
|
|
1853
1866
|
await analytics.track({
|
|
1854
1867
|
name: require_analytics_constants.AnalyticsEvents.COMMAND_EXECUTION,
|
|
1855
1868
|
id: commandName,
|
|
@@ -1864,7 +1877,7 @@ var AppCommandRunner = class {
|
|
|
1864
1877
|
return fn(middlewareCtx.clone());
|
|
1865
1878
|
}, this.#finalizer.bind(this));
|
|
1866
1879
|
const executeCommand = runCommand != null ? runCommand(_executeCommand) : _executeCommand;
|
|
1867
|
-
env.markStart(prepared.command.data.command.name);
|
|
1880
|
+
env.markStart(prepared.command.data.command.__routeKey ?? prepared.command.data.command.name);
|
|
1868
1881
|
if (!await commandkit.plugins.execute(async (ctx, plugin) => {
|
|
1869
1882
|
return plugin.executeCommand(ctx, env, source, prepared, executeCommand);
|
|
1870
1883
|
})) result = await executeCommand();
|
|
@@ -2024,11 +2037,17 @@ var CommandRegistrar = class {
|
|
|
2024
2037
|
* Gets the commands data, consuming pre-generated context menu entries when available.
|
|
2025
2038
|
*/
|
|
2026
2039
|
getCommandsData() {
|
|
2040
|
+
return [...this.getFlatCommandsData(), ...this.getHierarchicalCommandsData()];
|
|
2041
|
+
}
|
|
2042
|
+
/**
|
|
2043
|
+
* Gets flat command data, consuming pre-generated context menu entries when available.
|
|
2044
|
+
*/
|
|
2045
|
+
getFlatCommandsData() {
|
|
2027
2046
|
const commands = this.commandkit.commandHandler.getCommandsArray();
|
|
2028
2047
|
const commandIds = new Set(commands.map((command) => command.command.id));
|
|
2029
2048
|
return commands.flatMap((cmd) => {
|
|
2030
2049
|
const isPreGeneratedCtx = cmd.command.id.endsWith("::user-ctx") || cmd.command.id.endsWith("::message-ctx");
|
|
2031
|
-
const json = "toJSON" in cmd.data.command ? cmd.data.command.toJSON() : cmd.data.command;
|
|
2050
|
+
const json = this.sanitizeCommandData("toJSON" in cmd.data.command ? cmd.data.command.toJSON() : cmd.data.command);
|
|
2032
2051
|
const __metadata = cmd.metadata ?? cmd.data.metadata;
|
|
2033
2052
|
const isContextMenuType = json.type === discord_js.ApplicationCommandType.User || json.type === discord_js.ApplicationCommandType.Message;
|
|
2034
2053
|
const applyId = (id) => {
|
|
@@ -2079,6 +2098,119 @@ var CommandRegistrar = class {
|
|
|
2079
2098
|
});
|
|
2080
2099
|
}
|
|
2081
2100
|
/**
|
|
2101
|
+
* Gets hierarchical chat-input command payloads compiled from cached tree nodes.
|
|
2102
|
+
*/
|
|
2103
|
+
getHierarchicalCommandsData() {
|
|
2104
|
+
const router = this.commandkit.commandsRouter;
|
|
2105
|
+
if (!router) return [];
|
|
2106
|
+
const { treeNodes } = router.getData();
|
|
2107
|
+
const hierarchicalNodes = new Map(this.commandkit.commandHandler.getHierarchicalNodesArray().map((node) => [node.command.id, node]));
|
|
2108
|
+
const rootNodes = Array.from(treeNodes.values()).filter((node) => {
|
|
2109
|
+
return node.source !== "flat" && node.kind === "command" && node.route.length === 1;
|
|
2110
|
+
});
|
|
2111
|
+
const commands = [];
|
|
2112
|
+
for (const rootNode of rootNodes) {
|
|
2113
|
+
const payload = this.buildHierarchicalRootPayload(rootNode.id, treeNodes, hierarchicalNodes);
|
|
2114
|
+
if (payload) commands.push(payload);
|
|
2115
|
+
}
|
|
2116
|
+
return commands;
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Removes internal runtime-only fields before Discord registration data is emitted.
|
|
2120
|
+
*/
|
|
2121
|
+
sanitizeCommandData(command) {
|
|
2122
|
+
const { __routeKey, ...json } = command;
|
|
2123
|
+
return json;
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Builds a top-level Discord payload for a hierarchical command root.
|
|
2127
|
+
*/
|
|
2128
|
+
buildHierarchicalRootPayload(rootNodeId, treeNodes, hierarchicalNodes) {
|
|
2129
|
+
const rootNode = treeNodes.get(rootNodeId);
|
|
2130
|
+
const rootLoaded = hierarchicalNodes.get(rootNodeId);
|
|
2131
|
+
if (!rootNode || !rootLoaded) return null;
|
|
2132
|
+
const rootJson = this.sanitizeCommandData("toJSON" in rootLoaded.data.command ? rootLoaded.data.command.toJSON() : rootLoaded.data.command);
|
|
2133
|
+
if (rootNode.executable) {
|
|
2134
|
+
if (!rootLoaded.data.chatInput) return null;
|
|
2135
|
+
return {
|
|
2136
|
+
...rootJson,
|
|
2137
|
+
type: discord_js.ApplicationCommandType.ChatInput,
|
|
2138
|
+
description: rootJson.description ?? "No command description set.",
|
|
2139
|
+
__metadata: rootLoaded.metadata ?? rootLoaded.data.metadata,
|
|
2140
|
+
__applyId: (id) => {
|
|
2141
|
+
rootLoaded.discordId = id;
|
|
2142
|
+
}
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
const options = rootNode.childIds.map((childId) => this.buildHierarchicalOption(childId, treeNodes, hierarchicalNodes)).filter(Boolean);
|
|
2146
|
+
if (!options.length) return null;
|
|
2147
|
+
const scopeKeys = new Set(this.collectHierarchicalGuildScopes(rootNode.childIds, treeNodes, hierarchicalNodes));
|
|
2148
|
+
if (scopeKeys.size > 1) {
|
|
2149
|
+
Logger.error(`Failed to register hierarchical command "${rootJson.name ?? rootNode.token}": all chat-input leaves under the same root must use the same guild scope in v1.`);
|
|
2150
|
+
return null;
|
|
2151
|
+
}
|
|
2152
|
+
const scopeKey = scopeKeys.values().next().value;
|
|
2153
|
+
const scopeGuilds = scopeKey ? scopeKey.split(",").filter(Boolean) : [];
|
|
2154
|
+
const metadata = {
|
|
2155
|
+
...rootLoaded.metadata ?? rootLoaded.data.metadata,
|
|
2156
|
+
guilds: scopeGuilds.length ? scopeGuilds : void 0
|
|
2157
|
+
};
|
|
2158
|
+
return {
|
|
2159
|
+
...rootJson,
|
|
2160
|
+
type: discord_js.ApplicationCommandType.ChatInput,
|
|
2161
|
+
description: rootJson.description ?? "No command description set.",
|
|
2162
|
+
options,
|
|
2163
|
+
__metadata: metadata,
|
|
2164
|
+
__applyId: (id) => {
|
|
2165
|
+
rootLoaded.discordId = id;
|
|
2166
|
+
}
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
/**
|
|
2170
|
+
* Builds a nested subcommand or subcommand-group option from a hierarchical node.
|
|
2171
|
+
*/
|
|
2172
|
+
buildHierarchicalOption(nodeId, treeNodes, hierarchicalNodes) {
|
|
2173
|
+
const node = treeNodes.get(nodeId);
|
|
2174
|
+
const loadedNode = hierarchicalNodes.get(nodeId);
|
|
2175
|
+
if (!node || !loadedNode) return null;
|
|
2176
|
+
const json = this.sanitizeCommandData("toJSON" in loadedNode.data.command ? loadedNode.data.command.toJSON() : loadedNode.data.command);
|
|
2177
|
+
if (node.kind === "group") {
|
|
2178
|
+
const options = node.childIds.map((childId) => this.buildHierarchicalOption(childId, treeNodes, hierarchicalNodes)).filter(Boolean);
|
|
2179
|
+
if (!options.length) return null;
|
|
2180
|
+
return {
|
|
2181
|
+
...json,
|
|
2182
|
+
type: discord_js.ApplicationCommandOptionType.SubcommandGroup,
|
|
2183
|
+
description: json.description ?? "No command description set.",
|
|
2184
|
+
options
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
if (!node.executable || !loadedNode.data.chatInput) return null;
|
|
2188
|
+
return {
|
|
2189
|
+
...json,
|
|
2190
|
+
type: discord_js.ApplicationCommandOptionType.Subcommand,
|
|
2191
|
+
description: json.description ?? "No command description set."
|
|
2192
|
+
};
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Collects normalized guild scopes for all chat-input leaves within a hierarchical subtree.
|
|
2196
|
+
*/
|
|
2197
|
+
collectHierarchicalGuildScopes(nodeIds, treeNodes, hierarchicalNodes) {
|
|
2198
|
+
const scopes = [];
|
|
2199
|
+
for (const nodeId of nodeIds) {
|
|
2200
|
+
var _loadedNode$metadata;
|
|
2201
|
+
const node = treeNodes.get(nodeId);
|
|
2202
|
+
const loadedNode = hierarchicalNodes.get(nodeId);
|
|
2203
|
+
if (!node || !loadedNode) continue;
|
|
2204
|
+
if (node.kind === "group") {
|
|
2205
|
+
scopes.push(...this.collectHierarchicalGuildScopes(node.childIds, treeNodes, hierarchicalNodes));
|
|
2206
|
+
continue;
|
|
2207
|
+
}
|
|
2208
|
+
if (!node.executable || !loadedNode.data.chatInput) continue;
|
|
2209
|
+
scopes.push((((_loadedNode$metadata = loadedNode.metadata) === null || _loadedNode$metadata === void 0 ? void 0 : _loadedNode$metadata.guilds) ?? []).filter(Boolean).slice().sort().join(","));
|
|
2210
|
+
}
|
|
2211
|
+
return scopes;
|
|
2212
|
+
}
|
|
2213
|
+
/**
|
|
2082
2214
|
* Registers loaded commands.
|
|
2083
2215
|
*/
|
|
2084
2216
|
async register() {
|
|
@@ -2249,6 +2381,20 @@ var AppCommandHandler = class {
|
|
|
2249
2381
|
*/
|
|
2250
2382
|
loadedCommands = new discord_js.Collection();
|
|
2251
2383
|
/**
|
|
2384
|
+
* Executable runtime commands indexed by canonical route key.
|
|
2385
|
+
* This includes flat commands and hierarchical executable leaves.
|
|
2386
|
+
* @private
|
|
2387
|
+
* @internal
|
|
2388
|
+
*/
|
|
2389
|
+
runtimeRouteIndex = new discord_js.Collection();
|
|
2390
|
+
/**
|
|
2391
|
+
* Loaded hierarchical command nodes keyed by tree node id.
|
|
2392
|
+
* Container nodes are cached here for registration compilation.
|
|
2393
|
+
* @private
|
|
2394
|
+
* @internal
|
|
2395
|
+
*/
|
|
2396
|
+
hierarchicalNodes = new discord_js.Collection();
|
|
2397
|
+
/**
|
|
2252
2398
|
* @private
|
|
2253
2399
|
* @internal
|
|
2254
2400
|
*/
|
|
@@ -2291,31 +2437,54 @@ var AppCommandHandler = class {
|
|
|
2291
2437
|
* Prints a formatted banner showing all loaded commands organized by category.
|
|
2292
2438
|
*/
|
|
2293
2439
|
printBanner() {
|
|
2440
|
+
var _this$commandkit$comm;
|
|
2294
2441
|
const uncategorized = crypto.randomUUID();
|
|
2295
|
-
const
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2442
|
+
const flatCommands = this.getCommandsArray();
|
|
2443
|
+
const treeNodes = Array.from(((_this$commandkit$comm = this.commandkit.commandsRouter) === null || _this$commandkit$comm === void 0 ? void 0 : _this$commandkit$comm.getData().treeNodes.values()) ?? []);
|
|
2444
|
+
const hierarchicalRoots = treeNodes.filter((n) => n.kind === "command" && n.source !== "root");
|
|
2445
|
+
const totalCount = flatCommands.length + hierarchicalRoots.length;
|
|
2446
|
+
console.log(require_utils_colors.default.green(`Loaded ${require_utils_colors.default.magenta(totalCount.toString())} commands:`));
|
|
2447
|
+
const printHierarchicalNode = (nodeId, prefix, indent) => {
|
|
2448
|
+
const node = treeNodes.find((n) => n.id === nodeId);
|
|
2449
|
+
if (!node || node.kind === "root") return;
|
|
2450
|
+
const loadedNode = this.hierarchicalNodes.get(nodeId);
|
|
2451
|
+
const hasMw = loadedNode && loadedNode.command.middlewares.length > 0 ? require_utils_colors.default.magenta(" (λ)") : "";
|
|
2452
|
+
const kindLabel = node.kind === "group" ? require_utils_colors.default.cyan(` [group]`) : node.kind === "command" ? "" : "";
|
|
2453
|
+
console.log(`${require_utils_colors.default.green(prefix)} ${require_utils_colors.default.yellow(node.token)}${kindLabel}${hasMw}`);
|
|
2454
|
+
const children = node.childIds;
|
|
2455
|
+
children.forEach((childId, idx) => {
|
|
2456
|
+
const isLastChild = idx === children.length - 1;
|
|
2457
|
+
printHierarchicalNode(childId, indent + (isLastChild ? "└─" : "├─"), indent + (isLastChild ? " " : "│ "));
|
|
2458
|
+
});
|
|
2459
|
+
};
|
|
2460
|
+
const categoryBuckets = {};
|
|
2461
|
+
const ensureBucket = (cat) => {
|
|
2462
|
+
categoryBuckets[cat] ??= {
|
|
2463
|
+
flat: [],
|
|
2464
|
+
hierarchical: []
|
|
2465
|
+
};
|
|
2466
|
+
};
|
|
2467
|
+
for (const cmd of flatCommands) {
|
|
2468
|
+
const cat = cmd.command.category || uncategorized;
|
|
2469
|
+
ensureBucket(cat);
|
|
2470
|
+
categoryBuckets[cat].flat.push(cmd);
|
|
2471
|
+
}
|
|
2472
|
+
for (const root of hierarchicalRoots) {
|
|
2473
|
+
const cat = root.category || uncategorized;
|
|
2474
|
+
ensureBucket(cat);
|
|
2475
|
+
categoryBuckets[cat].hierarchical.push(root);
|
|
2476
|
+
}
|
|
2477
|
+
const categories = Object.keys(categoryBuckets).sort();
|
|
2303
2478
|
const categoryTree = {};
|
|
2304
2479
|
categories.forEach((category) => {
|
|
2305
|
-
if (category === uncategorized) return;
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
break;
|
|
2314
|
-
}
|
|
2315
|
-
}
|
|
2316
|
-
if (bestParent) {
|
|
2317
|
-
categoryTree[bestParent] = categoryTree[bestParent] || [];
|
|
2318
|
-
categoryTree[bestParent].push(category);
|
|
2480
|
+
if (category === uncategorized || !category.includes(":")) return;
|
|
2481
|
+
const parts = category.split(":");
|
|
2482
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
2483
|
+
const potentialParent = parts.slice(0, i).join(":");
|
|
2484
|
+
if (categories.includes(potentialParent)) {
|
|
2485
|
+
categoryTree[potentialParent] ??= [];
|
|
2486
|
+
categoryTree[potentialParent].push(category);
|
|
2487
|
+
break;
|
|
2319
2488
|
}
|
|
2320
2489
|
}
|
|
2321
2490
|
});
|
|
@@ -2323,20 +2492,37 @@ var AppCommandHandler = class {
|
|
|
2323
2492
|
const printCategory = (category, indent = "", isLast = false, parentPrefix = "") => {
|
|
2324
2493
|
if (processedCategories.has(category)) return;
|
|
2325
2494
|
processedCategories.add(category);
|
|
2326
|
-
const
|
|
2495
|
+
const bucket = categoryBuckets[category];
|
|
2327
2496
|
const hasChildren = categoryTree[category] && categoryTree[category].length > 0;
|
|
2497
|
+
const allEntries = [...bucket.flat, ...bucket.hierarchical];
|
|
2328
2498
|
const thisPrefix = isLast ? "└─" : "├─";
|
|
2329
2499
|
const childIndent = parentPrefix + (isLast ? " " : "│ ");
|
|
2330
2500
|
if (category !== uncategorized) {
|
|
2331
2501
|
const displayName = category.includes(":") ? category.split(":").pop() : category;
|
|
2332
2502
|
console.log(require_utils_colors.default.cyan(`${indent}${thisPrefix} ${require_utils_colors.default.bold(displayName)}`));
|
|
2333
2503
|
}
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2504
|
+
const cmdIndent = category !== uncategorized ? childIndent : indent;
|
|
2505
|
+
const totalEntries = allEntries.length;
|
|
2506
|
+
let entryIndex = 0;
|
|
2507
|
+
bucket.flat.forEach((cmd) => {
|
|
2508
|
+
const cmdPrefix = entryIndex === totalEntries - 1 && !hasChildren ? "└─" : "├─";
|
|
2337
2509
|
const name = cmd.data.command.name;
|
|
2338
2510
|
const middlewareIcon = cmd.command.middlewares.length > 0 ? require_utils_colors.default.magenta(" (λ)") : "";
|
|
2339
2511
|
console.log(`${require_utils_colors.default.green(`${cmdIndent}${cmdPrefix}`)} ${require_utils_colors.default.yellow(name)}${middlewareIcon}`);
|
|
2512
|
+
entryIndex++;
|
|
2513
|
+
});
|
|
2514
|
+
bucket.hierarchical.forEach((root) => {
|
|
2515
|
+
const isLastEntry = entryIndex === totalEntries - 1 && !hasChildren;
|
|
2516
|
+
const rootPrefix = cmdIndent + (isLastEntry ? "└─" : "├─");
|
|
2517
|
+
const rootChildIndent = cmdIndent + (isLastEntry ? " " : "│ ");
|
|
2518
|
+
const loadedNode = this.hierarchicalNodes.get(root.id);
|
|
2519
|
+
const hasMw = loadedNode && loadedNode.command.middlewares.length > 0 ? require_utils_colors.default.magenta(" (λ)") : "";
|
|
2520
|
+
console.log(`${require_utils_colors.default.green(rootPrefix)} ${require_utils_colors.default.yellow(root.token)}${hasMw}`);
|
|
2521
|
+
root.childIds.forEach((childId, idx) => {
|
|
2522
|
+
const isLastChild = idx === root.childIds.length - 1;
|
|
2523
|
+
printHierarchicalNode(childId, rootChildIndent + (isLastChild ? "└─" : "├─"), rootChildIndent + (isLastChild ? " " : "│ "));
|
|
2524
|
+
});
|
|
2525
|
+
entryIndex++;
|
|
2340
2526
|
});
|
|
2341
2527
|
if (hasChildren) {
|
|
2342
2528
|
const children = categoryTree[category].sort();
|
|
@@ -2369,6 +2555,20 @@ var AppCommandHandler = class {
|
|
|
2369
2555
|
return Array.from(this.loadedCommands.values());
|
|
2370
2556
|
}
|
|
2371
2557
|
/**
|
|
2558
|
+
* Gets all executable runtime routes, including hierarchical leaves.
|
|
2559
|
+
* @returns Array of route-indexed commands
|
|
2560
|
+
*/
|
|
2561
|
+
getRuntimeCommandsArray() {
|
|
2562
|
+
return Array.from(this.runtimeRouteIndex.values());
|
|
2563
|
+
}
|
|
2564
|
+
/**
|
|
2565
|
+
* Gets loaded hierarchical command nodes, including non-executable containers.
|
|
2566
|
+
* @returns Array of hierarchical node definitions
|
|
2567
|
+
*/
|
|
2568
|
+
getHierarchicalNodesArray() {
|
|
2569
|
+
return Array.from(this.hierarchicalNodes.values());
|
|
2570
|
+
}
|
|
2571
|
+
/**
|
|
2372
2572
|
* Registers event handlers for Discord interactions and messages.
|
|
2373
2573
|
*/
|
|
2374
2574
|
registerCommandHandler() {
|
|
@@ -2394,6 +2594,35 @@ var AppCommandHandler = class {
|
|
|
2394
2594
|
this.commandkit.client.on(discord_js.Events.MessageCreate, this.onMessageCreate);
|
|
2395
2595
|
}
|
|
2396
2596
|
/**
|
|
2597
|
+
* @private
|
|
2598
|
+
* @internal
|
|
2599
|
+
*/
|
|
2600
|
+
normalizeRouteKey(input) {
|
|
2601
|
+
return input.trim().replace(/[.:]/g, " ").split(/\s+/).filter(Boolean).join(".");
|
|
2602
|
+
}
|
|
2603
|
+
/**
|
|
2604
|
+
* @private
|
|
2605
|
+
* @internal
|
|
2606
|
+
*/
|
|
2607
|
+
buildInteractionRouteKey(source) {
|
|
2608
|
+
if (!source.isCommand() && !source.isAutocomplete()) return "";
|
|
2609
|
+
const segments = [source.commandName];
|
|
2610
|
+
if (source.isChatInputCommand() || source.isAutocomplete()) {
|
|
2611
|
+
const group = source.options.getSubcommandGroup(false);
|
|
2612
|
+
const subcommand = source.options.getSubcommand(false);
|
|
2613
|
+
if (group) segments.push(group);
|
|
2614
|
+
if (subcommand) segments.push(subcommand);
|
|
2615
|
+
}
|
|
2616
|
+
return segments.filter(Boolean).join(".");
|
|
2617
|
+
}
|
|
2618
|
+
/**
|
|
2619
|
+
* @private
|
|
2620
|
+
* @internal
|
|
2621
|
+
*/
|
|
2622
|
+
buildMessageRouteKey(parser) {
|
|
2623
|
+
return parser.getFullRoute().join(".");
|
|
2624
|
+
}
|
|
2625
|
+
/**
|
|
2397
2626
|
* Prepares a command for execution by resolving the command and its middleware.
|
|
2398
2627
|
* @param source - The interaction or message that triggered the command
|
|
2399
2628
|
* @param cmdName - Optional command name override
|
|
@@ -2403,13 +2632,19 @@ var AppCommandHandler = class {
|
|
|
2403
2632
|
var _loadedCommand$metada3, _loadedCommand$metada4;
|
|
2404
2633
|
if (getConfig().disablePrefixCommands && source instanceof discord_js.Message) return null;
|
|
2405
2634
|
let parser;
|
|
2406
|
-
|
|
2635
|
+
let routeKey;
|
|
2636
|
+
let usedCommandOverride = false;
|
|
2637
|
+
if (cmdName) {
|
|
2638
|
+
routeKey = this.normalizeRouteKey(cmdName);
|
|
2639
|
+
usedCommandOverride = true;
|
|
2640
|
+
}
|
|
2641
|
+
if (!routeKey) if (source instanceof discord_js.Message) {
|
|
2407
2642
|
if (source.author.bot) return null;
|
|
2408
2643
|
const prefix = await this.commandkit.appConfig.getMessageCommandPrefix(source);
|
|
2409
2644
|
if (!prefix || (typeof prefix === "string" || Array.isArray(prefix)) && !prefix.length) return null;
|
|
2410
2645
|
parser = new require_app_commands_MessageCommandParser.MessageCommandParser(source, prefix instanceof RegExp ? prefix : Array.isArray(prefix) ? prefix : [prefix], (command) => {
|
|
2411
2646
|
var _loadedCommand$metada, _loadedCommand$metada2, _json$options;
|
|
2412
|
-
const loadedCommand = this.
|
|
2647
|
+
const loadedCommand = this.findCommandByRoute(command);
|
|
2413
2648
|
if (!loadedCommand) {
|
|
2414
2649
|
if (require_utils_constants.COMMANDKIT_IS_DEV && this.commandkit.config.showUnknownPrefixCommandsWarning) Logger.error`Prefix command "${command}" was not found.\nNote: This warning is only shown in development mode as an alert to help you find the command. If you wish to remove this warning, set \`showUnknownPrefixCommandsWarning\` to \`false\` in your commandkit config.`;
|
|
2415
2650
|
return null;
|
|
@@ -2421,7 +2656,7 @@ var AppCommandHandler = class {
|
|
|
2421
2656
|
}, {})) ?? {};
|
|
2422
2657
|
});
|
|
2423
2658
|
try {
|
|
2424
|
-
|
|
2659
|
+
routeKey = this.buildMessageRouteKey(parser);
|
|
2425
2660
|
} catch (e) {
|
|
2426
2661
|
if (require_utils_error_codes.isErrorType(e, require_utils_error_codes.CommandKitErrorCodes.InvalidCommandPrefix)) return null;
|
|
2427
2662
|
Logger.error`${e}`;
|
|
@@ -2429,10 +2664,10 @@ var AppCommandHandler = class {
|
|
|
2429
2664
|
}
|
|
2430
2665
|
} else {
|
|
2431
2666
|
if (!(source.isChatInputCommand() || source.isAutocomplete() || source.isContextMenuCommand())) return null;
|
|
2432
|
-
|
|
2667
|
+
routeKey = this.buildInteractionRouteKey(source);
|
|
2433
2668
|
}
|
|
2434
2669
|
const hint = require_app_commands_helpers.isInteractionSource(source) ? source.isUserContextMenuCommand() ? "user" : source.isMessageContextMenuCommand() ? "message" : void 0 : void 0;
|
|
2435
|
-
const loadedCommand = this.findCommandByName(
|
|
2670
|
+
const loadedCommand = hint ? this.findCommandByName(routeKey, hint) : this.findCommandByRoute(routeKey, usedCommandOverride);
|
|
2436
2671
|
if (!loadedCommand) return null;
|
|
2437
2672
|
if ((source instanceof discord_js.CommandInteraction || source instanceof discord_js.AutocompleteInteraction) && source.guildId && ((_loadedCommand$metada3 = loadedCommand.metadata) === null || _loadedCommand$metada3 === void 0 || (_loadedCommand$metada3 = _loadedCommand$metada3.guilds) === null || _loadedCommand$metada3 === void 0 ? void 0 : _loadedCommand$metada3.length) && !((_loadedCommand$metada4 = loadedCommand.metadata) === null || _loadedCommand$metada4 === void 0 ? void 0 : _loadedCommand$metada4.guilds.includes(source.guildId))) return null;
|
|
2438
2673
|
if (source instanceof discord_js.Message) {
|
|
@@ -2483,21 +2718,46 @@ var AppCommandHandler = class {
|
|
|
2483
2718
|
}
|
|
2484
2719
|
return null;
|
|
2485
2720
|
}
|
|
2486
|
-
|
|
2487
|
-
|
|
2721
|
+
/**
|
|
2722
|
+
* Finds a command by its canonical route key.
|
|
2723
|
+
* @param route - The command route or command name
|
|
2724
|
+
* @param allowFlatAliasFallback - Whether to check flat aliases if the route key was not found
|
|
2725
|
+
* @returns The loaded command or null if not found
|
|
2726
|
+
*/
|
|
2727
|
+
findCommandByRoute(route, allowFlatAliasFallback = true) {
|
|
2728
|
+
const normalizedRoute = this.normalizeRouteKey(route);
|
|
2729
|
+
const directMatch = this.runtimeRouteIndex.get(normalizedRoute);
|
|
2730
|
+
if (directMatch) return directMatch;
|
|
2731
|
+
if (!allowFlatAliasFallback || normalizedRoute.includes(".")) return null;
|
|
2732
|
+
for (const loadedCommand of this.runtimeRouteIndex.values()) {
|
|
2488
2733
|
var _loadedCommand$data$m3;
|
|
2489
|
-
if (loadedCommand.data.command.name === name) return loadedCommand.data.command.name;
|
|
2490
2734
|
const aliases = (_loadedCommand$data$m3 = loadedCommand.data.metadata) === null || _loadedCommand$data$m3 === void 0 ? void 0 : _loadedCommand$data$m3.aliases;
|
|
2491
|
-
if (aliases && Array.isArray(aliases) && aliases.includes(
|
|
2735
|
+
if (aliases && Array.isArray(aliases) && aliases.includes(normalizedRoute)) return loadedCommand;
|
|
2492
2736
|
}
|
|
2737
|
+
return null;
|
|
2738
|
+
}
|
|
2739
|
+
/**
|
|
2740
|
+
* @private
|
|
2741
|
+
* @internal
|
|
2742
|
+
*/
|
|
2743
|
+
getRouteKeyFor(command) {
|
|
2744
|
+
return command.data.command.__routeKey ?? this.normalizeRouteKey(command.data.command.name);
|
|
2745
|
+
}
|
|
2746
|
+
resolveMessageCommandName(name) {
|
|
2747
|
+
const loadedCommand = this.findCommandByRoute(name);
|
|
2748
|
+
if (loadedCommand) return this.getRouteKeyFor(loadedCommand);
|
|
2493
2749
|
return name;
|
|
2494
2750
|
}
|
|
2495
2751
|
/**
|
|
2496
2752
|
* Reloads all commands and middleware from scratch.
|
|
2497
2753
|
*/
|
|
2498
2754
|
async reloadCommands() {
|
|
2755
|
+
var _this$commandkit$comm2;
|
|
2756
|
+
await ((_this$commandkit$comm2 = this.commandkit.commandsRouter) === null || _this$commandkit$comm2 === void 0 ? void 0 : _this$commandkit$comm2.scan());
|
|
2499
2757
|
this.loadedCommands.clear();
|
|
2500
2758
|
this.loadedMiddlewares.clear();
|
|
2759
|
+
this.runtimeRouteIndex.clear();
|
|
2760
|
+
this.hierarchicalNodes.clear();
|
|
2501
2761
|
this.externalCommandData.clear();
|
|
2502
2762
|
this.externalMiddlewareData.clear();
|
|
2503
2763
|
await this.loadCommands();
|
|
@@ -2534,7 +2794,10 @@ var AppCommandHandler = class {
|
|
|
2534
2794
|
* @param data - Array of loaded commands to register
|
|
2535
2795
|
*/
|
|
2536
2796
|
async registerExternalLoadedCommands(data) {
|
|
2537
|
-
for (const command of data)
|
|
2797
|
+
for (const command of data) {
|
|
2798
|
+
this.loadedCommands.set(command.command.id, command);
|
|
2799
|
+
this.registerRuntimeRoute(command);
|
|
2800
|
+
}
|
|
2538
2801
|
}
|
|
2539
2802
|
/**
|
|
2540
2803
|
* Loads all commands and middleware from the router.
|
|
@@ -2545,15 +2808,20 @@ var AppCommandHandler = class {
|
|
|
2545
2808
|
});
|
|
2546
2809
|
const commandsRouter = this.commandkit.commandsRouter;
|
|
2547
2810
|
if (!commandsRouter) throw new Error("Commands router has not yet initialized");
|
|
2548
|
-
const { commands, middlewares } = commandsRouter.getData();
|
|
2811
|
+
const { commands, middlewares, treeNodes, compiledRoutes } = commandsRouter.getData();
|
|
2549
2812
|
const combinedCommands = this.externalCommandData.size ? commands.concat(this.externalCommandData) : commands;
|
|
2550
2813
|
const combinedMiddlewares = this.externalMiddlewareData.size ? middlewares.concat(this.externalMiddlewareData) : middlewares;
|
|
2551
2814
|
for (const [id, middleware] of combinedMiddlewares) await this.loadMiddleware(id, middleware);
|
|
2552
2815
|
for (const [id, command] of combinedCommands) await this.loadCommand(id, command);
|
|
2816
|
+
const hierarchicalNodes = Array.from(treeNodes.values()).filter((node) => node.source !== "flat" && !!node.definitionPath).sort((left, right) => left.route.length - right.route.length);
|
|
2817
|
+
for (const node of hierarchicalNodes) {
|
|
2818
|
+
const routeKey = node.route.join(".");
|
|
2819
|
+
await this.loadHierarchicalNode(node, compiledRoutes.get(routeKey) ?? void 0);
|
|
2820
|
+
}
|
|
2553
2821
|
if (require_utils_constants.COMMANDKIT_IS_DEV) {
|
|
2554
|
-
const commandNames = Array.from(this.
|
|
2555
|
-
const aliases = Array.from(this.
|
|
2556
|
-
await require_utils_types_package.rewriteCommandDeclaration(`type CommandTypeData = ${[...commandNames, ...aliases].map((name) => JSON.stringify(name)).join(" | ")}`);
|
|
2822
|
+
const commandNames = Array.from(this.runtimeRouteIndex.keys());
|
|
2823
|
+
const aliases = Array.from(this.runtimeRouteIndex.values()).flatMap((v) => v.metadata.aliases || []);
|
|
2824
|
+
await require_utils_types_package.rewriteCommandDeclaration(`type CommandTypeData = ${Array.from(new Set([...commandNames, ...aliases])).map((name) => JSON.stringify(name)).join(" | ")}`);
|
|
2557
2825
|
}
|
|
2558
2826
|
await this.commandkit.plugins.execute((ctx, plugin) => {
|
|
2559
2827
|
return plugin.onAfterCommandsLoad(ctx);
|
|
@@ -2584,10 +2852,84 @@ var AppCommandHandler = class {
|
|
|
2584
2852
|
* @private
|
|
2585
2853
|
* @internal
|
|
2586
2854
|
*/
|
|
2855
|
+
shouldIndexAsRuntimeRoute(command) {
|
|
2856
|
+
return !!(command.data.chatInput || command.data.message || command.data.autocomplete);
|
|
2857
|
+
}
|
|
2858
|
+
/**
|
|
2859
|
+
* @private
|
|
2860
|
+
* @internal
|
|
2861
|
+
*/
|
|
2862
|
+
registerRuntimeRoute(command, routeKey) {
|
|
2863
|
+
if (!this.shouldIndexAsRuntimeRoute(command)) return;
|
|
2864
|
+
const key = this.normalizeRouteKey(routeKey ?? command.data.command.name);
|
|
2865
|
+
if (!key) return;
|
|
2866
|
+
const commandData = command.data.command;
|
|
2867
|
+
commandData.__routeKey ??= key;
|
|
2868
|
+
this.runtimeRouteIndex.set(key, command);
|
|
2869
|
+
}
|
|
2870
|
+
/**
|
|
2871
|
+
* @private
|
|
2872
|
+
* @internal
|
|
2873
|
+
*/
|
|
2874
|
+
async processCommandFile(fileUrl, identifier, fallbackName, isHierarchical) {
|
|
2875
|
+
const commandFileData = await import(`${require_utils_resolve_file_url.toFileURL(fileUrl)}?t=${Date.now()}`);
|
|
2876
|
+
if (!commandFileData.command) throw new Error(`Invalid export for ${isHierarchical ? "hierarchical node" : "command"} ${identifier}: no command definition found`);
|
|
2877
|
+
const metadataFunc = commandFileData.generateMetadata;
|
|
2878
|
+
const metadataObj = commandFileData.metadata;
|
|
2879
|
+
if (metadataFunc && metadataObj) throw new Error("A command may only export either `generateMetadata` or `metadata`, not both");
|
|
2880
|
+
const metadata = (metadataFunc ? await metadataFunc() : metadataObj) ?? {
|
|
2881
|
+
aliases: [],
|
|
2882
|
+
guilds: [],
|
|
2883
|
+
userPermissions: [],
|
|
2884
|
+
botPermissions: []
|
|
2885
|
+
};
|
|
2886
|
+
let commandName = commandFileData.command.name;
|
|
2887
|
+
if (isHierarchical) {
|
|
2888
|
+
if (typeof commandName === "string" && commandName !== fallbackName) Logger.warn(`Hierarchical node \`${identifier}\` overrides its command name with \`${commandName}\`. The filesystem token \`${fallbackName}\` will be used instead.`);
|
|
2889
|
+
commandName = fallbackName;
|
|
2890
|
+
} else commandName = commandName || fallbackName;
|
|
2891
|
+
let commandDescription = commandFileData.command.description;
|
|
2892
|
+
if (!commandDescription && commandFileData.chatInput) commandDescription = "No command description set.";
|
|
2893
|
+
const updatedCommandData = {
|
|
2894
|
+
...commandFileData.command,
|
|
2895
|
+
name: commandName,
|
|
2896
|
+
description: commandDescription
|
|
2897
|
+
};
|
|
2898
|
+
let handlerCount = 0;
|
|
2899
|
+
for (const [key, propValidator] of Object.entries(commandDataSchema)) {
|
|
2900
|
+
const exportedProp = commandFileData[key];
|
|
2901
|
+
if (exportedProp) {
|
|
2902
|
+
if (!await propValidator(exportedProp)) throw new Error(`Invalid export for ${isHierarchical ? "hierarchical node" : "command"} ${identifier}: ${key} does not match expected value`);
|
|
2903
|
+
if (!KNOWN_NON_HANDLER_KEYS.includes(key)) handlerCount++;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
let lastUpdated = updatedCommandData;
|
|
2907
|
+
await this.commandkit.plugins.execute(async (ctx, plugin) => {
|
|
2908
|
+
const res = await plugin.prepareCommand(ctx, lastUpdated);
|
|
2909
|
+
if (res) lastUpdated = res;
|
|
2910
|
+
});
|
|
2911
|
+
const commandJson = "toJSON" in lastUpdated && typeof lastUpdated.toJSON === "function" ? lastUpdated.toJSON() : lastUpdated;
|
|
2912
|
+
if ("guilds" in commandJson || "aliases" in commandJson) Logger.warn(`Command \`${identifier}\` uses deprecated metadata properties. Please update to use the new \`metadata\` object or \`generateMetadata\` function.`);
|
|
2913
|
+
const resolvedMetadata = {
|
|
2914
|
+
guilds: commandJson.guilds,
|
|
2915
|
+
aliases: commandJson.aliases,
|
|
2916
|
+
...metadata
|
|
2917
|
+
};
|
|
2918
|
+
return {
|
|
2919
|
+
commandFileData,
|
|
2920
|
+
handlerCount,
|
|
2921
|
+
commandJson,
|
|
2922
|
+
resolvedMetadata
|
|
2923
|
+
};
|
|
2924
|
+
}
|
|
2925
|
+
/**
|
|
2926
|
+
* @private
|
|
2927
|
+
* @internal
|
|
2928
|
+
*/
|
|
2587
2929
|
async loadCommand(id, command) {
|
|
2588
2930
|
try {
|
|
2589
2931
|
if (command.path === null) {
|
|
2590
|
-
|
|
2932
|
+
const loadedCommand = {
|
|
2591
2933
|
discordId: null,
|
|
2592
2934
|
command,
|
|
2593
2935
|
metadata: {
|
|
@@ -2597,50 +2939,14 @@ var AppCommandHandler = class {
|
|
|
2597
2939
|
botPermissions: []
|
|
2598
2940
|
},
|
|
2599
2941
|
data: { command: { name: command.name } }
|
|
2600
|
-
}
|
|
2942
|
+
};
|
|
2943
|
+
this.loadedCommands.set(id, loadedCommand);
|
|
2944
|
+
this.registerRuntimeRoute(loadedCommand);
|
|
2601
2945
|
return;
|
|
2602
2946
|
}
|
|
2603
|
-
const commandFileData = await
|
|
2604
|
-
if (!commandFileData.command) throw new Error(`Invalid export for command ${command.name}: no command definition found`);
|
|
2605
|
-
const metadataFunc = commandFileData.generateMetadata;
|
|
2606
|
-
const metadataObj = commandFileData.metadata;
|
|
2607
|
-
if (metadataFunc && metadataObj) throw new Error("A command may only export either `generateMetadata` or `metadata`, not both");
|
|
2608
|
-
const metadata = (metadataFunc ? await metadataFunc() : metadataObj) ?? {
|
|
2609
|
-
aliases: [],
|
|
2610
|
-
guilds: [],
|
|
2611
|
-
userPermissions: [],
|
|
2612
|
-
botPermissions: []
|
|
2613
|
-
};
|
|
2614
|
-
const commandName = commandFileData.command.name || command.name;
|
|
2615
|
-
let commandDescription = commandFileData.command.description;
|
|
2616
|
-
if (!commandDescription && commandFileData.chatInput) commandDescription = "No command description set.";
|
|
2617
|
-
const updatedCommandData = {
|
|
2618
|
-
...commandFileData.command,
|
|
2619
|
-
name: commandName,
|
|
2620
|
-
description: commandDescription
|
|
2621
|
-
};
|
|
2622
|
-
let handlerCount = 0;
|
|
2623
|
-
for (const [key, propValidator] of Object.entries(commandDataSchema)) {
|
|
2624
|
-
const exportedProp = commandFileData[key];
|
|
2625
|
-
if (exportedProp) {
|
|
2626
|
-
if (!await propValidator(exportedProp)) throw new Error(`Invalid export for command ${command.name}: ${key} does not match expected value`);
|
|
2627
|
-
if (!KNOWN_NON_HANDLER_KEYS.includes(key)) handlerCount++;
|
|
2628
|
-
}
|
|
2629
|
-
}
|
|
2947
|
+
const { commandFileData, handlerCount, commandJson, resolvedMetadata } = await this.processCommandFile(command.path, command.name, command.name, false);
|
|
2630
2948
|
if (handlerCount === 0) throw new Error(`Invalid export for command ${command.name}: at least one handler function must be provided`);
|
|
2631
|
-
|
|
2632
|
-
await this.commandkit.plugins.execute(async (ctx, plugin) => {
|
|
2633
|
-
const res = await plugin.prepareCommand(ctx, lastUpdated);
|
|
2634
|
-
if (res) lastUpdated = res;
|
|
2635
|
-
});
|
|
2636
|
-
const commandJson = "toJSON" in lastUpdated && typeof lastUpdated.toJSON === "function" ? lastUpdated.toJSON() : lastUpdated;
|
|
2637
|
-
if ("guilds" in commandJson || "aliases" in commandJson) Logger.warn(`Command \`${command.name}\` uses deprecated metadata properties. Please update to use the new \`metadata\` object or \`generateMetadata\` function.`);
|
|
2638
|
-
const resolvedMetadata = {
|
|
2639
|
-
guilds: commandJson.guilds,
|
|
2640
|
-
aliases: commandJson.aliases,
|
|
2641
|
-
...metadata
|
|
2642
|
-
};
|
|
2643
|
-
this.loadedCommands.set(id, {
|
|
2949
|
+
const loadedCommand = {
|
|
2644
2950
|
discordId: null,
|
|
2645
2951
|
command,
|
|
2646
2952
|
metadata: resolvedMetadata,
|
|
@@ -2649,20 +2955,68 @@ var AppCommandHandler = class {
|
|
|
2649
2955
|
metadata: resolvedMetadata,
|
|
2650
2956
|
command: commandJson
|
|
2651
2957
|
}
|
|
2652
|
-
}
|
|
2958
|
+
};
|
|
2959
|
+
this.loadedCommands.set(id, loadedCommand);
|
|
2960
|
+
this.registerRuntimeRoute(loadedCommand);
|
|
2653
2961
|
this.generateContextMenuCommands(id, command, commandFileData, commandJson, resolvedMetadata);
|
|
2654
2962
|
} catch (error) {
|
|
2655
2963
|
Logger.error`Failed to load command ${command.name} (${id}): ${error}`;
|
|
2656
2964
|
}
|
|
2657
2965
|
}
|
|
2658
2966
|
/**
|
|
2967
|
+
* Loads a hierarchical command node into the hierarchical cache.
|
|
2968
|
+
* Executable leaves are also added to the runtime route index.
|
|
2969
|
+
* @private
|
|
2970
|
+
* @internal
|
|
2971
|
+
*/
|
|
2972
|
+
async loadHierarchicalNode(node, compiledRoute) {
|
|
2973
|
+
if (!node.definitionPath) return;
|
|
2974
|
+
const routeKey = node.route.join(".");
|
|
2975
|
+
const command = {
|
|
2976
|
+
id: node.id,
|
|
2977
|
+
name: routeKey,
|
|
2978
|
+
path: node.definitionPath,
|
|
2979
|
+
relativePath: (compiledRoute === null || compiledRoute === void 0 ? void 0 : compiledRoute.relativePath) ?? node.relativePath,
|
|
2980
|
+
parentPath: (0, node_path.dirname)(node.definitionPath),
|
|
2981
|
+
middlewares: compiledRoute ? [...compiledRoute.middlewares] : [],
|
|
2982
|
+
category: node.category
|
|
2983
|
+
};
|
|
2984
|
+
try {
|
|
2985
|
+
const { commandFileData, handlerCount, commandJson, resolvedMetadata } = await this.processCommandFile(command.path, routeKey, node.token, true);
|
|
2986
|
+
const isRootHierarchyLeaf = node.kind === "command";
|
|
2987
|
+
const hasContextMenuHandlers = !!(commandFileData.userContextMenu || commandFileData.messageContextMenu);
|
|
2988
|
+
const hasExecutableSlashHandlers = !!(commandFileData.chatInput || commandFileData.message || commandFileData.autocomplete);
|
|
2989
|
+
if (!isRootHierarchyLeaf && hasContextMenuHandlers) throw new Error(`Invalid export for hierarchical node ${routeKey}: context menu handlers are only supported for top-level root commands.`);
|
|
2990
|
+
if (node.executable && handlerCount === 0) throw new Error(`Invalid export for hierarchical node ${routeKey}: executable leaves must provide at least one handler function`);
|
|
2991
|
+
if (!node.executable && hasExecutableSlashHandlers) throw new Error(`Invalid export for hierarchical node ${routeKey}: non-leaf hierarchical nodes cannot export executable slash/prefix handlers`);
|
|
2992
|
+
const loadedCommand = {
|
|
2993
|
+
discordId: null,
|
|
2994
|
+
command,
|
|
2995
|
+
metadata: resolvedMetadata,
|
|
2996
|
+
data: {
|
|
2997
|
+
...commandFileData,
|
|
2998
|
+
metadata: resolvedMetadata,
|
|
2999
|
+
command: {
|
|
3000
|
+
...commandJson,
|
|
3001
|
+
__routeKey: routeKey
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
};
|
|
3005
|
+
this.hierarchicalNodes.set(node.id, loadedCommand);
|
|
3006
|
+
if (node.executable) this.registerRuntimeRoute(loadedCommand, routeKey);
|
|
3007
|
+
if (isRootHierarchyLeaf && hasContextMenuHandlers) this.generateContextMenuCommands(node.id, command, commandFileData, commandJson, resolvedMetadata);
|
|
3008
|
+
} catch (error) {
|
|
3009
|
+
Logger.error`Failed to load hierarchical node ${routeKey} (${node.id}): ${error}`;
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
2659
3013
|
* Gets the metadata for a command.
|
|
2660
3014
|
* @param command - The command name to get metadata for
|
|
2661
3015
|
* @param hint - The hint for the command type (user or message)
|
|
2662
3016
|
* @returns The command metadata or null if not found
|
|
2663
3017
|
*/
|
|
2664
3018
|
getMetadataFor(command, hint) {
|
|
2665
|
-
const loadedCommand = this.findCommandByName(command, hint);
|
|
3019
|
+
const loadedCommand = hint ? this.findCommandByName(command, hint) : this.findCommandByRoute(command);
|
|
2666
3020
|
if (!loadedCommand) return null;
|
|
2667
3021
|
return loadedCommand.metadata ??= {
|
|
2668
3022
|
aliases: [],
|
|
@@ -3707,6 +4061,61 @@ function ChannelSelectMenu(props) {
|
|
|
3707
4061
|
return builder;
|
|
3708
4062
|
}
|
|
3709
4063
|
|
|
4064
|
+
//#endregion
|
|
4065
|
+
//#region src/components/interactive/checkbox/checkbox.ts
|
|
4066
|
+
function Checkbox(props) {
|
|
4067
|
+
const checkbox = new discord_js.CheckboxBuilder();
|
|
4068
|
+
applyId(props, checkbox);
|
|
4069
|
+
if (props.customId != null) checkbox.setCustomId(props.customId);
|
|
4070
|
+
if (props.default != null) checkbox.setDefault(props.default);
|
|
4071
|
+
return checkbox;
|
|
4072
|
+
}
|
|
4073
|
+
function CheckboxGroupOption(props) {
|
|
4074
|
+
const option = new discord_js.CheckboxGroupOptionBuilder();
|
|
4075
|
+
option.setLabel(props.label);
|
|
4076
|
+
option.setValue(props.value);
|
|
4077
|
+
if (props.description != null) option.setDescription(props.description);
|
|
4078
|
+
if (props.default != null) option.setDefault(props.default);
|
|
4079
|
+
return option;
|
|
4080
|
+
}
|
|
4081
|
+
function CheckboxGroup(props) {
|
|
4082
|
+
const checkboxGroup = new discord_js.CheckboxGroupBuilder();
|
|
4083
|
+
applyId(props, checkboxGroup);
|
|
4084
|
+
if (props.customId != null) checkboxGroup.setCustomId(props.customId);
|
|
4085
|
+
if (props.required != null) checkboxGroup.setRequired(props.required);
|
|
4086
|
+
if (props.minValues != null) checkboxGroup.setMinValues(props.minValues);
|
|
4087
|
+
if (props.maxValues != null) checkboxGroup.setMaxValues(props.maxValues);
|
|
4088
|
+
if (props.children != null) {
|
|
4089
|
+
const options = (Array.isArray(props.children) ? props.children : [props.children]).filter((option) => option != null);
|
|
4090
|
+
if (options.length === 0) throw new Error("CheckboxGroup requires at least 1 option. Use <CheckboxGroupOption label=... value=... /> as a child.");
|
|
4091
|
+
checkboxGroup.setOptions(options);
|
|
4092
|
+
}
|
|
4093
|
+
return checkboxGroup;
|
|
4094
|
+
}
|
|
4095
|
+
|
|
4096
|
+
//#endregion
|
|
4097
|
+
//#region src/components/interactive/radio/radio.ts
|
|
4098
|
+
function RadioGroup(props) {
|
|
4099
|
+
const radioGroup = new discord_js.RadioGroupBuilder();
|
|
4100
|
+
applyId(props, radioGroup);
|
|
4101
|
+
radioGroup.setCustomId(props.customId);
|
|
4102
|
+
if (props.children != null) {
|
|
4103
|
+
const options = (Array.isArray(props.children) ? props.children : [props.children]).filter((option) => option != null);
|
|
4104
|
+
if (options.length === 0) throw new Error("RadioGroup requires at least 1 option. Use <RadioGroupOption label=... value=... /> as a child.");
|
|
4105
|
+
radioGroup.setOptions(options);
|
|
4106
|
+
}
|
|
4107
|
+
if (props.required != null) radioGroup.setRequired(props.required);
|
|
4108
|
+
return radioGroup;
|
|
4109
|
+
}
|
|
4110
|
+
function RadioGroupOption(props) {
|
|
4111
|
+
const option = new discord_js.RadioGroupOptionBuilder();
|
|
4112
|
+
option.setLabel(props.label);
|
|
4113
|
+
option.setValue(props.value);
|
|
4114
|
+
if (props.description != null) option.setDescription(props.description);
|
|
4115
|
+
if (props.default != null) option.setDefault(props.default);
|
|
4116
|
+
return option;
|
|
4117
|
+
}
|
|
4118
|
+
|
|
3710
4119
|
//#endregion
|
|
3711
4120
|
//#region src/components/display/container.ts
|
|
3712
4121
|
/**
|
|
@@ -4163,11 +4572,11 @@ function registerDevHooks(commandkit) {
|
|
|
4163
4572
|
if (prevented) return;
|
|
4164
4573
|
switch (event) {
|
|
4165
4574
|
case require_utils_constants.HMREventType.ReloadCommands:
|
|
4166
|
-
commandkit.commandHandler.reloadCommands();
|
|
4575
|
+
await commandkit.commandHandler.reloadCommands();
|
|
4167
4576
|
handled = true;
|
|
4168
4577
|
break;
|
|
4169
4578
|
case require_utils_constants.HMREventType.ReloadEvents:
|
|
4170
|
-
commandkit.eventHandler.reloadEvents();
|
|
4579
|
+
await commandkit.eventHandler.reloadEvents();
|
|
4171
4580
|
handled = true;
|
|
4172
4581
|
break;
|
|
4173
4582
|
case require_utils_constants.HMREventType.Unknown:
|
|
@@ -4670,6 +5079,24 @@ Object.defineProperty(exports, 'ChannelSelectMenuKit', {
|
|
|
4670
5079
|
return ChannelSelectMenuKit;
|
|
4671
5080
|
}
|
|
4672
5081
|
});
|
|
5082
|
+
Object.defineProperty(exports, 'Checkbox', {
|
|
5083
|
+
enumerable: true,
|
|
5084
|
+
get: function () {
|
|
5085
|
+
return Checkbox;
|
|
5086
|
+
}
|
|
5087
|
+
});
|
|
5088
|
+
Object.defineProperty(exports, 'CheckboxGroup', {
|
|
5089
|
+
enumerable: true,
|
|
5090
|
+
get: function () {
|
|
5091
|
+
return CheckboxGroup;
|
|
5092
|
+
}
|
|
5093
|
+
});
|
|
5094
|
+
Object.defineProperty(exports, 'CheckboxGroupOption', {
|
|
5095
|
+
enumerable: true,
|
|
5096
|
+
get: function () {
|
|
5097
|
+
return CheckboxGroupOption;
|
|
5098
|
+
}
|
|
5099
|
+
});
|
|
4673
5100
|
Object.defineProperty(exports, 'CommandExecutionMode', {
|
|
4674
5101
|
enumerable: true,
|
|
4675
5102
|
get: function () {
|
|
@@ -4832,6 +5259,18 @@ Object.defineProperty(exports, 'ParagraphInput', {
|
|
|
4832
5259
|
return ParagraphInput;
|
|
4833
5260
|
}
|
|
4834
5261
|
});
|
|
5262
|
+
Object.defineProperty(exports, 'RadioGroup', {
|
|
5263
|
+
enumerable: true,
|
|
5264
|
+
get: function () {
|
|
5265
|
+
return RadioGroup;
|
|
5266
|
+
}
|
|
5267
|
+
});
|
|
5268
|
+
Object.defineProperty(exports, 'RadioGroupOption', {
|
|
5269
|
+
enumerable: true,
|
|
5270
|
+
get: function () {
|
|
5271
|
+
return RadioGroupOption;
|
|
5272
|
+
}
|
|
5273
|
+
});
|
|
4835
5274
|
Object.defineProperty(exports, 'RoleSelectMenu', {
|
|
4836
5275
|
enumerable: true,
|
|
4837
5276
|
get: function () {
|
|
@@ -5144,4 +5583,4 @@ Object.defineProperty(exports, 'useStore', {
|
|
|
5144
5583
|
return useStore;
|
|
5145
5584
|
}
|
|
5146
5585
|
});
|
|
5147
|
-
//# sourceMappingURL=commandkit-
|
|
5586
|
+
//# sourceMappingURL=commandkit-D2HMPuRQ.js.map
|