discord-embed-router 0.2.3 → 0.2.5

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.mjs CHANGED
@@ -2,6 +2,9 @@
2
2
  import path from "path";
3
3
  import { createHash } from "crypto";
4
4
  import { match } from "path-to-regexp";
5
+ import {
6
+ MessageFlags
7
+ } from "discord.js";
5
8
 
6
9
  // src/consts.ts
7
10
  var ID_PREFIX = "der";
@@ -41,25 +44,52 @@ var decodePath = ({
41
44
  }) => {
42
45
  const customId = interaction.customId;
43
46
  if (!customId.startsWith(idPrefix)) return false;
47
+ const res = parseMethodAndPath(customId.slice(idPrefix.length));
48
+ if (!res) return false;
49
+ const { method, path: path2 } = res;
44
50
  if (interaction.isButton()) {
45
- return parseMethodAndPath(customId.slice(idPrefix.length));
51
+ return {
52
+ method,
53
+ path: urlToPathString(
54
+ fillParams(path2, {
55
+ ts: interaction.createdTimestamp.toString()
56
+ })
57
+ )
58
+ };
46
59
  } else if (interaction.isAnySelectMenu()) {
47
60
  if (interaction.values.length === 0) return false;
48
- const res = parseMethodAndPath(customId.slice(idPrefix.length));
49
- if (!res) return false;
50
- const { method, path: path2 } = res;
61
+ if (interaction.isStringSelectMenu()) {
62
+ const toRes = parseOptionalMethodAndPath(interaction.values[0]);
63
+ const toURL = toRes ? fillParams(toRes.path, {
64
+ ts: interaction.createdTimestamp.toString()
65
+ }) : void 0;
66
+ const pathURL = fillParams(path2, {
67
+ ts: interaction.createdTimestamp.toString(),
68
+ to: toURL ? toURL.pathname.split("/").slice(1) : ""
69
+ });
70
+ for (const [key, value] of toURL?.searchParams ?? []) {
71
+ pathURL.searchParams.append(key, value);
72
+ }
73
+ return {
74
+ method,
75
+ path: urlToPathString(pathURL)
76
+ };
77
+ }
51
78
  return {
52
79
  method,
53
- path: fillParams(path2, {
54
- [interaction.isStringSelectMenu() ? "to" : interaction.isChannelSelectMenu() ? "channelId" : interaction.isRoleSelectMenu() ? "roleId" : "userId"]: interaction.values[0].split("/").slice(1)
55
- })
80
+ path: urlToPathString(
81
+ fillParams(path2, {
82
+ ts: interaction.createdTimestamp.toString(),
83
+ [interaction.isChannelSelectMenu() ? "channelId" : interaction.isRoleSelectMenu() ? "roleId" : "userId"]: interaction.values[0].split("/").slice(1)
84
+ })
85
+ )
56
86
  };
57
87
  }
58
88
  return false;
59
89
  };
60
90
  var parseMethodAndPath = (pathWithMethod) => {
61
91
  const firstSlash = pathWithMethod.indexOf("/");
62
- if (firstSlash <= 0) return false;
92
+ if (firstSlash < 0) return false;
63
93
  const method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];
64
94
  if (method === void 0) return false;
65
95
  return {
@@ -67,13 +97,22 @@ var parseMethodAndPath = (pathWithMethod) => {
67
97
  path: pathWithMethod.slice(firstSlash)
68
98
  };
69
99
  };
