meocord 4.2.2 → 4.2.3

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.
Files changed (136) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/dist/cjs/_shared/{controller.decorator-U2NBWcoU.cjs → controller.decorator-hp5xdJU4.cjs} +512 -183
  3. package/dist/cjs/_shared/{startup-roots-lA5xkBFq.cjs → event-sources-DzqTODXg.cjs} +265 -80
  4. package/dist/cjs/_shared/{providers-B4MOFBrW.cjs → providers-BBvbnmLP.cjs} +780 -281
  5. package/dist/cjs/_shared/{sharded-cooldown-store-HTUb3Ii_.cjs → sharded-cooldown-store-B62g5O88.cjs} +11 -9
  6. package/dist/cjs/_shared/{translate-error-CbBHUu5P.cjs → translate-error-wsgfsUET.cjs} +1 -1
  7. package/dist/cjs/common/index.cjs +4 -104
  8. package/dist/cjs/core/index.cjs +432 -181
  9. package/dist/cjs/decorator/index.cjs +85 -120
  10. package/dist/cjs/testing/index.cjs +1664 -784
  11. package/dist/cli.json +1 -1
  12. package/dist/esm/bin/app-template/package.json.template +9 -9
  13. package/dist/esm/bin/app-template/src/main.ts.template +3 -2
  14. package/dist/esm/bin/generator.js +6 -4
  15. package/dist/esm/bin/helper/filter-generator.helper.js +6 -4
  16. package/dist/esm/bin/helper/guard-generator.helper.js +6 -4
  17. package/dist/esm/bin/helper/interceptor-generator.helper.js +6 -4
  18. package/dist/esm/bin/helper/observer-generator.helper.js +6 -4
  19. package/dist/esm/bin/helper/pipe-generator.helper.js +6 -4
  20. package/dist/esm/bin/helper/service-generator.helper.js +6 -4
  21. package/dist/esm/bin/meocord.js +106 -48
  22. package/dist/esm/build/native-addons.js +75 -19
  23. package/dist/esm/build/rsbuild-config.js +11 -3
  24. package/dist/esm/build/typed-externals.js +15 -2
  25. package/dist/esm/common/cooldown-store.js +38 -14
  26. package/dist/esm/common/deprecation.js +4 -1
  27. package/dist/esm/common/execution-context.js +3 -1
  28. package/dist/esm/common/explained-error.js +7 -3
  29. package/dist/esm/common/log-level.js +13 -9
  30. package/dist/esm/common/logger.js +4 -2
  31. package/dist/esm/common/meocord-text.js +11 -6
  32. package/dist/esm/common/redis-cooldown-store.js +3 -7
  33. package/dist/esm/common/response/flags.js +17 -1
  34. package/dist/esm/common/response/install-context.js +27 -16
  35. package/dist/esm/common/response/presenter.js +7 -3
  36. package/dist/esm/common/response/response-state.js +27 -5
  37. package/dist/esm/common/sharded-cooldown-store.js +11 -9
  38. package/dist/esm/common/theme.js +3 -1
  39. package/dist/esm/common/translator.js +17 -8
  40. package/dist/esm/core/autocomplete-routes.js +26 -0
  41. package/dist/esm/core/command-conflicts.js +15 -7
  42. package/dist/esm/core/command-registration.js +15 -1
  43. package/dist/esm/core/cooldown-runner.js +7 -9
  44. package/dist/esm/core/defer.js +2 -5
  45. package/dist/esm/core/dispatcher.js +83 -58
  46. package/dist/esm/core/event-requirements.js +67 -19
  47. package/dist/esm/core/event-sources.js +100 -0
  48. package/dist/esm/core/fallback.js +3 -1
  49. package/dist/esm/core/filter-runner.js +4 -4
  50. package/dist/esm/core/guard-runner.js +173 -52
  51. package/dist/esm/core/handler-input.js +24 -3
  52. package/dist/esm/core/handler-pipeline.js +44 -28
  53. package/dist/esm/core/handler-registry.js +51 -21
  54. package/dist/esm/core/input-runner.js +7 -8
  55. package/dist/esm/core/interceptor-runner.js +4 -5
  56. package/dist/esm/core/lifecycle-hooks.js +3 -8
  57. package/dist/esm/core/lifecycle-order.js +1 -15
  58. package/dist/esm/core/meocord-classes.js +14 -1
  59. package/dist/esm/core/meocord-factory.js +80 -53
  60. package/dist/esm/core/meocord.app.js +174 -89
  61. package/dist/esm/core/message-help.js +5 -9
  62. package/dist/esm/core/message-params.js +126 -46
  63. package/dist/esm/core/message-routes.js +225 -45
  64. package/dist/esm/core/message-words.js +30 -2
  65. package/dist/esm/core/observer-runner.js +2 -1
  66. package/dist/esm/core/process-state.js +19 -0
  67. package/dist/esm/core/providers.js +28 -3
  68. package/dist/esm/core/scalar-types.js +57 -16
  69. package/dist/esm/core/shard-context.js +11 -10
  70. package/dist/esm/core/shard-exit.js +3 -3
  71. package/dist/esm/core/shard-manager.js +16 -6
  72. package/dist/esm/core/startup-roots.js +28 -8
  73. package/dist/esm/core/theme-resolvers.js +26 -11
  74. package/dist/esm/core/theme-runtime.js +23 -13
  75. package/dist/esm/core/theme-scope.js +27 -29
  76. package/dist/esm/core/theme-validation.js +1 -1
  77. package/dist/esm/decorator/app.decorator.js +6 -1
  78. package/dist/esm/decorator/command-builder.decorator.js +14 -0
  79. package/dist/esm/decorator/controller-class.decorator.js +1 -1
  80. package/dist/esm/decorator/controller.decorator.js +48 -19
  81. package/dist/esm/decorator/defer.decorator.js +2 -2
  82. package/dist/esm/decorator/event.decorator.js +4 -5
  83. package/dist/esm/decorator/filter.decorator.js +2 -2
  84. package/dist/esm/decorator/guard.decorator.js +4 -61
  85. package/dist/esm/decorator/inject.decorator.js +4 -1
  86. package/dist/esm/decorator/interceptor.decorator.js +2 -2
  87. package/dist/esm/decorator/theme.decorator.js +4 -3
  88. package/dist/esm/decorator/validation.decorator.js +5 -5
  89. package/dist/esm/package.json.js +1 -1
  90. package/dist/esm/testing/catalog.js +29 -13
  91. package/dist/esm/testing/cooldown-store-suite.js +3 -3
  92. package/dist/esm/testing/discord-defaults.js +449 -355
  93. package/dist/esm/testing/inspect-handler.js +91 -10
  94. package/dist/esm/testing/meocord-testing-module.js +195 -77
  95. package/dist/esm/testing/mock-fn.js +8 -2
  96. package/dist/esm/testing/mock-interaction.js +639 -113
  97. package/dist/esm/testing/response-log.js +8 -0
  98. package/dist/esm/testing/response.js +7 -5
  99. package/dist/esm/testing/routing.js +48 -6
  100. package/dist/esm/testing/strict-mocks.js +1 -0
  101. package/dist/esm/testing/theme.js +3 -2
  102. package/dist/esm/util/common.util.js +30 -9
  103. package/dist/esm/util/generator-cli.util.js +6 -4
  104. package/dist/esm/util/inherited-env.util.js +72 -13
  105. package/dist/esm/util/json.util.js +10 -3
  106. package/dist/esm/util/meocord-cli.util.js +3 -2
  107. package/dist/esm/util/meocord-config-loader.util.js +14 -1
  108. package/dist/esm/util/meocord-config-validation.util.js +13 -3
  109. package/dist/esm/util/meocord-source-config.util.js +13 -3
  110. package/dist/esm/util/platform.util.js +3 -2
  111. package/dist/esm/util/refusal.util.js +29 -11
  112. package/dist/esm/util/registration-mode.util.js +14 -1
  113. package/dist/esm/util/timer-limit.util.js +4 -1
  114. package/dist/esm/util/tsconfig-paths.util.js +38 -7
  115. package/dist/esm/util/tsconfig.util.js +16 -58
  116. package/dist/esm/util/user-text.util.js +8 -4
  117. package/dist/esm/util/value.util.js +15 -4
  118. package/dist/types/common/index.d.cts +13 -9
  119. package/dist/types/common/index.d.ts +13 -9
  120. package/dist/types/core/index.d.cts +21 -11
  121. package/dist/types/core/index.d.ts +21 -11
  122. package/dist/types/decorator/index.d.cts +63 -63
  123. package/dist/types/decorator/index.d.ts +63 -63
  124. package/dist/types/{index-DKJclIi-.d.ts → index-Brkd6QGL.d.ts} +81 -35
  125. package/dist/types/{index-Dlf0ZZtS.d.cts → index-CqXImwF_.d.cts} +81 -35
  126. package/dist/types/interface/index.d.cts +1 -1
  127. package/dist/types/interface/index.d.ts +1 -1
  128. package/dist/types/{route-Bh1U13yy.d.ts → route-IQrK-MN2.d.cts} +11 -3
  129. package/dist/types/{route-Bh1U13yy.d.cts → route-bI-okq7g.d.ts} +11 -3
  130. package/dist/types/testing/index.d.cts +137 -54
  131. package/dist/types/testing/index.d.ts +137 -54
  132. package/dist/types/{theme-resolvers-CyEz9pnv.d.cts → theme-resolvers-AtgeaYqF.d.cts} +1 -1
  133. package/dist/types/{theme-resolvers-DA204O-q.d.ts → theme-resolvers-BgqysV8d.d.ts} +1 -1
  134. package/dist/types/{translator-Bg7hwxDF.d.cts → translator-D8aydlCE.d.ts} +12 -11
  135. package/dist/types/{translator-CeP4bCzp.d.ts → translator-iJhDlgwL.d.cts} +12 -11
  136. package/package.json +5 -2
