meocord 4.1.0-beta.5 → 4.1.0-beta.7

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 (138) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/README.md +58 -3169
  3. package/dist/cjs/_shared/{explained-error-0T4WID-9.cjs → explained-error-BRrfk1lT.cjs} +34 -16
  4. package/dist/cjs/_shared/{providers-B_SmxbXl.cjs → providers-CIA3ykpw.cjs} +208 -120
  5. package/dist/cjs/_shared/{shard-context-D0rpUQZL.cjs → shard-context-fX-JKqOi.cjs} +1148 -192
  6. package/dist/cjs/_shared/{theme-resolvers-CIHGYuRP.cjs → theme-resolvers-B4BV5Ikl.cjs} +1001 -247
  7. package/dist/cjs/_shared/translate-error-DtdMVhf7.cjs +315 -0
  8. package/dist/cjs/common/index.cjs +314 -51
  9. package/dist/cjs/core/index.cjs +124 -385
  10. package/dist/cjs/decorator/index.cjs +345 -206
  11. package/dist/cjs/enum/index.cjs +41 -14
  12. package/dist/cjs/testing/index.cjs +892 -237
  13. package/dist/cli.json +590 -0
  14. package/dist/esm/bin/app-template/README.md.template +1 -1
  15. package/dist/esm/bin/app-template/src/controllers/context-menu/sample.context-menu.controller.ts.template +2 -2
  16. package/dist/esm/bin/builder-template/builder/context-menu.builder.template +1 -1
  17. package/dist/esm/bin/builder-template/controller/context-menu.controller.template +2 -2
  18. package/dist/esm/bin/generator.js +15 -8
  19. package/dist/esm/bin/helper/controller-generator.helper.js +25 -14
  20. package/dist/esm/bin/helper/filter-generator.helper.js +2 -4
  21. package/dist/esm/bin/helper/guard-generator.helper.js +2 -4
  22. package/dist/esm/bin/helper/interceptor-generator.helper.js +2 -4
  23. package/dist/esm/bin/helper/observer-generator.helper.js +2 -4
  24. package/dist/esm/bin/helper/pipe-generator.helper.js +2 -4
  25. package/dist/esm/bin/helper/service-generator.helper.js +2 -4
  26. package/dist/esm/bin/meocord.js +62 -15
  27. package/dist/esm/common/cooldown-store.js +48 -13
  28. package/dist/esm/common/decorator.js +27 -20
  29. package/dist/esm/common/errors.js +168 -43
  30. package/dist/esm/common/execution-context.js +19 -11
  31. package/dist/esm/common/explained-error.js +15 -4
  32. package/dist/esm/common/factory-provider.js +17 -13
  33. package/dist/esm/common/index.js +1 -0
  34. package/dist/esm/common/logger.js +32 -8
  35. package/dist/esm/common/meocord-messages.js +68 -0
  36. package/dist/esm/common/meocord-text.js +85 -0
  37. package/dist/esm/common/metadata.js +21 -16
  38. package/dist/esm/common/redis-cooldown-store.js +26 -16
  39. package/dist/esm/common/response/install-context.js +15 -7
  40. package/dist/esm/common/response/presenter.js +12 -8
  41. package/dist/esm/common/response/response-state.js +68 -55
  42. package/dist/esm/common/route.js +34 -16
  43. package/dist/esm/common/sharded-cooldown-store.js +18 -11
  44. package/dist/esm/common/theme.js +9 -0
  45. package/dist/esm/common/token.js +19 -10
  46. package/dist/esm/common/translate-error.js +67 -0
  47. package/dist/esm/common/translator.js +46 -36
  48. package/dist/esm/core/command-conflicts.js +75 -0
  49. package/dist/esm/core/command-registration.js +5 -4
  50. package/dist/esm/core/component-routes.js +33 -6
  51. package/dist/esm/core/dispatcher.js +103 -8
  52. package/dist/esm/core/event-requirements.js +19 -2
  53. package/dist/esm/core/fallback.js +11 -6
  54. package/dist/esm/core/handler-input.js +45 -31
  55. package/dist/esm/core/handler-pipeline.js +6 -3
  56. package/dist/esm/core/handler-registry.js +59 -17
  57. package/dist/esm/core/meocord-factory.js +37 -5
  58. package/dist/esm/core/meocord.app.js +18 -7
  59. package/dist/esm/core/message-help.js +267 -0
  60. package/dist/esm/core/message-params.js +170 -95
  61. package/dist/esm/core/message-routes.js +101 -18
  62. package/dist/esm/core/observer-runner.js +2 -2
  63. package/dist/esm/core/route-specificity.js +4 -3
  64. package/dist/esm/core/scalar-types.js +45 -0
  65. package/dist/esm/core/shard-context.js +12 -12
  66. package/dist/esm/core/shard-manager.js +16 -8
  67. package/dist/esm/core/theme-resolvers.js +13 -7
  68. package/dist/esm/core/theme-scope.js +31 -19
  69. package/dist/esm/decorator/app.decorator.js +47 -22
  70. package/dist/esm/decorator/command-builder.decorator.js +16 -11
  71. package/dist/esm/decorator/controller-class.decorator.js +21 -19
  72. package/dist/esm/decorator/controller.decorator.js +169 -54
  73. package/dist/esm/decorator/defer.decorator.js +23 -24
  74. package/dist/esm/decorator/event.decorator.js +29 -17
  75. package/dist/esm/decorator/filter.decorator.js +44 -26
  76. package/dist/esm/decorator/guard.decorator.js +42 -19
  77. package/dist/esm/decorator/inject.decorator.js +13 -5
  78. package/dist/esm/decorator/interceptor.decorator.js +43 -31
  79. package/dist/esm/decorator/observer.decorator.js +19 -17
  80. package/dist/esm/decorator/service.decorator.js +18 -5
  81. package/dist/esm/decorator/theme.decorator.js +14 -7
  82. package/dist/esm/decorator/validation.decorator.js +60 -29
  83. package/dist/esm/enum/controller.enum.js +39 -11
  84. package/dist/esm/enum/metadata-key.enum.js +2 -3
  85. package/dist/esm/package.json.js +1 -1
  86. package/dist/esm/testing/catalog.js +36 -9
  87. package/dist/esm/testing/cooldown-store-suite.js +16 -13
  88. package/dist/esm/testing/discord-shape.js +123 -0
  89. package/dist/esm/testing/execution-context.js +21 -6
  90. package/dist/esm/testing/inspect-handler.js +24 -11
  91. package/dist/esm/testing/meocord-testing-module.js +229 -35
  92. package/dist/esm/testing/mock-fn.js +65 -18
  93. package/dist/esm/testing/mock-interaction.js +235 -81
  94. package/dist/esm/testing/modal-fields.js +23 -10
  95. package/dist/esm/testing/response.js +41 -14
  96. package/dist/esm/testing/routing.js +53 -20
  97. package/dist/esm/testing/theme.js +27 -13
  98. package/dist/esm/util/dev-runner.util.js +40 -0
  99. package/dist/esm/util/generator-cli.util.js +2 -4
  100. package/dist/esm/util/interaction.util.js +9 -1
  101. package/dist/types/common/index.d.cts +260 -99
  102. package/dist/types/common/index.d.ts +260 -99
  103. package/dist/types/controller.enum-yd-fOr9m.d.cts +66 -0
  104. package/dist/types/controller.enum-yd-fOr9m.d.ts +66 -0
  105. package/dist/types/cooldown-store-BwDedkQk.d.cts +154 -0
  106. package/dist/types/cooldown-store-BwDedkQk.d.ts +154 -0
  107. package/dist/types/core/index.d.cts +176 -39
  108. package/dist/types/core/index.d.ts +176 -39
  109. package/dist/types/decorator/index.d.cts +618 -376
  110. package/dist/types/decorator/index.d.ts +618 -376
  111. package/dist/types/enum/index.d.cts +3 -4
  112. package/dist/types/enum/index.d.ts +3 -4
  113. package/dist/types/index-BmSDfetA.d.ts +2713 -0
  114. package/dist/types/index-CrcfxIXr.d.cts +2713 -0
  115. package/dist/types/interface/index.d.cts +4 -997
  116. package/dist/types/interface/index.d.ts +4 -997
  117. package/dist/types/route-DIqsQIDN.d.cts +102 -0
  118. package/dist/types/route-DIqsQIDN.d.ts +102 -0
  119. package/dist/types/testing/index.d.cts +913 -270
  120. package/dist/types/testing/index.d.ts +913 -270
  121. package/dist/types/{theme-resolvers-BUx8CQ0J.d.ts → theme-resolvers-CJq6aGG8.d.cts} +15 -7
  122. package/dist/types/{theme-resolvers-BUx8CQ0J.d.cts → theme-resolvers-CWU3_PhU.d.ts} +15 -7
  123. package/dist/types/translator-B2F8HOge.d.cts +250 -0
  124. package/dist/types/translator-CAOse4oQ.d.ts +250 -0
  125. package/meocord.eslint.cjs +3 -0
  126. package/meocord.eslint.d.cts +16 -4
  127. package/meocord.eslint.d.ts +31 -3
  128. package/meocord.eslint.mjs +3 -0
  129. package/package.json +7 -4
  130. package/dist/cjs/_shared/translator-CJtgDLJE.cjs +0 -631
  131. package/dist/types/controller.enum-BL6wEQls.d.cts +0 -32
  132. package/dist/types/controller.enum-BL6wEQls.d.ts +0 -32
  133. package/dist/types/errors-Dnx0meLj.d.cts +0 -836
  134. package/dist/types/errors-Dnx0meLj.d.ts +0 -836
  135. package/dist/types/route-BdFkN6G8.d.cts +0 -51
  136. package/dist/types/route-BdFkN6G8.d.ts +0 -51
  137. package/dist/types/translator-BC58l9jj.d.cts +0 -290
  138. package/dist/types/translator-BC58l9jj.d.ts +0 -290
