discord-embed-router 0.1.0 → 0.2.0

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.js CHANGED
@@ -31,17 +31,26 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  EmbedRouter: () => EmbedRouter,
34
- RouteButtonBuilder: () => RouteButtonBuilder
34
+ RouteButtonBuilder: () => RouteButtonBuilder,
35
+ RouteChannelSelectMenuBuilder: () => RouteChannelSelectMenuBuilder,
36
+ RouteRoleSelectMenuBuilder: () => RouteRoleSelectMenuBuilder,
37
+ RouteStringSelectMenuBuilder: () => RouteStringSelectMenuBuilder,
38
+ RouteStringSelectMenuOptionBuilder: () => RouteStringSelectMenuOptionBuilder,
39
+ RouteUserSelectMenuBuilder: () => RouteUserSelectMenuBuilder
35
40
  });
36
41
  module.exports = __toCommonJS(index_exports);
37
42
 
38
43
  // src/EmbedRouter.ts
39
44
  var import_node_path = __toESM(require("path"));
40
- var import_path_to_regexp2 = require("path-to-regexp");
45
+ var import_node_crypto = require("crypto");
46
+ var import_path_to_regexp3 = require("path-to-regexp");
41
47
 
42
48
  // src/consts.ts
43
49
  var ID_PREFIX = "der";
44
- var BASE_URL = "x://x";
50
+ var BASE_URL = "discord://embed.router";
51
+ var PUA_START = 57344;
52
+ var PUA_END = 63743;
53
+ var PUA_RANGE = PUA_END - PUA_START + 1;
45
54
 
46
55
  // src/helpers/pathToString.ts
47
56
  var import_path_to_regexp = require("path-to-regexp");
@@ -52,36 +61,113 @@ var pathToString = (path2, checkValidity = true) => {
52
61
  return typeof path2 === "string" ? path2 : (0, import_path_to_regexp.stringify)(path2);
53
62
  };
54
63
 
64
+ // src/helpers/decodePath.ts
65
+ var import_path_to_regexp2 = require("path-to-regexp");
66
+ var decodePath = (idPrefix, interaction) => {
67
+ const customId = interaction.customId;
68
+ if (!customId.startsWith(idPrefix)) return false;
69
+ if (interaction.isButton()) {
70
+ return customId.slice(idPrefix.length);
71
+ } else if (interaction.isStringSelectMenu()) {
72
+ if (interaction.values.length === 0) return false;
73
+ return fillParams(customId.slice(idPrefix.length), {
74
+ to: interaction.values[0].split("/").slice(1)
75
+ });
76
+ } else if (interaction.isChannelSelectMenu()) {
77
+ if (interaction.values.length === 0) return false;
78
+ return fillParams(customId.slice(idPrefix.length), {
79
+ channelId: interaction.values[0]
80
+ });
81
+ } else if (interaction.isRoleSelectMenu()) {
82
+ if (interaction.values.length === 0) return false;
83
+ return fillParams(customId.slice(idPrefix.length), {
84
+ roleId: interaction.values[0]
85
+ });
86
+ } else if (interaction.isUserSelectMenu()) {
87
+ if (interaction.values.length === 0) return false;
88
+ return fillParams(customId.slice(idPrefix.length), {
89
+ userId: interaction.values[0]
90
+ });
91
+ }
92
+ return false;
93
+ };
94
+ var fillParams = (path2, params = {}) => {
95
+ const url = new URL(path2, BASE_URL);
96
+ const toPath = (0, import_path_to_regexp2.compile)(url.pathname);
97
+ url.pathname = toPath(params);
98
+ for (const [key, value] of url.searchParams) {
99
+ if (value.startsWith(":") && key.slice(1) in params) {
100
+ const paramValue = params?.[key.slice(1)];
101
+ if (paramValue) {
102
+ url.searchParams.set(
103
+ key,
104
+ Array.isArray(paramValue) ? paramValue.join("/") : paramValue
105
+ );
106
+ } else {
107
+ url.searchParams.delete(key);
108
+ }
109
+ }
110
+ }
111
+ return `${url.pathname}${url.search}`;
112
+ };
113
+
55
114
  // src/EmbedRouter.ts
