@seedcord/http 0.2.3 → 0.3.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 +37 -5
- package/dist/{edge.index-C7y2HWE0.d.mts → edge.index-8mheWe3d.d.mts} +12 -19
- package/dist/{edge.index-7pBw2C-U.mjs → edge.index-CNLml121.mjs} +19 -51
- package/dist/edge.index-CNLml121.mjs.map +1 -0
- package/dist/edge.index.d.mts +3 -3
- package/dist/edge.index.mjs +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +10 -11
- package/dist/index.mjs.map +1 -1
- package/dist/manifest.index.mjs.map +1 -1
- package/package.json +27 -27
- package/dist/edge.index-7pBw2C-U.mjs.map +0 -1
- package/dist/edge.index-CAvykaH6.cjs +0 -1632
- package/dist/edge.index-CAvykaH6.cjs.map +0 -1
- package/dist/edge.index.cjs +0 -68
- package/dist/edge.index.d.cts +0 -1
- package/dist/index.cjs +0 -496
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1
- package/dist/manifest.index.cjs +0 -33
- package/dist/manifest.index.cjs.map +0 -1
- package/dist/manifest.index.d.cts +0 -1
package/dist/index.cjs
DELETED
|
@@ -1,496 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_edge_index = require('./edge.index-CAvykaH6.cjs');
|
|
3
|
-
require("reflect-metadata");
|
|
4
|
-
let _seedcord_errors_internal = require("@seedcord/errors/internal");
|
|
5
|
-
let envapt = require("envapt");
|
|
6
|
-
let _discordjs_rest = require("@discordjs/rest");
|
|
7
|
-
let _seedcord_core = require("@seedcord/core");
|
|
8
|
-
let _seedcord_core_internal = require("@seedcord/core/internal");
|
|
9
|
-
let _seedcord_logger = require("@seedcord/logger");
|
|
10
|
-
let _seedcord_rate_limiter = require("@seedcord/rate-limiter");
|
|
11
|
-
let discord_api_types_v10 = require("discord-api-types/v10");
|
|
12
|
-
let _seedcord_errors = require("@seedcord/errors");
|
|
13
|
-
let _seedcord_utils = require("@seedcord/utils");
|
|
14
|
-
let node_events = require("node:events");
|
|
15
|
-
let node_http = require("node:http");
|
|
16
|
-
let _seedcord_core_node_internal = require("@seedcord/core/node/internal");
|
|
17
|
-
let _seedcord_logger_node = require("@seedcord/logger/node");
|
|
18
|
-
let _seedcord_types_internal = require("@seedcord/types/internal");
|
|
19
|
-
let _seedcord_core_hmr = require("@seedcord/core/hmr");
|
|
20
|
-
let _seedcord_utils_node = require("@seedcord/utils/node");
|
|
21
|
-
let chalk = require("chalk");
|
|
22
|
-
chalk = require_edge_index.__toESM(chalk, 1);
|
|
23
|
-
let _seedcord_core_plugin = require("@seedcord/core/plugin");
|
|
24
|
-
|
|
25
|
-
//#region src/manifest/RouteManifest.ts
|
|
26
|
-
/** @internal */
|
|
27
|
-
const EMPTY_MANIFEST = {
|
|
28
|
-
commandRoutes: [],
|
|
29
|
-
componentRoutes: [],
|
|
30
|
-
autocompleteRoutes: [],
|
|
31
|
-
subscriberRoutes: [],
|
|
32
|
-
middlewareRoutes: []
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/node/InteractionDispatcher.ts
|
|
37
|
-
var InteractionDispatcher = class {
|
|
38
|
-
handlersDir;
|
|
39
|
-
maps;
|
|
40
|
-
targets;
|
|
41
|
-
/** @internal */
|
|
42
|
-
logger = new _seedcord_logger.Logger("Interactions", { channel: "interactions" });
|
|
43
|
-
isInitialized = false;
|
|
44
|
-
hmrHandler;
|
|
45
|
-
rowOwners = /* @__PURE__ */ new Map();
|
|
46
|
-
loading = false;
|
|
47
|
-
loadedHandlers = [];
|
|
48
|
-
constructor(handlersDir) {
|
|
49
|
-
this.handlersDir = handlersDir;
|
|
50
|
-
this.maps = require_edge_index.buildRouteMaps(EMPTY_MANIFEST);
|
|
51
|
-
this.targets = this.buildTargets();
|
|
52
|
-
if (!envapt.Envapter.isDevelopment && !envapt.Envapter.isTest) return;
|
|
53
|
-
this.hmrHandler = new _seedcord_core_hmr.HmrModuleHandler({
|
|
54
|
-
handlersDir,
|
|
55
|
-
isHandler: this.isHandler.bind(this),
|
|
56
|
-
registerHandler: this.registerHandler.bind(this),
|
|
57
|
-
unregisterHandler: this.unregisterHandler.bind(this),
|
|
58
|
-
getArtifacts: this.getArtifacts.bind(this),
|
|
59
|
-
logger: this.logger
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
/** @internal */
|
|
63
|
-
async init() {
|
|
64
|
-
if (this.isInitialized) return;
|
|
65
|
-
this.isInitialized = true;
|
|
66
|
-
this.loading = true;
|
|
67
|
-
this.loadedHandlers.length = 0;
|
|
68
|
-
try {
|
|
69
|
-
await (0, _seedcord_utils_node.traverseDirectory)(this.handlersDir, (fullPath, relativePath, imported) => {
|
|
70
|
-
for (const value of Object.values(imported)) {
|
|
71
|
-
if (!this.isHandler(value)) continue;
|
|
72
|
-
this.registerHandler(value, relativePath);
|
|
73
|
-
this.hmrHandler?.trackHandler(fullPath, value);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
} finally {
|
|
77
|
-
this.loading = false;
|
|
78
|
-
}
|
|
79
|
-
this.logger.utils.block("Loaded handlers", [...this.logger.utils.entries(this.loadedHandlers), ...this.logger.utils.counts({ routes: this.rowOwners.size })], "debug");
|
|
80
|
-
}
|
|
81
|
-
/** @internal */
|
|
82
|
-
async onHmr(event) {
|
|
83
|
-
await this.hmrHandler?.handle(event);
|
|
84
|
-
}
|
|
85
|
-
warnUnhandledRoutes(commandLeaves) {
|
|
86
|
-
this.warnMissing(commandLeaves, this.maps.slash, "Slash route", "@SlashRoute");
|
|
87
|
-
}
|
|
88
|
-
warnUnhandledContextMenuRoutes(leaves) {
|
|
89
|
-
this.warnMissing(leaves.user, this.maps.userContextMenu, "User context menu", "@ContextMenuRoute");
|
|
90
|
-
this.warnMissing(leaves.message, this.maps.messageContextMenu, "Message context menu", "@ContextMenuRoute");
|
|
91
|
-
}
|
|
92
|
-
warnMissing(names, map, label, decorator) {
|
|
93
|
-
for (const name of names) {
|
|
94
|
-
if (map.has(name)) continue;
|
|
95
|
-
this.logger.warn(`${label} ${_seedcord_logger.paint.sky.bold(name)} has no registered ${chalk.default.bold(decorator)} handler.`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
isHandler(value) {
|
|
99
|
-
if (typeof value !== "function") return false;
|
|
100
|
-
return (value.prototype instanceof require_edge_index.InteractionHandler || value.prototype instanceof require_edge_index.AutocompleteHandler) && Reflect.hasMetadata(_seedcord_core_internal.InteractionMetadataKey, value);
|
|
101
|
-
}
|
|
102
|
-
getArtifacts(ctor) {
|
|
103
|
-
const routeIds = [];
|
|
104
|
-
for (const [routeId, owner] of this.rowOwners) if (owner.ctor === ctor) routeIds.push(routeId);
|
|
105
|
-
return routeIds;
|
|
106
|
-
}
|
|
107
|
-
targetFor(route) {
|
|
108
|
-
return this.targets[route];
|
|
109
|
-
}
|
|
110
|
-
buildTargets() {
|
|
111
|
-
return {
|
|
112
|
-
[_seedcord_core_internal.InteractionRoutes.Slash]: {
|
|
113
|
-
map: this.maps.slash,
|
|
114
|
-
kind: "slash"
|
|
115
|
-
},
|
|
116
|
-
[_seedcord_core_internal.InteractionRoutes.UserContextMenu]: {
|
|
117
|
-
map: this.maps.userContextMenu,
|
|
118
|
-
kind: "userContextMenu"
|
|
119
|
-
},
|
|
120
|
-
[_seedcord_core_internal.InteractionRoutes.MessageContextMenu]: {
|
|
121
|
-
map: this.maps.messageContextMenu,
|
|
122
|
-
kind: "messageContextMenu"
|
|
123
|
-
},
|
|
124
|
-
[_seedcord_core_internal.InteractionRoutes.Autocomplete]: {
|
|
125
|
-
map: this.maps.autocomplete,
|
|
126
|
-
kind: "autocomplete"
|
|
127
|
-
},
|
|
128
|
-
[_seedcord_core_internal.InteractionRoutes.Button]: {
|
|
129
|
-
map: this.maps.components.button,
|
|
130
|
-
kind: "button"
|
|
131
|
-
},
|
|
132
|
-
[_seedcord_core_internal.InteractionRoutes.StringMenu]: {
|
|
133
|
-
map: this.maps.components.stringSelect,
|
|
134
|
-
kind: "stringMenu"
|
|
135
|
-
},
|
|
136
|
-
[_seedcord_core_internal.InteractionRoutes.UserMenu]: {
|
|
137
|
-
map: this.maps.components.userSelect,
|
|
138
|
-
kind: "userMenu"
|
|
139
|
-
},
|
|
140
|
-
[_seedcord_core_internal.InteractionRoutes.RoleMenu]: {
|
|
141
|
-
map: this.maps.components.roleSelect,
|
|
142
|
-
kind: "roleMenu"
|
|
143
|
-
},
|
|
144
|
-
[_seedcord_core_internal.InteractionRoutes.ChannelMenu]: {
|
|
145
|
-
map: this.maps.components.channelSelect,
|
|
146
|
-
kind: "channelMenu"
|
|
147
|
-
},
|
|
148
|
-
[_seedcord_core_internal.InteractionRoutes.MentionableMenu]: {
|
|
149
|
-
map: this.maps.components.mentionableSelect,
|
|
150
|
-
kind: "mentionableMenu"
|
|
151
|
-
},
|
|
152
|
-
[_seedcord_core_internal.InteractionRoutes.Modal]: {
|
|
153
|
-
map: this.maps.components.modal,
|
|
154
|
-
kind: "modal"
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
registerHandler(ctor, relativePath) {
|
|
159
|
-
const from = (0, _seedcord_utils.formatFilePath)(relativePath);
|
|
160
|
-
const writes = [];
|
|
161
|
-
for (const [route, keys] of (0, _seedcord_core_internal.interactionRoutesOf)(ctor)) {
|
|
162
|
-
const target = this.targetFor(route);
|
|
163
|
-
for (const key of keys) {
|
|
164
|
-
const routeId = `${target.kind}:${key}`;
|
|
165
|
-
const existing = this.rowOwners.get(routeId);
|
|
166
|
-
if (existing && existing.ctor !== ctor) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.InteractionDuplicateRoute, [
|
|
167
|
-
routeId,
|
|
168
|
-
`${existing.ctor.name} (${existing.from})`,
|
|
169
|
-
`${ctor.name} (${from})`
|
|
170
|
-
]);
|
|
171
|
-
writes.push([target, key]);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (writes.length === 0) return;
|
|
175
|
-
for (const [target, key] of writes) {
|
|
176
|
-
const routeId = `${target.kind}:${key}`;
|
|
177
|
-
target.map.set(key, {
|
|
178
|
-
kind: target.kind,
|
|
179
|
-
routeId,
|
|
180
|
-
load: () => Promise.resolve(ctor)
|
|
181
|
-
});
|
|
182
|
-
this.rowOwners.set(routeId, {
|
|
183
|
-
ctor,
|
|
184
|
-
target,
|
|
185
|
-
key,
|
|
186
|
-
from
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
if (this.loading) this.loadedHandlers.push({
|
|
190
|
-
name: ctor.name,
|
|
191
|
-
from
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
unregisterHandler(ctor, artifacts) {
|
|
195
|
-
const routeIds = artifacts ?? this.getArtifacts(ctor);
|
|
196
|
-
for (const routeId of routeIds) {
|
|
197
|
-
const owner = this.rowOwners.get(routeId);
|
|
198
|
-
if (owner?.ctor !== ctor) continue;
|
|
199
|
-
this.rowOwners.delete(routeId);
|
|
200
|
-
owner.target.map.delete(owner.key);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
//#endregion
|
|
206
|
-
//#region src/node/webBridge.ts
|
|
207
|
-
function toHeaders(raw) {
|
|
208
|
-
const headers = new Headers();
|
|
209
|
-
for (const [name, value] of Object.entries(raw)) {
|
|
210
|
-
if (value === void 0) continue;
|
|
211
|
-
if (Array.isArray(value)) for (const item of value) headers.append(name, item);
|
|
212
|
-
else headers.set(name, value);
|
|
213
|
-
}
|
|
214
|
-
return headers;
|
|
215
|
-
}
|
|
216
|
-
async function toWebRequest(request) {
|
|
217
|
-
const chunks = [];
|
|
218
|
-
for await (const chunk of request) chunks.push(chunk);
|
|
219
|
-
const method = request.method ?? "GET";
|
|
220
|
-
const body = method === "GET" || method === "HEAD" ? void 0 : new Uint8Array(Buffer.concat(chunks));
|
|
221
|
-
return new Request(`http://${request.headers.host ?? "localhost"}${request.url ?? "/"}`, {
|
|
222
|
-
method,
|
|
223
|
-
headers: toHeaders(request.headers),
|
|
224
|
-
...body !== void 0 && { body }
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
async function writeWebResponse(response, out) {
|
|
228
|
-
const headers = Object.fromEntries(response.headers);
|
|
229
|
-
const cookies = response.headers.getSetCookie();
|
|
230
|
-
if (cookies.length > 0) headers["set-cookie"] = cookies;
|
|
231
|
-
out.writeHead(response.status, headers);
|
|
232
|
-
out.end(response.body === null ? void 0 : Buffer.from(await response.arrayBuffer()));
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
//#endregion
|
|
236
|
-
//#region src/node/Seedcord.ts
|
|
237
|
-
const DEFAULT_PORT = 3e3;
|
|
238
|
-
const SERVER_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
239
|
-
const DRAIN_TIMEOUT_MS = 1e4;
|
|
240
|
-
/**
|
|
241
|
-
* The HTTP-interactions bot host, a long-running node server around the engine.
|
|
242
|
-
*
|
|
243
|
-
* Discovers handlers from `config.bot.interactions.path`, verifies and dispatches interactions on
|
|
244
|
-
* `start()`, and runs coordinated shutdown with an in-flight drain. The edge deploy path calls
|
|
245
|
-
* `createSeedcord` from a generated entry.
|
|
246
|
-
*/
|
|
247
|
-
var Seedcord = class Seedcord extends _seedcord_core_node_internal.Pluggable {
|
|
248
|
-
config;
|
|
249
|
-
/** @internal */
|
|
250
|
-
[_seedcord_types_internal.SeedcordBrand] = true;
|
|
251
|
-
/** @internal */
|
|
252
|
-
augmentTarget = "@seedcord/http";
|
|
253
|
-
/** @internal */
|
|
254
|
-
version = require_edge_index.version;
|
|
255
|
-
/** Workerd-compatible Discord REST client. `start()` sets the token. */
|
|
256
|
-
rest = new _discordjs_rest.REST();
|
|
257
|
-
/** @see {@link IRateLimiter} */
|
|
258
|
-
rateLimiter;
|
|
259
|
-
/** @see {@link Bus} */
|
|
260
|
-
bus;
|
|
261
|
-
subscribers;
|
|
262
|
-
interactions;
|
|
263
|
-
commandRegistry;
|
|
264
|
-
appId;
|
|
265
|
-
appIdPromise;
|
|
266
|
-
emojiInjector = new require_edge_index.EmojiInjector(this, () => this.applicationId());
|
|
267
|
-
hmrManager;
|
|
268
|
-
logger = new _seedcord_logger.Logger("Server", { channel: "bot" });
|
|
269
|
-
server;
|
|
270
|
-
boundPort;
|
|
271
|
-
fetchedUsername;
|
|
272
|
-
constructor(config) {
|
|
273
|
-
super(new _seedcord_core_node_internal.CoordinatedShutdown(), new _seedcord_core_node_internal.CoordinatedStartup());
|
|
274
|
-
this.config = config;
|
|
275
|
-
(0, _seedcord_logger_node.installNodeDefaults)(config.logger);
|
|
276
|
-
(0, _seedcord_core_internal.setBotColor)(config.botColor);
|
|
277
|
-
this.hmrManager = new _seedcord_core_internal.HmrManager();
|
|
278
|
-
this.hmrManager.init();
|
|
279
|
-
if (this.config.bot.interactions.path) this.interactions = new InteractionDispatcher(this.config.bot.interactions.path);
|
|
280
|
-
const commandsDir = this.config.bot.commands.path;
|
|
281
|
-
if (commandsDir) {
|
|
282
|
-
const injector = new _seedcord_core_internal.CommandInjector();
|
|
283
|
-
const registry = new _seedcord_core_node_internal.CommandRegistry({
|
|
284
|
-
dir: commandsDir,
|
|
285
|
-
rest: this.rest,
|
|
286
|
-
applicationId: () => this.requireApplicationId(),
|
|
287
|
-
onDeployed: (result) => {
|
|
288
|
-
injector.inject(result, registry.allCommands());
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
this.commandRegistry = registry;
|
|
292
|
-
}
|
|
293
|
-
this.rateLimiter = config.store ?? new _seedcord_rate_limiter.MemoryRateLimiter();
|
|
294
|
-
this.bus = new _seedcord_core.Bus(this);
|
|
295
|
-
this.subscribers = new _seedcord_core_node_internal.SubscriberLoader(this.bus, config.subscribers.path);
|
|
296
|
-
this.registerStartupTasks();
|
|
297
|
-
}
|
|
298
|
-
/** The bot's discord username, populated by the ready fetch. */
|
|
299
|
-
get username() {
|
|
300
|
-
return this.fetchedUsername;
|
|
301
|
-
}
|
|
302
|
-
/** The bound server port, populated once `start()` is listening. */
|
|
303
|
-
get port() {
|
|
304
|
-
return this.boundPort;
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Starts the host and runs the startup tasks.
|
|
308
|
-
*/
|
|
309
|
-
async start() {
|
|
310
|
-
try {
|
|
311
|
-
await super.init();
|
|
312
|
-
} catch (caught) {
|
|
313
|
-
await this.shutdown.run(1, false);
|
|
314
|
-
Seedcord.reset();
|
|
315
|
-
throw caught;
|
|
316
|
-
}
|
|
317
|
-
return this;
|
|
318
|
-
}
|
|
319
|
-
static reset() {
|
|
320
|
-
super.reset();
|
|
321
|
-
_seedcord_logger.LoggerChannelRegistry.instance.configure({});
|
|
322
|
-
}
|
|
323
|
-
registerStartupTasks() {
|
|
324
|
-
if (envapt.Envapter.isDevelopment || envapt.Envapter.isTest) this.registerHmrAwareModules();
|
|
325
|
-
this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Configuration, "bus-initialization", async () => {
|
|
326
|
-
this.bus.logger.utils.initialization("Subscribers", "start");
|
|
327
|
-
await this.subscribers.init();
|
|
328
|
-
this.bus.logger.utils.initialization("Subscribers", "end");
|
|
329
|
-
});
|
|
330
|
-
const { interactions } = this;
|
|
331
|
-
if (interactions) this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Configuration, "interactions-initialization", async () => {
|
|
332
|
-
interactions.logger.utils.initialization("Interactions", "start");
|
|
333
|
-
await interactions.init();
|
|
334
|
-
interactions.logger.utils.initialization("Interactions", "end");
|
|
335
|
-
});
|
|
336
|
-
this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Configuration, "authenticate", () => {
|
|
337
|
-
this.authenticate();
|
|
338
|
-
return Promise.resolve();
|
|
339
|
-
});
|
|
340
|
-
this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Login, "emoji-injection", () => this.emojiInjector.init());
|
|
341
|
-
const { commandRegistry } = this;
|
|
342
|
-
if (commandRegistry) this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Login, "command-deploy", async () => {
|
|
343
|
-
await commandRegistry.init();
|
|
344
|
-
this.appId = await this.applicationId();
|
|
345
|
-
await commandRegistry.setCommands();
|
|
346
|
-
interactions?.warnUnhandledRoutes(commandRegistry.routeLeaves());
|
|
347
|
-
interactions?.warnUnhandledContextMenuRoutes(commandRegistry.contextMenuLeaves());
|
|
348
|
-
});
|
|
349
|
-
this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Ready, "http-server", () => this.listen());
|
|
350
|
-
if (!envapt.Envapter.isTest) this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Ready, "identity", () => this.fetchUsername());
|
|
351
|
-
}
|
|
352
|
-
registerHmrAwareModules() {
|
|
353
|
-
this.startup.addTask(_seedcord_core_node_internal.StartupPhase.Configuration, "hmr-registration", async () => {
|
|
354
|
-
if (this.interactions) this.hmrManager.register(this.interactions);
|
|
355
|
-
if (this.commandRegistry) this.hmrManager.register(this.commandRegistry);
|
|
356
|
-
this.hmrManager.register(this.subscribers);
|
|
357
|
-
for (const plugin of this.plugins) this.hmrManager.register(plugin);
|
|
358
|
-
await Promise.resolve();
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
authenticate() {
|
|
362
|
-
this.rest.setToken((0, _seedcord_errors_internal.validateDiscordToken)(envapt.Envapter.get("DISCORD_BOT_TOKEN")));
|
|
363
|
-
}
|
|
364
|
-
applicationId() {
|
|
365
|
-
this.appIdPromise ??= require_edge_index.fetchApplicationId(this.rest);
|
|
366
|
-
return this.appIdPromise;
|
|
367
|
-
}
|
|
368
|
-
requireApplicationId() {
|
|
369
|
-
if (!this.appId) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CoreApplicationUnavailable);
|
|
370
|
-
return this.appId;
|
|
371
|
-
}
|
|
372
|
-
async listen() {
|
|
373
|
-
const maps = this.interactions?.maps ?? require_edge_index.buildRouteMaps(EMPTY_MANIFEST);
|
|
374
|
-
const { handle, inFlight } = require_edge_index.buildEngine(this, maps);
|
|
375
|
-
const server = (0, node_http.createServer)((incoming, outgoing) => {
|
|
376
|
-
(async () => {
|
|
377
|
-
const response = await handle(await toWebRequest(incoming));
|
|
378
|
-
await writeWebResponse(response, outgoing);
|
|
379
|
-
})().catch((error) => {
|
|
380
|
-
outgoing.destroy(Error.isError(error) ? error : new Error(String(error)));
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
this.server = server;
|
|
384
|
-
server.listen(this.config.port ?? DEFAULT_PORT);
|
|
385
|
-
await (0, node_events.once)(server, "listening");
|
|
386
|
-
this.boundPort = server.address().port;
|
|
387
|
-
this.logger.info(`Interactions server listening on port ${_seedcord_logger.paint.sky.bold(String(this.boundPort))}`);
|
|
388
|
-
(0, _seedcord_core_internal.getDevChannel)()?.send("seedcord:server-listening", { port: this.boundPort });
|
|
389
|
-
this.shutdown.addTask(_seedcord_core_node_internal.ShutdownPhase.Unbind, "stop-http-server", () => this.stopServer(), SERVER_SHUTDOWN_TIMEOUT_MS);
|
|
390
|
-
this.shutdown.addTask(_seedcord_core_node_internal.ShutdownPhase.Drain, "drain-inflight", async () => {
|
|
391
|
-
await Promise.allSettled(inFlight);
|
|
392
|
-
}, DRAIN_TIMEOUT_MS);
|
|
393
|
-
}
|
|
394
|
-
async fetchUsername() {
|
|
395
|
-
try {
|
|
396
|
-
const me = await this.rest.get(discord_api_types_v10.Routes.user("@me"));
|
|
397
|
-
this.fetchedUsername = me.username;
|
|
398
|
-
if (me.username) this.logger.info(`Running as ${_seedcord_logger.paint.iris.bold(me.username)}`);
|
|
399
|
-
} catch (caught) {
|
|
400
|
-
this.logger.warn("could not fetch the bot identity", caught);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
stopServer() {
|
|
404
|
-
const server = this.server;
|
|
405
|
-
if (!server?.listening) return Promise.resolve();
|
|
406
|
-
return new Promise((resolveClose, rejectClose) => {
|
|
407
|
-
server.close((err) => {
|
|
408
|
-
if (err) {
|
|
409
|
-
rejectClose(err);
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
this.logger.info(_seedcord_logger.paint.coral.bold("Interactions server stopped"));
|
|
413
|
-
resolveClose();
|
|
414
|
-
});
|
|
415
|
-
server.closeIdleConnections();
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
//#endregion
|
|
421
|
-
//#region src/plugin.ts
|
|
422
|
-
/**
|
|
423
|
-
* Base class for an HTTP plugin, binding `this.core` to the HTTP {@link Core}.
|
|
424
|
-
*
|
|
425
|
-
* A plugin that runs on either transport extends the base from `@seedcord/core/plugin`, whose
|
|
426
|
-
* `this.core` is typed to the shared members only.
|
|
427
|
-
*
|
|
428
|
-
* @typeParam Opts - The transport and runtime the plugin declares.
|
|
429
|
-
*/
|
|
430
|
-
var Plugin = class extends _seedcord_core_plugin.Plugin {};
|
|
431
|
-
|
|
432
|
-
//#endregion
|
|
433
|
-
exports.ArraySource = require_edge_index.ArraySource;
|
|
434
|
-
exports.AutocompleteHandler = require_edge_index.AutocompleteHandler;
|
|
435
|
-
exports.ButtonHandler = require_edge_index.ButtonHandler;
|
|
436
|
-
exports.ComponentHandler = require_edge_index.ComponentHandler;
|
|
437
|
-
exports.ContextMenuHandler = require_edge_index.ContextMenuHandler;
|
|
438
|
-
exports.CursorSource = require_edge_index.CursorSource;
|
|
439
|
-
exports.Emojis = require_edge_index.Emojis;
|
|
440
|
-
exports.Gated = require_edge_index.Gated;
|
|
441
|
-
exports.InteractionHandler = require_edge_index.InteractionHandler;
|
|
442
|
-
exports.ModalHandler = require_edge_index.ModalHandler;
|
|
443
|
-
exports.Paginator = require_edge_index.Paginator;
|
|
444
|
-
exports.Plugin = Plugin;
|
|
445
|
-
exports.RepliableHandler = require_edge_index.RepliableHandler;
|
|
446
|
-
exports.Seedcord = Seedcord;
|
|
447
|
-
exports.SelectMenuHandler = require_edge_index.SelectMenuHandler;
|
|
448
|
-
exports.SlashHandler = require_edge_index.SlashHandler;
|
|
449
|
-
exports.Subscriber = require_edge_index.Subscriber;
|
|
450
|
-
exports.WebhookLog = require_edge_index.WebhookLog;
|
|
451
|
-
exports.createSeedcord = require_edge_index.createSeedcord;
|
|
452
|
-
exports.version = require_edge_index.version;
|
|
453
|
-
Object.keys(_seedcord_core).forEach(function (k) {
|
|
454
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
455
|
-
enumerable: true,
|
|
456
|
-
get: function () { return _seedcord_core[k]; }
|
|
457
|
-
});
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
Object.keys(_seedcord_logger).forEach(function (k) {
|
|
461
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
462
|
-
enumerable: true,
|
|
463
|
-
get: function () { return _seedcord_logger[k]; }
|
|
464
|
-
});
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
Object.keys(_seedcord_rate_limiter).forEach(function (k) {
|
|
468
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
469
|
-
enumerable: true,
|
|
470
|
-
get: function () { return _seedcord_rate_limiter[k]; }
|
|
471
|
-
});
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
Object.keys(_seedcord_errors).forEach(function (k) {
|
|
475
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
476
|
-
enumerable: true,
|
|
477
|
-
get: function () { return _seedcord_errors[k]; }
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
var _seedcord_event_emitter = require("@seedcord/event-emitter");
|
|
482
|
-
Object.keys(_seedcord_event_emitter).forEach(function (k) {
|
|
483
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
484
|
-
enumerable: true,
|
|
485
|
-
get: function () { return _seedcord_event_emitter[k]; }
|
|
486
|
-
});
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
Object.keys(_seedcord_utils).forEach(function (k) {
|
|
490
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
491
|
-
enumerable: true,
|
|
492
|
-
get: function () { return _seedcord_utils[k]; }
|
|
493
|
-
});
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Logger","buildRouteMaps","Envapter","HmrModuleHandler","traverseDirectory","paint","InteractionHandler","AutocompleteHandler","InteractionMetadataKey","InteractionRoutes","formatFilePath","interactionRoutesOf","SeedcordError","SeedcordErrorCode","Pluggable","SeedcordBrand","packageVersion","REST","EmojiInjector","Logger","CoordinatedShutdown","CoordinatedStartup","HmrManager","CommandInjector","CommandRegistry","MemoryRateLimiter","Bus","SubscriberLoader","Envapter","StartupPhase","validateDiscordToken","fetchApplicationId","SeedcordError","SeedcordErrorCode","buildRouteMaps","buildEngine","createServer","once","paint","ShutdownPhase","Routes","CorePlugin"],"sources":["../src/manifest/RouteManifest.ts","../src/node/InteractionDispatcher.ts","../src/node/webBridge.ts","../src/node/Seedcord.ts","../src/plugin.ts"],"sourcesContent":["import type { SelectMenuKind, SubscriptionKey } from '@seedcord/core';\nimport type { EventFrequency } from '@seedcord/types';\nimport type { ApplicationCommandType } from 'discord-api-types/v10';\n\n/** The command kinds a manifest row registers, the wire enum's other members have no handler base. */\ntype RegistrableCommandType =\n ApplicationCommandType.ChatInput | ApplicationCommandType.User | ApplicationCommandType.Message;\n\n/** One file may export several handlers. */\nexport interface RouteModule {\n /** The exported binding inside the loaded module. */\n readonly exportName: string;\n /** The source file the row came from, reported when the export is missing. */\n readonly from: string;\n /** Lazy import of the module, evaluated on first hit. */\n readonly load: () => Promise<Record<string, unknown>>;\n}\n\n/**\n * A slash or context-menu command row. `type` picks the per-kind map, `name` is the lookup key. For a\n * chat-input command with subcommands, `name` is the full route path (`'config/set'`), the same key\n * `@SlashRoute` registers.\n */\ninterface CommandRoute extends RouteModule {\n readonly name: string;\n readonly type: RegistrableCommandType;\n}\n\n/**\n * A button, select, or modal row. `kind` picks the per-kind map, `prefix` is the stable customId prefix\n * the receiver routes by (the routeKey minus its layout hash).\n */\nexport interface ComponentRoute extends RouteModule {\n readonly kind: 'button' | `${SelectMenuKind}Select` | 'modal';\n readonly prefix: string;\n}\n\n/**\n * An autocomplete row, its own route keyed by the command's route path, separate from the slash row.\n */\ninterface AutocompleteRoute extends RouteModule {\n readonly name: string;\n}\n\n/**\n * A bus subscriber row. The Bus registers it without importing the subscriber module, and resolves the\n * class on the first publish of one of its keys.\n */\ninterface SubscriberRoute extends RouteModule {\n /** The subscription keys this subscriber registers for. */\n readonly keys: readonly SubscriptionKey[];\n /** Mirrors the `@Subscribe` frequency metadata. */\n readonly frequency: EventFrequency;\n}\n\n/** A middleware row. Middleware runs on every dispatch. */\ntype MiddlewareRoute = RouteModule;\n\n/**\n * The static route table the HTTP engine dispatches through, replacing the filesystem handler scan that\n * cannot run in a bundled isolate. `seedcord build` emits it, the mount path authors it by hand.\n */\nexport interface RouteManifest {\n readonly commandRoutes: readonly CommandRoute[];\n readonly componentRoutes: readonly ComponentRoute[];\n readonly autocompleteRoutes: readonly AutocompleteRoute[];\n readonly subscriberRoutes: readonly SubscriberRoute[];\n readonly middlewareRoutes: readonly MiddlewareRoute[];\n}\n\n/** @internal */\nexport const EMPTY_MANIFEST: RouteManifest = {\n commandRoutes: [],\n componentRoutes: [],\n autocompleteRoutes: [],\n subscriberRoutes: [],\n middlewareRoutes: []\n};\n","import { HmrModuleHandler } from '@seedcord/core/hmr';\nimport { interactionRoutesOf, InteractionMetadataKey, InteractionRoutes } from '@seedcord/core/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger, paint } from '@seedcord/logger';\nimport { formatFilePath } from '@seedcord/utils';\nimport { traverseDirectory } from '@seedcord/utils/node';\nimport chalk from 'chalk';\nimport { Envapter } from 'envapt';\n\nimport { AutocompleteHandler } from '@handlers/interaction/AutocompleteHandler';\nimport { InteractionHandler } from '@handlers/interaction/InteractionHandler';\nimport { buildRouteMaps } from '@src/dispatch/resolve';\nimport { EMPTY_MANIFEST } from '@src/manifest/RouteManifest';\n\nimport type { HandlerConstructor } from '@handlers/constructors';\nimport type { Initializeable } from '@seedcord/core';\nimport type { ContextMenuLeaves } from '@seedcord/core/internal';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { ResolvedRoute, RouteMap, RouteMaps } from '@src/dispatch/resolve';\n\ninterface RouteTarget {\n readonly map: RouteMap;\n readonly kind: ResolvedRoute['kind'];\n}\n\n// hmr swaps entries live and resolve() reads per request, but edge builds from manifest instead\nexport class InteractionDispatcher implements Initializeable, HmrAware {\n public readonly maps: RouteMaps;\n private readonly targets: Record<InteractionRoutes, RouteTarget>;\n\n /** @internal */\n public readonly logger = new Logger('Interactions', { channel: 'interactions' });\n\n private isInitialized = false;\n private readonly hmrHandler?: HmrModuleHandler<HandlerConstructor, void, string[]>;\n // routeId -> owner row, the duplicate guard and the hmr unregister index\n private readonly rowOwners = new Map<\n string,\n { ctor: HandlerConstructor; target: RouteTarget; key: string; from: string }\n >();\n\n private loading = false;\n private readonly loadedHandlers: { name: string; from: string }[] = [];\n\n constructor(private readonly handlersDir: string) {\n this.maps = buildRouteMaps(EMPTY_MANIFEST);\n this.targets = this.buildTargets();\n\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n this.hmrHandler = new HmrModuleHandler({\n handlersDir,\n isHandler: this.isHandler.bind(this),\n registerHandler: this.registerHandler.bind(this),\n unregisterHandler: this.unregisterHandler.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: this.logger\n });\n }\n\n /** @internal */\n public async init(): Promise<void> {\n if (this.isInitialized) return;\n this.isInitialized = true;\n\n this.loading = true;\n this.loadedHandlers.length = 0;\n try {\n await traverseDirectory(this.handlersDir, (fullPath, relativePath, imported) => {\n for (const value of Object.values(imported)) {\n if (!this.isHandler(value)) continue;\n this.registerHandler(value, relativePath);\n this.hmrHandler?.trackHandler(fullPath, value);\n }\n });\n } finally {\n this.loading = false;\n }\n\n this.logger.utils.block(\n 'Loaded handlers',\n [\n ...this.logger.utils.entries(this.loadedHandlers),\n ...this.logger.utils.counts({ routes: this.rowOwners.size })\n ],\n 'debug'\n );\n }\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n await this.hmrHandler?.handle(event);\n }\n\n public warnUnhandledRoutes(commandLeaves: Iterable<string>): void {\n this.warnMissing(commandLeaves, this.maps.slash, 'Slash route', '@SlashRoute');\n }\n\n public warnUnhandledContextMenuRoutes(leaves: ContextMenuLeaves): void {\n this.warnMissing(leaves.user, this.maps.userContextMenu, 'User context menu', '@ContextMenuRoute');\n this.warnMissing(leaves.message, this.maps.messageContextMenu, 'Message context menu', '@ContextMenuRoute');\n }\n\n private warnMissing(names: Iterable<string>, map: RouteMap, label: string, decorator: string): void {\n for (const name of names) {\n if (map.has(name)) continue;\n this.logger.warn(`${label} ${paint.sky.bold(name)} has no registered ${chalk.bold(decorator)} handler.`);\n }\n }\n\n private isHandler(value: unknown): value is HandlerConstructor {\n if (typeof value !== 'function') return false;\n // this package's own family bases, so a gateway handler in the same dir stays unregistered\n return (\n (value.prototype instanceof InteractionHandler || value.prototype instanceof AutocompleteHandler) &&\n Reflect.hasMetadata(InteractionMetadataKey, value)\n );\n }\n\n private getArtifacts(ctor: HandlerConstructor): string[] {\n const routeIds: string[] = [];\n for (const [routeId, owner] of this.rowOwners) {\n if (owner.ctor === ctor) routeIds.push(routeId);\n }\n return routeIds;\n }\n\n private targetFor(route: InteractionRoutes): RouteTarget {\n return this.targets[route];\n }\n\n private buildTargets(): Record<InteractionRoutes, RouteTarget> {\n return {\n [InteractionRoutes.Slash]: { map: this.maps.slash, kind: 'slash' },\n [InteractionRoutes.UserContextMenu]: { map: this.maps.userContextMenu, kind: 'userContextMenu' },\n [InteractionRoutes.MessageContextMenu]: { map: this.maps.messageContextMenu, kind: 'messageContextMenu' },\n [InteractionRoutes.Autocomplete]: { map: this.maps.autocomplete, kind: 'autocomplete' },\n [InteractionRoutes.Button]: { map: this.maps.components.button, kind: 'button' },\n [InteractionRoutes.StringMenu]: { map: this.maps.components.stringSelect, kind: 'stringMenu' },\n [InteractionRoutes.UserMenu]: { map: this.maps.components.userSelect, kind: 'userMenu' },\n [InteractionRoutes.RoleMenu]: { map: this.maps.components.roleSelect, kind: 'roleMenu' },\n [InteractionRoutes.ChannelMenu]: { map: this.maps.components.channelSelect, kind: 'channelMenu' },\n [InteractionRoutes.MentionableMenu]: {\n map: this.maps.components.mentionableSelect,\n kind: 'mentionableMenu'\n },\n [InteractionRoutes.Modal]: { map: this.maps.components.modal, kind: 'modal' }\n };\n }\n\n private registerHandler(ctor: HandlerConstructor, relativePath: string): void {\n const from = formatFilePath(relativePath);\n // a partial registration would orphan routes and break hmr rollback\n const writes: [RouteTarget, string][] = [];\n\n for (const [route, keys] of interactionRoutesOf(ctor)) {\n const target = this.targetFor(route);\n for (const key of keys) {\n const routeId = `${target.kind}:${key}`;\n const existing = this.rowOwners.get(routeId);\n // a different class on the same route silently shadows the existing one (last write wins)\n if (existing && existing.ctor !== ctor) {\n throw new SeedcordError(SeedcordErrorCode.InteractionDuplicateRoute, [\n routeId,\n `${existing.ctor.name} (${existing.from})`,\n `${ctor.name} (${from})`\n ]);\n }\n writes.push([target, key]);\n }\n }\n\n if (writes.length === 0) return;\n for (const [target, key] of writes) {\n const routeId = `${target.kind}:${key}`;\n target.map.set(key, { kind: target.kind, routeId, load: () => Promise.resolve(ctor) });\n this.rowOwners.set(routeId, { ctor, target, key, from });\n }\n\n if (this.loading) this.loadedHandlers.push({ name: ctor.name, from });\n }\n\n private unregisterHandler(ctor: HandlerConstructor, artifacts?: string[]): void {\n const routeIds = artifacts ?? this.getArtifacts(ctor);\n for (const routeId of routeIds) {\n const owner = this.rowOwners.get(routeId);\n if (owner?.ctor !== ctor) continue;\n this.rowOwners.delete(routeId);\n owner.target.map.delete(owner.key);\n }\n }\n}\n","import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';\n\nfunction toHeaders(raw: IncomingHttpHeaders): Headers {\n const headers = new Headers();\n for (const [name, value] of Object.entries(raw)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) headers.append(name, item);\n } else {\n headers.set(name, value);\n }\n }\n return headers;\n}\n\n// buffers the raw body before any parse so ed25519 verifies the exact signed bytes\nexport async function toWebRequest(request: IncomingMessage): Promise<Request> {\n const chunks: Buffer[] = [];\n // justified: the async iterator is typed any and IncomingMessage yields Buffer chunks\n for await (const chunk of request) chunks.push(chunk as Buffer);\n\n const method = request.method ?? 'GET';\n const body = method === 'GET' || method === 'HEAD' ? undefined : new Uint8Array(Buffer.concat(chunks));\n\n return new Request(`http://${request.headers.host ?? 'localhost'}${request.url ?? '/'}`, {\n method,\n headers: toHeaders(request.headers),\n ...(body !== undefined && { body })\n });\n}\n\nexport async function writeWebResponse(response: Response, out: ServerResponse): Promise<void> {\n const headers: Record<string, string | string[]> = Object.fromEntries(response.headers);\n // iterating Headers comma-joins same-name values, which corrupts Set-Cookie (a per-cookie header)\n const cookies = response.headers.getSetCookie();\n if (cookies.length > 0) headers['set-cookie'] = cookies;\n\n out.writeHead(response.status, headers);\n out.end(response.body === null ? undefined : Buffer.from(await response.arrayBuffer()));\n}\n","import { once } from 'node:events';\nimport { createServer } from 'node:http';\n\nimport { REST } from '@discordjs/rest';\nimport { Bus } from '@seedcord/core';\nimport { CommandInjector, getDevChannel, HmrManager, setBotColor } from '@seedcord/core/internal';\nimport {\n CommandRegistry,\n CoordinatedShutdown,\n CoordinatedStartup,\n Pluggable,\n ShutdownPhase,\n StartupPhase,\n SubscriberLoader\n} from '@seedcord/core/node/internal';\nimport { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError, validateDiscordToken } from '@seedcord/errors/internal';\nimport { Logger, LoggerChannelRegistry, paint } from '@seedcord/logger';\nimport { installNodeDefaults } from '@seedcord/logger/node';\nimport { MemoryRateLimiter } from '@seedcord/rate-limiter';\nimport { SeedcordBrand } from '@seedcord/types/internal';\nimport { Routes } from 'discord-api-types/v10';\nimport { Envapter } from 'envapt';\n\nimport { fetchApplicationId } from '@src/applicationId';\nimport { buildRouteMaps } from '@src/dispatch/resolve';\nimport { EmojiInjector } from '@src/emojis/EmojiInjector';\nimport { buildEngine } from '@src/engine';\nimport { EMPTY_MANIFEST } from '@src/manifest/RouteManifest';\n\nimport { InteractionDispatcher } from './InteractionDispatcher';\nimport { toWebRequest, writeWebResponse } from './webBridge';\nimport { version as packageVersion } from '../version';\n\nimport type { HttpConfig } from '@interfaces/Config';\nimport type { Core } from '@interfaces/Core';\nimport type { IRateLimiter } from '@seedcord/types';\nimport type { SeedcordInstance } from '@seedcord/types/internal';\nimport type { Server } from 'node:http';\nimport type { AddressInfo } from 'node:net';\n\nconst DEFAULT_PORT = 3000;\nconst SERVER_SHUTDOWN_TIMEOUT_MS = 5000;\nconst DRAIN_TIMEOUT_MS = 10_000;\n\ntype RuntimeOfConfig<Cfg extends HttpConfig> = Cfg extends { runtime: 'edge' } ? 'edge' : 'server';\n\n/**\n * The HTTP-interactions bot host, a long-running node server around the engine.\n *\n * Discovers handlers from `config.bot.interactions.path`, verifies and dispatches interactions on\n * `start()`, and runs coordinated shutdown with an in-flight drain. The edge deploy path calls\n * `createSeedcord` from a generated entry.\n */\nexport class Seedcord<Cfg extends HttpConfig = HttpConfig>\n extends Pluggable<'http', RuntimeOfConfig<Cfg>>\n implements Core, SeedcordInstance\n{\n // the CLI reads these to detect and augment the instance\n /** @internal */\n public readonly [SeedcordBrand] = true;\n /** @internal */\n public readonly augmentTarget = '@seedcord/http';\n /** @internal */\n public readonly version: string = packageVersion;\n\n /** Workerd-compatible Discord REST client. `start()` sets the token. */\n public readonly rest = new REST();\n\n /** @see {@link IRateLimiter} */\n public readonly rateLimiter: IRateLimiter;\n\n /** @see {@link Bus} */\n public readonly bus: Bus;\n\n private readonly subscribers: SubscriberLoader;\n\n private readonly interactions?: InteractionDispatcher;\n private readonly commandRegistry?: CommandRegistry;\n private appId?: string;\n private appIdPromise?: Promise<string>;\n private readonly emojiInjector = new EmojiInjector(this, () => this.applicationId());\n private readonly hmrManager: HmrManager;\n private readonly logger = new Logger('Server', { channel: 'bot' });\n\n private server?: Server;\n private boundPort?: number;\n private fetchedUsername?: string | undefined;\n\n constructor(public readonly config: Cfg) {\n super(new CoordinatedShutdown(), new CoordinatedStartup());\n\n installNodeDefaults(config.logger);\n setBotColor(config.botColor);\n\n this.hmrManager = new HmrManager();\n this.hmrManager.init();\n\n if (this.config.bot.interactions.path) {\n this.interactions = new InteractionDispatcher(this.config.bot.interactions.path);\n }\n\n const commandsDir = this.config.bot.commands.path;\n if (commandsDir) {\n const injector = new CommandInjector();\n // onDeployed only fires at deploy time, long after registry is assigned\n const registry: CommandRegistry = new CommandRegistry({\n dir: commandsDir,\n rest: this.rest,\n applicationId: () => this.requireApplicationId(),\n onDeployed: (result) => {\n injector.inject(result, registry.allCommands());\n }\n });\n this.commandRegistry = registry;\n }\n\n this.rateLimiter = config.store ?? new MemoryRateLimiter();\n this.bus = new Bus(this);\n this.subscribers = new SubscriberLoader(this.bus, config.subscribers.path);\n\n this.registerStartupTasks();\n }\n\n /** The bot's discord username, populated by the ready fetch. */\n public get username(): string | undefined {\n return this.fetchedUsername;\n }\n\n /** The bound server port, populated once `start()` is listening. */\n public get port(): number | undefined {\n return this.boundPort;\n }\n\n /**\n * Starts the host and runs the startup tasks.\n */\n public async start(): Promise<this> {\n try {\n await super.init();\n } catch (caught) {\n await this.shutdown.run(1, false);\n Seedcord.reset();\n throw caught;\n }\n return this;\n }\n\n protected static override reset(): void {\n super.reset();\n // super.reset() drops the dev TUI's log sink\n LoggerChannelRegistry.instance.configure({});\n }\n\n private registerStartupTasks(): void {\n if (Envapter.isDevelopment || Envapter.isTest) this.registerHmrAwareModules();\n\n this.startup.addTask(StartupPhase.Configuration, 'bus-initialization', async () => {\n this.bus.logger.utils.initialization('Subscribers', 'start');\n await this.subscribers.init();\n this.bus.logger.utils.initialization('Subscribers', 'end');\n });\n\n const { interactions } = this;\n if (interactions) {\n this.startup.addTask(StartupPhase.Configuration, 'interactions-initialization', async () => {\n interactions.logger.utils.initialization('Interactions', 'start');\n await interactions.init();\n interactions.logger.utils.initialization('Interactions', 'end');\n });\n }\n\n this.startup.addTask(StartupPhase.Configuration, 'authenticate', () => {\n this.authenticate();\n return Promise.resolve();\n });\n\n // needs the token from Configuration, and must finish before Ready opens the server to interactions\n this.startup.addTask(StartupPhase.Login, 'emoji-injection', () => this.emojiInjector.init());\n\n const { commandRegistry } = this;\n if (commandRegistry) {\n // one task because tasks in a phase run concurrently and the deploy reads the id\n this.startup.addTask(StartupPhase.Login, 'command-deploy', async () => {\n await commandRegistry.init();\n this.appId = await this.applicationId();\n await commandRegistry.setCommands();\n interactions?.warnUnhandledRoutes(commandRegistry.routeLeaves());\n interactions?.warnUnhandledContextMenuRoutes(commandRegistry.contextMenuLeaves());\n });\n }\n\n this.startup.addTask(StartupPhase.Ready, 'http-server', () => this.listen());\n\n if (!Envapter.isTest) {\n this.startup.addTask(StartupPhase.Ready, 'identity', () => this.fetchUsername());\n }\n }\n\n private registerHmrAwareModules(): void {\n this.startup.addTask(StartupPhase.Configuration, 'hmr-registration', async () => {\n if (this.interactions) this.hmrManager.register(this.interactions);\n if (this.commandRegistry) this.hmrManager.register(this.commandRegistry);\n this.hmrManager.register(this.subscribers);\n for (const plugin of this.plugins) {\n this.hmrManager.register(plugin);\n }\n await Promise.resolve();\n });\n }\n\n private authenticate(): void {\n this.rest.setToken(validateDiscordToken(Envapter.get('DISCORD_BOT_TOKEN')));\n }\n\n private applicationId(): Promise<string> {\n this.appIdPromise ??= fetchApplicationId(this.rest);\n return this.appIdPromise;\n }\n\n // the registry redeploys on a hot reload, after the startup task resolved this\n private requireApplicationId(): string {\n if (!this.appId) throw new SeedcordError(SeedcordErrorCode.CoreApplicationUnavailable);\n return this.appId;\n }\n\n private async listen(): Promise<void> {\n const maps = this.interactions?.maps ?? buildRouteMaps(EMPTY_MANIFEST);\n const { handle, inFlight } = buildEngine(this, maps);\n\n const server = createServer((incoming, outgoing) => {\n void (async () => {\n const response = await handle(await toWebRequest(incoming));\n await writeWebResponse(response, outgoing);\n })().catch((error: unknown) => {\n // a swallowed throw would hang the client with no cause\n outgoing.destroy(Error.isError(error) ? error : new Error(String(error)));\n });\n });\n this.server = server;\n\n server.listen(this.config.port ?? DEFAULT_PORT);\n await once(server, 'listening');\n // justified: address() is AddressInfo once a TCP server is listening\n this.boundPort = (server.address() as AddressInfo).port;\n this.logger.info(`Interactions server listening on port ${paint.sky.bold(String(this.boundPort))}`);\n getDevChannel()?.send('seedcord:server-listening', { port: this.boundPort });\n\n this.shutdown.addTask(\n ShutdownPhase.Unbind,\n 'stop-http-server',\n () => this.stopServer(),\n SERVER_SHUTDOWN_TIMEOUT_MS\n );\n // Unbind already ran, so every accepted request is in the in-flight set here\n this.shutdown.addTask(\n ShutdownPhase.Drain,\n 'drain-inflight',\n async () => {\n await Promise.allSettled(inFlight);\n },\n DRAIN_TIMEOUT_MS\n );\n }\n\n private async fetchUsername(): Promise<void> {\n try {\n // justified: the @me payload carries username per the discord api contract\n const me = (await this.rest.get(Routes.user('@me'))) as { username?: string };\n this.fetchedUsername = me.username;\n if (me.username) this.logger.info(`Running as ${paint.iris.bold(me.username)}`);\n } catch (caught) {\n // a bad token errors on the first real send anyway\n this.logger.warn('could not fetch the bot identity', caught);\n }\n }\n\n private stopServer(): Promise<void> {\n const server = this.server;\n if (!server?.listening) return Promise.resolve();\n\n return new Promise((resolveClose, rejectClose) => {\n server.close((err) => {\n if (err) {\n rejectClose(err);\n return;\n }\n this.logger.info(paint.coral.bold('Interactions server stopped'));\n resolveClose();\n });\n // close() waits on idle keep-alive sockets. active responses still flush, and the task\n // timeout bounds a hung one\n server.closeIdleConnections();\n });\n }\n}\n","import { Plugin as CorePlugin } from '@seedcord/core/plugin';\n\nimport type { Core } from '@interfaces/Core';\nimport type { PluginOptions } from '@seedcord/core/plugin';\nimport type { TypedOmit } from '@seedcord/types';\n\n/** The options an HTTP plugin declares, narrowed to the transports this base serves. */\nexport type HttpPluginOptions = TypedOmit<PluginOptions, 'transport'> & { transport?: 'http' | 'any' };\n\n/**\n * Base class for an HTTP plugin, binding `this.core` to the HTTP {@link Core}.\n *\n * A plugin that runs on either transport extends the base from `@seedcord/core/plugin`, whose\n * `this.core` is typed to the shared members only.\n *\n * @typeParam Opts - The transport and runtime the plugin declares.\n */\nexport abstract class Plugin<Opts extends HttpPluginOptions = {}> extends CorePlugin<Opts, Core> {}\n\nexport type { PluginLifecycleSpec, PluginOptions } from '@seedcord/core/plugin';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,MAAa,iBAAgC;CACzC,eAAe,CAAC;CAChB,iBAAiB,CAAC;CAClB,oBAAoB,CAAC;CACrB,kBAAkB,CAAC;CACnB,kBAAkB,CAAC;AACvB;;;;AClDA,IAAa,wBAAb,MAAuE;CAkBtC;CAjB7B,AAAgB;CAChB,AAAiB;;CAGjB,AAAgB,SAAS,IAAIA,wBAAO,gBAAgB,EAAE,SAAS,eAAe,CAAC;CAE/E,AAAQ,gBAAgB;CACxB,AAAiB;CAEjB,AAAiB,4BAAY,IAAI,IAG/B;CAEF,AAAQ,UAAU;CAClB,AAAiB,iBAAmD,CAAC;CAErE,YAAY,AAAiB,aAAqB;EAArB;EACzB,KAAK,OAAOC,kCAAe,cAAc;EACzC,KAAK,UAAU,KAAK,aAAa;EAEjC,IAAI,CAACC,gBAAS,iBAAiB,CAACA,gBAAS,QAAQ;EACjD,KAAK,aAAa,IAAIC,oCAAiB;GACnC;GACA,WAAW,KAAK,UAAU,KAAK,IAAI;GACnC,iBAAiB,KAAK,gBAAgB,KAAK,IAAI;GAC/C,mBAAmB,KAAK,kBAAkB,KAAK,IAAI;GACnD,cAAc,KAAK,aAAa,KAAK,IAAI;GACzC,QAAQ,KAAK;EACjB,CAAC;CACL;;CAGA,MAAa,OAAsB;EAC/B,IAAI,KAAK,eAAe;EACxB,KAAK,gBAAgB;EAErB,KAAK,UAAU;EACf,KAAK,eAAe,SAAS;EAC7B,IAAI;GACA,UAAMC,wCAAkB,KAAK,cAAc,UAAU,cAAc,aAAa;IAC5E,KAAK,MAAM,SAAS,OAAO,OAAO,QAAQ,GAAG;KACzC,IAAI,CAAC,KAAK,UAAU,KAAK,GAAG;KAC5B,KAAK,gBAAgB,OAAO,YAAY;KACxC,KAAK,YAAY,aAAa,UAAU,KAAK;IACjD;GACJ,CAAC;EACL,UAAU;GACN,KAAK,UAAU;EACnB;EAEA,KAAK,OAAO,MAAM,MACd,mBACA,CACI,GAAG,KAAK,OAAO,MAAM,QAAQ,KAAK,cAAc,GAChD,GAAG,KAAK,OAAO,MAAM,OAAO,EAAE,QAAQ,KAAK,UAAU,KAAK,CAAC,CAC/D,GACA,OACJ;CACJ;;CAGA,MAAa,MAAM,OAAsC;EACrD,MAAM,KAAK,YAAY,OAAO,KAAK;CACvC;CAEA,AAAO,oBAAoB,eAAuC;EAC9D,KAAK,YAAY,eAAe,KAAK,KAAK,OAAO,eAAe,aAAa;CACjF;CAEA,AAAO,+BAA+B,QAAiC;EACnE,KAAK,YAAY,OAAO,MAAM,KAAK,KAAK,iBAAiB,qBAAqB,mBAAmB;EACjG,KAAK,YAAY,OAAO,SAAS,KAAK,KAAK,oBAAoB,wBAAwB,mBAAmB;CAC9G;CAEA,AAAQ,YAAY,OAAyB,KAAe,OAAe,WAAyB;EAChG,KAAK,MAAM,QAAQ,OAAO;GACtB,IAAI,IAAI,IAAI,IAAI,GAAG;GACnB,KAAK,OAAO,KAAK,GAAG,MAAM,GAAGC,uBAAM,IAAI,KAAK,IAAI,EAAE,qBAAqB,cAAM,KAAK,SAAS,EAAE,UAAU;EAC3G;CACJ;CAEA,AAAQ,UAAU,OAA6C;EAC3D,IAAI,OAAO,UAAU,YAAY,OAAO;EAExC,QACK,MAAM,qBAAqBC,yCAAsB,MAAM,qBAAqBC,2CAC7E,QAAQ,YAAYC,gDAAwB,KAAK;CAEzD;CAEA,AAAQ,aAAa,MAAoC;EACrD,MAAM,WAAqB,CAAC;EAC5B,KAAK,MAAM,CAAC,SAAS,UAAU,KAAK,WAChC,IAAI,MAAM,SAAS,MAAM,SAAS,KAAK,OAAO;EAElD,OAAO;CACX;CAEA,AAAQ,UAAU,OAAuC;EACrD,OAAO,KAAK,QAAQ;CACxB;CAEA,AAAQ,eAAuD;EAC3D,OAAO;IACFC,0CAAkB,QAAQ;IAAE,KAAK,KAAK,KAAK;IAAO,MAAM;GAAQ;IAChEA,0CAAkB,kBAAkB;IAAE,KAAK,KAAK,KAAK;IAAiB,MAAM;GAAkB;IAC9FA,0CAAkB,qBAAqB;IAAE,KAAK,KAAK,KAAK;IAAoB,MAAM;GAAqB;IACvGA,0CAAkB,eAAe;IAAE,KAAK,KAAK,KAAK;IAAc,MAAM;GAAe;IACrFA,0CAAkB,SAAS;IAAE,KAAK,KAAK,KAAK,WAAW;IAAQ,MAAM;GAAS;IAC9EA,0CAAkB,aAAa;IAAE,KAAK,KAAK,KAAK,WAAW;IAAc,MAAM;GAAa;IAC5FA,0CAAkB,WAAW;IAAE,KAAK,KAAK,KAAK,WAAW;IAAY,MAAM;GAAW;IACtFA,0CAAkB,WAAW;IAAE,KAAK,KAAK,KAAK,WAAW;IAAY,MAAM;GAAW;IACtFA,0CAAkB,cAAc;IAAE,KAAK,KAAK,KAAK,WAAW;IAAe,MAAM;GAAc;IAC/FA,0CAAkB,kBAAkB;IACjC,KAAK,KAAK,KAAK,WAAW;IAC1B,MAAM;GACV;IACCA,0CAAkB,QAAQ;IAAE,KAAK,KAAK,KAAK,WAAW;IAAO,MAAM;GAAQ;EAChF;CACJ;CAEA,AAAQ,gBAAgB,MAA0B,cAA4B;EAC1E,MAAM,WAAOC,gCAAe,YAAY;EAExC,MAAM,SAAkC,CAAC;EAEzC,KAAK,MAAM,CAAC,OAAO,aAASC,6CAAoB,IAAI,GAAG;GACnD,MAAM,SAAS,KAAK,UAAU,KAAK;GACnC,KAAK,MAAM,OAAO,MAAM;IACpB,MAAM,UAAU,GAAG,OAAO,KAAK,GAAG;IAClC,MAAM,WAAW,KAAK,UAAU,IAAI,OAAO;IAE3C,IAAI,YAAY,SAAS,SAAS,MAC9B,MAAM,IAAIC,wCAAcC,mCAAkB,2BAA2B;KACjE;KACA,GAAG,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK;KACxC,GAAG,KAAK,KAAK,IAAI,KAAK;IAC1B,CAAC;IAEL,OAAO,KAAK,CAAC,QAAQ,GAAG,CAAC;GAC7B;EACJ;EAEA,IAAI,OAAO,WAAW,GAAG;EACzB,KAAK,MAAM,CAAC,QAAQ,QAAQ,QAAQ;GAChC,MAAM,UAAU,GAAG,OAAO,KAAK,GAAG;GAClC,OAAO,IAAI,IAAI,KAAK;IAAE,MAAM,OAAO;IAAM;IAAS,YAAY,QAAQ,QAAQ,IAAI;GAAE,CAAC;GACrF,KAAK,UAAU,IAAI,SAAS;IAAE;IAAM;IAAQ;IAAK;GAAK,CAAC;EAC3D;EAEA,IAAI,KAAK,SAAS,KAAK,eAAe,KAAK;GAAE,MAAM,KAAK;GAAM;EAAK,CAAC;CACxE;CAEA,AAAQ,kBAAkB,MAA0B,WAA4B;EAC5E,MAAM,WAAW,aAAa,KAAK,aAAa,IAAI;EACpD,KAAK,MAAM,WAAW,UAAU;GAC5B,MAAM,QAAQ,KAAK,UAAU,IAAI,OAAO;GACxC,IAAI,OAAO,SAAS,MAAM;GAC1B,KAAK,UAAU,OAAO,OAAO;GAC7B,MAAM,OAAO,IAAI,OAAO,MAAM,GAAG;EACrC;CACJ;AACJ;;;;AC7LA,SAAS,UAAU,KAAmC;CAClD,MAAM,UAAU,IAAI,QAAQ;CAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,GAAG,GAAG;EAC7C,IAAI,UAAU,QAAW;EACzB,IAAI,MAAM,QAAQ,KAAK,GACnB,KAAK,MAAM,QAAQ,OAAO,QAAQ,OAAO,MAAM,IAAI;OAEnD,QAAQ,IAAI,MAAM,KAAK;CAE/B;CACA,OAAO;AACX;AAGA,eAAsB,aAAa,SAA4C;CAC3E,MAAM,SAAmB,CAAC;CAE1B,WAAW,MAAM,SAAS,SAAS,OAAO,KAAK,KAAe;CAE9D,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,OAAO,WAAW,SAAS,WAAW,SAAS,SAAY,IAAI,WAAW,OAAO,OAAO,MAAM,CAAC;CAErG,OAAO,IAAI,QAAQ,UAAU,QAAQ,QAAQ,QAAQ,cAAc,QAAQ,OAAO,OAAO;EACrF;EACA,SAAS,UAAU,QAAQ,OAAO;EAClC,GAAI,SAAS,UAAa,EAAE,KAAK;CACrC,CAAC;AACL;AAEA,eAAsB,iBAAiB,UAAoB,KAAoC;CAC3F,MAAM,UAA6C,OAAO,YAAY,SAAS,OAAO;CAEtF,MAAM,UAAU,SAAS,QAAQ,aAAa;CAC9C,IAAI,QAAQ,SAAS,GAAG,QAAQ,gBAAgB;CAEhD,IAAI,UAAU,SAAS,QAAQ,OAAO;CACtC,IAAI,IAAI,SAAS,SAAS,OAAO,SAAY,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC,CAAC;AAC1F;;;;ACEA,MAAM,eAAe;AACrB,MAAM,6BAA6B;AACnC,MAAM,mBAAmB;;;;;;;;AAWzB,IAAa,WAAb,MAAa,iBACDC,uCAEZ;CAgCgC;;CA7B5B,CAAiBC,0CAAiB;;CAElC,AAAgB,gBAAgB;;CAEhC,AAAgB,UAAkBC;;CAGlC,AAAgB,OAAO,IAAIC,qBAAK;;CAGhC,AAAgB;;CAGhB,AAAgB;CAEhB,AAAiB;CAEjB,AAAiB;CACjB,AAAiB;CACjB,AAAQ;CACR,AAAQ;CACR,AAAiB,gBAAgB,IAAIC,iCAAc,YAAY,KAAK,cAAc,CAAC;CACnF,AAAiB;CACjB,AAAiB,SAAS,IAAIC,wBAAO,UAAU,EAAE,SAAS,MAAM,CAAC;CAEjE,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,AAAgB,QAAa;EACrC,MAAM,IAAIC,iDAAoB,GAAG,IAAIC,gDAAmB,CAAC;EADjC;EAGxB,+CAAoB,OAAO,MAAM;EACjC,yCAAY,OAAO,QAAQ;EAE3B,KAAK,aAAa,IAAIC,mCAAW;EACjC,KAAK,WAAW,KAAK;EAErB,IAAI,KAAK,OAAO,IAAI,aAAa,MAC7B,KAAK,eAAe,IAAI,sBAAsB,KAAK,OAAO,IAAI,aAAa,IAAI;EAGnF,MAAM,cAAc,KAAK,OAAO,IAAI,SAAS;EAC7C,IAAI,aAAa;GACb,MAAM,WAAW,IAAIC,wCAAgB;GAErC,MAAM,WAA4B,IAAIC,6CAAgB;IAClD,KAAK;IACL,MAAM,KAAK;IACX,qBAAqB,KAAK,qBAAqB;IAC/C,aAAa,WAAW;KACpB,SAAS,OAAO,QAAQ,SAAS,YAAY,CAAC;IAClD;GACJ,CAAC;GACD,KAAK,kBAAkB;EAC3B;EAEA,KAAK,cAAc,OAAO,SAAS,IAAIC,yCAAkB;EACzD,KAAK,MAAM,IAAIC,mBAAI,IAAI;EACvB,KAAK,cAAc,IAAIC,8CAAiB,KAAK,KAAK,OAAO,YAAY,IAAI;EAEzE,KAAK,qBAAqB;CAC9B;;CAGA,IAAW,WAA+B;EACtC,OAAO,KAAK;CAChB;;CAGA,IAAW,OAA2B;EAClC,OAAO,KAAK;CAChB;;;;CAKA,MAAa,QAAuB;EAChC,IAAI;GACA,MAAM,MAAM,KAAK;EACrB,SAAS,QAAQ;GACb,MAAM,KAAK,SAAS,IAAI,GAAG,KAAK;GAChC,SAAS,MAAM;GACf,MAAM;EACV;EACA,OAAO;CACX;CAEA,OAA0B,QAAc;EACpC,MAAM,MAAM;EAEZ,uCAAsB,SAAS,UAAU,CAAC,CAAC;CAC/C;CAEA,AAAQ,uBAA6B;EACjC,IAAIC,gBAAS,iBAAiBA,gBAAS,QAAQ,KAAK,wBAAwB;EAE5E,KAAK,QAAQ,QAAQC,0CAAa,eAAe,sBAAsB,YAAY;GAC/E,KAAK,IAAI,OAAO,MAAM,eAAe,eAAe,OAAO;GAC3D,MAAM,KAAK,YAAY,KAAK;GAC5B,KAAK,IAAI,OAAO,MAAM,eAAe,eAAe,KAAK;EAC7D,CAAC;EAED,MAAM,EAAE,iBAAiB;EACzB,IAAI,cACA,KAAK,QAAQ,QAAQA,0CAAa,eAAe,+BAA+B,YAAY;GACxF,aAAa,OAAO,MAAM,eAAe,gBAAgB,OAAO;GAChE,MAAM,aAAa,KAAK;GACxB,aAAa,OAAO,MAAM,eAAe,gBAAgB,KAAK;EAClE,CAAC;EAGL,KAAK,QAAQ,QAAQA,0CAAa,eAAe,sBAAsB;GACnE,KAAK,aAAa;GAClB,OAAO,QAAQ,QAAQ;EAC3B,CAAC;EAGD,KAAK,QAAQ,QAAQA,0CAAa,OAAO,yBAAyB,KAAK,cAAc,KAAK,CAAC;EAE3F,MAAM,EAAE,oBAAoB;EAC5B,IAAI,iBAEA,KAAK,QAAQ,QAAQA,0CAAa,OAAO,kBAAkB,YAAY;GACnE,MAAM,gBAAgB,KAAK;GAC3B,KAAK,QAAQ,MAAM,KAAK,cAAc;GACtC,MAAM,gBAAgB,YAAY;GAClC,cAAc,oBAAoB,gBAAgB,YAAY,CAAC;GAC/D,cAAc,+BAA+B,gBAAgB,kBAAkB,CAAC;EACpF,CAAC;EAGL,KAAK,QAAQ,QAAQA,0CAAa,OAAO,qBAAqB,KAAK,OAAO,CAAC;EAE3E,IAAI,CAACD,gBAAS,QACV,KAAK,QAAQ,QAAQC,0CAAa,OAAO,kBAAkB,KAAK,cAAc,CAAC;CAEvF;CAEA,AAAQ,0BAAgC;EACpC,KAAK,QAAQ,QAAQA,0CAAa,eAAe,oBAAoB,YAAY;GAC7E,IAAI,KAAK,cAAc,KAAK,WAAW,SAAS,KAAK,YAAY;GACjE,IAAI,KAAK,iBAAiB,KAAK,WAAW,SAAS,KAAK,eAAe;GACvE,KAAK,WAAW,SAAS,KAAK,WAAW;GACzC,KAAK,MAAM,UAAU,KAAK,SACtB,KAAK,WAAW,SAAS,MAAM;GAEnC,MAAM,QAAQ,QAAQ;EAC1B,CAAC;CACL;CAEA,AAAQ,eAAqB;EACzB,KAAK,KAAK,aAASC,gDAAqBF,gBAAS,IAAI,mBAAmB,CAAC,CAAC;CAC9E;CAEA,AAAQ,gBAAiC;EACrC,KAAK,iBAAiBG,sCAAmB,KAAK,IAAI;EAClD,OAAO,KAAK;CAChB;CAGA,AAAQ,uBAA+B;EACnC,IAAI,CAAC,KAAK,OAAO,MAAM,IAAIC,wCAAcC,mCAAkB,0BAA0B;EACrF,OAAO,KAAK;CAChB;CAEA,MAAc,SAAwB;EAClC,MAAM,OAAO,KAAK,cAAc,QAAQC,kCAAe,cAAc;EACrE,MAAM,EAAE,QAAQ,aAAaC,+BAAY,MAAM,IAAI;EAEnD,MAAM,aAASC,yBAAc,UAAU,aAAa;GAChD,CAAM,YAAY;IACd,MAAM,WAAW,MAAM,OAAO,MAAM,aAAa,QAAQ,CAAC;IAC1D,MAAM,iBAAiB,UAAU,QAAQ;GAC7C,EAAC,CAAE,CAAC,CAAC,OAAO,UAAmB;IAE3B,SAAS,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;GAC5E,CAAC;EACL,CAAC;EACD,KAAK,SAAS;EAEd,OAAO,OAAO,KAAK,OAAO,QAAQ,YAAY;EAC9C,UAAMC,kBAAK,QAAQ,WAAW;EAE9B,KAAK,YAAa,OAAO,QAAQ,CAAC,CAAiB;EACnD,KAAK,OAAO,KAAK,yCAAyCC,uBAAM,IAAI,KAAK,OAAO,KAAK,SAAS,CAAC,GAAG;EAClG,2CAAc,CAAC,EAAE,KAAK,6BAA6B,EAAE,MAAM,KAAK,UAAU,CAAC;EAE3E,KAAK,SAAS,QACVC,2CAAc,QACd,0BACM,KAAK,WAAW,GACtB,0BACJ;EAEA,KAAK,SAAS,QACVA,2CAAc,OACd,kBACA,YAAY;GACR,MAAM,QAAQ,WAAW,QAAQ;EACrC,GACA,gBACJ;CACJ;CAEA,MAAc,gBAA+B;EACzC,IAAI;GAEA,MAAM,KAAM,MAAM,KAAK,KAAK,IAAIC,6BAAO,KAAK,KAAK,CAAC;GAClD,KAAK,kBAAkB,GAAG;GAC1B,IAAI,GAAG,UAAU,KAAK,OAAO,KAAK,cAAcF,uBAAM,KAAK,KAAK,GAAG,QAAQ,GAAG;EAClF,SAAS,QAAQ;GAEb,KAAK,OAAO,KAAK,oCAAoC,MAAM;EAC/D;CACJ;CAEA,AAAQ,aAA4B;EAChC,MAAM,SAAS,KAAK;EACpB,IAAI,CAAC,QAAQ,WAAW,OAAO,QAAQ,QAAQ;EAE/C,OAAO,IAAI,SAAS,cAAc,gBAAgB;GAC9C,OAAO,OAAO,QAAQ;IAClB,IAAI,KAAK;KACL,YAAY,GAAG;KACf;IACJ;IACA,KAAK,OAAO,KAAKA,uBAAM,MAAM,KAAK,6BAA6B,CAAC;IAChE,aAAa;GACjB,CAAC;GAGD,OAAO,qBAAqB;EAChC,CAAC;CACL;AACJ;;;;;;;;;;;;ACtRA,IAAsB,SAAtB,cAA0EG,6BAAuB,CAAC"}
|
package/dist/index.d.cts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type * from './index.d.mts'
|
package/dist/manifest.index.cjs
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
let _seedcord_errors_internal = require("@seedcord/errors/internal");
|
|
3
|
-
let _seedcord_errors = require("@seedcord/errors");
|
|
4
|
-
|
|
5
|
-
//#region src/manifest.index.ts
|
|
6
|
-
const notGenerated = () => {
|
|
7
|
-
throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.ConfigManifestNotGenerated);
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* The generated route table. `seedcord build` aliases this module to the emitted file. Reading a route
|
|
11
|
-
* list off the un-built stub will throw.
|
|
12
|
-
*/
|
|
13
|
-
const manifest = {
|
|
14
|
-
get commandRoutes() {
|
|
15
|
-
return notGenerated();
|
|
16
|
-
},
|
|
17
|
-
get componentRoutes() {
|
|
18
|
-
return notGenerated();
|
|
19
|
-
},
|
|
20
|
-
get autocompleteRoutes() {
|
|
21
|
-
return notGenerated();
|
|
22
|
-
},
|
|
23
|
-
get subscriberRoutes() {
|
|
24
|
-
return notGenerated();
|
|
25
|
-
},
|
|
26
|
-
get middlewareRoutes() {
|
|
27
|
-
return notGenerated();
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
//#endregion
|
|
32
|
-
exports.manifest = manifest;
|
|
33
|
-
//# sourceMappingURL=manifest.index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.index.cjs","names":["SeedcordError","SeedcordErrorCode"],"sources":["../src/manifest.index.ts"],"sourcesContent":["import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport type { RouteManifest } from '@src/manifest/RouteManifest';\n\nexport type { RouteManifest } from '@src/manifest/RouteManifest';\n\nconst notGenerated = (): never => {\n throw new SeedcordError(SeedcordErrorCode.ConfigManifestNotGenerated);\n};\n\n/**\n * The generated route table. `seedcord build` aliases this module to the emitted file. Reading a route\n * list off the un-built stub will throw.\n */\nexport const manifest: RouteManifest = {\n get commandRoutes(): never {\n return notGenerated();\n },\n get componentRoutes(): never {\n return notGenerated();\n },\n get autocompleteRoutes(): never {\n return notGenerated();\n },\n get subscriberRoutes(): never {\n return notGenerated();\n },\n get middlewareRoutes(): never {\n return notGenerated();\n }\n};\n"],"mappings":";;;;;AAOA,MAAM,qBAA4B;CAC9B,MAAM,IAAIA,wCAAcC,mCAAkB,0BAA0B;AACxE;;;;;AAMA,MAAa,WAA0B;CACnC,IAAI,gBAAuB;EACvB,OAAO,aAAa;CACxB;CACA,IAAI,kBAAyB;EACzB,OAAO,aAAa;CACxB;CACA,IAAI,qBAA4B;EAC5B,OAAO,aAAa;CACxB;CACA,IAAI,mBAA0B;EAC1B,OAAO,aAAa;CACxB;CACA,IAAI,mBAA0B;EAC1B,OAAO,aAAa;CACxB;AACJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type * from './manifest.index.d.mts'
|