@seedcord/core 0.3.1 → 0.4.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/{Bus-BvF4VShN.mjs → Bus-BVwmKc-A.mjs} +36 -17
- package/dist/Bus-BVwmKc-A.mjs.map +1 -0
- package/dist/Pluggable-Cf5-WWmW.mjs +280 -0
- package/dist/Pluggable-Cf5-WWmW.mjs.map +1 -0
- package/dist/Pluggable-DFNUIlJM.d.mts +148 -0
- package/dist/{Plugin-D9ykXA5g.mjs → Plugin-C6oMqWf8.mjs} +7 -3
- package/dist/Plugin-C6oMqWf8.mjs.map +1 -0
- package/dist/{Plugin-CQ9IEj5X.d.mts → Plugin-CG9pWbPF.d.mts} +2 -2
- package/dist/{cursor-BANzac53.d.mts → cursor-BcRfmTSo.d.mts} +26 -72
- package/dist/{cursor-CuoA9cRh.mjs → cursor-GBUYz3jk.mjs} +378 -30
- package/dist/cursor-GBUYz3jk.mjs.map +1 -0
- package/dist/{index-rt8rZg4d.d.mts → index-ZzdQafFv.d.mts} +2 -2
- package/dist/index.d.mts +77 -19
- package/dist/index.mjs +186 -19
- package/dist/index.mjs.map +1 -1
- package/dist/internal.index.d.mts +11 -5
- package/dist/internal.index.mjs +8 -455
- package/dist/internal.index.mjs.map +1 -1
- package/dist/node-internal.index.d.mts +6 -133
- package/dist/node-internal.index.mjs +15 -472
- package/dist/node-internal.index.mjs.map +1 -1
- package/dist/node.index.d.mts +2 -0
- package/dist/node.index.mjs +256 -0
- package/dist/node.index.mjs.map +1 -0
- package/dist/{phases-hBxMCD2V.d.mts → phases-F8yvPd60.d.mts} +104 -72
- package/dist/plugin.index.d.mts +1 -1
- package/dist/plugin.index.mjs +1 -1
- package/dist/publishDefault-D826XXDQ.mjs +14 -0
- package/dist/publishDefault-D826XXDQ.mjs.map +1 -0
- package/dist/{slashRouteLeaves-De1SxqnX.mjs → slashRouteLeaves-CbYRwqMY.mjs} +10 -2
- package/dist/slashRouteLeaves-CbYRwqMY.mjs.map +1 -0
- package/dist/{subscribers-wnMyNYZd.mjs → subscribers-CGGQkUfM.mjs} +2 -2
- package/dist/{subscribers-wnMyNYZd.mjs.map → subscribers-CGGQkUfM.mjs.map} +1 -1
- package/package.json +14 -8
- package/dist/Bus-BvF4VShN.mjs.map +0 -1
- package/dist/Plugin-D9ykXA5g.mjs.map +0 -1
- package/dist/cursor-CuoA9cRh.mjs.map +0 -1
- package/dist/slashRouteLeaves-De1SxqnX.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as Commands, r as ContextMenus } from "./subscribers-
|
|
3
|
-
import { C as NotInDm, D as defineEffectGate, E as OnCooldown, F as
|
|
1
|
+
import { T as InteractionRoutes, _ as RowComponent, b as CommandMetadataKey, d as WebhookLog, f as Subscriber, g as BuilderComponent, l as WebhookUrl, t as Bus, u as Subscribe } from "./Bus-BVwmKc-A.mjs";
|
|
2
|
+
import { n as Commands, r as ContextMenus } from "./subscribers-CGGQkUfM.mjs";
|
|
3
|
+
import { A as translateSerializationError, C as NotInDm, D as defineEffectGate, E as OnCooldown, F as checkAckLegality, H as storeComponentRoute, I as sendTarget, K as CustomId, L as SelectMenuKind, M as publishResponse, O as defineGate, P as AckTrace, S as NotAllowed, T as NotOwner, U as storeInteractionRoute, V as selectMenuRouteOf, X as Notice, Y as NoticeCard, a as RequirePermissions, c as hasAll, d as pickNotice, h as runCheck, i as RequireBotPermissions, j as attemptWrite, k as serializeReply, l as missingNames, m as rollbackCommits, n as pageCursor, o as RequireRole, p as markCommits, r as Silence, t as PAGE_MAX, u as presentNames, v as HasDangerousPermissions, w as NotInGuild, x as NeedsAny, y as MissingPermissions, z as contextMenuRouteOf } from "./cursor-GBUYz3jk.mjs";
|
|
4
4
|
import { n as StartupPhase, t as ShutdownPhase } from "./phases-BauKJOTT.mjs";
|
|
5
5
|
import "reflect-metadata";
|
|
6
6
|
import { ActionRowBuilder, ButtonBuilder, TextDisplayBuilder } from "@discordjs/builders";
|
|
@@ -19,8 +19,8 @@ function RegisterCommand(scope, guilds = []) {
|
|
|
19
19
|
existingMeta.scope,
|
|
20
20
|
scope
|
|
21
21
|
]);
|
|
22
|
-
if (scope === "global" && guilds.length > 0) throw new
|
|
23
|
-
if (scope === "guild" && (!Array.isArray(guilds) || guilds.length === 0)) throw new
|
|
22
|
+
if (scope === "global" && guilds.length > 0) throw new SeedcordTypeError(SeedcordErrorCode.DecoratorCommandGlobalWithGuilds);
|
|
23
|
+
if (scope === "guild" && (!Array.isArray(guilds) || guilds.length === 0)) throw new SeedcordTypeError(SeedcordErrorCode.DecoratorCommandGuildWithoutGuilds);
|
|
24
24
|
const meta = scope === "global" ? { scope } : {
|
|
25
25
|
scope,
|
|
26
26
|
guilds
|
|
@@ -235,6 +235,7 @@ var BaseHandler = class {
|
|
|
235
235
|
* @typeParam TSender - The transport's reply sender
|
|
236
236
|
*/
|
|
237
237
|
var RepliableHandler = class extends BaseHandler {
|
|
238
|
+
/** The reply surface for this interaction. Pass the handler to reply from outside its class. */
|
|
238
239
|
sender;
|
|
239
240
|
routeId;
|
|
240
241
|
constructor(event, core, dispatch) {
|
|
@@ -242,10 +243,6 @@ var RepliableHandler = class extends BaseHandler {
|
|
|
242
243
|
this.routeId = dispatch?.routeId ?? this.constructor.name;
|
|
243
244
|
this.sender = this.buildSender(event, core, this.routeId);
|
|
244
245
|
}
|
|
245
|
-
/** @internal The dispatcher's fault boundary replies through the live ack state. */
|
|
246
|
-
getSender() {
|
|
247
|
-
return this.sender;
|
|
248
|
-
}
|
|
249
246
|
/** Send the initial response, exactly once. */
|
|
250
247
|
reply(response, opts) {
|
|
251
248
|
return this.sender.reply(response, opts);
|
|
@@ -272,6 +269,172 @@ var RepliableHandler = class extends BaseHandler {
|
|
|
272
269
|
}
|
|
273
270
|
};
|
|
274
271
|
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region src/reply/BaseReplySender.ts
|
|
274
|
+
/**
|
|
275
|
+
* Tracks acknowledgement state and throws a translated `SeedcordError` on an illegal verb before any
|
|
276
|
+
* transport call. Every verb runs the legality check, calls the transport's wire writer, then updates
|
|
277
|
+
* the state and the ack trace. Each transport binds `TMessage` to its own created-message type and
|
|
278
|
+
* supplies the writers.
|
|
279
|
+
*/
|
|
280
|
+
var BaseReplySender = class {
|
|
281
|
+
routeId;
|
|
282
|
+
telemetry;
|
|
283
|
+
state;
|
|
284
|
+
sent = /* @__PURE__ */ new Set();
|
|
285
|
+
ackedBy;
|
|
286
|
+
constructor(routeId, telemetry, initialState = "unacked") {
|
|
287
|
+
this.routeId = routeId;
|
|
288
|
+
this.telemetry = telemetry;
|
|
289
|
+
this.state = initialState;
|
|
290
|
+
}
|
|
291
|
+
report(method, startedAt, messageId) {
|
|
292
|
+
publishResponse(this.telemetry, {
|
|
293
|
+
routeId: this.routeId,
|
|
294
|
+
method,
|
|
295
|
+
startedAt,
|
|
296
|
+
outcome: "sent",
|
|
297
|
+
messageId
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
async attempt(method, startedAt, write) {
|
|
301
|
+
return await attemptWrite(this.telemetry, this.routeId, method, startedAt, write);
|
|
302
|
+
}
|
|
303
|
+
async reply(response, opts) {
|
|
304
|
+
this.checkLegality("reply");
|
|
305
|
+
const startedAt = performance.now();
|
|
306
|
+
const created = await this.attempt("reply", startedAt, () => this.writeReply(response, opts));
|
|
307
|
+
this.transition("reply", "replied");
|
|
308
|
+
const message = this.remember(this.requireMessage(created, "reply"));
|
|
309
|
+
this.report("reply", startedAt, message.id);
|
|
310
|
+
return message;
|
|
311
|
+
}
|
|
312
|
+
async defer(opts) {
|
|
313
|
+
this.checkLegality("defer");
|
|
314
|
+
const startedAt = performance.now();
|
|
315
|
+
await this.attempt("defer", startedAt, () => this.writeDefer(opts));
|
|
316
|
+
this.transition("defer", "deferred-reply");
|
|
317
|
+
this.report("defer", startedAt, null);
|
|
318
|
+
}
|
|
319
|
+
async deferUpdate() {
|
|
320
|
+
this.checkLegality("deferUpdate");
|
|
321
|
+
const startedAt = performance.now();
|
|
322
|
+
await this.attempt("deferUpdate", startedAt, () => this.writeDeferUpdate());
|
|
323
|
+
this.transition("deferUpdate", "deferred-update");
|
|
324
|
+
this.report("deferUpdate", startedAt, null);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* After a deferUpdate the state stays deferred-update. Calling this again rewrites. The returned message
|
|
328
|
+
* is the source message, editable only through a bare `update` or `edit`. A targeted `edit` or `delete`
|
|
329
|
+
* of it throws the foreign-target error.
|
|
330
|
+
*/
|
|
331
|
+
async update(response) {
|
|
332
|
+
this.checkLegality("update");
|
|
333
|
+
const startedAt = performance.now();
|
|
334
|
+
if (this.state === "deferred-update") {
|
|
335
|
+
const edited = await this.attempt("update", startedAt, () => this.editOriginal(response));
|
|
336
|
+
this.report("update", startedAt, edited.id);
|
|
337
|
+
return edited;
|
|
338
|
+
}
|
|
339
|
+
const created = await this.attempt("update", startedAt, () => this.writeUpdate(response));
|
|
340
|
+
this.transition("update", "replied");
|
|
341
|
+
const message = this.remember(this.requireMessage(created, "update"));
|
|
342
|
+
this.report("update", startedAt, message.id);
|
|
343
|
+
return message;
|
|
344
|
+
}
|
|
345
|
+
async followUp(response, opts) {
|
|
346
|
+
this.checkLegality("followUp");
|
|
347
|
+
const startedAt = performance.now();
|
|
348
|
+
const created = await this.attempt("followUp", startedAt, () => this.writeFollowUp(response, opts));
|
|
349
|
+
const message = this.remember(created);
|
|
350
|
+
this.report("followUp", startedAt, message.id);
|
|
351
|
+
return message;
|
|
352
|
+
}
|
|
353
|
+
async edit(targetOrResponse, maybeResponse) {
|
|
354
|
+
this.checkLegality("edit");
|
|
355
|
+
const startedAt = performance.now();
|
|
356
|
+
if (maybeResponse === void 0) {
|
|
357
|
+
const edited = await this.attempt("edit", startedAt, () => this.editOriginal(targetOrResponse));
|
|
358
|
+
this.report("edit", startedAt, edited.id);
|
|
359
|
+
return edited;
|
|
360
|
+
}
|
|
361
|
+
const target = targetOrResponse;
|
|
362
|
+
if (!this.sent.has(target.id)) throw new SeedcordError(SeedcordErrorCode.ReplyForeignEditTarget, [
|
|
363
|
+
"edit",
|
|
364
|
+
target.id,
|
|
365
|
+
this.routeId
|
|
366
|
+
]);
|
|
367
|
+
const written = await this.attempt("edit", startedAt, () => this.writeEditTarget(target.id, maybeResponse));
|
|
368
|
+
const message = this.remember(written);
|
|
369
|
+
this.report("edit", startedAt, message.id);
|
|
370
|
+
return message;
|
|
371
|
+
}
|
|
372
|
+
async delete(target) {
|
|
373
|
+
this.checkLegality("delete");
|
|
374
|
+
const startedAt = performance.now();
|
|
375
|
+
if (target === void 0) {
|
|
376
|
+
await this.attempt("delete", startedAt, () => this.writeDeleteOriginal());
|
|
377
|
+
this.report("delete", startedAt, null);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (!this.sent.has(target.id)) throw new SeedcordError(SeedcordErrorCode.ReplyForeignEditTarget, [
|
|
381
|
+
"delete",
|
|
382
|
+
target.id,
|
|
383
|
+
this.routeId
|
|
384
|
+
]);
|
|
385
|
+
await this.attempt("delete", startedAt, () => this.writeDeleteTarget(target.id));
|
|
386
|
+
this.sent.delete(target.id);
|
|
387
|
+
this.report("delete", startedAt, null);
|
|
388
|
+
}
|
|
389
|
+
/** Routes to the verb the current ack state permits. Every state has a route, so the illegal-ack throw is unreachable. */
|
|
390
|
+
async send(response, opts) {
|
|
391
|
+
const target = sendTarget(this.state);
|
|
392
|
+
if (target === "reply") return await this.reply(response, opts);
|
|
393
|
+
if (target === "edit") return await this.edit(response);
|
|
394
|
+
return await this.followUp(response, opts);
|
|
395
|
+
}
|
|
396
|
+
/** Must be the initial response. */
|
|
397
|
+
async showModal(modal) {
|
|
398
|
+
this.checkLegality("showModal");
|
|
399
|
+
this.guardModalSource();
|
|
400
|
+
let data;
|
|
401
|
+
try {
|
|
402
|
+
data = modal.toJSON();
|
|
403
|
+
} catch (error) {
|
|
404
|
+
const name = modal.constructor?.name;
|
|
405
|
+
throw translateSerializationError(error, !name || name === "Object" ? "modal" : name, 0, this.routeId);
|
|
406
|
+
}
|
|
407
|
+
const startedAt = performance.now();
|
|
408
|
+
await this.attempt("showModal", startedAt, () => this.writeModal(data));
|
|
409
|
+
this.transition("showModal", "replied");
|
|
410
|
+
this.report("showModal", startedAt, null);
|
|
411
|
+
}
|
|
412
|
+
serialize(response) {
|
|
413
|
+
return serializeReply(response, this.routeId);
|
|
414
|
+
}
|
|
415
|
+
remember(created) {
|
|
416
|
+
this.sent.add(created.id);
|
|
417
|
+
return created;
|
|
418
|
+
}
|
|
419
|
+
requireMessage(created, method) {
|
|
420
|
+
if (!created) throw new SeedcordError(SeedcordErrorCode.ReplyCallbackMissingMessage, [method, this.routeId]);
|
|
421
|
+
return created;
|
|
422
|
+
}
|
|
423
|
+
async editOriginal(response) {
|
|
424
|
+
const edited = await this.writeEditOriginal(response);
|
|
425
|
+
if (this.state !== "deferred-update") this.remember(edited);
|
|
426
|
+
return edited;
|
|
427
|
+
}
|
|
428
|
+
checkLegality(method) {
|
|
429
|
+
checkAckLegality(method, this.state, this.routeId, this.ackedBy);
|
|
430
|
+
}
|
|
431
|
+
transition(method, state) {
|
|
432
|
+
this.state = state;
|
|
433
|
+
this.ackedBy = new AckTrace(method);
|
|
434
|
+
}
|
|
435
|
+
guardModalSource() {}
|
|
436
|
+
};
|
|
437
|
+
|
|
275
438
|
//#endregion
|
|
276
439
|
//#region src/stops/Fault.ts
|
|
277
440
|
/**
|
|
@@ -314,8 +477,12 @@ var Fault = class extends Notice {
|
|
|
314
477
|
|
|
315
478
|
//#endregion
|
|
316
479
|
//#region src/gates/combinators.ts
|
|
480
|
+
const ALREADY_JOINED = / [&|] /;
|
|
481
|
+
function joinNames(gates, separator) {
|
|
482
|
+
return gates.map((gate) => ALREADY_JOINED.test(gate.name) ? `(${gate.name})` : gate.name).join(separator);
|
|
483
|
+
}
|
|
317
484
|
function and(...gates) {
|
|
318
|
-
return defineGate(gates
|
|
485
|
+
return defineGate(joinNames(gates, " & "), async (ctx) => {
|
|
319
486
|
for (const gate of gates) await runCheck(gate, ctx);
|
|
320
487
|
});
|
|
321
488
|
}
|
|
@@ -326,7 +493,7 @@ function or(...args) {
|
|
|
326
493
|
const last = args.at(-1);
|
|
327
494
|
const options = last !== void 0 && isOrOptions(last) ? last : void 0;
|
|
328
495
|
const gates = options ? args.slice(0, -1) : args;
|
|
329
|
-
return defineGate(gates
|
|
496
|
+
return defineGate(joinNames(gates, " | "), async (ctx) => {
|
|
330
497
|
const summaries = [];
|
|
331
498
|
let everyArmHasSummary = true;
|
|
332
499
|
for (const gate of gates) {
|
|
@@ -660,7 +827,7 @@ var ResolvedEmoji = class {
|
|
|
660
827
|
function paginate(items, page, perPage) {
|
|
661
828
|
if (!Number.isSafeInteger(perPage) || perPage <= 0) throw new SeedcordRangeError(SeedcordErrorCode.PaginationInvalidPerPage, [perPage]);
|
|
662
829
|
const totalPages = Math.max(1, Math.ceil(items.length / perPage));
|
|
663
|
-
const clamped = Math.min(Math.max(Math.trunc(page), 0), totalPages - 1);
|
|
830
|
+
const clamped = Math.min(Math.max(Number.isNaN(page) ? 0 : Math.trunc(page), 0), totalPages - 1);
|
|
664
831
|
const start = clamped * perPage;
|
|
665
832
|
return {
|
|
666
833
|
items: items.slice(start, start + perPage),
|
|
@@ -812,8 +979,8 @@ var PaginatorBase = class {
|
|
|
812
979
|
this.cursor = pageCursor(config.prefix);
|
|
813
980
|
this.config = config;
|
|
814
981
|
}
|
|
815
|
-
/**
|
|
816
|
-
async
|
|
982
|
+
/** Build one page as a {@link ReplyResponse}. Each transport wraps this in a `page()` taking its handler. */
|
|
983
|
+
async buildPage(ctx, n) {
|
|
817
984
|
const view = await this.config.source.page(ctx, n);
|
|
818
985
|
return renderPage(view, this.cursor, this.config);
|
|
819
986
|
}
|
|
@@ -835,7 +1002,7 @@ function perPageOf(opts) {
|
|
|
835
1002
|
* @typeParam Item - The item type, inferred from the loader's return.
|
|
836
1003
|
* @typeParam Ctx - The transport's page context. Each transport exports a subclass that fixes it.
|
|
837
1004
|
*/
|
|
838
|
-
var
|
|
1005
|
+
var ArraySourceBase = class {
|
|
839
1006
|
load;
|
|
840
1007
|
perPage;
|
|
841
1008
|
constructor(load, opts) {
|
|
@@ -855,7 +1022,7 @@ var ArraySource = class {
|
|
|
855
1022
|
* @typeParam Item - The item type, inferred from the fetcher's slice.
|
|
856
1023
|
* @typeParam Ctx - The transport's page context. Each transport exports a subclass that fixes it.
|
|
857
1024
|
*/
|
|
858
|
-
var
|
|
1025
|
+
var CursorSourceBase = class {
|
|
859
1026
|
fetch;
|
|
860
1027
|
perPage;
|
|
861
1028
|
constructor(fetch, opts) {
|
|
@@ -863,7 +1030,7 @@ var CursorSource = class {
|
|
|
863
1030
|
this.perPage = perPageOf(opts);
|
|
864
1031
|
}
|
|
865
1032
|
async page(ctx, n) {
|
|
866
|
-
const page = Math.max(0, Math.trunc(n));
|
|
1033
|
+
const page = Number.isFinite(n) ? Math.max(0, Math.trunc(n)) : 0;
|
|
867
1034
|
const { items, hasNext } = await this.fetch(ctx, page, this.perPage);
|
|
868
1035
|
return {
|
|
869
1036
|
items: [...items],
|
|
@@ -878,8 +1045,8 @@ var CursorSource = class {
|
|
|
878
1045
|
//#endregion
|
|
879
1046
|
//#region src/index.ts
|
|
880
1047
|
/** Package version */
|
|
881
|
-
const version = "0.
|
|
1048
|
+
const version = "0.4.0";
|
|
882
1049
|
|
|
883
1050
|
//#endregion
|
|
884
|
-
export {
|
|
1051
|
+
export { ArraySourceBase, AutocompleteRoute, BaseHandler, BaseReplySender, BuilderComponent, Bus, ButtonRoute, Commands, ContextMenus, Cooldown, CursorSourceBase, CustomId, DispatchContext, DmOnly, Fault, GuildOnly, MessageContextMenuRoute, ModalRoute, Notice, OwnerOnly, PaginatorBase, RegisterCommand, RepliableHandler, RequireBotPermissions, RequirePermissions, RequireRole, ResolvedEmoji, RowComponent, SelectMenuKind, SelectMenuRoute, ShutdownPhase, Silence, SlashRoute, StartupPhase, Subscribe, Subscriber, UserContextMenuRoute, WebhookLog, WebhookUrl, and, assertPermissions, defineEffectGate, defineGate, mergeRoles, or, paginate, version };
|
|
885
1052
|
//# sourceMappingURL=index.mjs.map
|