discord-embed-router 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import EventEmitter from 'node:events';
1
2
  import { ParamData, Path, MatchFunction, MatchResult, TokenData } from 'path-to-regexp';
2
3
  import { InteractionEditReplyOptions, Interaction, ButtonInteraction, AnySelectMenuInteraction, InteractionReplyOptions, ButtonBuilder, APIButtonComponent, StringSelectMenuOptionBuilder, StringSelectMenuBuilder, StringSelectMenuComponentData, APIStringSelectComponent, RestOrArray, ChannelSelectMenuBuilder, ChannelSelectMenuComponentData, APIChannelSelectComponent, RoleSelectMenuBuilder, RoleSelectMenuComponentData, APIRoleSelectComponent, UserSelectMenuBuilder, UserSelectMenuComponentData, APIUserSelectComponent } from 'discord.js';
3
4
 
@@ -36,7 +37,26 @@ type ExtractParams<T extends string | TokenData, Depth extends string = ""> = T
36
37
  [K in Name]?: string;
37
38
  }) & ExtractParams<After, Depth> : ExtractParams<Rest, Depth> : Char extends "{" ? ExtractParams<Rest, `${Depth}1`> : Char extends "}" ? ExtractParams<Rest, Depth extends `1${infer Rest2}` ? Rest2 : Depth> : ExtractParams<Rest, Depth> : object : never;
38
39
 