@@ -1,12 +1,68 @@
1
1
  import { CooldownStore } from '../common/index.js';
2
2
  import { BuildableCommandType, CommandBuilderOptions, CommandBuilderBase, PIPED_BRAND, CommandBuilderConstructor, CommandInteractionType, MessageHandlerOptions, CheckedParams, ReactionHandlerSettings, ReactionEvent, ControllerOptions, StageParams, GuardOptions, GuardInterface, InterceptorOptions, InterceptorInterface, ExceptionFilter, Provider, CooldownStoreFailure, ResponsePresenter, MessageCommandOptions, DispatchObserver, RootTheme, ThemeResolvers, ThemeResolver, PipeInterface, StandardSchemaV1, ValidatePipes, ValidateOptions, InferSchemaOutput, CooldownOptions, ProviderToken, ObserverOptions, ThemeOverride } from '../interface/index.js';
3
- import { AutocompleteInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, RoleSelectMenuInteraction, ChannelSelectMenuInteraction, MentionableSelectMenuInteraction, OmitPartialGroupDMChannel, Message, MessageReaction, PartialMessageReaction, ClientEvents, ClientOptions, ActivityOptions } from 'discord.js';
3
+ import { ClientEvents, AutocompleteInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, RoleSelectMenuInteraction, ChannelSelectMenuInteraction, MentionableSelectMenuInteraction, OmitPartialGroupDMChannel, Message, MessageReaction, PartialMessageReaction, ClientOptions, ActivityOptions } from 'discord.js';
4
4
  import { CommandType } from '../enum/index.js';