100
+ var parseOptionalMethodAndPath = (pathWithMethod) => {
101
+ const firstSlash = pathWithMethod.indexOf("/");
102
+ if (firstSlash < 0) return false;
103
+ const method = ENCODING_TO_METHOD[pathWithMethod.slice(0, firstSlash)];
104
+ return {
105
+ method: method ?? "",
106
+ path: pathWithMethod.slice(firstSlash)
107
+ };
108
+ };
70
109
  var fillParams = (path2, params = {}) => {
71
110
  const url = new URL(path2, BASE_URL);
72
111
  const toPath = compile(url.pathname);
73
112
  url.pathname = toPath(params);
74
113
  for (const [key, value] of url.searchParams) {
75
- if (value.startsWith(":") && key.slice(1) in params) {
76
- const paramValue = params?.[key.slice(1)];
114
+ if (value.startsWith(":") && value.slice(1) in params) {
115
+ const paramValue = params?.[value.slice(1)];
77
116
  if (paramValue) {
78
117
  url.searchParams.set(
79
118
  key,
@@ -84,6 +123,9 @@ var fillParams = (path2, params = {}) => {
84
123
  }
85
124
  }
86
125
  }
126
+ return url;
127
+ };
128
+ var urlToPathString = (url) => {
87
129
  return `${url.pathname}${url.search}`;
88
130
  };
89
131
 
@@ -101,6 +143,8 @@ var EmbedRouter = class _EmbedRouter {
101
143
  }
102
144
  // All added routes
103
145
  #routes = /* @__PURE__ */ new Map();
146
+ // message.id -> cleanup object
147
+ #cleanups = /* @__PURE__ */ new Map();
104
148
  /**
105
149
  *
106
150
  * @param name the name to give the router. ensures buttons stay connected across restarts
@@ -224,10 +268,13 @@ var EmbedRouter = class _EmbedRouter {
224
268
  * @param interaction interactions from "interactionCreate" (filter for ButtonInteractions)
225
269
  */
226
270
  async listener(interaction, locals) {
271
+ if (interaction.isAutocomplete())
272
+ throw new Error("Autocomplete Interactions aren't supported");
273
+ this.#runCleanup(interaction.message.id, false);
227
274
  const res = decodePath({ idPrefix: this.getIdPrefix(), interaction });
228
275
  if (!res)
229
276
  throw new Error(`Invalid component found: id ${interaction.customId}`);
230
- this.dispatch({ interaction, method: res.method, path: res.path, locals });
277
+ this.dispatch(interaction, res.path, { method: res.method, locals });
231
278
  }
232
279
  /**
233
280
  * Replies to or editReplies to an interaction based on the route output
@@ -238,19 +285,16 @@ var EmbedRouter = class _EmbedRouter {
238
285
  * @param flags discord flags to send with message (optional, only allowed on first reply)
239
286
  * @param locals additional info to pass in to page through state.local (optional)
240
287
  */
241
- async dispatch({
242
- interaction,
288
+ async dispatch(interaction, path2, {
243
289
  method = "GET",
244
- path: path2,
245
290
  flags,
246
291
  locals
247
- }) {
292
+ } = {}) {
248
293
  if (interaction.isAutocomplete())
249
294
  throw new Error("Autocomplete Interactions aren't supported");
250
- const routeResponse = await this.#resolve({
295
+ const routeResponse = await this.#resolve(path2, {
251
296
  interaction,
252
297
  method,
253
- path: path2,
254
298
  locals
255
299
  });
256
300
  if (routeResponse === false)
@@ -274,11 +318,28 @@ var EmbedRouter = class _EmbedRouter {
274
318
  );
275
319
  await interaction.update(routeResponse);
276
320
  } else {
277
- interaction.reply({
321
+ await interaction.reply({
278
322
  ...routeResponse,
279
323
  flags
280
324
  });
281
325
  }
326
+ if (!routeResponse?.cleanup) return;
327
+ const message = await interaction.fetchReply();
328
+ const channel = interaction.channel;
329
+ const applyFn = message.flags.has(
330
+ MessageFlags.Ephemeral
331
+ ) ? interaction.editReply.bind(interaction) : channel ? (options) => channel.messages.edit(message.id, options) : void 0;
332
+ if (!applyFn)
333
+ return process.emitWarning(
334
+ `Could not derive applyFunction for ${pathToString(path2, false)}. Cleanup return results will not be applied to message.`,
335
+ "EmbedRouterWarning"
336
+ );
337
+ this.#addCleanup(
338
+ message.id,
339
+ routeResponse.cleanup.bind(routeResponse),
340
+ applyFn,
341
+ routeResponse?.timeout
342
+ );
282
343
  }
283
344
  /**
284
345
  * Resolves a route to the associated message (DOES NOT UPDATE MESSAGE)
@@ -289,10 +350,9 @@ var EmbedRouter = class _EmbedRouter {
289
350
  * @param locals additional info to pass in to page through state.local (optional)
290
351
  * @returns discord message associated with route OR false
291
352
  */
292
- async #resolve({
353
+ async #resolve(path2, {
293
354
  interaction,
294
355
  method = "GET",
295
- path: path2,
296
356
  locals
297
357
  }) {
298
358
  const url = new URL(pathToString(path2, false), BASE_URL);
@@ -309,6 +369,30 @@ var EmbedRouter = class _EmbedRouter {
309
369
  }
310
370
  return false;
311
371
  }
372
+ // Helpers for using and storing cleanup functions
373
+ #addCleanup(messageId, cleanupFn, applyFn, timeout) {
374
+ this.#removeCleanup(messageId);
375
+ this.#cleanups.set(messageId, {
376
+ cleanupFn,
377
+ applyFn,
378
+ timeout: isFinite(timeout) ? setTimeout(() => this.#runCleanup(messageId, true), timeout) : void 0
379
+ });
380
+ }
381
+ #removeCleanup(messageId) {
382
+ const cleanup = this.#cleanups.get(messageId);
383
+ if (!cleanup) return;
384
+ clearTimeout(cleanup.timeout);
385
+ this.#cleanups.delete(messageId);
386
+ }
387
+ async #runCleanup(messageId, applyResult) {
388
+ const cleanup = this.#cleanups.get(messageId);
389
+ 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);
394
+ }
395
+ }
312
396
  };
313
397
 
314
398
  // src/componentBuilders/RouteButtonBuilder.ts
@@ -327,12 +411,7 @@ var encodePath = ({
327
411
  url.searchParams.set(key, value);
328
412
  }
329
413
  }
