@seedcord/http 0.7.0 → 0.8.1
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/{edge.index-CWUU_d_X.mjs → edge.index-CdX0NeZA.mjs} +127 -47
- package/dist/edge.index-CdX0NeZA.mjs.map +1 -0
- package/dist/{edge.index-LAWTa6NI.d.mts → edge.index-CgLU9PiF.d.mts} +402 -340
- package/dist/edge.index.d.mts +2 -2
- package/dist/edge.index.mjs +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +60 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/dist/edge.index-CWUU_d_X.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import { GatedMetadataKey, PublishDefault, RegisterDefaults, RegisterSubscriber, accessorStore, asError, clearStore, decodeComponentRoute, deferFlags, guardedAccessor, isEmojiTuple, outcomeFor, queuedMsFor, reportDispatch, reportedWrite, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
|
|
2
|
+
import { GatedMetadataKey, MiddlewareRegistry, PublishDefault, RegisterDefaults, RegisterSubscriber, accessorStore, asError, clearStore, decodeComponentRoute, deferFlags, guardedAccessor, interactionMiddleware, isEmojiTuple, outcomeFor, queuedMsFor, reportDispatch, reportedWrite, resultFor, runAfter, runHandlerGates, sendFlags, slowGateMonitor } from "@seedcord/core/internal";
|
|
3
3
|
import { SeedcordError, SeedcordTypeError, applicationIdFromToken, validateDiscordToken } from "@seedcord/errors/internal";
|
|
4
4
|
import { Logger } from "@seedcord/logger";
|
|
5
5
|
import { Converters, Envapter } from "envapt";
|
|
@@ -46,9 +46,10 @@ function callbackData(reply, flags) {
|
|
|
46
46
|
var ReplySender = class extends BaseReplySender {
|
|
47
47
|
ref;
|
|
48
48
|
rest;
|
|
49
|
-
constructor(ref, rest,
|
|
50
|
-
super(
|
|
49
|
+
constructor(ref, rest, dispatch, bus) {
|
|
50
|
+
super({
|
|
51
51
|
bus,
|
|
52
|
+
dispatch,
|
|
52
53
|
interactionId: ref.id
|
|
53
54
|
});
|
|
54
55
|
this.ref = ref;
|
|
@@ -150,13 +151,13 @@ var RepliableHandler$1 = class extends RepliableHandler {
|
|
|
150
151
|
getEvent() {
|
|
151
152
|
return this.event;
|
|
152
153
|
}
|
|
153
|
-
buildSender(event, core,
|
|
154
|
+
buildSender(event, core, dispatch) {
|
|
154
155
|
const ref = {
|
|
155
156
|
application_id: event.application_id,
|
|
156
157
|
id: event.id,
|
|
157
158
|
token: event.token
|
|
158
159
|
};
|
|
159
|
-
return new ReplySender(ref, core.rest,
|
|
160
|
+
return new ReplySender(ref, core.rest, dispatch, core.bus);
|
|
160
161
|
}
|
|
161
162
|
/**
|
|
162
163
|
* Typed Discord REST API (`@discordjs/core/http-only`) over `core.rest`, one instance per core.
|
|
@@ -170,12 +171,13 @@ var RepliableHandler$1 = class extends RepliableHandler {
|
|
|
170
171
|
|
|
171
172
|
//#endregion
|
|
172
173
|
//#region src/gates/context.ts
|
|
173
|
-
function interactionGateContext(payload, core,
|
|
174
|
+
function interactionGateContext(payload, core, dispatch) {
|
|
174
175
|
const member = payload.member ?? null;
|
|
175
176
|
const resolved = member?.user ?? payload.user;
|
|
176
177
|
return {
|
|
177
178
|
kind: "interaction",
|
|
178
179
|
core,
|
|
180
|
+
dispatch,
|
|
179
181
|
interaction: payload,
|
|
180
182
|
user: resolved,
|
|
181
183
|
member,
|
|
@@ -185,7 +187,7 @@ function interactionGateContext(payload, core, routeId) {
|
|
|
185
187
|
memberRoleIds: member?.roles ?? [],
|
|
186
188
|
memberPermissions: member ? BigInt(member.permissions) : null,
|
|
187
189
|
appPermissions: BigInt(payload.app_permissions),
|
|
188
|
-
|
|
190
|
+
declaredRoute: null
|
|
189
191
|
};
|
|
190
192
|
}
|
|
191
193
|
|
|
@@ -200,18 +202,21 @@ function slashRouteOf(data) {
|
|
|
200
202
|
|
|
201
203
|
//#endregion
|
|
202
204
|
//#region src/dispatch/reportFault.ts
|
|
203
|
-
function reportFault(error, uuid,
|
|
205
|
+
function reportFault(error, uuid, dispatch, payload, core) {
|
|
204
206
|
const source = interactionSource(payload);
|
|
207
|
+
const from = {
|
|
208
|
+
uuid,
|
|
209
|
+
dispatchId: dispatch.id,
|
|
210
|
+
origin: dispatch.routeId
|
|
211
|
+
};
|
|
205
212
|
if (error instanceof Notice && source) core.bus[PublishDefault]("handledException", {
|
|
206
213
|
denial: error,
|
|
207
|
-
|
|
208
|
-
routeId,
|
|
214
|
+
...from,
|
|
209
215
|
source
|
|
210
216
|
});
|
|
211
217
|
else core.bus[PublishDefault]("unknownException", {
|
|
212
|
-
|
|
218
|
+
...from,
|
|
213
219
|
error,
|
|
214
|
-
routeId,
|
|
215
220
|
...actors(payload),
|
|
216
221
|
metadata: payload
|
|
217
222
|
});
|
|
@@ -313,44 +318,50 @@ async function sendGuarded(routeId, send) {
|
|
|
313
318
|
async function respondEmptyChoices(scope) {
|
|
314
319
|
const telemetry = {
|
|
315
320
|
bus: scope.core.bus,
|
|
321
|
+
dispatch: scope.dispatch,
|
|
316
322
|
interactionId: scope.payload.id
|
|
317
323
|
};
|
|
318
|
-
await reportedWrite(telemetry,
|
|
324
|
+
await reportedWrite(telemetry, "respond", () => scope.core.rest.post(Routes.interactionCallback(scope.payload.id, scope.payload.token), { body: {
|
|
319
325
|
type: InteractionResponseType.ApplicationCommandAutocompleteResult,
|
|
320
326
|
data: { choices: [] }
|
|
321
327
|
} }));
|
|
322
328
|
}
|
|
323
|
-
function renderContext(
|
|
324
|
-
const
|
|
325
|
-
|
|
329
|
+
function renderContext(scope, uuid) {
|
|
330
|
+
const { dispatch } = scope;
|
|
331
|
+
const developerUsername = scope.core.config.notifications?.developerUsername;
|
|
332
|
+
return developerUsername === void 0 ? {
|
|
333
|
+
uuid,
|
|
334
|
+
dispatch
|
|
335
|
+
} : {
|
|
326
336
|
uuid,
|
|
327
|
-
developerUsername
|
|
337
|
+
developerUsername,
|
|
338
|
+
dispatch
|
|
328
339
|
};
|
|
329
340
|
}
|
|
330
341
|
async function handleNotice(notice, uuid, scope) {
|
|
331
342
|
if (notice.report) {
|
|
332
343
|
logger().error(`${notice.name}: ${paint.mute(uuid)}`, notice);
|
|
333
|
-
reportFault(notice, uuid, scope.
|
|
344
|
+
reportFault(notice, uuid, scope.dispatch, scope.payload, scope.core);
|
|
334
345
|
}
|
|
335
346
|
const { sender } = scope;
|
|
336
347
|
if (!sender) {
|
|
337
348
|
await sendGuarded(scope.routeId, () => respondEmptyChoices(scope));
|
|
338
349
|
return;
|
|
339
350
|
}
|
|
340
|
-
const response = notice.render(renderContext(scope
|
|
351
|
+
const response = notice.render(renderContext(scope, uuid));
|
|
341
352
|
await sendGuarded(scope.routeId, () => sender.send(response, { ephemeral: notice.ephemeral }));
|
|
342
353
|
}
|
|
343
354
|
async function handleRawFault(error, uuid, scope) {
|
|
344
355
|
const { core, sender } = scope;
|
|
345
356
|
if (core.config.errors?.errorStack ?? false) logger().error(paint.mute(uuid), error);
|
|
346
357
|
else logger().error(`${paint.mute(uuid)} | ${error.message}`);
|
|
347
|
-
reportFault(error, uuid, scope.
|
|
358
|
+
reportFault(error, uuid, scope.dispatch, scope.payload, core);
|
|
348
359
|
if (!sender) {
|
|
349
360
|
await sendGuarded(scope.routeId, () => respondEmptyChoices(scope));
|
|
350
361
|
return;
|
|
351
362
|
}
|
|
352
363
|
const Override = core.config.errors?.defaultError;
|
|
353
|
-
const response = (Override ? new Override(uuid) : new Fault()).render(renderContext(
|
|
364
|
+
const response = (Override ? new Override(uuid) : new Fault()).render(renderContext(scope, uuid));
|
|
354
365
|
await sendGuarded(scope.routeId, () => sender.send(response, { ephemeral: true }));
|
|
355
366
|
}
|
|
356
367
|
async function handleFault(caught, scope) {
|
|
@@ -376,30 +387,33 @@ function unhandledRouteId(match) {
|
|
|
376
387
|
const key = match.attemptedKey ?? "";
|
|
377
388
|
return `${match.kind}:${key.length > 0 ? key : "unrouted"}`;
|
|
378
389
|
}
|
|
379
|
-
function freshScope(match, payload, core) {
|
|
390
|
+
function freshScope(match, payload, core, dispatch) {
|
|
380
391
|
const ref = {
|
|
381
392
|
application_id: payload.application_id,
|
|
382
393
|
id: payload.id,
|
|
383
394
|
token: payload.token
|
|
384
395
|
};
|
|
385
|
-
const routeId = unhandledRouteId(match);
|
|
386
396
|
return {
|
|
387
397
|
core,
|
|
388
398
|
payload,
|
|
389
|
-
routeId,
|
|
390
|
-
|
|
399
|
+
routeId: unhandledRouteId(match),
|
|
400
|
+
dispatch,
|
|
401
|
+
sender: match.kind === InteractionKind.Autocomplete ? null : new ReplySender(ref, core.rest, dispatch, core.bus)
|
|
391
402
|
};
|
|
392
403
|
}
|
|
393
|
-
function dispatchReporter(match, payload, core) {
|
|
404
|
+
function dispatchReporter(match, payload, core, dispatchId) {
|
|
394
405
|
const startedAt = performance.now();
|
|
395
406
|
const queuedMs = queuedMsFor(payload.id);
|
|
396
407
|
return (outcome) => {
|
|
397
408
|
reportDispatch(core.bus, {
|
|
409
|
+
dispatchId,
|
|
398
410
|
routeId: unhandledRouteId(match),
|
|
399
411
|
interactionId: payload.id,
|
|
400
412
|
kind: match.kind,
|
|
401
413
|
outcome,
|
|
402
414
|
fallback: match.routeId === null,
|
|
415
|
+
userId: (payload.member?.user ?? payload.user)?.id ?? null,
|
|
416
|
+
guildId: payload.guild_id ?? null,
|
|
403
417
|
startedAt,
|
|
404
418
|
queuedMs
|
|
405
419
|
});
|
|
@@ -412,61 +426,98 @@ async function answer(caught, scope, report, outcome = outcomeFor(caught)) {
|
|
|
412
426
|
report(outcome);
|
|
413
427
|
}
|
|
414
428
|
}
|
|
415
|
-
async function loadHandlerCtor(match, payload, core, report) {
|
|
429
|
+
async function loadHandlerCtor(match, payload, core, dispatch, report) {
|
|
416
430
|
const routeId = unhandledRouteId(match);
|
|
417
431
|
let exported;
|
|
418
432
|
try {
|
|
419
433
|
exported = await match.load();
|
|
420
434
|
} catch (caught) {
|
|
421
435
|
logger().error(`Route ${paint.sky.bold(routeId)} failed to load its handler.`, caught);
|
|
422
|
-
await answer(caught, freshScope(match, payload, core), report, "failed");
|
|
436
|
+
await answer(caught, freshScope(match, payload, core, dispatch), report, "failed");
|
|
423
437
|
return null;
|
|
424
438
|
}
|
|
425
439
|
if (isHandlerCtor(exported)) return exported;
|
|
426
440
|
logger().error(`Route ${paint.sky.bold(routeId)} loaded an export that is not a handler class.`);
|
|
427
|
-
await answer(/* @__PURE__ */ new Error(`route ${routeId} loaded an export that is not a handler class`), freshScope(match, payload, core), report, "failed");
|
|
441
|
+
await answer(/* @__PURE__ */ new Error(`route ${routeId} loaded an export that is not a handler class`), freshScope(match, payload, core, dispatch), report, "failed");
|
|
428
442
|
return null;
|
|
429
443
|
}
|
|
444
|
+
async function runMiddlewares(step, kind, sender) {
|
|
445
|
+
const { args, dispatch, ran } = step;
|
|
446
|
+
for (const Middleware of args.middlewares.chainFor(kind)) {
|
|
447
|
+
const event = args.payload;
|
|
448
|
+
const instance = new Middleware(event, args.core, dispatch, sender);
|
|
449
|
+
ran.push(instance);
|
|
450
|
+
await instance.execute();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async function refusalBeforeHandler(step) {
|
|
454
|
+
const { args, scope } = step;
|
|
455
|
+
const { kind } = args.match;
|
|
456
|
+
if (kind !== InteractionKind.Autocomplete && scope.sender) try {
|
|
457
|
+
await runMiddlewares(step, kind, scope.sender);
|
|
458
|
+
} catch (caught) {
|
|
459
|
+
return { caught };
|
|
460
|
+
}
|
|
461
|
+
return gateRefusal(step);
|
|
462
|
+
}
|
|
430
463
|
async function dispatchInteraction(args) {
|
|
431
464
|
const { match, payload, core } = args;
|
|
432
|
-
const report = dispatchReporter(match, payload, core);
|
|
433
|
-
const Handler = await loadHandlerCtor(match, payload, core, report);
|
|
434
|
-
if (!Handler) return null;
|
|
435
465
|
const routeId = unhandledRouteId(match);
|
|
436
|
-
logger().debug(`Processing ${paint.sky.bold(routeId)} with ${paint.mute(Handler.name)}`);
|
|
437
466
|
const dispatch = new DispatchContext(routeId);
|
|
467
|
+
const report = dispatchReporter(match, payload, core, dispatch.id);
|
|
468
|
+
const Handler = await loadHandlerCtor(match, payload, core, dispatch, report);
|
|
469
|
+
if (!Handler) return null;
|
|
470
|
+
logger().debug(`Processing ${paint.sky.bold(routeId)} with ${paint.mute(Handler.name)}`);
|
|
438
471
|
let handler;
|
|
439
472
|
try {
|
|
440
473
|
handler = new Handler(payload, core, dispatch);
|
|
441
474
|
} catch (caught) {
|
|
442
|
-
await answer(caught, freshScope(match, payload, core), report);
|
|
475
|
+
await answer(caught, freshScope(match, payload, core, dispatch), report);
|
|
443
476
|
return null;
|
|
444
477
|
}
|
|
445
478
|
const scope = {
|
|
446
479
|
core,
|
|
447
480
|
payload,
|
|
448
481
|
routeId,
|
|
482
|
+
dispatch,
|
|
449
483
|
sender: handler instanceof RepliableHandler$1 ? handler.sender : null
|
|
450
484
|
};
|
|
451
|
-
const
|
|
485
|
+
const ran = [];
|
|
486
|
+
const refusal = await refusalBeforeHandler({
|
|
487
|
+
args,
|
|
488
|
+
Handler,
|
|
489
|
+
dispatch,
|
|
490
|
+
scope,
|
|
491
|
+
ran
|
|
492
|
+
});
|
|
452
493
|
if (refusal) {
|
|
453
|
-
|
|
494
|
+
try {
|
|
495
|
+
await answer(refusal.caught, scope, report);
|
|
496
|
+
} finally {
|
|
497
|
+
await runAfter(ran, resultFor(refusal.caught), logger());
|
|
498
|
+
}
|
|
454
499
|
return null;
|
|
455
500
|
}
|
|
456
501
|
return async () => {
|
|
502
|
+
let result = { outcome: "handled" };
|
|
457
503
|
try {
|
|
458
504
|
await handler.execute();
|
|
459
505
|
report("handled");
|
|
460
506
|
} catch (caught) {
|
|
507
|
+
result = resultFor(caught);
|
|
461
508
|
await answer(caught, scope, report);
|
|
509
|
+
} finally {
|
|
510
|
+
await runAfter(ran, result, logger());
|
|
462
511
|
}
|
|
463
512
|
};
|
|
464
513
|
}
|
|
465
|
-
async function gateRefusal(
|
|
466
|
-
|
|
514
|
+
async function gateRefusal(step) {
|
|
515
|
+
const { Handler, dispatch } = step;
|
|
516
|
+
const { match, payload, core } = step.args;
|
|
517
|
+
if (match.kind === InteractionKind.Autocomplete || payload.type === InteractionType.ApplicationCommandAutocomplete) return null;
|
|
467
518
|
const monitor = slowGateMonitor();
|
|
468
519
|
try {
|
|
469
|
-
await runHandlerGates(
|
|
520
|
+
await runHandlerGates(Handler, interactionGateContext(payload, core, dispatch), match.routeId ?? void 0, monitor?.observe);
|
|
470
521
|
return null;
|
|
471
522
|
} catch (caught) {
|
|
472
523
|
return { caught };
|
|
@@ -637,11 +688,11 @@ var AutocompleteHandler = class extends BaseHandler {
|
|
|
637
688
|
}
|
|
638
689
|
/** Send autocomplete suggestions, callback type 8. Prefer {@link match}, which restricts each field's choices to its declared type. */
|
|
639
690
|
async respond(choices) {
|
|
640
|
-
const routeId = this.dispatch?.routeId ?? "autocomplete";
|
|
641
691
|
await reportedWrite({
|
|
642
692
|
bus: this.core.bus,
|
|
693
|
+
dispatch: this.dispatch,
|
|
643
694
|
interactionId: this.event.id
|
|
644
|
-
},
|
|
695
|
+
}, "respond", () => this.core.rest.post(Routes.interactionCallback(this.event.id, this.event.token), { body: {
|
|
645
696
|
type: InteractionResponseType.ApplicationCommandAutocompleteResult,
|
|
646
697
|
data: { choices }
|
|
647
698
|
} }));
|
|
@@ -899,7 +950,7 @@ const decoder = new TextDecoder();
|
|
|
899
950
|
function hasInteractionType(payload) {
|
|
900
951
|
return typeof payload === "object" && payload !== null && "type" in payload && typeof payload.type === "number";
|
|
901
952
|
}
|
|
902
|
-
function buildEngine(core, maps) {
|
|
953
|
+
function buildEngine(core, maps, middlewares) {
|
|
903
954
|
if (!Envapter.has("DISCORD_PUBLIC_KEY")) throw new SeedcordError(SeedcordErrorCode.ConfigMissingEnv, ["DISCORD_PUBLIC_KEY"]);
|
|
904
955
|
const publicKey = Envapter.getRequired("DISCORD_PUBLIC_KEY", Converters.String);
|
|
905
956
|
const verifier = new Ed25519Verifier(publicKey);
|
|
@@ -910,7 +961,8 @@ function buildEngine(core, maps) {
|
|
|
910
961
|
const start = await dispatchInteraction({
|
|
911
962
|
match,
|
|
912
963
|
payload,
|
|
913
|
-
core
|
|
964
|
+
core,
|
|
965
|
+
middlewares
|
|
914
966
|
});
|
|
915
967
|
if (!start) return;
|
|
916
968
|
const work = start().catch(rootFault);
|
|
@@ -990,7 +1042,7 @@ function createSeedcord(config, manifest) {
|
|
|
990
1042
|
const core = createCore(config, token);
|
|
991
1043
|
core.bus[RegisterDefaults]();
|
|
992
1044
|
registerSubscribers(core.bus, manifest);
|
|
993
|
-
return buildEngine(core, buildRouteMaps(manifest)).handle;
|
|
1045
|
+
return buildEngine(core, buildRouteMaps(manifest), new MiddlewareRegistry(interactionMiddleware)).handle;
|
|
994
1046
|
}
|
|
995
1047
|
|
|
996
1048
|
//#endregion
|
|
@@ -1238,6 +1290,34 @@ var EmojiInjector = class {
|
|
|
1238
1290
|
}
|
|
1239
1291
|
};
|
|
1240
1292
|
|
|
1293
|
+
//#endregion
|
|
1294
|
+
//#region src/handlers/interaction/InteractionMiddleware.ts
|
|
1295
|
+
/**
|
|
1296
|
+
* Base class for interaction middleware on the HTTP transport.
|
|
1297
|
+
*
|
|
1298
|
+
* Middleware runs after the dispatcher builds the handler and before the gates, over the handler's own
|
|
1299
|
+
* reply surface. Name the kinds in the generic and list the same ones in `{ kinds }`. Several kinds give
|
|
1300
|
+
* `this.event` a union. Narrow it on `type` and `data.component_type`. A catchall reads every repliable
|
|
1301
|
+
* kind.
|
|
1302
|
+
*
|
|
1303
|
+
* @typeParam Kind - One or more {@link InteractionKind} members. Defaults to every repliable kind.
|
|
1304
|
+
*
|
|
1305
|
+
* @example
|
|
1306
|
+
* ```ts
|
|
1307
|
+
* \@RegisterInteractionMiddleware({ kinds: [InteractionKind.Button] })
|
|
1308
|
+
* class Audit extends InteractionMiddleware<InteractionKind.Button> {
|
|
1309
|
+
* async execute() {
|
|
1310
|
+
* this.logger.info(this.event.data.custom_id);
|
|
1311
|
+
* }
|
|
1312
|
+
* }
|
|
1313
|
+
* ```
|
|
1314
|
+
*/
|
|
1315
|
+
var InteractionMiddleware = class extends RepliableHandler$1 {
|
|
1316
|
+
constructor(event, core, dispatch, sender) {
|
|
1317
|
+
super(event, core, dispatch, sender);
|
|
1318
|
+
}
|
|
1319
|
+
};
|
|
1320
|
+
|
|
1241
1321
|
//#endregion
|
|
1242
1322
|
//#region src/handlers/interaction/SlashHandler.ts
|
|
1243
1323
|
/**
|
|
@@ -1813,8 +1893,8 @@ function Gated(...gates) {
|
|
|
1813
1893
|
|
|
1814
1894
|
//#endregion
|
|
1815
1895
|
//#region src/version.ts
|
|
1816
|
-
const version = "0.
|
|
1896
|
+
const version = "0.8.1";
|
|
1817
1897
|
|
|
1818
1898
|
//#endregion
|
|
1819
|
-
export {
|
|
1820
|
-
//# sourceMappingURL=edge.index-
|
|
1899
|
+
export { ReplySender as A, ModalFields as C, InteractionHandler as D, buildRouteMaps as E, AutocompleteHandler as O, Emojis as S, buildEngine as T, MessageContextMenuHandler as _, Paginator as a, InteractionMiddleware as b, ChannelMenuHandler as c, SelectMenuHandler as d, StringMenuHandler as f, ComponentHandler as g, ButtonHandler as h, CursorSource as i, RepliableHandler$1 as k, MentionableMenuHandler as l, ModalHandler as m, Gated as n, Subscriber$1 as o, UserMenuHandler as p, ArraySource as r, WebhookLog$1 as s, version as t, RoleMenuHandler as u, UserContextMenuHandler as v, createSeedcord as w, EmojiInjector as x, SlashHandler as y };
|
|
1900
|
+
//# sourceMappingURL=edge.index-CdX0NeZA.mjs.map
|