meocord 4.2.1 → 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.
- package/CHANGELOG.md +188 -0
- package/dist/cjs/_shared/{controller.decorator-XKMlcUZz.cjs → controller.decorator-hp5xdJU4.cjs} +550 -189
- package/dist/cjs/_shared/{startup-roots-CgfPQrNl.cjs → event-sources-DzqTODXg.cjs} +274 -88
- package/dist/cjs/_shared/{providers-BZgJyfZS.cjs → providers-BBvbnmLP.cjs} +837 -295
- package/dist/cjs/_shared/{sharded-cooldown-store-CsJJyCZd.cjs → sharded-cooldown-store-B62g5O88.cjs} +11 -9
- package/dist/cjs/_shared/{translate-error-BUAR1WYG.cjs → translate-error-wsgfsUET.cjs} +1 -1
- package/dist/cjs/common/index.cjs +4 -104
- package/dist/cjs/core/index.cjs +435 -182
- package/dist/cjs/decorator/index.cjs +116 -121
- package/dist/cjs/testing/index.cjs +1923 -808
- package/dist/cli.json +1 -1
- package/dist/esm/bin/app-template/package.json.template +9 -9
- package/dist/esm/bin/app-template/src/main.ts.template +3 -2
- package/dist/esm/bin/generator.js +6 -4
- package/dist/esm/bin/helper/filter-generator.helper.js +6 -4
- package/dist/esm/bin/helper/guard-generator.helper.js +6 -4
- package/dist/esm/bin/helper/interceptor-generator.helper.js +6 -4
- package/dist/esm/bin/helper/observer-generator.helper.js +6 -4
- package/dist/esm/bin/helper/pipe-generator.helper.js +6 -4
- package/dist/esm/bin/helper/service-generator.helper.js +6 -4
- package/dist/esm/bin/meocord.js +106 -48
- package/dist/esm/build/native-addons.js +75 -19
- package/dist/esm/build/rsbuild-config.js +11 -3
- package/dist/esm/build/typed-externals.js +15 -2
- package/dist/esm/common/cooldown-store.js +38 -14
- package/dist/esm/common/deprecation.js +4 -1
- package/dist/esm/common/execution-context.js +3 -1
- package/dist/esm/common/explained-error.js +7 -3
- package/dist/esm/common/log-level.js +13 -9
- package/dist/esm/common/logger.js +4 -2
- package/dist/esm/common/meocord-text.js +11 -6
- package/dist/esm/common/redis-cooldown-store.js +3 -7
- package/dist/esm/common/response/flags.js +17 -1
- package/dist/esm/common/response/install-context.js +27 -16
- package/dist/esm/common/response/presenter.js +7 -3
- package/dist/esm/common/response/response-state.js +32 -10
- package/dist/esm/common/sharded-cooldown-store.js +11 -9
- package/dist/esm/common/theme.js +3 -1
- package/dist/esm/common/translator.js +27 -8
- package/dist/esm/core/autocomplete-routes.js +26 -0
- package/dist/esm/core/command-conflicts.js +15 -7
- package/dist/esm/core/command-registration.js +15 -1
- package/dist/esm/core/cooldown-runner.js +7 -9
- package/dist/esm/core/defer.js +2 -5
- package/dist/esm/core/dispatcher.js +92 -66
- package/dist/esm/core/event-requirements.js +67 -19
- package/dist/esm/core/event-sources.js +100 -0
- package/dist/esm/core/fallback.js +3 -1
- package/dist/esm/core/filter-runner.js +6 -6
- package/dist/esm/core/guard-runner.js +173 -52
- package/dist/esm/core/handler-input.js +24 -3
- package/dist/esm/core/handler-pipeline.js +54 -32
- package/dist/esm/core/handler-registry.js +51 -21
- package/dist/esm/core/input-runner.js +7 -8
- package/dist/esm/core/interceptor-runner.js +4 -5
- package/dist/esm/core/lifecycle-hooks.js +3 -8
- package/dist/esm/core/lifecycle-order.js +1 -15
- package/dist/esm/core/meocord-classes.js +14 -1
- package/dist/esm/core/meocord-factory.js +83 -54
- package/dist/esm/core/meocord.app.js +174 -89
- package/dist/esm/core/message-help.js +37 -15
- package/dist/esm/core/message-params.js +126 -46
- package/dist/esm/core/message-routes.js +225 -45
- package/dist/esm/core/message-words.js +30 -2
- package/dist/esm/core/observer-runner.js +4 -2
- package/dist/esm/core/process-state.js +19 -0
- package/dist/esm/core/providers.js +39 -4
- package/dist/esm/core/scalar-types.js +57 -16
- package/dist/esm/core/shard-context.js +11 -10
- package/dist/esm/core/shard-exit.js +3 -3
- package/dist/esm/core/shard-manager.js +16 -6
- package/dist/esm/core/stage-scope.js +2 -1
- package/dist/esm/core/startup-roots.js +28 -8
- package/dist/esm/core/theme-resolvers.js +26 -11
- package/dist/esm/core/theme-runtime.js +23 -13
- package/dist/esm/core/theme-scope.js +31 -30
- package/dist/esm/core/theme-validation.js +1 -1
- package/dist/esm/decorator/app.decorator.js +37 -1
- package/dist/esm/decorator/command-builder.decorator.js +14 -0
- package/dist/esm/decorator/controller-class.decorator.js +1 -1
- package/dist/esm/decorator/controller.decorator.js +48 -19
- package/dist/esm/decorator/defer.decorator.js +2 -2
- package/dist/esm/decorator/event.decorator.js +4 -5
- package/dist/esm/decorator/filter.decorator.js +4 -4
- package/dist/esm/decorator/guard.decorator.js +4 -61
- package/dist/esm/decorator/inject.decorator.js +4 -1
- package/dist/esm/decorator/interceptor.decorator.js +2 -2
- package/dist/esm/decorator/theme.decorator.js +4 -3
- package/dist/esm/decorator/validation.decorator.js +5 -5
- package/dist/esm/package.json.js +1 -1
- package/dist/esm/testing/catalog.js +32 -25
- package/dist/esm/testing/cooldown-store-suite.js +3 -3
- package/dist/esm/testing/discord-defaults.js +449 -335
- package/dist/esm/testing/inspect-handler.js +91 -10
- package/dist/esm/testing/meocord-testing-module.js +217 -91
- package/dist/esm/testing/mock-fn.js +8 -2
- package/dist/esm/testing/mock-interaction.js +864 -124
- package/dist/esm/testing/response-log.js +8 -0
- package/dist/esm/testing/response.js +7 -5
- package/dist/esm/testing/routing.js +48 -6
- package/dist/esm/testing/strict-mocks.js +8 -4
- package/dist/esm/testing/theme.js +3 -2
- package/dist/esm/util/common.util.js +30 -9
- package/dist/esm/util/generator-cli.util.js +6 -4
- package/dist/esm/util/inherited-env.util.js +72 -13
- package/dist/esm/util/json.util.js +10 -3
- package/dist/esm/util/meocord-cli.util.js +3 -2
- package/dist/esm/util/meocord-config-loader.util.js +14 -1
- package/dist/esm/util/meocord-config-validation.util.js +13 -3
- package/dist/esm/util/meocord-source-config.util.js +13 -3
- package/dist/esm/util/platform.util.js +3 -2
- package/dist/esm/util/refusal.util.js +29 -11
- package/dist/esm/util/registration-mode.util.js +14 -1
- package/dist/esm/util/timer-limit.util.js +4 -1
- package/dist/esm/util/tsconfig-paths.util.js +38 -7
- package/dist/esm/util/tsconfig.util.js +16 -58
- package/dist/esm/util/user-text.util.js +8 -4
- package/dist/esm/util/value.util.js +33 -5
- package/dist/types/common/index.d.cts +17 -10
- package/dist/types/common/index.d.ts +17 -10
- package/dist/types/core/index.d.cts +21 -11
- package/dist/types/core/index.d.ts +21 -11
- package/dist/types/decorator/index.d.cts +63 -63
- package/dist/types/decorator/index.d.ts +63 -63
- package/dist/types/{index-DKJclIi-.d.ts → index-Brkd6QGL.d.ts} +81 -35
- package/dist/types/{index-Dlf0ZZtS.d.cts → index-CqXImwF_.d.cts} +81 -35
- package/dist/types/interface/index.d.cts +1 -1
- package/dist/types/interface/index.d.ts +1 -1
- package/dist/types/{route-Bh1U13yy.d.ts → route-IQrK-MN2.d.cts} +11 -3
- package/dist/types/{route-Bh1U13yy.d.cts → route-bI-okq7g.d.ts} +11 -3
- package/dist/types/testing/index.d.cts +158 -61
- package/dist/types/testing/index.d.ts +158 -61
- package/dist/types/{theme-resolvers-CyEz9pnv.d.cts → theme-resolvers-AtgeaYqF.d.cts} +1 -1
- package/dist/types/{theme-resolvers-DA204O-q.d.ts → theme-resolvers-BgqysV8d.d.ts} +1 -1
- package/dist/types/{translator-Bg7hwxDF.d.cts → translator-D8aydlCE.d.ts} +12 -11
- package/dist/types/{translator-CeP4bCzp.d.ts → translator-iJhDlgwL.d.cts} +12 -11
- package/package.json +5 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ServiceIdentifier, Container } from 'inversify';
|
|
2
|
-
import { Client, Interaction, Message, MessageReaction, PartialMessageReaction, User, PartialUser, ClientEvents, Base, Locale, GuildMember, Role, GuildBasedChannel, Guild, APIMessageTopLevelComponent, JSONEncodable, APIEmbed, MessageFlagsResolvable, TextBasedChannel, BaseChannel, APIAuthorizingIntegrationOwnersMap, APIInteractionGuildMember, PermissionResolvable, APIUser, CacheType, CommandInteractionOptionResolver, ThreadChannel, AnyThreadChannel, ChatInputCommandInteraction, AutocompleteInteraction, MessageContextMenuCommandInteraction, UserContextMenuCommandInteraction, PrimaryEntryPointCommandInteraction, ContextMenuCommandInteraction, CommandInteraction, ButtonInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, RoleSelectMenuInteraction, MentionableSelectMenuInteraction, ChannelSelectMenuInteraction, MessageComponentInteraction, ModalSubmitInteraction, BaseInteraction, DMChannel, PartialGroupDMChannel, OmitPartialGroupDMChannel, Attachment, ModalSubmitFields, MessagePayload, InteractionReplyOptions, InteractionUpdateOptions, InteractionEditReplyOptions, MessageEditOptions, APIModalInteractionResponseCallbackData, ModalComponentData, InteractionDeferReplyOptions, InteractionDeferUpdateOptions, MessageResolvable, DiscordAPIError } from 'discord.js';
|
|
2
|
+
import { Client, Interaction, Message, MessageReaction, PartialMessageReaction, User, PartialUser, ClientEvents, Base, Locale, GuildMember, Role, GuildBasedChannel, Guild, APIMessageTopLevelComponent, JSONEncodable, APIEmbed, MessageFlagsResolvable, TextBasedChannel, BaseChannel, APIAuthorizingIntegrationOwnersMap, APIInteractionGuildMember, PermissionResolvable, APIUser, CacheType, CommandInteractionOptionResolver, ThreadChannel, AnyThreadChannel, ChatInputCommandInteraction, AutocompleteInteraction, MessageContextMenuCommandInteraction, UserContextMenuCommandInteraction, PrimaryEntryPointCommandInteraction, ContextMenuCommandInteraction, CommandInteraction, ButtonInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, RoleSelectMenuInteraction, MentionableSelectMenuInteraction, ChannelSelectMenuInteraction, MessageComponentInteraction, ModalSubmitInteraction, BaseInteraction, DMChannel, PartialGroupDMChannel, OmitPartialGroupDMChannel, Attachment, ModalSubmitFields, MessagePayload, InteractionReplyOptions, InteractionUpdateOptions, InteractionEditReplyOptions, MessageEditOptions, APIModalInteractionResponseCallbackData, ModalComponentData, InteractionDeferReplyOptions, InteractionDeferUpdateOptions, MessageResolvable, LaunchActivityOptions, ApplicationCommandOptionChoiceData, DiscordAPIError } from 'discord.js';
|
|
3
3
|
import { ReactionHandlerAction, CommandType } from '../enum/index.js';
|
|
4
|
-
import { a8 as Provider, P as ProviderToken } from '../index-
|
|
4
|
+
import { a8 as Provider, P as ProviderToken } from '../index-Brkd6QGL.js';
|
|
5
5
|
import { CooldownStore, ExecutionContextType, ExecutionContext, CooldownScope, MetadataDecorator, ResponsePhase, ResponseCall } from '../common/index.js';
|
|
6
6
|
import { DispatchObserver, GuardInterface, InterceptorInterface, ExceptionFilter, ThemeOverride, ThemeResolvers, ThemeResolver, MessageCommandOptions, MessagePrefix, RootTheme, DeepReadonly, MeoCordTheme } from '../interface/index.js';
|
|
7
|
-
export { ao as ClassProvider, F as FactoryProvider, ap as ValueProvider } from '../index-
|
|
7
|
+
export { ao as ClassProvider, F as FactoryProvider, ap as ValueProvider } from '../index-Brkd6QGL.js';
|
|
8
8
|
import { ThemeCache } from '../common/index.js';
|
|
9
9
|
import { Translator } from '../common/index.js';
|
|
10
10
|
import '@rsbuild/core';
|
|
@@ -216,6 +216,8 @@ declare class TestingModule {
|
|
|
216
216
|
private readonly services;
|
|
217
217
|
/** How long `close()` waits for the `onShutdown` hooks, as the bot's `shutdownTimeout` does. */
|
|
218
218
|
private readonly shutdownTimeout;
|
|
219
|
+
/** The `app`, whose presenter `init()` makes after the providers, as the bot does. */
|
|
220
|
+
private readonly app?;
|
|
219
221
|
constructor(container: Container, controllers?: readonly (new (...args: any[]) => unknown)[], eventClasses?: readonly (new (...args: any[]) => unknown)[], providers?: ProviderMap, order?: readonly unknown[], messageOptions?: MessageCommandOptions, lifecycle?: readonly LifecycleUnit[],
|
|
220
222
|
/** The lifecycle units the container has constructed, which `close()` shuts down. */
|
|
221
223
|
constructed?: ReadonlySet<unknown>,
|
|
@@ -224,8 +226,12 @@ declare class TestingModule {
|
|
|
224
226
|
/** The app's listed services, made at `init()` as the bot makes them before it logs in. */
|
|
225
227
|
services?: readonly (new (...args: any[]) => unknown)[],
|
|
226
228
|
/** How long `close()` waits for the `onShutdown` hooks, as the bot's `shutdownTimeout` does. */
|
|
227
|
-
shutdownTimeout?: number
|
|
229
|
+
shutdownTimeout?: number,
|
|
230
|
+
/** The `app`, whose presenter `init()` makes after the providers, as the bot does. */
|
|
231
|
+
app?: object | undefined);
|
|
228
232
|
private resolving?;
|
|
233
|
+
/** The instances whose `@On` and `@Once` handlers `emit` runs, read at `init()`. */
|
|
234
|
+
private sources?;
|
|
229
235
|
private readying?;
|
|
230
236
|
private closing?;
|
|
231
237
|
/** The `onReady` hooks' pass, which `close()` waits for, less one whose `onReady` called `close()`. */
|
|
@@ -358,16 +364,24 @@ declare class TestingModule {
|
|
|
358
364
|
* command's or an autocomplete's options, or the handler's customId params with a modal's fields or
|
|
359
365
|
* a select menu's choices.
|
|
360
366
|
* An interaction's customId or command name must be one dispatch routes to the handler, ranking
|
|
361
|
-
* every handler of the module as the bot does; a mock built without one is not checked.
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* the
|
|
366
|
-
*
|
|
367
|
+
* every handler of the module as the bot does; a mock built without one is not checked. An autocomplete is
|
|
368
|
+
* checked by its command path and its focused option: one dispatch gives to another `@Autocomplete` handler,
|
|
369
|
+
* or to none, is refused under `useStrictMocks()`, and otherwise warned about once and run.
|
|
370
|
+
* With a message alone, a patterned `@MessageHandler` gets the params its pattern captures from the content,
|
|
371
|
+
* after the prefix of the module's `app`, with typed params resolved as dispatch resolves them, from the
|
|
372
|
+
* message's guild caches first. A message whose `content` isn't a string, as a mock's without
|
|
373
|
+
* `useStrictMocks()`, gets `{}`. Under strict mocks a message has empty `content`, and a patterned handler
|
|
374
|
+
* rejects it, as dispatch runs no handler for a message with no text: give the mock the `content` the handler
|
|
375
|
+
* takes. A word that is not a value of its type, and a prefixed message that names the command but leaves out
|
|
376
|
+
* a param, go through the handler's filters as a `MessageUsageError`, as dispatch answers them.
|
|
377
|
+
* An `@On` or `@Once` handler no route reaches runs as {@link emit} runs it, as an event with the arguments given,
|
|
378
|
+
* under `useStrictMocks()`; without strict mocks it runs as its first argument's type, and `invoke` warns once
|
|
379
|
+
* where that differs.
|
|
367
380
|
* @returns Whether the handler ran, and the error a filter handled, if any. Rejects with an error no
|
|
368
381
|
* filter handles, or with the error a filter throws: the built-in fallback, which answers such
|
|
369
382
|
* errors in the bot, does not run here. Rejects before running anything with an interaction or a
|
|
370
|
-
* message the handler's route does not match, naming both
|
|
383
|
+
* message the handler's route does not match, naming both, and under `useStrictMocks()` with such an
|
|
384
|
+
* autocomplete. Given fewer arguments than the handler
|
|
371
385
|
* declares, with a first that is neither an interaction nor a message, such as a reaction without its
|
|
372
386
|
* `ReactionEvent`, it rejects under `useStrictMocks()`, and otherwise warns once and runs the handler.
|
|
373
387
|
*
|
|
@@ -394,6 +408,22 @@ declare class TestingModule {
|
|
|
394
408
|
invoke<C extends new (...args: any[]) => unknown, M extends HandlerName<C>>(controller: C, methodName: M, ...args: HandlerArgs<C, M>): Promise<InvocationResult>;
|
|
395
409
|
/** The handlers already warned about for being given fewer arguments than they take, so each is named once. */
|
|
396
410
|
private readonly warnedArgumentCounts;
|
|
411
|
+
/** The `@On` and `@Once` handlers already warned about for running other than as an event, so each is named once. */
|
|
412
|
+
private readonly warnedEventRuns;
|
|
413
|
+
/**
|
|
414
|
+
* Warns once, without strict mocks, that `invoke` runs an event handler other than as the bot does: as the type its
|
|
415
|
+
* first argument gives, or with params it added. Only `invoke` warns, on the test's own call.
|
|
416
|
+
*/
|
|
417
|
+
private warnEventRun;
|
|
418
|
+
/** Runs an `@On` or `@Once` handler as the bot and `emit` do: as an event, with its arguments as given. */
|
|
419
|
+
private runEventHandler;
|
|
420
|
+
/** The autocomplete mismatches already warned about without strict mocks, so each handler and route warns once. */
|
|
421
|
+
private readonly warnedAutocompleteRoutes;
|
|
422
|
+
/**
|
|
423
|
+
* Refuses under strict mocks, and otherwise warns once, an autocomplete dispatch gives to another handler or to none.
|
|
424
|
+
* Without strict mocks the handler still runs, since a test that passes that way would fail.
|
|
425
|
+
*/
|
|
426
|
+
private checkAutocompleteRoute;
|
|
397
427
|
/**
|
|
398
428
|
* Refuses under `useStrictMocks()`, or warns once otherwise, a call that gives a handler fewer arguments than it
|
|
399
429
|
* declares when `invoke` builds none for it, as for a reaction given without its `ReactionEvent`.
|
|
@@ -404,10 +434,17 @@ declare class TestingModule {
|
|
|
404
434
|
/** Counts `call` as under way until it settles. */
|
|
405
435
|
private track;
|
|
406
436
|
/**
|
|
407
|
-
* Makes this module the app of the input's client, as the bot is of its own
|
|
408
|
-
*
|
|
437
|
+
* Makes this module the app of the input's client, as the bot is of its own: its answers are drawn by this
|
|
438
|
+
* module's presenter, in its theme and language, `respond()` outside any call included, as in a collector's callback
|
|
439
|
+
* on that client. A module without a presenter clears the client's under strict mocks, so the default draws; default
|
|
440
|
+
* mode leaves another module's in place and warns once.
|
|
409
441
|
*/
|
|
410
442
|
private registerClient;
|
|
443
|
+
/**
|
|
444
|
+
* Makes this module the app of each event argument's client, as the bot is of its own, under strict mocks; default
|
|
445
|
+
* mode leaves the clients as they are and warns once where this module would draw answers otherwise.
|
|
446
|
+
*/
|
|
447
|
+
private registerEventClients;
|
|
411
448
|
private builtComponentRoutes?;
|
|
412
449
|
/** The module's component routes, ranked as dispatch ranks them; throws, as the bot would, for two of one shape. */
|
|
413
450
|
private componentRoutes;
|
|
@@ -451,8 +488,9 @@ declare class TestingModule {
|
|
|
451
488
|
/**
|
|
452
489
|
* Emits a client event to the module's `@On` and `@Once` handlers, through the pipeline the app runs
|
|
453
490
|
* them in up to its event fallback: the global guards of the module's `app`, then each handler's own.
|
|
454
|
-
*
|
|
455
|
-
*
|
|
491
|
+
* As on the bot, every instance the module runs lifecycle hooks on, the cooldown store aside, receives
|
|
492
|
+
* it: the controllers and services, what they and the stages inject, and each provided class or value.
|
|
493
|
+
* A `@Once` handler handles only the first event, as it would on a client.
|
|
456
494
|
*
|
|
457
495
|
* The bot's event fallback doesn't run here. On a bot, a guard's `GuardDeniedError` is logged and the
|
|
458
496
|
* event skipped, and a handler's `UserError` is logged and, when the event carries a message, answered
|
|
@@ -519,7 +557,9 @@ declare class TestingModuleBuilder {
|
|
|
519
557
|
/**
|
|
520
558
|
* Replaces a provider with a test double.
|
|
521
559
|
*
|
|
522
|
-
* The double needs only the members the test uses; misspelled member names are still rejected.
|
|
560
|
+
* The double needs only the members the test uses; misspelled member names are still rejected. A token MeoCord binds
|
|
561
|
+
* itself, such as `ShardContext` or `HandlerRegistry`, takes the double in place of MeoCord's own, so a test can stub
|
|
562
|
+
* cross-shard calls.
|
|
523
563
|
*
|
|
524
564
|
* @param token - The provider to replace.
|
|
525
565
|
* @example
|
|
@@ -684,7 +724,8 @@ declare class MeoCordTestingModule {
|
|
|
684
724
|
* @param app - The class `@MeoCord` decorates.
|
|
685
725
|
* @param options - Providers that replace the app's by token, extra controllers, and observers.
|
|
686
726
|
* @returns The builder, whose `override*` methods still apply, for `compile()`.
|
|
687
|
-
* @throws TypeError when `app` is not a `@MeoCord` class.
|
|
727
|
+
* @throws TypeError when `app` is not a `@MeoCord` class. After {@link reportAllStartupErrors}, an app whose
|
|
728
|
+
* `@MeoCord` was refused throws the error it was refused for instead.
|
|
688
729
|
*
|
|
689
730
|
* @example
|
|
690
731
|
* ```ts
|
|
@@ -746,9 +787,9 @@ type Implementation<T> = {
|
|
|
746
787
|
* @see {@link MockState}
|
|
747
788
|
*/
|
|
748
789
|
interface MockResult<T = unknown> {
|
|
749
|
-
/** `'return'` when the call returned, `'throw'` when it threw. */
|
|
750
|
-
type: 'return' | 'throw';
|
|
751
|
-
/** What the call returned, or the error it threw. */
|
|
790
|
+
/** `'return'` when the call returned, `'throw'` when it threw, `'incomplete'` while it is still running. */
|
|
791
|
+
type: 'return' | 'throw' | 'incomplete';
|
|
792
|
+
/** What the call returned, or the error it threw; `undefined` while it is incomplete. */
|
|
752
793
|
value: T;
|
|
753
794
|
}
|
|
754
795
|
/**
|
|
@@ -796,7 +837,8 @@ interface MockState<T extends (...args: any[]) => any = (...args: any[]) => any>
|
|
|
796
837
|
* The mock API of a mock function: what it has recorded, and the methods that change what it does.
|
|
797
838
|
*
|
|
798
839
|
* Every mock from `meocord/testing` has it, with the names jest and Vitest use, so a test written for either runner
|
|
799
|
-
* reads the same.
|
|
840
|
+
* reads the same. The values it takes and records aren't checked against the function it mocks; see
|
|
841
|
+
* {@link MockedFunction}.
|
|
800
842
|
*
|
|
801
843
|
* @group Testing
|
|
802
844
|
* @category Mocks
|
|
@@ -838,9 +880,12 @@ interface MockInstance<T extends (...args: any[]) => any = (...args: any[]) => a
|
|
|
838
880
|
/**
|
|
839
881
|
* A mock function with the signature of `T`, and the mock API of {@link MockInstance}.
|
|
840
882
|
*
|
|
841
|
-
* It takes the place of jest's `MockedFunction<T>` and Vitest's `MockedFunction<T
|
|
842
|
-
* method of a mock with it
|
|
843
|
-
* a
|
|
883
|
+
* It takes the place of jest's `MockedFunction<T>` and Vitest's `MockedFunction<T>`, and the mock factories type each
|
|
884
|
+
* method of a mock with it. Calling the mock is checked against `T`. The values its mock API takes and records are
|
|
885
|
+
* not, for a plain function as for an overloaded one: `mockReturnValue` and `mockResolvedValue` take any value,
|
|
886
|
+
* `mockImplementation` takes any function, and each of `mock.calls`' arguments and each of `mock.results`' values reads
|
|
887
|
+
* as `any`. So a partial fake, such as `guild.members.fetch.mockResolvedValue({ id })`, type-checks, and so does a
|
|
888
|
+
* value of the wrong type.
|
|
844
889
|
*
|
|
845
890
|
* @group Testing
|
|
846
891
|
* @category Mocks
|
|
@@ -1103,9 +1148,14 @@ type NotRaw<T> = T extends {
|
|
|
1103
1148
|
* collections of what it picks, each empty unless given. Other data Discord always sends reads as Discord sends it,
|
|
1104
1149
|
* such as `false` for a flag and `null` for what may be absent; what picks the handler, `commandName` or `customId`, is
|
|
1105
1150
|
* the test's to give. Replies follow Discord's order, so a second `reply()` rejects, and {@link getResponse} reports
|
|
1106
|
-
* every answer the interaction got
|
|
1107
|
-
*
|
|
1108
|
-
*
|
|
1151
|
+
* every answer the interaction got; under `useStrictMocks()`, `launchActivity()`, `sendPremiumRequired()` and an
|
|
1152
|
+
* autocomplete's `respond()` count as answers too. Under `useStrictMocks()` an answer marks the interaction `replied`,
|
|
1153
|
+
* `deferred` or, for an autocomplete, `responded` once it resolves, as discord.js does after Discord takes it: an edit
|
|
1154
|
+
* or follow-up made before then rejects with `InteractionNotReplied`, and a second answer sent while the first is in
|
|
1155
|
+
* flight is refused with Discord's 40060. In default mode the mark is made at the call, with a warning where a bot
|
|
1156
|
+
* would fail. Every method is a mock function, and one that returns a promise in discord.js resolves. What the mock
|
|
1157
|
+
* computes for itself, such as `memberPermissions` and `appPermissions`, calls none of them and caches nothing, so a
|
|
1158
|
+
* stub a test sets stays for its own code.
|
|
1109
1159
|
*
|
|
1110
1160
|
* An answer keeps that order whatever it is set to do: one a test gives a value with `mockResolvedValue` replies or
|
|
1111
1161
|
* defers as a real one would, and one that rejects changes nothing. `fetchReply()` reads back what `reply()` or
|
|
@@ -1295,7 +1345,8 @@ interface MockGuildOverrides {
|
|
|
1295
1345
|
channels?: readonly GuildBasedChannel[];
|
|
1296
1346
|
}
|
|
1297
1347
|
/**
|
|
1298
|
-
* Creates a mock {@link Guild}, with
|
|
1348
|
+
* Creates a mock {@link Guild}, with its `members`, `channels`, `roles`, `bans`, `emojis`, `stickers`, `scheduledEvents`,
|
|
1349
|
+
* `autoModerationRules` and `invites` managers ready to stub.
|
|
1299
1350
|
*
|
|
1300
1351
|
* Use it for the server a message or an interaction came from, with the members, roles and channels a handler looks
|
|
1301
1352
|
* up in it.
|
|
@@ -1305,14 +1356,18 @@ interface MockGuildOverrides {
|
|
|
1305
1356
|
*
|
|
1306
1357
|
* @remarks
|
|
1307
1358
|
* A manager's `fetch(id)` resolves to its cached item with that id, as discord.js looks there first, or to a new one it
|
|
1308
|
-
* caches under that id: a member or
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1359
|
+
* caches under that id: a member, channel, emoji, sticker, scheduled event or AutoMod rule in this guild, a role with
|
|
1360
|
+
* that id, a ban, or an invite with that code. `members.fetch({ user: ids })` resolves to a collection of each of those
|
|
1361
|
+
* members, found or made the same way; `create()` resolves to a mock of its item, a channel of the type its options
|
|
1362
|
+
* name under `useStrictMocks()`, which it caches as discord.js does, but for an invite, made for the channel given and
|
|
1363
|
+
* cached nowhere; `edit()` resolves under `useStrictMocks()` to the item with the id given, found or made the same way,
|
|
1364
|
+
* and under `useStrictMocks()` either takes the `name` its options give. A list fetch resolves to an empty collection.
|
|
1365
|
+
* Members, roles and channels given are put in their managers' caches, where dispatch looks first when it resolves a
|
|
1366
|
+
* message's typed params; a member {@link createMockMember} made without a server is in this one. Its `roles.everyone`
|
|
1367
|
+
* is the role given with the guild's id, or else an @everyone role of its own at position 0, in `roles.cache` as
|
|
1368
|
+
* Discord has it. That role has no permissions in default mode; under `useStrictMocks()` it has the ones Discord
|
|
1369
|
+
* gives @everyone in a new server. The guild is named `'Guild'` and its `preferredLocale` is `'en-US'` unless given,
|
|
1370
|
+
* so `t.forGuild(guild)` translates as for a new English server.
|
|
1316
1371
|
*
|
|
1317
1372
|
* The mock makes a member for any id it's asked for, so a test of an id that isn't a member rejects the fetch, as
|
|
1318
1373
|
* `guild.members.fetch.mockRejectedValue(createDiscordError(10007))`, or resolves a collection without that member.
|
|
@@ -1575,7 +1630,8 @@ interface ChatInputOptions {
|
|
|
1575
1630
|
* entity option carries its id in `value` and the object itself, as the gateway sends it: a user option its `user`,
|
|
1576
1631
|
* and in a server its `member` too. A user option's
|
|
1577
1632
|
* `getMember()` is the user's member in the server of the interaction the options are given to, and `null` in a DM;
|
|
1578
|
-
* a member given resolves `getUser()` to its user.
|
|
1633
|
+
* a member given resolves `getUser()` to its user. Under `useStrictMocks()` a user option's `getMentionable()` is its
|
|
1634
|
+
* member too where there is one, as discord.js reads it; default mode returns the user, with a warning once. A getter throws discord.js's type error for an option of another
|
|
1579
1635
|
* type, as discord.js does, required or not. Only a user or member read as a role, or a role read as a user or member,
|
|
1580
1636
|
* is `null`, or that error when required, as the option may be a mentionable one; a plain `{ id }` reads as any entity.
|
|
1581
1637
|
* A whole number is an Integer option and a fraction a Number one, so
|
|
@@ -1583,7 +1639,13 @@ interface ChatInputOptions {
|
|
|
1583
1639
|
*
|
|
1584
1640
|
* The `focused` option reads as Discord sends it, through `getFocused()`, `getFocused(true)` and `data` alike: a
|
|
1585
1641
|
* string, `''` when no value is given, and marked `focused` in `data`. A number given for it is its digits under
|
|
1586
|
-
* `useStrictMocks()`; otherwise it stays the number, with a warning when read.
|
|
1642
|
+
* `useStrictMocks()`; otherwise it stays the number, with a warning when read. Under `useStrictMocks()` `get()` and the
|
|
1643
|
+
* typed getters read it by name from that same option, as discord.js does; one given no value takes the string,
|
|
1644
|
+
* integer and number getters alike. Default mode reads what was given, `null` for no value, with a warning once.
|
|
1645
|
+
*
|
|
1646
|
+
* Given to an `AutocompleteInteraction`, a user, member, role, channel, mentionable or attachment option reads as
|
|
1647
|
+
* Discord sends an autocomplete's options under `useStrictMocks()`: its id alone, in `data` and the handler's params,
|
|
1648
|
+
* with the entity getters returning `null`. Otherwise it keeps the object given, with a warning once.
|
|
1587
1649
|
*
|
|
1588
1650
|
* @typeParam Cached - `any` by default, to match `createMockInteraction(ChatInputCommandInteraction)`; pass it when the
|
|
1589
1651
|
* interaction under test is cache-pinned.
|
|
@@ -1616,8 +1678,9 @@ declare function createChatInputOptions<Cached extends CacheType = any>(opts?: C
|
|
|
1616
1678
|
* and `message.thread` is `null` when the channel caches no thread under the message's id. So do a message's
|
|
1617
1679
|
* `editedAt`, a member's `presence`, a server's `verified` and `systemChannel` and a channel's `parent`, each `null` or
|
|
1618
1680
|
* `false` until the test gives what it is computed from. A reaction's `me` is `false`, a message's
|
|
1619
|
-
* `mentions.repliedUser` and a modal's `message` are `null`,
|
|
1620
|
-
* MeoCord's dispatcher fetches neither. No
|
|
1681
|
+
* `mentions.repliedUser` and a modal's `message` are `null`, an interaction's `ephemeral` is `null` until `reply()` or
|
|
1682
|
+
* `deferReply()` decides it, and a reaction has a whole message of its own, so MeoCord's dispatcher fetches neither. No
|
|
1683
|
+
* placeholder warning is logged.
|
|
1621
1684
|
*
|
|
1622
1685
|
* @remarks
|
|
1623
1686
|
* Those getters read what a server holds, so strict mocks also have it as Discord sends it: the bot's member is in the
|
|
@@ -1630,11 +1693,14 @@ declare function createChatInputOptions<Cached extends CacheType = any>(opts?: C
|
|
|
1630
1693
|
* A message the bot sends is its `client.user`'s, and one it sends in a DM is in that DM. Give the bot's member a role
|
|
1631
1694
|
* to let it do more, such as kick a member its role ranks above. A value the test sets on a mock wins over the computed
|
|
1632
1695
|
* one. An interaction's answer that discord.js would refuse, such as a second `reply()` after one a test set with
|
|
1633
|
-
* `mockResolvedValue`, is refused too, where without it the mock runs it and warns.
|
|
1634
|
-
*
|
|
1696
|
+
* `mockResolvedValue`, is refused too, where without it the mock runs it and warns. An answer marks the interaction
|
|
1697
|
+
* `replied`, `deferred` or `responded` once it resolves, as discord.js does, so code that doesn't await one fails as it
|
|
1698
|
+
* would on a bot, within one run of the test's code. The next major version (5.0) computes these values, and refuses
|
|
1699
|
+
* those answers, without the call.
|
|
1635
1700
|
*
|
|
1636
1701
|
* `invoke` also refuses a call that gives a handler fewer arguments than it declares where it builds none, such as a
|
|
1637
1702
|
* reaction handler given its reaction without its `ReactionEvent`; without strict mocks, it warns once and calls it.
|
|
1703
|
+
* It refuses an autocomplete that dispatch gives to another `@Autocomplete` handler, or to none, the same way.
|
|
1638
1704
|
*
|
|
1639
1705
|
* `compile()` also refuses an `overrideGuard`, `overrideInterceptor` or `overrideFilter` stub without the stage's
|
|
1640
1706
|
* method, `canActivate`, `intercept` or `catch`; without strict mocks, it warns and builds the module.
|
|
@@ -1701,9 +1767,14 @@ interface MessageToResolve {
|
|
|
1701
1767
|
botId?: string;
|
|
1702
1768
|
/**
|
|
1703
1769
|
* Whether the message is a direct message, where `mention: 'only'` does not apply, and a handler that works only in
|
|
1704
|
-
* a server, by its scope or a `member`, `role` or `channel` param in its pattern, is not reached, as dispatch
|
|
1705
|
-
* it
|
|
1706
|
-
*
|
|
1770
|
+
* a server, by its scope or a `member`, `role` or `channel` param in its pattern, is not reached, as dispatch never
|
|
1771
|
+
* runs it: it answers "This command works in a server only." to a message sent with a prefix or a mention, and
|
|
1772
|
+
* nothing to one without, which may be chat. Under `useStrictMocks()` a handler with a required flag of those types,
|
|
1773
|
+
* or one the message gives, is not reached either, as dispatch refuses it the same way; default mode resolves it,
|
|
1774
|
+
* with a warning. Without it, a mention alone starts what it starts in a server, and a handler of any scope may
|
|
1775
|
+
* answer, with a warning where one that works only in a DM does. Under `useStrictMocks()`, the message is read as
|
|
1776
|
+
* sent in a server, as dispatch reads one: such a handler is passed over for one that works there, or resolves to
|
|
1777
|
+
* `undefined`.
|
|
1707
1778
|
*/
|
|
1708
1779
|
dm?: boolean;
|
|
1709
1780
|
}
|
|
@@ -1875,11 +1946,13 @@ declare function createModalFields(values: Record<string, string | string[] | At
|
|
|
1875
1946
|
*
|
|
1876
1947
|
* Use it in a test for a team that wants no fallback in production. It reports the messages a locale lacks, the
|
|
1877
1948
|
* messages the default catalog doesn't have, the plural forms a language needs but a plural lacks, such as `few` for
|
|
1878
|
-
* Russian, a translation of another shape than the default's, a text for a plural or a plural for a text, and each
|
|
1879
|
-
* `{param}` a translation uses that the message it translates doesn't take. An empty translation, `''`, counts
|
|
1880
|
-
* lacking, as the translator reads it as missing. It reads the catalogs' own strings, so it checks the params of a
|
|
1881
|
-
* catalog from a plain variable or a JSON file too, which the compiler can't. An object
|
|
1882
|
-
* its every key is a plural category, so a group with an `other` key is a group
|
|
1949
|
+
* Russian, a translation of another shape than the default's, a text for a plural or a group, or a plural for a text, and each
|
|
1950
|
+
* `{param}` a translation uses that the message it translates doesn't take. An empty translation, `''` or `null`, counts
|
|
1951
|
+
* as lacking, as the translator reads it as missing. It reads the catalogs' own strings, so it checks the params of a
|
|
1952
|
+
* catalog from a plain variable or a JSON file too, which the compiler can't. An object in the default catalog counts as
|
|
1953
|
+
* a plural only when its every key is a plural category, so a group with an `other` key is a group, and a translation
|
|
1954
|
+
* is read by the default catalog's shapes, as the translator reads it: one that keeps only a group's `other` message
|
|
1955
|
+
* lacks the group's other messages.
|
|
1883
1956
|
*
|
|
1884
1957
|
* @remarks
|
|
1885
1958
|
* MeoCord's own texts, a catalog's `meocord` group, fall back to English by design, so only a key MeoCord lacks, and
|
|
@@ -2068,9 +2141,15 @@ interface HandlerInspection {
|
|
|
2068
2141
|
readonly controller: new (...args: any[]) => unknown;
|
|
2069
2142
|
/** The handler method's name. */
|
|
2070
2143
|
readonly methodName: string;
|
|
2071
|
-
/**
|
|
2144
|
+
/**
|
|
2145
|
+
* The guards that run before the handler, in order: global guards, class guards, then method guards. Under
|
|
2146
|
+
* `useStrictMocks()`, only those for the handler's context types.
|
|
2147
|
+
*/
|
|
2072
2148
|
readonly guards: readonly InspectedGuard[];
|
|
2073
|
-
/**
|
|
2149
|
+
/**
|
|
2150
|
+
* The interceptors around the handler, outermost first: global, class, then method interceptors. Under
|
|
2151
|
+
* `useStrictMocks()`, only those for the handler's context types, and none for an autocomplete.
|
|
2152
|
+
*/
|
|
2074
2153
|
readonly interceptors: readonly InspectedInterceptor[];
|
|
2075
2154
|
/**
|
|
2076
2155
|
* The exception filters for the handler, in the order they are tried: the method's, then the
|
|
@@ -2083,11 +2162,16 @@ interface HandlerInspection {
|
|
|
2083
2162
|
readonly pattern: string | undefined;
|
|
2084
2163
|
/**
|
|
2085
2164
|
* The routes the handler answers because a class its controller extends declares them, such as `slash "ping"`:
|
|
2086
|
-
* those its own class doesn't declare for it. Empty for a handler that declares all it answers.
|
|
2087
|
-
* `
|
|
2165
|
+
* those its own class doesn't declare for it. Empty for a handler that declares all it answers. Under
|
|
2166
|
+
* `useStrictMocks()` it names an inherited `@On` or `@Once` event too, such as `event "guildCreate"`; default mode
|
|
2167
|
+
* leaves events out, with a warning once where it would name one. A test reads it; `toEqual` doesn't compare it, so
|
|
2168
|
+
* an assertion on the other fields holds either way.
|
|
2088
2169
|
*/
|
|
2089
2170
|
readonly inheritedRoutes: readonly string[];
|
|
2090
|
-
/**
|
|
2171
|
+
/**
|
|
2172
|
+
* The `app`'s observers, in the order they are told about the call; empty without an `app`. Under `useStrictMocks()`,
|
|
2173
|
+
* only those whose `types` include the handler's.
|
|
2174
|
+
*/
|
|
2091
2175
|
readonly observers: readonly (new (...args: any[]) => DispatchObserver)[];
|
|
2092
2176
|
/**
|
|
2093
2177
|
* Reads a metadata value as `ExecutionContext.get` does: the method's value, else the controller's.
|
|
@@ -2155,8 +2239,10 @@ interface InspectHandlerOptions {
|
|
|
2155
2239
|
* Reports what runs when a handler is dispatched, and the metadata declared on it, without running anything.
|
|
2156
2240
|
*
|
|
2157
2241
|
* Use it to check that decorators set a handler up as intended: its guards with their params, its interceptors,
|
|
2158
|
-
* filters and cooldowns, in the order dispatch applies them.
|
|
2159
|
-
*
|
|
2242
|
+
* filters and cooldowns, in the order dispatch applies them. Under `useStrictMocks()`, the guards, interceptors and
|
|
2243
|
+
* observers are those dispatch runs for the handler's context types: a stage declared with `types` is listed only for
|
|
2244
|
+
* a handler of one of them, and an autocomplete lists no interceptors. Default mode lists every one, with a warning
|
|
2245
|
+
* once where dispatch runs fewer. To check what a handler does, run it with {@link TestingModule.invoke}.
|
|
2160
2246
|
*
|
|
2161
2247
|
* @param controller - The controller class declaring the handler.
|
|
2162
2248
|
* @param methodName - The handler method's name.
|
|
@@ -2201,7 +2287,8 @@ interface ResponseReport {
|
|
|
2201
2287
|
/**
|
|
2202
2288
|
* Every answer call the interaction got, through `respond()` or discord.js directly, in order: the payload it sent,
|
|
2203
2289
|
* without `withResponse`, and the `error` of one Discord refused. Checking a call's `method` types its `payload` as
|
|
2204
|
-
* that method takes it: the options of a reply, an edit or a deferral, the modal shown,
|
|
2290
|
+
* that method takes it: the options of a reply, an edit or a deferral, the modal shown, the message deleted, or an
|
|
2291
|
+
* autocomplete's choices.
|
|
2205
2292
|
*/
|
|
2206
2293
|
calls: readonly ((ResponseCall & {
|
|
2207
2294
|
method: 'reply' | 'followUp';
|
|
@@ -2227,15 +2314,25 @@ interface ResponseReport {
|
|
|
2227
2314
|
}) | (ResponseCall & {
|
|
2228
2315
|
method: 'deleteReply';
|
|
2229
2316
|
payload?: MessageResolvable | '@original';
|
|
2317
|
+
}) | (ResponseCall & {
|
|
2318
|
+
method: 'launchActivity';
|
|
2319
|
+
payload?: Omit<LaunchActivityOptions, 'withResponse'>;
|
|
2320
|
+
}) | (ResponseCall & {
|
|
2321
|
+
method: 'sendPremiumRequired';
|
|
2322
|
+
payload?: undefined;
|
|
2323
|
+
}) | (ResponseCall & {
|
|
2324
|
+
method: 'respond';
|
|
2325
|
+
payload?: readonly ApplicationCommandOptionChoiceData[];
|
|
2230
2326
|
}))[];
|
|
2231
2327
|
}
|
|
2232
2328
|
/**
|
|
2233
2329
|
* Reports how an interaction was answered: where its answer stands, and every answer call it got, in order.
|
|
2234
2330
|
*
|
|
2235
2331
|
* Use it after `invoke` or `dispatch` to check what the member sees. A mock interaction records each `reply`,
|
|
2236
|
-
* `deferReply`, `editReply`, `followUp`, `deleteReply`, `update`, `deferUpdate` and `showModal`,
|
|
2237
|
-
*
|
|
2238
|
-
*
|
|
2332
|
+
* `deferReply`, `editReply`, `followUp`, `deleteReply`, `update`, `deferUpdate` and `showModal`, and under
|
|
2333
|
+
* `useStrictMocks()` each `launchActivity`, `sendPremiumRequired` and autocomplete `respond` too, whether the handler made
|
|
2334
|
+
* it through `respond()` or with discord.js directly, so both are reported, each once. For a message or a reaction, read
|
|
2335
|
+
* the mock's own methods.
|
|
2239
2336
|
*
|
|
2240
2337
|
* @param interaction - The interaction a handler answered.
|
|
2241
2338
|
* @returns The state, whether anything the member can see was sent, and the calls, in order.
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Locale, Interaction, Guild } from 'discord.js';
|
|
2
|
-
import { aq as MeoCordMessages } from './index-
|
|
2
|
+
import { aq as MeoCordMessages } from './index-Brkd6QGL.js';
|
|
3
|
+
|
|
4
|
+
/** Each character of a string, as a union; tail-recursive, so a long string stays within the compiler's depth. */
|
|
5
|
+
type Chars<S extends string, Found = never> = S extends `${infer First}${infer Rest}` ? Chars<Rest, Found | First> : Found;
|
|
6
|
+
/** A character `\w` matches without the `u` flag: ASCII letters, digits and `_`. */
|
|
7
|
+
type WordChar = Chars<'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'>;
|
|
8
|
+
/**
|
|
9
|
+
* Whether a string is one or more word characters, as a `{name}` takes them in a message or a customId pattern. It
|
|
10
|
+
* reads 16 at a time, so a name up to 16,000 characters long stays within the compiler's 1,000 steps of tail recursion.
|
|
11
|
+
*/
|
|
12
|
+
type IsWord<S extends string> = S extends `${infer A}${infer B}${infer C}${infer D}${infer E}${infer F}${infer G}${infer H}${infer I}${infer J}${infer K}${infer L}${infer M}${infer N}${infer O}${infer P}${infer Rest}` ? [A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P] extends [WordChar] ? Rest extends '' ? true : IsWord<Rest> : false : S extends `${WordChar}${infer Rest}` ? Rest extends '' ? true : IsWord<Rest> : false;
|
|
3
13
|
|
|
4
14
|
/**
|
|
5
15
|
* The plural categories `Intl.PluralRules` selects between.
|
|
@@ -61,15 +71,6 @@ type LocalizationKey<C> = {
|
|
|
61
71
|
}[StringMessageKey<C>];
|
|
62
72
|
/** The message at a key. */
|
|
63
73
|
type MessageAt<C, K extends string> = K extends `${infer Head}.${infer Rest}` ? Head extends keyof C ? MessageAt<C[Head], Rest> : never : K extends keyof C ? C[K] : never;
|
|
64
|
-
/** Each character of a string, as a union; tail-recursive, so a long string stays within the compiler's depth. */
|
|
65
|
-
type Chars<S extends string, Found = never> = S extends `${infer First}${infer Rest}` ? Chars<Rest, Found | First> : Found;
|
|
66
|
-
/** A character `\w` matches without the `u` flag: ASCII letters, digits and `_`. */
|
|
67
|
-
type WordChar = Chars<'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'>;
|
|
68
|
-
/**
|
|
69
|
-
* Whether a string is one or more word characters. It reads 16 at a time, so a name up to 16,000 characters long stays
|
|
70
|
-
* within the compiler's 1,000 steps of tail recursion.
|
|
71
|
-
*/
|
|
72
|
-
type IsWord<S extends string> = S extends `${infer A}${infer B}${infer C}${infer D}${infer E}${infer F}${infer G}${infer H}${infer I}${infer J}${infer K}${infer L}${infer M}${infer N}${infer O}${infer P}${infer Rest}` ? [A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P] extends [WordChar] ? Rest extends '' ? true : IsWord<Rest> : false : S extends `${WordChar}${infer Rest}` ? Rest extends '' ? true : IsWord<Rest> : false;
|
|
73
74
|
/**
|
|
74
75
|
* The `{param}` names of a message, read from the left as translating reads them: `{{` is a brace written as text, and
|
|
75
76
|
* `{` then word characters then `}` is a param. Where the braces hold anything else, reading resumes after the `{`.
|
|
@@ -367,4 +368,4 @@ declare abstract class Translator<C = CatalogShape> {
|
|
|
367
368
|
declare function createTranslator<const Locales extends Readonly<Record<string, CatalogShape>>, const Default extends keyof Locales & `${Locale}`>(options: TranslatorOptions<Locales, Default>): Translator<Locales[Default]>;
|
|
368
369
|
|
|
369
370
|
export { Translator as T, createTranslator as g, defineCatalog as h };
|
|
370
|
-
export type { CatalogDefinition as C, LocaleCatalog as L, MessageKey as M, PluralCategory as P, StringMessageKey as S, CatalogShape as a, LocalizationKey as b, MessageParams as c, PluralMessage as d, Translate as e, TranslatorOptions as f };
|
|
371
|
+
export type { CatalogDefinition as C, IsWord as I, LocaleCatalog as L, MessageKey as M, PluralCategory as P, StringMessageKey as S, CatalogShape as a, LocalizationKey as b, MessageParams as c, PluralMessage as d, Translate as e, TranslatorOptions as f };
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Locale, Interaction, Guild } from 'discord.js';
|
|
2
|
-
import { aq as MeoCordMessages } from './index-
|
|
2
|
+
import { aq as MeoCordMessages } from './index-CqXImwF_.cjs';
|
|
3
|
+
|
|
4
|
+
/** Each character of a string, as a union; tail-recursive, so a long string stays within the compiler's depth. */
|
|
5
|
+
type Chars<S extends string, Found = never> = S extends `${infer First}${infer Rest}` ? Chars<Rest, Found | First> : Found;
|
|
6
|
+
/** A character `\w` matches without the `u` flag: ASCII letters, digits and `_`. */
|
|
7
|
+
type WordChar = Chars<'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'>;
|
|
8
|
+
/**
|
|
9
|
+
* Whether a string is one or more word characters, as a `{name}` takes them in a message or a customId pattern. It
|
|
10
|
+
* reads 16 at a time, so a name up to 16,000 characters long stays within the compiler's 1,000 steps of tail recursion.
|
|
11
|
+
*/
|
|
12
|
+
type IsWord<S extends string> = S extends `${infer A}${infer B}${infer C}${infer D}${infer E}${infer F}${infer G}${infer H}${infer I}${infer J}${infer K}${infer L}${infer M}${infer N}${infer O}${infer P}${infer Rest}` ? [A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P] extends [WordChar] ? Rest extends '' ? true : IsWord<Rest> : false : S extends `${WordChar}${infer Rest}` ? Rest extends '' ? true : IsWord<Rest> : false;
|
|
3
13
|
|
|
4
14
|
/**
|
|
5
15
|
* The plural categories `Intl.PluralRules` selects between.
|
|
@@ -61,15 +71,6 @@ type LocalizationKey<C> = {
|
|
|
61
71
|
}[StringMessageKey<C>];
|
|
62
72
|
/** The message at a key. */
|
|
63
73
|
type MessageAt<C, K extends string> = K extends `${infer Head}.${infer Rest}` ? Head extends keyof C ? MessageAt<C[Head], Rest> : never : K extends keyof C ? C[K] : never;
|
|
64
|
-
/** Each character of a string, as a union; tail-recursive, so a long string stays within the compiler's depth. */
|
|
65
|
-
type Chars<S extends string, Found = never> = S extends `${infer First}${infer Rest}` ? Chars<Rest, Found | First> : Found;
|
|
66
|
-
/** A character `\w` matches without the `u` flag: ASCII letters, digits and `_`. */
|
|
67
|
-
type WordChar = Chars<'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'>;
|
|
68
|
-
/**
|
|
69
|
-
* Whether a string is one or more word characters. It reads 16 at a time, so a name up to 16,000 characters long stays
|
|
70
|
-
* within the compiler's 1,000 steps of tail recursion.
|
|
71
|
-
*/
|
|
72
|
-
type IsWord<S extends string> = S extends `${infer A}${infer B}${infer C}${infer D}${infer E}${infer F}${infer G}${infer H}${infer I}${infer J}${infer K}${infer L}${infer M}${infer N}${infer O}${infer P}${infer Rest}` ? [A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P] extends [WordChar] ? Rest extends '' ? true : IsWord<Rest> : false : S extends `${WordChar}${infer Rest}` ? Rest extends '' ? true : IsWord<Rest> : false;
|
|
73
74
|
/**
|
|
74
75
|
* The `{param}` names of a message, read from the left as translating reads them: `{{` is a brace written as text, and
|
|
75
76
|
* `{` then word characters then `}` is a param. Where the braces hold anything else, reading resumes after the `{`.
|
|
@@ -367,4 +368,4 @@ declare abstract class Translator<C = CatalogShape> {
|
|
|
367
368
|
declare function createTranslator<const Locales extends Readonly<Record<string, CatalogShape>>, const Default extends keyof Locales & `${Locale}`>(options: TranslatorOptions<Locales, Default>): Translator<Locales[Default]>;
|
|
368
369
|
|
|
369
370
|
export { Translator as T, createTranslator as g, defineCatalog as h };
|
|
370
|
-
export type { CatalogDefinition as C, LocaleCatalog as L, MessageKey as M, PluralCategory as P, StringMessageKey as S, CatalogShape as a, LocalizationKey as b, MessageParams as c, PluralMessage as d, Translate as e, TranslatorOptions as f };
|
|
371
|
+
export type { CatalogDefinition as C, IsWord as I, LocaleCatalog as L, MessageKey as M, PluralCategory as P, StringMessageKey as S, CatalogShape as a, LocalizationKey as b, MessageParams as c, PluralMessage as d, Translate as e, TranslatorOptions as f };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meocord",
|
|
3
3
|
"description": "Decorator-based framework for Discord bots on discord.js, with dependency injection, guards, a CLI and a testing toolkit.",
|
|
4
|
-
"version": "4.2.
|
|
4
|
+
"version": "4.2.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=22.13"
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"bench:messages": "bun scripts/bench-messages.ts",
|
|
25
25
|
"bench:theme": "bun scripts/bench-theme.ts",
|
|
26
26
|
"changeset": "changeset",
|
|
27
|
-
"release:version": "changeset version && bun scripts/check-jsdoc-examples.ts --fix && bun scripts/release-notes.ts && prettier --write CHANGELOG.md",
|
|
27
|
+
"release:version": "bun run notes:check && changeset version && bun scripts/check-jsdoc-examples.ts --fix && bun scripts/release-notes.ts && prettier --write CHANGELOG.md",
|
|
28
|
+
"notes:check": "bun scripts/release-notes.ts --check",
|
|
28
29
|
"notices": "bun scripts/third-party-notices.ts",
|
|
29
30
|
"notices:check": "bun scripts/third-party-notices.ts --check",
|
|
30
31
|
"check:jsdoc-examples": "bun scripts/check-jsdoc-examples.ts",
|
|
@@ -196,6 +197,8 @@
|
|
|
196
197
|
"discord.js",
|
|
197
198
|
"typescript",
|
|
198
199
|
"bot-framework",
|
|
200
|
+
"discord-bot-framework",
|
|
201
|
+
"discord-framework",
|
|
199
202
|
"decorator",
|
|
200
203
|
"dependency-injection",
|
|
201
204
|
"inversify",
|