@seedcord/http 0.1.0-next.3 → 0.2.0-next.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.
@@ -1,7 +1,6 @@
1
1
  import { SelectMenuKind, SubscriptionKey } from "@seedcord/core";
2
2
  import { ApplicationCommandType } from "discord-api-types/v10";
3
3
  import { EventFrequency } from "@seedcord/types";
4
-
5
4
  //#region src/manifest/RouteManifest.d.ts
6
5
  /** The command kinds a manifest row registers, the wire enum's other members have no handler base. */
7
6
  type RegistrableCommandType = ApplicationCommandType.ChatInput | ApplicationCommandType.User | ApplicationCommandType.Message;
@@ -62,4 +61,4 @@ interface RouteManifest {
62
61
  }
63
62
  //#endregion
64
63
  export { RouteManifest as t };
65
- //# sourceMappingURL=RouteManifest-DE-HCMwd.d.mts.map
64
+ //# sourceMappingURL=RouteManifest-4jc-Lpnm.d.mts.map
@@ -1,12 +1,12 @@
1
- import { t as RouteManifest } from "./RouteManifest-DE-HCMwd.mjs";
1
+ import { t as RouteManifest } from "./RouteManifest-4jc-Lpnm.mjs";
2
+ import "reflect-metadata";
2
3
  import { REST } from "@discordjs/rest";
3
4
  import { ArraySource, AutocompleteOptions, BaseHandler, Bus, ContextMenuKind, CoreBase, CursorSource, DispatchContext, Gate, GateContextBase, GuildPermissionsContext, PaginatorBase, PaginatorConfig, RepliableHandler, RequiredOf, SelectMenuKind, SlashOptionRegistry, Subscriber, SubscriptionKey, WebhookLog } from "@seedcord/core";
4
5
  import { AnyCustomId, AutocompletableNames, BaseReplySender, ChoiceValueOf, EntryFor, FocusedField, GateFitsWith, HasComponentDefs, InteractionRoutes, MatchArms, ModalLike, PageCursor, SingleParams, SlashOptions } from "@seedcord/core/internal";
5
6
  import { APIApplicationCommandAutocompleteInteraction, APIApplicationCommandOptionChoice, APIAttachment, APIChatInputApplicationCommandInteraction, APIContextMenuInteraction, APIInteraction, APIInteractionDataResolvedChannelBase, APIInteractionDataResolvedGuildMember, APIInteractionGuildMember, APIMessage, APIMessageApplicationCommandInteraction, APIMessageChannelSelectInteractionData, APIMessageComponentButtonInteraction, APIMessageComponentEmoji, APIMessageComponentInteraction, APIMessageComponentSelectMenuInteraction, APIMessageMentionableSelectInteractionData, APIMessageRoleSelectInteractionData, APIMessageStringSelectInteractionData, APIMessageUserSelectInteractionData, APIModalInteractionResponseCallbackData, APIModalSubmitInteraction, APIRole, APIThreadChannel, APIUser, APIUserApplicationCommandInteraction, ApplicationCommandType, ChannelType, ThreadChannelType } from "discord-api-types/v10";
6
7
  import { API } from "@discordjs/core/http-only";
7
- import { Config, DeferOpts, EmojiMap, HealthCheckOption, ReplyResponse, SendOpts } from "@seedcord/types";
8
+ import { Config, DeferOpts, EmojiMap, ReplyResponse, SendOpts } from "@seedcord/types";
8
9
  import { NonEmptyTuple, Promisable } from "type-fest";
9
-
10
10
  //#region src/subscriptions.d.ts
