@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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { i as Bus, n as StartupPhase, r as CoreBase, t as ShutdownPhase } from "./phases-F8yvPd60.mjs";
|
|
2
|
+
import { a as PluginCtor, d as Transport, f as TransportAssert, i as PluginArgs, l as Runtime, o as PluginLike, s as ChannelKeyAssert, t as CoreParamAssert, u as RuntimeAssert } from "./Plugin-CG9pWbPF.mjs";
|
|
3
|
+
import { Logger } from "@seedcord/logger";
|
|
4
|
+
import { REST } from "@discordjs/rest";
|
|
5
|
+
import { HostPluginKeys, HostShutdown, HostStartup } from "@seedcord/types/internal";
|
|
6
|
+
import { Config, IRateLimiter } from "@seedcord/types";
|
|
7
|
+
//#region src/node/Lifecycle/LifecycleTypes.d.ts
|
|
8
|
+
interface LifecycleTask {
|
|
9
|
+
name: string;
|
|
10
|
+
task: () => Promise<void>;
|
|
11
|
+
timeout: number;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/node/Lifecycle/CoordinatedLifecycle.d.ts
|
|
15
|
+
declare abstract class CoordinatedLifecycle<TPhase extends number> {
|
|
16
|
+
protected readonly phaseOrder: TPhase[];
|
|
17
|
+
protected readonly phaseEnum: Record<number, string>;
|
|
18
|
+
protected readonly logger: Logger;
|
|
19
|
+
protected readonly tasksMap: Map<TPhase, LifecycleTask[]>;
|
|
20
|
+
protected constructor(loggerName: string, phaseOrder: TPhase[], phaseEnum: Record<number, string>);
|
|
21
|
+
addTask(phase: TPhase, taskName: string, task: () => Promise<void>, timeoutMs: number): void;
|
|
22
|
+
removeTask(phase: TPhase, taskName: string): boolean;
|
|
23
|
+
protected runPhase(phase: TPhase): Promise<void>;
|
|
24
|
+
protected runTaskWithTimeout(phase: TPhase, task: LifecycleTask): Promise<void>;
|
|
25
|
+
protected isAborted(): boolean;
|
|
26
|
+
protected abstract canAddTask(): boolean;
|
|
27
|
+
protected abstract canRemoveTask(): boolean;
|
|
28
|
+
protected abstract getTaskType(): string;
|
|
29
|
+
protected abstract executeTasksInPhase(phase: TPhase, tasks: LifecycleTask[]): Promise<PromiseSettledResult<void>[]>;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/node/Lifecycle/CoordinatedShutdown.d.ts
|
|
33
|
+
declare class CoordinatedShutdown extends CoordinatedLifecycle<ShutdownPhase> {
|
|
34
|
+
private isShuttingDown;
|
|
35
|
+
private hasShutdown;
|
|
36
|
+
private exitCode;
|
|
37
|
+
private onSigTerm;
|
|
38
|
+
private onSigInt;
|
|
39
|
+
private startupGate?;
|
|
40
|
+
constructor();
|
|
41
|
+
protected canAddTask(): boolean;
|
|
42
|
+
protected canRemoveTask(): boolean;
|
|
43
|
+
protected getTaskType(): string;
|
|
44
|
+
protected executeTasksInPhase(phase: ShutdownPhase, tasks: LifecycleTask[]): Promise<PromiseSettledResult<void>[]>;
|
|
45
|
+
private registerSignalHandlers;
|
|
46
|
+
/** @internal */
|
|
47
|
+
removeSignalHandlers(): void;
|
|
48
|
+
/** @internal run() awaits this so boot finishes registering its dispose tasks first */
|
|
49
|
+
gateOnStartup(settled: Promise<void>): void;
|
|
50
|
+
addTask(phase: ShutdownPhase, taskName: string, task: () => Promise<void>, timeoutMs?: number): void;
|
|
51
|
+
/** @internal */
|
|
52
|
+
removeTask(phase: ShutdownPhase, taskName: string): boolean;
|
|
53
|
+
/** @internal */
|
|
54
|
+
run(exitCode?: number, exitProcess?: boolean): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/node/Lifecycle/CoordinatedStartup.d.ts
|
|
58
|
+
declare class CoordinatedStartup extends CoordinatedLifecycle<StartupPhase> {
|
|
59
|
+
private isStartingUp;
|
|
60
|
+
private hasStarted;
|
|
61
|
+
constructor();
|
|
62
|
+
addTask(phase: StartupPhase, taskName: string, task: () => Promise<void>, timeoutMs?: number): void;
|
|
63
|
+
protected canAddTask(): boolean;
|
|
64
|
+
protected canRemoveTask(): boolean;
|
|
65
|
+
protected getTaskType(): string;
|
|
66
|
+
protected executeTasksInPhase(phase: StartupPhase, tasks: LifecycleTask[]): Promise<PromiseSettledResult<void>[]>;
|
|
67
|
+
/** @internal */
|
|
68
|
+
run(): Promise<void>;
|
|
69
|
+
protected isAborted(): boolean;
|
|
70
|
+
/** @internal */
|
|
71
|
+
abort(): void;
|
|
72
|
+
/** @internal */
|
|
73
|
+
get isReady(): boolean;
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/node/Pluggable.d.ts
|
|
77
|
+
/**
|
|
78
|
+
* Base class for a plugin host, a transport `Seedcord` class.
|
|
79
|
+
*
|
|
80
|
+
* You attach plugins while configuring the bot. Within one startup phase, their `init()` calls run
|
|
81
|
+
* one after another in attach order.
|
|
82
|
+
*/
|
|
83
|
+
declare abstract class Pluggable<BotT extends Transport, BotRt extends Runtime> implements CoreBase {
|
|
84
|
+
abstract readonly config: Config;
|
|
85
|
+
abstract readonly rest: REST;
|
|
86
|
+
abstract readonly applicationId: string;
|
|
87
|
+
abstract readonly rateLimiter: IRateLimiter;
|
|
88
|
+
abstract readonly bus: Bus;
|
|
89
|
+
/** @internal */
|
|
90
|
+
readonly [HostShutdown]: CoordinatedShutdown;
|
|
91
|
+
/** @internal */
|
|
92
|
+
readonly [HostStartup]: CoordinatedStartup;
|
|
93
|
+
/** Add a task that runs while the bot shuts down. */
|
|
94
|
+
readonly shutdown: Pick<CoordinatedShutdown, 'addTask'>;
|
|
95
|
+
/** Add a task that runs while the bot starts. */
|
|
96
|
+
readonly startup: Pick<CoordinatedStartup, 'addTask'>;
|
|
97
|
+
protected isInitialized: boolean;
|
|
98
|
+
protected startFailed: boolean;
|
|
99
|
+
protected readonly plugins: PluginLike[];
|
|
100
|
+
private readonly pluginLogger;
|
|
101
|
+
private readonly attachments;
|
|
102
|
+
private readonly completedInits;
|
|
103
|
+
private readonly disposePhases;
|
|
104
|
+
private pluginTasksRegistered;
|
|
105
|
+
private initPromise?;
|
|
106
|
+
private static isInstantiated;
|
|
107
|
+
private static liveHost?;
|
|
108
|
+
private static liveShutdown?;
|
|
109
|
+
private static liveProcessErrors?;
|
|
110
|
+
constructor(shutdown: CoordinatedShutdown, startup: CoordinatedStartup);
|
|
111
|
+
/** @internal */
|
|
112
|
+
protected init(): Promise<this>;
|
|
113
|
+
private runInit;
|
|
114
|
+
/** @internal codegen reads this to emit the `Core` augmentation */
|
|
115
|
+
get [HostPluginKeys](): readonly string[];
|
|
116
|
+
/** @internal */
|
|
117
|
+
protected static reset(host?: object): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Attaches a plugin under `key`. Read the instance back as `core[key]`. `seedcord codegen`
|
|
120
|
+
* writes the `Core` augmentation that types it there.
|
|
121
|
+
*
|
|
122
|
+
* Startup runs each plugin's `init()` in attach order within its phase.
|
|
123
|
+
*
|
|
124
|
+
* Attaching a plugin whose `transport` or `runtime` differs from this host fails to compile.
|
|
125
|
+
* Your constructor takes `CoreBase` as its first parameter (you don't need to pass it though).
|
|
126
|
+
* A narrower one fails to compile here.
|
|
127
|
+
*
|
|
128
|
+
* @param key - Also the channel the plugin logs on. Reserved channel names throw.
|
|
129
|
+
* @param args - Whatever your constructor takes after the host.
|
|
130
|
+
* @throws A **SeedcordError** if you attach after the bot has started. A taken or reserved key throws too.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* seedcord.attach('db', Mongoose, { uri: 'mongodb://...', name: 'seedcord', dir: ... });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
attach<Key extends string, Ctor extends PluginCtor>(this: this, key: ChannelKeyAssert<Key>, Plugin: Ctor & TransportAssert<InstanceType<Ctor>, BotT> & RuntimeAssert<InstanceType<Ctor>, BotRt> & CoreParamAssert<Ctor>, ...args: PluginArgs<Ctor>): this & Record<Key, InstanceType<Ctor>>;
|
|
137
|
+
private registerPluginTasks;
|
|
138
|
+
private runInits;
|
|
139
|
+
private registerReadyTask;
|
|
140
|
+
private registerDisposeTask;
|
|
141
|
+
private runDisposals;
|
|
142
|
+
private disposeCompleted;
|
|
143
|
+
private rollback;
|
|
144
|
+
}
|
|
145
|
+
declare function shutdownOf(host: Pick<Pluggable<Transport, Runtime>, typeof HostShutdown>): CoordinatedShutdown;
|
|
146
|
+
//#endregion
|
|
147
|
+
export { LifecycleTask as a, CoordinatedShutdown as i, shutdownOf as n, CoordinatedStartup as r, Pluggable as t };
|
|
148
|
+
//# sourceMappingURL=Pluggable-DFNUIlJM.d.mts.map
|
|
@@ -2,7 +2,7 @@ import { n as StartupPhase, t as ShutdownPhase } from "./phases-BauKJOTT.mjs";
|
|
|
2
2
|
import { t as getDevChannel } from "./devChannel-CQU7hq7Q.mjs";
|
|
3
3
|
import { SeedcordErrorCode } from "@seedcord/errors";
|
|
4
4
|
import { Logger } from "@seedcord/logger";
|
|
5
|
-
import { SeedcordError } from "@seedcord/errors/internal";
|
|
5
|
+
import { SeedcordError, SeedcordRangeError } from "@seedcord/errors/internal";
|
|
6
6
|
|
|
7
7
|
//#region src/plugin/lifecycle.ts
|
|
8
8
|
const DEFAULT_INIT_TIMEOUT_MS = 15e3;
|
|
@@ -10,7 +10,11 @@ const DEFAULT_READY_TIMEOUT_MS = 15e3;
|
|
|
10
10
|
const DEFAULT_DISPOSE_TIMEOUT_MS = 1e4;
|
|
11
11
|
function timeoutOf(field, declared, fallback, pluginName) {
|
|
12
12
|
if (declared === void 0) return fallback;
|
|
13
|
-
if (!Number.isFinite(declared) || declared <= 0) throw new
|
|
13
|
+
if (!Number.isFinite(declared) || declared <= 0) throw new SeedcordRangeError(SeedcordErrorCode.PluginInvalidLifecycleTimeout, [
|
|
14
|
+
pluginName,
|
|
15
|
+
field,
|
|
16
|
+
declared
|
|
17
|
+
]);
|
|
14
18
|
return declared;
|
|
15
19
|
}
|
|
16
20
|
/** @internal */
|
|
@@ -111,4 +115,4 @@ function pluginLoggerOf(plugin) {
|
|
|
111
115
|
|
|
112
116
|
//#endregion
|
|
113
117
|
export { pluginLoggerOf as n, resolvedLifecycleSpecOf as r, Plugin as t };
|
|
114
|
-
//# sourceMappingURL=Plugin-
|
|
118
|
+
//# sourceMappingURL=Plugin-C6oMqWf8.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Plugin-C6oMqWf8.mjs","names":[],"sources":["../src/plugin/lifecycle.ts","../src/plugin/Plugin.ts"],"sourcesContent":["import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordRangeError } from '@seedcord/errors/internal';\n\nimport { ShutdownPhase, StartupPhase } from '#src/lifecycle/phases';\n\n/**\n * Sets when a plugin's lifecycle methods run. Pass it as the second argument to `super()`. Omit a\n * field to keep its default.\n *\n * @see {@link StartupPhase}\n * @see {@link ShutdownPhase}\n * @example\n * ```ts\n * super(host, { init: { phase: StartupPhase.Login }, dispose: { timeout: 30_000 } });\n * ```\n */\nexport interface PluginLifecycleSpec {\n /**\n * Defaults to `StartupPhase.Configuration` and 15000ms. Set the phase to `Ready` and `init()`\n * runs ahead of every plugin's `ready()`.\n */\n init?: { phase?: StartupPhase; timeout?: number };\n /** `ready()` always runs in `StartupPhase.Ready`. Defaults to a 15000ms timeout. */\n ready?: { timeout?: number };\n /** Defaults to `ShutdownPhase.Disconnect` and 10000ms. */\n dispose?: { phase?: ShutdownPhase; timeout?: number };\n}\n\n/** @internal */\nexport interface ResolvedPluginLifecycleSpec {\n readonly init: { readonly phase: StartupPhase; readonly timeout: number };\n readonly ready: { readonly timeout: number };\n readonly dispose: { readonly phase: ShutdownPhase; readonly timeout: number };\n}\n\nconst DEFAULT_INIT_TIMEOUT_MS = 15_000;\nconst DEFAULT_READY_TIMEOUT_MS = 15_000;\nconst DEFAULT_DISPOSE_TIMEOUT_MS = 10_000;\n\nfunction timeoutOf(\n field: 'init' | 'ready' | 'dispose',\n declared: number | undefined,\n fallback: number,\n pluginName: string\n): number {\n if (declared === undefined) return fallback;\n if (!Number.isFinite(declared) || declared <= 0) {\n throw new SeedcordRangeError(SeedcordErrorCode.PluginInvalidLifecycleTimeout, [pluginName, field, declared]);\n }\n return declared;\n}\n\n/** @internal */\nexport function resolveLifecycleSpec(\n spec: PluginLifecycleSpec | undefined,\n pluginName: string\n): ResolvedPluginLifecycleSpec {\n return {\n init: {\n phase: spec?.init?.phase ?? StartupPhase.Configuration,\n timeout: timeoutOf('init', spec?.init?.timeout, DEFAULT_INIT_TIMEOUT_MS, pluginName)\n },\n ready: {\n timeout: timeoutOf('ready', spec?.ready?.timeout, DEFAULT_READY_TIMEOUT_MS, pluginName)\n },\n dispose: {\n phase: spec?.dispose?.phase ?? ShutdownPhase.Disconnect,\n timeout: timeoutOf('dispose', spec?.dispose?.timeout, DEFAULT_DISPOSE_TIMEOUT_MS, pluginName)\n }\n };\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\n\nimport { getDevChannel } from '#hmr/devChannel';\n\nimport { RuntimeBrand, TransportBrand } from './brands';\nimport { resolveLifecycleSpec } from './lifecycle';\n\nimport type { CoreBase } from '#interfaces/CoreBase';\nimport type { ResolvedPluginLifecycleSpec, PluginLifecycleSpec } from './lifecycle';\nimport type { TransportOf, PluginOptions, RuntimeOf } from './options';\nimport type { Tail, HmrAware, HmrUpdateEvent } from '@seedcord/types';\n\nexport interface Initializeable {\n init(): Promise<void>;\n}\n\n/** @internal */\nconst resolvedSpecSlot = Symbol('seedcord.plugin.spec');\n/** @internal */\nconst loggerSlot = Symbol('seedcord.plugin.logger');\n\n/**\n * Base class for a seedcord plugin. Extend it and implement `init()`. `this.core` is the running\n * bot.\n *\n * Your constructor takes the host first and passes it to `super()`. Add your own parameters after\n * it. `attach()` types them at the call site.\n *\n * @typeParam Opts - Where this plugin may attach, checked only at compile time.\n * @typeParam TCore - The `Core` each transport binds `this.core` to.\n *\n * @example\n * ```ts\n * class Analytics extends Plugin<{ transport: 'gateway' }> {\n * constructor(\n * host: CoreBase,\n * private readonly apiKey: string\n * ) {\n * super(host, { init: { phase: StartupPhase.Login } });\n * }\n *\n * public async init(): Promise<void> {\n * await this.connect(this.apiKey);\n * }\n * }\n *\n * seedcord.attach('analytics', Analytics, apiKey);\n * ```\n */\nexport abstract class Plugin<Opts extends PluginOptions = {}, TCore extends CoreBase = CoreBase>\n implements Initializeable, HmrAware\n{\n // phantom, never set at runtime.\n /** @internal */\n declare readonly [TransportBrand]?: TransportOf<Opts>;\n /** @internal */\n declare readonly [RuntimeBrand]?: RuntimeOf<Opts>;\n\n /** @internal */\n readonly [resolvedSpecSlot]: ResolvedPluginLifecycleSpec;\n /** @internal */\n readonly [loggerSlot]: Logger;\n\n /** Logs under the plugin's class name, on the channel its attach key sets. */\n protected readonly logger: Logger;\n\n // CoreBase here keeps the augmented Core out of ConstructorParameters, which attach reads\n constructor(\n private readonly host: CoreBase,\n spec?: PluginLifecycleSpec\n ) {\n this.logger = new Logger(this.constructor.name);\n this[loggerSlot] = this.logger;\n this[resolvedSpecSlot] = resolveLifecycleSpec(spec, this.constructor.name);\n }\n\n /** The host, typed to the transport whose `Plugin` base this class extends. */\n protected get core(): TCore {\n // justified: each transport binds TCore to the Core its own host satisfies\n return this.host as TCore;\n }\n\n /**\n * Runs in `StartupPhase.Configuration` by default.\n * Move it to a different phase with the {@link PluginLifecycleSpec}.\n */\n abstract init(): Promise<void>;\n\n /**\n * Runs in the Ready phase, after every attached plugin's `init()` has resolved. The other Ready\n * tasks run alongside it, including the http server binding its port.\n *\n * Override it when your work needs a logged-in client or a resolved application id.\n */\n ready?(): Promise<void>;\n\n /** Runs during teardown, in `ShutdownPhase.Disconnect` by default. It never runs when `init()` has thrown. */\n dispose?(): Promise<void>;\n\n /**\n * Throws a `SeedcordError` that contains the plugin class name and the reason.\n *\n * @param reason - Why the options are invalid.\n */\n protected rejectOptions(reason: string): never {\n throw new SeedcordError(SeedcordErrorCode.PluginOptionsRejected, [this.constructor.name, reason]);\n }\n\n /** Override to reload plugin state on an HMR update. */\n public onHmr(_event: HmrUpdateEvent): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Registers critical file patterns that should trigger a full restart when changed in Dev HMR.\n * @param patterns - Glob patterns relative to the project root\n */\n protected registerCriticalFiles(patterns: string[]): void {\n getDevChannel()?.send('seedcord:register-critical-files', { patterns });\n }\n}\n\n/** @internal */\nexport function resolvedLifecycleSpecOf(plugin: PluginLike): ResolvedPluginLifecycleSpec {\n return plugin[resolvedSpecSlot];\n}\n\n/** @internal */\nexport function pluginLoggerOf(plugin: PluginLike): Logger {\n return plugin[loggerSlot];\n}\n\nexport type { PluginLifecycleSpec } from './lifecycle';\nexport type { PluginOptions } from './options';\n\n// a bound of Plugin<{}> rejects every plugin that declares an option, since Plugin<A> and Plugin<B>\n// are mutually unassignable. every member here must stay Opts-independent.\n/** @internal */\nexport type PluginLike = Pick<\n Plugin,\n 'init' | 'ready' | 'dispose' | 'onHmr' | typeof resolvedSpecSlot | typeof loggerSlot\n>;\n\n// a `CoreBase` first parameter rejects a narrowing ctor on its own, and it also collapses\n// `InstanceType<Ctor>` to `PluginLike` at every attach call. CoreParamAssert checks it instead.\n/** @internal */\nexport type PluginCtor<TPlugin extends PluginLike = PluginLike> = new (...args: any[]) => TPlugin;\n\n/** @internal */\nexport type PluginArgs<Ctor extends PluginCtor> = Tail<ConstructorParameters<Ctor>>;\n\ntype CoreParamTooNarrow = Record<\n 'this plugin constructor must take CoreBase as its first parameter and read the transport Core off this.core',\n never\n>;\n\n// a narrowed first parameter fails `CoreBase extends Param`\n/** @internal */\nexport type CoreParamAssert<Ctor extends PluginCtor> = CoreBase extends ConstructorParameters<Ctor>[0]\n ? unknown\n : CoreParamTooNarrow;\n"],"mappings":";;;;;;;AAmCA,MAAM,0BAA0B;AAChC,MAAM,2BAA2B;AACjC,MAAM,6BAA6B;AAEnC,SAAS,UACL,OACA,UACA,UACA,YACM;CACN,IAAI,aAAa,QAAW,OAAO;CACnC,IAAI,CAAC,OAAO,SAAS,QAAQ,KAAK,YAAY,GAC1C,MAAM,IAAI,mBAAmB,kBAAkB,+BAA+B;EAAC;EAAY;EAAO;CAAQ,CAAC;CAE/G,OAAO;AACX;;AAGA,SAAgB,qBACZ,MACA,YAC2B;CAC3B,OAAO;EACH,MAAM;GACF,OAAO,MAAM,MAAM;GACnB,SAAS,UAAU,QAAQ,MAAM,MAAM,SAAS,yBAAyB,UAAU;EACvF;EACA,OAAO,EACH,SAAS,UAAU,SAAS,MAAM,OAAO,SAAS,0BAA0B,UAAU,EAC1F;EACA,SAAS;GACL,OAAO,MAAM,SAAS;GACtB,SAAS,UAAU,WAAW,MAAM,SAAS,SAAS,4BAA4B,UAAU;EAChG;CACJ;AACJ;;;;;ACnDA,MAAM,mBAAmB,OAAO,sBAAsB;;AAEtD,MAAM,aAAa,OAAO,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BlD,IAAsB,SAAtB,MAEA;CAiByB;;CATrB,CAAU;;CAEV,CAAU;;CAGV,AAAmB;CAGnB,YACI,AAAiB,MACjB,MACF;EAFmB;EAGjB,KAAK,SAAS,IAAI,OAAO,KAAK,YAAY,IAAI;EAC9C,KAAK,cAAc,KAAK;EACxB,KAAK,oBAAoB,qBAAqB,MAAM,KAAK,YAAY,IAAI;CAC7E;;CAGA,IAAc,OAAc;EAExB,OAAO,KAAK;CAChB;;;;;;CAwBA,AAAU,cAAc,QAAuB;EAC3C,MAAM,IAAI,cAAc,kBAAkB,uBAAuB,CAAC,KAAK,YAAY,MAAM,MAAM,CAAC;CACpG;;CAGA,AAAO,MAAM,QAAuC;EAChD,OAAO,QAAQ,QAAQ;CAC3B;;;;;CAMA,AAAU,sBAAsB,UAA0B;EACtD,cAAc,CAAC,EAAE,KAAK,oCAAoC,EAAE,SAAS,CAAC;CAC1E;AACJ;;AAGA,SAAgB,wBAAwB,QAAiD;CACrF,OAAO,OAAO;AAClB;;AAGA,SAAgB,eAAe,QAA4B;CACvD,OAAO,OAAO;AAClB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as StartupPhase, r as CoreBase, t as ShutdownPhase } from "./phases-
|
|
1
|
+
import { n as StartupPhase, r as CoreBase, t as ShutdownPhase } from "./phases-F8yvPd60.mjs";
|
|
2
2
|
import { Logger } from "@seedcord/logger";
|
|
3
3
|
import { FrameworkChannel, HmrAware, HmrUpdateEvent, Tail, TypedExclude } from "@seedcord/types";
|
|
4
4
|
//#region src/plugin/brands.d.ts
|
|
@@ -190,4 +190,4 @@ type CoreParamTooNarrow = Record<'this plugin constructor must take CoreBase as
|
|
|
190
190
|
type CoreParamAssert<Ctor extends PluginCtor> = CoreBase extends ConstructorParameters<Ctor>[0] ? unknown : CoreParamTooNarrow;
|
|
191
191
|
//#endregion
|
|
192
192
|
export { PluginCtor as a, PluginOptions as c, Transport as d, TransportAssert as f, PluginArgs as i, Runtime as l, Initializeable as n, PluginLike as o, PluginLifecycleSpec as p, Plugin as r, ChannelKeyAssert as s, CoreParamAssert as t, RuntimeAssert as u };
|
|
193
|
-
//# sourceMappingURL=Plugin-
|
|
193
|
+
//# sourceMappingURL=Plugin-CG9pWbPF.d.mts.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as Constructor } from "./basic-Dng__Ena.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { b as Notice, r as CoreBase, z as InteractionRoutes } from "./phases-F8yvPd60.mjs";
|
|
3
3
|
import "reflect-metadata";
|
|
4
4
|
import { ActionRowBuilder, ButtonBuilder, ChannelSelectMenuBuilder, CheckboxBuilder, CheckboxGroupBuilder, CheckboxGroupOptionBuilder, ContainerBuilder, ContextMenuCommandBuilder, EmbedBuilder, FileBuilder, FileUploadBuilder, LabelBuilder, MediaGalleryBuilder, MentionableSelectMenuBuilder, ModalBuilder, RadioGroupBuilder, RadioGroupOptionBuilder, RoleSelectMenuBuilder, SectionBuilder, SeparatorBuilder, SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, TextDisplayBuilder, TextInputBuilder, UserSelectMenuBuilder } from "@discordjs/builders";
|
|
5
|
-
import { APIMessageTopLevelComponent,
|
|
6
|
-
import {
|
|
5
|
+
import { APIMessageTopLevelComponent, ApplicationCommandType, ChannelType, Snowflake } from "discord-api-types/v10";
|
|
6
|
+
import { ReplyResponse } from "@seedcord/types";
|
|
7
7
|
//#region src/registries/ContextMenuRegistry.d.ts
|
|
8
8
|
/** The two context-menu command kinds Discord defines. */
|
|
9
9
|
type ContextMenuKind = ApplicationCommandType.User | ApplicationCommandType.Message;
|
|
@@ -363,6 +363,8 @@ interface CustomIdField<Decoded> {
|
|
|
363
363
|
readonly max?: number;
|
|
364
364
|
/** The allowed values, for a oneOf field. */
|
|
365
365
|
readonly choices?: readonly string[];
|
|
366
|
+
/** Whether this field also carries null. */
|
|
367
|
+
readonly nullable?: boolean;
|
|
366
368
|
/** Phantom only, carries the decoded type and is never set at runtime. */
|
|
367
369
|
readonly decoded?: Decoded;
|
|
368
370
|
}
|
|
@@ -380,6 +382,16 @@ type CustomIdShape = Record<string, CustomIdField<unknown>>;
|
|
|
380
382
|
type DecodedParams<Shape extends CustomIdShape> = { [Name in keyof Shape]: Shape[Name] extends CustomIdField<infer Decoded> ? Decoded : never; };
|
|
381
383
|
//#endregion
|
|
382
384
|
//#region src/customId/CustomId.d.ts
|
|
385
|
+
/** Per-field options every {@link CustomId} chain method takes. */
|
|
386
|
+
interface FieldOptions<Nullable extends boolean = boolean> {
|
|
387
|
+
/**
|
|
388
|
+
* Whether the field also carries null. A nullable field costs one extra slot on the wire.
|
|
389
|
+
*
|
|
390
|
+
* @defaultValue `false`
|
|
391
|
+
*/
|
|
392
|
+
nullable?: Nullable;
|
|
393
|
+
}
|
|
394
|
+
type Nullish<Decoded, Nullable extends boolean> = Nullable extends true ? Decoded | null : Decoded;
|
|
383
395
|
/** Strip the layout hash off the routeKey to recover the stable prefix the controller routes by. @internal */
|
|
384
396
|
declare function prefixOf(wire: string): string;
|
|
385
397
|
/**
|
|
@@ -421,7 +433,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
421
433
|
* new CustomId('ban').snowflake('userId');
|
|
422
434
|
* ```
|
|
423
435
|
*/
|
|
424
|
-
snowflake<Name extends string>(name: Name): CustomId<Prefix, Shape & Record<Name, CustomIdField<Snowflake
|
|
436
|
+
snowflake<Name extends string, const Nullable extends boolean = false>(name: Name, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<Snowflake, Nullable>>>>;
|
|
425
437
|
/**
|
|
426
438
|
* Add a UUID field, decoded as a lowercase uuid string.
|
|
427
439
|
*
|
|
@@ -430,7 +442,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
430
442
|
* new CustomId('ticket').uuid('ticketId');
|
|
431
443
|
* ```
|
|
432
444
|
*/
|
|
433
|
-
uuid<Name extends string>(name: Name): CustomId<Prefix, Shape & Record<Name, CustomIdField<string
|
|
445
|
+
uuid<Name extends string, const Nullable extends boolean = false>(name: Name, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<string, Nullable>>>>;
|
|
434
446
|
/**
|
|
435
447
|
* Add an integer field with no bounds, for a value up to 2^53.
|
|
436
448
|
*
|
|
@@ -439,7 +451,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
439
451
|
* new CustomId('shop').int('amount');
|
|
440
452
|
* ```
|
|
441
453
|
*/
|
|
442
|
-
int<Name extends string>(name: Name): CustomId<Prefix, Shape & Record<Name, CustomIdField<number
|
|
454
|
+
int<Name extends string, const Nullable extends boolean = false>(name: Name, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<number, Nullable>>>>;
|
|
443
455
|
/**
|
|
444
456
|
* Add an integer field bounded by min and max, so it packs into fewer characters on the wire.
|
|
445
457
|
*
|
|
@@ -448,7 +460,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
448
460
|
* new CustomId('paginate').int('page', 1, 50);
|
|
449
461
|
* ```
|
|
450
462
|
*/
|
|
451
|
-
int<Name extends string>(name: Name, min: number, max: number): CustomId<Prefix, Shape & Record<Name, CustomIdField<number
|
|
463
|
+
int<Name extends string, const Nullable extends boolean = false>(name: Name, min: number, max: number, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<number, Nullable>>>>;
|
|
452
464
|
/**
|
|
453
465
|
* Add a boolean flag.
|
|
454
466
|
*
|
|
@@ -457,7 +469,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
457
469
|
* new CustomId('settings').bool('silent');
|
|
458
470
|
* ```
|
|
459
471
|
*/
|
|
460
|
-
bool<Name extends string>(name: Name): CustomId<Prefix, Shape & Record<Name, CustomIdField<boolean
|
|
472
|
+
bool<Name extends string, const Nullable extends boolean = false>(name: Name, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<boolean, Nullable>>>>;
|
|
461
473
|
/**
|
|
462
474
|
* Add a field that is one value from a fixed list, decoded as the literal union. No `as const` needed.
|
|
463
475
|
*
|
|
@@ -466,7 +478,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
466
478
|
* new CustomId('poll').oneOf('choice', ['yes', 'no', 'abstain']);
|
|
467
479
|
* ```
|
|
468
480
|
*/
|
|
469
|
-
oneOf<Name extends string, const Choices extends NonEmptyTuple<string
|
|
481
|
+
oneOf<Name extends string, const Choices extends NonEmptyTuple<string>, const Nullable extends boolean = false>(name: Name, choices: Choices, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<Choices[number], Nullable>>>>;
|
|
470
482
|
/**
|
|
471
483
|
* Add a free short text field. Avoid it where possible. It cannot be packed, which makes it the most
|
|
472
484
|
* expensive field on the wire.
|
|
@@ -476,7 +488,7 @@ declare class CustomId<Prefix extends string, Shape extends CustomIdShape = {}>
|
|
|
476
488
|
* new CustomId('note').str('message');
|
|
477
489
|
* ```
|
|
478
490
|
*/
|
|
479
|
-
str<Name extends string>(name: Name): CustomId<Prefix, Shape & Record<Name, CustomIdField<string
|
|
491
|
+
str<Name extends string, const Nullable extends boolean = false>(name: Name, opts?: FieldOptions<Nullable>): CustomId<Prefix, Shape & Record<Name, CustomIdField<Nullish<string, Nullable>>>>;
|
|
480
492
|
/**
|
|
481
493
|
* Mint a wire string from values. Throws if a value is out of its field's range or the wire is over 100 chars.
|
|
482
494
|
*
|
|
@@ -548,65 +560,6 @@ interface SerializedReply<TNative = never> {
|
|
|
548
560
|
}
|
|
549
561
|
declare function serializeReply<TNative>(response: ReplyResponse<TNative> | string, routeId: string): SerializedReply<TNative>;
|
|
550
562
|
//#endregion
|
|
551
|
-
//#region src/reply/BaseReplySender.d.ts
|
|
552
|
-
/** The shape djs modal builders emit from `toJSON()`. */
|
|
553
|
-
interface ModalLike {
|
|
554
|
-
toJSON(): APIModalInteractionResponseCallbackData;
|
|
555
|
-
}
|
|
556
|
-
/**
|
|
557
|
-
* Tracks acknowledgement state and throws a translated `SeedcordError` on an illegal verb before any
|
|
558
|
-
* transport call. Every verb runs the legality check, calls the transport's wire writer, then updates
|
|
559
|
-
* the state and the ack trace. Each transport binds `TMessage` to its own created-message type and
|
|
560
|
-
* supplies the writers.
|
|
561
|
-
*/
|
|
562
|
-
declare abstract class BaseReplySender<TMessage extends {
|
|
563
|
-
id: string;
|
|
564
|
-
}, TNative = never> {
|
|
565
|
-
protected readonly routeId: string;
|
|
566
|
-
private readonly telemetry;
|
|
567
|
-
private state;
|
|
568
|
-
private readonly sent;
|
|
569
|
-
private ackedBy?;
|
|
570
|
-
protected constructor(routeId: string, telemetry: ReplyTelemetry, initialState?: AckState);
|
|
571
|
-
private report;
|
|
572
|
-
private attempt;
|
|
573
|
-
reply(response: ReplyResponse<TNative> | string, opts?: SendOpts): Promise<TMessage>;
|
|
574
|
-
defer(opts?: DeferOpts): Promise<void>;
|
|
575
|
-
deferUpdate(): Promise<void>;
|
|
576
|
-
/**
|
|
577
|
-
* After a deferUpdate the state stays deferred-update. Calling this again rewrites. The returned message
|
|
578
|
-
* is the source message, editable only through a bare `update` or `edit`. A targeted `edit` or `delete`
|
|
579
|
-
* of it throws the foreign-target error.
|
|
580
|
-
*/
|
|
581
|
-
update(response: ReplyResponse<TNative> | string): Promise<TMessage>;
|
|
582
|
-
followUp(response: ReplyResponse<TNative> | string, opts?: SendOpts): Promise<TMessage>;
|
|
583
|
-
edit(response: ReplyResponse<TNative> | string): Promise<TMessage>;
|
|
584
|
-
edit(target: TMessage, response: ReplyResponse<TNative> | string): Promise<TMessage>;
|
|
585
|
-
delete(): Promise<void>;
|
|
586
|
-
delete(target: TMessage): Promise<void>;
|
|
587
|
-
/** Routes to the verb the current ack state permits. Every state has a route, so the illegal-ack throw is unreachable. */
|
|
588
|
-
send(response: ReplyResponse<TNative> | string, opts?: SendOpts): Promise<TMessage>;
|
|
589
|
-
/** Must be the initial response. */
|
|
590
|
-
showModal(modal: ModalLike): Promise<void>;
|
|
591
|
-
protected serialize(response: ReplyResponse<TNative> | string): SerializedReply<TNative>;
|
|
592
|
-
protected remember(created: TMessage): TMessage;
|
|
593
|
-
private requireMessage;
|
|
594
|
-
private editOriginal;
|
|
595
|
-
private checkLegality;
|
|
596
|
-
private transition;
|
|
597
|
-
protected guardModalSource(): void;
|
|
598
|
-
protected abstract writeReply(response: ReplyResponse<TNative> | string, opts?: SendOpts): Promise<TMessage | undefined>;
|
|
599
|
-
protected abstract writeDefer(opts?: DeferOpts): Promise<void>;
|
|
600
|
-
protected abstract writeDeferUpdate(): Promise<void>;
|
|
601
|
-
protected abstract writeUpdate(response: ReplyResponse<TNative> | string): Promise<TMessage | undefined>;
|
|
602
|
-
protected abstract writeFollowUp(response: ReplyResponse<TNative> | string, opts?: SendOpts): Promise<TMessage>;
|
|
603
|
-
protected abstract writeEditOriginal(response: ReplyResponse<TNative> | string): Promise<TMessage>;
|
|
604
|
-
protected abstract writeEditTarget(targetId: string, response: ReplyResponse<TNative> | string): Promise<TMessage>;
|
|
605
|
-
protected abstract writeDeleteOriginal(): Promise<void>;
|
|
606
|
-
protected abstract writeDeleteTarget(targetId: string): Promise<void>;
|
|
607
|
-
protected abstract writeModal(data: APIModalInteractionResponseCallbackData): Promise<void>;
|
|
608
|
-
}
|
|
609
|
-
//#endregion
|
|
610
563
|
//#region src/gates/Gate.d.ts
|
|
611
564
|
/**
|
|
612
565
|
* The transport-agnostic gate context, the scalar identity of the acting user resolvable from any
|
|
@@ -821,7 +774,8 @@ type RequiredOf<TGate> = TGate extends Gate<infer Ctx> ? Ctx : never;
|
|
|
821
774
|
type IntersectRequired<Gates extends readonly Gate<GateContextBase>[]> = Gates extends readonly [infer First extends Gate<GateContextBase>, ...infer Rest extends readonly Gate<GateContextBase>[]] ? RequiredOf<First> & IntersectRequired<Rest> : unknown;
|
|
822
775
|
type TwoOrMore<Item> = readonly [Item, Item, ...Item[]];
|
|
823
776
|
type GateName<TGate> = TGate extends Gate<GateContextBase, infer Name> ? Name : string;
|
|
824
|
-
type
|
|
777
|
+
type Grouped<Name extends string> = Name extends `${string} & ${string}` | `${string} | ${string}` ? `(${Name})` : Name;
|
|
778
|
+
type JoinNames<Gates extends readonly Gate<GateContextBase>[], Sep extends string> = Gates extends readonly [infer Only extends Gate<GateContextBase>] ? Grouped<GateName<Only>> : Gates extends readonly [infer First extends Gate<GateContextBase>, ...infer Rest extends readonly Gate<GateContextBase>[]] ? `${Grouped<GateName<First>>}${Sep}${JoinNames<Rest, Sep>}` : string;
|
|
825
779
|
type GateMismatch<Name extends string, Want extends string, Got extends string> = `gate '${Name}' requires a ${Want} handler, and this handler is ${Got}`;
|
|
826
780
|
type GateFitsWith<Provided, ProvidedLabel extends string, TGate, ReqLabel extends string> = [Provided] extends [RequiredOf<TGate>] ? TGate : Constructor<[GateMismatch<GateName<TGate>, ReqLabel, ProvidedLabel>]>;
|
|
827
781
|
//#endregion
|
|
@@ -1029,5 +983,5 @@ type PageCursor<Prefix extends string> = CustomId<Prefix, {
|
|
|
1029
983
|
/** Build the page cursor for a paginator. */
|
|
1030
984
|
declare function pageCursor<Prefix extends string>(prefix: Prefix): PageCursor<Prefix>;
|
|
1031
985
|
//#endregion
|
|
1032
|
-
export {
|
|
1033
|
-
//# sourceMappingURL=cursor-
|
|
986
|
+
export { Promisable as $, serializeReply as A, contextMenuRouteOf as B, Gate as C, defineEffectGate as D, RequiredOf as E, ContextMenuNamesBrand as F, AnyCustomId as G, selectMenuRouteOf as H, SlashRouteBrand as I, decodeFor as J, CustomId as K, RoutableConstructor as L, ComponentDefsBrand as M, ComponentKindBrand as N, defineGate as O, ContextMenuKindBrand as P, RegisterCommand as Q, SelectMenuKind as R, EffectGate as S, GuildPermissionsContext as T, storeComponentRoute as U, interactionRoutesOf as V, storeInteractionRoute as W, DecodedParams as X, prefixOf as Y, CommandMeta as Z, pickNotice as _, AutocompleteOptions as a, CacheFor as at, JoinNames as b, FocusedField as c, SlashOption as ct, RequirePermissionsOptions as d, ContextMenuKind as dt, IsNever as et, RequireRole as f, MenuCacheFor as ft, GateNoticeOptions as g, PermissionScope as h, UserContextMenuRegistry as ht, AutocompletableNames as i, RowType as it, AutocompleteRouteBrand as j, SerializedReply as k, RequireBotPermissions as l, SlashRegistry as lt, PermissionNames as m, NamesFor as mt, PageCursor as n, RowComponent as nt, ChoiceValueOf as o, OptionKind as ot, RequireRoleOptions as p, MessageContextMenuRegistry as pt, FieldOptions as q, pageCursor as r, BuilderType as rt, EntryFor as s, RouteCache as st, PAGE_MAX as t, BuilderComponent as tt, RequirePermissions as u, SlashRouteEntry as ut, GateFitsWith as v, GateContextBase as w, TwoOrMore as x, IntersectRequired as y, areRoutes as z };
|
|
987
|
+
//# sourceMappingURL=cursor-BcRfmTSo.d.mts.map
|