5
5
  import { Route, RouteParams, RouteValues, RouteValue } from '../common/index.js';
6
6
  import { ServiceIdentifier } from 'inversify';
7
7
  import { Translator } from '../common/index.js';
8
8
  import '@rsbuild/core';
9
9
 
10
+ /**
11
+ * Handles a discord.js client event every time it is emitted, on a controller or a service.
12
+ *
13
+ * Use it for gateway events MeoCord has no handler type for, such as a member joining or a channel being
14
+ * created. For commands, components, messages and reactions, use {@link Command}, `@MessageHandler` or
15
+ * `@ReactionHandler`, which route them.
16
+ *
17
+ * @remarks
18
+ * The handler's parameters are typed from discord.js's `ClientEvents`. It runs through the pipeline, so the app's
19
+ * global guards apply to it, and its class's and its own, and an error it throws is logged without stopping the bot. Handling `interactionCreate`
20
+ * or `messageCreate` here runs alongside MeoCord's own dispatch of them.
21
+ *
22
+ * @param event - The client event to handle, such as `'guildMemberAdd'`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * @On('guildMemberAdd')
27
+ * async greet(member: GuildMember) {
28
+ * await member.send(`Welcome to ${member.guild.name}!`)
29
+ * }
30
+ * ```
31
+ *
32
+ * @pipeline handler with the guards, interceptors and filters that apply to events: the app's global ones, its class's and its own
33
+ * @group Decorators
34
+ * @category Handlers
35
+ * @see {@link Once}
36
+ * @see {@link https://meocord.dev/docs/4.2/gateway-events | Gateway events}
37
+ */
38
+ declare function On<E extends keyof ClientEvents>(event: E): <F extends (...args: ClientEvents[E]) => unknown>(target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<F>) => void;
39
+ /**
40
+ * Handles a discord.js client event the first time it is emitted only, on a controller or a service.
41
+ *
42
+ * Use it for one-off work on an event, such as warming a cache once the client is ready. For every emission,
43
+ * use {@link On}; for work at startup and shutdown, a service's `onReady` and `onShutdown` hooks.
44
+ *
45
+ * @param event - The client event to handle, such as `'clientReady'`.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * @Service()
50
+ * export class CacheWarmer {
51
+ * @Once('clientReady')
52
+ * async warm(client: Client<true>) {
53
+ * await client.guilds.fetch()
54
+ * }
55
+ * }
56
+ * ```
57
+ *
58
+ * @pipeline handler with the guards, interceptors and filters that apply to events: the app's global ones, its class's and its own
59
+ * @group Decorators
60
+ * @category Handlers
61
+ * @see {@link On}
62
+ * @see {@link https://meocord.dev/docs/4.2/gateway-events | Gateway events}
63
+ */
64
+ declare function Once<E extends keyof ClientEvents>(event: E): <F extends (...args: ClientEvents[E]) => unknown>(target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<F>) => void;
65
+
10
66
  /**
11
67
  * Marks a class as a service, which controllers and other services inject by its type.
12
68
  *
@@ -424,62 +480,6 @@ declare function Autocomplete<_R = unknown>(commandPath: string, optionName?: st
424
480
  */
