@seedcord/core 0.9.4 → 0.11.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.
- package/README.md +28 -10
- package/dist/CoordinatedShutdown-H5YjZn8A.d.mts +78 -0
- package/dist/CoordinatedStartup-CGnJrqcl.mjs +168 -0
- package/dist/CoordinatedStartup-CGnJrqcl.mjs.map +1 -0
- package/dist/{HmrModuleHandler-DOAtah3j.mjs → HmrModuleHandler-8ZC-UuZh.mjs} +9 -22
- package/dist/HmrModuleHandler-8ZC-UuZh.mjs.map +1 -0
- package/dist/PluginHost-B8kxLOeb.mjs +245 -0
- package/dist/PluginHost-B8kxLOeb.mjs.map +1 -0
- package/dist/{Plugin-Dhx_ivqj.d.mts → PluginHost-DB4j8unu.d.mts} +110 -17
- package/dist/PluginLifecycle-AhQ46NIr.mjs +158 -0
- package/dist/PluginLifecycle-AhQ46NIr.mjs.map +1 -0
- package/dist/ServerHost-CvGQr7oN.mjs +191 -0
- package/dist/ServerHost-CvGQr7oN.mjs.map +1 -0
- package/dist/ServerHost-DYeh0KTk.d.mts +40 -0
- package/dist/hmr.index.d.mts +0 -1
- package/dist/hmr.index.mjs +1 -1
- package/dist/{cursor-BTU5bGoo.d.mts → index-Du71Xx69.d.mts} +253 -6
- package/dist/index.d.mts +19 -84
- package/dist/index.mjs +17 -37
- package/dist/index.mjs.map +1 -1
- package/dist/internal.index.d.mts +185 -22
- package/dist/internal.index.mjs +713 -19
- package/dist/internal.index.mjs.map +1 -1
- package/dist/node-internal.index.d.mts +25 -70
- package/dist/node-internal.index.mjs +84 -298
- package/dist/node-internal.index.mjs.map +1 -1
- package/dist/node.index.d.mts +3 -2
- package/dist/node.index.mjs +53 -200
- package/dist/node.index.mjs.map +1 -1
- package/dist/{phases-D_zQBXga.d.mts → phases-FTM69J3a.d.mts} +4 -4
- package/dist/plugin.index.d.mts +2 -2
- package/dist/plugin.index.mjs +2 -2
- package/dist/publishDefault-D3dAyzZ9.mjs +7 -0
- package/dist/publishDefault-D3dAyzZ9.mjs.map +1 -0
- package/dist/subscribers-Ce3SWy23.mjs +1913 -0
- package/dist/subscribers-Ce3SWy23.mjs.map +1 -0
- package/package.json +17 -16
- package/dist/Bus-BxPa-Uvp.mjs +0 -866
- package/dist/Bus-BxPa-Uvp.mjs.map +0 -1
- package/dist/HmrModuleHandler-DOAtah3j.mjs.map +0 -1
- package/dist/Pluggable-CXyUZIvT.mjs +0 -310
- package/dist/Pluggable-CXyUZIvT.mjs.map +0 -1
- package/dist/Pluggable-CwKbLui3.d.mts +0 -162
- package/dist/Plugin-CmNW5n6a.mjs +0 -122
- package/dist/Plugin-CmNW5n6a.mjs.map +0 -1
- package/dist/contextMenuLeaves-COzDYa6c.d.mts +0 -17
- package/dist/cursor-CgNBnJfu.mjs +0 -802
- package/dist/cursor-CgNBnJfu.mjs.map +0 -1
- package/dist/devChannel-CQU7hq7Q.mjs +0 -14
- package/dist/devChannel-CQU7hq7Q.mjs.map +0 -1
- package/dist/index-B_-EjyvS.d.mts +0 -135
- package/dist/publishDefault-BuSZPbjT.mjs +0 -14
- package/dist/publishDefault-BuSZPbjT.mjs.map +0 -1
- package/dist/slashRouteLeaves-k1hJnXDO.mjs +0 -31
- package/dist/slashRouteLeaves-k1hJnXDO.mjs.map +0 -1
- package/dist/subscribers-xGy7a7xR.mjs +0 -167
- package/dist/subscribers-xGy7a7xR.mjs.map +0 -1
- package/dist/types-BG0BimVr.d.mts +0 -13
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { i as Bus, n as StartupPhase, r as CoreBase, t as ShutdownPhase } from "./phases-D_zQBXga.mjs";
|
|
2
|
-
import { c as PluginLike, d as Transport, n as AttachableCtor, o as PluginArgs, r as Attached, s as PluginCtor, t as AttachKeyAssert, u as Runtime } from "./Plugin-Dhx_ivqj.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
|
-
private deadlineMs;
|
|
41
|
-
private phasesExpireAt;
|
|
42
|
-
private runningPhase;
|
|
43
|
-
constructor(deadlineMs?: number);
|
|
44
|
-
/** @internal */
|
|
45
|
-
setDeadline(deadlineMs: number): void;
|
|
46
|
-
private runPhases;
|
|
47
|
-
protected canAddTask(): boolean;
|
|
48
|
-
protected canRemoveTask(): boolean;
|
|
49
|
-
protected getTaskType(): string;
|
|
50
|
-
protected executeTasksInPhase(phase: ShutdownPhase, tasks: LifecycleTask[]): Promise<PromiseSettledResult<void>[]>;
|
|
51
|
-
private registerSignalHandlers;
|
|
52
|
-
/** @internal */
|
|
53
|
-
removeSignalHandlers(): void;
|
|
54
|
-
/** @internal run() awaits this so boot finishes registering its dispose tasks first */
|
|
55
|
-
gateOnStartup(settled: Promise<void>): void;
|
|
56
|
-
addTask(phase: ShutdownPhase, taskName: string, task: () => Promise<void>, timeoutMs?: number): void;
|
|
57
|
-
/** @internal */
|
|
58
|
-
removeTask(phase: ShutdownPhase, taskName: string): boolean;
|
|
59
|
-
/** @internal */
|
|
60
|
-
run(exitCode?: number, exitProcess?: boolean): Promise<void>;
|
|
61
|
-
}
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/node/Lifecycle/CoordinatedStartup.d.ts
|
|
64
|
-
declare class CoordinatedStartup extends CoordinatedLifecycle<StartupPhase> {
|
|
65
|
-
private isStartingUp;
|
|
66
|
-
private hasStarted;
|
|
67
|
-
constructor();
|
|
68
|
-
addTask(phase: StartupPhase, taskName: string, task: () => Promise<void>, timeoutMs?: number): void;
|
|
69
|
-
protected canAddTask(): boolean;
|
|
70
|
-
protected canRemoveTask(): boolean;
|
|
71
|
-
protected getTaskType(): string;
|
|
72
|
-
protected executeTasksInPhase(phase: StartupPhase, tasks: LifecycleTask[]): Promise<PromiseSettledResult<void>[]>;
|
|
73
|
-
/** @internal */
|
|
74
|
-
run(): Promise<void>;
|
|
75
|
-
protected isAborted(): boolean;
|
|
76
|
-
/** @internal */
|
|
77
|
-
abort(): void;
|
|
78
|
-
/** @internal */
|
|
79
|
-
get isReady(): boolean;
|
|
80
|
-
}
|
|
81
|
-
//#endregion
|
|
82
|
-
//#region src/node/Pluggable.d.ts
|
|
83
|
-
/**
|
|
84
|
-
* Base class for a plugin host, a transport `Seedcord` class.
|
|
85
|
-
*
|
|
86
|
-
* You attach plugins while configuring the bot. Within one startup phase, their `init()` calls run
|
|
87
|
-
* one after another in attach order.
|
|
88
|
-
*/
|
|
89
|
-
declare abstract class Pluggable<BotT extends Transport, BotRt extends Runtime> implements CoreBase {
|
|
90
|
-
abstract readonly config: Config;
|
|
91
|
-
abstract readonly rest: REST;
|
|
92
|
-
abstract readonly applicationId: string;
|
|
93
|
-
abstract readonly rateLimiter: IRateLimiter;
|
|
94
|
-
abstract readonly bus: Bus;
|
|
95
|
-
/** @internal */
|
|
96
|
-
readonly [HostShutdown]: CoordinatedShutdown;
|
|
97
|
-
/** @internal */
|
|
98
|
-
readonly [HostStartup]: CoordinatedStartup;
|
|
99
|
-
/** Add a task that runs while the bot shuts down. */
|
|
100
|
-
readonly shutdown: Pick<CoordinatedShutdown, 'addTask'>;
|
|
101
|
-
/** Add a task that runs while the bot starts. */
|
|
102
|
-
readonly startup: Pick<CoordinatedStartup, 'addTask'>;
|
|
103
|
-
protected isInitialized: boolean;
|
|
104
|
-
protected startFailed: boolean;
|
|
105
|
-
protected readonly plugins: PluginLike[];
|
|
106
|
-
private readonly groups;
|
|
107
|
-
private readonly pluginLogger;
|
|
108
|
-
private readonly attachments;
|
|
109
|
-
private readonly completedInits;
|
|
110
|
-
private readonly disposePhases;
|
|
111
|
-
private pluginTasksRegistered;
|
|
112
|
-
private initPromise?;
|
|
113
|
-
private static isInstantiated;
|
|
114
|
-
private static liveHost?;
|
|
115
|
-
private static liveShutdown?;
|
|
116
|
-
private static liveProcessErrors?;
|
|
117
|
-
constructor(shutdown: CoordinatedShutdown, startup: CoordinatedStartup);
|
|
118
|
-
/** @internal */
|
|
119
|
-
protected init(): Promise<this>;
|
|
120
|
-
private runInit;
|
|
121
|
-
/** @internal codegen reads this to emit the `Core` augmentation */
|
|
122
|
-
get [HostPluginKeys](): readonly string[];
|
|
123
|
-
/** @internal */
|
|
124
|
-
protected static reset(host?: object): boolean;
|
|
125
|
-
/**
|
|
126
|
-
* Attaches a plugin under `key`. Read the instance back as `core[key]`. `seedcord codegen`
|
|
127
|
-
* writes the `Core` augmentation that types it there.
|
|
128
|
-
*
|
|
129
|
-
* Put one dot in the key to nest the plugin under a group, so `'services.users'` reads back as
|
|
130
|
-
* `core.services.users`. Each name holds one plugin or one group.
|
|
131
|
-
*
|
|
132
|
-
* Startup runs each plugin's `init()` in attach order within its phase.
|
|
133
|
-
*
|
|
134
|
-
* Attaching a plugin whose `transport` or `runtime` differs from this host fails to compile.
|
|
135
|
-
* Your constructor takes `CoreBase` as its first parameter (you don't need to pass it though).
|
|
136
|
-
* A narrower one fails to compile here.
|
|
137
|
-
*
|
|
138
|
-
* @param key - Also the channel the plugin logs on, dots included. Reserved channel names throw.
|
|
139
|
-
* @param args - Whatever your constructor takes after the host.
|
|
140
|
-
* @throws A **SeedcordError** if you attach after the bot has started. A taken or reserved key throws too.
|
|
141
|
-
* So does a plugin that extends `Plugin` from another copy of `@seedcord/core`.
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* seedcord.attach('db', Mongoose, { uri: 'mongodb://...', name: 'seedcord', dir: ... });
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
|
-
attach<Key extends string, Ctor extends PluginCtor>(this: this, key: AttachKeyAssert<Key, this>, Plugin: AttachableCtor<Ctor, BotT, BotRt>, ...args: PluginArgs<Ctor>): this & Attached<Key, InstanceType<Ctor>>;
|
|
148
|
-
private assertFree;
|
|
149
|
-
private groupFor;
|
|
150
|
-
private registerPluginTasks;
|
|
151
|
-
private runInits;
|
|
152
|
-
private disposeWhenInitResolves;
|
|
153
|
-
private registerReadyTask;
|
|
154
|
-
private registerDisposeTask;
|
|
155
|
-
private runDisposals;
|
|
156
|
-
private disposeCompleted;
|
|
157
|
-
private rollback;
|
|
158
|
-
}
|
|
159
|
-
declare function shutdownOf(host: Pick<Pluggable<Transport, Runtime>, typeof HostShutdown>): CoordinatedShutdown;
|
|
160
|
-
//#endregion
|
|
161
|
-
export { LifecycleTask as a, CoordinatedShutdown as i, shutdownOf as n, CoordinatedStartup as r, Pluggable as t };
|
|
162
|
-
//# sourceMappingURL=Pluggable-CwKbLui3.d.mts.map
|
package/dist/Plugin-CmNW5n6a.mjs
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { n as StartupPhase, t as ShutdownPhase } from "./phases-BauKJOTT.mjs";
|
|
2
|
-
import { t as getDevChannel } from "./devChannel-CQU7hq7Q.mjs";
|
|
3
|
-
import { SeedcordErrorCode } from "@seedcord/errors";
|
|
4
|
-
import { SeedcordError, SeedcordRangeError } from "@seedcord/errors/internal";
|
|
5
|
-
import { Logger } from "@seedcord/logger";
|
|
6
|
-
|
|
7
|
-
//#region src/plugin/lifecycle.ts
|
|
8
|
-
const DEFAULT_INIT_TIMEOUT_MS = 15e3;
|
|
9
|
-
const DEFAULT_READY_TIMEOUT_MS = 15e3;
|
|
10
|
-
const DEFAULT_DISPOSE_TIMEOUT_MS = 1e4;
|
|
11
|
-
function timeoutOf(field, declared, fallback, pluginName) {
|
|
12
|
-
if (declared === void 0) return fallback;
|
|
13
|
-
if (!Number.isFinite(declared) || declared <= 0) throw new SeedcordRangeError(SeedcordErrorCode.PluginInvalidLifecycleTimeout, [
|
|
14
|
-
pluginName,
|
|
15
|
-
field,
|
|
16
|
-
declared
|
|
17
|
-
]);
|
|
18
|
-
return declared;
|
|
19
|
-
}
|
|
20
|
-
/** @internal */
|
|
21
|
-
function resolveLifecycleSpec(spec, pluginName) {
|
|
22
|
-
return {
|
|
23
|
-
init: {
|
|
24
|
-
phase: spec?.init?.phase ?? 1,
|
|
25
|
-
timeout: timeoutOf("init", spec?.init?.timeout, DEFAULT_INIT_TIMEOUT_MS, pluginName)
|
|
26
|
-
},
|
|
27
|
-
ready: { timeout: timeoutOf("ready", spec?.ready?.timeout, DEFAULT_READY_TIMEOUT_MS, pluginName) },
|
|
28
|
-
dispose: {
|
|
29
|
-
phase: spec?.dispose?.phase ?? 3,
|
|
30
|
-
timeout: timeoutOf("dispose", spec?.dispose?.timeout, DEFAULT_DISPOSE_TIMEOUT_MS, pluginName)
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/plugin/Plugin.ts
|
|
37
|
-
/** @internal */
|
|
38
|
-
const resolvedSpecSlot = Symbol("seedcord:plugin:spec");
|
|
39
|
-
/** @internal */
|
|
40
|
-
const loggerSlot = Symbol("seedcord:plugin:logger");
|
|
41
|
-
/**
|
|
42
|
-
* Base class for a seedcord plugin. Extend it and implement `init()`. `this.core` is the running
|
|
43
|
-
* bot.
|
|
44
|
-
*
|
|
45
|
-
* Your constructor takes the host first and passes it to `super()`. Add your own parameters after
|
|
46
|
-
* it. `attach()` types them at the call site.
|
|
47
|
-
*
|
|
48
|
-
* @typeParam Opts - Where this plugin may attach, checked only at compile time.
|
|
49
|
-
* @typeParam TCore - The `Core` each transport binds `this.core` to.
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```ts
|
|
53
|
-
* class Analytics extends Plugin<{ transport: 'gateway' }> {
|
|
54
|
-
* constructor(
|
|
55
|
-
* host: CoreBase,
|
|
56
|
-
* private readonly apiKey: string
|
|
57
|
-
* ) {
|
|
58
|
-
* super(host, { init: { phase: StartupPhase.Login } });
|
|
59
|
-
* }
|
|
60
|
-
*
|
|
61
|
-
* public async init(): Promise<void> {
|
|
62
|
-
* await this.connect(this.apiKey);
|
|
63
|
-
* }
|
|
64
|
-
* }
|
|
65
|
-
*
|
|
66
|
-
* seedcord.attach('analytics', Analytics, apiKey);
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
var Plugin = class {
|
|
70
|
-
host;
|
|
71
|
-
/** @internal */
|
|
72
|
-
[resolvedSpecSlot];
|
|
73
|
-
/** @internal */
|
|
74
|
-
[loggerSlot];
|
|
75
|
-
/** Logs under the plugin's class name, on the channel its attach key sets. */
|
|
76
|
-
logger;
|
|
77
|
-
constructor(host, spec) {
|
|
78
|
-
this.host = host;
|
|
79
|
-
this.logger = new Logger(this.constructor.name);
|
|
80
|
-
this[loggerSlot] = this.logger;
|
|
81
|
-
this[resolvedSpecSlot] = resolveLifecycleSpec(spec, this.constructor.name);
|
|
82
|
-
}
|
|
83
|
-
/** The host, typed to the transport whose `Plugin` base this class extends. */
|
|
84
|
-
get core() {
|
|
85
|
-
return this.host;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Throws a `SeedcordError` that contains the plugin class name and the reason.
|
|
89
|
-
*
|
|
90
|
-
* @param reason - Why the options are invalid.
|
|
91
|
-
*/
|
|
92
|
-
rejectOptions(reason) {
|
|
93
|
-
throw new SeedcordError(SeedcordErrorCode.PluginOptionsRejected, [this.constructor.name, reason]);
|
|
94
|
-
}
|
|
95
|
-
/** Override to reload plugin state on an HMR update. */
|
|
96
|
-
onHmr(_event) {
|
|
97
|
-
return Promise.resolve();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Registers critical file patterns that should trigger a full restart when changed in Dev HMR.
|
|
101
|
-
* @param patterns - Glob patterns relative to the project root
|
|
102
|
-
*/
|
|
103
|
-
registerCriticalFiles(patterns) {
|
|
104
|
-
getDevChannel()?.send("seedcord:register-critical-files", { patterns });
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
/** @internal */
|
|
108
|
-
function resolvedLifecycleSpecOf(plugin) {
|
|
109
|
-
return plugin[resolvedSpecSlot];
|
|
110
|
-
}
|
|
111
|
-
/** @internal */
|
|
112
|
-
function extendsThisCorePlugin(ctor) {
|
|
113
|
-
return ctor.prototype instanceof Plugin;
|
|
114
|
-
}
|
|
115
|
-
/** @internal */
|
|
116
|
-
function pluginLoggerOf(plugin) {
|
|
117
|
-
return plugin[loggerSlot];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
//#endregion
|
|
121
|
-
export { resolvedLifecycleSpecOf as i, extendsThisCorePlugin as n, pluginLoggerOf as r, Plugin as t };
|
|
122
|
-
//# sourceMappingURL=Plugin-CmNW5n6a.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Plugin-CmNW5n6a.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 {\n TransportOf,\n PluginOptions,\n RuntimeOf,\n Runtime,\n RuntimeAssert,\n Transport,\n TransportAssert\n} from './options';\nimport type { Tail, FrameworkChannel, 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 /**\n * Runs during teardown, in `ShutdownPhase.Disconnect` by default. seedcord skips it when `init()`\n * has thrown.\n *\n * When `init()` outlasts its timeout, seedcord calls this once that `init()` resolves, outside any\n * shutdown phase. The process must still be alive for that call to happen.\n */\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 extendsThisCorePlugin(ctor: PluginCtor): boolean {\n return ctor.prototype instanceof Plugin;\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\n/** @internal */\nexport type Attached<Key extends string, Instance> = Key extends `${infer Group}.${infer Leaf}`\n ? Record<Group, Record<Leaf, Instance>>\n : Record<Key, Instance>;\n\n// attach writes the key onto the host, so a key like toString would shadow the one on Object.prototype\n// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types -- lint:fix swaps this for `keyof object`, which is never\ntype HostMember<Host> = keyof Host | keyof Object;\n\n// a string argument against an object type renders only as `string is not assignable`\n/** @internal */\nexport type AttachKeyAssert<Key extends string, Host> = Key extends ''\n ? 'A plugin key needs a name.'\n : Key extends `${infer Group}.${infer Leaf}`\n ? Leaf extends `${string}.${string}`\n ? `'${Key}' has more than one dot. A plugin key takes one dot at most.`\n : '' extends Group | Leaf\n ? `'${Key}' has an empty part. Write a group and a plugin name around the dot, like 'services.users'.`\n : Group extends FrameworkChannel\n ? `'${Group}' is a channel the framework logs on. Pick another group name.`\n : Group extends keyof Host\n ? Host[Group] extends PluginLike\n ? `'${Group}' already holds a plugin, so '${Leaf}' cannot nest inside it.`\n : Host[Group] extends Record<string, PluginLike>\n ? Leaf extends keyof Host[Group]\n ? `'${Key}' is already attached.`\n : Key\n : `'${Group}' is already a member on the bot. Pick another group name.`\n : Group extends HostMember<Host>\n ? `'${Group}' is already a member on the bot. Pick another group name.`\n : Key\n : Key extends FrameworkChannel\n ? `'${Key}' is a channel the framework logs on. Pick another plugin key.`\n : Key extends keyof Host\n ? Host[Key] extends PluginLike\n ? `'${Key}' is already attached.`\n : Host[Key] extends Record<string, PluginLike>\n ? `'${Key}' already holds a group of plugins. Attach this one under a name of its own.`\n : `'${Key}' is already a member on the bot. Pick another plugin key.`\n : Key extends HostMember<Host>\n ? `'${Key}' is already a member on the bot. Pick another plugin key.`\n : Key;\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`\ntype CoreParamAssert<Ctor extends PluginCtor> = CoreBase extends ConstructorParameters<Ctor>[0]\n ? unknown\n : CoreParamTooNarrow;\n\ntype AttachAsserts<Ctor extends PluginCtor, BotT extends Transport, BotRt extends Runtime> = TransportAssert<\n InstanceType<Ctor>,\n BotT\n> &\n RuntimeAssert<InstanceType<Ctor>, BotRt> &\n CoreParamAssert<Ctor>;\n\n// typescript can't infer Ctor from a generic class through `Ctor & AttachAsserts`. every assert returns unknown to pass.\n/** @internal */\nexport type AttachableCtor<Ctor extends PluginCtor, BotT extends Transport, BotRt extends Runtime> =\n unknown extends AttachAsserts<Ctor, BotT, BotRt> ? Ctor : AttachAsserts<Ctor, BotT, BotRt>;\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;;;;;AC3CA,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;;;;;;CA8BA,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,sBAAsB,MAA2B;CAC7D,OAAO,KAAK,qBAAqB;AACrC;;AAGA,SAAgB,eAAe,QAA4B;CACvD,OAAO,OAAO;AAClB"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ContextMenuCommandBuilder, SlashCommandBuilder } from "@discordjs/builders";
|
|
2
|
-
//#region src/commands/contextMenuLeaves.d.ts
|
|
3
|
-
/** @internal */
|
|
4
|
-
interface ContextMenuLeaves {
|
|
5
|
-
readonly user: Set<string>;
|
|
6
|
-
readonly message: Set<string>;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* dedupes names across builders, since the same builder repeats once per guild.
|
|
10
|
-
* a user and a message command can share a name.
|
|
11
|
-
*
|
|
12
|
-
* @internal
|
|
13
|
-
*/
|
|
14
|
-
declare function contextMenuLeaves(commands: Iterable<SlashCommandBuilder | ContextMenuCommandBuilder>): ContextMenuLeaves;
|
|
15
|
-
//#endregion
|
|
16
|
-
export { contextMenuLeaves as n, ContextMenuLeaves as t };
|
|
17
|
-
//# sourceMappingURL=contextMenuLeaves-COzDYa6c.d.mts.map
|