330
- return `${idPrefix}${METHOD_TO_ENCODING[method]}${url.pathname}${url.search}`;
331
- };
332
-
333
- // src/types/componentBuilders.ts
334
- var isSetOptions = (u) => {
335
- return typeof u === "object" && u !== null && (!("method" in u) || "method" in u && typeof u.method === "string" || u.method === void 0) && "path" in u && typeof u.path === "string" && (!("query" in u) || "query" in u && ["object", "string"].includes(typeof u.query) || u.query === void 0);
414
+ return `${idPrefix}${method === "" ? "" : METHOD_TO_ENCODING[method]}${url.pathname}${url.search}`;
336
415
  };
337
416
 
338
417
  // src/componentBuilders/RouteButtonBuilder.ts
@@ -365,12 +444,14 @@ var RouteButtonBuilder = class extends ButtonBuilder {
365
444
  setCustomId() {
366
445
  throw new Error("setCustomId is not supported on RouteButtonBuilder");
367
446
  }
368
- setTo(arg) {
369
- const {
370
- method = "GET",
371
- path: path2,
372
- query
373
- } = isSetOptions(arg) ? arg : { path: arg };
447
+ /**
448
+ * Sets the path to route to when clicked
449
+ *
450
+ * @param path the path to route to, can include :ts
451
+ * @param query any query parameters you want to add, can include :ts
452
+ * @param method method to send to route
453
+ */
454
+ setTo(path2, { method = "GET", query } = {}) {
374
455
  super.setCustomId(
375
456
  encodePath({
376
457
  idPrefix: this.#embedRouter.getIdPrefix(),
@@ -389,7 +470,7 @@ import {
389
470
  StringSelectMenuBuilder
390
471
  } from "discord.js";
391
472
 
392
- // src/componentBuilders/RouteStringMenuOptionBuilder.ts
473
+ // src/componentBuilders/RouteStringSelectMenuOptionBuilder.ts
393
474
  import { StringSelectMenuOptionBuilder } from "discord.js";
394
475
  var RouteStringSelectMenuOptionBuilder = class extends StringSelectMenuOptionBuilder {
395
476
  /**
@@ -403,12 +484,14 @@ var RouteStringSelectMenuOptionBuilder = class extends StringSelectMenuOptionBui
403
484
  "setValue is not supported on RouteStringSelectMenuOptionBuilder"
404
485
  );
405
486
  }
406
- setTo(arg) {
407
- const {
408
- method = "GET",
409
- path: path2,
410
- query
411
- } = isSetOptions(arg) ? arg : { path: arg };
487
+ /**
488
+ * Sets the path to route to when selected
489
+ *
490
+ * @param path the path to route to, can include :ts
491
+ * @param query any query parameters you want to add, can include :ts
492
+ * @param method method to send to route
493
+ */
494
+ setTo(path2, { method = "", query } = {}) {
412
495
  super.setValue(
413
496
  encodePath({
414
497
  idPrefix: "",
@@ -503,12 +586,14 @@ var RouteStringSelectMenuBuilder = class extends StringSelectMenuBuilder {
503
586
  );
504
587
  return this;
505
588
  }
506
- setPattern(arg) {
507
- const {
508
- method = "GET",
509
- path: path2,
510
- query
511
- } = isSetOptions(arg) ? arg : { path: arg };
589
+ /**
590
+ * Sets the pattern to redirect to (Required)
591
+ *
592
+ * @param path the path to redirect to, can include :ts :to *to
593
+ * @param query any query parameters you want to add, can include :ts :to *to
594
+ * @param method method to send to route
595
+ */
596
+ setPattern(path2, { method = "GET", query } = {}) {
512
597
  super.setCustomId(
513
598
  encodePath({
514
599
  idPrefix: this.#embedRouter.getIdPrefix(),
@@ -547,12 +632,14 @@ var RouteChannelSelectMenuBuilder = class extends ChannelSelectMenuBuilder {
547
632
  "setCustomId is not supported on RouteChannelSelectMenuBuilder"
548
633
  );
549
634
  }
550
- setPattern(arg) {
551
- const {
552
- method = "GET",
553
- path: path2,
554
- query
555
- } = isSetOptions(arg) ? arg : { path: arg };
635
+ /**
636
+ * Sets the pattern to redirect to (Required)
637
+ *
638
+ * @param path the path to redirect to, can include :ts :channelId
639
+ * @param query any query parameters you want to add, can include :ts :channelId
640
+ * @param method method to send to route
641
+ */
642
+ setPattern(path2, { method = "GET", query } = {}) {
556
643
  super.setCustomId(
557
644
  encodePath({
558
645
  idPrefix: this.#embedRouter.getIdPrefix(),
@@ -591,12 +678,14 @@ var RouteRoleSelectMenuBuilder = class extends RoleSelectMenuBuilder {
591
678
  "setCustomId is not supported on RouteRoleSelectMenuBuilder"
592
679
  );
593
680
  }
594
- setPattern(arg) {
595
- const {
596
- method = "GET",
597
- path: path2,
598
- query
599
- } = isSetOptions(arg) ? arg : { path: arg };
681
+ /**
682
+ * Sets the pattern to redirect to (Required)
683
+ *
684
+ * @param path the path to redirect to, can include :ts :roleId
685
+ * @param query any query parameters you want to add, can include :ts :roleId
686
+ * @param method method to send to route
687
+ */
688
+ setPattern(path2, { method = "GET", query } = {}) {
600
689
  super.setCustomId(
601
690
  encodePath({
602
691
  idPrefix: this.#embedRouter.getIdPrefix(),
@@ -635,12 +724,14 @@ var RouteUserSelectMenuBuilder = class extends UserSelectMenuBuilder {
635
724
  "setCustomId is not supported on RouteUserSelectMenuBuilder"
636
725
  );
637
726
  }
638
- setPattern(arg) {
639
- const {
640
- method = "GET",
641
- path: path2,
642
- query
643
- } = isSetOptions(arg) ? arg : { path: arg };
727
+ /**
728
+ * Sets the pattern to redirect to (Required)
729
+ *
730
+ * @param path the path to redirect to, can include :ts :userId
731
+ * @param query any query parameters you want to add, can include :ts :userId
732
+ * @param method method to send to route
733
+ */
734
+ setPattern(path2, { method = "GET", query } = {}) {
644
735
  super.setCustomId(
645
736
  encodePath({
646
737
  idPrefix: this.#embedRouter.getIdPrefix(),
@@ -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/types/componentBuilders.ts","../src/componentBuilders/RouteStringSelectMenuBuilder.ts","../src/componentBuilders/RouteStringMenuOptionBuilder.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\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} 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\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>(routePath: P, embedRouter: EmbedRouter<L>) {\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\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, method: res.method, path: res.path, 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,\n\t\tmethod = \"GET\",\n\t\tpath,\n\t\tflags,\n\t\tlocals,\n\t}: {\n\t\tinteraction: Interaction;\n\t\tmethod?: Method;\n\t\tpath: P;\n\t\tflags?: InteractionReplyOptions[\"flags\"] | undefined;\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\t// don't check validity because url params are considered invalid\n\t\tconst routeResponse = await this.#resolve({\n\t\t\tinteraction,\n\t\t\tmethod,\n\t\t\tpath,\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\tinteraction.reply({\n\t\t\t\t...(routeResponse as InteractionReplyOptions),\n\t\t\t\tflags,\n\t\t\t});\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\tinteraction,\n\t\tmethod = \"GET\",\n\t\tpath,\n\t\tlocals,\n\t}: {\n\t\tinteraction: Interaction;\n\t\tmethod?: Method;\n\t\tpath: P;\n\t\tlocals?: L | undefined;\n\t}): Promise<RouteResponse | 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","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\tif (interaction.isButton()) {\n\t\treturn parseMethodAndPath(customId.slice(idPrefix.length));\n\t} else if (interaction.isAnySelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\t\tconst res = parseMethodAndPath(customId.slice(idPrefix.length));\n\t\tif (!res) return false;\n\n\t\tconst { method, path } = res;\n\t\treturn {\n\t\t\tmethod,\n\t\t\tpath: fillParams(path, {\n\t\t\t\t[interaction.isStringSelectMenu()\n\t\t\t\t\t? \"to\"\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}),\n\t\t};\n\t}\n\n\treturn false;\n};\n\nexport const 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 fillParams = (\n\tpath: string,\n\tparams: Partial<Record<string, string | string[]>> = {},\n): string => {\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(\":\") && key.slice(1) in params) {\n\t\t\tconst paramValue = params?.[key.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.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 { isSetOptions, SetOptions } 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\n\t * @param query any query parameters you want to add\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>({ method, path, query }: SetOptions<P>): this;\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to\n\t */\n\tpublic setTo<P extends Path>(path: P): this;\n\n\tpublic setTo<P extends Path>(arg: P | SetOptions<P>) {\n\t\tconst {\n\t\t\tmethod = \"GET\",\n\t\t\tpath,\n\t\t\tquery,\n\t\t} = isSetOptions(arg) ? arg : { path: arg };\n\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 = ({\n\tidPrefix,\n\tmethod,\n\tpath,\n\tquery,\n}: {\n\tidPrefix: string;\n\tmethod: 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_TO_ENCODING[method]}${url.pathname}${url.search}`;\n};\n","import { Path } from \"path-to-regexp\";\nimport { Method } from \"./routes\";\n\nexport type SetOptions<P extends Path> = {\n\tmethod?: Method;\n\tpath: P;\n\tquery?: ConstructorParameters<typeof URLSearchParams>[0] | undefined;\n};\n\nexport const isSetOptions = <P extends Path>(\n\tu: unknown,\n): u is SetOptions<P> => {\n\treturn (\n\t\ttypeof u === \"object\" &&\n\t\tu !== null &&\n\t\t(!(\"method\" in u) ||\n\t\t\t(\"method\" in u && typeof u.method === \"string\") ||\n\t\t\tu.method === undefined) &&\n\t\t\"path\" in u &&\n\t\ttypeof u.path === \"string\" &&\n\t\t(!(\"query\" in u) ||\n\t\t\t(\"query\" in u && [\"object\", \"string\"].includes(typeof u.query)) ||\n\t\t\tu.query === undefined)\n\t);\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 \"./RouteStringMenuOptionBuilder\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\nimport { isSetOptions, SetOptions } 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, :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 method method to send to route\n\t */\n\tpublic setPattern<P extends Path>({\n\t\tmethod,\n\t\tpath,\n\t\tquery,\n\t}: SetOptions<P>): this;\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to\n\t */\n\tpublic setPattern<P extends Path>(path: P): this;\n\n\tpublic setPattern<P extends Path>(arg: P | SetOptions<P>) {\n\t\tconst {\n\t\t\tmethod = \"GET\",\n\t\t\tpath,\n\t\t\tquery,\n\t\t} = isSetOptions(arg) ? arg : { path: arg };\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 { isSetOptions, SetOptions } 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 clicked\n\t *\n\t * @param path the path to route to\n\t * @param query any query parameters you want to add\n\t * @param method method to send to route\n\t */\n\tpublic setTo<P extends Path>({ method, path, query }: SetOptions<P>): this;\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to\n\t */\n\tpublic setTo<P extends Path>(path: P): this;\n\n\tpublic setTo<P extends Path>(arg: P | SetOptions<P>) {\n\t\tconst {\n\t\t\tmethod = \"GET\",\n\t\t\tpath,\n\t\t\tquery,\n\t\t} = isSetOptions(arg) ? arg : { path: arg };\n\t\tsuper.setValue(\n\t\t\tencodePath({\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 { isSetOptions, SetOptions } 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, :channelId in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :channelId will be replaced with the selected user's id\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>({\n\t\tmethod,\n\t\tpath,\n\t\tquery,\n\t}: SetOptions<P>): this;\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to\n\t */\n\tpublic setPattern<P extends Path>(path: P): this;\n\n\tpublic setPattern<P extends Path>(arg: P | SetOptions<P>) {\n\t\tconst {\n\t\t\tmethod = \"GET\",\n\t\t\tpath,\n\t\t\tquery,\n\t\t} = isSetOptions(arg) ? arg : { path: arg };\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 { isSetOptions, SetOptions } 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, :roleId in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :roleId will be replaced with the selected user's id\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>({\n\t\tmethod,\n\t\tpath,\n\t\tquery,\n\t}: SetOptions<P>): this;\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to\n\t */\n\tpublic setPattern<P extends Path>(path: P): this;\n\n\tpublic setPattern<P extends Path>(arg: P | SetOptions<P>) {\n\t\tconst {\n\t\t\tmethod = \"GET\",\n\t\t\tpath,\n\t\t\tquery,\n\t\t} = isSetOptions(arg) ? arg : { path: arg };\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 { isSetOptions, SetOptions } 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, :userId in path will be replaced with the selected user's id\n\t * @param query any query parameters you want to add, :userId will be replaced with the selected user's id\n\t * @param method method to send to route\n\t */\n\tpublic setPattern<P extends Path>({\n\t\tmethod,\n\t\tpath,\n\t\tquery,\n\t}: SetOptions<P>): this;\n\t/**\n\t * Sets the path to route to when clicked\n\t *\n\t * @param path the path to route to\n\t */\n\tpublic setPattern<P extends Path>(path: P): this;\n\n\tpublic setPattern<P extends Path>(arg: P | SetOptions<P>) {\n\t\tconst {\n\t\t\tmethod = \"GET\",\n\t\t\tpath,\n\t\t\tquery,\n\t\t} = isSetOptions(arg) ? arg : { path: arg };\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":";AAAA,OAAO,UAAU;AACjB,SAAS,kBAAkB;AAC3B,SAAS,aAAgC;;;ACAlC,IAAM,YAAY;AAClB,IAAM,qBAA6C;AAAA,EACzD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AACT;AACO,IAAM,qBAA6C;AAAA,EACzD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACJ;AAEO,IAAM,WAAW;AAEjB,IAAM,YAAY;AAClB,IAAM,UAAU;AAChB,IAAM,YAAY,UAAU,YAAY;;;ACtB/C,SAAS,OAAa,WAAW,iBAAiB;AAE3C,IAAM,eAAe,CAC3BA,OACA,gBAAgB,SACJ;AACZ,MAAI,eAAe;AAClB,WAAO,UAAUA,iBAAgB,YAAYA,QAAO,MAAMA,KAAI,CAAC;AAAA,EAChE;AACA,SAAO,OAAOA,UAAS,WAAWA,QAAO,UAAUA,KAAI;AACxD;;;ACVA,SAAS,eAAqB;AAKvB,IAAM,aAAa,CAAC;AAAA,EAC1B;AAAA,EACA;AACD,MAG8C;AAC7C,QAAM,WAAW,YAAY;AAC7B,MAAI,CAAC,SAAS,WAAW,QAAQ,EAAG,QAAO;AAE3C,MAAI,YAAY,SAAS,GAAG;AAC3B,WAAO,mBAAmB,SAAS,MAAM,SAAS,MAAM,CAAC;AAAA,EAC1D,WAAW,YAAY,gBAAgB,GAAG;AACzC,QAAI,YAAY,OAAO,WAAW,EAAG,QAAO;AAC5C,UAAM,MAAM,mBAAmB,SAAS,MAAM,SAAS,MAAM,CAAC;AAC9D,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,EAAE,QAAQ,MAAAC,MAAK,IAAI;AACzB,WAAO;AAAA,MACN;AAAA,MACA,MAAM,WAAWA,OAAM;AAAA,QACtB,CAAC,YAAY,mBAAmB,IAC7B,OACA,YAAY,oBAAoB,IAC/B,cACA,YAAY,iBAAiB,IAC5B,WACA,QAAQ,GAAG,YAAY,OAAO,CAAC,EAAG,MAAM,GAAG,EAAE,MAAM,CAAC;AAAA,MAC1D,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAEO,IAAM,qBAAqB,CACjC,mBAC8C;AAE9C,QAAM,aAAa,eAAe,QAAQ,GAAG;AAE7C,MAAI,cAAc,EAAG,QAAO;AAE5B,QAAM,SAAS,mBAAmB,eAAe,MAAM,GAAG,UAAU,CAAC;AACrE,MAAI,WAAW,OAAW,QAAO;AACjC,SAAO;AAAA,IACN;AAAA,IACA,MAAM,eAAe,MAAM,UAAU;AAAA,EACtC;AACD;AAEA,IAAM,aAAa,CAClBA,OACA,SAAqD,CAAC,MAC1C;AACZ,QAAM,MAAM,IAAI,IAAIA,OAAM,QAAQ;AAClC,QAAM,SAAS,QAAQ,IAAI,QAAQ;AAEnC,MAAI,WAAW,OAAO,MAAM;AAC5B,aAAW,CAAC,KAAK,KAAK,KAAK,IAAI,cAAc;AAC5C,QAAI,MAAM,WAAW,GAAG,KAAK,IAAI,MAAM,CAAC,KAAK,QAAQ;AACpD,YAAM,aAAa,SAAS,IAAI,MAAM,CAAC,CAAC;AACxC,UAAI,YAAY;AACf,YAAI,aAAa;AAAA,UAChB;AAAA,UACA,MAAM,QAAQ,UAAU,IAAI,WAAW,KAAK,GAAG,IAAI;AAAA,QACpD;AAAA,MACD,OAAO;AACN,YAAI,aAAa,OAAO,GAAG;AAAA,MAC5B;AAAA,IACD;AAAA,EACD;AACA,SAAO,GAAG,IAAI,QAAQ,GAAG,IAAI,MAAM;AACpC;;;AH1DO,IAAM,cAAN,MAAM,aAAe;AAAA;AAAA,EAE3B,OAAO,mBAAmB,oBAAI,IAAkC;AAAA;AAAA,EAGhE,QAAQ;AAAA;AAAA,EAER;AAAA,EACA,cAAsB;AAAA,EACf,cAAc;AACpB,WAAO,GAAG,KAAK,SAAS,GAAG,KAAK,WAAW;AAAA,EAC5C;AAAA;AAAA,EAGA,UAAmD,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3D,YAAY;AAAA,IACX,OAAO;AAAA,IACP,WAAW;AAAA,EACZ,IAGI,CAAC,GAAG;AACP,QAAI,aAAY,iBAAiB,QAAQ,WAAW;AACnD,YAAM,IAAI,MAAM,8BAA8B,SAAS,UAAU;AAAA,IAClE;AACA,QAAI,SAAS,SAAS,GAAG,GAAG;AAC3B,YAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,IACxD;AACA,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,kBAAkB;AAAA,EACxB;AAAA,EAEA,oBAAoB;AAEnB,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,KAAK,EAAE,OAAO;AAC5D,QAAI,MAAM,KAAK,aAAa,CAAC;AAC7B,QAAI;AACJ,UAAM,iBAAiB,CAAC;AAExB,WAAO,MAAM;AACZ,YAAM,YAAY,YAAa,QAAQ;AACvC,aAAO,OAAO,cAAc,SAAS;AAErC,YAAM,kBAAkB,aAAY,iBAAiB,IAAI,IAAI;AAC7D,UAAI,oBAAoB,OAAW;AAEnC,UAAI,KAAK,MAAM,SAAS,KAAK,gBAAgB,MAAM,WAAW,GAAG;AAEhE,wBAAgB,kBAAkB;AAClC;AAAA,MACD;AAEA,qBAAe,KAAK,eAAe;AAAA,IACpC;AACA,iBAAY,iBAAiB,IAAI,MAAM,IAA4B;AAEnE,QAAI,eAAe,SAAS,KAAK,KAAK,MAAM,SAAS,GAAG;AACvD,cAAQ;AAAA,QACP,8CAA8C,KAAK,KAAK,UAAU,eAAe,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QACtH;AAAA,MACD;AAAA,IACD;AACA,SAAK,cAAc;AAAA,EACpB;AAAA,EAEA,UACC,QACA,WACA,SACC;AACD,UAAM,eAAe,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC;AAClD,iBAAa,KAAK;AAAA,MACjB;AAAA,MACA,MAAM,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AAAA,MACvD,eAAe,MAAM,SAAS;AAAA,MAC9B;AAAA,IACD,CAAC;AACD,SAAK,QAAQ,IAAI,QAAQ,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,IACN,WACA,SACC;AACD,SAAK,UAAU,OAAO,WAAW,OAAO;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,KACN,WACA,SACC;AACD,SAAK,UAAU,QAAQ,WAAW,OAAO;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,IACN,WACA,SACC;AACD,SAAK,UAAU,OAAO,WAAW,OAAO;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,MACN,WACA,SACC;AACD,SAAK,UAAU,SAAS,WAAW,OAAO;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,OACN,WACA,SACC;AACD,SAAK,UAAU,UAAU,WAAW,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,IAA2B,WAAc,aAA6B;AAC5E,UAAM,aAAa,aAAa,SAAS;AACzC,eAAW,CAAC,QAAQ,MAAM,KAAK,YAAY,SAAS;AACnD,iBAAW,SAAS,QAAQ;AAC3B,aAAK;AAAA,UACJ;AAAA,UACA,MAAM,KAAK,IAAI,CAAC,MAAM,KAAK,MAAM,KAAK,YAAY,aAAa,CAAC,CAAC,CAAC;AAAA,UAClE,MAAM;AAAA,QACP;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,SACZ,aACA,QACC;AACD,UAAM,MAAM,WAAW,EAAE,UAAU,KAAK,YAAY,GAAG,YAAY,CAAC;AACpE,QAAI,CAAC;AACJ,YAAM,IAAI,MAAM,+BAA+B,YAAY,QAAQ,EAAE;AAEtE,SAAK,SAAS,EAAE,aAAa,QAAQ,IAAI,QAAQ,MAAM,IAAI,MAAM,OAAO,CAAC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,SAAgC;AAAA,IAC5C;AAAA,IACA,SAAS;AAAA,IACT,MAAAC;AAAA,IACA;AAAA,IACA;AAAA,EACD,GAMG;AACF,QAAI,YAAY,eAAe;AAC9B,YAAM,IAAI,MAAM,4CAA4C;AAG7D,UAAM,gBAAgB,MAAM,KAAK,SAAS;AAAA,MACzC;AAAA,MACA;AAAA,MACA,MAAAA;AAAA,MACA;AAAA,IACD,CAAC;AACD,QAAI,kBAAkB;AACrB,YAAM,IAAI,MAAM,sBAAsB,aAAaA,OAAM,KAAK,CAAC,EAAE;AAElE,QAAI,YAAY,WAAW,YAAY,UAAU;AAChD,UAAI;AACH,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AACD,UAAI,cAAe,OAAM,YAAY,UAAU,aAAa;AAAA,IAC7D,WAAW,CAAC,eAAe;AAC1B,UAAI,iBAAiB,aAAa;AACjC,cAAM,YAAY,YAAY;AAAA,MAC/B,OAAO;AACN,cAAM,YAAY,WAAW;AAAA,MAC9B;AAAA,IACD,WAAW,YAAY,aAAa;AACnC,UAAI;AACH,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AACD,YAAM,YAAY,OAAO,aAAa;AAAA,IACvC,OAAO;AACN,kBAAY,MAAM;AAAA,QACjB,GAAI;AAAA,QACJ;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SAAyB;AAAA,IAC9B;AAAA,IACA,SAAS;AAAA,IACT,MAAAA;AAAA,IACA;AAAA,EACD,GAKmC;AAElC,UAAM,MAAM,IAAI,IAAI,aAAaA,OAAM,KAAK,GAAG,QAAQ;AACvD,eAAW,SAAS,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC,GAAG;AACnD,YAAM,SAAS,MAAM,cAAc,IAAI,QAAQ;AAC/C,UAAI,QAAQ;AACX,eAAO,MAAM,MAAM,QAAQ,aAAa;AAAA,UACvC,GAAI;AAAA,UACJ,OAAO,IAAI;AAAA,UACX,aAAa;AAAA,UACb;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;;;AI/SA,SAA6B,qBAAqB;;;ACK3C,IAAM,aAAa,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,MAAAC;AAAA,EACA;AACD,MAKM;AACL,QAAM,MAAM,IAAI,IAAI,aAAaA,KAAI,GAAG,QAAQ;AAChD,MAAI,OAAO;AACV,eAAW,CAAC,KAAK,KAAK,KAAK,IAAI,gBAAgB,KAAK,GAAG;AACtD,UAAI,aAAa,IAAI,KAAK,KAAK;AAAA,IAChC;AAAA,EACD;AACA,SAAO,GAAG,QAAQ,GAAG,mBAAmB,MAAM,CAAC,GAAG,IAAI,QAAQ,GAAG,IAAI,MAAM;AAC5E;;;ACdO,IAAM,eAAe,CAC3B,MACwB;AACxB,SACC,OAAO,MAAM,YACb,MAAM,SACL,EAAE,YAAY,MACb,YAAY,KAAK,OAAO,EAAE,WAAW,YACtC,EAAE,WAAW,WACd,UAAU,KACV,OAAO,EAAE,SAAS,aACjB,EAAE,WAAW,MACZ,WAAW,KAAK,CAAC,UAAU,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,KAC7D,EAAE,UAAU;AAEf;;;AFlBO,IAAM,qBAAN,cAAoC,cAAc;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YACC,aACA,MACC;AACD,UAAM,IAAI;AAEV,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,SAAe;AACvB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACrE;AAAA,EAiBO,MAAsB,KAAwB;AACpD,UAAM;AAAA,MACL,SAAS;AAAA,MACT,MAAAC;AAAA,MACA;AAAA,IACD,IAAI,aAAa,GAAG,IAAI,MAAM,EAAE,MAAM,IAAI;AAE1C,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU,KAAK,aAAa,YAAY;AAAA,QACxC;AAAA,QACA,MAAAA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AACD;;;AG5EA;AAAA,EAEC;AAAA,EAEA;AAAA,OAEM;;;ACNP,SAAS,qCAAqC;AAKvC,IAAM,qCAAN,cAAiD,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5E,WAAiB;AACzB,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA,EAiBO,MAAsB,KAAwB;AACpD,UAAM;AAAA,MACL,SAAS;AAAA,MACT,MAAAC;AAAA,MACA;AAAA,IACD,IAAI,aAAa,GAAG,IAAI,MAAM,EAAE,MAAM,IAAI;AAC1C,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,MAAAA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AACD;;;ADrCO,IAAM,+BAAN,cAA8C,wBAAwB;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,aACA,MAGC;AACD,UAAM,IAAI;AAEV,SAAK,eAAe;AAEpB,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU,KAAK,aAAa,YAAY;AAAA,QACxC,QAAQ;AAAA,QACR,MAAM;AAAA,MACP,CAAC;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,aAAmB;AAC3B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,aAAmB;AAC3B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,UACH,KAII;AACP,UAAM,WAAW,eAAe,GAAG;AACnC,UAAM;AAAA,MACL,SAAS;AAAA,QAAI,CAAC,MACb,aAAa,qCACV,IACA,IAAI,mCAAmC,CAAC;AAAA,MAC5C;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,UACH,KAII;AACP,UAAM,WAAW,eAAe,GAAG;AACnC,UAAM;AAAA,MACL,SAAS;AAAA,QAAI,CAAC,MACb,aAAa,qCACV,IACA,IAAI,mCAAmC,CAAC;AAAA,MAC5C;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAqBO,WAA2B,KAAwB;AACzD,UAAM;AAAA,MACL,SAAS;AAAA,MACT,MAAAC;AAAA,MACA;AAAA,IACD,IAAI,aAAa,GAAG,IAAI,MAAM,EAAE,MAAM,IAAI;AAC1C,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU,KAAK,aAAa,YAAY;AAAA,QACxC;AAAA,QACA,MAAAA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AACD;;;AE9JA;AAAA,EAEC;AAAA,OAEM;AAMA,IAAM,gCAAN,cAA+C,yBAAyB;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YACC,aACA,MAGC;AACD,UAAM,IAAI;AAEV,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA,EAqBO,WAA2B,KAAwB;AACzD,UAAM;AAAA,MACL,SAAS;AAAA,MACT,MAAAC;AAAA,MACA;AAAA,IACD,IAAI,aAAa,GAAG,IAAI,MAAM,EAAE,MAAM,IAAI;AAC1C,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU,KAAK,aAAa,YAAY;AAAA,QACxC;AAAA,QACA,MAAAA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AACD;;;AC7EA;AAAA,EAEC;AAAA,OAEM;AAMA,IAAM,6BAAN,cAA4C,sBAAsB;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YACC,aACA,MAEC;AACD,UAAM,IAAI;AAEV,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA,EAqBO,WAA2B,KAAwB;AACzD,UAAM;AAAA,MACL,SAAS;AAAA,MACT,MAAAC;AAAA,MACA;AAAA,IACD,IAAI,aAAa,GAAG,IAAI,MAAM,EAAE,MAAM,IAAI;AAC1C,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU,KAAK,aAAa,YAAY;AAAA,QACxC;AAAA,QACA,MAAAA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AACD;;;AC5EA;AAAA,EAEC;AAAA,OAEM;AAMA,IAAM,6BAAN,cAA4C,sBAAsB;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YACC,aACA,MAEC;AACD,UAAM,IAAI;AAEV,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA,EAqBO,WAA2B,KAAwB;AACzD,UAAM;AAAA,MACL,SAAS;AAAA,MACT,MAAAC;AAAA,MACA;AAAA,IACD,IAAI,aAAa,GAAG,IAAI,MAAM,EAAE,MAAM,IAAI;AAC1C,UAAM;AAAA,MACL,WAAW;AAAA,QACV,UAAU,KAAK,aAAa,YAAY;AAAA,QACxC;AAAA,QACA,MAAAA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AACD;","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 { 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discord-embed-router",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "A vite inspired router for discord.js embeds and interactions",
5
5
  "files": [
6
6
  "dist"