@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.index.mjs","names":["logger"],"sources":["../src/decorators/brands.ts","../src/dispatch/MiddlewareRegistry.ts","../src/gates/runGates.ts","../src/gates/slowGate.ts","../src/miscellaneous/emojiConfig.ts","../src/hmr/wrapHot.ts","../src/hmr/HmrManager.ts","../src/dispatch/dispatchReport.ts","../src/dispatch/runAfter.ts"],"sourcesContent":["// phantom, nothing assigns these at runtime\n\nexport const SlashRouteBrand: unique symbol = Symbol('seedcord:brand:slash-route');\nexport const AutocompleteRouteBrand: unique symbol = Symbol('seedcord:brand:autocomplete-route');\nexport const ContextMenuKindBrand: unique symbol = Symbol('seedcord:brand:context-menu-kind');\nexport const ContextMenuNamesBrand: unique symbol = Symbol('seedcord:brand:context-menu-names');\nexport const ComponentKindBrand: unique symbol = Symbol('seedcord:brand:component-kind');\nexport const ComponentDefsBrand: unique symbol = Symbol('seedcord:brand:component-defs');\nexport const MiddlewareKindsBrand: unique symbol = Symbol('seedcord:brand:middleware-kinds');\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\n\nimport { interactionMiddlewareMetaOf } from '#decorators/middleware';\n\nimport type { AnyMiddlewareCtor } from '#decorators/middleware';\nimport type { MiddlewareKind } from '#src/metadataKeys';\n\n/**\n * A decorated middleware reduced to what the registry orders and filters on. An absent `keys` puts the\n * middleware in every chain.\n *\n * @internal\n */\nexport interface MiddlewareRegistration<Key extends string> {\n readonly priority: number;\n readonly keys?: readonly Key[];\n}\n\n/**\n * Reads a transport's decorator metadata off a class. Returns `undefined` for an undecorated one.\n *\n * @internal\n */\nexport type MiddlewareRegistrationOf<Ctor, Key extends string> = (\n ctor: Ctor\n) => MiddlewareRegistration<Key> | undefined;\n\n/** @internal */\nexport function interactionMiddleware(ctor: AnyMiddlewareCtor): MiddlewareRegistration<MiddlewareKind> | undefined {\n const metadata = interactionMiddlewareMetaOf(ctor);\n if (!metadata) return undefined;\n return { priority: metadata.priority, ...(metadata.kinds && { keys: metadata.kinds }) };\n}\n\ninterface Entry<Ctor, Key extends string> {\n readonly ctor: Ctor;\n readonly priority: number;\n readonly keys?: ReadonlySet<Key>;\n}\n\n/**\n * Holds the middleware a transport loaded and keeps one chain per key. An interaction keys on its kind\n * and an event on its name. Priority and the key filter behave the same on each.\n *\n * @typeParam Ctor - The transport's middleware constructor type.\n * @typeParam Key - The chain lookup key.\n *\n * @internal\n */\nexport class MiddlewareRegistry<Ctor extends AnyMiddlewareCtor, Key extends string = MiddlewareKind> {\n private readonly entries: Entry<Ctor, Key>[] = [];\n // an in-flight dispatch keeps walking the array chainFor gave it. never mutate one in place.\n private chains = new Map<Key, readonly Ctor[]>();\n\n public constructor(private readonly registrationOf: MiddlewareRegistrationOf<Ctor, Key>) {}\n\n /**\n * Adds a decorated middleware class and returns what it registered with. Returns `undefined` for an\n * undecorated class or one already registered.\n *\n * @throws A **SeedcordError** If another class with the same name is registered.\n */\n public register(ctor: Ctor): MiddlewareRegistration<Key> | undefined {\n const registration = this.registrationOf(ctor);\n if (!registration) return undefined;\n\n // a double import or an hmr re-scan registers the same class twice\n if (this.entries.some((entry) => entry.ctor === ctor)) return undefined;\n if (this.entries.some((entry) => entry.ctor.name === ctor.name)) {\n throw new SeedcordError(SeedcordErrorCode.DuplicateMiddleware, [ctor.name]);\n }\n\n this.entries.push({\n ctor,\n priority: registration.priority,\n ...(registration.keys && { keys: new Set(registration.keys) })\n });\n this.rebuild();\n return registration;\n }\n\n public unregister(ctor: Ctor): void {\n const index = this.entries.findIndex((entry) => entry.ctor === ctor);\n if (index === -1) return;\n this.entries.splice(index, 1);\n this.rebuild();\n }\n\n public chainFor(key: Key): readonly Ctor[] {\n const built = this.chains.get(key);\n if (built) return built;\n\n const chain = this.entries.filter((entry) => !entry.keys || entry.keys.has(key)).map((entry) => entry.ctor);\n this.chains.set(key, chain);\n return chain;\n }\n\n private rebuild(): void {\n // a stable sort keeps ties in registration order\n this.entries.sort((a, b) => a.priority - b.priority);\n this.chains = new Map();\n }\n}\n","import 'reflect-metadata';\n\nimport { GatedMetadataKey } from '#src/metadataKeys';\n\nimport { discardCommits, runCheck, runCommits } from './effects';\n\nimport type { Gate, GateContextBase } from './Gate';\n\n// a combinator (`and`/`or`) reports once under its joined name.\nexport type GateObserver = (gateName: string, elapsedMs: number) => void;\n\nasync function timedCheck(gate: Gate<GateContextBase>, ctx: GateContextBase, observe: GateObserver): Promise<void> {\n const start = performance.now();\n // finally so a refusing gate still reports\n try {\n await runCheck(gate, ctx);\n } finally {\n observe(gate.name, performance.now() - start);\n }\n}\n\n// the first refusal throws out to the dispatcher boundary. an effect gate's commit runs once the\n// whole set passes, and observe never times the commit phase.\nexport async function runGates(\n gates: readonly Gate<GateContextBase>[],\n ctx: GateContextBase,\n observe?: GateObserver\n): Promise<void> {\n try {\n for (const gate of gates) {\n await (observe ? timedCheck(gate, ctx, observe) : runCheck(gate, ctx));\n }\n await runCommits(ctx);\n } finally {\n discardCommits(ctx);\n }\n}\n\n// dispatchers call this before execute, inside the boundary, so a refusal renders or drops\nexport async function runHandlerGates(\n handlerCtor: object,\n ctx: GateContextBase,\n declaredRoute?: string,\n observe?: GateObserver\n): Promise<void> {\n // justified: getMetadata returns any, and this key only ever stores the @Gated gate array\n const gates = Reflect.getMetadata(GatedMetadataKey, handlerCtor) as readonly Gate<GateContextBase>[] | undefined;\n if (!gates) return;\n await runGates(gates, { ...ctx, declaredRoute: declaredRoute ?? null }, observe);\n}\n","import { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { Envapter } from 'envapt';\n\nimport type { GateObserver } from './runGates';\n\n// combined check time slower than this cuts into the 3s interaction-ack budget\nconst SLOW_GATE_MS = 750;\n\n// lazy because the logger reads the environment, which binds after this module loads\nlet gateLogger: Logger | undefined;\nfunction logger(): Logger {\n gateLogger ??= new Logger('Gates', { channel: 'gates' });\n return gateLogger;\n}\n\n/**\n * collects each gate check's elapsed time for one dispatch. `report` warns once when the checks sum\n * past the threshold, naming the total, the route, and each gate's share.\n */\nexport interface SlowGateMonitor {\n readonly observe: GateObserver;\n report(declaredRoute: string | null): void;\n}\n\n// undefined in production, so timedCheck skips the clock there. read per call, the environment binds late\nexport function slowGateMonitor(): SlowGateMonitor | undefined {\n if (Envapter.isProduction) return undefined;\n const readings: { name: string; ms: number }[] = [];\n return {\n observe: (name, ms) => readings.push({ name, ms }),\n report(declaredRoute) {\n const total = readings.reduce((sum, reading) => sum + reading.ms, 0);\n if (total < SLOW_GATE_MS) return;\n const shares = readings\n .toSorted((a, b) => b.ms - a.ms)\n .map((reading) => `${paint.sky.bold(reading.name)} ${paint.mute(`${Math.round(reading.ms)}ms`)}`);\n const route = declaredRoute === null ? '' : ` for ${paint.sky.bold(declaredRoute)}`;\n const headline = `gates${route} took ${paint.amber(`${Math.round(total)}ms`)} of the 3s ack budget`;\n logger().utils.block(headline, shares, 'warn', (text) => text);\n }\n };\n}\n","// narrows a configured emoji value to the [name, guildId] form\nexport function isEmojiTuple(value: unknown): value is readonly [string, string] {\n return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string' && typeof value[1] === 'string';\n}\n","import type { DevChannel } from '@seedcord/types/internal';\n\n// the minimal raw-hot shape, satisfied by both vite's `import.meta.hot` and the CLI's `NormalizedHotChannel`.\ninterface RawHot {\n send(event: string, data?: unknown): void;\n on(event: string, cb: (data: unknown) => void): void;\n}\n\n/** @internal */\nexport function wrapHot<TSend, TRecv>(hot: RawHot): DevChannel<TSend, TRecv> {\n return {\n send: (event, data) => hot.send(event, data),\n // justified: RawHot types every payload as unknown, and the wire contract guarantees it matches TRecv[Key]\n on: (event, cb) => hot.on(event, cb as (data: unknown) => void)\n };\n}\n","// scoped here so import.meta.hot stays untyped in the rest of the package\n/// <reference types=\"vite/client\" />\nimport { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { Envapter } from 'envapt';\n\nimport { setDevChannel } from './devChannel';\nimport { wrapHot } from './wrapHot';\n\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { SeedcordCliEvents, SeedcordFrameworkEvents } from '@seedcord/types/internal';\n\nexport class HmrManager {\n private readonly logger = new Logger('HMR', { channel: 'hmr' });\n private readonly listeners = new Set<HmrAware>();\n\n /** @internal */\n public init(): void {\n if (!import.meta.hot) return;\n // the only raw `import.meta.hot` read in the framework\n const channel = wrapHot<SeedcordFrameworkEvents, SeedcordCliEvents>(import.meta.hot);\n setDevChannel(channel);\n\n if (!(Envapter.isDevelopment || Envapter.isTest)) {\n return;\n }\n\n this.logger.debug('Enabled');\n channel.on('seedcord:hmr', (payload) => void this.handleUpdate(payload));\n }\n\n /** @internal */\n public register(listener: HmrAware): void {\n this.listeners.add(listener);\n }\n\n private async handleUpdate(event: HmrUpdateEvent): Promise<void> {\n const promises = [...this.listeners].map(async (listener) => {\n try {\n await listener.onHmr(event);\n } catch (error) {\n this.logger.error(`Error handling HMR update in ${paint.sky.bold(listener.constructor.name)}`, error);\n }\n });\n\n await Promise.all(promises);\n }\n}\n","import { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { timestampFromSnowflake } from '@seedcord/utils';\n\nimport { Notice } from '#stops/Notice';\nimport { Silence } from '#stops/Silence';\nimport { PublishDefault } from '#subscribers/publishDefault';\n\nimport type { InteractionKind } from '#src/metadataKeys';\nimport type { Bus } from '#subscribers/Bus';\nimport type { DispatchOutcome } from '#subscribers/types/Subscriptions';\n\nlet dispatchLogger: Logger | undefined;\nfunction logger(): Logger {\n dispatchLogger ??= new Logger('Dispatch', { channel: 'interactions' });\n return dispatchLogger;\n}\n\n/**\n * Classifies a caught stop for `interactionDispatched` so a gate and a\n * handler label the same stop identically.\n *\n * @internal\n */\nexport function outcomeFor(caught: unknown): Exclude<DispatchOutcome, 'handled'> {\n if (caught instanceof Silence) return 'refused';\n if (caught instanceof Notice) return caught.report ? 'failed' : 'refused';\n return 'failed';\n}\n\ninterface DispatchReport {\n readonly dispatchId: string;\n readonly routeId: string;\n readonly interactionId: string;\n readonly kind: `${InteractionKind}`;\n readonly outcome: DispatchOutcome;\n /** True when no route matched and the unhandled default ran. */\n readonly fallback: boolean;\n readonly userId: string | null;\n readonly guildId: string | null;\n /** `performance.now()` captured as the dispatch began. */\n readonly startedAt: number;\n /** {@link queuedMsFor} read at the same moment as `startedAt`. */\n readonly queuedMs: number;\n}\n\n/**\n * Discord's interaction creation to now, read from the snowflake. Called at dispatch entry, since\n * a later read would count the handler run into the queue time as well.\n *\n * @internal\n */\nexport function queuedMsFor(interactionId: string): number {\n // timestampFromSnowflake throws on a malformed id\n try {\n return Date.now() - timestampFromSnowflake(interactionId);\n } catch {\n return 0;\n }\n}\n\nexport function reportDispatch(bus: Bus, report: DispatchReport): void {\n const durationMs = performance.now() - report.startedAt;\n bus[PublishDefault]('interactionDispatched', {\n dispatchId: report.dispatchId,\n routeId: report.routeId,\n interactionId: report.interactionId,\n kind: report.kind,\n outcome: report.outcome,\n fallback: report.fallback,\n userId: report.userId,\n guildId: report.guildId,\n durationMs,\n queuedMs: report.queuedMs\n });\n\n // a throwing log sink must not stop the publish above\n logger().trace(\n `${paint.sky.bold(report.routeId)} ${report.outcome} ${paint.mute('in')} ${Math.round(durationMs)}ms`\n );\n}\n","import { asError } from '#stops/asError';\n\nimport { outcomeFor } from './dispatchReport';\n\nimport type { DispatchResult, EventDispatchResult, HandlerResult } from './dispatchResult';\nimport type { Logger } from '@seedcord/logger';\n\ninterface Afterable<Result> {\n after?(result: Result): Promise<void>;\n}\n\n/** @internal */\nexport function resultFor(caught: unknown): DispatchResult {\n return { outcome: outcomeFor(caught), caught };\n}\n\n/**\n * Builds what an event middleware's `after()` receives. `handlers` is empty exactly when the chain\n * stopped the event.\n *\n * @internal\n */\nexport function eventResultFor(\n stopped: { caught: unknown } | null,\n handlers: readonly HandlerResult[]\n): EventDispatchResult {\n if (!stopped) return { outcome: 'handled', handlers };\n return { ...resultFor(stopped.caught), handlers: [] };\n}\n\n/**\n * Calls `after()` on each middleware that ran, newest first. A throw inside one is logged. Every\n * remaining middleware still gets its call.\n *\n * @internal\n */\nexport async function runAfter<Result>(\n ran: readonly Afterable<Result>[],\n result: Result,\n logger: Logger\n): Promise<void> {\n for (let index = ran.length - 1; index >= 0; index--) {\n const middleware = ran[index];\n try {\n await middleware?.after?.(result);\n } catch (caught) {\n logger.error(`${middleware?.constructor.name ?? 'A middleware'} threw from after()`, asError(caught));\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"internal.index.mjs","names":["logger"],"sources":["../src/subscribers/SubscriberLoader.ts","../src/decorators/brands.ts","../src/dispatch/MiddlewareRegistry.ts","../src/gates/runGates.ts","../src/gates/slowGate.ts","../src/miscellaneous/emojiConfig.ts","../src/miscellaneous/currentApplication.ts","../src/miscellaneous/readBotToken.ts","../src/miscellaneous/resolveEmojis.ts","../src/bakedIds.ts","../src/commands/guildSummaries.ts","../src/commands/DeployReporter.ts","../src/commands/deployTarget.ts","../src/commands/isCommandClass.ts","../src/commands/LastDeploy.ts","../src/commands/planDeploy.ts","../src/commands/putCommands.ts","../src/commands/readCommands.ts","../src/commands/slashRouteLeaves.ts","../src/commands/CommandRegistry.ts","../src/hmr/wrapHot.ts","../src/hmr/HmrManager.ts","../src/hmr/wire.ts","../src/hmr/forwardLogsToCli.ts","../src/dispatch/dispatchReport.ts","../src/dispatch/runAfter.ts"],"sourcesContent":["import { paint } from '@seedcord/errors';\nimport { importFiles } from '@seedcord/utils';\nimport { Envapter } from 'envapt';\n\nimport { HmrModuleHandler } from '#hmr/HmrModuleHandler';\nimport { SubscribeMetadataKey } from '#src/metadataKeys';\nimport { busLoggerOf } from '#subscribers/Bus';\nimport { registrationFor, Subscriber } from '#subscribers/index';\nimport {\n RegisterDefaults,\n RegisteredCount,\n RegisterSubscriber,\n UnregisterSubscriber,\n VerifyWebhooks\n} from '#subscribers/slots';\n\nimport type { Initializeable } from '#src/plugin/Plugin';\nimport type { SubscribeMetadataEntry } from '#subscribers/decorators/Subscribe';\nimport type { StoredSubscriberCtor, Bus } from '#subscribers/index';\nimport type { SubscriptionKey } from '#subscribers/types/Subscriptions';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\n\ntype SubscriberArtifact = SubscriptionKey[];\n\nexport class SubscriberLoader implements Initializeable, HmrAware {\n private isInitialized = false;\n private readonly hmrHandler?: HmrModuleHandler<StoredSubscriberCtor, void, SubscriberArtifact>;\n\n constructor(\n private readonly bus: Bus,\n private readonly directory: string | null\n ) {\n if (!this.directory) return;\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n\n this.hmrHandler = new HmrModuleHandler({\n handlersDir: this.directory,\n isHandler: this.isSubscriber.bind(this),\n registerHandler: this.registerSubscriber.bind(this),\n unregisterHandler: this.unregisterSubscriber.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: busLoggerOf(this.bus)\n });\n }\n\n /** @internal */\n public async init(): Promise<void> {\n if (this.isInitialized) return;\n this.isInitialized = true;\n\n this.bus[RegisterDefaults]();\n\n const { directory } = this;\n if (directory) {\n busLoggerOf(this.bus).debug(paint.mute(directory));\n await this.load(directory);\n busLoggerOf(this.bus).utils.list(\n [`${paint.iris.bold(this.bus[RegisteredCount])} subscribers`],\n paint.mint.bold('Loaded'),\n 'debug'\n );\n }\n\n if (!Envapter.isTest) await this.bus[VerifyWebhooks]();\n }\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n if (this.hmrHandler) await this.hmrHandler.handle(event);\n }\n\n private async load(dir: string): Promise<void> {\n for await (const { fullPath, relativePath, imported } of importFiles(dir)) {\n for (const value of Object.values(imported)) {\n if (!this.isSubscriber(value)) continue;\n\n this.registerSubscriber(value);\n this.hmrHandler?.trackHandler(fullPath, value);\n busLoggerOf(this.bus).utils.registration(value.name, relativePath, undefined, 'trace');\n }\n }\n }\n\n private registerSubscriber(ctor: StoredSubscriberCtor): void {\n this.bus[RegisterSubscriber](registrationFor(ctor));\n }\n\n private unregisterSubscriber(ctor: StoredSubscriberCtor, artifacts?: SubscriberArtifact): void {\n this.bus[UnregisterSubscriber](ctor, artifacts);\n }\n\n private getArtifacts(ctor: StoredSubscriberCtor): SubscriberArtifact {\n const meta = Reflect.getMetadata(SubscribeMetadataKey, ctor) as SubscribeMetadataEntry;\n return [meta.subscriber];\n }\n\n private isSubscriber(value: unknown): value is StoredSubscriberCtor {\n if (typeof value !== 'function') return false;\n return value.prototype instanceof Subscriber && Reflect.hasMetadata(SubscribeMetadataKey, value);\n }\n}\n","// phantom, nothing assigns these at runtime\n\nexport const SlashRouteBrand: unique symbol = Symbol('seedcord:brand:slash-route');\nexport const AutocompleteRouteBrand: unique symbol = Symbol('seedcord:brand:autocomplete-route');\nexport const ContextMenuKindBrand: unique symbol = Symbol('seedcord:brand:context-menu-kind');\nexport const ContextMenuNamesBrand: unique symbol = Symbol('seedcord:brand:context-menu-names');\nexport const ComponentKindBrand: unique symbol = Symbol('seedcord:brand:component-kind');\nexport const ComponentDefsBrand: unique symbol = Symbol('seedcord:brand:component-defs');\nexport const MiddlewareKindsBrand: unique symbol = Symbol('seedcord:brand:middleware-kinds');\n","import { interactionMiddlewareMetaOf } from '#decorators/middleware';\n\nimport type { AnyMiddlewareCtor } from '#decorators/middleware';\nimport type { MiddlewareKind } from '#src/metadataKeys';\n\n/**\n * A decorated middleware reduced to what the registry orders and filters on. An absent `keys` puts the\n * middleware in every chain.\n *\n * @internal\n */\nexport interface MiddlewareRegistration<Key extends string> {\n readonly priority: number;\n readonly keys?: readonly Key[];\n}\n\n/**\n * Reads a transport's decorator metadata off a class. Returns `undefined` for an undecorated one.\n *\n * @internal\n */\nexport type MiddlewareRegistrationOf<Ctor, Key extends string> = (\n ctor: Ctor\n) => MiddlewareRegistration<Key> | undefined;\n\n/** @internal */\nexport function interactionMiddleware(ctor: AnyMiddlewareCtor): MiddlewareRegistration<MiddlewareKind> | undefined {\n const metadata = interactionMiddlewareMetaOf(ctor);\n if (!metadata) return undefined;\n return { priority: metadata.priority, ...(metadata.kinds && { keys: metadata.kinds }) };\n}\n\ninterface Entry<Ctor, Key extends string> {\n readonly ctor: Ctor;\n readonly priority: number;\n readonly keys?: ReadonlySet<Key>;\n}\n\n/**\n * Holds the middleware a transport loaded and keeps one chain per key. An interaction keys on its kind\n * and an event on its name. Priority and the key filter behave the same on each.\n *\n * @typeParam Ctor - The transport's middleware constructor type.\n * @typeParam Key - The chain lookup key.\n *\n * @internal\n */\nexport class MiddlewareRegistry<Ctor extends AnyMiddlewareCtor, Key extends string = MiddlewareKind> {\n private readonly entries: Entry<Ctor, Key>[] = [];\n // an in-flight dispatch keeps walking the array chainFor gave it. never mutate one in place.\n private chains = new Map<Key, readonly Ctor[]>();\n\n public constructor(private readonly registrationOf: MiddlewareRegistrationOf<Ctor, Key>) {}\n\n /**\n * Adds a decorated middleware class and returns what it registered with. Returns `undefined` for an\n * undecorated class or one already registered.\n */\n public register(ctor: Ctor): MiddlewareRegistration<Key> | undefined {\n const registration = this.registrationOf(ctor);\n if (!registration) return undefined;\n\n // a double import or an hmr re-scan registers the same class twice\n if (this.entries.some((entry) => entry.ctor === ctor)) return undefined;\n\n this.entries.push({\n ctor,\n priority: registration.priority,\n ...(registration.keys && { keys: new Set(registration.keys) })\n });\n this.rebuild();\n return registration;\n }\n\n public unregister(ctor: Ctor): void {\n const index = this.entries.findIndex((entry) => entry.ctor === ctor);\n if (index === -1) return;\n this.entries.splice(index, 1);\n this.rebuild();\n }\n\n public chainFor(key: Key): readonly Ctor[] {\n const built = this.chains.get(key);\n if (built) return built;\n\n const chain = this.entries.filter((entry) => !entry.keys || entry.keys.has(key)).map((entry) => entry.ctor);\n this.chains.set(key, chain);\n return chain;\n }\n\n private rebuild(): void {\n // a stable sort keeps ties in registration order\n this.entries.sort((a, b) => a.priority - b.priority);\n this.chains = new Map();\n }\n}\n","import 'reflect-metadata';\n\nimport { GatedMetadataKey } from '#src/metadataKeys';\n\nimport { discardCommits, runCheck, runCommits } from './effects';\n\nimport type { Gate, GateContextBase } from './Gate';\n\n// a combinator (`and`/`or`) reports once under its joined name.\nexport type GateObserver = (gateName: string, elapsedMs: number) => void;\n\nasync function timedCheck(gate: Gate<GateContextBase>, ctx: GateContextBase, observe: GateObserver): Promise<void> {\n const start = performance.now();\n // finally so a refusing gate still reports\n try {\n await runCheck(gate, ctx);\n } finally {\n observe(gate.name, performance.now() - start);\n }\n}\n\n// the first refusal throws out to the dispatcher boundary. an effect gate's commit runs once the\n// whole set passes, and observe never times the commit phase.\nexport async function runGates(\n gates: readonly Gate<GateContextBase>[],\n ctx: GateContextBase,\n observe?: GateObserver\n): Promise<void> {\n try {\n for (const gate of gates) {\n await (observe ? timedCheck(gate, ctx, observe) : runCheck(gate, ctx));\n }\n await runCommits(ctx);\n } finally {\n discardCommits(ctx);\n }\n}\n\n// dispatchers call this before execute, inside the boundary, so a refusal renders or drops\nexport async function runHandlerGates(\n handlerCtor: object,\n ctx: GateContextBase,\n declaredRoute?: string,\n observe?: GateObserver\n): Promise<void> {\n // justified: getMetadata returns any, and this key only ever stores the @Gated gate array\n const gates = Reflect.getMetadata(GatedMetadataKey, handlerCtor) as readonly Gate<GateContextBase>[] | undefined;\n if (!gates) return;\n await runGates(gates, { ...ctx, declaredRoute: declaredRoute ?? null }, observe);\n}\n","import { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { Envapter } from 'envapt';\n\nimport type { GateObserver } from './runGates';\n\n// combined check time slower than this cuts into the 3s interaction-ack budget\nconst SLOW_GATE_MS = 750;\n\n// lazy because the logger reads the environment, which binds after this module loads\nlet gateLogger: Logger | undefined;\nfunction logger(): Logger {\n gateLogger ??= new Logger('Gates', { channel: 'gates' });\n return gateLogger;\n}\n\n/**\n * collects each gate check's elapsed time for one dispatch. `report` warns once when the checks sum\n * past the threshold, naming the total, the route, and each gate's share.\n */\nexport interface SlowGateMonitor {\n readonly observe: GateObserver;\n report(declaredRoute: string | null): void;\n}\n\n// undefined in production, so timedCheck skips the clock there. read per call, the environment binds late\nexport function slowGateMonitor(): SlowGateMonitor | undefined {\n if (Envapter.isProduction) return undefined;\n const readings: { name: string; ms: number }[] = [];\n return {\n observe: (name, ms) => readings.push({ name, ms }),\n report(declaredRoute) {\n const total = readings.reduce((sum, reading) => sum + reading.ms, 0);\n if (total < SLOW_GATE_MS) return;\n const shares = readings\n .toSorted((a, b) => b.ms - a.ms)\n .map((reading) => `${paint.sky.bold(reading.name)} ${paint.mute(`${Math.round(reading.ms)}ms`)}`);\n const route = declaredRoute === null ? '' : ` for ${paint.sky.bold(declaredRoute)}`;\n const headline = `gates${route} took ${paint.amber(`${Math.round(total)}ms`)} of the 3s ack budget`;\n logger().utils.block(headline, shares, 'warn', (text) => text);\n }\n };\n}\n","// narrows a configured emoji value to the [name, guildId] form\nexport function isEmojiTuple(value: unknown): value is readonly [string, string] {\n return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string' && typeof value[1] === 'string';\n}\n","import { Routes } from 'discord-api-types/v10';\n\nimport type { REST } from '@discordjs/rest';\nimport type { RESTGetCurrentApplicationResult } from 'discord-api-types/v10';\n\nexport async function currentApplication(rest: Pick<REST, 'get'>): Promise<RESTGetCurrentApplicationResult> {\n // justified: the discord api contract for this route\n return (await rest.get(Routes.currentApplication())) as RESTGetCurrentApplicationResult;\n}\n","import { validateDiscordToken } from '@seedcord/errors/internal';\nimport { Envapter } from 'envapt';\n\nimport type { BotToken } from '@seedcord/errors/internal';\n\nexport function readBotToken(): BotToken {\n return validateDiscordToken(Envapter.get('DISCORD_BOT_TOKEN'));\n}\n","import { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError, SeedcordTypeError, throwSingleOrAggregate } from '@seedcord/errors/internal';\nimport { asError } from '@seedcord/utils/internal';\nimport { Routes } from 'discord-api-types/v10';\n\nimport { isEmojiTuple } from '#src/miscellaneous/emojiConfig';\nimport { accessorStore } from '#src/miscellaneous/guarded';\nimport { ResolvedEmoji } from '#src/miscellaneous/ResolvedEmoji';\n\nimport type { REST } from '@discordjs/rest';\nimport type { APIEmoji, RESTGetAPIApplicationEmojisResult, RESTGetAPIGuildEmojisResult } from 'discord-api-types/v10';\n\ntype EmojiRest = Pick<REST, 'get'>;\n\ntype EmojisByName = Map<string, APIEmoji>;\n\nfunction byName(list: readonly APIEmoji[]): EmojisByName {\n const map: EmojisByName = new Map();\n for (const entry of list) if (entry.name) map.set(entry.name, entry);\n return map;\n}\n\nclass EmojiResolver {\n private readonly resolved = accessorStore<ResolvedEmoji>();\n private readonly problems: Error[] = [];\n private readonly guilds = new Map<string, EmojisByName | Error>();\n private application?: EmojisByName | Error;\n\n constructor(\n private readonly rest: EmojiRest,\n private readonly applicationId: string\n ) {}\n\n public async resolve(configured: Readonly<Record<string, unknown>>): Promise<Record<string, ResolvedEmoji>> {\n for (const [key, value] of Object.entries(configured)) {\n if (isEmojiTuple(value)) await this.fromGuild(key, value);\n else if (typeof value === 'string') await this.fromApplication(key, value);\n else this.problems.push(new SeedcordTypeError(SeedcordErrorCode.ConfigEmojiInvalid, [key]));\n }\n\n throwSingleOrAggregate(this.problems, SeedcordErrorCode.ConfigEmojiUnresolved);\n return this.resolved;\n }\n\n private async fromApplication(key: string, name: string): Promise<void> {\n this.application ??= await this.applicationEmojis();\n\n if (Error.isError(this.application)) {\n this.unreadable(\n key,\n name,\n 'the application',\n this.application,\n `Check that ${paint.bold('DISCORD_BOT_TOKEN')} is still valid.`\n );\n return;\n }\n this.pick(key, name, this.application, 'the application');\n }\n\n private async applicationEmojis(): Promise<EmojisByName | Error> {\n try {\n // justified: the discord api contract for this route\n const listed = (await this.rest.get(\n Routes.applicationEmojis(this.applicationId)\n )) as RESTGetAPIApplicationEmojisResult;\n return byName(listed.items);\n } catch (error) {\n return asError(error);\n }\n }\n\n private async fromGuild(key: string, [name, guildId]: readonly [string, string]): Promise<void> {\n let guild = this.guilds.get(guildId);\n if (!guild) {\n guild = await this.guildEmojis(guildId);\n this.guilds.set(guildId, guild);\n }\n\n if (Error.isError(guild)) {\n this.unreadable(key, name, `guild ${guildId}`, guild, 'Check that the bot is in that guild.');\n return;\n }\n this.pick(key, name, guild, `guild ${guildId}`);\n }\n\n private async guildEmojis(guildId: string): Promise<EmojisByName | Error> {\n try {\n // justified: the discord api contract for this route\n return byName((await this.rest.get(Routes.guildEmojis(guildId))) as RESTGetAPIGuildEmojisResult);\n } catch (error) {\n return asError(error);\n }\n }\n\n private pick(key: string, name: string, source: EmojisByName, where: string): void {\n const found = source.get(name);\n if (!found?.id) {\n this.problems.push(new SeedcordError(SeedcordErrorCode.ConfigEmojiNotFound, [key, name, where]));\n return;\n }\n this.resolved[key] = new ResolvedEmoji(name, found.id, found.animated ?? false);\n }\n\n private unreadable(key: string, name: string, where: string, cause: Error, fix: string): void {\n this.problems.push(\n new SeedcordError(SeedcordErrorCode.ConfigEmojiSourceUnreadable, [key, name, where, cause.message, fix], {\n cause\n })\n );\n }\n}\n\nexport function resolveEmojis(\n rest: EmojiRest,\n applicationId: string,\n configured: Readonly<Record<string, unknown>>\n): Promise<Record<string, ResolvedEmoji>> {\n return new EmojiResolver(rest, applicationId).resolve(configured);\n}\n","import type { LinkedCommands } from '#src/commands/linkCommands';\nimport type { ResolvedEmoji } from '#src/miscellaneous/ResolvedEmoji';\n\nexport const BAKED_IDS_KEY = 'seedcord:core:baked-ids';\n\nexport interface BakedIds {\n readonly publicKey: string;\n readonly emojis: Readonly<Record<string, Pick<ResolvedEmoji, 'name' | 'id' | 'animated'>>>;\n readonly commands: LinkedCommands['commands'];\n readonly contextMenus: LinkedCommands['contextMenus'];\n}\n","import { Routes } from 'discord-api-types/v10';\n\nimport type { REST } from '@discordjs/rest';\nimport type { RESTGetAPIGuildResult } from 'discord-api-types/v10';\n\nexport interface GuildSummary {\n id: string;\n name: string;\n}\n\ntype ReadRest = Pick<REST, 'get'>;\n\n// the name is only a label. a guild the bot cannot read keeps its id as one\nasync function guildName(rest: ReadRest, guildId: string): Promise<string> {\n try {\n // justified: the discord api contract for the guild route\n return ((await rest.get(Routes.guild(guildId))) as RESTGetAPIGuildResult).name;\n } catch {\n return guildId;\n }\n}\n\nexport function guildSummaries(\n rest: ReadRest,\n guildIds: Iterable<string>,\n knownNames: ReadonlyMap<string, string> = new Map()\n): Promise<GuildSummary[]> {\n return Promise.all(\n Iterator.from(guildIds).map(async (id) => ({ id, name: knownNames.get(id) ?? (await guildName(rest, id)) }))\n );\n}\n","import { paint } from '@seedcord/errors';\nimport { pluralize, unlessAborted } from '@seedcord/utils/internal';\n\nimport { getDevChannel } from '#hmr/devChannel';\nimport { guildSummaries } from '#src/commands/guildSummaries';\nimport { GLOBAL_ID, skippedNote } from '#src/commands/scopes';\n\nimport type { CommandBody } from '#src/commands/putCommands';\nimport type { ScopeId } from '#src/commands/scopes';\nimport type { REST } from '@discordjs/rest';\nimport type { Logger } from '@seedcord/logger';\n\nexport class DeployReporter {\n private readonly guildNames = new Map<string, string>();\n\n constructor(private readonly logger: Logger) {}\n\n // only seedcord dev reads guild names\n public async readGuildNames(\n rest: Pick<REST, 'get'>,\n scopes: readonly ScopeId[],\n signal: AbortSignal | undefined\n ): Promise<void> {\n if (!getDevChannel()) return;\n const unread = scopes.filter((scope) => scope !== GLOBAL_ID && !this.guildNames.has(scope));\n for (const { id, name } of await unlessAborted(guildSummaries(rest, unread), signal)) {\n this.guildNames.set(id, name);\n }\n }\n\n public skipped(scopes: readonly ScopeId[]): void {\n if (scopes.length > 0) this.logger.info(skippedNote(scopes, (guildId) => this.guildLabel(guildId)));\n }\n\n public deployed(scope: ScopeId, commands: readonly CommandBody[]): void {\n const { utils } = this.logger;\n const count = paint.iris.bold(commands.length);\n const tag = pluralize(commands.length, 'command');\n const title =\n scope === GLOBAL_ID\n ? `Deployed ${count} global ${tag}`\n : `Deployed ${count} ${tag} to ${this.guildLabel(scope)}`;\n\n utils.block(title, utils.wrap(commands.map((command) => command.name)), 'info');\n }\n\n private guildLabel(guildId: string): string {\n return paint.sky.bold(this.guildNames.get(guildId) ?? guildId);\n }\n}\n","import { SeedcordErrorCode } from '@seedcord/errors';\nimport { SeedcordTypeError } from '@seedcord/errors/internal';\n\nimport { ConfigGuilds } from '#decorators/Command';\n\nimport type { CommandMeta } from '#decorators/Command';\n\nexport type DeployTarget = Exclude<CommandMeta, { scope: 'config' }>;\n\nexport function resolveDeployTarget(\n meta: CommandMeta,\n configured: readonly string[],\n commandName: string\n): DeployTarget {\n if (meta.scope === 'global') return { scope: 'global' };\n\n if (meta.scope === 'config') {\n return configured.length > 0 ? guildTarget(configured) : { scope: 'global' };\n }\n\n if (configured.length === 0 && meta.guilds.includes(ConfigGuilds)) {\n throw new SeedcordTypeError(SeedcordErrorCode.CoreCommandGuildsEmpty, [commandName]);\n }\n\n return guildTarget(meta.guilds.flatMap((target) => (target === ConfigGuilds ? configured : target)));\n}\n\n// a repeated id would push the same builder into one guild twice, and discord rejects a duplicate name in the put\nfunction guildTarget(guilds: readonly string[]): DeployTarget {\n return { scope: 'guild', guilds: [...new Set(guilds)] };\n}\n","import { isBuilderComponentClass } from '#components/Component';\nimport { CommandMetadataKey } from '#src/metadataKeys';\n\nimport type { BuilderComponent } from '#components/Component';\nimport type { Constructor } from 'type-fest';\n\n/** @internal */\nexport type CommandCtor = Constructor<BuilderComponent<'command' | 'context_menu'>, never[]>;\n\n// the cli's codegen scan reads this too\n/** @internal */\nexport function isCommandClass(value: unknown): value is CommandCtor {\n return isBuilderComponentClass(value) && Reflect.hasMetadata(CommandMetadataKey, value);\n}\n","import { unlessAborted } from '@seedcord/utils/internal';\n\nimport { getDevChannel } from '#hmr/devChannel';\n\nimport type { DeployedHashes, SeedcordCliEvents } from '@seedcord/types/internal';\n\n// seedcord dev answers from one small file\n// something has really gone wrong if this times out\nconst ANSWER_TIMEOUT_MS = 5000;\n\nexport class LastDeploy {\n private saved?: Promise<DeployedHashes | undefined>;\n\n public read(applicationId: string, signal: AbortSignal | undefined): Promise<DeployedHashes | undefined> {\n this.saved ??= askSeedcordDev(applicationId);\n return unlessAborted(this.saved, signal);\n }\n\n public save(deployed: DeployedHashes): void {\n this.saved = Promise.resolve(deployed);\n getDevChannel()?.send('seedcord:commands-deployed', deployed);\n }\n}\n\nfunction askSeedcordDev(applicationId: string): Promise<DeployedHashes | undefined> {\n const cli = getDevChannel();\n if (!cli) return Promise.resolve(undefined);\n const { promise, resolve } = Promise.withResolvers<DeployedHashes | undefined>();\n const settle = (deployed: DeployedHashes | undefined): void => {\n clearTimeout(timer);\n cli.off('seedcord:last-deploy', onAnswer);\n resolve(deployed);\n };\n const onAnswer = ({ deployed }: SeedcordCliEvents['seedcord:last-deploy']): void => settle(deployed);\n const timer = setTimeout(() => settle(undefined), ANSWER_TIMEOUT_MS);\n cli.on('seedcord:last-deploy', onAnswer);\n cli.send('seedcord:read-deployed', { applicationId });\n return promise;\n}\n","import { commandKey } from '#src/commands/linkCommands';\nimport { globalFirst } from '#src/commands/scopes';\n\nimport type { CommandBody, CommandScopes } from '#src/commands/putCommands';\nimport type { ScopeId } from '#src/commands/scopes';\nimport type { DeployResult } from '#src/commands/types';\nimport type { DeployedHashes } from '@seedcord/types/internal';\nimport type { APIApplicationCommand } from 'discord-api-types/v10';\n\ntype ScopeHashes = DeployedHashes['scopes'];\n\ninterface DeployPlan {\n hashes: ScopeHashes;\n // saved before the PUTs in case one fails\n skippedHashes: ScopeHashes;\n toPut: CommandScopes;\n skipped: ScopeId[];\n onDiscord: DeployResult;\n}\n\nconst HEX = 16;\n\nfunction byCodePoint(a: string, b: string): number {\n return a < b ? -1 : Number(a > b);\n}\n\nasync function hashOf(commands: readonly CommandBody[]): Promise<string> {\n // load order differs between the CLI scan and the registry\n const sorted = commands.toSorted((a, b) => byCodePoint(commandKey(a), commandKey(b)));\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(JSON.stringify(sorted)));\n return [...new Uint8Array(digest)].map((byte) => byte.toString(HEX).padStart(2, '0')).join('');\n}\n\nasync function scopeHashes(scopes: CommandScopes): Promise<ScopeHashes> {\n const hashed = [...scopes].map(async ([scope, commands]) => [scope, await hashOf(commands)] as const);\n return Object.fromEntries(await Promise.all(hashed));\n}\n\nfunction sameCommandNames(\n inCode: readonly CommandBody[],\n deployed: Map<string, APIApplicationCommand> | undefined\n): boolean {\n const onDiscord = new Set(deployed?.values().map(commandKey));\n return new Set(inCode.map(commandKey)).symmetricDifference(onDiscord).size === 0;\n}\n\nexport async function planDeploy(\n scopes: CommandScopes,\n last: ScopeHashes | undefined,\n readUnchanged: (scopes: ScopeId[]) => Promise<DeployResult>\n): Promise<DeployPlan> {\n const hashes = await scopeHashes(scopes);\n const unchanged = globalFirst(scopes).filter(([scope]) => hashes[scope] === last?.[scope]);\n const onDiscord = await readUnchanged(unchanged.map(([scope]) => scope));\n const skipped = new Set(\n unchanged\n .filter(([scope, commands]) => sameCommandNames(commands, onDiscord.get(scope)))\n .map(([scope]) => scope)\n );\n return {\n hashes,\n skippedHashes: Object.fromEntries(Object.entries(hashes).filter(([scope]) => skipped.has(scope))),\n toPut: new Map(scopes.entries().filter(([scope]) => !skipped.has(scope))),\n skipped: [...skipped],\n onDiscord\n };\n}\n","import { DiscordAPIError, HTTPError, RESTEvents } from '@discordjs/rest';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { asError, unlessAborted } from '@seedcord/utils/internal';\n\nimport { indexById } from '#src/commands/linkCommands';\nimport { commandsRoute, GLOBAL_ID, globalFirst } from '#src/commands/scopes';\n\nimport type { ScopeId } from '#src/commands/scopes';\nimport type { DeployResult } from '#src/commands/types';\nimport type { RateLimitData, REST } from '@discordjs/rest';\nimport type { ILogger } from '@seedcord/types';\nimport type { APIApplicationCommand, RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v10';\n\nexport type CommandBody = RESTPostAPIApplicationCommandsJSONBody;\n\n// a scope left out keeps what discord has. an empty list clears it\nexport type CommandScopes = ReadonlyMap<ScopeId, readonly CommandBody[]>;\n\ninterface PutCommandsOptions {\n readonly rest: Pick<REST, 'put' | 'on' | 'off'>;\n readonly applicationId: string;\n readonly logger: Pick<ILogger, 'warn'>;\n readonly signal?: AbortSignal | undefined;\n readonly onDeployed?: (scope: ScopeId, commands: readonly CommandBody[]) => void;\n}\n\nconst MS_PER_SECOND = 1000;\n\n// discord replaces every command in a scope with the PUT body\nexport async function putCommands(scopes: CommandScopes, options: PutCommandsOptions): Promise<DeployResult> {\n const result: DeployResult = new Map();\n for (const [scope, commands] of globalFirst(scopes)) {\n result.set(scope, indexById(await putScope(scope, commands, options)));\n options.onDeployed?.(scope, commands);\n }\n return result;\n}\n\nasync function putScope(\n scope: ScopeId,\n commands: readonly CommandBody[],\n options: PutCommandsOptions\n): Promise<APIApplicationCommand[]> {\n try {\n return await put(commandsRoute(options.applicationId, scope), commands, options);\n } catch (error) {\n if (options.signal?.aborted) throw error;\n const refusal: [string, number | undefined] = [asError(error).message, statusOf(error)];\n throw scope === GLOBAL_ID\n ? new SeedcordError(SeedcordErrorCode.CoreCommandGlobalDeployFailed, refusal, { cause: error })\n : new SeedcordError(SeedcordErrorCode.CoreCommandGuildDeployFailed, [scope, ...refusal], { cause: error });\n }\n}\n\nfunction statusOf(error: unknown): number | undefined {\n return error instanceof DiscordAPIError || error instanceof HTTPError ? error.status : undefined;\n}\n\nasync function put(\n route: `/${string}`,\n body: readonly CommandBody[],\n { rest, logger, signal }: PutCommandsOptions\n): Promise<APIApplicationCommand[]> {\n const reportWait = (info: RateLimitData): void => {\n if (info.method !== 'PUT' || !info.url.endsWith(route)) return;\n const seconds = Math.ceil(info.timeToReset / MS_PER_SECOND);\n logger.warn(`Discord rate-limited the command deploy. It continues in ${paint.amber(`${seconds}s`)}.`);\n };\n\n rest.on(RESTEvents.RateLimited, reportWait);\n try {\n // @discordjs/rest checks the signal before it sends a request. Its rate-limit sleep ignores it\n // justified: the bulk-overwrite routes return the deployed command array\n return (await unlessAborted(rest.put(route, { body, signal }), signal)) as APIApplicationCommand[];\n } finally {\n rest.off(RESTEvents.RateLimited, reportWait);\n }\n}\n","import { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { asError } from '@seedcord/utils/internal';\n\nimport { indexById } from '#src/commands/linkCommands';\nimport { commandsRoute, GLOBAL_ID } from '#src/commands/scopes';\n\nimport type { ScopeId } from '#src/commands/scopes';\nimport type { DeployResult } from '#src/commands/types';\nimport type { REST } from '@discordjs/rest';\nimport type { APIApplicationCommand, RESTGetAPIApplicationCommandsResult } from 'discord-api-types/v10';\n\ninterface ReadCommandsOptions {\n readonly rest: Pick<REST, 'get'>;\n readonly applicationId: string;\n readonly signal?: AbortSignal | undefined;\n}\n\nexport async function readCommandsAt(\n scope: ScopeId,\n { rest, applicationId, signal }: ReadCommandsOptions\n): Promise<Map<string, APIApplicationCommand>> {\n const route = commandsRoute(applicationId, scope);\n try {\n // justified: the discord api contract for both command list routes\n return indexById((await rest.get(route, { signal })) as RESTGetAPIApplicationCommandsResult);\n } catch (error) {\n if (signal?.aborted) throw error;\n const reason = asError(error).message;\n throw new SeedcordError(\n SeedcordErrorCode.CoreDiscordReadFailed,\n scope === GLOBAL_ID\n ? ['the commands deployed globally', reason]\n : [\n `the commands deployed to guild ${paint.sky(scope)}`,\n reason,\n `Check that ${paint.bold('DISCORD_BOT_TOKEN')} is still valid and that the bot is in that guild.`\n ],\n { cause: error }\n );\n }\n}\n\nexport async function readCommands(scopes: Iterable<ScopeId>, options: ReadCommandsOptions): Promise<DeployResult> {\n const read = Iterator.from(scopes).map(async (scope) => [scope, await readCommandsAt(scope, options)] as const);\n return new Map(await Promise.all(read));\n}\n","import { SlashCommandBuilder } from '@discordjs/builders';\nimport { routeLeavesOf } from '@seedcord/utils/internal';\n\nimport type { ContextMenuCommandBuilder } from '@discordjs/builders';\n\n/**\n * dedupes route keys since the same builder appears once per guild.\n * these come from the same {@link routeLeavesOf} that `seedcord codegen` reads, so the boot-time\n * check compares against the generated registry's keys.\n *\n * @internal\n */\nexport function slashRouteLeaves(commands: Iterable<SlashCommandBuilder | ContextMenuCommandBuilder>): Set<string> {\n const leaves = new Set<string>();\n for (const command of commands) {\n if (!(command instanceof SlashCommandBuilder)) continue;\n for (const leaf of routeLeavesOf(command.toJSON())) leaves.add(leaf.route);\n }\n return leaves;\n}\n","import { SlashCommandBuilder } from '@discordjs/builders';\nimport { SeedcordErrorCode, paint } from '@seedcord/errors';\nimport { SeedcordError } from '@seedcord/errors/internal';\nimport { Logger } from '@seedcord/logger';\nimport { formatFilePath, importFiles } from '@seedcord/utils';\nimport { botFolder } from '@seedcord/utils/internal';\nimport { Envapter } from 'envapt';\n\nimport { getDevChannel } from '#hmr/devChannel';\nimport { HmrModuleHandler } from '#hmr/HmrModuleHandler';\nimport { CommandInjector } from '#src/commands/CommandInjector';\nimport { contextMenuLeaves } from '#src/commands/contextMenuLeaves';\nimport { DeployReporter } from '#src/commands/DeployReporter';\nimport { resolveDeployTarget } from '#src/commands/deployTarget';\nimport { isCommandClass } from '#src/commands/isCommandClass';\nimport { LastDeploy } from '#src/commands/LastDeploy';\nimport { planDeploy } from '#src/commands/planDeploy';\nimport { putCommands } from '#src/commands/putCommands';\nimport { readCommands } from '#src/commands/readCommands';\nimport { GLOBAL_ID, scopeIdsOf } from '#src/commands/scopes';\nimport { slashRouteLeaves } from '#src/commands/slashRouteLeaves';\nimport { CommandMetadataKey } from '#src/metadataKeys';\nimport { PublishDefault } from '#subscribers/publishDefault';\n\nimport type { CommandMeta } from '#decorators/Command';\nimport type { CoreBase } from '#interfaces/CoreBase';\nimport type { ContextMenuLeaves } from '#src/commands/contextMenuLeaves';\nimport type { DeployTarget } from '#src/commands/deployTarget';\nimport type { CommandCtor } from '#src/commands/isCommandClass';\nimport type { CommandBody, CommandScopes } from '#src/commands/putCommands';\nimport type { ScopeId } from '#src/commands/scopes';\nimport type { CommandBuilder, DeployResult } from '#src/commands/types';\nimport type { Initializeable } from '#src/plugin/Plugin';\nimport type { AllSubscriptions } from '#subscribers/types/Subscriptions';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { APIApplicationCommand } from 'discord-api-types/v10';\n\ntype CommandArtifact = DeployTarget & { name: string };\n\n// gateway's and http's InteractionDispatcher both fit this\ninterface RouteWarnings {\n warnUnhandledRoutes(leaves: Iterable<string>): void;\n warnUnhandledContextMenuRoutes(leaves: ContextMenuLeaves): void;\n}\n\ninterface DeployHooks {\n routes?: RouteWarnings | undefined;\n check?: (commands: CommandBuilder[]) => void;\n}\n\n// discord's global command bucket allows 2 PUTs a minute\n// 75s covers a full wait plus the request itself\nexport const COMMAND_DEPLOY_TIMEOUT_MS = 75_000;\n\n/**\n * Scans the command directory, builds each command, and PUTs the global and guild scopes to Discord.\n *\n * @internal\n */\nexport class CommandRegistry implements Initializeable, HmrAware {\n private readonly logger = new Logger('Commands', { channel: 'commands' });\n private isInitialised = false;\n\n public readonly scopedCommands = new Map<ScopeId, CommandBuilder[]>();\n\n private readonly ctorToCommand = new Map<CommandCtor, CommandArtifact>();\n\n // batched during bulk load. A reload reports on the hmr channel instead\n private loading = false;\n private readonly loadedCommands: { name: string; from: string; kind: 'slash command' | 'context menu' }[] = [];\n\n private readonly hmrHandler?: HmrModuleHandler<CommandCtor, void, CommandArtifact | undefined>;\n private readonly pendingEvents = new Map<string, HmrUpdateEvent>();\n private readonly injector = new CommandInjector();\n private readonly lastDeploy = new LastDeploy();\n private readonly reporter = new DeployReporter(this.logger);\n\n private readonly dir: string;\n private readonly configuredGuilds: readonly string[];\n\n public constructor(private readonly core: CoreBase) {\n const { commands } = core.config.bot;\n if (!commands.path) {\n throw new SeedcordError(SeedcordErrorCode.CoreControllerPathMissing, ['CommandRegistry', 'commands']);\n }\n this.dir = commands.path;\n this.configuredGuilds = commands.guilds ?? [];\n\n if (!Envapter.isDevelopment && !Envapter.isTest) return;\n this.hmrHandler = new HmrModuleHandler<CommandCtor, void, CommandArtifact | undefined>({\n handlersDir: this.dir,\n isHandler: isCommandClass,\n registerHandler: this.registerCommand.bind(this),\n unregisterHandler: this.unregisterCommand.bind(this),\n getArtifacts: this.getArtifacts.bind(this),\n logger: this.logger\n });\n }\n\n private getArtifacts(ctor: CommandCtor): CommandArtifact | undefined {\n return this.ctorToCommand.get(ctor);\n }\n\n /** @internal */\n public async init(): Promise<void> {\n if (this.isInitialised) return;\n this.isInitialised = true;\n\n this.loading = true;\n this.loadedCommands.length = 0;\n try {\n await this.loadCommands(this.dir);\n } finally {\n this.loading = false;\n }\n\n this.reportLoad();\n\n getDevChannel()?.on('seedcord:refresh-commands', (data) => {\n void this.refresh(data.shouldRefresh);\n });\n }\n\n private reportLoad(): void {\n const { utils } = this.logger;\n\n utils.summary(\n 'Loaded commands',\n {\n global: this.scopedCommands.get(GLOBAL_ID)?.length ?? 0,\n 'guild groups': [...this.scopedCommands.keys()].filter((scope) => scope !== GLOBAL_ID).length\n },\n 'debug'\n );\n\n let slash = 0;\n let menu = 0;\n for (const command of this.loadedCommands) {\n if (command.kind === 'slash command') slash++;\n else menu++;\n }\n\n utils.block(\n 'Loaded commands',\n [\n ...utils.entries(this.loadedCommands),\n ...utils.counts({ 'slash commands': slash, 'context menus': menu })\n ],\n 'debug'\n );\n }\n\n /** @internal */\n public async refresh(shouldRefresh = true): Promise<void> {\n if (!shouldRefresh) {\n this.logger.debug(paint.italic('Command refresh cancelled.'));\n this.pendingEvents.clear();\n return;\n }\n\n this.logger.debug(paint.italic('Refreshing commands...'));\n for (const event of this.pendingEvents.values()) {\n await this.hmrHandler?.handle(event);\n }\n this.pendingEvents.clear();\n await this.setCommands();\n }\n\n /** @internal */\n public async onHmr(event: HmrUpdateEvent): Promise<void> {\n if (botFolder(this.dir).holds(event.file)) {\n this.pendingEvents.delete(event.file);\n this.pendingEvents.set(event.file, event);\n getDevChannel()?.send('seedcord:commands-update-prompt', {\n files: [...this.pendingEvents.keys()].map((f) => formatFilePath(f))\n });\n } else {\n await this.hmrHandler?.handle(event);\n }\n }\n\n private async loadCommands(dir: string): Promise<void> {\n for await (const { fullPath, relativePath, imported } of importFiles(dir)) {\n for (const exported of Object.values(imported)) {\n if (!isCommandClass(exported)) continue;\n this.registerCommand(exported, relativePath);\n this.hmrHandler?.trackHandler(fullPath, exported);\n }\n }\n }\n\n private registerCommand(Ctor: CommandCtor, rel: string): void {\n const meta = Reflect.getMetadata(CommandMetadataKey, Ctor) as CommandMeta | undefined;\n\n if (!meta) return;\n\n const instance = new Ctor();\n const comp = instance.component;\n const kind = comp instanceof SlashCommandBuilder ? 'slash command' : 'context menu';\n\n const target = resolveDeployTarget(meta, this.configuredGuilds, Ctor.name);\n\n for (const scope of scopeIdsOf(target)) {\n const inScope = this.scopedCommands.get(scope);\n if (inScope) inScope.push(comp);\n else this.scopedCommands.set(scope, [comp]);\n }\n\n this.ctorToCommand.set(Ctor, { name: comp.name, ...target });\n\n if (this.loading) {\n this.loadedCommands.push({ name: comp.name, from: formatFilePath(rel), kind });\n }\n }\n\n private unregisterCommand(ctor: CommandCtor, artifacts?: CommandArtifact): void {\n const info = artifacts ?? this.ctorToCommand.get(ctor);\n if (!info) return;\n\n for (const scope of scopeIdsOf(info)) {\n const inScope = this.scopedCommands.get(scope) ?? [];\n const idx = inScope.findIndex((c) => c.name === info.name);\n if (idx !== -1) inScope.splice(idx, 1);\n }\n this.ctorToCommand.delete(ctor);\n }\n\n /** @internal */\n public async deploy(signal: AbortSignal, { routes, check }: DeployHooks): Promise<void> {\n await this.init();\n check?.(this.allCommands());\n await this.setCommands(signal);\n routes?.warnUnhandledRoutes(this.routeLeaves());\n routes?.warnUnhandledContextMenuRoutes(this.contextMenuLeaves());\n }\n\n /** @internal */\n public async setCommands(signal?: AbortSignal): Promise<DeployResult> {\n // read here because gateway assigns core.rest after this registry is constructed\n const { rest, applicationId } = this.core;\n const last = await this.lastDeploy.read(applicationId, signal);\n const plan = await planDeploy(this.commandBodies(), last?.scopes, (unchanged) =>\n readCommands(unchanged, { rest, applicationId, signal })\n );\n await this.reporter.readGuildNames(rest, [...plan.toPut.keys(), ...plan.skipped], signal);\n if (plan.toPut.size > 0) this.lastDeploy.save({ applicationId, scopes: plan.skippedHashes });\n const put = await putCommands(plan.toPut, {\n rest,\n applicationId,\n logger: this.logger,\n signal,\n onDeployed: (scope: ScopeId, commands: readonly CommandBody[]) => this.reporter.deployed(scope, commands)\n });\n\n this.reporter.skipped(plan.skipped);\n const result: DeployResult = new Map([...plan.onDiscord, ...put]);\n this.lastDeploy.save({ applicationId, scopes: plan.hashes });\n\n this.injector.inject(result, this.allCommands());\n this.core.bus[PublishDefault]('commandsDeployed', deployedPayload(result));\n return result;\n }\n\n private commandBodies(): CommandScopes {\n // a guild-only start keeps the global commands another deploy put there\n const deployable = this.scopedCommands\n .entries()\n .filter(([scope, commands]) => scope !== GLOBAL_ID || commands.length > 0);\n return new Map(deployable.map(([scope, commands]) => [scope, commands.map((c) => c.toJSON())]));\n }\n\n private allCommands(): CommandBuilder[] {\n return [...this.scopedCommands.values()].flat();\n }\n\n private routeLeaves(): Set<string> {\n return slashRouteLeaves(this.allCommands());\n }\n\n private contextMenuLeaves(): ContextMenuLeaves {\n return contextMenuLeaves(this.allCommands().map((command) => command.toJSON()));\n }\n}\n\nfunction deployedPayload(result: DeployResult): AllSubscriptions['commandsDeployed'] {\n const guilds: Record<string, APIApplicationCommand[]> = {};\n for (const [scope, deployed] of result) {\n if (scope !== GLOBAL_ID) guilds[scope] = [...deployed.values()];\n }\n return { global: [...(result.get(GLOBAL_ID)?.values() ?? [])], guilds };\n}\n","import type { DevChannel } from '@seedcord/types/internal';\n\n// the minimal raw-hot shape, satisfied by both vite's `import.meta.hot` and the CLI's `NormalizedHotChannel`.\ninterface RawHot {\n send(event: string, data?: unknown): void;\n on(event: string, cb: (data: unknown) => void): void;\n off(event: string, cb: (data: unknown) => void): void;\n}\n\n/** @internal */\nexport function wrapHot<TSend, TRecv>(hot: RawHot): DevChannel<TSend, TRecv> {\n return {\n send: (event, data) => hot.send(event, data),\n // justified: RawHot types every payload as unknown, and the wire contract guarantees it matches TRecv[Key]\n on: (event, cb) => hot.on(event, cb as (data: unknown) => void),\n // justified: the same cast as on()\n off: (event, cb) => hot.off(event, cb as (data: unknown) => void)\n };\n}\n","// scoped here so import.meta.hot stays untyped in the rest of the package\n/// <reference types=\"vite/client\" />\nimport { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { Envapter } from 'envapt';\n\nimport { getDevChannel, setDevChannel } from './devChannel';\nimport { wrapHot } from './wrapHot';\n\nimport type { CliChannel } from './devChannel';\nimport type { HmrAware, HmrUpdateEvent } from '@seedcord/types';\nimport type { SeedcordCliEvents, SeedcordFrameworkEvents } from '@seedcord/types/internal';\n\n// the only raw `import.meta.hot` read in the framework\nexport function connectDevChannel(): CliChannel | undefined {\n if (import.meta.hot) setDevChannel(wrapHot<SeedcordFrameworkEvents, SeedcordCliEvents>(import.meta.hot));\n return getDevChannel();\n}\n\nexport class HmrManager {\n private readonly logger = new Logger('HMR', { channel: 'hmr' });\n private readonly listeners = new Set<HmrAware>();\n\n public init(channel: CliChannel | undefined): void {\n if (!channel) return;\n\n if (!(Envapter.isDevelopment || Envapter.isTest)) {\n return;\n }\n\n this.logger.debug('Enabled');\n channel.on('seedcord:hmr', (payload) => void this.handleUpdate(payload));\n }\n\n public register(listener: HmrAware): void {\n this.listeners.add(listener);\n }\n\n private async handleUpdate(event: HmrUpdateEvent): Promise<void> {\n const promises = [...this.listeners].map(async (listener) => {\n try {\n await listener.onHmr(event);\n } catch (error) {\n this.logger.error(`Error handling HMR update in ${paint.sky.bold(listener.constructor.name)}`, error);\n }\n });\n\n await Promise.all(promises);\n }\n}\n","import { LEVEL_COLOR } from '@seedcord/logger';\nimport { filterCirculars } from '@seedcord/utils';\nimport { isPlainObject } from '@seedcord/utils/internal';\n\nimport type { LogLevel, LogRecord } from '@seedcord/types';\nimport type { WireError } from '@seedcord/types/internal';\n\n// each arg is either an Error or a JSON-safe value\ntype WireArg = { error: WireError } | { value: unknown };\n\ninterface WireLogRecord extends Omit<LogRecord, 'args'> {\n args?: WireArg[] | undefined;\n}\n\nexport function toWireError(thrown: unknown): WireError {\n return encodeError(thrown, new Set());\n}\n\nfunction encodeError(thrown: unknown, sent: Set<Error>): WireError {\n if (!Error.isError(thrown)) return { name: 'Error', message: String(thrown) };\n sent.add(thrown);\n const unsent = (value: unknown): boolean => !Error.isError(value) || !sent.has(value);\n const { cause } = thrown;\n return {\n name: thrown.name,\n message: thrown.message,\n stack: thrown.stack,\n code: Reflect.get(thrown, 'code'),\n cause: cause !== undefined && unsent(cause) ? encodeError(cause, sent) : undefined,\n errors:\n thrown instanceof AggregateError\n ? thrown.errors.filter(unsent).map((member) => encodeError(member, sent))\n : undefined\n };\n}\n\nexport function fromWireError({ name, message, stack, code, cause, errors }: WireError): Error {\n const options = cause && { cause: fromWireError(cause) };\n const error = errors\n ? new AggregateError(errors.map(fromWireError), message, options)\n : new Error(message, options);\n error.name = name;\n if (stack !== undefined) error.stack = stack;\n if (code !== undefined) Reflect.set(error, 'code', code);\n return error;\n}\n\n// node's console.log text for a function or a class\nfunction functionText(fn: { readonly name: string }): string {\n const parent: unknown = Object.getPrototypeOf(fn);\n if (Function.prototype.toString.call(fn).startsWith('class')) {\n const extended = typeof parent === 'function' && parent.name ? ` extends ${parent.name}` : '';\n return `[class ${fn.name || '(anonymous)'}${extended}]`;\n }\n const kind = parent === null ? 'Function (null prototype)' : fn.constructor.name;\n return fn.name ? `[${kind}: ${fn.name}]` : `[${kind} (anonymous)]`;\n}\n\nfunction toWireArg(arg: unknown): WireArg {\n if (Error.isError(arg)) return { error: toWireError(arg) };\n // JSON can't hold undefined, a symbol, a bigint or a function\n switch (typeof arg) {\n case 'undefined':\n case 'symbol': {\n return { value: String(arg) };\n }\n case 'bigint': {\n return { value: `${arg}n` };\n }\n case 'function': {\n return { value: functionText(arg) };\n }\n default: {\n return { value: filterCirculars(arg, { mode: 'json' }) };\n }\n }\n}\n\nfunction fromWireArg(arg: WireArg): unknown {\n return 'error' in arg ? fromWireError(arg.error) : arg.value;\n}\n\nfunction toWireLog({ args, ...record }: LogRecord): WireLogRecord {\n return { ...record, args: args?.map(toWireArg) };\n}\n\nfunction fromWireLog({ args, ...record }: WireLogRecord): LogRecord {\n return args ? { ...record, args: args.map(fromWireArg) } : record;\n}\n\n// seedcord dev's workerLogger reads these lines back out of the worker's console output\nconst DEV_LOG_MARKER = 'seedcord:log ';\n\nexport function toDevLogLine(record: LogRecord): string {\n return `${DEV_LOG_MARKER}${JSON.stringify(toWireLog(record))}`;\n}\n\nfunction isLogLevel(value: unknown): value is LogLevel {\n return typeof value === 'string' && Object.hasOwn(LEVEL_COLOR, value);\n}\n\nfunction isWireError(value: unknown): value is WireError {\n return (\n isPlainObject(value) &&\n typeof value.name === 'string' &&\n typeof value.message === 'string' &&\n (value.stack === undefined || typeof value.stack === 'string') &&\n (value.cause === undefined || isWireError(value.cause)) &&\n (value.errors === undefined || (Array.isArray(value.errors) && value.errors.every(isWireError)))\n );\n}\n\nfunction isWireArg(value: unknown): value is WireArg {\n if (!isPlainObject(value)) return false;\n return 'error' in value ? isWireError(value.error) : 'value' in value;\n}\n\nfunction isWireArgs(value: unknown): value is WireLogRecord['args'] {\n return value === undefined || (Array.isArray(value) && value.every(isWireArg));\n}\n\nfunction isWireLogRecord(value: unknown): value is WireLogRecord {\n return (\n isPlainObject(value) &&\n isLogLevel(value.level) &&\n typeof value.message === 'string' &&\n typeof value.label === 'string' &&\n typeof value.channel === 'string' &&\n typeof value.timestamp === 'number' &&\n isWireArgs(value.args)\n );\n}\n\n// the bot's own console output can start with the marker too\nexport function fromDevLogLine(line: string): LogRecord | undefined {\n if (!line.startsWith(DEV_LOG_MARKER)) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line.slice(DEV_LOG_MARKER.length));\n } catch {\n return undefined;\n }\n return isWireLogRecord(parsed) ? fromWireLog(parsed) : undefined;\n}\n","import { format } from 'node:util';\n\nimport { LoggerChannelRegistry } from '@seedcord/logger';\nimport { CONSOLE_LEVEL, consoleRecord, routeConsole, traceError } from '@seedcord/logger/internal';\n\nimport { toDevLogLine } from './wire';\n\nimport type { ConsoleMethod } from '@seedcord/logger/internal';\n\n// workerd's Console prints the arguments of these and nothing for group, count or time\nconst WORKER_ROUTED = [\n 'debug',\n 'dir',\n 'dirxml',\n 'error',\n 'info',\n 'log',\n 'table',\n 'trace',\n 'warn'\n] as const satisfies readonly ConsoleMethod[];\n\n// workaround: workerd cancels a hot.send made during a request. @cloudflare/vite-plugin's runner never awaits it.\n// move this back to the dev channel once the plugin gets fixed\nexport function forwardLogsToCli(): void {\n const registry = LoggerChannelRegistry.instance;\n // eslint-disable-next-line no-console -- console is the transport\n const print = console.log.bind(console);\n registry.installSink({ kind: 'capture', onLog: (record) => print(toDevLogLine(record)) }, { muteConsole: true });\n routeConsole(WORKER_ROUTED, (method, args, invoked) => {\n const level = CONSOLE_LEVEL[method];\n if (method === 'trace') {\n registry.dispatch(consoleRecord(level, '', [traceError(format(...args), invoked)]));\n return;\n }\n const [first, ...rest] = args;\n registry.dispatch(\n typeof first === 'string' ? consoleRecord(level, first, rest) : consoleRecord(level, '', args)\n );\n });\n}\n","import { paint } from '@seedcord/errors';\nimport { Logger } from '@seedcord/logger';\nimport { timestampFromSnowflake } from '@seedcord/utils';\n\nimport { Notice } from '#stops/Notice';\nimport { Silence } from '#stops/Silence';\nimport { PublishDefault } from '#subscribers/publishDefault';\n\nimport type { InteractionKind } from '#src/metadataKeys';\nimport type { Bus } from '#subscribers/Bus';\nimport type { DispatchOutcome } from '#subscribers/types/Subscriptions';\n\nlet dispatchLogger: Logger | undefined;\nfunction logger(): Logger {\n dispatchLogger ??= new Logger('Dispatch', { channel: 'interactions' });\n return dispatchLogger;\n}\n\n/**\n * Classifies a caught stop for `interactionDispatched` so a gate and a\n * handler label the same stop identically.\n *\n * @internal\n */\nexport function outcomeFor(caught: unknown): Exclude<DispatchOutcome, 'handled'> {\n if (caught instanceof Silence) return 'refused';\n if (caught instanceof Notice) return caught.report ? 'failed' : 'refused';\n return 'failed';\n}\n\ninterface DispatchReport {\n readonly dispatchId: string;\n readonly routeId: string;\n readonly interactionId: string;\n readonly kind: `${InteractionKind}`;\n readonly outcome: DispatchOutcome;\n /** True when no route matched and the unhandled default ran. */\n readonly fallback: boolean;\n readonly userId: string | null;\n readonly guildId: string | null;\n /** `performance.now()` captured as the dispatch began. */\n readonly startedAt: number;\n /** {@link queuedMsFor} read at the same moment as `startedAt`. */\n readonly queuedMs: number;\n}\n\n/**\n * Discord's interaction creation to now, read from the snowflake. Called at dispatch entry, since\n * a later read would count the handler run into the queue time as well.\n *\n * @internal\n */\nexport function queuedMsFor(interactionId: string): number {\n // timestampFromSnowflake throws on a malformed id\n try {\n return Date.now() - timestampFromSnowflake(interactionId);\n } catch {\n return 0;\n }\n}\n\nexport function reportDispatch(bus: Bus, report: DispatchReport): void {\n const durationMs = performance.now() - report.startedAt;\n bus[PublishDefault]('interactionDispatched', {\n dispatchId: report.dispatchId,\n routeId: report.routeId,\n interactionId: report.interactionId,\n kind: report.kind,\n outcome: report.outcome,\n fallback: report.fallback,\n userId: report.userId,\n guildId: report.guildId,\n durationMs,\n queuedMs: report.queuedMs\n });\n\n // a throwing log sink must not stop the publish above\n logger().trace(\n `${paint.sky.bold(report.routeId)} ${report.outcome} ${paint.mute('in')} ${Math.round(durationMs)}ms`\n );\n}\n","import { asError } from '@seedcord/utils/internal';\n\nimport { outcomeFor } from './dispatchReport';\n\nimport type { DispatchResult, EventDispatchResult, HandlerResult } from './dispatchResult';\nimport type { Logger } from '@seedcord/logger';\n\ninterface Afterable<Result> {\n after?(result: Result): Promise<void>;\n}\n\n/** @internal */\nexport function resultFor(caught: unknown): DispatchResult {\n return { outcome: outcomeFor(caught), caught };\n}\n\n/**\n * Builds what an event middleware's `after()` receives. `handlers` is empty exactly when the chain\n * stopped the event.\n *\n * @internal\n */\nexport function eventResultFor(\n stopped: { caught: unknown } | null,\n handlers: readonly HandlerResult[]\n): EventDispatchResult {\n if (!stopped) return { outcome: 'handled', handlers };\n return { ...resultFor(stopped.caught), handlers: [] };\n}\n\n/**\n * Calls `after()` on each middleware that ran, newest first. A throw inside one is logged. Every\n * remaining middleware still gets its call.\n *\n * @internal\n */\nexport async function runAfter<Result>(\n ran: readonly Afterable<Result>[],\n result: Result,\n logger: Logger\n): Promise<void> {\n for (let index = ran.length - 1; index >= 0; index--) {\n const middleware = ran[index];\n try {\n await middleware?.after?.(result);\n } catch (caught) {\n logger.error(`${middleware?.constructor.name ?? 'A middleware'} threw from after()`, asError(caught));\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import "./
|
|
4
|
-
import { i as Initializeable } from "./Plugin-Dhx_ivqj.mjs";
|
|
5
|
-
import { t as ContextMenuLeaves } from "./contextMenuLeaves-COzDYa6c.mjs";
|
|
6
|
-
import { a as LifecycleTask, i as CoordinatedShutdown, n as shutdownOf } from "./Pluggable-CwKbLui3.mjs";
|
|
1
|
+
import { n as StartupPhase, t as ShutdownPhase } from "./phases-FTM69J3a.mjs";
|
|
2
|
+
import { r as LifecycleTask, t as CoordinatedShutdown } from "./CoordinatedShutdown-H5YjZn8A.mjs";
|
|
3
|
+
import { n as shutdownOf } from "./ServerHost-DYeh0KTk.mjs";
|
|
7
4
|
import { Logger } from "@seedcord/logger";
|
|
8
5
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
9
|
-
import { HealthCheckConfig, HealthCheckOption
|
|
6
|
+
import { HealthCheckConfig, HealthCheckOption } from "@seedcord/types";
|
|
10
7
|
//#region src/node/Lifecycle/drainWindow.d.ts
|
|
11
8
|
export declare const DRAIN_WINDOW_MS = 5000;
|
|
12
9
|
export declare const DRAIN_TASK_TIMEOUT_MS: number;
|
|
13
|
-
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/node/Lifecycle/InFlight.d.ts
|
|
12
|
+
export declare class InFlight {
|
|
13
|
+
private readonly logger;
|
|
14
|
+
private readonly label;
|
|
15
|
+
private readonly running;
|
|
16
|
+
private isClosed;
|
|
17
|
+
constructor(logger: Logger, label: string);
|
|
18
|
+
get closed(): boolean;
|
|
19
|
+
close(): void;
|
|
20
|
+
track(work: Promise<unknown>): void;
|
|
21
|
+
drain(timeoutMs: number): Promise<void>;
|
|
22
|
+
private settleAll;
|
|
23
|
+
}
|
|
14
24
|
//#endregion
|
|
15
25
|
//#region src/node/HealthCheck.d.ts
|
|
16
26
|
export declare class HealthCheck {
|
|
@@ -32,73 +42,18 @@ export declare class HealthCheck {
|
|
|
32
42
|
export declare class HealthResponder {
|
|
33
43
|
readonly path: string;
|
|
34
44
|
constructor(path?: string);
|
|
45
|
+
static fromOption(option?: HealthCheckOption): HealthResponder | undefined;
|
|
35
46
|
tryRespond(req: IncomingMessage, res: ServerResponse): boolean;
|
|
47
|
+
answer(request: Request, ready: boolean): Response | undefined;
|
|
48
|
+
private matches;
|
|
49
|
+
private body;
|
|
36
50
|
}
|
|
37
51
|
//#endregion
|
|
38
|
-
//#region src/
|
|
52
|
+
//#region src/lifecycle/withTimeout.d.ts
|
|
39
53
|
export declare function settleWithin(work: Promise<unknown>, timeoutMs: number): Promise<void>;
|
|
40
54
|
//#endregion
|
|
41
|
-
//#region src/node/
|
|
42
|
-
export declare
|
|
43
|
-
private readonly bus;
|
|
44
|
-
private readonly directory;
|
|
45
|
-
private isInitialized;
|
|
46
|
-
private readonly hmrHandler?;
|
|
47
|
-
constructor(bus: Bus, directory: string | null);
|
|
48
|
-
/** @internal */
|
|
49
|
-
init(): Promise<void>;
|
|
50
|
-
/** @internal */
|
|
51
|
-
onHmr(event: HmrUpdateEvent): Promise<void>;
|
|
52
|
-
private load;
|
|
53
|
-
private registerSubscriber;
|
|
54
|
-
private unregisterSubscriber;
|
|
55
|
-
private getArtifacts;
|
|
56
|
-
private isSubscriber;
|
|
57
|
-
}
|
|
58
|
-
//#endregion
|
|
59
|
-
//#region src/node/commands/CommandRegistry.d.ts
|
|
60
|
-
/**
|
|
61
|
-
* Scans the command directory, builds each command, and PUTs the global and guild scopes to Discord.
|
|
62
|
-
*
|
|
63
|
-
* @internal
|
|
64
|
-
*/
|
|
65
|
-
export declare class CommandRegistry implements Initializeable, HmrAware {
|
|
66
|
-
private readonly core;
|
|
67
|
-
private readonly logger;
|
|
68
|
-
private isInitialised;
|
|
69
|
-
readonly globalCommands: CommandBuilder[];
|
|
70
|
-
readonly guildCommands: Map<string, CommandBuilder[]>;
|
|
71
|
-
private readonly ctorToCommand;
|
|
72
|
-
private loading;
|
|
73
|
-
private readonly loadedCommands;
|
|
74
|
-
private readonly hmrHandler?;
|
|
75
|
-
private readonly pendingEvents;
|
|
76
|
-
private readonly injector;
|
|
77
|
-
private readonly dir;
|
|
78
|
-
private readonly configuredGuilds;
|
|
79
|
-
constructor(core: CoreBase);
|
|
80
|
-
private getArtifacts;
|
|
81
|
-
/** @internal */
|
|
82
|
-
init(): Promise<void>;
|
|
83
|
-
private reportLoad;
|
|
84
|
-
/** @internal */
|
|
85
|
-
refresh(shouldRefresh?: boolean): Promise<void>;
|
|
86
|
-
/** @internal */
|
|
87
|
-
onHmr(event: HmrUpdateEvent): Promise<void>;
|
|
88
|
-
private loadCommands;
|
|
89
|
-
private registerCommand;
|
|
90
|
-
private unregisterCommand;
|
|
91
|
-
/** @internal */
|
|
92
|
-
setCommands(): Promise<DeployResult>;
|
|
93
|
-
private putGuild;
|
|
94
|
-
private put;
|
|
95
|
-
/** Every registered builder, global first. A guild command in N guilds appears once per guild. @internal */
|
|
96
|
-
allCommands(): CommandBuilder[];
|
|
97
|
-
/** @internal */
|
|
98
|
-
routeLeaves(): Set<string>;
|
|
99
|
-
/** @internal */
|
|
100
|
-
contextMenuLeaves(): ContextMenuLeaves;
|
|
101
|
-
}
|
|
55
|
+
//#region src/node/envaptBaseDir.d.ts
|
|
56
|
+
export declare function setEnvaptBaseDir(): void;
|
|
102
57
|
//#endregion
|
|
103
58
|
export { type LifecycleTask, ShutdownPhase, StartupPhase, shutdownOf };
|
|
104
59
|
//# sourceMappingURL=node-internal.index.d.mts.map
|