425
481
  declare function Controller(options?: ControllerOptions): (target: abstract new (...args: any[]) => unknown, propertyKey?: string | symbol) => void;
426
482
 
427
- /**
428
- * Handles a discord.js client event every time it is emitted, on a controller or a service.
429
- *
430
- * Use it for gateway events MeoCord has no handler type for, such as a member joining or a channel being
431
- * created. For commands, components, messages and reactions, use {@link Command}, `@MessageHandler` or
432
- * `@ReactionHandler`, which route them.
433
- *
434
- * @remarks
435
- * The handler's parameters are typed from discord.js's `ClientEvents`. It runs through the pipeline, so the app's
436
- * global guards apply to it, and its class's and its own, and an error it throws is logged without stopping the bot. Handling `interactionCreate`
437
- * or `messageCreate` here runs alongside MeoCord's own dispatch of them.
438
- *
439
- * @param event - The client event to handle, such as `'guildMemberAdd'`.
440
- *
441
- * @example
442
- * ```ts
443
- * @On('guildMemberAdd')
444
- * async greet(member: GuildMember) {
445
- * await member.send(`Welcome to ${member.guild.name}!`)
446
- * }
447
- * ```
448
- *
449
- * @pipeline handler with the guards, interceptors and filters that apply to events: the app's global ones, its class's and its own
450
- * @group Decorators
451
- * @category Handlers
452
- * @see {@link Once}
453
- * @see {@link https://meocord.dev/docs/4.2/gateway-events | Gateway events}
454
- */
455
- declare function On<E extends keyof ClientEvents>(event: E): <F extends (...args: ClientEvents[E]) => unknown>(target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<F>) => void;
456
- /**
457
- * Handles a discord.js client event the first time it is emitted only, on a controller or a service.
458
- *
459
- * Use it for one-off work on an event, such as warming a cache once the client is ready. For every emission,
460
- * use {@link On}; for work at startup and shutdown, a service's `onReady` and `onShutdown` hooks.
461
- *
462
- * @param event - The client event to handle, such as `'clientReady'`.
463
- *
464
- * @example
465
- * ```ts
466
- * @Service()
467
- * export class CacheWarmer {
468
- * @Once('clientReady')
469
- * async warm(client: Client<true>) {
470
- * await client.guilds.fetch()
471
- * }
472
- * }
473
- * ```
474
- *
475
- * @pipeline handler with the guards, interceptors and filters that apply to events: the app's global ones, its class's and its own
476
- * @group Decorators
477
- * @category Handlers
478
- * @see {@link On}
479
- * @see {@link https://meocord.dev/docs/4.2/gateway-events | Gateway events}
480
- */
481
- declare function Once<E extends keyof ClientEvents>(event: E): <F extends (...args: ClientEvents[E]) => unknown>(target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<F>) => void;
482
-
483
483
  /**
484
484
  * One entry of `@UseGuard`, `@UseInterceptor`, `@UseFilter`, `@UsePipe` or `@MeoCord`'s lists, checked
485
485
  * against the class it provides: `params` against the params the class declares. An entry typed only as
@@ -735,8 +735,8 @@ declare function UseFilter<const T extends readonly unknown[]>(...filters: {
735
735
  * @see {@link MeoCordConfig}
736
736
  */