39
- declare class EmbedRouter<L> {
40
+ type EventMap<T> = Record<keyof T, unknown[]>;
41
+ type IfEventMap<Events extends EventMap<Events>, True, False> = object extends Events ? False : True;
42
+ interface EventEmitterEventMap {
43
+ newListener: [
44
+ eventName: string | symbol,
45
+ listener: (...args: unknown[]) => void
46
+ ];
47
+ removeListener: [
48
+ eventName: string | symbol,
49
+ listener: (...args: unknown[]) => void
50
+ ];
51
+ }
52
+ type EventNames<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap<Events, EventName | (keyof Events & (string | symbol)) | keyof EventEmitterEventMap, string | symbol>;
53
+ type Args<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap<Events, EventName extends keyof Events ? Events[EventName] : EventName extends keyof EventEmitterEventMap ? EventEmitterEventMap[EventName] : unknown[], unknown[]>;
54
+ type Listener<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap<Events, (...args: EventName extends keyof Events ? Events[EventName] : EventName extends keyof EventEmitterEventMap ? EventEmitterEventMap[EventName] : unknown[]) => void, (...args: unknown[]) => void>;
55
+
56
+ type EmbedRouterEvents = {
57
+ routeError: [err: Error, interaction?: Interaction | undefined];
58
+ };
59
+ declare class EmbedRouter<L> extends EventEmitter<EmbedRouterEvents> {
40
60
  #private;
41
61
  getIdPrefix(): string;
42
62
  /**
@@ -110,6 +130,8 @@ declare class EmbedRouter<L> {
110
130
  flags?: InteractionReplyOptions["flags"] | undefined;
111
131
  locals?: L | undefined;
112
132
  }): Promise<void>;
133
+ onError(listener: Listener<EmbedRouterEvents, "routeError">): this;
134
+ emit<E extends string | symbol>(eventName: EventNames<EmbedRouterEvents, E>, ...args: Args<EmbedRouterEvents, E>): boolean;
113
135
  }
114
136
 
115
137
  type RouteOptions<AllowEmptyMethod extends boolean = false> = {
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import EventEmitter from 'node:events';
1
2
  import { ParamData, Path, MatchFunction, MatchResult, TokenData } from 'path-to-regexp';
2
3
  import { InteractionEditReplyOptions, Interaction, ButtonInteraction, AnySelectMenuInteraction, InteractionReplyOptions, ButtonBuilder, APIButtonComponent, StringSelectMenuOptionBuilder, StringSelectMenuBuilder, StringSelectMenuComponentData, APIStringSelectComponent, RestOrArray, ChannelSelectMenuBuilder, ChannelSelectMenuComponentData, APIChannelSelectComponent, RoleSelectMenuBuilder, RoleSelectMenuComponentData, APIRoleSelectComponent, UserSelectMenuBuilder, UserSelectMenuComponentData, APIUserSelectComponent } from 'discord.js';
3
4
 
@@ -36,7 +37,26 @@ type ExtractParams<T extends string | TokenData, Depth extends string = ""> = T
36
37
  [K in Name]?: string;
37
38
  }) & ExtractParams<After, Depth> : ExtractParams<Rest, Depth> : Char extends "{" ? ExtractParams<Rest, `${Depth}1`> : Char extends "}" ? ExtractParams<Rest, Depth extends `1${infer Rest2}` ? Rest2 : Depth> : ExtractParams<Rest, Depth> : object : never;
38
39
 
39
- declare class EmbedRouter<L> {
40
+ type EventMap<T> = Record<keyof T, unknown[]>;
41
+ type IfEventMap<Events extends EventMap<Events>, True, False> = object extends Events ? False : True;
42
+ interface EventEmitterEventMap {
43
+ newListener: [
44
+ eventName: string | symbol,
45
+ listener: (...args: unknown[]) => void
46
+ ];
47
+ removeListener: [
48
+ eventName: string | symbol,
49
+ listener: (...args: unknown[]) => void
50
+ ];
51
+ }
52
+ type EventNames<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap<Events, EventName | (keyof Events & (string | symbol)) | keyof EventEmitterEventMap, string | symbol>;
53
+ type Args<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap<Events, EventName extends keyof Events ? Events[EventName] : EventName extends keyof EventEmitterEventMap ? EventEmitterEventMap[EventName] : unknown[], unknown[]>;
54
+ type Listener<Events extends EventMap<Events>, EventName extends string | symbol> = IfEventMap<Events, (...args: EventName extends keyof Events ? Events[EventName] : EventName extends keyof EventEmitterEventMap ? EventEmitterEventMap[EventName] : unknown[]) => void, (...args: unknown[]) => void>;
55
+
56
+ type EmbedRouterEvents = {
57
+ routeError: [err: Error, interaction?: Interaction | undefined];
58
+ };
59
+ declare class EmbedRouter<L> extends EventEmitter<EmbedRouterEvents> {
40
60
  #private;
41
61
  getIdPrefix(): string;
42
62
  /**
@@ -110,6 +130,8 @@ declare class EmbedRouter<L> {
110
130
  flags?: InteractionReplyOptions["flags"] | undefined;
111
131
  locals?: L | undefined;
112
132
  }): Promise<void>;
133
+ onError(listener: Listener<EmbedRouterEvents, "routeError">): this;
134
+ emit<E extends string | symbol>(eventName: EventNames<EmbedRouterEvents, E>, ...args: Args<EmbedRouterEvents, E>): boolean;
113
135
  }
114
136
 
115
137
  type RouteOptions<AllowEmptyMethod extends boolean = false> = {
package/dist/index.js CHANGED
@@ -42,6 +42,7 @@ module.exports = __toCommonJS(index_exports);
42
42
 
43
43
  // src/EmbedRouter.ts
44
44
  var import_node_path = __toESM(require("path"));
45
+ var import_node_events = __toESM(require("events"));
45
46
  var import_node_crypto = require("crypto");
46
47
  var import_path_to_regexp3 = require("path-to-regexp");
47
48
  var import_discord = require("discord.js");
@@ -120,7 +121,7 @@ var decodePath = ({
120
121
  path: urlToPathString(
121
122
  fillParams(path2, {
122
123
  ts: interaction.createdTimestamp.toString(),
123
- [interaction.isChannelSelectMenu() ? "channelId" : interaction.isRoleSelectMenu() ? "roleId" : "userId"]: interaction.values[0].split("/").slice(1)
124
+ [interaction.isChannelSelectMenu() ? "channelId" : interaction.isRoleSelectMenu() ? "roleId" : "userId"]: interaction.values[0]
124
125
  })
125
126
  )
126
127
  };
@@ -170,7 +171,7 @@ var urlToPathString = (url) => {
170
171
  };
171
172
 
172
173
  // src/EmbedRouter.ts
173
- var EmbedRouter = class _EmbedRouter {
174
+ var EmbedRouter = class _EmbedRouter extends import_node_events.default {
174
175
  // identifier -> embedRouter
175
176
  static #usedIdentifiers = /* @__PURE__ */ new Map();
176
177
  // Name used to generate prefixes
@@ -194,6 +195,7 @@ var EmbedRouter = class _EmbedRouter {
194
195
  name = "",
195
196
  idPrefix = ID_PREFIX
196
197
  } = {}) {
198
+ super();
197
199
  if (_EmbedRouter.#usedIdentifiers.size >= PUA_RANGE) {
198
200
  throw new Error(`You can not have more than ${PUA_RANGE} routers`);
199
201
  }
@@ -308,13 +310,24 @@ var EmbedRouter = class _EmbedRouter {
308
310
  * @param interaction interactions from "interactionCreate" (filter for ButtonInteractions)
309
311
  */
310
312
  async listener(interaction, locals) {
311
- if (interaction.isAutocomplete())
312
- throw new Error("Autocomplete Interactions aren't supported");
313
- this.#runCleanup(interaction.message.id, false);
314
- const res = decodePath({ idPrefix: this.getIdPrefix(), interaction });
315
- if (!res)
316
- throw new Error(`Invalid component found: id ${interaction.customId}`);
317
- this.dispatch(interaction, res.path, { method: res.method, locals });
313
+ try {
314
+ if (interaction.isAutocomplete())
315
+ throw new Error("Autocomplete Interactions aren't supported");
316
+ await this.#runCleanup(interaction.message.id, false);
317
+ const res = decodePath({ idPrefix: this.getIdPrefix(), interaction });
318
+ if (!res)
319
+ throw new Error(`Invalid component found: id ${interaction.customId}`);
320
+ await this.dispatch(interaction, res.path, {
321
+ method: res.method,
322
+ locals
323
+ });
324
+ } catch (e) {
325
+ this.emit(
326
+ "routeError",
327
+ e instanceof Error ? e : new Error(String(e)),
328
+ interaction
329
+ );
330
+ }
318
331
  }
319
332
  /**
320
333
  * Replies to or editReplies to an interaction based on the route output
@@ -427,11 +440,29 @@ var EmbedRouter = class _EmbedRouter {
427
440
  async #runCleanup(messageId, applyResult) {
428
441
  const cleanup = this.#cleanups.get(messageId);
429
442
  if (!cleanup) return;
430
- this.#removeCleanup(messageId);
431
- const result = await cleanup?.cleanupFn();
432
- if (applyResult && result) {
433
- await cleanup.applyFn(result).catch(console.error);
443
+ try {
444
+ this.#removeCleanup(messageId);
445
+ const result = await cleanup?.cleanupFn();
446
+ if (applyResult && result) {
447
+ await cleanup.applyFn(result).catch(console.error);
448
+ }
449
+ } catch (e) {
450
+ this.emit(
451
+ "routeError",
452
+ e instanceof Error ? e : new Error(String(e)),
453
+ void 0
454
+ );
455
+ }
456
+ }
457
+ // event helpers
458
+ onError(listener) {
459
+ return this.on("routeError", listener);
460
+ }
461
+ emit(eventName, ...args) {
462
+ if (eventName === "routeError" && this.listenerCount(eventName) === 0) {
463
+ console.error(args);
434
464
  }
465
+ return super.emit(eventName, ...args);
435
466
  }
436
467
  };
437
468
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/EmbedRouter.ts","../src/consts.ts","../src/helpers/pathToString.ts","../src/helpers/decodePath.ts","../src/componentBuilders/RouteButtonBuilder.ts","../src/helpers/encodePath.ts","../src/componentBuilders/RouteStringSelectMenuBuilder.ts","../src/componentBuilders/RouteStringSelectMenuOptionBuilder.ts","../src/componentBuilders/RouteChannelSelectMenuBuilder.ts","../src/componentBuilders/RouteRoleSelectMenuBuilder.ts","../src/componentBuilders/RouteUserSelectMenuBuilder.ts"],"sourcesContent":["export { EmbedRouter } from \"./EmbedRouter\";\n\nexport { RouteButtonBuilder } from \"./componentBuilders/RouteButtonBuilder\";\nexport { RouteStringSelectMenuBuilder } from \"./componentBuilders/RouteStringSelectMenuBuilder\";\nexport { RouteStringSelectMenuOptionBuilder } from \"./componentBuilders/RouteStringSelectMenuOptionBuilder\";\nexport { RouteChannelSelectMenuBuilder } from \"./componentBuilders/RouteChannelSelectMenuBuilder\";\nexport { RouteRoleSelectMenuBuilder } from \"./componentBuilders/RouteRoleSelectMenuBuilder\";\nexport { RouteUserSelectMenuBuilder } from \"./componentBuilders/RouteUserSelectMenuBuilder\";\n\nexport type * from \"./types/routes\";\n","import path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { match, MatchResult, Path } from \"path-to-regexp\";\nimport type {\n\tApplyHandler,\n\tCompiledRoute,\n\tMethod,\n\tRouteHandler,\n\tRouteResponse,\n} from \"./types/routes\";\nimport type { ExtractParams } from \"./types/ExtractParams\";\nimport {\n\tAnySelectMenuInteraction,\n\tButtonInteraction,\n\tInteraction,\n\tInteractionReplyOptions,\n\tMessageFlags,\n\tSnowflake,\n} from \"discord.js\";\nimport { BASE_URL, ID_PREFIX, PUA_RANGE, PUA_START } from \"./consts\";\nimport { pathToString } from \"./helpers/pathToString\";\nimport { decodePath } from \"./helpers/decodePath\";\n\nexport class EmbedRouter<L> {\n\t// identifier -> embedRouter\n\tstatic #usedIdentifiers = new Map<string, EmbedRouter<unknown>>();\n\n\t// Name used to generate prefixes\n\t#name = \"\";\n\t// Prefix for customIds of RouteButtonBuilders\n\t#idPrefix: string;\n\t#identifier: string = \"\";\n\tpublic getIdPrefix() {\n\t\treturn `${this.#idPrefix}${this.#identifier}`;\n\t}\n\n\t// All added routes\n\t#routes: Map<Method, CompiledRoute<Method, L>[]> = new Map();\n\t// message.id -> cleanup object\n\t#cleanups: Map<\n\t\tSnowflake,\n\t\t{\n\t\t\ttimeout?: NodeJS.Timeout | undefined;\n\t\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>;\n\t\t\tapplyFn: ApplyHandler;\n\t\t}\n\t> = new Map();\n\n\t/**\n\t *\n\t * @param name the name to give the router. ensures buttons stay connected across restarts\n\t * @param idPrefix the prefix for RouteButtonBuilder customIds\n\t */\n\tconstructor({\n\t\tname = \"\",\n\t\tidPrefix = ID_PREFIX,\n\t}: {\n\t\tname?: string | undefined;\n\t\tidPrefix?: string | undefined;\n\t} = {}) {\n\t\tif (EmbedRouter.#usedIdentifiers.size >= PUA_RANGE) {\n\t\t\tthrow new Error(`You can not have more than ${PUA_RANGE} routers`);\n\t\t}\n\t\tif (idPrefix.includes(\"/\")) {\n\t\t\tthrow new Error(`Prefix can't contain \"/\": ${idPrefix}`);\n\t\t}\n\t\tthis.#idPrefix = idPrefix;\n\t\tthis.#name = name;\n\t\tthis.#updateIdentifier();\n\t}\n\n\t#updateIdentifier() {\n\t\t// Private Use Area: Unicode Characters not from any language\n\t\tconst hash = createHash(\"sha256\").update(this.#name).digest();\n\t\tlet raw = hash.readUint32BE(0);\n\t\tlet char: string;\n\t\tconst nameCollisions = [];\n\t\t// find next available identifier\n\t\twhile (true) {\n\t\t\tconst codepoint = PUA_START + (raw++ % PUA_RANGE);\n\t\t\tchar = String.fromCodePoint(codepoint);\n\n\t\t\tconst collisionRouter = EmbedRouter.#usedIdentifiers.get(char);\n\t\t\tif (collisionRouter === undefined) break; // no collisions\n\n\t\t\tif (this.#name.length > 0 && collisionRouter.#name.length === 0) {\n\t\t\t\t// evict old name; usedIdentifier is still taken\n\t\t\t\tcollisionRouter.#updateIdentifier();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnameCollisions.push(collisionRouter);\n\t\t}\n\t\tEmbedRouter.#usedIdentifiers.set(char, this as EmbedRouter<unknown>);\n\n\t\tif (nameCollisions.length > 0 && this.#name.length > 0) {\n\t\t\tprocess.emitWarning(\n\t\t\t\t`EmbedRouter identifier collision for name \"${this.#name}\" with ${nameCollisions.map((c) => `\"${c.#name}\"`).join(\", \")}`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\t\t}\n\t\tthis.#identifier = char;\n\t}\n\n\t#addRoute<M extends Method, P extends Path = Path>(\n\t\tmethod: M,\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<M, L, ExtractParams<P>>,\n\t) {\n\t\tconst methodRoutes = this.#routes.get(method) ?? [];\n\t\tmethodRoutes.push({\n\t\t\tmethod,\n\t\t\tpath: Array.isArray(routePath) ? routePath : [routePath],\n\t\t\tmatchFunction: match(routePath),\n\t\t\thandler: handler as RouteHandler<M, L>,\n\t\t});\n\t\tthis.#routes.set(method, methodRoutes);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic get<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"GET\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"GET\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic post<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"POST\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"POST\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic put<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PUT\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PUT\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic patch<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PATCH\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PATCH\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic delete<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"DELETE\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"DELETE\", routePath, handler);\n\t}\n\n\t/**\n\t * Adds a subrouter to the router\n\t *\n\t * @param routePath path of the router\n\t * @param embedRouter router to add at the path\n\t */\n\tpublic use<P extends Path = Path>(\n\t\troutePath: P,\n\t\tembedRouter: EmbedRouter<Partial<L>>,\n\t) {\n\t\tconst pathString = pathToString(routePath);\n\t\tfor (const [method, routes] of embedRouter.#routes) {\n\t\t\tfor (const route of routes) {\n\t\t\t\tthis.#addRoute(\n\t\t\t\t\tmethod,\n\t\t\t\t\troute.path.map((p) => path.posix.join(pathString, pathToString(p))),\n\t\t\t\t\troute.handler,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Must be attached to \"interactionCreate\" event for RouteButtonBuilder to work\n\t *\n\t * @param interaction interactions from \"interactionCreate\" (filter for ButtonInteractions)\n\t */\n\tpublic async listener(\n\t\tinteraction: ButtonInteraction | AnySelectMenuInteraction,\n\t\tlocals?: L | undefined,\n\t) {\n\t\tif (interaction.isAutocomplete())\n\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\tthis.#runCleanup(interaction.message.id, false);\n\n\t\tconst res = decodePath({ idPrefix: this.getIdPrefix(), interaction });\n\t\tif (!res)\n\t\t\tthrow new Error(`Invalid component found: id ${interaction.customId}`);\n\n\t\tthis.dispatch(interaction, res.path, { method: res.method, locals });\n\t}\n\n\t/**\n\t * Replies to or editReplies to an interaction based on the route output\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param flags discord flags to send with message (optional, only allowed on first reply)\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t */\n\tpublic async dispatch<P extends Path = Path>(\n\t\tinteraction: Interaction,\n\t\tpath: P,\n\t\t{\n\t\t\tmethod = \"GET\",\n\t\t\tflags,\n\t\t\tlocals,\n\t\t}: {\n\t\t\tmethod?: Method;\n\t\t\tflags?: InteractionReplyOptions[\"flags\"] | undefined;\n\t\t\tlocals?: L | undefined;\n\t\t} = {},\n\t) {\n\t\tif (interaction.isAutocomplete())\n\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\t// don't check validity because url params are considered invalid\n\t\tconst routeResponse = await this.#resolve(path, {\n\t\t\tinteraction,\n\t\t\tmethod,\n\t\t\tlocals,\n\t\t});\n\t\tif (routeResponse === false)\n\t\t\tthrow new Error(`No route found for ${pathToString(path, false)}`);\n\n\t\tif (interaction.replied || interaction.deferred) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tif (routeResponse) await interaction.editReply(routeResponse);\n\t\t} else if (!routeResponse) {\n\t\t\tif (\"deferUpdate\" in interaction) {\n\t\t\t\tawait interaction.deferUpdate();\n\t\t\t} else {\n\t\t\t\tawait interaction.deferReply();\n\t\t\t}\n\t\t} else if (\"update\" in interaction) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tawait interaction.update(routeResponse);\n\t\t} else {\n\t\t\tawait interaction.reply({\n\t\t\t\t...(routeResponse as InteractionReplyOptions),\n\t\t\t\tflags,\n\t\t\t});\n\t\t}\n\n\t\t// Apply cleanup if needed\n\t\tif (!routeResponse?.cleanup) return;\n\n\t\tconst message = await interaction.fetchReply();\n\t\tconst channel = interaction.channel;\n\t\tconst applyFn: ApplyHandler | undefined = message.flags.has(\n\t\t\tMessageFlags.Ephemeral,\n\t\t)\n\t\t\t? interaction.editReply.bind(interaction)\n\t\t\t: channel\n\t\t\t\t? (options) => channel.messages.edit(message.id, options)\n\t\t\t\t: undefined;\n\t\tif (!applyFn)\n\t\t\treturn process.emitWarning(\n\t\t\t\t`Could not derive applyFunction for ${pathToString(path, false)}. Cleanup return results will not be applied to message.`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\n\t\tthis.#addCleanup(\n\t\t\tmessage.id,\n\t\t\trouteResponse.cleanup.bind(routeResponse),\n\t\t\tapplyFn,\n\t\t\trouteResponse?.timeout,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves a route to the associated message (DOES NOT UPDATE MESSAGE)\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t * @returns discord message associated with route OR false\n\t */\n\tasync #resolve<P extends Path>(\n\t\tpath: P,\n\t\t{\n\t\t\tinteraction,\n\t\t\tmethod = \"GET\",\n\t\t\tlocals,\n\t\t}: {\n\t\t\tinteraction: Interaction;\n\t\t\tmethod?: Method;\n\t\t\tlocals?: L | undefined;\n\t\t},\n\t): Promise<RouteResponse | undefined | false> {\n\t\t// don't check validity because url params are considered invalid\n\t\tconst url = new URL(pathToString(path, false), BASE_URL);\n\t\tfor (const route of this.#routes.get(method) ?? []) {\n\t\t\tconst result = route.matchFunction(url.pathname);\n\t\t\tif (result) {\n\t\t\t\treturn await route.handler(interaction, {\n\t\t\t\t\t...(result as MatchResult<ExtractParams<P>>),\n\t\t\t\t\tquery: url.searchParams,\n\t\t\t\t\tembedRouter: this,\n\t\t\t\t\tlocals,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Helpers for using and storing cleanup functions\n\t#addCleanup(\n\t\tmessageId: Snowflake,\n\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>,\n\t\tapplyFn: ApplyHandler,\n\t\ttimeout: number,\n\t) {\n\t\tthis.#removeCleanup(messageId);\n\t\tthis.#cleanups.set(messageId, {\n\t\t\tcleanupFn,\n\t\t\tapplyFn,\n\t\t\ttimeout: isFinite(timeout)\n\t\t\t\t? setTimeout(() => this.#runCleanup(messageId, true), timeout)\n\t\t\t\t: undefined,\n\t\t});\n\t}\n\n\t#removeCleanup(messageId: Snowflake) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\tclearTimeout(cleanup.timeout);\n\t\tthis.#cleanups.delete(messageId);\n\t}\n\n\tasync #runCleanup(messageId: Snowflake, applyResult: boolean) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\tthis.#removeCleanup(messageId);\n\t\tconst result = await cleanup?.cleanupFn();\n\t\tif (applyResult && result) {\n\t\t\tawait cleanup.applyFn(result).catch(console.error);\n\t\t}\n\t}\n}\n","import { Method } from \"./types/routes\";\n\nexport const ID_PREFIX = \"der\";\nexport const METHOD_TO_ENCODING: Record<Method, string> = {\n\tGET: \"G\",\n\tPOST: \"P\",\n\tPUT: \"U\",\n\tPATCH: \"A\",\n\tDELETE: \"D\",\n};\nexport const ENCODING_TO_METHOD: Record<string, Method> = {\n\tG: \"GET\",\n\tP: \"POST\",\n\tU: \"PUT\",\n\tA: \"PATCH\",\n\tD: \"DELETE\",\n};\n// base url is never sent; only used for processing locally\nexport const BASE_URL = \"discord://embed.router\";\n\nexport const PUA_START = 0xe000;\nexport const PUA_END = 0xf8ff;\nexport const PUA_RANGE = PUA_END - PUA_START + 1;\n","import { parse, Path, stringify, TokenData } from \"path-to-regexp\";\n\nexport const pathToString = <P extends Path>(\n\tpath: P,\n\tcheckValidity = true,\n): string => {\n\tif (checkValidity) {\n\t\treturn stringify(path instanceof TokenData ? path : parse(path));\n\t}\n\treturn typeof path === \"string\" ? path : stringify(path);\n};\n","import { compile, Path } from \"path-to-regexp\";\nimport { AnySelectMenuInteraction, ButtonInteraction } from \"discord.js\";\nimport { BASE_URL, ENCODING_TO_METHOD } from \"../consts\";\nimport { Method } from \"../types/routes\";\n\nexport const decodePath = ({\n\tidPrefix,\n\tinteraction,\n}: {\n\tidPrefix: string;\n\tinteraction: ButtonInteraction | AnySelectMenuInteraction;\n}): { method: Method; path: Path } | false => {\n\tconst customId = interaction.customId;\n\tif (!customId.startsWith(idPrefix)) return false;\n\n\tconst res = parseMethodAndPath(customId.slice(idPrefix.length));\n\tif (!res) return false;\n\tconst { method, path } = res;\n\n\tif (interaction.isButton()) {\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t} else if (interaction.isAnySelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\n\t\tif (interaction.isStringSelectMenu()) {\n\t\t\t// also fill in variables for to's\n\t\t\tconst toRes = parseOptionalMethodAndPath(interaction.values[0]!);\n\t\t\tconst toURL = toRes\n\t\t\t\t? fillParams(toRes.path, {\n\t\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t\tconst pathURL = fillParams(path, {\n\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\tto: toURL ? toURL.pathname.split(\"/\").slice(1) : \"\",\n\t\t\t});\n\t\t\t// merge query params\n\t\t\tfor (const [key, value] of toURL?.searchParams ?? []) {\n\t\t\t\tpathURL.searchParams.append(key, value);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod,\n\t\t\t\tpath: urlToPathString(pathURL),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t[interaction.isChannelSelectMenu()\n\t\t\t\t\t\t? \"channelId\"\n\t\t\t\t\t\t: interaction.isRoleSelectMenu()\n\t\t\t\t\t\t\t? \"roleId\"\n\t\t\t\t\t\t\t: \"userId\"]: interaction.values[0]!.split(\"/\").slice(1),\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn false;\n};\n\nconst parseMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\tif (method === undefined) return false;\n\treturn {\n\t\tmethod,\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst parseOptionalMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method | \"\"; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\treturn {\n\t\tmethod: method ?? \"\",\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst fillParams = (\n\tpath: string,\n\tparams: Partial<Record<string, string | string[]>> = {},\n): URL => {\n\tconst url = new URL(path, BASE_URL);\n\tconst toPath = compile(url.pathname);\n\n\turl.pathname = toPath(params);\n\tfor (const [key, value] of url.searchParams) {\n\t\tif (value.startsWith(\":\") && value.slice(1) in params) {\n\t\t\tconst paramValue = params?.[value.slice(1)];\n\t\t\tif (paramValue) {\n\t\t\t\turl.searchParams.set(\n\t\t\t\t\tkey,\n\t\t\t\t\tArray.isArray(paramValue) ? paramValue.join(\"/\") : paramValue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\turl.searchParams.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\treturn url;\n};\n\nconst urlToPathString = (url: URL): string => {\n\treturn `${url.pathname}${url.search}`;\n};\n","import { APIButtonComponent, ButtonBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteButtonBuilder<L> extends ButtonBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?: Omit<Partial<APIButtonComponent>, \"custom_id\" | \"url\"> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setURL(): this {\n\t\tthrow new Error(\"setURL is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\"setCustomId is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t): this {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { Path } from \"path-to-regexp\";\nimport { BASE_URL, METHOD_TO_ENCODING } from \"../consts\";\nimport { pathToString } from \"./pathToString\";\nimport { Method } from \"../types/routes\";\n\nexport const encodePath = <AllowEmptyMethod extends boolean = false>({\n\tidPrefix,\n\tmethod,\n\tpath,\n\tquery,\n}: {\n\tidPrefix: string;\n\tmethod: AllowEmptyMethod extends false ? Method : Method | \"\";\n\tpath: Path;\n\tquery?: ConstructorParameters<typeof URLSearchParams>[0] | undefined;\n}) => {\n\tconst url = new URL(pathToString(path), BASE_URL);\n\tif (query) {\n\t\tfor (const [key, value] of new URLSearchParams(query)) {\n\t\t\turl.searchParams.set(key, value);\n\t\t}\n\t}\n\treturn `${idPrefix}${method === \"\" ? \"\" : METHOD_TO_ENCODING[method as Method]}${url.pathname}${url.search}`;\n};\n","import {\n\tAPIStringSelectComponent,\n\tnormalizeArray,\n\tRestOrArray,\n\tStringSelectMenuBuilder,\n\tStringSelectMenuComponentData,\n} from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { RouteStringSelectMenuOptionBuilder } from \"./RouteStringSelectMenuOptionBuilder\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuBuilder<L> extends StringSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param path the path to redirect to, :to or *to in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :to will be replaced with the selected user's id\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<StringSelectMenuComponentData | APIStringSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: \"/*to\",\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use addTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride addOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"addOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use setTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"setOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Adds route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic addTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.addOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic setTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.setOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :to *to\n\t * @param query any query parameters you want to add, can include :ts :to *to\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { StringSelectMenuOptionBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuOptionBuilder extends StringSelectMenuOptionBuilder {\n\t/**\n\t * Not supported for RouteStringSelectMenuOptionBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setValue(): this {\n\t\tthrow new Error(\n\t\t\t\"setValue is not supported on RouteStringSelectMenuOptionBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the path to route to when selected\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"\", query }: RouteOptions<true> = {},\n\t): this {\n\t\tsuper.setValue(\n\t\t\tencodePath<true>({\n\t\t\t\tidPrefix: \"\",\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIChannelSelectComponent,\n\tChannelSelectMenuBuilder,\n\tChannelSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteChannelSelectMenuBuilder<L> extends ChannelSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<ChannelSelectMenuComponentData | APIChannelSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteChannelSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteChannelSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :channelId\n\t * @param query any query parameters you want to add, can include :ts :channelId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIRoleSelectComponent,\n\tRoleSelectMenuBuilder,\n\tRoleSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteRoleSelectMenuBuilder<L> extends RoleSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<RoleSelectMenuComponentData | APIRoleSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteRoleSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteRoleSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :roleId\n\t * @param query any query parameters you want to add, can include :ts :roleId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIUserSelectComponent,\n\tUserSelectMenuBuilder,\n\tUserSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteUserSelectMenuBuilder<L> extends UserSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<UserSelectMenuComponentData | APIUserSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteUserSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteUserSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :userId\n\t * @param query any query parameters you want to add, can include :ts :userId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n"],"mappings":"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","names":["import_path_to_regexp","path","import_path_to_regexp","path","path","import_discord","path","path","import_discord","import_discord","path","path","import_discord","path","import_discord","path","import_discord","path"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/EmbedRouter.ts","../src/consts.ts","../src/helpers/pathToString.ts","../src/helpers/decodePath.ts","../src/componentBuilders/RouteButtonBuilder.ts","../src/helpers/encodePath.ts","../src/componentBuilders/RouteStringSelectMenuBuilder.ts","../src/componentBuilders/RouteStringSelectMenuOptionBuilder.ts","../src/componentBuilders/RouteChannelSelectMenuBuilder.ts","../src/componentBuilders/RouteRoleSelectMenuBuilder.ts","../src/componentBuilders/RouteUserSelectMenuBuilder.ts"],"sourcesContent":["export { EmbedRouter } from \"./EmbedRouter\";\n\nexport { RouteButtonBuilder } from \"./componentBuilders/RouteButtonBuilder\";\nexport { RouteStringSelectMenuBuilder } from \"./componentBuilders/RouteStringSelectMenuBuilder\";\nexport { RouteStringSelectMenuOptionBuilder } from \"./componentBuilders/RouteStringSelectMenuOptionBuilder\";\nexport { RouteChannelSelectMenuBuilder } from \"./componentBuilders/RouteChannelSelectMenuBuilder\";\nexport { RouteRoleSelectMenuBuilder } from \"./componentBuilders/RouteRoleSelectMenuBuilder\";\nexport { RouteUserSelectMenuBuilder } from \"./componentBuilders/RouteUserSelectMenuBuilder\";\n\nexport type * from \"./types/routes\";\n","import path from \"node:path\";\nimport EventEmitter from \"node:events\";\nimport { createHash } from \"node:crypto\";\nimport { match, MatchResult, Path } from \"path-to-regexp\";\nimport type {\n\tApplyHandler,\n\tCompiledRoute,\n\tMethod,\n\tRouteHandler,\n\tRouteResponse,\n} from \"./types/routes\";\nimport type { ExtractParams } from \"./types/ExtractParams\";\nimport {\n\tAnySelectMenuInteraction,\n\tButtonInteraction,\n\tInteraction,\n\tInteractionReplyOptions,\n\tMessageFlags,\n\tSnowflake,\n} from \"discord.js\";\nimport { BASE_URL, ID_PREFIX, PUA_RANGE, PUA_START } from \"./consts\";\nimport { pathToString } from \"./helpers/pathToString\";\nimport { decodePath } from \"./helpers/decodePath\";\nimport { Args, EventNames, Listener } from \"./types/EmbedRouterEvents\";\n\ntype EmbedRouterEvents = {\n\trouteError: [err: Error, interaction?: Interaction | undefined];\n};\n\nexport class EmbedRouter<L> extends EventEmitter<EmbedRouterEvents> {\n\t// identifier -> embedRouter\n\tstatic #usedIdentifiers = new Map<string, EmbedRouter<unknown>>();\n\n\t// Name used to generate prefixes\n\t#name = \"\";\n\t// Prefix for customIds of RouteButtonBuilders\n\t#idPrefix: string;\n\t#identifier: string = \"\";\n\tpublic getIdPrefix() {\n\t\treturn `${this.#idPrefix}${this.#identifier}`;\n\t}\n\n\t// All added routes\n\t#routes: Map<Method, CompiledRoute<Method, L>[]> = new Map();\n\t// message.id -> cleanup object\n\t#cleanups: Map<\n\t\tSnowflake,\n\t\t{\n\t\t\ttimeout?: NodeJS.Timeout | undefined;\n\t\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>;\n\t\t\tapplyFn: ApplyHandler;\n\t\t}\n\t> = new Map();\n\n\t/**\n\t *\n\t * @param name the name to give the router. ensures buttons stay connected across restarts\n\t * @param idPrefix the prefix for RouteButtonBuilder customIds\n\t */\n\tconstructor({\n\t\tname = \"\",\n\t\tidPrefix = ID_PREFIX,\n\t}: {\n\t\tname?: string | undefined;\n\t\tidPrefix?: string | undefined;\n\t} = {}) {\n\t\tsuper();\n\n\t\tif (EmbedRouter.#usedIdentifiers.size >= PUA_RANGE) {\n\t\t\tthrow new Error(`You can not have more than ${PUA_RANGE} routers`);\n\t\t}\n\t\tif (idPrefix.includes(\"/\")) {\n\t\t\tthrow new Error(`Prefix can't contain \"/\": ${idPrefix}`);\n\t\t}\n\t\tthis.#idPrefix = idPrefix;\n\t\tthis.#name = name;\n\t\tthis.#updateIdentifier();\n\t}\n\n\t#updateIdentifier() {\n\t\t// Private Use Area: Unicode Characters not from any language\n\t\tconst hash = createHash(\"sha256\").update(this.#name).digest();\n\t\tlet raw = hash.readUint32BE(0);\n\t\tlet char: string;\n\t\tconst nameCollisions = [];\n\t\t// find next available identifier\n\t\twhile (true) {\n\t\t\tconst codepoint = PUA_START + (raw++ % PUA_RANGE);\n\t\t\tchar = String.fromCodePoint(codepoint);\n\n\t\t\tconst collisionRouter = EmbedRouter.#usedIdentifiers.get(char);\n\t\t\tif (collisionRouter === undefined) break; // no collisions\n\n\t\t\tif (this.#name.length > 0 && collisionRouter.#name.length === 0) {\n\t\t\t\t// evict old name; usedIdentifier is still taken\n\t\t\t\tcollisionRouter.#updateIdentifier();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnameCollisions.push(collisionRouter);\n\t\t}\n\t\tEmbedRouter.#usedIdentifiers.set(char, this as EmbedRouter<unknown>);\n\n\t\tif (nameCollisions.length > 0 && this.#name.length > 0) {\n\t\t\tprocess.emitWarning(\n\t\t\t\t`EmbedRouter identifier collision for name \"${this.#name}\" with ${nameCollisions.map((c) => `\"${c.#name}\"`).join(\", \")}`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\t\t}\n\t\tthis.#identifier = char;\n\t}\n\n\t#addRoute<M extends Method, P extends Path = Path>(\n\t\tmethod: M,\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<M, L, ExtractParams<P>>,\n\t) {\n\t\tconst methodRoutes = this.#routes.get(method) ?? [];\n\t\tmethodRoutes.push({\n\t\t\tmethod,\n\t\t\tpath: Array.isArray(routePath) ? routePath : [routePath],\n\t\t\tmatchFunction: match(routePath),\n\t\t\thandler: handler as RouteHandler<M, L>,\n\t\t});\n\t\tthis.#routes.set(method, methodRoutes);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic get<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"GET\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"GET\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic post<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"POST\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"POST\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic put<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PUT\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PUT\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic patch<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PATCH\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PATCH\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic delete<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"DELETE\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"DELETE\", routePath, handler);\n\t}\n\n\t/**\n\t * Adds a subrouter to the router\n\t *\n\t * @param routePath path of the router\n\t * @param embedRouter router to add at the path\n\t */\n\tpublic use<P extends Path = Path>(\n\t\troutePath: P,\n\t\tembedRouter: EmbedRouter<Partial<L>>,\n\t) {\n\t\tconst pathString = pathToString(routePath);\n\t\tfor (const [method, routes] of embedRouter.#routes) {\n\t\t\tfor (const route of routes) {\n\t\t\t\tthis.#addRoute(\n\t\t\t\t\tmethod,\n\t\t\t\t\troute.path.map((p) => path.posix.join(pathString, pathToString(p))),\n\t\t\t\t\troute.handler,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Must be attached to \"interactionCreate\" event for RouteButtonBuilder to work\n\t *\n\t * @param interaction interactions from \"interactionCreate\" (filter for ButtonInteractions)\n\t */\n\tpublic async listener(\n\t\tinteraction: ButtonInteraction | AnySelectMenuInteraction,\n\t\tlocals?: L | undefined,\n\t) {\n\t\ttry {\n\t\t\tif (interaction.isAutocomplete())\n\t\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\t\tawait this.#runCleanup(interaction.message.id, false);\n\n\t\t\tconst res = decodePath({ idPrefix: this.getIdPrefix(), interaction });\n\t\t\tif (!res)\n\t\t\t\tthrow new Error(`Invalid component found: id ${interaction.customId}`);\n\n\t\t\tawait this.dispatch(interaction, res.path, {\n\t\t\t\tmethod: res.method,\n\t\t\t\tlocals,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tthis.emit(\n\t\t\t\t\"routeError\",\n\t\t\t\te instanceof Error ? e : new Error(String(e)),\n\t\t\t\tinteraction,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Replies to or editReplies to an interaction based on the route output\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param flags discord flags to send with message (optional, only allowed on first reply)\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t */\n\tpublic async dispatch<P extends Path = Path>(\n\t\tinteraction: Interaction,\n\t\tpath: P,\n\t\t{\n\t\t\tmethod = \"GET\",\n\t\t\tflags,\n\t\t\tlocals,\n\t\t}: {\n\t\t\tmethod?: Method;\n\t\t\tflags?: InteractionReplyOptions[\"flags\"] | undefined;\n\t\t\tlocals?: L | undefined;\n\t\t} = {},\n\t) {\n\t\tif (interaction.isAutocomplete())\n\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\t// don't check validity because url params are considered invalid\n\t\tconst routeResponse = await this.#resolve(path, {\n\t\t\tinteraction,\n\t\t\tmethod,\n\t\t\tlocals,\n\t\t});\n\t\tif (routeResponse === false)\n\t\t\tthrow new Error(`No route found for ${pathToString(path, false)}`);\n\n\t\tif (interaction.replied || interaction.deferred) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tif (routeResponse) await interaction.editReply(routeResponse);\n\t\t} else if (!routeResponse) {\n\t\t\tif (\"deferUpdate\" in interaction) {\n\t\t\t\tawait interaction.deferUpdate();\n\t\t\t} else {\n\t\t\t\tawait interaction.deferReply();\n\t\t\t}\n\t\t} else if (\"update\" in interaction) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tawait interaction.update(routeResponse);\n\t\t} else {\n\t\t\tawait interaction.reply({\n\t\t\t\t...(routeResponse as InteractionReplyOptions),\n\t\t\t\tflags,\n\t\t\t});\n\t\t}\n\n\t\t// Apply cleanup if needed\n\t\tif (!routeResponse?.cleanup) return;\n\n\t\tconst message = await interaction.fetchReply();\n\t\tconst channel = interaction.channel;\n\t\tconst applyFn: ApplyHandler | undefined = message.flags.has(\n\t\t\tMessageFlags.Ephemeral,\n\t\t)\n\t\t\t? interaction.editReply.bind(interaction)\n\t\t\t: channel\n\t\t\t\t? (options) => channel.messages.edit(message.id, options)\n\t\t\t\t: undefined;\n\t\tif (!applyFn)\n\t\t\treturn process.emitWarning(\n\t\t\t\t`Could not derive applyFunction for ${pathToString(path, false)}. Cleanup return results will not be applied to message.`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\n\t\tthis.#addCleanup(\n\t\t\tmessage.id,\n\t\t\trouteResponse.cleanup.bind(routeResponse),\n\t\t\tapplyFn,\n\t\t\trouteResponse?.timeout,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves a route to the associated message (DOES NOT UPDATE MESSAGE)\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t * @returns discord message associated with route OR false\n\t */\n\tasync #resolve<P extends Path>(\n\t\tpath: P,\n\t\t{\n\t\t\tinteraction,\n\t\t\tmethod = \"GET\",\n\t\t\tlocals,\n\t\t}: {\n\t\t\tinteraction: Interaction;\n\t\t\tmethod?: Method;\n\t\t\tlocals?: L | undefined;\n\t\t},\n\t): Promise<RouteResponse | undefined | false> {\n\t\t// don't check validity because url params are considered invalid\n\t\tconst url = new URL(pathToString(path, false), BASE_URL);\n\t\tfor (const route of this.#routes.get(method) ?? []) {\n\t\t\tconst result = route.matchFunction(url.pathname);\n\t\t\tif (result) {\n\t\t\t\treturn await route.handler(interaction, {\n\t\t\t\t\t...(result as MatchResult<ExtractParams<P>>),\n\t\t\t\t\tquery: url.searchParams,\n\t\t\t\t\tembedRouter: this,\n\t\t\t\t\tlocals,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Helpers for using and storing cleanup functions\n\t#addCleanup(\n\t\tmessageId: Snowflake,\n\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>,\n\t\tapplyFn: ApplyHandler,\n\t\ttimeout: number,\n\t) {\n\t\tthis.#removeCleanup(messageId);\n\t\tthis.#cleanups.set(messageId, {\n\t\t\tcleanupFn,\n\t\t\tapplyFn,\n\t\t\ttimeout: isFinite(timeout)\n\t\t\t\t? setTimeout(() => this.#runCleanup(messageId, true), timeout)\n\t\t\t\t: undefined,\n\t\t});\n\t}\n\n\t#removeCleanup(messageId: Snowflake) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\tclearTimeout(cleanup.timeout);\n\t\tthis.#cleanups.delete(messageId);\n\t}\n\n\tasync #runCleanup(messageId: Snowflake, applyResult: boolean) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\ttry {\n\t\t\tthis.#removeCleanup(messageId);\n\t\t\tconst result = await cleanup?.cleanupFn();\n\t\t\tif (applyResult && result) {\n\t\t\t\tawait cleanup.applyFn(result).catch(console.error);\n\t\t\t}\n\t\t} catch (e: unknown) {\n\t\t\tthis.emit(\n\t\t\t\t\"routeError\",\n\t\t\t\te instanceof Error ? e : new Error(String(e)),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t}\n\t}\n\n\t// event helpers\n\tpublic onError(listener: Listener<EmbedRouterEvents, \"routeError\">) {\n\t\treturn this.on(\"routeError\", listener);\n\t}\n\n\toverride emit<E extends string | symbol>(\n\t\teventName: EventNames<EmbedRouterEvents, E>,\n\t\t...args: Args<EmbedRouterEvents, E>\n\t): boolean {\n\t\tif (eventName === \"routeError\" && this.listenerCount(eventName) === 0) {\n\t\t\tconsole.error(args);\n\t\t}\n\t\treturn super.emit(eventName, ...args);\n\t}\n}\n","import { Method } from \"./types/routes\";\n\nexport const ID_PREFIX = \"der\";\nexport const METHOD_TO_ENCODING: Record<Method, string> = {\n\tGET: \"G\",\n\tPOST: \"P\",\n\tPUT: \"U\",\n\tPATCH: \"A\",\n\tDELETE: \"D\",\n};\nexport const ENCODING_TO_METHOD: Record<string, Method> = {\n\tG: \"GET\",\n\tP: \"POST\",\n\tU: \"PUT\",\n\tA: \"PATCH\",\n\tD: \"DELETE\",\n};\n// base url is never sent; only used for processing locally\nexport const BASE_URL = \"discord://embed.router\";\n\nexport const PUA_START = 0xe000;\nexport const PUA_END = 0xf8ff;\nexport const PUA_RANGE = PUA_END - PUA_START + 1;\n","import { parse, Path, stringify, TokenData } from \"path-to-regexp\";\n\nexport const pathToString = <P extends Path>(\n\tpath: P,\n\tcheckValidity = true,\n): string => {\n\tif (checkValidity) {\n\t\treturn stringify(path instanceof TokenData ? path : parse(path));\n\t}\n\treturn typeof path === \"string\" ? path : stringify(path);\n};\n","import { compile, Path } from \"path-to-regexp\";\nimport { AnySelectMenuInteraction, ButtonInteraction } from \"discord.js\";\nimport { BASE_URL, ENCODING_TO_METHOD } from \"../consts\";\nimport { Method } from \"../types/routes\";\n\nexport const decodePath = ({\n\tidPrefix,\n\tinteraction,\n}: {\n\tidPrefix: string;\n\tinteraction: ButtonInteraction | AnySelectMenuInteraction;\n}): { method: Method; path: Path } | false => {\n\tconst customId = interaction.customId;\n\tif (!customId.startsWith(idPrefix)) return false;\n\n\tconst res = parseMethodAndPath(customId.slice(idPrefix.length));\n\tif (!res) return false;\n\tconst { method, path } = res;\n\n\tif (interaction.isButton()) {\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t} else if (interaction.isAnySelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\n\t\tif (interaction.isStringSelectMenu()) {\n\t\t\t// also fill in variables for to's\n\t\t\tconst toRes = parseOptionalMethodAndPath(interaction.values[0]!);\n\t\t\tconst toURL = toRes\n\t\t\t\t? fillParams(toRes.path, {\n\t\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t\tconst pathURL = fillParams(path, {\n\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\tto: toURL ? toURL.pathname.split(\"/\").slice(1) : \"\",\n\t\t\t});\n\t\t\t// merge query params\n\t\t\tfor (const [key, value] of toURL?.searchParams ?? []) {\n\t\t\t\tpathURL.searchParams.append(key, value);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod,\n\t\t\t\tpath: urlToPathString(pathURL),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t[interaction.isChannelSelectMenu()\n\t\t\t\t\t\t? \"channelId\"\n\t\t\t\t\t\t: interaction.isRoleSelectMenu()\n\t\t\t\t\t\t\t? \"roleId\"\n\t\t\t\t\t\t\t: \"userId\"]: interaction.values[0]!,\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn false;\n};\n\nconst parseMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\tif (method === undefined) return false;\n\treturn {\n\t\tmethod,\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst parseOptionalMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method | \"\"; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\treturn {\n\t\tmethod: method ?? \"\",\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst fillParams = (\n\tpath: string,\n\tparams: Partial<Record<string, string | string[]>> = {},\n): URL => {\n\tconst url = new URL(path, BASE_URL);\n\tconst toPath = compile(url.pathname);\n\n\turl.pathname = toPath(params);\n\tfor (const [key, value] of url.searchParams) {\n\t\tif (value.startsWith(\":\") && value.slice(1) in params) {\n\t\t\tconst paramValue = params?.[value.slice(1)];\n\t\t\tif (paramValue) {\n\t\t\t\turl.searchParams.set(\n\t\t\t\t\tkey,\n\t\t\t\t\tArray.isArray(paramValue) ? paramValue.join(\"/\") : paramValue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\turl.searchParams.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\treturn url;\n};\n\nconst urlToPathString = (url: URL): string => {\n\treturn `${url.pathname}${url.search}`;\n};\n","import { APIButtonComponent, ButtonBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteButtonBuilder<L> extends ButtonBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?: Omit<Partial<APIButtonComponent>, \"custom_id\" | \"url\"> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setURL(): this {\n\t\tthrow new Error(\"setURL is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\"setCustomId is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t): this {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { Path } from \"path-to-regexp\";\nimport { BASE_URL, METHOD_TO_ENCODING } from \"../consts\";\nimport { pathToString } from \"./pathToString\";\nimport { Method } from \"../types/routes\";\n\nexport const encodePath = <AllowEmptyMethod extends boolean = false>({\n\tidPrefix,\n\tmethod,\n\tpath,\n\tquery,\n}: {\n\tidPrefix: string;\n\tmethod: AllowEmptyMethod extends false ? Method : Method | \"\";\n\tpath: Path;\n\tquery?: ConstructorParameters<typeof URLSearchParams>[0] | undefined;\n}) => {\n\tconst url = new URL(pathToString(path), BASE_URL);\n\tif (query) {\n\t\tfor (const [key, value] of new URLSearchParams(query)) {\n\t\t\turl.searchParams.set(key, value);\n\t\t}\n\t}\n\treturn `${idPrefix}${method === \"\" ? \"\" : METHOD_TO_ENCODING[method as Method]}${url.pathname}${url.search}`;\n};\n","import {\n\tAPIStringSelectComponent,\n\tnormalizeArray,\n\tRestOrArray,\n\tStringSelectMenuBuilder,\n\tStringSelectMenuComponentData,\n} from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { RouteStringSelectMenuOptionBuilder } from \"./RouteStringSelectMenuOptionBuilder\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuBuilder<L> extends StringSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param path the path to redirect to, :to or *to in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :to will be replaced with the selected user's id\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<StringSelectMenuComponentData | APIStringSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: \"/*to\",\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use addTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride addOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"addOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use setTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"setOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Adds route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic addTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.addOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic setTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.setOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :to *to\n\t * @param query any query parameters you want to add, can include :ts :to *to\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { StringSelectMenuOptionBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuOptionBuilder extends StringSelectMenuOptionBuilder {\n\t/**\n\t * Not supported for RouteStringSelectMenuOptionBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setValue(): this {\n\t\tthrow new Error(\n\t\t\t\"setValue is not supported on RouteStringSelectMenuOptionBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the path to route to when selected\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"\", query }: RouteOptions<true> = {},\n\t): this {\n\t\tsuper.setValue(\n\t\t\tencodePath<true>({\n\t\t\t\tidPrefix: \"\",\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIChannelSelectComponent,\n\tChannelSelectMenuBuilder,\n\tChannelSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteChannelSelectMenuBuilder<L> extends ChannelSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<ChannelSelectMenuComponentData | APIChannelSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteChannelSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteChannelSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :channelId\n\t * @param query any query parameters you want to add, can include :ts :channelId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIRoleSelectComponent,\n\tRoleSelectMenuBuilder,\n\tRoleSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteRoleSelectMenuBuilder<L> extends RoleSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<RoleSelectMenuComponentData | APIRoleSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteRoleSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteRoleSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :roleId\n\t * @param query any query parameters you want to add, can include :ts :roleId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIUserSelectComponent,\n\tUserSelectMenuBuilder,\n\tUserSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteUserSelectMenuBuilder<L> extends UserSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<UserSelectMenuComponentData | APIUserSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteUserSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteUserSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :userId\n\t * @param query any query parameters you want to add, can include :ts :userId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n"],"mappings":"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","names":["import_path_to_regexp","path","import_path_to_regexp","path","EventEmitter","path","import_discord","path","path","import_discord","import_discord","path","path","import_discord","path","import_discord","path","import_discord","path"]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/EmbedRouter.ts
2
2
  import path from "path";
3
+ import EventEmitter from "events";
3
4
  import { createHash } from "crypto";
4
5
  import { match } from "path-to-regexp";
5
6
  import {
@@ -80,7 +81,7 @@ var decodePath = ({
80
81
  path: urlToPathString(
81
82
  fillParams(path2, {
82
83
  ts: interaction.createdTimestamp.toString(),
83
- [interaction.isChannelSelectMenu() ? "channelId" : interaction.isRoleSelectMenu() ? "roleId" : "userId"]: interaction.values[0].split("/").slice(1)
84
+ [interaction.isChannelSelectMenu() ? "channelId" : interaction.isRoleSelectMenu() ? "roleId" : "userId"]: interaction.values[0]
84
85
  })
85
86
  )
86
87
  };
@@ -130,7 +131,7 @@ var urlToPathString = (url) => {
130
131
  };
131
132
 
132
133
  // src/EmbedRouter.ts
133
- var EmbedRouter = class _EmbedRouter {
134
+ var EmbedRouter = class _EmbedRouter extends EventEmitter {
134
135
  // identifier -> embedRouter
135
136
  static #usedIdentifiers = /* @__PURE__ */ new Map();
136
137
  // Name used to generate prefixes
@@ -154,6 +155,7 @@ var EmbedRouter = class _EmbedRouter {
154
155
  name = "",
155
156
  idPrefix = ID_PREFIX
156
157
  } = {}) {
158
+ super();
157
159
  if (_EmbedRouter.#usedIdentifiers.size >= PUA_RANGE) {
158
160
  throw new Error(`You can not have more than ${PUA_RANGE} routers`);
159
161
  }
@@ -268,13 +270,24 @@ var EmbedRouter = class _EmbedRouter {
268
270
  * @param interaction interactions from "interactionCreate" (filter for ButtonInteractions)
269
271
  */
270
272
  async listener(interaction, locals) {
271
- if (interaction.isAutocomplete())
272
- throw new Error("Autocomplete Interactions aren't supported");
273
- this.#runCleanup(interaction.message.id, false);
274
- const res = decodePath({ idPrefix: this.getIdPrefix(), interaction });
275
- if (!res)
276
- throw new Error(`Invalid component found: id ${interaction.customId}`);
277
- this.dispatch(interaction, res.path, { method: res.method, locals });
273
+ try {
274
+ if (interaction.isAutocomplete())
275
+ throw new Error("Autocomplete Interactions aren't supported");
276
+ await this.#runCleanup(interaction.message.id, false);
277
+ const res = decodePath({ idPrefix: this.getIdPrefix(), interaction });
278
+ if (!res)
279
+ throw new Error(`Invalid component found: id ${interaction.customId}`);
280
+ await this.dispatch(interaction, res.path, {
281
+ method: res.method,
282
+ locals
283
+ });
284
+ } catch (e) {
285
+ this.emit(
286
+ "routeError",
287
+ e instanceof Error ? e : new Error(String(e)),
288
+ interaction
289
+ );
290
+ }
278
291
  }
279
292
  /**
280
293
  * Replies to or editReplies to an interaction based on the route output
@@ -387,11 +400,29 @@ var EmbedRouter = class _EmbedRouter {
387
400
  async #runCleanup(messageId, applyResult) {
388
401
  const cleanup = this.#cleanups.get(messageId);
389
402
  if (!cleanup) return;
390
- this.#removeCleanup(messageId);
391
- const result = await cleanup?.cleanupFn();
392
- if (applyResult && result) {
393
- await cleanup.applyFn(result).catch(console.error);
403
+ try {
404
+ this.#removeCleanup(messageId);
405
+ const result = await cleanup?.cleanupFn();
406
+ if (applyResult && result) {
407
+ await cleanup.applyFn(result).catch(console.error);
408
+ }
409
+ } catch (e) {
410
+ this.emit(
411
+ "routeError",
412
+ e instanceof Error ? e : new Error(String(e)),
413
+ void 0
414
+ );
415
+ }
416
+ }
417
+ // event helpers
418
+ onError(listener) {
419
+ return this.on("routeError", listener);
420
+ }
421
+ emit(eventName, ...args) {
422
+ if (eventName === "routeError" && this.listenerCount(eventName) === 0) {
423
+ console.error(args);
394
424
  }
425
+ return super.emit(eventName, ...args);
395
426
  }
396
427
  };
397
428
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/EmbedRouter.ts","../src/consts.ts","../src/helpers/pathToString.ts","../src/helpers/decodePath.ts","../src/componentBuilders/RouteButtonBuilder.ts","../src/helpers/encodePath.ts","../src/componentBuilders/RouteStringSelectMenuBuilder.ts","../src/componentBuilders/RouteStringSelectMenuOptionBuilder.ts","../src/componentBuilders/RouteChannelSelectMenuBuilder.ts","../src/componentBuilders/RouteRoleSelectMenuBuilder.ts","../src/componentBuilders/RouteUserSelectMenuBuilder.ts"],"sourcesContent":["import path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { match, MatchResult, Path } from \"path-to-regexp\";\nimport type {\n\tApplyHandler,\n\tCompiledRoute,\n\tMethod,\n\tRouteHandler,\n\tRouteResponse,\n} from \"./types/routes\";\nimport type { ExtractParams } from \"./types/ExtractParams\";\nimport {\n\tAnySelectMenuInteraction,\n\tButtonInteraction,\n\tInteraction,\n\tInteractionReplyOptions,\n\tMessageFlags,\n\tSnowflake,\n} from \"discord.js\";\nimport { BASE_URL, ID_PREFIX, PUA_RANGE, PUA_START } from \"./consts\";\nimport { pathToString } from \"./helpers/pathToString\";\nimport { decodePath } from \"./helpers/decodePath\";\n\nexport class EmbedRouter<L> {\n\t// identifier -> embedRouter\n\tstatic #usedIdentifiers = new Map<string, EmbedRouter<unknown>>();\n\n\t// Name used to generate prefixes\n\t#name = \"\";\n\t// Prefix for customIds of RouteButtonBuilders\n\t#idPrefix: string;\n\t#identifier: string = \"\";\n\tpublic getIdPrefix() {\n\t\treturn `${this.#idPrefix}${this.#identifier}`;\n\t}\n\n\t// All added routes\n\t#routes: Map<Method, CompiledRoute<Method, L>[]> = new Map();\n\t// message.id -> cleanup object\n\t#cleanups: Map<\n\t\tSnowflake,\n\t\t{\n\t\t\ttimeout?: NodeJS.Timeout | undefined;\n\t\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>;\n\t\t\tapplyFn: ApplyHandler;\n\t\t}\n\t> = new Map();\n\n\t/**\n\t *\n\t * @param name the name to give the router. ensures buttons stay connected across restarts\n\t * @param idPrefix the prefix for RouteButtonBuilder customIds\n\t */\n\tconstructor({\n\t\tname = \"\",\n\t\tidPrefix = ID_PREFIX,\n\t}: {\n\t\tname?: string | undefined;\n\t\tidPrefix?: string | undefined;\n\t} = {}) {\n\t\tif (EmbedRouter.#usedIdentifiers.size >= PUA_RANGE) {\n\t\t\tthrow new Error(`You can not have more than ${PUA_RANGE} routers`);\n\t\t}\n\t\tif (idPrefix.includes(\"/\")) {\n\t\t\tthrow new Error(`Prefix can't contain \"/\": ${idPrefix}`);\n\t\t}\n\t\tthis.#idPrefix = idPrefix;\n\t\tthis.#name = name;\n\t\tthis.#updateIdentifier();\n\t}\n\n\t#updateIdentifier() {\n\t\t// Private Use Area: Unicode Characters not from any language\n\t\tconst hash = createHash(\"sha256\").update(this.#name).digest();\n\t\tlet raw = hash.readUint32BE(0);\n\t\tlet char: string;\n\t\tconst nameCollisions = [];\n\t\t// find next available identifier\n\t\twhile (true) {\n\t\t\tconst codepoint = PUA_START + (raw++ % PUA_RANGE);\n\t\t\tchar = String.fromCodePoint(codepoint);\n\n\t\t\tconst collisionRouter = EmbedRouter.#usedIdentifiers.get(char);\n\t\t\tif (collisionRouter === undefined) break; // no collisions\n\n\t\t\tif (this.#name.length > 0 && collisionRouter.#name.length === 0) {\n\t\t\t\t// evict old name; usedIdentifier is still taken\n\t\t\t\tcollisionRouter.#updateIdentifier();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnameCollisions.push(collisionRouter);\n\t\t}\n\t\tEmbedRouter.#usedIdentifiers.set(char, this as EmbedRouter<unknown>);\n\n\t\tif (nameCollisions.length > 0 && this.#name.length > 0) {\n\t\t\tprocess.emitWarning(\n\t\t\t\t`EmbedRouter identifier collision for name \"${this.#name}\" with ${nameCollisions.map((c) => `\"${c.#name}\"`).join(\", \")}`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\t\t}\n\t\tthis.#identifier = char;\n\t}\n\n\t#addRoute<M extends Method, P extends Path = Path>(\n\t\tmethod: M,\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<M, L, ExtractParams<P>>,\n\t) {\n\t\tconst methodRoutes = this.#routes.get(method) ?? [];\n\t\tmethodRoutes.push({\n\t\t\tmethod,\n\t\t\tpath: Array.isArray(routePath) ? routePath : [routePath],\n\t\t\tmatchFunction: match(routePath),\n\t\t\thandler: handler as RouteHandler<M, L>,\n\t\t});\n\t\tthis.#routes.set(method, methodRoutes);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic get<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"GET\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"GET\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic post<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"POST\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"POST\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic put<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PUT\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PUT\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic patch<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PATCH\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PATCH\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic delete<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"DELETE\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"DELETE\", routePath, handler);\n\t}\n\n\t/**\n\t * Adds a subrouter to the router\n\t *\n\t * @param routePath path of the router\n\t * @param embedRouter router to add at the path\n\t */\n\tpublic use<P extends Path = Path>(\n\t\troutePath: P,\n\t\tembedRouter: EmbedRouter<Partial<L>>,\n\t) {\n\t\tconst pathString = pathToString(routePath);\n\t\tfor (const [method, routes] of embedRouter.#routes) {\n\t\t\tfor (const route of routes) {\n\t\t\t\tthis.#addRoute(\n\t\t\t\t\tmethod,\n\t\t\t\t\troute.path.map((p) => path.posix.join(pathString, pathToString(p))),\n\t\t\t\t\troute.handler,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Must be attached to \"interactionCreate\" event for RouteButtonBuilder to work\n\t *\n\t * @param interaction interactions from \"interactionCreate\" (filter for ButtonInteractions)\n\t */\n\tpublic async listener(\n\t\tinteraction: ButtonInteraction | AnySelectMenuInteraction,\n\t\tlocals?: L | undefined,\n\t) {\n\t\tif (interaction.isAutocomplete())\n\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\tthis.#runCleanup(interaction.message.id, false);\n\n\t\tconst res = decodePath({ idPrefix: this.getIdPrefix(), interaction });\n\t\tif (!res)\n\t\t\tthrow new Error(`Invalid component found: id ${interaction.customId}`);\n\n\t\tthis.dispatch(interaction, res.path, { method: res.method, locals });\n\t}\n\n\t/**\n\t * Replies to or editReplies to an interaction based on the route output\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param flags discord flags to send with message (optional, only allowed on first reply)\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t */\n\tpublic async dispatch<P extends Path = Path>(\n\t\tinteraction: Interaction,\n\t\tpath: P,\n\t\t{\n\t\t\tmethod = \"GET\",\n\t\t\tflags,\n\t\t\tlocals,\n\t\t}: {\n\t\t\tmethod?: Method;\n\t\t\tflags?: InteractionReplyOptions[\"flags\"] | undefined;\n\t\t\tlocals?: L | undefined;\n\t\t} = {},\n\t) {\n\t\tif (interaction.isAutocomplete())\n\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\t// don't check validity because url params are considered invalid\n\t\tconst routeResponse = await this.#resolve(path, {\n\t\t\tinteraction,\n\t\t\tmethod,\n\t\t\tlocals,\n\t\t});\n\t\tif (routeResponse === false)\n\t\t\tthrow new Error(`No route found for ${pathToString(path, false)}`);\n\n\t\tif (interaction.replied || interaction.deferred) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tif (routeResponse) await interaction.editReply(routeResponse);\n\t\t} else if (!routeResponse) {\n\t\t\tif (\"deferUpdate\" in interaction) {\n\t\t\t\tawait interaction.deferUpdate();\n\t\t\t} else {\n\t\t\t\tawait interaction.deferReply();\n\t\t\t}\n\t\t} else if (\"update\" in interaction) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tawait interaction.update(routeResponse);\n\t\t} else {\n\t\t\tawait interaction.reply({\n\t\t\t\t...(routeResponse as InteractionReplyOptions),\n\t\t\t\tflags,\n\t\t\t});\n\t\t}\n\n\t\t// Apply cleanup if needed\n\t\tif (!routeResponse?.cleanup) return;\n\n\t\tconst message = await interaction.fetchReply();\n\t\tconst channel = interaction.channel;\n\t\tconst applyFn: ApplyHandler | undefined = message.flags.has(\n\t\t\tMessageFlags.Ephemeral,\n\t\t)\n\t\t\t? interaction.editReply.bind(interaction)\n\t\t\t: channel\n\t\t\t\t? (options) => channel.messages.edit(message.id, options)\n\t\t\t\t: undefined;\n\t\tif (!applyFn)\n\t\t\treturn process.emitWarning(\n\t\t\t\t`Could not derive applyFunction for ${pathToString(path, false)}. Cleanup return results will not be applied to message.`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\n\t\tthis.#addCleanup(\n\t\t\tmessage.id,\n\t\t\trouteResponse.cleanup.bind(routeResponse),\n\t\t\tapplyFn,\n\t\t\trouteResponse?.timeout,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves a route to the associated message (DOES NOT UPDATE MESSAGE)\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t * @returns discord message associated with route OR false\n\t */\n\tasync #resolve<P extends Path>(\n\t\tpath: P,\n\t\t{\n\t\t\tinteraction,\n\t\t\tmethod = \"GET\",\n\t\t\tlocals,\n\t\t}: {\n\t\t\tinteraction: Interaction;\n\t\t\tmethod?: Method;\n\t\t\tlocals?: L | undefined;\n\t\t},\n\t): Promise<RouteResponse | undefined | false> {\n\t\t// don't check validity because url params are considered invalid\n\t\tconst url = new URL(pathToString(path, false), BASE_URL);\n\t\tfor (const route of this.#routes.get(method) ?? []) {\n\t\t\tconst result = route.matchFunction(url.pathname);\n\t\t\tif (result) {\n\t\t\t\treturn await route.handler(interaction, {\n\t\t\t\t\t...(result as MatchResult<ExtractParams<P>>),\n\t\t\t\t\tquery: url.searchParams,\n\t\t\t\t\tembedRouter: this,\n\t\t\t\t\tlocals,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Helpers for using and storing cleanup functions\n\t#addCleanup(\n\t\tmessageId: Snowflake,\n\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>,\n\t\tapplyFn: ApplyHandler,\n\t\ttimeout: number,\n\t) {\n\t\tthis.#removeCleanup(messageId);\n\t\tthis.#cleanups.set(messageId, {\n\t\t\tcleanupFn,\n\t\t\tapplyFn,\n\t\t\ttimeout: isFinite(timeout)\n\t\t\t\t? setTimeout(() => this.#runCleanup(messageId, true), timeout)\n\t\t\t\t: undefined,\n\t\t});\n\t}\n\n\t#removeCleanup(messageId: Snowflake) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\tclearTimeout(cleanup.timeout);\n\t\tthis.#cleanups.delete(messageId);\n\t}\n\n\tasync #runCleanup(messageId: Snowflake, applyResult: boolean) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\tthis.#removeCleanup(messageId);\n\t\tconst result = await cleanup?.cleanupFn();\n\t\tif (applyResult && result) {\n\t\t\tawait cleanup.applyFn(result).catch(console.error);\n\t\t}\n\t}\n}\n","import { Method } from \"./types/routes\";\n\nexport const ID_PREFIX = \"der\";\nexport const METHOD_TO_ENCODING: Record<Method, string> = {\n\tGET: \"G\",\n\tPOST: \"P\",\n\tPUT: \"U\",\n\tPATCH: \"A\",\n\tDELETE: \"D\",\n};\nexport const ENCODING_TO_METHOD: Record<string, Method> = {\n\tG: \"GET\",\n\tP: \"POST\",\n\tU: \"PUT\",\n\tA: \"PATCH\",\n\tD: \"DELETE\",\n};\n// base url is never sent; only used for processing locally\nexport const BASE_URL = \"discord://embed.router\";\n\nexport const PUA_START = 0xe000;\nexport const PUA_END = 0xf8ff;\nexport const PUA_RANGE = PUA_END - PUA_START + 1;\n","import { parse, Path, stringify, TokenData } from \"path-to-regexp\";\n\nexport const pathToString = <P extends Path>(\n\tpath: P,\n\tcheckValidity = true,\n): string => {\n\tif (checkValidity) {\n\t\treturn stringify(path instanceof TokenData ? path : parse(path));\n\t}\n\treturn typeof path === \"string\" ? path : stringify(path);\n};\n","import { compile, Path } from \"path-to-regexp\";\nimport { AnySelectMenuInteraction, ButtonInteraction } from \"discord.js\";\nimport { BASE_URL, ENCODING_TO_METHOD } from \"../consts\";\nimport { Method } from \"../types/routes\";\n\nexport const decodePath = ({\n\tidPrefix,\n\tinteraction,\n}: {\n\tidPrefix: string;\n\tinteraction: ButtonInteraction | AnySelectMenuInteraction;\n}): { method: Method; path: Path } | false => {\n\tconst customId = interaction.customId;\n\tif (!customId.startsWith(idPrefix)) return false;\n\n\tconst res = parseMethodAndPath(customId.slice(idPrefix.length));\n\tif (!res) return false;\n\tconst { method, path } = res;\n\n\tif (interaction.isButton()) {\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t} else if (interaction.isAnySelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\n\t\tif (interaction.isStringSelectMenu()) {\n\t\t\t// also fill in variables for to's\n\t\t\tconst toRes = parseOptionalMethodAndPath(interaction.values[0]!);\n\t\t\tconst toURL = toRes\n\t\t\t\t? fillParams(toRes.path, {\n\t\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t\tconst pathURL = fillParams(path, {\n\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\tto: toURL ? toURL.pathname.split(\"/\").slice(1) : \"\",\n\t\t\t});\n\t\t\t// merge query params\n\t\t\tfor (const [key, value] of toURL?.searchParams ?? []) {\n\t\t\t\tpathURL.searchParams.append(key, value);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod,\n\t\t\t\tpath: urlToPathString(pathURL),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t[interaction.isChannelSelectMenu()\n\t\t\t\t\t\t? \"channelId\"\n\t\t\t\t\t\t: interaction.isRoleSelectMenu()\n\t\t\t\t\t\t\t? \"roleId\"\n\t\t\t\t\t\t\t: \"userId\"]: interaction.values[0]!.split(\"/\").slice(1),\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn false;\n};\n\nconst parseMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\tif (method === undefined) return false;\n\treturn {\n\t\tmethod,\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst parseOptionalMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method | \"\"; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\treturn {\n\t\tmethod: method ?? \"\",\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst fillParams = (\n\tpath: string,\n\tparams: Partial<Record<string, string | string[]>> = {},\n): URL => {\n\tconst url = new URL(path, BASE_URL);\n\tconst toPath = compile(url.pathname);\n\n\turl.pathname = toPath(params);\n\tfor (const [key, value] of url.searchParams) {\n\t\tif (value.startsWith(\":\") && value.slice(1) in params) {\n\t\t\tconst paramValue = params?.[value.slice(1)];\n\t\t\tif (paramValue) {\n\t\t\t\turl.searchParams.set(\n\t\t\t\t\tkey,\n\t\t\t\t\tArray.isArray(paramValue) ? paramValue.join(\"/\") : paramValue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\turl.searchParams.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\treturn url;\n};\n\nconst urlToPathString = (url: URL): string => {\n\treturn `${url.pathname}${url.search}`;\n};\n","import { APIButtonComponent, ButtonBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteButtonBuilder<L> extends ButtonBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?: Omit<Partial<APIButtonComponent>, \"custom_id\" | \"url\"> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setURL(): this {\n\t\tthrow new Error(\"setURL is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\"setCustomId is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t): this {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { Path } from \"path-to-regexp\";\nimport { BASE_URL, METHOD_TO_ENCODING } from \"../consts\";\nimport { pathToString } from \"./pathToString\";\nimport { Method } from \"../types/routes\";\n\nexport const encodePath = <AllowEmptyMethod extends boolean = false>({\n\tidPrefix,\n\tmethod,\n\tpath,\n\tquery,\n}: {\n\tidPrefix: string;\n\tmethod: AllowEmptyMethod extends false ? Method : Method | \"\";\n\tpath: Path;\n\tquery?: ConstructorParameters<typeof URLSearchParams>[0] | undefined;\n}) => {\n\tconst url = new URL(pathToString(path), BASE_URL);\n\tif (query) {\n\t\tfor (const [key, value] of new URLSearchParams(query)) {\n\t\t\turl.searchParams.set(key, value);\n\t\t}\n\t}\n\treturn `${idPrefix}${method === \"\" ? \"\" : METHOD_TO_ENCODING[method as Method]}${url.pathname}${url.search}`;\n};\n","import {\n\tAPIStringSelectComponent,\n\tnormalizeArray,\n\tRestOrArray,\n\tStringSelectMenuBuilder,\n\tStringSelectMenuComponentData,\n} from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { RouteStringSelectMenuOptionBuilder } from \"./RouteStringSelectMenuOptionBuilder\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuBuilder<L> extends StringSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param path the path to redirect to, :to or *to in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :to will be replaced with the selected user's id\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<StringSelectMenuComponentData | APIStringSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: \"/*to\",\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use addTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride addOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"addOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use setTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"setOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Adds route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic addTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.addOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic setTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.setOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :to *to\n\t * @param query any query parameters you want to add, can include :ts :to *to\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { StringSelectMenuOptionBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuOptionBuilder extends StringSelectMenuOptionBuilder {\n\t/**\n\t * Not supported for RouteStringSelectMenuOptionBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setValue(): this {\n\t\tthrow new Error(\n\t\t\t\"setValue is not supported on RouteStringSelectMenuOptionBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the path to route to when selected\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"\", query }: RouteOptions<true> = {},\n\t): this {\n\t\tsuper.setValue(\n\t\t\tencodePath<true>({\n\t\t\t\tidPrefix: \"\",\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIChannelSelectComponent,\n\tChannelSelectMenuBuilder,\n\tChannelSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteChannelSelectMenuBuilder<L> extends ChannelSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<ChannelSelectMenuComponentData | APIChannelSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteChannelSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteChannelSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :channelId\n\t * @param query any query parameters you want to add, can include :ts :channelId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIRoleSelectComponent,\n\tRoleSelectMenuBuilder,\n\tRoleSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteRoleSelectMenuBuilder<L> extends RoleSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<RoleSelectMenuComponentData | APIRoleSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteRoleSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteRoleSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :roleId\n\t * @param query any query parameters you want to add, can include :ts :roleId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIUserSelectComponent,\n\tUserSelectMenuBuilder,\n\tUserSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteUserSelectMenuBuilder<L> extends UserSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<UserSelectMenuComponentData | APIUserSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteUserSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteUserSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :userId\n\t * @param query any query parameters you want to add, can include :ts :userId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n"],"mappings":"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","names":["path","path","path","path","path","path","path","path","path","path"]}
1
+ {"version":3,"sources":["../src/EmbedRouter.ts","../src/consts.ts","../src/helpers/pathToString.ts","../src/helpers/decodePath.ts","../src/componentBuilders/RouteButtonBuilder.ts","../src/helpers/encodePath.ts","../src/componentBuilders/RouteStringSelectMenuBuilder.ts","../src/componentBuilders/RouteStringSelectMenuOptionBuilder.ts","../src/componentBuilders/RouteChannelSelectMenuBuilder.ts","../src/componentBuilders/RouteRoleSelectMenuBuilder.ts","../src/componentBuilders/RouteUserSelectMenuBuilder.ts"],"sourcesContent":["import path from \"node:path\";\nimport EventEmitter from \"node:events\";\nimport { createHash } from \"node:crypto\";\nimport { match, MatchResult, Path } from \"path-to-regexp\";\nimport type {\n\tApplyHandler,\n\tCompiledRoute,\n\tMethod,\n\tRouteHandler,\n\tRouteResponse,\n} from \"./types/routes\";\nimport type { ExtractParams } from \"./types/ExtractParams\";\nimport {\n\tAnySelectMenuInteraction,\n\tButtonInteraction,\n\tInteraction,\n\tInteractionReplyOptions,\n\tMessageFlags,\n\tSnowflake,\n} from \"discord.js\";\nimport { BASE_URL, ID_PREFIX, PUA_RANGE, PUA_START } from \"./consts\";\nimport { pathToString } from \"./helpers/pathToString\";\nimport { decodePath } from \"./helpers/decodePath\";\nimport { Args, EventNames, Listener } from \"./types/EmbedRouterEvents\";\n\ntype EmbedRouterEvents = {\n\trouteError: [err: Error, interaction?: Interaction | undefined];\n};\n\nexport class EmbedRouter<L> extends EventEmitter<EmbedRouterEvents> {\n\t// identifier -> embedRouter\n\tstatic #usedIdentifiers = new Map<string, EmbedRouter<unknown>>();\n\n\t// Name used to generate prefixes\n\t#name = \"\";\n\t// Prefix for customIds of RouteButtonBuilders\n\t#idPrefix: string;\n\t#identifier: string = \"\";\n\tpublic getIdPrefix() {\n\t\treturn `${this.#idPrefix}${this.#identifier}`;\n\t}\n\n\t// All added routes\n\t#routes: Map<Method, CompiledRoute<Method, L>[]> = new Map();\n\t// message.id -> cleanup object\n\t#cleanups: Map<\n\t\tSnowflake,\n\t\t{\n\t\t\ttimeout?: NodeJS.Timeout | undefined;\n\t\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>;\n\t\t\tapplyFn: ApplyHandler;\n\t\t}\n\t> = new Map();\n\n\t/**\n\t *\n\t * @param name the name to give the router. ensures buttons stay connected across restarts\n\t * @param idPrefix the prefix for RouteButtonBuilder customIds\n\t */\n\tconstructor({\n\t\tname = \"\",\n\t\tidPrefix = ID_PREFIX,\n\t}: {\n\t\tname?: string | undefined;\n\t\tidPrefix?: string | undefined;\n\t} = {}) {\n\t\tsuper();\n\n\t\tif (EmbedRouter.#usedIdentifiers.size >= PUA_RANGE) {\n\t\t\tthrow new Error(`You can not have more than ${PUA_RANGE} routers`);\n\t\t}\n\t\tif (idPrefix.includes(\"/\")) {\n\t\t\tthrow new Error(`Prefix can't contain \"/\": ${idPrefix}`);\n\t\t}\n\t\tthis.#idPrefix = idPrefix;\n\t\tthis.#name = name;\n\t\tthis.#updateIdentifier();\n\t}\n\n\t#updateIdentifier() {\n\t\t// Private Use Area: Unicode Characters not from any language\n\t\tconst hash = createHash(\"sha256\").update(this.#name).digest();\n\t\tlet raw = hash.readUint32BE(0);\n\t\tlet char: string;\n\t\tconst nameCollisions = [];\n\t\t// find next available identifier\n\t\twhile (true) {\n\t\t\tconst codepoint = PUA_START + (raw++ % PUA_RANGE);\n\t\t\tchar = String.fromCodePoint(codepoint);\n\n\t\t\tconst collisionRouter = EmbedRouter.#usedIdentifiers.get(char);\n\t\t\tif (collisionRouter === undefined) break; // no collisions\n\n\t\t\tif (this.#name.length > 0 && collisionRouter.#name.length === 0) {\n\t\t\t\t// evict old name; usedIdentifier is still taken\n\t\t\t\tcollisionRouter.#updateIdentifier();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnameCollisions.push(collisionRouter);\n\t\t}\n\t\tEmbedRouter.#usedIdentifiers.set(char, this as EmbedRouter<unknown>);\n\n\t\tif (nameCollisions.length > 0 && this.#name.length > 0) {\n\t\t\tprocess.emitWarning(\n\t\t\t\t`EmbedRouter identifier collision for name \"${this.#name}\" with ${nameCollisions.map((c) => `\"${c.#name}\"`).join(\", \")}`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\t\t}\n\t\tthis.#identifier = char;\n\t}\n\n\t#addRoute<M extends Method, P extends Path = Path>(\n\t\tmethod: M,\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<M, L, ExtractParams<P>>,\n\t) {\n\t\tconst methodRoutes = this.#routes.get(method) ?? [];\n\t\tmethodRoutes.push({\n\t\t\tmethod,\n\t\t\tpath: Array.isArray(routePath) ? routePath : [routePath],\n\t\t\tmatchFunction: match(routePath),\n\t\t\thandler: handler as RouteHandler<M, L>,\n\t\t});\n\t\tthis.#routes.set(method, methodRoutes);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic get<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"GET\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"GET\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic post<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"POST\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"POST\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic put<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PUT\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PUT\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic patch<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"PATCH\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"PATCH\", routePath, handler);\n\t}\n\n\t/**\n\t * Registers a path with the router\n\t *\n\t * @param routePath path to match with\n\t * @param handler function that generates the message when a path is matched\n\t */\n\tpublic delete<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<\"DELETE\", L, ExtractParams<P>>,\n\t) {\n\t\tthis.#addRoute(\"DELETE\", routePath, handler);\n\t}\n\n\t/**\n\t * Adds a subrouter to the router\n\t *\n\t * @param routePath path of the router\n\t * @param embedRouter router to add at the path\n\t */\n\tpublic use<P extends Path = Path>(\n\t\troutePath: P,\n\t\tembedRouter: EmbedRouter<Partial<L>>,\n\t) {\n\t\tconst pathString = pathToString(routePath);\n\t\tfor (const [method, routes] of embedRouter.#routes) {\n\t\t\tfor (const route of routes) {\n\t\t\t\tthis.#addRoute(\n\t\t\t\t\tmethod,\n\t\t\t\t\troute.path.map((p) => path.posix.join(pathString, pathToString(p))),\n\t\t\t\t\troute.handler,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Must be attached to \"interactionCreate\" event for RouteButtonBuilder to work\n\t *\n\t * @param interaction interactions from \"interactionCreate\" (filter for ButtonInteractions)\n\t */\n\tpublic async listener(\n\t\tinteraction: ButtonInteraction | AnySelectMenuInteraction,\n\t\tlocals?: L | undefined,\n\t) {\n\t\ttry {\n\t\t\tif (interaction.isAutocomplete())\n\t\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\t\tawait this.#runCleanup(interaction.message.id, false);\n\n\t\t\tconst res = decodePath({ idPrefix: this.getIdPrefix(), interaction });\n\t\t\tif (!res)\n\t\t\t\tthrow new Error(`Invalid component found: id ${interaction.customId}`);\n\n\t\t\tawait this.dispatch(interaction, res.path, {\n\t\t\t\tmethod: res.method,\n\t\t\t\tlocals,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tthis.emit(\n\t\t\t\t\"routeError\",\n\t\t\t\te instanceof Error ? e : new Error(String(e)),\n\t\t\t\tinteraction,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Replies to or editReplies to an interaction based on the route output\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param flags discord flags to send with message (optional, only allowed on first reply)\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t */\n\tpublic async dispatch<P extends Path = Path>(\n\t\tinteraction: Interaction,\n\t\tpath: P,\n\t\t{\n\t\t\tmethod = \"GET\",\n\t\t\tflags,\n\t\t\tlocals,\n\t\t}: {\n\t\t\tmethod?: Method;\n\t\t\tflags?: InteractionReplyOptions[\"flags\"] | undefined;\n\t\t\tlocals?: L | undefined;\n\t\t} = {},\n\t) {\n\t\tif (interaction.isAutocomplete())\n\t\t\tthrow new Error(\"Autocomplete Interactions aren't supported\");\n\n\t\t// don't check validity because url params are considered invalid\n\t\tconst routeResponse = await this.#resolve(path, {\n\t\t\tinteraction,\n\t\t\tmethod,\n\t\t\tlocals,\n\t\t});\n\t\tif (routeResponse === false)\n\t\t\tthrow new Error(`No route found for ${pathToString(path, false)}`);\n\n\t\tif (interaction.replied || interaction.deferred) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tif (routeResponse) await interaction.editReply(routeResponse);\n\t\t} else if (!routeResponse) {\n\t\t\tif (\"deferUpdate\" in interaction) {\n\t\t\t\tawait interaction.deferUpdate();\n\t\t\t} else {\n\t\t\t\tawait interaction.deferReply();\n\t\t\t}\n\t\t} else if (\"update\" in interaction) {\n\t\t\tif (flags)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"You can only set flags for interactions that haven't been replied to\",\n\t\t\t\t);\n\t\t\tawait interaction.update(routeResponse);\n\t\t} else {\n\t\t\tawait interaction.reply({\n\t\t\t\t...(routeResponse as InteractionReplyOptions),\n\t\t\t\tflags,\n\t\t\t});\n\t\t}\n\n\t\t// Apply cleanup if needed\n\t\tif (!routeResponse?.cleanup) return;\n\n\t\tconst message = await interaction.fetchReply();\n\t\tconst channel = interaction.channel;\n\t\tconst applyFn: ApplyHandler | undefined = message.flags.has(\n\t\t\tMessageFlags.Ephemeral,\n\t\t)\n\t\t\t? interaction.editReply.bind(interaction)\n\t\t\t: channel\n\t\t\t\t? (options) => channel.messages.edit(message.id, options)\n\t\t\t\t: undefined;\n\t\tif (!applyFn)\n\t\t\treturn process.emitWarning(\n\t\t\t\t`Could not derive applyFunction for ${pathToString(path, false)}. Cleanup return results will not be applied to message.`,\n\t\t\t\t\"EmbedRouterWarning\",\n\t\t\t);\n\n\t\tthis.#addCleanup(\n\t\t\tmessage.id,\n\t\t\trouteResponse.cleanup.bind(routeResponse),\n\t\t\tapplyFn,\n\t\t\trouteResponse?.timeout,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves a route to the associated message (DOES NOT UPDATE MESSAGE)\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param method method to send to route\n\t * @param locals additional info to pass in to page through state.local (optional)\n\t * @returns discord message associated with route OR false\n\t */\n\tasync #resolve<P extends Path>(\n\t\tpath: P,\n\t\t{\n\t\t\tinteraction,\n\t\t\tmethod = \"GET\",\n\t\t\tlocals,\n\t\t}: {\n\t\t\tinteraction: Interaction;\n\t\t\tmethod?: Method;\n\t\t\tlocals?: L | undefined;\n\t\t},\n\t): Promise<RouteResponse | undefined | false> {\n\t\t// don't check validity because url params are considered invalid\n\t\tconst url = new URL(pathToString(path, false), BASE_URL);\n\t\tfor (const route of this.#routes.get(method) ?? []) {\n\t\t\tconst result = route.matchFunction(url.pathname);\n\t\t\tif (result) {\n\t\t\t\treturn await route.handler(interaction, {\n\t\t\t\t\t...(result as MatchResult<ExtractParams<P>>),\n\t\t\t\t\tquery: url.searchParams,\n\t\t\t\t\tembedRouter: this,\n\t\t\t\t\tlocals,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t// Helpers for using and storing cleanup functions\n\t#addCleanup(\n\t\tmessageId: Snowflake,\n\t\tcleanupFn: NonNullable<RouteResponse[\"cleanup\"]>,\n\t\tapplyFn: ApplyHandler,\n\t\ttimeout: number,\n\t) {\n\t\tthis.#removeCleanup(messageId);\n\t\tthis.#cleanups.set(messageId, {\n\t\t\tcleanupFn,\n\t\t\tapplyFn,\n\t\t\ttimeout: isFinite(timeout)\n\t\t\t\t? setTimeout(() => this.#runCleanup(messageId, true), timeout)\n\t\t\t\t: undefined,\n\t\t});\n\t}\n\n\t#removeCleanup(messageId: Snowflake) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\tclearTimeout(cleanup.timeout);\n\t\tthis.#cleanups.delete(messageId);\n\t}\n\n\tasync #runCleanup(messageId: Snowflake, applyResult: boolean) {\n\t\tconst cleanup = this.#cleanups.get(messageId);\n\t\tif (!cleanup) return;\n\n\t\ttry {\n\t\t\tthis.#removeCleanup(messageId);\n\t\t\tconst result = await cleanup?.cleanupFn();\n\t\t\tif (applyResult && result) {\n\t\t\t\tawait cleanup.applyFn(result).catch(console.error);\n\t\t\t}\n\t\t} catch (e: unknown) {\n\t\t\tthis.emit(\n\t\t\t\t\"routeError\",\n\t\t\t\te instanceof Error ? e : new Error(String(e)),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t}\n\t}\n\n\t// event helpers\n\tpublic onError(listener: Listener<EmbedRouterEvents, \"routeError\">) {\n\t\treturn this.on(\"routeError\", listener);\n\t}\n\n\toverride emit<E extends string | symbol>(\n\t\teventName: EventNames<EmbedRouterEvents, E>,\n\t\t...args: Args<EmbedRouterEvents, E>\n\t): boolean {\n\t\tif (eventName === \"routeError\" && this.listenerCount(eventName) === 0) {\n\t\t\tconsole.error(args);\n\t\t}\n\t\treturn super.emit(eventName, ...args);\n\t}\n}\n","import { Method } from \"./types/routes\";\n\nexport const ID_PREFIX = \"der\";\nexport const METHOD_TO_ENCODING: Record<Method, string> = {\n\tGET: \"G\",\n\tPOST: \"P\",\n\tPUT: \"U\",\n\tPATCH: \"A\",\n\tDELETE: \"D\",\n};\nexport const ENCODING_TO_METHOD: Record<string, Method> = {\n\tG: \"GET\",\n\tP: \"POST\",\n\tU: \"PUT\",\n\tA: \"PATCH\",\n\tD: \"DELETE\",\n};\n// base url is never sent; only used for processing locally\nexport const BASE_URL = \"discord://embed.router\";\n\nexport const PUA_START = 0xe000;\nexport const PUA_END = 0xf8ff;\nexport const PUA_RANGE = PUA_END - PUA_START + 1;\n","import { parse, Path, stringify, TokenData } from \"path-to-regexp\";\n\nexport const pathToString = <P extends Path>(\n\tpath: P,\n\tcheckValidity = true,\n): string => {\n\tif (checkValidity) {\n\t\treturn stringify(path instanceof TokenData ? path : parse(path));\n\t}\n\treturn typeof path === \"string\" ? path : stringify(path);\n};\n","import { compile, Path } from \"path-to-regexp\";\nimport { AnySelectMenuInteraction, ButtonInteraction } from \"discord.js\";\nimport { BASE_URL, ENCODING_TO_METHOD } from \"../consts\";\nimport { Method } from \"../types/routes\";\n\nexport const decodePath = ({\n\tidPrefix,\n\tinteraction,\n}: {\n\tidPrefix: string;\n\tinteraction: ButtonInteraction | AnySelectMenuInteraction;\n}): { method: Method; path: Path } | false => {\n\tconst customId = interaction.customId;\n\tif (!customId.startsWith(idPrefix)) return false;\n\n\tconst res = parseMethodAndPath(customId.slice(idPrefix.length));\n\tif (!res) return false;\n\tconst { method, path } = res;\n\n\tif (interaction.isButton()) {\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t} else if (interaction.isAnySelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\n\t\tif (interaction.isStringSelectMenu()) {\n\t\t\t// also fill in variables for to's\n\t\t\tconst toRes = parseOptionalMethodAndPath(interaction.values[0]!);\n\t\t\tconst toURL = toRes\n\t\t\t\t? fillParams(toRes.path, {\n\t\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t\tconst pathURL = fillParams(path, {\n\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\tto: toURL ? toURL.pathname.split(\"/\").slice(1) : \"\",\n\t\t\t});\n\t\t\t// merge query params\n\t\t\tfor (const [key, value] of toURL?.searchParams ?? []) {\n\t\t\t\tpathURL.searchParams.append(key, value);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod,\n\t\t\t\tpath: urlToPathString(pathURL),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: urlToPathString(\n\t\t\t\tfillParams(path, {\n\t\t\t\t\tts: interaction.createdTimestamp.toString(),\n\t\t\t\t\t[interaction.isChannelSelectMenu()\n\t\t\t\t\t\t? \"channelId\"\n\t\t\t\t\t\t: interaction.isRoleSelectMenu()\n\t\t\t\t\t\t\t? \"roleId\"\n\t\t\t\t\t\t\t: \"userId\"]: interaction.values[0]!,\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\t}\n\n\treturn false;\n};\n\nconst parseMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\tif (method === undefined) return false;\n\treturn {\n\t\tmethod,\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst parseOptionalMethodAndPath = (\n\tpathWithMethod: string,\n): { method: Method | \"\"; path: string } | false => {\n\t// path always start with \"/\"\n\tconst firstSlash = pathWithMethod.indexOf(\"/\");\n\t// invalid customId\n\tif (firstSlash < 0) return false;\n\n\tconst method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];\n\treturn {\n\t\tmethod: method ?? \"\",\n\t\tpath: pathWithMethod.slice(firstSlash),\n\t};\n};\n\nconst fillParams = (\n\tpath: string,\n\tparams: Partial<Record<string, string | string[]>> = {},\n): URL => {\n\tconst url = new URL(path, BASE_URL);\n\tconst toPath = compile(url.pathname);\n\n\turl.pathname = toPath(params);\n\tfor (const [key, value] of url.searchParams) {\n\t\tif (value.startsWith(\":\") && value.slice(1) in params) {\n\t\t\tconst paramValue = params?.[value.slice(1)];\n\t\t\tif (paramValue) {\n\t\t\t\turl.searchParams.set(\n\t\t\t\t\tkey,\n\t\t\t\t\tArray.isArray(paramValue) ? paramValue.join(\"/\") : paramValue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\turl.searchParams.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\treturn url;\n};\n\nconst urlToPathString = (url: URL): string => {\n\treturn `${url.pathname}${url.search}`;\n};\n","import { APIButtonComponent, ButtonBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteButtonBuilder<L> extends ButtonBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?: Omit<Partial<APIButtonComponent>, \"custom_id\" | \"url\"> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setURL(): this {\n\t\tthrow new Error(\"setURL is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Not supported for RouteButtonBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\"setCustomId is not supported on RouteButtonBuilder\");\n\t}\n\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t): this {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { Path } from \"path-to-regexp\";\nimport { BASE_URL, METHOD_TO_ENCODING } from \"../consts\";\nimport { pathToString } from \"./pathToString\";\nimport { Method } from \"../types/routes\";\n\nexport const encodePath = <AllowEmptyMethod extends boolean = false>({\n\tidPrefix,\n\tmethod,\n\tpath,\n\tquery,\n}: {\n\tidPrefix: string;\n\tmethod: AllowEmptyMethod extends false ? Method : Method | \"\";\n\tpath: Path;\n\tquery?: ConstructorParameters<typeof URLSearchParams>[0] | undefined;\n}) => {\n\tconst url = new URL(pathToString(path), BASE_URL);\n\tif (query) {\n\t\tfor (const [key, value] of new URLSearchParams(query)) {\n\t\t\turl.searchParams.set(key, value);\n\t\t}\n\t}\n\treturn `${idPrefix}${method === \"\" ? \"\" : METHOD_TO_ENCODING[method as Method]}${url.pathname}${url.search}`;\n};\n","import {\n\tAPIStringSelectComponent,\n\tnormalizeArray,\n\tRestOrArray,\n\tStringSelectMenuBuilder,\n\tStringSelectMenuComponentData,\n} from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { RouteStringSelectMenuOptionBuilder } from \"./RouteStringSelectMenuOptionBuilder\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuBuilder<L> extends StringSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param path the path to redirect to, :to or *to in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :to will be replaced with the selected user's id\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<StringSelectMenuComponentData | APIStringSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: \"/*to\",\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use addTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride addOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"addOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Not supported for RouteStringSelectMenuBuilder (use setTos)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setOptions(): this {\n\t\tthrow new Error(\n\t\t\t\"setOptions is not supported on RouteStringSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Adds route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic addTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.addOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets route select menu options to builder\n\t *\n\t * @param tos the list of route select menu options\n\t */\n\tpublic setTos(\n\t\t...tos: RestOrArray<\n\t\t\t| RouteStringSelectMenuOptionBuilder\n\t\t\t| ConstructorParameters<typeof RouteStringSelectMenuOptionBuilder>[0]\n\t\t>\n\t): this {\n\t\tconst resolved = normalizeArray(tos);\n\t\tsuper.setOptions(\n\t\t\tresolved.map((o) =>\n\t\t\t\to instanceof RouteStringSelectMenuOptionBuilder\n\t\t\t\t\t? o\n\t\t\t\t\t: new RouteStringSelectMenuOptionBuilder(o),\n\t\t\t),\n\t\t);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :to *to\n\t * @param query any query parameters you want to add, can include :ts :to *to\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import { StringSelectMenuOptionBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteStringSelectMenuOptionBuilder extends StringSelectMenuOptionBuilder {\n\t/**\n\t * Not supported for RouteStringSelectMenuOptionBuilder (use setTo)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setValue(): this {\n\t\tthrow new Error(\n\t\t\t\"setValue is not supported on RouteStringSelectMenuOptionBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the path to route to when selected\n\t *\n\t * @param path the path to route to, can include :ts\n\t * @param query any query parameters you want to add, can include :ts\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"\", query }: RouteOptions<true> = {},\n\t): this {\n\t\tsuper.setValue(\n\t\t\tencodePath<true>({\n\t\t\t\tidPrefix: \"\",\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIChannelSelectComponent,\n\tChannelSelectMenuBuilder,\n\tChannelSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteChannelSelectMenuBuilder<L> extends ChannelSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\t| Partial<ChannelSelectMenuComponentData | APIChannelSelectComponent>\n\t\t\t| undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteChannelSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteChannelSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :channelId\n\t * @param query any query parameters you want to add, can include :ts :channelId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIRoleSelectComponent,\n\tRoleSelectMenuBuilder,\n\tRoleSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteRoleSelectMenuBuilder<L> extends RoleSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<RoleSelectMenuComponentData | APIRoleSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteRoleSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteRoleSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :roleId\n\t * @param query any query parameters you want to add, can include :ts :roleId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n","import {\n\tAPIUserSelectComponent,\n\tUserSelectMenuBuilder,\n\tUserSelectMenuComponentData,\n} from \"discord.js\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { RouteOptions } from \"../types/componentBuilders\";\n\nexport class RouteUserSelectMenuBuilder<L> extends UserSelectMenuBuilder {\n\t#embedRouter: EmbedRouter<L>;\n\n\t/**\n\t *\n\t * @param embedRouter the router you want to route with\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tdata?:\n\t\t\tPartial<UserSelectMenuComponentData | APIUserSelectComponent> | undefined,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.#embedRouter = embedRouter;\n\t}\n\n\t/**\n\t * Not supported for RouteUserSelectMenuBuilder (customId set from embedRouter)\n\t *\n\t * @remarks\n\t * @param\n\t */\n\toverride setCustomId(): this {\n\t\tthrow new Error(\n\t\t\t\"setCustomId is not supported on RouteUserSelectMenuBuilder\",\n\t\t);\n\t}\n\n\t/**\n\t * Sets the pattern to redirect to (Required)\n\t *\n\t * @param path the path to redirect to, can include :ts :userId\n\t * @param query any query parameters you want to add, can include :ts :userId\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>(\n\t\tpath: P,\n\t\t{ method = \"GET\", query }: RouteOptions = {},\n\t) {\n\t\tsuper.setCustomId(\n\t\t\tencodePath({\n\t\t\t\tidPrefix: this.#embedRouter.getIdPrefix(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tquery,\n\t\t\t}),\n\t\t);\n\n\t\treturn this;\n\t}\n}\n"],"mappings":"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","names":["path","path","path","path","path","path","path","path","path","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discord-embed-router",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "A vite inspired router for discord.js embeds and interactions",
5
5
  "files": [
6
6
  "dist"
@@ -23,6 +23,8 @@
23
23
  "discord",
24
24
  "discord.js",
25
25
  "embeds",
26
+ "discord router",
27
+ "discord embed router",
26
28
  "router",
27
29
  "interactions"
28
30
  ],