package/CHANGELOG.md CHANGED
@@ -1,5 +1,100 @@
1
1
  # meocord
2
2
 
3
+ ## 4.1.0-beta.7
4
+
5
+ ### Minor Changes
6
+
7
+ - [#257](https://github.com/meocord/meocord/pull/257) [`afa139d`](https://github.com/meocord/meocord/commit/afa139debcc8e4accfe3f5c2a8997dbe9d0fb4d3) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `MeoCordTestingModule.fromApp(App, options?)` builds a testing module from a whole `@MeoCord` app, wired as the bot wires it: its controllers, services, providers and cooldown store, with its stages, translator, presenter, message options, theme and observers. A test no longer lists the app's controllers and providers again. `options.providers` replaces the app's by token, before anything is made, so a database factory the test replaces never runs; `options.controllers` and `options.observers` add a test's own; the `override*()` methods still apply. The app's services are made at `init()`, as the bot makes them before it logs in.
8
+
9
+ A class that injects the Discord `Client` in a testing module that was given none is now refused with what to do, `{ provide: Client, useValue: createMockClient() }`, where it read `No bindings found for service: "Client"`.
10
+
11
+ - [#258](https://github.com/meocord/meocord/pull/258) [`f9189b9`](https://github.com/meocord/meocord/commit/f9189b9b1008a9fee97ede546466b302afe71e92) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A context menu handler is typed with the kind its builder's `setType()` names. With `.setType(ApplicationCommandType.User)`, `@Command('Report user', ReportUserBuilder)` gives the handler a `UserContextMenuCommandInteraction`, and a handler declaring `MessageContextMenuCommandInteraction` no longer compiles. It is caught however the interaction is imported, an `import { type … }` included, where the check as the bot starts needed it imported as a value. Such a handler was broken anyway: dispatch sends a builder's command only to a handler of its kind, so its first click already failed. Declare the kind the builder's `setType()` names.
12
+
13
+ Nothing new is needed: MeoCord adds the kind to discord.js's `ContextMenuCommandBuilder.setType` for the compiler alone, and nothing changes at runtime. A builder whose kind the compiler can't tell, one that never calls `setType()` or picks the kind at runtime, gives either kind as before, and is still checked as the bot starts.
14
+
15
+ ### Patch Changes
16
+
17
+ - [#260](https://github.com/meocord/meocord/pull/260) [`18334ec`](https://github.com/meocord/meocord/commit/18334ecb55c1301586606e4c8d7a9a6ddf4173a1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The package includes `dist/cli.json`, which describes the `meocord` CLI: every command and subcommand, with its aliases, arguments, options, defaults, choices and descriptions, in the order `meocord --help` lists them. The build writes it from the program the CLI runs, so it always matches the installed version, and a tool can read it as data, without running the CLI. `schemaVersion` changes only when a change to the shape would break a reader.
18
+
19
+ - [#261](https://github.com/meocord/meocord/pull/261) [`701890b`](https://github.com/meocord/meocord/commit/701890b82e7edad7fa020cc4764f4fd7c5fdfb51) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A message `@Defer` locked is put back when its handler answers only with a follow-up, returns without answering, or throws. On a message with an uploaded file, such as an image in a Components V2 card, a click soon after the message was sent could leave it locked instead: its buttons and selects disabled under the loading view, for good. The lock's edit has Discord process the uploaded file again, and MeoCord, seeing the message change from what its edit returned, took it for someone else's edit and left it alone. It now keeps the time Discord stamps on its own edit, and leaves a message as it is only when it shows a later edit. The file stays attached, and a select that was clicked comes back with its options and defaults as the message had them, not the user's pick.
20
+
21
+ `meocord/testing`: a mock interaction's `editReply()` and `fetchReply()` now keep its message as Discord does. Components get their ids, media resolves, a file uploaded with the message comes back loading from the first edit that keeps it, and each edit is stamped with its time. `createMockMessage` takes `editedTimestamp`.
22
+
23
+ - [#259](https://github.com/meocord/meocord/pull/259) [`01f11d4`](https://github.com/meocord/meocord/commit/01f11d4a0b024ce5a1fd5b83acea5476ae58ca56) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A bot whose commands only one handler or one builder could ever take stops when it is created, as `meocord start`, `meocord register`, a shard manager and a testing module build it, naming both:
24
+
25
+ - two handlers of one slash command name or subcommand path, or of one context menu name and kind, where only the first ever ran: `StatsController.stats and AdminController.adminStats both handle the slash command "stats", so only StatsController.stats would ever run.`;
26
+ - two builder classes that build one application command, where only the first was registered, with a warning: `StatsBuilder on StatsController.stats and CopiedStatsBuilder on StatsController.statistics both build the slash command "stats"…`.
27
+
28
+ One builder on a command and its own subcommand paths is still one command, and a user and a message context menu may still share a name. See [Upgrading to 4.1](https://meocord.dev/docs/4.1/migrating#two-handlers-of-one-command-stop-the-bot).
29
+
30
+ - [#254](https://github.com/meocord/meocord/pull/254) [`2b02b0e`](https://github.com/meocord/meocord/commit/2b02b0ea9e8ad9f8e594ae14e32ba76400ee3275) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A slash command builder given on a subcommand path, such as `@Command('settings notify email', SettingsCommandBuilder)`, is named for what it is. A builder that builds its name from the path fails as before, now with a message naming the handler: `SettingsSlashController.notifyEmail declares the builder SettingsCommandBuilder on "settings notify email", which is a subcommand path: the builder of its command, "settings", describes it`, with what to declare instead, where it said "Invalid string format" and advised checking name lengths. A builder that names its command itself keeps working, and is warned about once as the bot starts, with the same advice: declare the handler with `@Command('settings notify email', CommandType.SLASH)`, and give the builder to `@Command('settings')`.
31
+
32
+ - [#255](https://github.com/meocord/meocord/pull/255) [`2852892`](https://github.com/meocord/meocord/commit/2852892922694fb883c8244b9469781e152468c1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - An observer is told a message command's usage error as `'invalid'`, the user's input that doesn't fit, as it is told a `ValidationError`. It was told `'error'`, so metrics counted a user's typo as a fault of the bot. This covers a word of the wrong type, a param left out, a flag the command lacks, a command sent where it doesn't work, and a parent's words alone, answered with its subcommands. A dashboard that counts `'error'` sees these under `'invalid'` from this release.
33
+
34
+ ## 4.1.0-beta.6
35
+
36
+ ### Minor Changes
37
+
38
+ - [#228](https://github.com/meocord/meocord/pull/228) [`8e1b936`](https://github.com/meocord/meocord/commit/8e1b9368772588f2a5a3269dd2aff8da1a9878c1) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `@MeoCord({ messages: { mention: 'only' } })` starts every message command in a server with a mention of the bot and nothing else, neither a prefix nor the message as plain text, while a direct message starts as usual, after the prefix or as it is; `@MessageHandler(pattern, { mention: 'only' })` does the same for one command beside the app's prefix. Discord sends a message's text without the privileged MessageContent intent when the message mentions the bot, and in direct messages, so such commands, and commands with `scope: 'dm'`, no longer need it: MeoCord's startup warning about MessageContent names only a `@MessageHandler()` listener and commands a prefix or plain text starts in a server, and says what still arrives without it. A mention-only bot can run without the intent, and without applying for it once verified. In a test, `resolveRoute(App, { content, dm: true })` reads a message as a direct message.
39
+
40
+ - [#252](https://github.com/meocord/meocord/pull/252) [`2d0575f`](https://github.com/meocord/meocord/commit/2d0575faba17cc4d458a6da20bb189dfa9506942) Thanks [@l7aromeo](https://github.com/l7aromeo)! - MeoCord's own texts for users go through the app's translator: a message command's usage and each thing wrong with it, the built-in `!help` and the labels of `HandlerRegistry.messageHelp`, cooldown and cooldown store refusals, "Command not found!", the generic error, and the default presenter's "Working on it…" and "Oops!". Add a `meocord` group to any catalog given to `@MeoCord({ i18n })`, all of it or part, such as `meocord: { usage: { heading: 'Cara pakai: {usage}' } }`; a text a locale leaves out stays in English, line by line. Answers to an interaction are in the user's language, replies to a message in the server's preferred language, or the default locale's in a DM. MeoCord's English stands as the English catalog, so an English-speaking user or server gets it even under a default locale in another language, unless the app's own `en-US` or `en-GB` catalog words the text. The keys and their English are in the new `MeoCordMessages` type from `meocord/interface`, and a key MeoCord lacks, or a `{param}` its English text lacks, fails to compile. Without `i18n`, every text is the English one it is today.
41
+
42
+ - `translateError(error, t, target)` from `meocord/common` returns the text the fallback answers an error with, in the language of an interaction, a message or a locale, for an exception filter that answers MeoCord's errors its own way.
43
+ - A message param type takes `labelKey`, a message key of the app's catalog, for a label in each server's language. `@MeoCord` refuses one without `i18n`, or one the default catalog has no message for.
44
+ - `expectCompleteCatalog(t, { meocord: true })` requires every locale that is not English to translate each of MeoCord's texts. Without the option it reports only a `meocord` key MeoCord lacks.
45
+
46
+ See [Localisation](https://meocord.dev/docs/4.1/localisation).
47
+
48
+ - [#251](https://github.com/meocord/meocord/pull/251) [`b4a9e58`](https://github.com/meocord/meocord/commit/b4a9e5841427c47322621be289e0d0ca8c1b0ee2) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Message commands have a built-in help command, off unless asked for: `@MeoCord({ messages: { prefix: '!', help: true } })` answers `!help` with the commands the caller can use where they asked, one line each with its handler's `description`, and `!help <command>` with one command's usage, params, aliases and where it works. `help: { command, aliases }` names other words. The list leaves out a handler with a guard on its method or controller, since it runs no guards, and one whose new `hidden: true` option asks to be left out; named, either is shown. `!help` for words with no handler of their own lists their subcommands, and an unknown name or nothing to list gets a line saying so. It answers only after a prefix or mention, and an app's own `help` handler always runs instead, with a warning at startup. With `replyEmoji` the reply begins with the theme's `emojis.info`.
49
+
50
+ The reply follows the app's translations, `meocord.help.*` in its catalog with `@MeoCord({ i18n })`, in the server's language, and is English otherwise; see [MeoCord's own texts](https://meocord.dev/docs/4.1/localisation). A presenter's new optional `messageHelp(help, message)` method writes it instead, from `MessageHelp`, what the built-in found. `HandlerRegistry.messageHelp(message, query?)` gives the same model to a help command of the app's own, with help on or off, and `MessageHandlerEntry.hidden` says whether a handler asked to be left out. `hidden` also leaves a subcommand out of the usage listing a message naming only a parent gets.
51
+
52
+ - [#246](https://github.com/meocord/meocord/pull/246) [`6c46b07`](https://github.com/meocord/meocord/commit/6c46b07b19dff7fde4614e7d80e0ff3e4ddfe8d0) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A message that names only a command's leading words, such as `!config` when `config set …` and `config get …` exist, or an unknown subcommand, such as `!config reset`, gets the usage of each subcommand in reply, under a `Usage:` heading, one line per handler by its own pattern, where it got no reply. A handler whose pattern matches the message still runs, so a `config` or `config {key}` handler takes it as before. A subcommand with a guard, on its method or its controller, inherited ones included, is left out of the listing on purpose, since the listing runs no guards and must not name what a caller may be refused; it still answers its own usage when named, and a parent with nothing left to list gets no reply. App-wide guards do not filter the listing, as they do not filter a usage reply. The reply is a `MessageUsageError`, answered through the app's global filters and then the fallback, like any usage reply.
53
+
54
+ - [#231](https://github.com/meocord/meocord/pull/231) [`8395b05`](https://github.com/meocord/meocord/commit/8395b056427c22caaf65afc16522ffc0d2b336aa) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A button's, select menu's or modal's customId pattern can type a param, `{name:type}`, with `int`, `number`, `bool` or words to choose from such as `{order:asc|desc}`, read by the parsers message commands use. The handler receives the value, such as a number for `@Command('counter/{count:int}', CommandType.BUTTON)`, and its params are checked against the pattern when the code compiles; `route(pattern).build()` takes values of those types. A segment that is not a value of its type matches no route. Such a pattern used to be read as literal text, so it silently never matched; a type a customId cannot hold, such as `{target:member}`, now stops the bot where it is declared. Beside a text param in the same place, a typed one is tried first, and of two types the narrower (words to choose from, then `bool`, `int`, `number`), whatever order they are declared in; and patterns whose typed segments take no value in common are different routes. For a route with a typed param, `resolveRoute` adds `values`, the params as the handler receives them, beside `params`, which stays their text; every other result is as it was. From `meocord/common`, `RouteValues<Pattern>` now gives each typed param the value of its type, such as `number` for `{count:int}`, and an untyped param takes any `RouteValue`, a string, number or bigint, as before; `RouteParams<Pattern>` names each param without its type.
55
+
56
+ - [#239](https://github.com/meocord/meocord/pull/239) [`a5868f4`](https://github.com/meocord/meocord/commit/a5868f4feb33197c0d88a4254f8ab50c28b7f690) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A context menu handler can declare the kind of interaction its builder registers: `UserContextMenuCommandInteraction` for a builder that calls `setType(ApplicationCommandType.User)`, or `MessageContextMenuCommandInteraction` for `Message`. It had to take the union of both, since declaring one failed to compile with "Unable to resolve signature of method decorator". The union still works. A builder's kind is a value TypeScript cannot read, so the bot checks it as it starts: a handler that declares the other kind stops it, naming both.
57
+
58
+ `meocord g co context-menu <name>` generates a user context menu command with its handler typed to match, and `--message` generates a message one. The context menu controller in a new project is typed the same way.
59
+
60
+ ### Patch Changes
61
+
62
+ - [#229](https://github.com/meocord/meocord/pull/229) [`551c0eb`](https://github.com/meocord/meocord/commit/551c0ebc6c1f6a544702ade824c1410007449c5c) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A user context menu command and a message context menu command with the same name, which Discord allows, each reach their own `@Command` handler. The first handler declared under the name took both, so a message command could run the user command's handler. `TestingModule.invoke` refuses the other kind's interaction the same way, naming both kinds.
63
+
64
+ - [#243](https://github.com/meocord/meocord/pull/243) [`68638ab`](https://github.com/meocord/meocord/commit/68638abbe22544542808ae68332ce089a6c238bc) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `meocord start --dev` exits 1 when the bot cannot log in, as `meocord start --prod` does, instead of watching on with the bot offline: a missing or refused token, refused intents, or Discord being unreachable is not something a code change fixes. It says so in one line, after the reason the bot gave. After any other exit, such as an error at startup or a crash once online, it keeps watching and says `The application exited with code N; waiting for changes.`, then starts the bot again on the next rebuild. With `sharding`, the shard manager ends the session the same way.
65
+
66
+ - [#249](https://github.com/meocord/meocord/pull/249) [`4af6d70`](https://github.com/meocord/meocord/commit/4af6d70fb37bbc5fc2a8f28778156beeda3d00ee) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The package's homepage is https://meocord.dev, the documentation site, where npm links it, and a new application's README links MeoCord there.
67
+
68
+ - [#240](https://github.com/meocord/meocord/pull/240) [`b462777`](https://github.com/meocord/meocord/commit/b462777be7fa16d17113d061f9e7e815725ca230) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `module.invoke()` checks an interaction's customId against every handler of the testing module, ranked as dispatch ranks them, as it already did for a message. A customId dispatch gives to another handler, such as `card/summary` beside `card/{id}`, rejects naming the handler that runs, where it ran the named handler anyway. A handler declared under two patterns gets the params of the one dispatch picks, typed values included. A testing module whose controllers would stop the bot, such as two whose patterns match the same customIds, now makes `invoke` throw the same startup error with a customId, as `dispatch` already did; give each such controller its own module.
69
+
70
+ - [#244](https://github.com/meocord/meocord/pull/244) [`eef71c7`](https://github.com/meocord/meocord/commit/eef71c79adebc5ee37a9637cc52a8fde38d9111d) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The editor documentation of the application, the config file and the remaining public helpers says what each is for, with examples that compile, and links the guide: `MeoCordFactory`, `MeoCordApplication`, `@MeoCord`, `HandlerRegistry` and its entry types, `ShardContext`, `MeoCordConfig`, `ShardingConfig`, `CommandRegistrationConfig`, `RsbuildConfig`, the providers and `createToken`/`factoryProvider`, `Logger`, `OnReady`/`OnShutdown`, `CommandType`, `DeepPartial`/`DeepReadonly` and the `meocord/eslint` config. `MetadataKey` is marked internal: it holds MeoCord's own reflect keys and is not part of the documented API.
71
+
72
+ - [#226](https://github.com/meocord/meocord/pull/226) [`5c14933`](https://github.com/meocord/meocord/commit/5c1493377b616cfb474cb300144b922f99342f81) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The JSDoc of every decorator in `meocord/decorator`, and of `CooldownOptions`, `DeferOptions` and `CommandBuilderOptions`, is rewritten for the hover in your editor: a one-line summary, when to use it and what to use instead, how it works, where it runs in a call, and an example that compiles against the published types. The options of `@Guard`, `@Interceptor`, `@Observer`, `@Validate`, `@Cooldown` and `@Defer` are documented on each option, with its default.
73
+
74
+ - [#236](https://github.com/meocord/meocord/pull/236) [`01d92f6`](https://github.com/meocord/meocord/commit/01d92f634ecbfe4925f8779ebc64f2363e642043) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The guide links in the JSDoc of the decorators and the pipeline types point to the 4.1 documentation, the version you installed, and to its pages as they are named: slash commands, buttons, selects and modals, and how a call runs.
75
+
76
+ - [#241](https://github.com/meocord/meocord/pull/241) [`51282fe`](https://github.com/meocord/meocord/commit/51282fe4386c3e83013eff5be719cd001e8422b7) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The editor documentation of `MessageCommandOptions`, `MessageHandlerOptions`, `route`, `Route`, `RouteParams`, `RouteValue` and `RouteValues` says what each is for, with an example that compiles, and links the guide.
77
+
78
+ - [#234](https://github.com/meocord/meocord/pull/234) [`4c9c1dc`](https://github.com/meocord/meocord/commit/4c9c1dc20180f8002cba7983b9c3dd47de59887e) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The editor hover for `@MessageHandler`, `@ReactionHandler`, `ReactionHandlerAction`, `CommandNotFoundError`, `MessageUsageError` and the message param types (`ParamsOf`, `ParamRefsOf`, `EntityRef`, `MessageParamType`, `MessageParamTypes`, `CheckedParams`, `MessageScope`, `MessagePrefix`, `ReactionHandlerOptions`, `ReactionHandlerSettings`, `MessageUsageIssue`, `MessageParams`) now says in a sentence what each is, when to use it and what to use instead, with an example that compiles against the published types.
79
+
80
+ - [#230](https://github.com/meocord/meocord/pull/230) [`1004d7b`](https://github.com/meocord/meocord/commit/1004d7be4cc3782ebdd741e2b83d779731ff7785) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The JSDoc of the types and helpers a guard, interceptor, filter, pipe or observer works with is rewritten for the hover in your editor: `ExecutionContext`, `GuardDeniedError`, `ValidationError`, `createMetadata`, `SetMetadata`, `applyDecorators`, `StageParams`, `Piped`, the stage interfaces, the observer types, the Standard Schema types and the command builder types. Each has a one-line summary and when to use it, and each example compiles against the published types.
81
+
82
+ - [#232](https://github.com/meocord/meocord/pull/232) [`fcd3457`](https://github.com/meocord/meocord/commit/fcd3457492b5915ec99b75748b7181a6135dc128) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The JSDoc of `respond`, the theme API (`useTheme`, `bindTheme`, `UseTheme`, `ThemeCache`, `Theme` and the theme types), the errors a user is shown (`UserError`, `CooldownError`, `CooldownStoreError`), the presenter types, the translator and the cooldown stores now follows the JSDoc standard, for the hover in your editor and the API reference. Every example among them compiles against the published types: those that read an `interaction`, a database or an app they did not declare are now complete, and `MemoryCooldownStore`, `Theme`, `cooldownMessage` and `cooldownStoreMessage` gain one.
83
+
84
+ - [#235](https://github.com/meocord/meocord/pull/235) [`ee38bcb`](https://github.com/meocord/meocord/commit/ee38bcb6834033c77e11830fdded5480719b8b06) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The JSDoc of `meocord/testing`'s mocks follows the standard in CONTRIBUTING.md: `createMockInteraction`, `createMock`, `createMockUser`, `createMockClient`, `createMockGuild`, `createMockChannel`, `createMockMessage`, `createChatInputOptions`, `createModalFields`, `createDiscordError`, `createMockTheme`, `withTheme`, `createMockFn`, `isMockFunction`, `clearAllMocks` and `resetAllMocks`, with the types they take and return. Each has a one-line summary, when to use it, and an example that compiles against the published package, and declares everything it uses. `MockInstance`'s methods describe themselves on hover.
85
+
86
+ - [#233](https://github.com/meocord/meocord/pull/233) [`5f42ad2`](https://github.com/meocord/meocord/commit/5f42ad2fa683d03531e93b79a5ee558d8e88f518) Thanks [@l7aromeo](https://github.com/l7aromeo)! - The JSDoc of `meocord/testing`'s module and inspection helpers follows the standard in CONTRIBUTING.md: `MeoCordTestingModule`, `TestingModuleBuilder`, `TestingModule` and their options and results, `getResponse`, `inspectHandler`, `createExecutionContext`, `resolveRoute`, `findRouteConflicts`, `expectCompleteCatalog` and `testCooldownStore`. Each has a one-line summary, when to use it, and an example that compiles against the published package, and every option documents itself, so the hover in your editor and the API reference say the same thing.
87
+
88
+ - [#247](https://github.com/meocord/meocord/pull/247) [`b31f281`](https://github.com/meocord/meocord/commit/b31f281fc85692414718dbddd12404034b5ed337) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `bun run lint` in an application prints nothing when the code is clean. `meocord/eslint` gives its import resolver the application's three tsconfigs, so each file resolves aliases through the tsconfig that includes it, and the resolver printed `Multiple projects found, consider using a single tsconfig with references…` on every run. It now sets the resolver's `noWarnOnMultipleProjects`, since several projects are the intended setup. Existing applications get it by updating meocord; nothing in them changes.
89
+
90
+ - [#238](https://github.com/meocord/meocord/pull/238) [`dba5def`](https://github.com/meocord/meocord/commit/dba5def4f87aeef879e7ca62050ac821b4d23480) Thanks [@l7aromeo](https://github.com/l7aromeo)! - A message command's usage reply reads right for every param type: a word of the wrong type is now `"lots" is not a valid whole number`, so an app's own type labelled with a noun such as `emoji` reads `is not a valid emoji`, where it read `is not a emoji`. A `bool` param is named a `yes or no answer`. A role deleted while a command's guards ran is named `<@&id> is not a role in this server`, and a value of an app's own type whose `EntityRef` resolves to nothing `is not a valid <label>`, where both read `is not a value of its type`. A `MessageParamType`'s `label` is the bare noun, such as `hex colour`, as its example now shows. A test that matches the old wording, such as `is not a whole number`, needs the new one.
91
+
92
+ - [#250](https://github.com/meocord/meocord/pull/250) [`873aeab`](https://github.com/meocord/meocord/commit/873aeabaeb0d4ad11cfa4c7aaffcc0cc7e589d19) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `MessageParamType`'s documentation link in your editor opens the message params page, which covers typed params and your own param types, rather than the message commands page.
93
+
94
+ - [#225](https://github.com/meocord/meocord/pull/225) [`c862b1f`](https://github.com/meocord/meocord/commit/c862b1f637c50a53d8e1551a6ad1106cc08806ef) Thanks [@l7aromeo](https://github.com/l7aromeo)! - Importing `meocord/common` no longer computes the Redis script hash until a `RedisCooldownStore` uses it. Each script's SHA1 is worked out the first time a store given `evalsha` runs it, then kept, so an app that never uses Redis hashes nothing, and one without `evalsha` never needs the hash.
95
+
96
+ - [#237](https://github.com/meocord/meocord/pull/237) [`69ec4e8`](https://github.com/meocord/meocord/commit/69ec4e808f3709bfa5dfcfd6dc3939c73cee86b2) Thanks [@l7aromeo](https://github.com/l7aromeo)! - `getResponse(interaction).sent` counts only calls Discord accepted. A reply, update, edit or follow-up that Discord refused, such as a reply rejected with 10062 once the three seconds passed, used to count as sent, so a test of what the member sees after an expired interaction could pass while the member saw nothing. The refused call stays in `calls`, in the order it was made, and carries what it rejected with as `error`, the new optional field of `ResponseCall`: every call `respond()` makes, deferrals and modals included, is marked this way.
97
+
3
98
  ## 4.1.0-beta.5
4
99
 
5
100
  ### Minor Changes