737
737
  interface MeoCordOptions<G extends readonly unknown[] = readonly unknown[], I extends readonly unknown[] = readonly unknown[], F extends readonly unknown[] = readonly unknown[]> {
738
- /** Controllers to register. */
739
- controllers: ServiceIdentifier[];
738
+ /** Controllers to register: their classes. */
739
+ controllers: (abstract new (...args: any[]) => any)[];
740
740
  /**
741
741
  * Options for the discord.js `Client`, such as its intents and partials. The shards it runs as are set in
742
742
  * `meocord.config.ts`, under `sharding`.
@@ -835,10 +835,10 @@ interface MeoCordOptions<G extends readonly unknown[] = readonly unknown[], I ex
835
835
  /**
836
836
  * Themes by where a call comes from: `guild` for a server's, over the handler's, and `user` for a user's, over the
837
837
  * server's, in a server or a DM. Each returns part of a theme or `undefined`, at once or as a promise, and is looked
838
- * up while `@Defer` acknowledges, before the guards. A result that is not a valid theme is left out, with a warning
839
- * once per server or user; a resolver that fails or passes its timeout leaves its theme out of the call, logged once
840
- * until it answers again. A class implementing {@link ThemeResolver} does the same with the app's services, resolved
841
- * from its container.
838
+ * up while `@Defer` acknowledges, before the guards. A result that is not a valid theme, as is one that cannot be
839
+ * read, such as an object with a cycle or a getter that throws, is left out, with a warning once per server or user;
840
+ * a resolver that fails or passes its timeout leaves its theme out of the call, logged once until it answers again.
841
+ * A class implementing {@link ThemeResolver} does the same with the app's services, resolved from its container.
842
842
  */
843
843
  themeFor?: ThemeResolvers | (new (...args: any[]) => ThemeResolver);
844
844
  /**
@@ -307,9 +307,10 @@ interface ResponseSendOptions {
307
307
  */
308
308
  interface ResponseCall {
309
309
  /**
310
- * The Discord method it used; `message.edit` edits the message itself, once the interaction's token has expired.
310
+ * The Discord method it used; `respond` answers an autocomplete with its choices, and `message.edit` edits the message
311
+ * itself, once the interaction's token has expired.
311
312
  */
312
- method: 'deferReply' | 'deferUpdate' | 'reply' | 'update' | 'editReply' | 'followUp' | 'deleteReply' | 'showModal' | 'message.edit';
313
+ method: 'deferReply' | 'deferUpdate' | 'reply' | 'update' | 'editReply' | 'followUp' | 'deleteReply' | 'showModal' | 'launchActivity' | 'sendPremiumRequired' | 'respond' | 'message.edit';
313
314
  /** What was sent, as that method received it; none for a deferral or a deletion. */
314
315
  payload?: unknown;
315
316
  /** What the call rejected with, such as the `DiscordAPIError` for a refused call; absent when it succeeded. */
@@ -794,7 +795,8 @@ declare abstract class ExecutionContext {
794
795
  /**
795
796
  * The response state of the interaction being handled, the same one `respond(interaction)` returns,
796
797
  * or `undefined` for anything that cannot be answered: a message, a reaction, an event or
797
- * autocomplete.
798
+ * autocomplete. An `@On('interactionCreate')` handler's call has none either, as MeoCord answers that interaction
799
+ * through the handler it dispatches it to.
798
800
  */
799
801
  get response(): ResponseState | undefined;
800
802
  /**
@@ -834,11 +836,19 @@ declare abstract class ExecutionContext {
834
836
  * {@link ExecutionContext.getHandlerParams} returns.
835
837
  */
836
838
  abstract getArgs(): readonly unknown[];
837
- /** The interaction being handled, or `undefined` for a message, reaction or event. */
839
+ /**
840
+ * The interaction being handled, or `undefined` for a message or a reaction. For an event, the interaction it
841
+ * carries, as `@On('interactionCreate')` does; `undefined` for any other event.
842
+ */
838
843
  abstract getInteraction(): Interaction | undefined;
839
- /** The message being handled, or `undefined` for anything else. */
844
+ /**
845
+ * The message being handled, or an event's first argument when it is a message, as in `@On('messageCreate')`;
846
+ * `undefined` for anything else, a reaction's message included. For `@On('messageUpdate')`, that is the message as it
847
+ * was before the edit, which may be partial; the edited one is the event's second argument, from
848
+ * {@link ExecutionContext.getArgs}.
849
+ */
840
850
  abstract getMessage(): Message | undefined;
841
- /** The reaction being handled, or `undefined` for anything else. */
851
+ /** The reaction being handled, or the one an event carries; `undefined` for anything else. */
842
852
  abstract getReaction(): MessageReaction | PartialMessageReaction | undefined;
843
853
  /** What is being handled: an interaction, an autocomplete request, a message, a reaction or an event. */
844
854
  abstract getType(): ExecutionContextType;
@@ -1099,7 +1109,8 @@ interface CooldownVerdict {
1099
1109
  * With a refusal, when the next call is allowed, as a Unix timestamp in milliseconds on the store's own clock. Every
1100
1110
  * refusal in one wait gives the same one, so `messages.dmOnCooldown` tells one wait from the next by it, across
1101
1111
  * processes and however late the answer arrives. The built-in stores give it; a store without it is told apart by
1102
- * `retryAfterMs` and the bot's clock instead.
1112
+ * `retryAfterMs` and the bot's clock instead. Their `consume`, and the default `consumeMany` of a store that asks it,
1113
+ * give it as a non-enumerable property, so their verdicts compare and serialise without it.
1103
1114
  */
1104
1115
  retryTimestamp?: number;
1105
1116
  }
@@ -1684,8 +1695,9 @@ interface DispatchResult {
1684
1695
  */
1685
1696
  durationMs: number;
1686
1697
  /**
1687
- * The guard class that denied the call, whether it returned `false` or threw `GuardDeniedError`.
1688
- * Only with the outcome `'denied'`, and not for a `GuardDeniedError` the handler threw itself.
1698
+ * The guard class that denied the call, whether it returned `false` or threw `GuardDeniedError`. With the outcome
1699
+ * `'denied'`, or `'error'` when the answer to a guard's `GuardDeniedError` failed to build; not for a
1700
+ * `GuardDeniedError` the handler threw itself.
1689
1701
  */
1690
1702
  deniedBy?: abstract new (...args: any[]) => unknown;
1691
1703
  /**
@@ -1781,8 +1793,11 @@ type StageParams<C extends abstract new (...args: any[]) => unknown> = 'params'
1781
1793
  interface GuardOptions {
1782
1794
  /**
1783
1795
  * The context types the guard runs for, as `ExecutionContext.getType()` reports them; it is skipped for
1784
- * any other call. A subclass inherits them unless it declares its own. A global guard also runs before
1785
- * `@On` handlers, so one that reads an interaction declares `['interaction']`.
1796
+ * any other call. An autocomplete is its own type, `'autocomplete'`, so a guard limited to `'interaction'`
1797
+ * doesn't run before `@Autocomplete` handlers. A subclass inherits them unless it declares its own. A global
1798
+ * guard also runs before `@On` handlers, so one that reads an interaction declares `['interaction']`, or
1799
+ * `['interaction', 'autocomplete']` to run before autocomplete handlers too. A guard that runs before an
1800
+ * autocomplete answers nothing there: return `false` to show no choices.
1786
1801
  *
1787
1802
  * @defaultValue every type
1788
1803
  */
@@ -2108,10 +2123,11 @@ interface MeoCordApplication {
2108
2123
  * every shard would meet, MeoCord refusing the app or Discord refusing the login for good (an invalid token, or
2109
2124
  * intents it disallows or does not know), the manager logs why, stops every shard and exits 1 instead.
2110
2125
  *
2111
- * @returns A promise that resolves once the bot is logged in, or every shard has been spawned.
2112
- * @throws For a bot in one process, the error of a provider's factory that failed, or the login
2113
- * error, such as an invalid token. A start that `stop()` ends rejects, and so does a start of an app already
2114
- * stopped.
2126
+ * @returns A promise that resolves once the bot is logged in, or every shard has been spawned. With process
2127
+ * sharding, it also resolves when `stop()` ends the start, which then spawns no more shards.
2128
+ * @throws For a bot in one process, the error of a provider's factory that failed, or the login error, such as an
2129
+ * invalid token; it also rejects when `stop()` ends the start. In either mode, a start of an app already stopped
2130
+ * rejects.
2115
2131
  */
2116
2132
  start(): Promise<void>;
2117
2133
  /**
@@ -2122,7 +2138,8 @@ interface MeoCordApplication {
2122
2138
  * not waited for.
2123
2139
  *
2124
2140
  * A stop while the bot starts ends that start: it waits for the providers being made, at most `shutdownTimeout`, and
2125
- * nothing more is made after it. A call after the first waits for it, and a stopped app does not start again.
2141
+ * nothing more is made after it. What the start made is shut down by the rule {@link OnShutdown} gives. A call after
2142
+ * the first waits for it, and a stopped app does not start again.
2126
2143
  *
2127
2144
  * @returns A promise that resolves once the bot is stopped. It never rejects: a failure to close is logged, and sets
2128
2145
  * `process.exitCode` to 1 unless another code is already set.
@@ -2131,6 +2148,10 @@ interface MeoCordApplication {
2131
2148
  /**
2132
2149
  * Registers the application's commands with Discord, where `meocord.config.ts`'s `commands` says.
2133
2150
  * A failure is logged rather than thrown.
2151
+ *
2152
+ * For a bot in one process, it needs the bot online, as the application comes from the login; called earlier, it
2153
+ * logs a warning and registers nothing. With process sharding, the manager registers over REST, before or after
2154
+ * `start()`.
2134
2155
  */
2135
2156
  registerCommands(): Promise<void>;
2136
2157
  }
@@ -2197,17 +2218,25 @@ interface OnReady {
2197
2218
  * Implement it to stop what {@link OnReady} started: timers, open connections, writes still buffered.
2198
2219
  *
2199
2220
  * @remarks
2200
- * Called when the bot stops, on SIGINT or SIGTERM or through `app.stop()`, before the client is destroyed, and only
2201
- * if `onReady` hooks ran. Hooks run one at a time in reverse dependency order, so a service stops before the services
2202
- * it injects. The whole sequence is limited by `shutdownTimeout` in `meocord.config.ts`; shutdown then goes on
2203
- * whether or not it finished. A hook that throws is logged and the next one still runs.
2204
- *
2205
- * It runs only for a class whose `onReady` has finished, or that has none. A stop while the ready hooks
2206
- * are running waits for the `onReady` in progress, within `shutdownTimeout`, then shuts that class down too;
2207
- * those not reached yet are skipped, and no further `onReady` starts. An `onReady` still running once only the
2208
- * hooks' share of the timeout is left is named in a warning and skipped. An `onReady` that threw counts as
2221
+ * Called when the bot stops, on SIGINT or SIGTERM or through `app.stop()`, before the client is destroyed, and when
2222
+ * its start fails. Hooks run one at a time in reverse dependency order, so a service stops before the services it
2223
+ * injects. The whole sequence is limited by `shutdownTimeout` in `meocord.config.ts`; shutdown then goes on whether or
2224
+ * not it finished. A hook that throws is logged and the next one still runs.
2225
+ *
2226
+ * It runs for each class and provided value the bot has made whose `onReady`, and that of everything it depends on,
2227
+ * has finished or doesn't exist. So a provided value with no `onReady`, such as a connection pool, is closed on any
2228
+ * stop once it is made, one during startup included, while a class whose `onReady` never ran is not shut down, nor is
2229
+ * anything that depends on it. A stop while the ready hooks are running waits for the `onReady` in progress, within
2230
+ * `shutdownTimeout`, then shuts that class down too, and no further `onReady` starts. An `onReady` still running once
2231
+ * only the hooks' share of the timeout is left is named in a warning and skipped. An `onReady` that threw counts as
2209
2232
  * finished, so its partial setup is cleaned up.
2210
2233
  *
2234
+ * A start that fails, because a provider's factory or the login failed, shuts down what it made by the same rule, so
2235
+ * the process can end with its exit code. A value the app gave with `useValue` is left open: a retry of `start()` makes
2236
+ * the rest again, and once the bot stops, by `app.stop()`, a Ctrl+C or a SIGTERM, the value is shut down by the same
2237
+ * rule, which leaves out one with an `onReady` a failed start never ran. A stop while a failed start shuts down waits
2238
+ * for that shutdown, all within one `shutdownTimeout`.
2239
+ *
2211
2240
  * @example
2212
2241
  * ```ts
2213
2242
  * import { appendFile } from 'node:fs/promises'
@@ -2646,7 +2675,8 @@ interface MessageCommandOptions {
2646
2675
  types?: Record<string, MessageParamType>;
2647
2676
  /**
2648
2677
  * How long a reply showing a command's usage, or a guard's or validation's reason, stays before it is deleted, in
2649
- * seconds. `0` keeps it.
2678
+ * seconds. `0` keeps it, and so does a time longer than a timer can wait, 2147483 seconds (about 24.8 days), which
2679
+ * startup warns about.
2650
2680
  * @defaultValue `10`
2651
2681
  */
2652
2682
  deleteUsageRepliesAfter?: number;
@@ -2787,7 +2817,7 @@ interface MessageHelpEntry {
2787
2817
  description?: string;
2788
2818
  /** Its aliases and other spellings, as the caller types them, such as `!m`. */
2789
2819
  aliases: string[];
2790
- /** Where it works; a command with a `member`, `role` or `channel` param works in servers only. */
2820
+ /** Where it works; a command with a `member`, `role` or `channel` param, or required flag, works in servers only. */
2791
2821
  scope: MessageScope;
2792
2822
  /** Each param and flag, with what it takes. */
2793
2823
  params: MessageHelpParam[];
@@ -2902,7 +2932,10 @@ interface MessageParamTypes {
2902
2932
  member: GuildMember;
2903
2933
  /** A user, by mention or ID. */
2904
2934
  user: User;
2905
- /** A role of the message's server, by mention, ID or name. */
2935
+ /**
2936
+ * A role of the message's server, by mention, ID or name; an optional one that another optional param follows
2937
+ * takes a mention or an ID only.
2938
+ */
2906
2939
  role: Role;
2907
2940
  /** A channel of the message's server, by mention or ID. */
2908
2941
  channel: GuildBasedChannel;
@@ -2940,8 +2973,11 @@ interface EntityRef<T> {
2940
2973
  /** Fetches the entity, once however many callers ask at the same time; `undefined` when there is none. */
2941
2974
  resolve(): Promise<T | undefined>;
2942
2975
  }
2943
- /** Splits a pattern into its words, at most 16 of them, so the checker's work stays small. */
2944
- type PatternWords<S extends string, Acc extends string[] = []> = Acc['length'] extends 16 ? Acc : S extends `${infer Word} ${infer Rest}` ? PatternWords<Rest, Word extends '' ? Acc : [...Acc, Word]> : S extends '' ? Acc : [...Acc, S];
2976
+ /**
2977
+ * Splits a pattern into its words. Each word is one step of tail recursion, with the words found so far in `Acc`, so a
2978
+ * pattern may hold about 1,000 of them.
2979
+ */
2980
+ type PatternWords<S extends string, Acc extends string[] = []> = S extends `${infer Word} ${infer Rest}` ? PatternWords<Rest, Word extends '' ? Acc : [...Acc, Word]> : S extends '' ? Acc : [...Acc, S];
2945
2981
  /**
2946
2982
  * The value a param's type gives: a named type, or one of the words `a|b` lists. An app's type not declared
2947
2983
  * in {@link MessageParamTypes} is not checked.
@@ -3099,8 +3135,9 @@ interface MessageHandlerOptions {
3099
3135
  description?: string;
3100
3136
  /**
3101
3137
  * Where the command works; `'any'` by default. A message sent elsewhere gets a usage reply saying
3102
- * where it works, and the handler does not run. A command with a `member`, `role` or `channel` param
3103
- * works in servers only; `'dm'` with one is refused as the bot starts.
3138
+ * where it works, and the handler does not run. A command with a `member`, `role` or `channel` param, or a required
3139
+ * flag of one of those types, works in servers only; `'dm'` with one, or with an optional such flag, is refused as the
3140
+ * bot starts. An optional flag of those types refuses a DM only when the message gives it.
3104
3141
  */
3105
3142
  scope?: MessageScope;
3106
3143
  /**
@@ -3182,8 +3219,13 @@ interface MeoCordConfig {
3182
3219
  rsbuild?: (config: RsbuildConfig) => RsbuildConfig | undefined;
3183
3220
  /**
3184
3221
  * Makes stack traces name your source files, lines and columns, from the source map the build writes
3185
- * beside `dist/main.js`. Under Node, `meocord start` passes `--enable-source-maps`; under Bun, or Node
3186
- * started without the flag, the bundle maps each stack through `Error.prepareStackTrace` itself.
3222
+ * beside `dist/main.js`. Under Node, `meocord start` passes `--enable-source-maps`; started without the
3223
+ * flag, the bundle maps each stack through `Error.prepareStackTrace` itself. Either way every trace Node
3224
+ * prints is mapped.
3225
+ *
3226
+ * Under Bun, the bundle maps `error.stack`, and so each trace MeoCord's `Logger` prints. What Bun prints
3227
+ * itself, for an uncaught error, an unhandled rejection or `console.error(error)` before `error.stack` is
3228
+ * read, keeps the bundle's positions.
3187
3229
  *
3188
3230
  * Set `false` for an error tracker that applies uploaded source maps to the bundle's positions, or a
3189
3231
  * source mapper of your own.
@@ -3355,7 +3397,11 @@ interface CommandBuilderOptions {
3355
3397
  * empty after dropping blank ids is not registered at all, rather than falling back to global. Under a
3356
3398
  * development server, it goes there with every other command.
3357
3399
  *
3358
- * @defaultValue the configured scope
3400
+ * A builder that extends another and gives no `guilds` inherits its base's, with a warning when it is decorated: declare
3401
+ * `guilds` on the subclass to keep them. The next major version (5.0) registers such a builder's command in the
3402
+ * configured scope.
3403
+ *
3404
+ * @defaultValue the configured scope, or the guilds of the builder it extends
3359
3405
  */
3360
3406
  guilds?: (string | undefined)[];
3361
3407
  }