11
11
  declare module '@seedcord/core/internal' {
12
12
  interface DefaultSubscriptions {
@@ -19,15 +19,16 @@ declare module '@seedcord/core/internal' {
19
19
  //#endregion
20
20
  //#region src/interfaces/Config.d.ts
21
21
  /**
22
- * Config for a long-running node server. Pass to `new Seedcord(config).start(port)`.
22
+ * Config for a long-running node server. Pass to `new Seedcord(config).start()`.
23
23
  */
24
24
  interface HttpServerConfig extends Config {
25
25
  runtime?: 'server';
26
26
  /**
27
- * The health-check server. `false` disables it, `true` or omit for the defaults, an object
28
- * configures it.
27
+ * Port the interactions server uses.
28
+ *
29
+ * @defaultValue `3000`
29
30
  */
30
- healthCheck?: HealthCheckOption;
31
+ port?: number;
31
32
  }
32
33
  /**
33
34
  * Config for a bundled isolate deployment. `seedcord build` generates a worker entry that calls
@@ -35,7 +36,7 @@ interface HttpServerConfig extends Config {
35
36
  */
36
37
  interface HttpEdgeConfig extends Config {
37
38
  runtime: 'edge';
38
- healthCheck?: never;
39
+ port?: never;
39
40
  }
40
41
  /**
41
42
  * The http transport's configuration, discriminated on `runtime`.
@@ -86,7 +87,7 @@ declare function createSeedcord(config: HttpConfig, manifest: RouteManifest): (r
86
87
  //#endregion
87
88
  //#region src/inputs/SlashOptions.d.ts
88
89
  type ResolvedChannelOf<Type extends ChannelType> = APIInteractionDataResolvedChannelBase<Type> & (Type extends ThreadChannelType ? Pick<APIThreadChannel, 'parent_id' | 'thread_metadata'> : unknown);
89
- type AnyResolvedChannel = { [Type in ChannelType]: ResolvedChannelOf<Type> }[ChannelType];
90
+ type AnyResolvedChannel = { [Type in ChannelType]: ResolvedChannelOf<Type>; }[ChannelType];
90
91
  interface HttpLens {
91
92
  user: APIUser;
92
93
  member: APIInteractionDataResolvedGuildMember;
@@ -117,7 +118,7 @@ interface ResolvedEmoji extends APIMessageComponentEmoji {
117
118
  toString(): string;
118
119
  }
119
120
  /** The global {@link Emojis} accessor type. */
120
- type InjectedEmojiMap = { [K in keyof EmojiMap]: ResolvedEmoji };
121
+ type InjectedEmojiMap = { [K in keyof EmojiMap]: ResolvedEmoji; };
121
122
  /**
122
123
  * The bot's resolved emojis, keyed by {@link EmojiMap}. Filled by {@link EmojiInjector} during startup.
123
124
  * A read before that throws.
@@ -140,7 +141,7 @@ type SentMessage = APIMessage;
140
141
  declare class ReplySender extends BaseReplySender<SentMessage> {
141
142
  private readonly ref;
142
143
  private readonly rest;
143
- constructor(ref: InteractionRef, rest: REST, routeId: string, bus?: Bus);
144
+ constructor(ref: InteractionRef, rest: REST, routeId: string, bus: Bus);
144
145
  protected writeReply(response: ReplyResponse | string, opts?: SendOpts): Promise<SentMessage | undefined>;
145
146
  protected writeDefer(opts?: DeferOpts): Promise<void>;
146
147
  protected writeDeferUpdate(): Promise<void>;
@@ -171,7 +172,7 @@ type Repliables = Exclude<ValidInteractionTypes, APIApplicationCommandAutocomple
171
172
  *
172
173
  * @typeParam Event - The repliable interaction type this handler processes
173
174
  */
174
- declare abstract class RepliableHandler$1<Event extends Repliables> extends RepliableHandler<Event, Core, SentMessage, ReplySender> {
175
+ declare abstract class RepliableHandler$1<Event extends Repliables> extends RepliableHandler<Event, Core, SentMessage, never, ReplySender> {
175
176
  /** @internal */
176
177
  getEvent(): Event;
177
178
  protected buildSender(event: Event, core: Core, routeId: string): ReplySender;
@@ -203,7 +204,7 @@ declare abstract class InteractionHandler<Event extends Repliables> extends Repl
203
204
  }
204
205
  //#endregion
205
206
  //#region src/handlers/interaction/SlashHandler.d.ts
206
- type SlashMatchArms<Route extends keyof SlashOptionRegistry, Ret> = { [Key in Route]: (options: SlashOptions$1<Key>) => Promisable<Ret> };
207
+ type SlashMatchArms<Route extends keyof SlashOptionRegistry, Ret> = { [Key in Route]: (options: SlashOptions$1<Key>) => Promisable<Ret>; };
207
208
  /**
208
209
  * Base class for a chat-input (slash) command handler on the HTTP transport.
209
210
  *
@@ -263,7 +264,7 @@ declare abstract class ContextMenuHandler<Kind extends ContextMenuKind> extends
263
264
  }
264
265
  //#endregion
265
266
  //#region src/handlers/interaction/AutocompleteHandler.d.ts
266
- type FocusedArms<Route extends keyof SlashOptionRegistry, Ret> = { [Name in AutocompletableNames<Route>]: (value: string, respond: (choices: readonly APIApplicationCommandOptionChoice<ChoiceValueOf<EntryFor<Route, Name>>>[]) => Promise<void>) => Promisable<Ret> };
267
+ type FocusedArms<Route extends keyof SlashOptionRegistry, Ret> = { [Name in AutocompletableNames<Route>]: (value: string, respond: (choices: readonly APIApplicationCommandOptionChoice<ChoiceValueOf<EntryFor<Route, Name>>>[]) => Promise<void>) => Promisable<Ret>; };
267
268
  /**
268
269
  * Base class for an autocomplete handler on the HTTP transport.
269
270
  *
@@ -559,7 +560,7 @@ interface Ungateable {
559
560
  type ProvidedContext<TCtor extends AnyHandlerCtor> = InstanceType<TCtor> extends RepliableHandler$1<infer Event> ? InteractionGateContext<Event> : Ungateable;
560
561
  type SelectData<Repliable> = Repliable extends APIMessageComponentSelectMenuInteraction ? Repliable['data'] : never;
561
562
  type KindName<Ctx> = Ctx extends Ungateable ? 'autocomplete' : Ctx extends GuildPermissionsContext ? 'gateway (guild permissions)' : Ctx extends InteractionGateContext<infer Repliable> ? Repliable extends APIChatInputApplicationCommandInteraction ? 'Slash' : Repliable extends APIMessageApplicationCommandInteraction ? 'MessageMenu' : Repliable extends APIUserApplicationCommandInteraction ? 'UserMenu' : SelectData<Repliable> extends APIMessageStringSelectInteractionData ? 'StringSelect' : SelectData<Repliable> extends APIMessageUserSelectInteractionData ? 'UserSelect' : SelectData<Repliable> extends APIMessageRoleSelectInteractionData ? 'RoleSelect' : SelectData<Repliable> extends APIMessageChannelSelectInteractionData ? 'ChannelSelect' : SelectData<Repliable> extends APIMessageMentionableSelectInteractionData ? 'MentionableSelect' : Repliable extends APIMessageComponentButtonInteraction ? 'Button' : Repliable extends APIModalSubmitInteraction ? 'Modal' : 'an interaction' : 'an agnostic';
562
- type FitAll<TCtor extends AnyHandlerCtor, Gates extends readonly Gate<GateContextBase>[]> = { [Index in keyof Gates]: GateFitsWith<ProvidedContext<TCtor>, KindName<ProvidedContext<TCtor>>, Gates[Index], KindName<RequiredOf<Gates[Index]>>> };
563
+ type FitAll<TCtor extends AnyHandlerCtor, Gates extends readonly Gate<GateContextBase>[]> = { [Index in keyof Gates]: GateFitsWith<ProvidedContext<TCtor>, KindName<ProvidedContext<TCtor>>, Gates[Index], KindName<RequiredOf<Gates[Index]>>>; };
563
564
  //#endregion
564
565
  //#region src/gates/Gated.d.ts
565
566
  /**
@@ -601,4 +602,4 @@ declare function Gated<const Gates extends NonEmptyTuple<Gate<GateContextBase>>>
601
602
  declare const version: string;
602
603
  //#endregion
603
604
  export { createSeedcord as C, HttpEdgeConfig as D, HttpConfig as E, HttpServerConfig as O, SlashOptions$1 as S, Core as T, InteractionHandler as _, CursorSource$1 as a, InjectedEmojiMap as b, Subscriber$1 as c, SelectMenuHandler as d, ButtonHandler as f, SlashHandler as g, ContextMenuHandler as h, ArraySource$1 as i, WebhookLog$1 as l, AutocompleteHandler as m, Gated as n, Paginator as o, ComponentHandler as p, InteractionGateContext as r, PageContext as s, version as t, ModalHandler as u, RepliableHandler$1 as v, EngineContext as w, ResolvedEmoji as x, Emojis as y };
604
- //# sourceMappingURL=edge.index-atnWgXP-.d.mts.map
605
+ //# sourceMappingURL=edge.index-CrVektFx.d.mts.map
@@ -1,9 +1,9 @@
1
- import { n as __reExport, t as __exportAll } from "./rolldown-runtime-BUUfjzRC.mjs";
1
+ import "reflect-metadata";
2
2
  import { SeedcordError, validateDiscordToken } from "@seedcord/errors/internal";
3
3
  import { Converters, Envapter } from "envapt";
4
4
  import { DiscordAPIError, REST } from "@discordjs/rest";
5
5
  import { ArraySource, BaseHandler, Bus, CursorSource, DispatchContext, Fault, Notice, PaginatorBase, RepliableHandler, Silence, Subscriber, WebhookLog } from "@seedcord/core";
6
- import { BaseReplySender, FaultThrottle, GatedMetadataKey, PublishDefault, accessorStore, asError, clearStore, decodeComponentRoute, deferFlags, dispatchedPayload, guardedAccessor, isEmojiTuple, outcomeFor, prefixOf, queuedMsFor, reportedWrite, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
6
+ import { BaseReplySender, FaultThrottle, GatedMetadataKey, PublishDefault, accessorStore, asError, clearStore, decodeComponentRoute, deferFlags, guardedAccessor, isEmojiTuple, outcomeFor, prefixOf, queuedMsFor, reportDispatch, reportedWrite, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
7
7
  import { Logger, paint } from "@seedcord/logger";
8
8
  import { MemoryRateLimiter } from "@seedcord/rate-limiter";
9
9
  import { ApplicationCommandOptionType, ApplicationCommandType, ComponentType, InteractionResponseType, InteractionType, MessageFlags, RESTJSONErrorCodes, Routes } from "discord-api-types/v10";
@@ -20,11 +20,12 @@ function wireAllowedMentions(mentions) {
20
20
  };
21
21
  }
22
22
  function wireAttachments(files) {
23
- if (!files?.some((file) => file.description)) return null;
23
+ if (!files?.some((file) => file.description ?? file.title)) return null;
24
24
  return files.map((file, index) => ({
25
25
  id: index,
26
- ...file.name && { filename: file.name },
27
- ...file.description && { description: file.description }
26
+ filename: file.name,
27
+ ...file.description && { description: file.description },
28
+ ...file.title && { title: file.title }
28
29
  }));
29
30
  }
30
31
  function callbackData(reply, flags) {
@@ -44,7 +45,7 @@ var ReplySender = class extends BaseReplySender {
44
45
  ref;
45
46
  rest;
46
47
  constructor(ref, rest, routeId, bus) {
47
- super(routeId, "unacked", bus && {
48
+ super(routeId, {
48
49
  bus,
49
50
  interactionId: ref.id
50
51
  });
@@ -109,9 +110,9 @@ var ReplySender = class extends BaseReplySender {
109
110
  });
110
111
  }
111
112
  rawFiles(files) {
112
- return files.map((file, index) => ({
113
- name: file.name ?? `file-${index}`,
114
- data: file.attachment
113
+ return files.map((file) => ({
114
+ name: file.name,
115
+ data: file.data
115
116
  }));
116
117
  }
117
118
  createdMessage(result) {
@@ -148,11 +149,12 @@ var RepliableHandler$1 = class extends RepliableHandler {
148
149
  return this.event;
149
150
  }
150
151
  buildSender(event, core, routeId) {
151
- return new ReplySender({
152
+ const ref = {
152
153
  application_id: event.application_id,
153
154
  id: event.id,
154
155
  token: event.token
155
- }, core.rest, routeId, core.bus);
156
+ };
157
+ return new ReplySender(ref, core.rest, routeId, core.bus);
156
158
  }
157
159
  /**
158
160
  * Typed Discord REST API (`@discordjs/core/http-only`) over `core.rest`, one instance per core.
@@ -311,7 +313,7 @@ function createCore(config, token) {
311
313
  function isHandlerCtor(value) {
312
314
  return typeof value === "function" && value.prototype instanceof BaseHandler;
313
315
  }
314
- const HARMLESS_API_CODES = new Set([
316
+ const HARMLESS_API_CODES = /* @__PURE__ */ new Set([
315
317
  RESTJSONErrorCodes.UnknownInteraction,
316
318
  RESTJSONErrorCodes.InteractionHasAlreadyBeenAcknowledged,
317
319
  RESTJSONErrorCodes.UnknownMessage
@@ -328,10 +330,11 @@ async function sendGuarded(routeId, send) {
328
330
  }
329
331
  }
330
332
  async function respondEmptyChoices(scope) {
331
- await reportedWrite({
333
+ const telemetry = {
332
334
  bus: scope.core.bus,
333
335
  interactionId: scope.payload.id
334
- }, scope.routeId, "respond", () => scope.core.rest.post(Routes.interactionCallback(scope.payload.id, scope.payload.token), { body: {
336
+ };
337
+ await reportedWrite(telemetry, scope.routeId, "respond", () => scope.core.rest.post(Routes.interactionCallback(scope.payload.id, scope.payload.token), { body: {
335
338
  type: InteractionResponseType.ApplicationCommandAutocompleteResult,
336
339
  data: { choices: [] }
337
340
  } }));
@@ -410,7 +413,7 @@ function dispatchReporter(match, payload, core) {
410
413
  const startedAt = performance.now();
411
414
  const queuedMs = queuedMsFor(payload.id);
412
415
  return (outcome) => {
413
- core.bus[PublishDefault]("interactionDispatched", dispatchedPayload({
416
+ reportDispatch(core.bus, {
414
417
  routeId: unhandledRouteId(match),
415
418
  interactionId: payload.id,
416
419
  kind: match.kind,
@@ -418,7 +421,7 @@ function dispatchReporter(match, payload, core) {
418
421
  fallback: match.routeId === null,
419
422
  startedAt,
420
423
  queuedMs
421
- }));
424
+ });
422
425
  };
423
426
  }
424
427
  async function answer(caught, scope, report, outcome = outcomeFor(caught)) {
@@ -453,7 +456,9 @@ async function dispatchInteraction(args) {
453
456
  const report = dispatchReporter(match, payload, core);
454
457
  const ctor = await loadHandlerCtor(match, payload, core, report);
455
458
  if (!ctor) return null;
456
- const dispatch = new DispatchContext(unhandledRouteId(match));
459
+ const routeId = unhandledRouteId(match);
460
+ logger().debug(`Processing ${paint.mint.bold(routeId)} with ${paint.mute(ctor.name)}`);
461
+ const dispatch = new DispatchContext(routeId);
457
462
  let handler;
458
463
  try {
459
464
  handler = new ctor(payload, core, dispatch);
@@ -464,7 +469,7 @@ async function dispatchInteraction(args) {
464
469
  const scope = {
465
470
  core,
466
471
  payload,
467
- routeId: unhandledRouteId(match),
472
+ routeId,
468
473
  sender: handler instanceof RepliableHandler$1 ? handler.getSender() : null
469
474
  };
470
475
  const refusal = await gateRefusal(ctor, match, payload, core);
@@ -914,12 +919,14 @@ const TIMESTAMP_PATTERN = /^\d+$/;
914
919
  var ReplayGuard = class {
915
920
  seen = /* @__PURE__ */ new Map();
916
921
  lastSweep = Date.now();
917
- accepts(signatureHex, timestampHeader) {
922
+ fresh(timestampHeader) {
923
+ if (!TIMESTAMP_PATTERN.test(timestampHeader)) return null;
924
+ const timestampMs = Number(timestampHeader) * MS_PER_SECOND;
925
+ return Math.abs(Date.now() - timestampMs) <= REPLAY_WINDOW_MS ? timestampMs : null;
926
+ }
927
+ unseen(signatureHex, timestampMs) {
918
928
  const now = Date.now();
919
929
  this.maybeSweep(now);
920
- if (!TIMESTAMP_PATTERN.test(timestampHeader)) return false;
921
- const timestampMs = Number(timestampHeader) * MS_PER_SECOND;
922
- if (Math.abs(now - timestampMs) > REPLAY_WINDOW_MS) return false;
923
930
  const rejectUntil = this.seen.get(signatureHex);
924
931
  if (rejectUntil !== void 0 && rejectUntil >= now) return false;
925
932
  this.seen.set(signatureHex, timestampMs + REPLAY_WINDOW_MS);
@@ -947,7 +954,8 @@ function hasInteractionType(payload) {
947
954
  }
948
955
  function buildEngine(core, maps) {
949
956
  if (!Envapter.has("DISCORD_PUBLIC_KEY")) throw new SeedcordError(SeedcordErrorCode.ConfigMissingPublicKey);
950
- const verifier = new Ed25519Verifier(Envapter.getRequired("DISCORD_PUBLIC_KEY", Converters.String));
957
+ const publicKey = Envapter.getRequired("DISCORD_PUBLIC_KEY", Converters.String);
958
+ const verifier = new Ed25519Verifier(publicKey);
951
959
  const replays = new ReplayGuard();
952
960
  const inFlight = /* @__PURE__ */ new Set();
953
961
  const logger = new Logger("Engine", { channel: "bot" });
@@ -971,24 +979,31 @@ function buildEngine(core, maps) {
971
979
  core.bus[PublishDefault]("unhandledInteractionError", { error });
972
980
  }
973
981
  const handle = async (request, ctx) => {
974
- if (request.method !== "POST") return new Response(null, {
982
+ const [response, outcome] = await respond(request, ctx);
983
+ logger.debug(`${request.method} ${outcome} ${paint.amber(String(response.status))}`);
984
+ return response;
985
+ };
986
+ const respond = async (request, ctx) => {
987
+ if (request.method !== "POST") return [new Response(null, {
975
988
  status: METHOD_NOT_ALLOWED,
976
989
  headers: { allow: "POST" }
977
- });
990
+ }), "not-post"];
978
991
  const signature = request.headers.get(SIGNATURE_HEADER);
979
992
  const timestamp = request.headers.get(TIMESTAMP_HEADER);
980
- if (signature === null || timestamp === null) return new Response(null, { status: UNAUTHORIZED });
993
+ if (signature === null || timestamp === null) return [new Response(null, { status: UNAUTHORIZED }), "unsigned"];
994
+ const timestampMs = replays.fresh(timestamp);
995
+ if (timestampMs === null) return [new Response(null, { status: UNAUTHORIZED }), "stale"];
981
996
  const body = new Uint8Array(await request.arrayBuffer());
982
- if (!await verifier.verify(signature, timestamp, body)) return new Response(null, { status: UNAUTHORIZED });
983
- if (!replays.accepts(signature, timestamp)) return new Response(null, { status: UNAUTHORIZED });
997
+ if (!await verifier.verify(signature, timestamp, body)) return [new Response(null, { status: UNAUTHORIZED }), "bad-signature"];
984
998
  let payload;
985
999
  try {
986
1000
  payload = JSON.parse(decoder.decode(body));
987
1001
  } catch {
988
- return new Response(null, { status: BAD_REQUEST });
1002
+ return [new Response(null, { status: BAD_REQUEST }), "bad-body"];
989
1003
  }
990
- if (!hasInteractionType(payload)) return new Response(null, { status: BAD_REQUEST });
991
- if (payload.type === PING) return Response.json({ type: InteractionResponseType.Pong });
1004
+ if (!hasInteractionType(payload)) return [new Response(null, { status: BAD_REQUEST }), "bad-body"];
1005
+ if (payload.type === PING) return [Response.json({ type: InteractionResponseType.Pong }), "ping"];
1006
+ if (!replays.unseen(signature, timestampMs)) return [new Response(null, { status: UNAUTHORIZED }), "replay"];
992
1007
  try {
993
1008
  core.bus[PublishDefault]("anyInteraction", { interaction: payload });
994
1009
  const match = resolve(maps, payload);
@@ -996,7 +1011,7 @@ function buildEngine(core, maps) {
996
1011
  } catch (caught) {
997
1012
  rootFault(caught);
998
1013
  }
999
- return new Response(null, { status: ACCEPTED });
1014
+ return [new Response(null, { status: ACCEPTED }), "dispatched"];
1000
1015
  };
1001
1016
  return {
1002
1017
  handle,
@@ -1020,7 +1035,8 @@ function buildEngine(core, maps) {
1020
1035
  * `SeedcordError` when either is missing or malformed.
1021
1036
  */
1022
1037
  function createSeedcord(config, manifest) {
1023
- const core = createCore(config, validateDiscordToken(Envapter.get("DISCORD_BOT_TOKEN")));
1038
+ const token = validateDiscordToken(Envapter.get("DISCORD_BOT_TOKEN"));
1039
+ const core = createCore(config, token);
1024
1040
  core.bus.registerDefaults();
1025
1041
  registerSubscribers(core.bus, manifest);
1026
1042
  return buildEngine(core, buildRouteMaps(manifest)).handle;
@@ -1466,8 +1482,8 @@ function Gated(...gates) {
1466
1482
  //#endregion
1467
1483
  //#region src/version.ts
1468
1484
  /** Package version */
1469
- const version = "0.1.0-next.3";
1485
+ const version = "0.2.0-next.0";
1470
1486
 
1471
1487
  //#endregion
1472
1488
  export { RepliableHandler$1 as S, createSeedcord as _, Paginator as a, InteractionHandler as b, ModalHandler as c, ComponentHandler as d, ContextMenuHandler as f, fetchApplicationId as g, Emojis as h, CursorSource$1 as i, SelectMenuHandler as l, EmojiInjector as m, Gated as n, Subscriber$1 as o, SlashHandler as p, ArraySource$1 as r, WebhookLog$1 as s, version as t, ButtonHandler as u, buildEngine as v, AutocompleteHandler as x, buildRouteMaps as y };
1473
- //# sourceMappingURL=edge.index-Cv4plNWY.mjs.map
1489
+ //# sourceMappingURL=edge.index-DPLzbHBG.mjs.map