56
115
  var EmbedRouter = class _EmbedRouter {
57
- static usedIdentifiers = /* @__PURE__ */ new Set();
58
- static generateUniqueIdentifier() {
59
- const PUA_START = 57344;
60
- const PUA_END = 63743;
61
- let char;
62
- do {
63
- const codepoint = PUA_START + Math.floor(Math.random() * (PUA_END - PUA_START + 1));
64
- char = String.fromCodePoint(codepoint);
65
- } while (_EmbedRouter.usedIdentifiers.has(char));
66
- _EmbedRouter.usedIdentifiers.add(char);
67
- return char;
68
- }
116
+ // identifier -> embedRouter
117
+ static usedIdentifiers = /* @__PURE__ */ new Map();
118
+ // Name used to generate prefixes
119
+ name = "";
69
120
  // Prefix for customIds of RouteButtonBuilders
70
121
  idPrefix;
122
+ identifier = "";
71
123
  getIdPrefix() {
72
- return this.idPrefix;
124
+ return `${this.idPrefix}${this.identifier}`;
73
125
  }
74
126
  // All added routes
75
127
  routes = [];
76
128
  /**
77
129
  *
130
+ * @param name the name to give the router. ensures buttons stay connected across restarts
78
131
  * @param idPrefix the prefix for RouteButtonBuilder customIds
79
132
  */
80
- constructor(idPrefix = ID_PREFIX) {
133
+ constructor({
134
+ name = "",
135
+ idPrefix = ID_PREFIX
136
+ } = {}) {
137
+ if (_EmbedRouter.usedIdentifiers.size >= PUA_RANGE) {
138
+ throw new Error(`You can not have more than ${PUA_RANGE} routers`);
139
+ }
81
140
  if (idPrefix.includes("/")) {
82
141
  throw new Error(`Prefix can't contain "/": ${idPrefix}`);
83
142
  }
84
- this.idPrefix = `${idPrefix}${_EmbedRouter.generateUniqueIdentifier()}`;
143
+ this.idPrefix = idPrefix;
144
+ this.name = name;
145
+ this.updateIdentifier();
146
+ }
147
+ updateIdentifier() {
148
+ const hash = (0, import_node_crypto.createHash)("sha256").update(this.name).digest();
149
+ let raw = hash.readUint32BE(0);
150
+ let char;
151
+ const nameCollisions = [];
152
+ while (true) {
153
+ const codepoint = PUA_START + raw++ % PUA_RANGE;
154
+ char = String.fromCodePoint(codepoint);
155
+ const collisionRouter = _EmbedRouter.usedIdentifiers.get(char);
156
+ if (collisionRouter === void 0) break;
157
+ if (this.name.length > 0 && collisionRouter.name.length === 0) {
158
+ collisionRouter.updateIdentifier();
159
+ break;
160
+ }
161
+ nameCollisions.push(collisionRouter);
162
+ }
163
+ _EmbedRouter.usedIdentifiers.set(char, this);
164
+ if (nameCollisions.length > 0 && this.name.length > 0) {
165
+ process.emitWarning(
166
+ `EmbedRouter identifier collision for name "${this.name}" with ${nameCollisions.map((c) => `"${c.name}"`).join(", ")}`,
167
+ "EmbedRouterWarning"
168
+ );
169
+ }
170
+ this.identifier = char;
85
171
  }
86
172
  /**
87
173
  * Registers a path with the router
@@ -89,10 +175,10 @@ var EmbedRouter = class _EmbedRouter {
89
175
  * @param routePath path to match with
90
176
  * @param handler function that generates the message when a path is matched
91
177
  */
92
- on(routePath, handler) {
178
+ get(routePath, handler) {
93
179
  this.routes.push({
94
180
  path: Array.isArray(routePath) ? routePath : [routePath],
95
- matchFunction: (0, import_path_to_regexp2.match)(routePath),
181
+ matchFunction: (0, import_path_to_regexp3.match)(routePath),
96
182
  handler
97
183
  });
98
184
  }
@@ -105,7 +191,7 @@ var EmbedRouter = class _EmbedRouter {
105
191
  use(routePath, embedRouter) {
106
192
  const pathString = pathToString(routePath);
107
193
  for (const route of embedRouter.routes) {
108
- this.on(
194
+ this.get(
109
195
  route.path.map((p) => import_node_path.default.posix.join(pathString, pathToString(p))),
110
196
  route.handler
111
197
  );
@@ -116,12 +202,11 @@ var EmbedRouter = class _EmbedRouter {
116
202
  *
117
203
  * @param interaction interactions from "interactionCreate" (filter for ButtonInteractions)
118
204
  */
119
- async listener(interaction) {
120
- if (!interaction.isButton()) return;
121
- const customId = interaction.customId;
122
- if (!customId.startsWith(this.idPrefix)) return;
123
- const path2 = customId.slice(this.idPrefix.length);
124
- this.dispatch(interaction, path2);
205
+ async listener(interaction, locals) {
206
+ const path2 = decodePath(this.getIdPrefix(), interaction);
207
+ if (!path2)
208
+ throw new Error(`Invalid component found: id ${interaction.customId}`);
209
+ this.dispatch(interaction, path2, locals);
125
210
  }
126
211
  /**
127
212
  * Connect or update an interaction message to a path
@@ -130,16 +215,16 @@ var EmbedRouter = class _EmbedRouter {
130
215
  * @param path path to route the interaction to
131
216
  * @param flags optional discord flags to send with message (only allowed on first reply)
132
217
  */
133
- async dispatch(interaction, path2, flags) {
218
+ async dispatch(interaction, path2, locals, flags) {
134
219
  if (interaction.isAutocomplete())
135
220
  throw new Error("Autocomplete Interactions aren't supported");
136
221
  const resolvedRoute = this.resolve(pathToString(path2, false));
137
222
  if (!resolvedRoute)
138
223
  throw new Error(`No route found for ${pathToString(path2, false)}`);
139
- const routeResponse = resolvedRoute.handler(
140
- interaction,
141
- resolvedRoute.state
142
- );
224
+ const routeResponse = await resolvedRoute.handler(interaction, {
225
+ ...resolvedRoute.state,
226
+ locals
227
+ });
143
228
  if (interaction.replied || interaction.deferred) {
144
229
  if (flags)
145
230
  throw new Error(
@@ -167,19 +252,43 @@ var EmbedRouter = class _EmbedRouter {
167
252
  return {
168
253
  state: {
169
254
  ...result,
170
- searchParams: url.searchParams
255
+ query: url.searchParams,
256
+ embedRouter: this
171
257
  },
172
258
  handler: route.handler
173
259
  };
174
260
  }
175
261
  }
176
- return null;
262
+ return false;
177
263
  }
178
264
  };
179
265
 
180
- // src/RouteButtonBuilder.ts
266
+ // src/componentBuilders/RouteButtonBuilder.ts
181
267
  var import_discord = require("discord.js");
268
+
269
+ // src/helpers/encodePath.ts
270
+ var encodePath = (idPrefix, path2, query) => {
271
+ const url = new URL(pathToString(path2), BASE_URL);
272
+ if (query) {
273
+ for (const [key, value] of new URLSearchParams(query)) {
274
+ url.searchParams.set(key, value);
275
+ }
276
+ }
277
+ return `${idPrefix}${url.pathname}${url.search}`;
278
+ };
279
+
280
+ // src/componentBuilders/RouteButtonBuilder.ts
182
281
  var RouteButtonBuilder = class extends import_discord.ButtonBuilder {
282
+ embedRouter;
283
+ /**
284
+ *
285
+ * @param embedRouter the router you want to route with
286
+ * @param data the data to construct a component out of
287
+ */
288
+ constructor(embedRouter, data) {
289
+ super(data);
290
+ this.embedRouter = embedRouter;
291
+ }
183
292
  /**
184
293
  * Not supported for RouteButtonBuilder
185
294
  *
@@ -190,7 +299,7 @@ var RouteButtonBuilder = class extends import_discord.ButtonBuilder {
190
299
  throw new Error("setURL is not supported on RouteButtonBuilder");
191
300
  }
192
301
  /**
193
- * Not supported for RouteButtonBuilder (setTo uses customId)
302
+ * Not supported for RouteButtonBuilder (use setTo)
194
303
  *
195
304
  * @remarks
196
305
  * @param
@@ -202,18 +311,238 @@ var RouteButtonBuilder = class extends import_discord.ButtonBuilder {
202
311
  * Sets the path to route to when clicked
203
312
  *
204
313
  * @param path the path to route to
205
- * @param idPrefix the prefix to add before the custom_id
314
+ * @param query any query parameters you want to add
315
+ */
316
+ setTo(path2, query) {
317
+ super.setCustomId(encodePath(this.embedRouter.getIdPrefix(), path2, query));
318
+ return this;
319
+ }
320
+ };
321
+
322
+ // src/componentBuilders/RouteStringSelectMenuBuilder.ts
323
+ var import_discord3 = require("discord.js");
324
+
325
+ // src/componentBuilders/RouteStringMenuOptionBuilder.ts
326
+ var import_discord2 = require("discord.js");
327
+ var RouteStringSelectMenuOptionBuilder = class extends import_discord2.StringSelectMenuOptionBuilder {
328
+ /**
329
+ *
330
+ * @param data the data to construct a component out of
331
+ */
332
+ constructor(data) {
333
+ const stringSelectData = data ? {
334
+ ...data,
335
+ value: encodePath("", data.to)
336
+ } : void 0;
337
+ super(stringSelectData);
338
+ }
339
+ /**
340
+ * Not supported for RouteStringSelectMenuOptionBuilder (use setTo)
341
+ *
342
+ * @remarks
343
+ * @param
344
+ */
345
+ setValue() {
346
+ throw new Error(
347
+ "setValue is not supported on RouteStringSelectMenuOptionBuilder"
348
+ );
349
+ }
350
+ /**
351
+ * Sets the path to route to when clicked
352
+ *
353
+ * @param path the path to route to
354
+ * @param query any query parameters you want to add
355
+ */
356
+ setTo(path2, query) {
357
+ super.setValue(encodePath("", path2, query));
358
+ return this;
359
+ }
360
+ };
361
+
362
+ // src/componentBuilders/RouteStringSelectMenuBuilder.ts
363
+ var RouteStringSelectMenuBuilder = class extends import_discord3.StringSelectMenuBuilder {
364
+ embedRouter;
365
+ /**
366
+ *
367
+ * @param embedRouter the router you want to route with
368
+ * @param path the path to redirect to, :to or *to in path will be replaced with the selected user's id
369
+ * @param query any query parameters you want to add, :to will be replaced with the selected user's id
370
+ * @param data the data to construct a component out of
371
+ */
372
+ constructor(embedRouter, path2 = "/*to", query, data) {
373
+ super(data);
374
+ this.embedRouter = embedRouter;
375
+ super.setCustomId(
376
+ encodePath(
377
+ this.embedRouter.getIdPrefix(),
378
+ path2,
379
+ new URLSearchParams(query)
380
+ )
381
+ );
382
+ }
383
+ /**
384
+ * Not supported for RouteStringSelectMenuBuilder (customId set from embedRouter)
385
+ *
386
+ * @remarks
387
+ * @param
206
388
  */
207
- setTo(embedRouter, path2) {
208
- const idPrefix = embedRouter.getIdPrefix();
209
- const url = new URL(pathToString(path2, false), BASE_URL);
210
- const customId = `${idPrefix}${url.pathname}${url.search}`;
211
- super.setCustomId(customId);
389
+ setCustomId() {
390
+ throw new Error(
391
+ "setCustomId is not supported on RouteStringSelectMenuBuilder"
392
+ );
393
+ }
394
+ /**
395
+ * Not supported for RouteStringSelectMenuBuilder (use addTos)
396
+ *
397
+ * @remarks
398
+ * @param
399
+ */
400
+ addOptions() {
401
+ throw new Error(
402
+ "addOptions is not supported on RouteStringSelectMenuBuilder"
403
+ );
404
+ }
405
+ /**
406
+ * Not supported for RouteStringSelectMenuBuilder (use setTos)
407
+ *
408
+ * @remarks
409
+ * @param
410
+ */
411
+ setOptions() {
412
+ throw new Error(
413
+ "setOptions is not supported on RouteStringSelectMenuBuilder"
414
+ );
415
+ }
416
+ /**
417
+ * Adds route select menu options to builder
418
+ *
419
+ * @param tos the list of route select menu options
420
+ */
421
+ addTos(...tos) {
422
+ const resolved = (0, import_discord3.normalizeArray)(tos);
423
+ super.addOptions(
424
+ resolved.map(
425
+ (o) => o instanceof RouteStringSelectMenuOptionBuilder ? o : new RouteStringSelectMenuOptionBuilder(o)
426
+ )
427
+ );
428
+ return this;
429
+ }
430
+ /**
431
+ * Sets route select menu options to builder
432
+ *
433
+ * @param tos the list of route select menu options
434
+ */
435
+ setTos(...tos) {
436
+ const resolved = (0, import_discord3.normalizeArray)(tos);
437
+ super.setOptions(
438
+ resolved.map(
439
+ (o) => o instanceof RouteStringSelectMenuOptionBuilder ? o : new RouteStringSelectMenuOptionBuilder(o)
440
+ )
441
+ );
442
+ return this;
443
+ }
444
+ };
445
+
446
+ // src/componentBuilders/RouteChannelSelectMenuBuilder.ts
447
+ var import_discord4 = require("discord.js");
448
+ var RouteChannelSelectMenuBuilder = class extends import_discord4.ChannelSelectMenuBuilder {
449
+ embedRouter;
450
+ /**
451
+ *
452
+ * @param embedRouter the router you want to route with
453
+ * @param path the path to redirect to, :channelId in path will be replaced with the selected user's id
454
+ * @param query any query parameters you want to add, :channelId will be replaced with the selected user's id
455
+ * @param data the data to construct a component out of
456
+ */
457
+ constructor(embedRouter, path2, query, data) {
458
+ super(data);
459
+ this.embedRouter = embedRouter;
460
+ super.setCustomId(encodePath(this.embedRouter.getIdPrefix(), path2, query));
461
+ }
462
+ /**
463
+ * Not supported for RouteChannelSelectMenuBuilder (customId set from embedRouter)
464
+ *
465
+ * @remarks
466
+ * @param
467
+ */
468
+ setCustomId() {
469
+ throw new Error(
470
+ "setCustomId is not supported on RouteChannelSelectMenuBuilder"
471
+ );
472
+ }
473
+ };
474
+
475
+ // src/componentBuilders/RouteRoleSelectMenuBuilder.ts
476
+ var import_discord5 = require("discord.js");
477
+ var RouteRoleSelectMenuBuilder = class extends import_discord5.RoleSelectMenuBuilder {
478
+ embedRouter;
479
+ /**
480
+ *
481
+ * @param embedRouter the router you want to route with
482
+ * @param path the path to redirect to, :roleId in path will be replaced with the selected user's id
483
+ * @param query any query parameters you want to add, :roleId will be replaced with the selected user's id
484
+ * @param data the data to construct a component out of
485
+ */
486
+ constructor(embedRouter, path2, query, data) {
487
+ super(data);
488
+ this.embedRouter = embedRouter;
489
+ super.setCustomId(encodePath(this.embedRouter.getIdPrefix(), path2, query));
490
+ }
491
+ /**
492
+ * Not supported for RouteRoleSelectMenuBuilder (customId set from embedRouter)
493
+ *
494
+ * @remarks
495
+ * @param
496
+ */
497
+ setCustomId() {
498
+ throw new Error(
499
+ "setCustomId is not supported on RouteRoleSelectMenuBuilder"
500
+ );
501
+ }
502
+ };
503
+
504
+ // src/componentBuilders/RouteUserSelectMenuBuilder.ts
505
+ var import_discord6 = require("discord.js");
506
+ var RouteUserSelectMenuBuilder = class extends import_discord6.UserSelectMenuBuilder {
507
+ embedRouter;
508
+ /**
509
+ *
510
+ * @param embedRouter the router you want to route with
511
+ * @param path the path to redirect to, :userId in path will be replaced with the selected user's id
512
+ * @param query any query parameters you want to add, :userId will be replaced with the selected user's id
513
+ * @param data the data to construct a component out of
514
+ */
515
+ constructor(embedRouter, path2, query, data) {
516
+ super(data);
517
+ this.embedRouter = embedRouter;
518
+ super.setCustomId(
519
+ encodePath(
520
+ this.embedRouter.getIdPrefix(),
521
+ path2,
522
+ new URLSearchParams(query)
523
+ )
524
+ );
525
+ }
526
+ /**
527
+ * Not supported for RouteUserSelectMenuBuilder (customId set from embedRouter)
528
+ *
529
+ * @remarks
530
+ * @param
531
+ */
532
+ setCustomId() {
533
+ throw new Error(
534
+ "setCustomId is not supported on RouteUserSelectMenuBuilder"
535
+ );
212
536
  }
213
537
  };
214
538
  // Annotate the CommonJS export names for ESM import in node:
215
539
  0 && (module.exports = {
216
540
  EmbedRouter,
217
- RouteButtonBuilder
541
+ RouteButtonBuilder,
542
+ RouteChannelSelectMenuBuilder,
543
+ RouteRoleSelectMenuBuilder,
544
+ RouteStringSelectMenuBuilder,
545
+ RouteStringSelectMenuOptionBuilder,
546
+ RouteUserSelectMenuBuilder
218
547
  });
219
548
  //# sourceMappingURL=index.js.map
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/RouteButtonBuilder.ts"],"sourcesContent":["export { EmbedRouter } from \"./EmbedRouter\";\nexport { RouteButtonBuilder } from \"./RouteButtonBuilder\";\n\nexport type * from \"./types/routes\";\n","import path from \"node:path\";\nimport { match, ParamData, Path } from \"path-to-regexp\";\nimport {\n\tCompiledRoute,\n\tResolvedRoute,\n\tRouteHandler,\n\tState,\n} from \"./types/routes\";\nimport { ExtractParams } from \"./types/ExtractParams\";\nimport {\n\tButtonInteraction,\n\tInteraction,\n\tInteractionReplyOptions,\n} from \"discord.js\";\nimport { BASE_URL, ID_PREFIX } from \"./consts\";\nimport { pathToString } from \"./helpers/pathToString\";\n\nexport class EmbedRouter {\n\tprivate static usedIdentifiers = new Set<string>();\n\tprivate static generateUniqueIdentifier(): string {\n\t\tconst PUA_START = 0xe000;\n\t\tconst PUA_END = 0xf8ff;\n\t\tlet char: string;\n\t\tdo {\n\t\t\tconst codepoint =\n\t\t\t\tPUA_START + Math.floor(Math.random() * (PUA_END - PUA_START + 1));\n\t\t\tchar = String.fromCodePoint(codepoint);\n\t\t} while (EmbedRouter.usedIdentifiers.has(char));\n\t\tEmbedRouter.usedIdentifiers.add(char);\n\t\treturn char;\n\t}\n\n\t// Prefix for customIds of RouteButtonBuilders\n\tprivate idPrefix;\n\tgetIdPrefix() {\n\t\treturn this.idPrefix;\n\t}\n\n\t// All added routes\n\tprivate routes: CompiledRoute<ParamData>[] = [];\n\n\t/**\n\t *\n\t * @param idPrefix the prefix for RouteButtonBuilder customIds\n\t */\n\tconstructor(idPrefix = ID_PREFIX) {\n\t\tif (idPrefix.includes(\"/\")) {\n\t\t\tthrow new Error(`Prefix can't contain \"/\": ${idPrefix}`);\n\t\t}\n\t\tthis.idPrefix = `${idPrefix}${EmbedRouter.generateUniqueIdentifier()}`;\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\ton<P extends Path = Path>(\n\t\troutePath: P | P[],\n\t\thandler: RouteHandler<ExtractParams<P>>,\n\t) {\n\t\tthis.routes.push({\n\t\t\tpath: Array.isArray(routePath) ? routePath : [routePath],\n\t\t\tmatchFunction: match(routePath),\n\t\t\thandler: handler as RouteHandler<ParamData>,\n\t\t});\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\tuse<P extends Path = Path>(routePath: P, embedRouter: EmbedRouter) {\n\t\tconst pathString = pathToString(routePath);\n\t\tfor (const route of embedRouter.routes) {\n\t\t\tthis.on(\n\t\t\t\troute.path.map((p) => path.posix.join(pathString, pathToString(p))),\n\t\t\t\troute.handler,\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\tasync listener(interaction: ButtonInteraction) {\n\t\tif (!interaction.isButton()) return;\n\n\t\tconst customId = interaction.customId;\n\t\tif (!customId.startsWith(this.idPrefix)) return;\n\n\t\tconst path = customId.slice(this.idPrefix.length);\n\t\tthis.dispatch(interaction, path);\n\t}\n\n\t/**\n\t * Connect or update an interaction message to a path\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param flags optional discord flags to send with message (only allowed on first reply)\n\t */\n\tasync dispatch<P extends Path = Path>(\n\t\tinteraction: Interaction,\n\t\tpath: P,\n\t\tflags?: InteractionReplyOptions[\"flags\"],\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 resolvedRoute = this.resolve(pathToString(path, false));\n\t\tif (!resolvedRoute)\n\t\t\tthrow new Error(`No route found for ${pathToString(path, false)}`);\n\n\t\tconst routeResponse = resolvedRoute.handler(\n\t\t\tinteraction,\n\t\t\tresolvedRoute.state,\n\t\t);\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\tawait interaction.editReply(routeResponse);\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\tprivate resolve<P extends string>(\n\t\troutePath: P,\n\t): ResolvedRoute<ExtractParams<P>> | null {\n\t\tconst url = new URL(routePath, BASE_URL);\n\t\tfor (const route of this.routes) {\n\t\t\tconst result = route.matchFunction(url.pathname);\n\t\t\tif (result) {\n\t\t\t\treturn {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\t...(result as State<ExtractParams<P>>),\n\t\t\t\t\t\tsearchParams: url.searchParams,\n\t\t\t\t\t},\n\t\t\t\t\thandler: route.handler,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n}\n","export const ID_PREFIX = \"der\";\nexport const BASE_URL = \"x://x\";\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 { ButtonBuilder } from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { BASE_URL } from \"./consts\";\nimport { pathToString } from \"./helpers/pathToString\";\nimport { EmbedRouter } from \"./EmbedRouter\";\n\nexport class RouteButtonBuilder extends ButtonBuilder {\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 (setTo uses customId)\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 idPrefix the prefix to add before the custom_id\n\t */\n\tsetTo<P extends Path>(embedRouter: EmbedRouter, path: P) {\n\t\tconst idPrefix = embedRouter.getIdPrefix();\n\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\tconst customId = `${idPrefix}${url.pathname}${url.search}`;\n\n\t\tsuper.setCustomId(customId);\n\t}\n}\n"],"mappings":"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","names":["import_path_to_regexp","path","path","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/RouteStringMenuOptionBuilder.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/RouteStringMenuOptionBuilder\";\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, Path } from \"path-to-regexp\";\nimport type {\n\tCompiledRoute,\n\tResolvedRoute,\n\tRouteHandler,\n\tState,\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\tprivate static usedIdentifiers = new Map<string, EmbedRouter<unknown>>();\n\n\t// Name used to generate prefixes\n\tprivate name = \"\";\n\t// Prefix for customIds of RouteButtonBuilders\n\tprivate idPrefix: string;\n\tprivate identifier: string = \"\";\n\tpublic getIdPrefix() {\n\t\treturn `${this.idPrefix}${this.identifier}`;\n\t}\n\n\t// All added routes\n\tprivate routes: CompiledRoute<L>[] = [];\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;\n\t\tidPrefix?: string;\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\tprivate 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/**\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<L, ExtractParams<P>>,\n\t) {\n\t\tthis.routes.push({\n\t\t\tpath: Array.isArray(routePath) ? routePath : [routePath],\n\t\t\tmatchFunction: match(routePath),\n\t\t\thandler: handler as RouteHandler<L>,\n\t\t});\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 route of embedRouter.routes) {\n\t\t\tthis.get(\n\t\t\t\troute.path.map((p) => path.posix.join(pathString, pathToString(p))),\n\t\t\t\troute.handler,\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,\n\t) {\n\t\tconst path = decodePath(this.getIdPrefix(), interaction);\n\t\tif (!path)\n\t\t\tthrow new Error(`Invalid component found: id ${interaction.customId}`);\n\n\t\tthis.dispatch(interaction, path, locals);\n\t}\n\n\t/**\n\t * Connect or update an interaction message to a path\n\t *\n\t * @param interaction interaction to connect to\n\t * @param path path to route the interaction to\n\t * @param flags optional discord flags to send with message (only allowed on first reply)\n\t */\n\tpublic async dispatch<P extends Path = Path>(\n\t\tinteraction: Interaction,\n\t\tpath: P,\n\t\tlocals?: L,\n\t\tflags?: InteractionReplyOptions[\"flags\"],\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 resolvedRoute = this.resolve(pathToString(path, false));\n\t\tif (!resolvedRoute)\n\t\t\tthrow new Error(`No route found for ${pathToString(path, false)}`);\n\n\t\tconst routeResponse = await resolvedRoute.handler(interaction, {\n\t\t\t...resolvedRoute.state,\n\t\t\tlocals,\n\t\t});\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\tawait interaction.editReply(routeResponse);\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\tprivate resolve<P extends string>(\n\t\troutePath: P,\n\t): ResolvedRoute<L, ExtractParams<P>> | false {\n\t\tconst url = new URL(routePath, BASE_URL);\n\t\tfor (const route of this.routes) {\n\t\t\tconst result = route.matchFunction(url.pathname);\n\t\t\tif (result) {\n\t\t\t\treturn {\n\t\t\t\t\tstate: {\n\t\t\t\t\t\t...(result as State<L, ExtractParams<P>>),\n\t\t\t\t\t\tquery: url.searchParams,\n\t\t\t\t\t\tembedRouter: this,\n\t\t\t\t\t},\n\t\t\t\t\thandler: route.handler,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n","export const ID_PREFIX = \"der\";\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 } from \"../consts\";\n\nexport const decodePath = (\n\tidPrefix: string,\n\tinteraction: ButtonInteraction | AnySelectMenuInteraction,\n): Path | false => {\n\tconst customId = interaction.customId;\n\tif (!customId.startsWith(idPrefix)) return false;\n\n\tif (interaction.isButton()) {\n\t\treturn customId.slice(idPrefix.length);\n\t} else if (interaction.isStringSelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\t\treturn fillParams(customId.slice(idPrefix.length), {\n\t\t\tto: interaction.values[0]!.split(\"/\").slice(1),\n\t\t});\n\t} else if (interaction.isChannelSelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\t\treturn fillParams(customId.slice(idPrefix.length), {\n\t\t\tchannelId: interaction.values[0],\n\t\t});\n\t} else if (interaction.isRoleSelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\t\treturn fillParams(customId.slice(idPrefix.length), {\n\t\t\troleId: interaction.values[0],\n\t\t});\n\t} else if (interaction.isUserSelectMenu()) {\n\t\tif (interaction.values.length === 0) return false;\n\t\treturn fillParams(customId.slice(idPrefix.length), {\n\t\t\tuserId: interaction.values[0],\n\t\t});\n\t}\n\n\treturn false;\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\";\n\nexport class RouteButtonBuilder<L> extends ButtonBuilder {\n\tprivate 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\">,\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 */\n\tpublic setTo<P extends Path>(\n\t\tpath: P,\n\t\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\n\t): this {\n\t\tsuper.setCustomId(encodePath(this.embedRouter.getIdPrefix(), path, query));\n\n\t\treturn this;\n\t}\n}\n","import { Path } from \"path-to-regexp\";\nimport { BASE_URL } from \"../consts\";\nimport { pathToString } from \"./pathToString\";\n\nexport const encodePath = (\n\tidPrefix: string,\n\tpath: Path,\n\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\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}${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 \"./RouteStringMenuOptionBuilder\";\nimport { EmbedRouter } from \"../EmbedRouter\";\nimport { encodePath } from \"../helpers/encodePath\";\n\nexport class RouteStringSelectMenuBuilder<\n\tL,\n\tP extends Path,\n> extends StringSelectMenuBuilder {\n\tprivate 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\tpath: P | string = \"/*to\",\n\t\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\n\t\tdata?: Partial<StringSelectMenuComponentData | APIStringSelectComponent>,\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\tthis.embedRouter.getIdPrefix(),\n\t\t\t\tpath,\n\t\t\t\tnew URLSearchParams(query),\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","import {\n\tAPISelectMenuOption,\n\tSelectMenuComponentOptionData,\n\tStringSelectMenuOptionBuilder,\n} from \"discord.js\";\nimport { Path } from \"path-to-regexp\";\nimport { encodePath } from \"../helpers/encodePath\";\n\nexport class RouteStringSelectMenuOptionBuilder extends StringSelectMenuOptionBuilder {\n\t/**\n\t *\n\t * @param data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tdata?: Omit<\n\t\t\tSelectMenuComponentOptionData | APISelectMenuOption,\n\t\t\t\"value\"\n\t\t> & { to: string },\n\t) {\n\t\tconst stringSelectData = data\n\t\t\t? {\n\t\t\t\t\t...data,\n\t\t\t\t\tvalue: encodePath(\"\", data.to),\n\t\t\t\t}\n\t\t\t: undefined;\n\t\tsuper(stringSelectData);\n\t}\n\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 */\n\tsetTo<P extends Path>(\n\t\tpath: P,\n\t\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\n\t): this {\n\t\tsuper.setValue(encodePath(\"\", path, query));\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\";\n\nexport class RouteChannelSelectMenuBuilder<\n\tL,\n\tP extends Path,\n> extends ChannelSelectMenuBuilder {\n\tprivate 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, :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 data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tpath: P,\n\t\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\n\t\tdata?: Partial<ChannelSelectMenuComponentData | APIChannelSelectComponent>,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.embedRouter = embedRouter;\n\n\t\tsuper.setCustomId(encodePath(this.embedRouter.getIdPrefix(), path, query));\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","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\";\n\nexport class RouteRoleSelectMenuBuilder<\n\tL,\n\tP extends Path,\n> extends RoleSelectMenuBuilder {\n\tprivate 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, :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 data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tpath: P,\n\t\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\n\t\tdata?: Partial<RoleSelectMenuComponentData | APIRoleSelectComponent>,\n\t) {\n\t\tsuper(data);\n\n\t\tthis.embedRouter = embedRouter;\n\n\t\tsuper.setCustomId(encodePath(this.embedRouter.getIdPrefix(), path, query));\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","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\";\n\nexport class RouteUserSelectMenuBuilder<\n\tL,\n\tP extends Path,\n> extends UserSelectMenuBuilder {\n\tprivate 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, :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 data the data to construct a component out of\n\t */\n\tconstructor(\n\t\tembedRouter: EmbedRouter<L>,\n\t\tpath: P,\n\t\tquery?: ConstructorParameters<typeof URLSearchParams>[0],\n\t\tdata?: Partial<UserSelectMenuComponentData | APIUserSelectComponent>,\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\tthis.embedRouter.getIdPrefix(),\n\t\t\t\tpath,\n\t\t\t\tnew URLSearchParams(query),\n\t\t\t),\n\t\t);\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,uBAAiB;AACjB,yBAA2B;AAC3B,IAAAA,yBAA4B;;;ACFrB,IAAM,YAAY;AAElB,IAAM,WAAW;AAEjB,IAAM,YAAY;AAClB,IAAM,UAAU;AAChB,IAAM,YAAY,UAAU,YAAY;;;ACN/C,4BAAkD;AAE3C,IAAM,eAAe,CAC3BC,OACA,gBAAgB,SACJ;AACZ,MAAI,eAAe;AAClB,eAAO,iCAAUA,iBAAgB,kCAAYA,YAAO,6BAAMA,KAAI,CAAC;AAAA,EAChE;AACA,SAAO,OAAOA,UAAS,WAAWA,YAAO,iCAAUA,KAAI;AACxD;;;ACVA,IAAAC,yBAA8B;AAIvB,IAAM,aAAa,CACzB,UACA,gBACkB;AAClB,QAAM,WAAW,YAAY;AAC7B,MAAI,CAAC,SAAS,WAAW,QAAQ,EAAG,QAAO;AAE3C,MAAI,YAAY,SAAS,GAAG;AAC3B,WAAO,SAAS,MAAM,SAAS,MAAM;AAAA,EACtC,WAAW,YAAY,mBAAmB,GAAG;AAC5C,QAAI,YAAY,OAAO,WAAW,EAAG,QAAO;AAC5C,WAAO,WAAW,SAAS,MAAM,SAAS,MAAM,GAAG;AAAA,MAClD,IAAI,YAAY,OAAO,CAAC,EAAG,MAAM,GAAG,EAAE,MAAM,CAAC;AAAA,IAC9C,CAAC;AAAA,EACF,WAAW,YAAY,oBAAoB,GAAG;AAC7C,QAAI,YAAY,OAAO,WAAW,EAAG,QAAO;AAC5C,WAAO,WAAW,SAAS,MAAM,SAAS,MAAM,GAAG;AAAA,MAClD,WAAW,YAAY,OAAO,CAAC;AAAA,IAChC,CAAC;AAAA,EACF,WAAW,YAAY,iBAAiB,GAAG;AAC1C,QAAI,YAAY,OAAO,WAAW,EAAG,QAAO;AAC5C,WAAO,WAAW,SAAS,MAAM,SAAS,MAAM,GAAG;AAAA,MAClD,QAAQ,YAAY,OAAO,CAAC;AAAA,IAC7B,CAAC;AAAA,EACF,WAAW,YAAY,iBAAiB,GAAG;AAC1C,QAAI,YAAY,OAAO,WAAW,EAAG,QAAO;AAC5C,WAAO,WAAW,SAAS,MAAM,SAAS,MAAM,GAAG;AAAA,MAClD,QAAQ,YAAY,OAAO,CAAC;AAAA,IAC7B,CAAC;AAAA,EACF;AAEA,SAAO;AACR;AAEA,IAAM,aAAa,CAClBC,OACA,SAAqD,CAAC,MAC1C;AACZ,QAAM,MAAM,IAAI,IAAIA,OAAM,QAAQ;AAClC,QAAM,aAAS,gCAAQ,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;;;AHxCO,IAAM,cAAN,MAAM,aAAe;AAAA;AAAA,EAE3B,OAAe,kBAAkB,oBAAI,IAAkC;AAAA;AAAA,EAG/D,OAAO;AAAA;AAAA,EAEP;AAAA,EACA,aAAqB;AAAA,EACtB,cAAc;AACpB,WAAO,GAAG,KAAK,QAAQ,GAAG,KAAK,UAAU;AAAA,EAC1C;AAAA;AAAA,EAGQ,SAA6B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,YAAY;AAAA,IACX,OAAO;AAAA,IACP,WAAW;AAAA,EACZ,IAGI,CAAC,GAAG;AACP,QAAI,aAAY,gBAAgB,QAAQ,WAAW;AAClD,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,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,iBAAiB;AAAA,EACvB;AAAA,EAEQ,mBAAmB;AAE1B,UAAM,WAAO,+BAAW,QAAQ,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO;AAC3D,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,gBAAgB,IAAI,IAAI;AAC5D,UAAI,oBAAoB,OAAW;AAEnC,UAAI,KAAK,KAAK,SAAS,KAAK,gBAAgB,KAAK,WAAW,GAAG;AAE9D,wBAAgB,iBAAiB;AACjC;AAAA,MACD;AAEA,qBAAe,KAAK,eAAe;AAAA,IACpC;AACA,iBAAY,gBAAgB,IAAI,MAAM,IAA4B;AAElE,QAAI,eAAe,SAAS,KAAK,KAAK,KAAK,SAAS,GAAG;AACtD,cAAQ;AAAA,QACP,8CAA8C,KAAK,IAAI,UAAU,eAAe,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QACpH;AAAA,MACD;AAAA,IACD;AACA,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,IACN,WACA,SACC;AACD,SAAK,OAAO,KAAK;AAAA,MAChB,MAAM,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AAAA,MACvD,mBAAe,8BAAM,SAAS;AAAA,MAC9B;AAAA,IACD,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,IAA2B,WAAc,aAA6B;AAC5E,UAAM,aAAa,aAAa,SAAS;AACzC,eAAW,SAAS,YAAY,QAAQ;AACvC,WAAK;AAAA,QACJ,MAAM,KAAK,IAAI,CAAC,MAAM,iBAAAC,QAAK,MAAM,KAAK,YAAY,aAAa,CAAC,CAAC,CAAC;AAAA,QAClE,MAAM;AAAA,MACP;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,SACZ,aACA,QACC;AACD,UAAMA,QAAO,WAAW,KAAK,YAAY,GAAG,WAAW;AACvD,QAAI,CAACA;AACJ,YAAM,IAAI,MAAM,+BAA+B,YAAY,QAAQ,EAAE;AAEtE,SAAK,SAAS,aAAaA,OAAM,MAAM;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,SACZ,aACAA,OACA,QACA,OACC;AACD,QAAI,YAAY,eAAe;AAC9B,YAAM,IAAI,MAAM,4CAA4C;AAG7D,UAAM,gBAAgB,KAAK,QAAQ,aAAaA,OAAM,KAAK,CAAC;AAC5D,QAAI,CAAC;AACJ,YAAM,IAAI,MAAM,sBAAsB,aAAaA,OAAM,KAAK,CAAC,EAAE;AAElE,UAAM,gBAAgB,MAAM,cAAc,QAAQ,aAAa;AAAA,MAC9D,GAAG,cAAc;AAAA,MACjB;AAAA,IACD,CAAC;AAED,QAAI,YAAY,WAAW,YAAY,UAAU;AAChD,UAAI;AACH,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AACD,YAAM,YAAY,UAAU,aAAa;AAAA,IAC1C,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,EAEQ,QACP,WAC6C;AAC7C,UAAM,MAAM,IAAI,IAAI,WAAW,QAAQ;AACvC,eAAW,SAAS,KAAK,QAAQ;AAChC,YAAM,SAAS,MAAM,cAAc,IAAI,QAAQ;AAC/C,UAAI,QAAQ;AACX,eAAO;AAAA,UACN,OAAO;AAAA,YACN,GAAI;AAAA,YACJ,OAAO,IAAI;AAAA,YACX,aAAa;AAAA,UACd;AAAA,UACA,SAAS,MAAM;AAAA,QAChB;AAAA,MACD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;;;AI9MA,qBAAkD;;;ACI3C,IAAM,aAAa,CACzB,UACAC,OACA,UACI;AACJ,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,IAAI,QAAQ,GAAG,IAAI,MAAM;AAC/C;;;ADXO,IAAM,qBAAN,cAAoC,6BAAc;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,YACC,aACA,MACC;AACD,UAAM,IAAI;AAEV,SAAK,cAAc;AAAA,EACpB;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,MACNC,OACA,OACO;AACP,UAAM,YAAY,WAAW,KAAK,YAAY,YAAY,GAAGA,OAAM,KAAK,CAAC;AAEzE,WAAO;AAAA,EACR;AACD;;;AExDA,IAAAC,kBAMO;;;ACNP,IAAAC,kBAIO;AAIA,IAAM,qCAAN,cAAiD,8CAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrF,YACC,MAIC;AACD,UAAM,mBAAmB,OACtB;AAAA,MACA,GAAG;AAAA,MACH,OAAO,WAAW,IAAI,KAAK,EAAE;AAAA,IAC9B,IACC;AACH,UAAM,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,WAAiB;AACzB,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MACCC,OACA,OACO;AACP,UAAM,SAAS,WAAW,IAAIA,OAAM,KAAK,CAAC;AAE1C,WAAO;AAAA,EACR;AACD;;;AD1CO,IAAM,+BAAN,cAGG,wCAAwB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,YACC,aACAC,QAAmB,QACnB,OACA,MACC;AACD,UAAM,IAAI;AAEV,SAAK,cAAc;AAEnB,UAAM;AAAA,MACL;AAAA,QACC,KAAK,YAAY,YAAY;AAAA,QAC7BA;AAAA,QACA,IAAI,gBAAgB,KAAK;AAAA,MAC1B;AAAA,IACD;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,eAAW,gCAAe,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,eAAW,gCAAe,GAAG;AACnC,UAAM;AAAA,MACL,SAAS;AAAA,QAAI,CAAC,MACb,aAAa,qCACV,IACA,IAAI,mCAAmC,CAAC;AAAA,MAC5C;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;;;AE3HA,IAAAC,kBAIO;AAKA,IAAM,gCAAN,cAGG,yCAAyB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,YACC,aACAC,OACA,OACA,MACC;AACD,UAAM,IAAI;AAEV,SAAK,cAAc;AAEnB,UAAM,YAAY,WAAW,KAAK,YAAY,YAAY,GAAGA,OAAM,KAAK,CAAC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;;;AC9CA,IAAAC,kBAIO;AAKA,IAAM,6BAAN,cAGG,sCAAsB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,YACC,aACAC,OACA,OACA,MACC;AACD,UAAM,IAAI;AAEV,SAAK,cAAc;AAEnB,UAAM,YAAY,WAAW,KAAK,YAAY,YAAY,GAAGA,OAAM,KAAK,CAAC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;;;AC9CA,IAAAC,kBAIO;AAKA,IAAM,6BAAN,cAGG,sCAAsB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,YACC,aACAC,OACA,OACA,MACC;AACD,UAAM,IAAI;AAEV,SAAK,cAAc;AAEnB,UAAM;AAAA,MACL;AAAA,QACC,KAAK,YAAY,YAAY;AAAA,QAC7BA;AAAA,QACA,IAAI,gBAAgB,KAAK;AAAA,MAC1B;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,cAAoB;AAC5B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;","names":["import_path_to_regexp","path","import_path_to_regexp","path","path","path","path","import_discord","import_discord","path","path","import_discord","path","import_discord","path","import_discord","path"]}