@azurioh/discord-kernel 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +318 -1
- package/dist/authz/require-level-guard.d.ts +1 -1
- package/dist/authz/require-level-guard.d.ts.map +1 -1
- package/dist/color.d.ts +42 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +130 -0
- package/dist/color.js.map +1 -0
- package/dist/discord/command/all-required.d.ts +8 -0
- package/dist/discord/command/all-required.d.ts.map +1 -0
- package/dist/discord/command/all-required.js +12 -0
- package/dist/discord/command/all-required.js.map +1 -0
- package/dist/discord/command/autocomplete-dispatcher.d.ts.map +1 -1
- package/dist/discord/command/autocomplete-dispatcher.js +2 -1
- package/dist/discord/command/autocomplete-dispatcher.js.map +1 -1
- package/dist/discord/command/autocomplete-limits.d.ts +3 -0
- package/dist/discord/command/autocomplete-limits.d.ts.map +1 -0
- package/dist/discord/command/autocomplete-limits.js +6 -0
- package/dist/discord/command/autocomplete-limits.js.map +1 -0
- package/dist/discord/command/autocomplete.d.ts +6 -1
- package/dist/discord/command/autocomplete.d.ts.map +1 -1
- package/dist/discord/command/autocomplete.js +6 -6
- package/dist/discord/command/autocomplete.js.map +1 -1
- package/dist/discord/command/command-responders.d.ts +26 -0
- package/dist/discord/command/command-responders.d.ts.map +1 -0
- package/dist/discord/command/command-responders.js +16 -0
- package/dist/discord/command/command-responders.js.map +1 -0
- package/dist/discord/command/context.d.ts +8 -17
- package/dist/discord/command/context.d.ts.map +1 -1
- package/dist/discord/command/context.js +8 -37
- package/dist/discord/command/context.js.map +1 -1
- package/dist/discord/command/cooldown-guard.d.ts +1 -1
- package/dist/discord/command/cooldown-guard.d.ts.map +1 -1
- package/dist/discord/command/create-command.d.ts +1 -8
- package/dist/discord/command/create-command.d.ts.map +1 -1
- package/dist/discord/command/create-command.js +17 -65
- package/dist/discord/command/create-command.js.map +1 -1
- package/dist/discord/command/create-context-menu-command.d.ts +3 -9
- package/dist/discord/command/create-context-menu-command.d.ts.map +1 -1
- package/dist/discord/command/create-context-menu-command.js +14 -65
- package/dist/discord/command/create-context-menu-command.js.map +1 -1
- package/dist/discord/command/errors.d.ts +1 -1
- package/dist/discord/command/errors.d.ts.map +1 -1
- package/dist/discord/command/errors.js +2 -2
- package/dist/discord/command/errors.js.map +1 -1
- package/dist/discord/command/guard.d.ts +15 -8
- package/dist/discord/command/guard.d.ts.map +1 -1
- package/dist/discord/command/guard.js +4 -4
- package/dist/discord/command/guard.js.map +1 -1
- package/dist/discord/command/options.d.ts +1 -10
- package/dist/discord/command/options.d.ts.map +1 -1
- package/dist/discord/command/options.js +127 -320
- package/dist/discord/command/options.js.map +1 -1
- package/dist/discord/command/passes-guard.d.ts +14 -0
- package/dist/discord/command/passes-guard.d.ts.map +1 -0
- package/dist/discord/command/passes-guard.js +27 -0
- package/dist/discord/command/passes-guard.js.map +1 -0
- package/dist/discord/command/permission-guard.d.ts +1 -1
- package/dist/discord/command/permission-guard.d.ts.map +1 -1
- package/dist/discord/command/render-command-failure.d.ts +23 -0
- package/dist/discord/command/render-command-failure.d.ts.map +1 -0
- package/dist/discord/command/render-command-failure.js +40 -0
- package/dist/discord/command/render-command-failure.js.map +1 -0
- package/dist/discord/command/route-key.d.ts +8 -0
- package/dist/discord/command/route-key.d.ts.map +1 -0
- package/dist/discord/command/route-key.js +13 -0
- package/dist/discord/command/route-key.js.map +1 -0
- package/dist/discord/command/router.d.ts +32 -7
- package/dist/discord/command/router.d.ts.map +1 -1
- package/dist/discord/command/router.js +48 -10
- package/dist/discord/command/router.js.map +1 -1
- package/dist/discord/command/send-embed.d.ts +14 -0
- package/dist/discord/command/send-embed.d.ts.map +1 -0
- package/dist/discord/command/send-embed.js +37 -0
- package/dist/discord/command/send-embed.js.map +1 -0
- package/dist/discord/command/types.d.ts +7 -1
- package/dist/discord/command/types.d.ts.map +1 -1
- package/dist/discord/components/component-access.d.ts +12 -0
- package/dist/discord/components/component-access.d.ts.map +1 -0
- package/dist/discord/components/component-access.js +21 -0
- package/dist/discord/components/component-access.js.map +1 -0
- package/dist/discord/components/component-router.d.ts +37 -15
- package/dist/discord/components/component-router.d.ts.map +1 -1
- package/dist/discord/components/component-router.js +44 -32
- package/dist/discord/components/component-router.js.map +1 -1
- package/dist/discord/components/interactive-message/index.d.ts +3 -1
- package/dist/discord/components/interactive-message/index.d.ts.map +1 -1
- package/dist/discord/components/interactive-message/index.js +5 -3
- package/dist/discord/components/interactive-message/index.js.map +1 -1
- package/dist/discord/components/interactive-message/interactive-message-collector.d.ts +3 -28
- package/dist/discord/components/interactive-message/interactive-message-collector.d.ts.map +1 -1
- package/dist/discord/components/interactive-message/interactive-message-collector.js +6 -53
- package/dist/discord/components/interactive-message/interactive-message-collector.js.map +1 -1
- package/dist/discord/components/interactive-message/message-edit-options.d.ts +18 -0
- package/dist/discord/components/interactive-message/message-edit-options.d.ts.map +1 -0
- package/dist/discord/components/interactive-message/message-edit-options.js +40 -0
- package/dist/discord/components/interactive-message/message-edit-options.js.map +1 -0
- package/dist/discord/components/interactive-message/mount-interactive-message.d.ts +2 -1
- package/dist/discord/components/interactive-message/mount-interactive-message.d.ts.map +1 -1
- package/dist/discord/components/interactive-message/mount-interactive-message.js +4 -2
- package/dist/discord/components/interactive-message/mount-interactive-message.js.map +1 -1
- package/dist/discord/components/interactive-message/state-store.d.ts +12 -0
- package/dist/discord/components/interactive-message/state-store.d.ts.map +1 -0
- package/dist/discord/components/interactive-message/state-store.js +14 -0
- package/dist/discord/components/interactive-message/state-store.js.map +1 -0
- package/dist/discord/components/paginator/mount-paginator.js +7 -5
- package/dist/discord/components/paginator/mount-paginator.js.map +1 -1
- package/dist/discord/components/paginator/paginator-view.d.ts +1 -1
- package/dist/discord/components/paginator/paginator-view.d.ts.map +1 -1
- package/dist/discord/components/persistent-paginator.d.ts +1 -1
- package/dist/discord/components/persistent-paginator.d.ts.map +1 -1
- package/dist/discord/components/persistent-paginator.js +6 -6
- package/dist/discord/components/persistent-paginator.js.map +1 -1
- package/dist/discord/components/settings-editor/from-declaration-controls.d.ts +67 -0
- package/dist/discord/components/settings-editor/from-declaration-controls.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-controls.js +245 -0
- package/dist/discord/components/settings-editor/from-declaration-controls.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-display.d.ts +23 -0
- package/dist/discord/components/settings-editor/from-declaration-display.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-display.js +114 -0
- package/dist/discord/components/settings-editor/from-declaration-display.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-layout.d.ts +33 -0
- package/dist/discord/components/settings-editor/from-declaration-layout.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-layout.js +178 -0
- package/dist/discord/components/settings-editor/from-declaration-layout.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-search.d.ts +27 -0
- package/dist/discord/components/settings-editor/from-declaration-search.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-search.js +58 -0
- package/dist/discord/components/settings-editor/from-declaration-search.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-stored.d.ts +21 -0
- package/dist/discord/components/settings-editor/from-declaration-stored.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-stored.js +37 -0
- package/dist/discord/components/settings-editor/from-declaration-stored.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-subject.d.ts +32 -0
- package/dist/discord/components/settings-editor/from-declaration-subject.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-subject.js +65 -0
- package/dist/discord/components/settings-editor/from-declaration-subject.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-values.d.ts +57 -0
- package/dist/discord/components/settings-editor/from-declaration-values.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration-values.js +187 -0
- package/dist/discord/components/settings-editor/from-declaration-values.js.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration.d.ts +39 -0
- package/dist/discord/components/settings-editor/from-declaration.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/from-declaration.js +132 -0
- package/dist/discord/components/settings-editor/from-declaration.js.map +1 -0
- package/dist/discord/components/settings-editor/index.d.ts +3 -1
- package/dist/discord/components/settings-editor/index.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/index.js +6 -3
- package/dist/discord/components/settings-editor/index.js.map +1 -1
- package/dist/discord/components/settings-editor/mount-settings-editor.d.ts +16 -2
- package/dist/discord/components/settings-editor/mount-settings-editor.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/mount-settings-editor.js +14 -10
- package/dist/discord/components/settings-editor/mount-settings-editor.js.map +1 -1
- package/dist/discord/components/settings-editor/navigation.d.ts +20 -0
- package/dist/discord/components/settings-editor/navigation.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/navigation.js +22 -0
- package/dist/discord/components/settings-editor/navigation.js.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor-card.view.d.ts +4 -3
- package/dist/discord/components/settings-editor/settings-editor-card.view.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor-card.view.js +60 -34
- package/dist/discord/components/settings-editor/settings-editor-card.view.js.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor-field-modal.d.ts +2 -1
- package/dist/discord/components/settings-editor/settings-editor-field-modal.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor-field-modal.js +48 -72
- package/dist/discord/components/settings-editor/settings-editor-field-modal.js.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor-field-values.d.ts +6 -0
- package/dist/discord/components/settings-editor/settings-editor-field-values.d.ts.map +1 -0
- package/dist/discord/components/settings-editor/settings-editor-field-values.js +13 -0
- package/dist/discord/components/settings-editor/settings-editor-field-values.js.map +1 -0
- package/dist/discord/components/settings-editor/settings-editor-fields.d.ts +6 -5
- package/dist/discord/components/settings-editor/settings-editor-fields.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor-fields.js +0 -10
- package/dist/discord/components/settings-editor/settings-editor-fields.js.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor.view.d.ts +3 -2
- package/dist/discord/components/settings-editor/settings-editor.view.d.ts.map +1 -1
- package/dist/discord/components/settings-editor/settings-editor.view.js +4 -21
- package/dist/discord/components/settings-editor/settings-editor.view.js.map +1 -1
- package/dist/discord/events/event-guild-id.d.ts +10 -0
- package/dist/discord/events/event-guild-id.d.ts.map +1 -0
- package/dist/discord/events/event-guild-id.js +37 -0
- package/dist/discord/events/event-guild-id.js.map +1 -0
- package/dist/discord/events/event-router.d.ts +17 -3
- package/dist/discord/events/event-router.d.ts.map +1 -1
- package/dist/discord/events/event-router.js +33 -9
- package/dist/discord/events/event-router.js.map +1 -1
- package/dist/discord/i18n.d.ts +17 -2
- package/dist/discord/i18n.d.ts.map +1 -1
- package/dist/discord/i18n.js +43 -6
- package/dist/discord/i18n.js.map +1 -1
- package/dist/discord/interaction/interaction-locale.d.ts +14 -0
- package/dist/discord/interaction/interaction-locale.d.ts.map +1 -0
- package/dist/discord/interaction/interaction-locale.js +12 -0
- package/dist/discord/interaction/interaction-locale.js.map +1 -0
- package/dist/discord/interaction/locale-resolver.d.ts +27 -0
- package/dist/discord/interaction/locale-resolver.d.ts.map +1 -0
- package/dist/discord/interaction/locale-resolver.js +3 -0
- package/dist/discord/interaction/locale-resolver.js.map +1 -0
- package/dist/discord/interaction/modal.d.ts.map +1 -1
- package/dist/discord/interaction/modal.js +5 -40
- package/dist/discord/interaction/modal.js.map +1 -1
- package/dist/discord/interaction/reply-locale.d.ts +18 -0
- package/dist/discord/interaction/reply-locale.d.ts.map +1 -0
- package/dist/discord/interaction/reply-locale.js +25 -0
- package/dist/discord/interaction/reply-locale.js.map +1 -0
- package/dist/discord/interaction/select-bounds.d.ts +19 -0
- package/dist/discord/interaction/select-bounds.d.ts.map +1 -0
- package/dist/discord/interaction/select-bounds.js +17 -0
- package/dist/discord/interaction/select-bounds.js.map +1 -0
- package/dist/discord/interaction/select-menu.d.ts.map +1 -1
- package/dist/discord/interaction/select-menu.js +2 -9
- package/dist/discord/interaction/select-menu.js.map +1 -1
- package/dist/discord/placeholder-registry.d.ts +1 -1
- package/dist/discord/placeholder-registry.d.ts.map +1 -1
- package/dist/discord/presenter.d.ts +1 -1
- package/dist/discord/presenter.d.ts.map +1 -1
- package/dist/discord/settings/discord-guild-directory.d.ts +28 -0
- package/dist/discord/settings/discord-guild-directory.d.ts.map +1 -0
- package/dist/discord/settings/discord-guild-directory.js +171 -0
- package/dist/discord/settings/discord-guild-directory.js.map +1 -0
- package/dist/discord/settings/guild-locale-resolver.d.ts +25 -0
- package/dist/discord/settings/guild-locale-resolver.d.ts.map +1 -0
- package/dist/discord/settings/guild-locale-resolver.js +33 -0
- package/dist/discord/settings/guild-locale-resolver.js.map +1 -0
- package/dist/discord/settings/is-module-disabled.d.ts +16 -0
- package/dist/discord/settings/is-module-disabled.d.ts.map +1 -0
- package/dist/discord/settings/is-module-disabled.js +20 -0
- package/dist/discord/settings/is-module-disabled.js.map +1 -0
- package/dist/discord/settings/module-disabled-embed.d.ts +13 -0
- package/dist/discord/settings/module-disabled-embed.d.ts.map +1 -0
- package/dist/discord/settings/module-disabled-embed.js +16 -0
- package/dist/discord/settings/module-disabled-embed.js.map +1 -0
- package/dist/discord/settings/require-configured.d.ts +26 -0
- package/dist/discord/settings/require-configured.d.ts.map +1 -0
- package/dist/discord/settings/require-configured.js +62 -0
- package/dist/discord/settings/require-configured.js.map +1 -0
- package/dist/discord/ui/color-aliases.d.ts +31 -0
- package/dist/discord/ui/color-aliases.d.ts.map +1 -0
- package/dist/discord/ui/color-aliases.js +66 -0
- package/dist/discord/ui/color-aliases.js.map +1 -0
- package/dist/discord/ui/color-input.d.ts +5 -32
- package/dist/discord/ui/color-input.d.ts.map +1 -1
- package/dist/discord/ui/color-input.js +8 -157
- package/dist/discord/ui/color-input.js.map +1 -1
- package/dist/discord/ui/colors.d.ts +0 -2
- package/dist/discord/ui/colors.d.ts.map +1 -1
- package/dist/discord/ui/colors.js +4 -5
- package/dist/discord/ui/colors.js.map +1 -1
- package/dist/discord/ui/embed.d.ts.map +1 -1
- package/dist/discord/ui/embed.js +3 -8
- package/dist/discord/ui/embed.js.map +1 -1
- package/dist/discord/ui/truncate-text.d.ts +11 -0
- package/dist/discord/ui/truncate-text.d.ts.map +1 -0
- package/dist/discord/ui/truncate-text.js +19 -0
- package/dist/discord/ui/truncate-text.js.map +1 -0
- package/dist/errors/error-message.d.ts +9 -0
- package/dist/errors/error-message.d.ts.map +1 -0
- package/dist/errors/error-message.js +14 -0
- package/dist/errors/error-message.js.map +1 -0
- package/dist/i18n/business-message.d.ts +1 -1
- package/dist/i18n/business-message.d.ts.map +1 -1
- package/dist/i18n/catalog.d.ts +9 -0
- package/dist/i18n/catalog.d.ts.map +1 -1
- package/dist/i18n/catalog.js +4 -0
- package/dist/i18n/catalog.js.map +1 -1
- package/dist/i18n/locale.d.ts +2 -0
- package/dist/i18n/locale.d.ts.map +1 -1
- package/dist/i18n/locale.js +3 -1
- package/dist/i18n/locale.js.map +1 -1
- package/dist/i18n/translator.d.ts +2 -0
- package/dist/i18n/translator.d.ts.map +1 -1
- package/dist/i18n/translator.js.map +1 -1
- package/dist/module/module.d.ts +15 -1
- package/dist/module/module.d.ts.map +1 -1
- package/dist/resilience/retry.js +2 -2
- package/dist/resilience/retry.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts.map +1 -1
- package/dist/scheduler/scheduler.js +2 -4
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/settings/cache.d.ts +29 -0
- package/dist/settings/cache.d.ts.map +1 -0
- package/dist/settings/cache.js +47 -0
- package/dist/settings/cache.js.map +1 -0
- package/dist/settings/choice.d.ts +10 -0
- package/dist/settings/choice.d.ts.map +1 -0
- package/dist/settings/choice.js +3 -0
- package/dist/settings/choice.js.map +1 -0
- package/dist/settings/decode-stored.d.ts +20 -0
- package/dist/settings/decode-stored.d.ts.map +1 -0
- package/dist/settings/decode-stored.js +35 -0
- package/dist/settings/decode-stored.js.map +1 -0
- package/dist/settings/define-settings.d.ts +52 -0
- package/dist/settings/define-settings.d.ts.map +1 -0
- package/dist/settings/define-settings.js +141 -0
- package/dist/settings/define-settings.js.map +1 -0
- package/dist/settings/describe-field.d.ts +19 -0
- package/dist/settings/describe-field.d.ts.map +1 -0
- package/dist/settings/describe-field.js +131 -0
- package/dist/settings/describe-field.js.map +1 -0
- package/dist/settings/describe.d.ts +27 -0
- package/dist/settings/describe.d.ts.map +1 -0
- package/dist/settings/describe.js +62 -0
- package/dist/settings/describe.js.map +1 -0
- package/dist/settings/duration.d.ts +16 -0
- package/dist/settings/duration.d.ts.map +1 -0
- package/dist/settings/duration.js +56 -0
- package/dist/settings/duration.js.map +1 -0
- package/dist/settings/field-order.d.ts +37 -0
- package/dist/settings/field-order.d.ts.map +1 -0
- package/dist/settings/field-order.js +100 -0
- package/dist/settings/field-order.js.map +1 -0
- package/dist/settings/field-search.d.ts +10 -0
- package/dist/settings/field-search.d.ts.map +1 -0
- package/dist/settings/field-search.js +18 -0
- package/dist/settings/field-search.js.map +1 -0
- package/dist/settings/fields/builders.d.ts +41 -0
- package/dist/settings/fields/builders.d.ts.map +1 -0
- package/dist/settings/fields/builders.js +83 -0
- package/dist/settings/fields/builders.js.map +1 -0
- package/dist/settings/fields/field.d.ts +199 -0
- package/dist/settings/fields/field.d.ts.map +1 -0
- package/dist/settings/fields/field.js +33 -0
- package/dist/settings/fields/field.js.map +1 -0
- package/dist/settings/fields/zod-schema.d.ts +67 -0
- package/dist/settings/fields/zod-schema.d.ts.map +1 -0
- package/dist/settings/fields/zod-schema.js +281 -0
- package/dist/settings/fields/zod-schema.js.map +1 -0
- package/dist/settings/in-memory/in-memory-guild-directory.d.ts +24 -0
- package/dist/settings/in-memory/in-memory-guild-directory.d.ts.map +1 -0
- package/dist/settings/in-memory/in-memory-guild-directory.js +42 -0
- package/dist/settings/in-memory/in-memory-guild-directory.js.map +1 -0
- package/dist/settings/in-memory/in-memory-settings-store.d.ts +8 -0
- package/dist/settings/in-memory/in-memory-settings-store.d.ts.map +1 -0
- package/dist/settings/in-memory/in-memory-settings-store.js +43 -0
- package/dist/settings/in-memory/in-memory-settings-store.js.map +1 -0
- package/dist/settings/in-memory/in-process-notifier.d.ts +9 -0
- package/dist/settings/in-memory/in-process-notifier.d.ts.map +1 -0
- package/dist/settings/in-memory/in-process-notifier.js +32 -0
- package/dist/settings/in-memory/in-process-notifier.js.map +1 -0
- package/dist/settings/index.d.ts +22 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +31 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/is-plain-object.d.ts +6 -0
- package/dist/settings/is-plain-object.d.ts.map +1 -0
- package/dist/settings/is-plain-object.js +15 -0
- package/dist/settings/is-plain-object.js.map +1 -0
- package/dist/settings/messages.d.ts +61 -0
- package/dist/settings/messages.d.ts.map +1 -0
- package/dist/settings/messages.js +155 -0
- package/dist/settings/messages.js.map +1 -0
- package/dist/settings/migrate.d.ts +35 -0
- package/dist/settings/migrate.d.ts.map +1 -0
- package/dist/settings/migrate.js +42 -0
- package/dist/settings/migrate.js.map +1 -0
- package/dist/settings/ports/guild-directory.d.ts +61 -0
- package/dist/settings/ports/guild-directory.d.ts.map +1 -0
- package/dist/settings/ports/guild-directory.js +3 -0
- package/dist/settings/ports/guild-directory.js.map +1 -0
- package/dist/settings/ports/settings-changed-notifier.d.ts +20 -0
- package/dist/settings/ports/settings-changed-notifier.d.ts.map +1 -0
- package/dist/settings/ports/settings-changed-notifier.js +3 -0
- package/dist/settings/ports/settings-changed-notifier.js.map +1 -0
- package/dist/settings/ports/settings-store.d.ts +76 -0
- package/dist/settings/ports/settings-store.d.ts.map +1 -0
- package/dist/settings/ports/settings-store.js +3 -0
- package/dist/settings/ports/settings-store.js.map +1 -0
- package/dist/settings/registry.d.ts +31 -0
- package/dist/settings/registry.d.ts.map +1 -0
- package/dist/settings/registry.js +102 -0
- package/dist/settings/registry.js.map +1 -0
- package/dist/settings/settings-declaration-error.d.ts +13 -0
- package/dist/settings/settings-declaration-error.d.ts.map +1 -0
- package/dist/settings/settings-declaration-error.js +22 -0
- package/dist/settings/settings-declaration-error.js.map +1 -0
- package/dist/settings/settings-service.d.ts +148 -0
- package/dist/settings/settings-service.d.ts.map +1 -0
- package/dist/settings/settings-service.js +279 -0
- package/dist/settings/settings-service.js.map +1 -0
- package/dist/settings/settings-validation-error.d.ts +23 -0
- package/dist/settings/settings-validation-error.d.ts.map +1 -0
- package/dist/settings/settings-validation-error.js +17 -0
- package/dist/settings/settings-validation-error.js.map +1 -0
- package/dist/settings/status.d.ts +16 -0
- package/dist/settings/status.d.ts.map +1 -0
- package/dist/settings/status.js +18 -0
- package/dist/settings/status.js.map +1 -0
- package/dist/settings/suggest.d.ts +77 -0
- package/dist/settings/suggest.d.ts.map +1 -0
- package/dist/settings/suggest.js +192 -0
- package/dist/settings/suggest.js.map +1 -0
- package/dist/settings/system/kernel-settings.d.ts +43 -0
- package/dist/settings/system/kernel-settings.d.ts.map +1 -0
- package/dist/settings/system/kernel-settings.js +53 -0
- package/dist/settings/system/kernel-settings.js.map +1 -0
- package/dist/settings/system/module-gate.d.ts +31 -0
- package/dist/settings/system/module-gate.d.ts.map +1 -0
- package/dist/settings/system/module-gate.js +34 -0
- package/dist/settings/system/module-gate.js.map +1 -0
- package/dist/settings/testing/index.d.ts +2 -0
- package/dist/settings/testing/index.d.ts.map +1 -0
- package/dist/settings/testing/index.js +6 -0
- package/dist/settings/testing/index.js.map +1 -0
- package/dist/settings/testing/settings-store-contract.d.ts +29 -0
- package/dist/settings/testing/settings-store-contract.d.ts.map +1 -0
- package/dist/settings/testing/settings-store-contract.js +192 -0
- package/dist/settings/testing/settings-store-contract.js.map +1 -0
- package/dist/settings/timed-search.d.ts +26 -0
- package/dist/settings/timed-search.d.ts.map +1 -0
- package/dist/settings/timed-search.js +48 -0
- package/dist/settings/timed-search.js.map +1 -0
- package/dist/settings/types.d.ts +37 -0
- package/dist/settings/types.d.ts.map +1 -0
- package/dist/settings/types.js +3 -0
- package/dist/settings/types.js.map +1 -0
- package/dist/settings/validate.d.ts +55 -0
- package/dist/settings/validate.d.ts.map +1 -0
- package/dist/settings/validate.js +196 -0
- package/dist/settings/validate.js.map +1 -0
- package/package.json +463 -88
- package/src/authz/require-level-guard.ts +1 -1
- package/src/color.ts +134 -0
- package/src/discord/command/all-required.ts +12 -0
- package/src/discord/command/autocomplete-dispatcher.ts +2 -1
- package/src/discord/command/autocomplete-limits.ts +2 -0
- package/src/discord/command/autocomplete.ts +8 -7
- package/src/discord/command/command-responders.ts +39 -0
- package/src/discord/command/context.ts +14 -54
- package/src/discord/command/cooldown-guard.ts +1 -1
- package/src/discord/command/create-command.ts +19 -94
- package/src/discord/command/create-context-menu-command.ts +19 -97
- package/src/discord/command/errors.ts +1 -1
- package/src/discord/command/guard.ts +24 -12
- package/src/discord/command/options.ts +202 -412
- package/src/discord/command/passes-guard.ts +37 -0
- package/src/discord/command/permission-guard.ts +1 -1
- package/src/discord/command/render-command-failure.ts +71 -0
- package/src/discord/command/route-key.ts +9 -0
- package/src/discord/command/router.ts +73 -12
- package/src/discord/command/send-embed.ts +42 -0
- package/src/discord/command/types.ts +7 -1
- package/src/discord/components/component-access.ts +20 -0
- package/src/discord/components/component-router.ts +73 -36
- package/src/discord/components/interactive-message/index.ts +5 -3
- package/src/discord/components/interactive-message/interactive-message-collector.ts +4 -68
- package/src/discord/components/interactive-message/message-edit-options.ts +47 -0
- package/src/discord/components/interactive-message/mount-interactive-message.ts +5 -3
- package/src/discord/components/interactive-message/state-store.ts +20 -0
- package/src/discord/components/paginator/mount-paginator.ts +3 -3
- package/src/discord/components/paginator/paginator-view.ts +1 -1
- package/src/discord/components/persistent-paginator.ts +8 -9
- package/src/discord/components/settings-editor/from-declaration-controls.ts +371 -0
- package/src/discord/components/settings-editor/from-declaration-display.ts +155 -0
- package/src/discord/components/settings-editor/from-declaration-layout.ts +247 -0
- package/src/discord/components/settings-editor/from-declaration-search.ts +77 -0
- package/src/discord/components/settings-editor/from-declaration-stored.ts +39 -0
- package/src/discord/components/settings-editor/from-declaration-subject.ts +110 -0
- package/src/discord/components/settings-editor/from-declaration-values.ts +240 -0
- package/src/discord/components/settings-editor/from-declaration.ts +218 -0
- package/src/discord/components/settings-editor/index.ts +5 -2
- package/src/discord/components/settings-editor/mount-settings-editor.ts +28 -10
- package/src/discord/components/settings-editor/navigation.ts +41 -0
- package/src/discord/components/settings-editor/settings-editor-card.view.ts +79 -36
- package/src/discord/components/settings-editor/settings-editor-field-modal.ts +76 -68
- package/src/discord/components/settings-editor/settings-editor-field-values.ts +11 -0
- package/src/discord/components/settings-editor/settings-editor-fields.ts +6 -11
- package/src/discord/components/settings-editor/settings-editor.view.ts +11 -24
- package/src/discord/events/event-guild-id.ts +35 -0
- package/src/discord/events/event-router.ts +46 -13
- package/src/discord/i18n.ts +47 -8
- package/src/discord/interaction/interaction-locale.ts +19 -0
- package/src/discord/interaction/locale-resolver.ts +28 -0
- package/src/discord/interaction/modal.ts +5 -40
- package/src/discord/interaction/reply-locale.ts +35 -0
- package/src/discord/interaction/select-bounds.ts +33 -0
- package/src/discord/interaction/select-menu.ts +2 -9
- package/src/discord/placeholder-registry.ts +1 -1
- package/src/discord/presenter.ts +1 -1
- package/src/discord/settings/discord-guild-directory.ts +214 -0
- package/src/discord/settings/guild-locale-resolver.ts +38 -0
- package/src/discord/settings/is-module-disabled.ts +22 -0
- package/src/discord/settings/module-disabled-embed.ts +19 -0
- package/src/discord/settings/require-configured.ts +68 -0
- package/src/discord/ui/color-aliases.ts +70 -0
- package/src/discord/ui/color-input.ts +8 -173
- package/src/discord/ui/colors.ts +2 -3
- package/src/discord/ui/embed.ts +3 -9
- package/src/discord/ui/truncate-text.ts +15 -0
- package/src/errors/error-message.ts +10 -0
- package/src/i18n/business-message.ts +1 -1
- package/src/i18n/catalog.ts +14 -0
- package/src/i18n/locale.ts +3 -0
- package/src/i18n/translator.ts +3 -0
- package/src/module/module.ts +15 -1
- package/src/resilience/retry.ts +1 -1
- package/src/scheduler/scheduler.ts +2 -5
- package/src/settings/cache.ts +70 -0
- package/src/settings/choice.ts +9 -0
- package/src/settings/decode-stored.ts +40 -0
- package/src/settings/define-settings.ts +214 -0
- package/src/settings/describe-field.ts +155 -0
- package/src/settings/describe.ts +90 -0
- package/src/settings/duration.ts +54 -0
- package/src/settings/field-order.ts +128 -0
- package/src/settings/field-search.ts +16 -0
- package/src/settings/fields/builders.ts +161 -0
- package/src/settings/fields/field.ts +205 -0
- package/src/settings/fields/zod-schema.ts +300 -0
- package/src/settings/in-memory/in-memory-guild-directory.ts +69 -0
- package/src/settings/in-memory/in-memory-settings-store.ts +46 -0
- package/src/settings/in-memory/in-process-notifier.ts +40 -0
- package/src/settings/index.ts +72 -0
- package/src/settings/is-plain-object.ts +11 -0
- package/src/settings/messages.ts +161 -0
- package/src/settings/migrate.ts +58 -0
- package/src/settings/ports/guild-directory.ts +48 -0
- package/src/settings/ports/settings-changed-notifier.ts +20 -0
- package/src/settings/ports/settings-store.ts +74 -0
- package/src/settings/registry.ts +137 -0
- package/src/settings/settings-declaration-error.ts +16 -0
- package/src/settings/settings-service.ts +535 -0
- package/src/settings/settings-validation-error.ts +41 -0
- package/src/settings/status.ts +25 -0
- package/src/settings/suggest.ts +267 -0
- package/src/settings/system/kernel-settings.ts +74 -0
- package/src/settings/system/module-gate.ts +49 -0
- package/src/settings/testing/index.ts +7 -0
- package/src/settings/testing/settings-store-contract.ts +278 -0
- package/src/settings/timed-search.ts +56 -0
- package/src/settings/types.ts +42 -0
- package/src/settings/validate.ts +298 -0
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
} from "discord.js";
|
|
21
21
|
import { isValidWallClock } from "@/datetime";
|
|
22
22
|
import { OptionValidationError } from "@/discord/command/errors";
|
|
23
|
+
import type { Choice } from "@/settings/choice";
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Translated name/description for a single option, keyed by Discord locale
|
|
@@ -32,14 +33,28 @@ export interface OptionLocalizations {
|
|
|
32
33
|
descriptionLocalizations?: LocalizationMap;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
/** The setters every discord.js option builder shares, whatever its type. */
|
|
37
|
+
interface OptionBuilder {
|
|
38
|
+
setName(name: string): unknown;
|
|
39
|
+
setDescription(description: string): unknown;
|
|
40
|
+
setRequired(required: boolean): unknown;
|
|
41
|
+
setNameLocalizations(map: LocalizationMap): unknown;
|
|
42
|
+
setDescriptionLocalizations(map: LocalizationMap): unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The block every option type opens with: its name, description, whether it
|
|
47
|
+
* is required, and its translated labels.
|
|
48
|
+
*/
|
|
49
|
+
function describeOption(
|
|
50
|
+
option: OptionBuilder,
|
|
51
|
+
name: string,
|
|
52
|
+
declared: { readonly description: string; readonly isRequired: boolean },
|
|
41
53
|
localizations: OptionLocalizations,
|
|
42
54
|
): void {
|
|
55
|
+
option.setName(name);
|
|
56
|
+
option.setDescription(declared.description);
|
|
57
|
+
option.setRequired(declared.isRequired);
|
|
43
58
|
if (localizations.nameLocalizations) {
|
|
44
59
|
option.setNameLocalizations(localizations.nameLocalizations);
|
|
45
60
|
}
|
|
@@ -75,12 +90,6 @@ export interface OptionContainer {
|
|
|
75
90
|
): unknown;
|
|
76
91
|
}
|
|
77
92
|
|
|
78
|
-
/** A single suggestion returned to Discord while the user types. */
|
|
79
|
-
export interface Choice {
|
|
80
|
-
readonly name: string;
|
|
81
|
-
readonly value: string | number;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
93
|
/**
|
|
85
94
|
* Computes the suggestions for a focused option. Sync resolvers are allowed so a
|
|
86
95
|
* static list does not have to pay for a promise.
|
|
@@ -199,8 +208,7 @@ class StringOption<TValue extends string, TRequired extends boolean>
|
|
|
199
208
|
apply(container: OptionContainer, name: string): void {
|
|
200
209
|
assertChoicesAndAutocompleteExclusive(this.choiceValues !== null, this.autocomplete);
|
|
201
210
|
container.addStringOption((option) => {
|
|
202
|
-
option
|
|
203
|
-
applyOptionLocalizations(option, this.localizations);
|
|
211
|
+
describeOption(option, name, this, this.localizations);
|
|
204
212
|
if (this.choiceValues) {
|
|
205
213
|
option.addChoices(...this.choiceValues.map((value) => ({ name: value, value })));
|
|
206
214
|
}
|
|
@@ -245,85 +253,86 @@ export function createStringOption(
|
|
|
245
253
|
);
|
|
246
254
|
}
|
|
247
255
|
|
|
248
|
-
|
|
256
|
+
/**
|
|
257
|
+
* What an option type contributes on top of the shared name/description/
|
|
258
|
+
* required/localization block: which builder it registers through (and any
|
|
259
|
+
* extra setter it applies there), how it reads the submitted value, and the
|
|
260
|
+
* name its `choices()` refusal gives it.
|
|
261
|
+
*/
|
|
262
|
+
interface OptionKind<TValue, TBuilder> {
|
|
263
|
+
readonly label: string;
|
|
264
|
+
add(container: OptionContainer, configure: (option: TBuilder) => void): void;
|
|
265
|
+
read(interaction: ChatInputCommandInteraction, name: string, required: boolean): TValue | null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Adapt a `configure` step to the builder callback discord.js expects back. */
|
|
269
|
+
function configuring<TBase>(
|
|
270
|
+
configure: (option: TBase) => void,
|
|
271
|
+
): <TBuilder extends TBase>(option: TBuilder) => TBuilder {
|
|
272
|
+
return (option) => {
|
|
273
|
+
configure(option);
|
|
274
|
+
return option;
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* An option type that supports neither choices nor autocomplete: every
|
|
280
|
+
* difference between two of them lives in their {@link OptionKind}.
|
|
281
|
+
*/
|
|
282
|
+
class PlainOption<TValue, TRequired extends boolean> implements Option<TValue, TRequired> {
|
|
249
283
|
constructor(
|
|
284
|
+
private readonly kind: OptionKind<TValue, OptionBuilder>,
|
|
250
285
|
readonly description: string,
|
|
251
286
|
readonly isRequired: TRequired,
|
|
252
287
|
private readonly localizations: OptionLocalizations = {},
|
|
253
288
|
) {}
|
|
254
289
|
|
|
255
|
-
required(): Option<
|
|
256
|
-
return new
|
|
290
|
+
required(): Option<TValue, true> {
|
|
291
|
+
return new PlainOption<TValue, true>(this.kind, this.description, true, this.localizations);
|
|
257
292
|
}
|
|
258
293
|
|
|
259
|
-
choices<const C extends readonly
|
|
260
|
-
throw new OptionValidationError(
|
|
294
|
+
choices<const C extends readonly TValue[]>(_values: C): Option<C[number], TRequired> {
|
|
295
|
+
throw new OptionValidationError(`${this.kind.label} options do not support choices.`);
|
|
261
296
|
}
|
|
262
297
|
|
|
263
298
|
apply(container: OptionContainer, name: string): void {
|
|
264
|
-
|
|
265
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
266
|
-
applyOptionLocalizations(option, this.localizations);
|
|
267
|
-
return option;
|
|
268
|
-
});
|
|
299
|
+
this.kind.add(container, (option) => describeOption(option, name, this, this.localizations));
|
|
269
300
|
}
|
|
270
301
|
|
|
271
302
|
read(
|
|
272
303
|
interaction: ChatInputCommandInteraction,
|
|
273
304
|
name: string,
|
|
274
|
-
): TRequired extends true ?
|
|
275
|
-
return
|
|
276
|
-
?
|
|
277
|
-
:
|
|
305
|
+
): TRequired extends true ? TValue : TValue | null {
|
|
306
|
+
return this.kind.read(interaction, name, this.isRequired) as TRequired extends true
|
|
307
|
+
? TValue
|
|
308
|
+
: TValue | null;
|
|
278
309
|
}
|
|
279
310
|
}
|
|
280
311
|
|
|
312
|
+
const USER_KIND: OptionKind<User, OptionBuilder> = {
|
|
313
|
+
label: "User",
|
|
314
|
+
add: (container, configure) => container.addUserOption(configuring(configure)),
|
|
315
|
+
read: (interaction, name, required) => interaction.options.getUser(name, required),
|
|
316
|
+
};
|
|
317
|
+
|
|
281
318
|
export function createUserOption(
|
|
282
319
|
description: string,
|
|
283
320
|
localizations: OptionLocalizations = {},
|
|
284
321
|
): Option<User, false> {
|
|
285
|
-
return new
|
|
322
|
+
return new PlainOption<User, false>(USER_KIND, description, false, localizations);
|
|
286
323
|
}
|
|
287
324
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
) {}
|
|
294
|
-
|
|
295
|
-
required(): Option<boolean, true> {
|
|
296
|
-
return new BooleanOption<true>(this.description, true, this.localizations);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
choices<const C extends readonly boolean[]>(_values: C): Option<C[number], TRequired> {
|
|
300
|
-
throw new OptionValidationError("Boolean options do not support choices.");
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
apply(container: OptionContainer, name: string): void {
|
|
304
|
-
container.addBooleanOption((option) => {
|
|
305
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
306
|
-
applyOptionLocalizations(option, this.localizations);
|
|
307
|
-
return option;
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
read(
|
|
312
|
-
interaction: ChatInputCommandInteraction,
|
|
313
|
-
name: string,
|
|
314
|
-
): TRequired extends true ? boolean : boolean | null {
|
|
315
|
-
return interaction.options.getBoolean(
|
|
316
|
-
name,
|
|
317
|
-
this.isRequired as boolean,
|
|
318
|
-
) as TRequired extends true ? boolean : boolean | null;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
325
|
+
const BOOLEAN_KIND: OptionKind<boolean, OptionBuilder> = {
|
|
326
|
+
label: "Boolean",
|
|
327
|
+
add: (container, configure) => container.addBooleanOption(configuring(configure)),
|
|
328
|
+
read: (interaction, name, required) => interaction.options.getBoolean(name, required),
|
|
329
|
+
};
|
|
321
330
|
|
|
322
331
|
export function createBooleanOption(
|
|
323
332
|
description: string,
|
|
324
333
|
localizations: OptionLocalizations = {},
|
|
325
334
|
): Option<boolean, false> {
|
|
326
|
-
return new
|
|
335
|
+
return new PlainOption<boolean, false>(BOOLEAN_KIND, description, false, localizations);
|
|
327
336
|
}
|
|
328
337
|
|
|
329
338
|
interface IntegerBounds {
|
|
@@ -331,8 +340,20 @@ interface IntegerBounds {
|
|
|
331
340
|
max?: number;
|
|
332
341
|
}
|
|
333
342
|
|
|
334
|
-
|
|
343
|
+
/** The setters the integer and number builders share on top of the plain ones. */
|
|
344
|
+
interface NumericOptionBuilder extends OptionBuilder {
|
|
345
|
+
setMinValue(min: number): unknown;
|
|
346
|
+
setMaxValue(max: number): unknown;
|
|
347
|
+
setAutocomplete(autocomplete: boolean): unknown;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* An integer or a number option: bounded, autocompletable, never offered as a
|
|
352
|
+
* fixed choice list. The two differ only in their {@link OptionKind}.
|
|
353
|
+
*/
|
|
354
|
+
class NumericOption<TRequired extends boolean> implements AutocompletableOption<number, TRequired> {
|
|
335
355
|
constructor(
|
|
356
|
+
private readonly kind: OptionKind<number, NumericOptionBuilder>,
|
|
336
357
|
readonly description: string,
|
|
337
358
|
readonly isRequired: TRequired,
|
|
338
359
|
private readonly bounds: IntegerBounds,
|
|
@@ -341,7 +362,8 @@ class IntegerOption<TRequired extends boolean> implements AutocompletableOption<
|
|
|
341
362
|
) {}
|
|
342
363
|
|
|
343
364
|
required(): AutocompletableOption<number, true> {
|
|
344
|
-
return new
|
|
365
|
+
return new NumericOption<true>(
|
|
366
|
+
this.kind,
|
|
345
367
|
this.description,
|
|
346
368
|
true,
|
|
347
369
|
this.bounds,
|
|
@@ -351,11 +373,12 @@ class IntegerOption<TRequired extends boolean> implements AutocompletableOption<
|
|
|
351
373
|
}
|
|
352
374
|
|
|
353
375
|
choices<const C extends readonly number[]>(_values: C): Option<C[number], TRequired> {
|
|
354
|
-
throw new OptionValidationError(
|
|
376
|
+
throw new OptionValidationError(`${this.kind.label} options do not support choices.`);
|
|
355
377
|
}
|
|
356
378
|
|
|
357
379
|
withAutocomplete(resolver: AutocompleteResolver): AutocompletableOption<number, TRequired> {
|
|
358
|
-
return new
|
|
380
|
+
return new NumericOption<TRequired>(
|
|
381
|
+
this.kind,
|
|
359
382
|
this.description,
|
|
360
383
|
this.isRequired,
|
|
361
384
|
this.bounds,
|
|
@@ -365,9 +388,8 @@ class IntegerOption<TRequired extends boolean> implements AutocompletableOption<
|
|
|
365
388
|
}
|
|
366
389
|
|
|
367
390
|
apply(container: OptionContainer, name: string): void {
|
|
368
|
-
|
|
369
|
-
option
|
|
370
|
-
applyOptionLocalizations(option, this.localizations);
|
|
391
|
+
this.kind.add(container, (option) => {
|
|
392
|
+
describeOption(option, name, this, this.localizations);
|
|
371
393
|
if (this.bounds.min !== undefined) {
|
|
372
394
|
option.setMinValue(this.bounds.min);
|
|
373
395
|
}
|
|
@@ -377,7 +399,6 @@ class IntegerOption<TRequired extends boolean> implements AutocompletableOption<
|
|
|
377
399
|
if (this.autocomplete !== undefined) {
|
|
378
400
|
option.setAutocomplete(true);
|
|
379
401
|
}
|
|
380
|
-
return option;
|
|
381
402
|
});
|
|
382
403
|
}
|
|
383
404
|
|
|
@@ -385,139 +406,84 @@ class IntegerOption<TRequired extends boolean> implements AutocompletableOption<
|
|
|
385
406
|
interaction: ChatInputCommandInteraction,
|
|
386
407
|
name: string,
|
|
387
408
|
): TRequired extends true ? number : number | null {
|
|
388
|
-
return
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
) as TRequired extends true ? number : number | null;
|
|
409
|
+
return this.kind.read(interaction, name, this.isRequired) as TRequired extends true
|
|
410
|
+
? number
|
|
411
|
+
: number | null;
|
|
392
412
|
}
|
|
393
413
|
}
|
|
394
414
|
|
|
415
|
+
const INTEGER_KIND: OptionKind<number, NumericOptionBuilder> = {
|
|
416
|
+
label: "Integer",
|
|
417
|
+
add: (container, configure) => container.addIntegerOption(configuring(configure)),
|
|
418
|
+
read: (interaction, name, required) => interaction.options.getInteger(name, required),
|
|
419
|
+
};
|
|
420
|
+
|
|
395
421
|
export function createIntegerOption(
|
|
396
422
|
description: string,
|
|
397
423
|
bounds: IntegerBounds = {},
|
|
398
424
|
localizations: OptionLocalizations = {},
|
|
399
425
|
): AutocompletableOption<number, false> {
|
|
400
|
-
return new
|
|
426
|
+
return new NumericOption<false>(
|
|
427
|
+
INTEGER_KIND,
|
|
428
|
+
description,
|
|
429
|
+
false,
|
|
430
|
+
bounds,
|
|
431
|
+
undefined,
|
|
432
|
+
localizations,
|
|
433
|
+
);
|
|
401
434
|
}
|
|
402
435
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
readonly autocomplete?: AutocompleteResolver,
|
|
409
|
-
private readonly localizations: OptionLocalizations = {},
|
|
410
|
-
) {}
|
|
411
|
-
|
|
412
|
-
required(): AutocompletableOption<number, true> {
|
|
413
|
-
return new NumberOption<true>(
|
|
414
|
-
this.description,
|
|
415
|
-
true,
|
|
416
|
-
this.bounds,
|
|
417
|
-
this.autocomplete,
|
|
418
|
-
this.localizations,
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
choices<const C extends readonly number[]>(_values: C): Option<C[number], TRequired> {
|
|
423
|
-
throw new OptionValidationError("Number options do not support choices.");
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
withAutocomplete(resolver: AutocompleteResolver): AutocompletableOption<number, TRequired> {
|
|
427
|
-
return new NumberOption<TRequired>(
|
|
428
|
-
this.description,
|
|
429
|
-
this.isRequired,
|
|
430
|
-
this.bounds,
|
|
431
|
-
resolver,
|
|
432
|
-
this.localizations,
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
apply(container: OptionContainer, name: string): void {
|
|
437
|
-
container.addNumberOption((option) => {
|
|
438
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
439
|
-
applyOptionLocalizations(option, this.localizations);
|
|
440
|
-
if (this.bounds.min !== undefined) {
|
|
441
|
-
option.setMinValue(this.bounds.min);
|
|
442
|
-
}
|
|
443
|
-
if (this.bounds.max !== undefined) {
|
|
444
|
-
option.setMaxValue(this.bounds.max);
|
|
445
|
-
}
|
|
446
|
-
if (this.autocomplete !== undefined) {
|
|
447
|
-
option.setAutocomplete(true);
|
|
448
|
-
}
|
|
449
|
-
return option;
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
read(
|
|
454
|
-
interaction: ChatInputCommandInteraction,
|
|
455
|
-
name: string,
|
|
456
|
-
): TRequired extends true ? number : number | null {
|
|
457
|
-
return interaction.options.getNumber(name, this.isRequired as boolean) as TRequired extends true
|
|
458
|
-
? number
|
|
459
|
-
: number | null;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
436
|
+
const NUMBER_KIND: OptionKind<number, NumericOptionBuilder> = {
|
|
437
|
+
label: "Number",
|
|
438
|
+
add: (container, configure) => container.addNumberOption(configuring(configure)),
|
|
439
|
+
read: (interaction, name, required) => interaction.options.getNumber(name, required),
|
|
440
|
+
};
|
|
462
441
|
|
|
463
442
|
export function createNumberOption(
|
|
464
443
|
description: string,
|
|
465
444
|
bounds: IntegerBounds = {},
|
|
466
445
|
localizations: OptionLocalizations = {},
|
|
467
446
|
): AutocompletableOption<number, false> {
|
|
468
|
-
return new
|
|
447
|
+
return new NumericOption<false>(
|
|
448
|
+
NUMBER_KIND,
|
|
449
|
+
description,
|
|
450
|
+
false,
|
|
451
|
+
bounds,
|
|
452
|
+
undefined,
|
|
453
|
+
localizations,
|
|
454
|
+
);
|
|
469
455
|
}
|
|
470
456
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
457
|
+
/** A plain string input whose raw text is validated, then converted, by `parse`. */
|
|
458
|
+
function textKind<TValue>(
|
|
459
|
+
label: string,
|
|
460
|
+
parse: (raw: string) => TValue,
|
|
461
|
+
): OptionKind<TValue, OptionBuilder> {
|
|
462
|
+
return {
|
|
463
|
+
label,
|
|
464
|
+
add: (container, configure) => container.addStringOption(configuring(configure)),
|
|
465
|
+
read: (interaction, name, required) => {
|
|
466
|
+
const raw = interaction.options.getString(name, required);
|
|
467
|
+
return raw === null ? null : parse(raw);
|
|
468
|
+
},
|
|
469
|
+
};
|
|
478
470
|
}
|
|
479
471
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
readonly description: string,
|
|
483
|
-
readonly isRequired: TRequired,
|
|
484
|
-
private readonly localizations: OptionLocalizations = {},
|
|
485
|
-
) {}
|
|
486
|
-
|
|
487
|
-
required(): Option<Date, true> {
|
|
488
|
-
return new DateTimeOption<true>(this.description, true, this.localizations);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
choices<const C extends readonly Date[]>(_values: C): Option<C[number], TRequired> {
|
|
492
|
-
throw new OptionValidationError("Date options do not support choices.");
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
apply(container: OptionContainer, name: string): void {
|
|
496
|
-
container.addStringOption((option) => {
|
|
497
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
498
|
-
applyOptionLocalizations(option, this.localizations);
|
|
499
|
-
return option;
|
|
500
|
-
});
|
|
501
|
-
}
|
|
472
|
+
const INVALID_DATETIME_MESSAGE =
|
|
473
|
+
"Invalid date format. Use `YYYY-MM-DD HH:MM` (e.g. `2025-03-15 14:00`).";
|
|
502
474
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
): TRequired extends true ? Date : Date | null {
|
|
507
|
-
const raw = interaction.options.getString(name, this.isRequired as boolean);
|
|
508
|
-
if (raw === null) {
|
|
509
|
-
return null as TRequired extends true ? Date : Date | null;
|
|
510
|
-
}
|
|
511
|
-
assertValidDate(raw, INVALID_DATETIME_MESSAGE);
|
|
512
|
-
return new Date(raw.replace(" ", "T")) as TRequired extends true ? Date : Date | null;
|
|
475
|
+
const DATE_TIME_KIND = textKind<Date>("Date", (raw) => {
|
|
476
|
+
if (Number.isNaN(Date.parse(raw))) {
|
|
477
|
+
throw new OptionValidationError(INVALID_DATETIME_MESSAGE);
|
|
513
478
|
}
|
|
514
|
-
|
|
479
|
+
return new Date(raw.replace(" ", "T"));
|
|
480
|
+
});
|
|
515
481
|
|
|
516
482
|
export function createDateTimeOption(
|
|
517
483
|
description: string,
|
|
518
484
|
localizations: OptionLocalizations = {},
|
|
519
485
|
): Option<Date, false> {
|
|
520
|
-
return new
|
|
486
|
+
return new PlainOption<Date, false>(DATE_TIME_KIND, description, false, localizations);
|
|
521
487
|
}
|
|
522
488
|
|
|
523
489
|
const INVALID_WALL_CLOCK_MESSAGE =
|
|
@@ -532,43 +498,12 @@ const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
532
498
|
* IANA zone applies. This is what lets the same option be reused by any module
|
|
533
499
|
* that needs a wall-clock input.
|
|
534
500
|
*/
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
readonly isRequired: TRequired,
|
|
539
|
-
private readonly localizations: OptionLocalizations = {},
|
|
540
|
-
) {}
|
|
541
|
-
|
|
542
|
-
required(): Option<string, true> {
|
|
543
|
-
return new WallClockOption<true>(this.description, true, this.localizations);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
choices<const C extends readonly string[]>(_values: C): Option<C[number], TRequired> {
|
|
547
|
-
throw new OptionValidationError("Wall-clock options do not support choices.");
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
apply(container: OptionContainer, name: string): void {
|
|
551
|
-
container.addStringOption((option) => {
|
|
552
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
553
|
-
applyOptionLocalizations(option, this.localizations);
|
|
554
|
-
return option;
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
read(
|
|
559
|
-
interaction: ChatInputCommandInteraction,
|
|
560
|
-
name: string,
|
|
561
|
-
): TRequired extends true ? string : string | null {
|
|
562
|
-
const raw = interaction.options.getString(name, this.isRequired as boolean);
|
|
563
|
-
if (raw === null) {
|
|
564
|
-
return null as TRequired extends true ? string : string | null;
|
|
565
|
-
}
|
|
566
|
-
if (!isValidWallClock(raw)) {
|
|
567
|
-
throw new OptionValidationError(INVALID_WALL_CLOCK_MESSAGE);
|
|
568
|
-
}
|
|
569
|
-
return raw as TRequired extends true ? string : string | null;
|
|
501
|
+
const WALL_CLOCK_KIND = textKind<string>("Wall-clock", (raw) => {
|
|
502
|
+
if (!isValidWallClock(raw)) {
|
|
503
|
+
throw new OptionValidationError(INVALID_WALL_CLOCK_MESSAGE);
|
|
570
504
|
}
|
|
571
|
-
|
|
505
|
+
return raw;
|
|
506
|
+
});
|
|
572
507
|
|
|
573
508
|
/**
|
|
574
509
|
* A `YYYY-MM-DD[ HH:MM[:SS]]` string option, validated against the wall-clock
|
|
@@ -579,49 +514,18 @@ export function createWallClockOption(
|
|
|
579
514
|
description: string,
|
|
580
515
|
localizations: OptionLocalizations = {},
|
|
581
516
|
): Option<string, false> {
|
|
582
|
-
return new
|
|
517
|
+
return new PlainOption<string, false>(WALL_CLOCK_KIND, description, false, localizations);
|
|
583
518
|
}
|
|
584
519
|
|
|
585
520
|
/** A strict, date-only (`YYYY-MM-DD`) option — rejects any time component. */
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
) {}
|
|
592
|
-
|
|
593
|
-
required(): Option<Date, true> {
|
|
594
|
-
return new DateOption<true>(this.description, true, this.localizations);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
choices<const C extends readonly Date[]>(_values: C): Option<C[number], TRequired> {
|
|
598
|
-
throw new OptionValidationError("Date options do not support choices.");
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
apply(container: OptionContainer, name: string): void {
|
|
602
|
-
container.addStringOption((option) => {
|
|
603
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
604
|
-
applyOptionLocalizations(option, this.localizations);
|
|
605
|
-
return option;
|
|
606
|
-
});
|
|
521
|
+
const DATE_KIND = textKind<Date>("Date", (raw) => {
|
|
522
|
+
// Strict `YYYY-MM-DD` with a real-calendar check (rejects `2026/03/15`,
|
|
523
|
+
// time-bearing input, and impossible dates like `2026-02-30`).
|
|
524
|
+
if (!DATE_ONLY_PATTERN.test(raw) || !isValidWallClock(raw)) {
|
|
525
|
+
throw new OptionValidationError(INVALID_DATE_ONLY_MESSAGE);
|
|
607
526
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
interaction: ChatInputCommandInteraction,
|
|
611
|
-
name: string,
|
|
612
|
-
): TRequired extends true ? Date : Date | null {
|
|
613
|
-
const raw = interaction.options.getString(name, this.isRequired as boolean);
|
|
614
|
-
if (raw === null) {
|
|
615
|
-
return null as TRequired extends true ? Date : Date | null;
|
|
616
|
-
}
|
|
617
|
-
// Strict `YYYY-MM-DD` with a real-calendar check (rejects `2026/03/15`,
|
|
618
|
-
// time-bearing input, and impossible dates like `2026-02-30`).
|
|
619
|
-
if (!DATE_ONLY_PATTERN.test(raw) || !isValidWallClock(raw)) {
|
|
620
|
-
throw new OptionValidationError(INVALID_DATE_ONLY_MESSAGE);
|
|
621
|
-
}
|
|
622
|
-
return new Date(raw) as TRequired extends true ? Date : Date | null;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
527
|
+
return new Date(raw);
|
|
528
|
+
});
|
|
625
529
|
|
|
626
530
|
/**
|
|
627
531
|
* A strict date-only (`YYYY-MM-DD`) option. The returned `Date` is UTC
|
|
@@ -633,7 +537,7 @@ export function createDateOption(
|
|
|
633
537
|
description: string,
|
|
634
538
|
localizations: OptionLocalizations = {},
|
|
635
539
|
): Option<Date, false> {
|
|
636
|
-
return new
|
|
540
|
+
return new PlainOption<Date, false>(DATE_KIND, description, false, localizations);
|
|
637
541
|
}
|
|
638
542
|
|
|
639
543
|
/** The channel types Discord accepts on a channel option (guild channels only). */
|
|
@@ -655,54 +559,28 @@ export type ChannelOptionValue<TType extends AllowedChannelType> = Extract<
|
|
|
655
559
|
}
|
|
656
560
|
>;
|
|
657
561
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
{
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
true,
|
|
672
|
-
this.channelTypes,
|
|
673
|
-
this.localizations,
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
choices<const C extends readonly ChannelOptionValue<TType>[]>(
|
|
678
|
-
_values: C,
|
|
679
|
-
): Option<C[number], TRequired> {
|
|
680
|
-
throw new OptionValidationError("Channel options do not support choices.");
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
apply(container: OptionContainer, name: string): void {
|
|
684
|
-
container.addChannelOption((option) => {
|
|
685
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
686
|
-
applyOptionLocalizations(option, this.localizations);
|
|
687
|
-
if (this.channelTypes !== undefined) {
|
|
688
|
-
option.addChannelTypes(...this.channelTypes);
|
|
689
|
-
}
|
|
690
|
-
return option;
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
read(
|
|
695
|
-
interaction: ChatInputCommandInteraction,
|
|
696
|
-
name: string,
|
|
697
|
-
): TRequired extends true ? ChannelOptionValue<TType> : ChannelOptionValue<TType> | null {
|
|
562
|
+
function channelKind<TType extends AllowedChannelType>(
|
|
563
|
+
channelTypes: readonly TType[] | undefined,
|
|
564
|
+
): OptionKind<ChannelOptionValue<TType>, OptionBuilder> {
|
|
565
|
+
return {
|
|
566
|
+
label: "Channel",
|
|
567
|
+
add: (container, configure) =>
|
|
568
|
+
container.addChannelOption((option) => {
|
|
569
|
+
configure(option);
|
|
570
|
+
if (channelTypes !== undefined) {
|
|
571
|
+
option.addChannelTypes(...channelTypes);
|
|
572
|
+
}
|
|
573
|
+
return option;
|
|
574
|
+
}),
|
|
698
575
|
// The declared types are re-sent at read time: `addChannelTypes` only drives
|
|
699
576
|
// the client-side picker, so Discord can still deliver another channel kind.
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
577
|
+
read: (interaction, name, required) =>
|
|
578
|
+
interaction.options.getChannel(
|
|
579
|
+
name,
|
|
580
|
+
required,
|
|
581
|
+
channelTypes,
|
|
582
|
+
) as ChannelOptionValue<TType> | null,
|
|
583
|
+
};
|
|
706
584
|
}
|
|
707
585
|
|
|
708
586
|
export function createChannelOption<const TType extends AllowedChannelType = AllowedChannelType>(
|
|
@@ -710,138 +588,50 @@ export function createChannelOption<const TType extends AllowedChannelType = All
|
|
|
710
588
|
channelTypes?: readonly TType[],
|
|
711
589
|
localizations: OptionLocalizations = {},
|
|
712
590
|
): Option<ChannelOptionValue<TType>, false> {
|
|
713
|
-
return new
|
|
591
|
+
return new PlainOption<ChannelOptionValue<TType>, false>(
|
|
592
|
+
channelKind(channelTypes),
|
|
593
|
+
description,
|
|
594
|
+
false,
|
|
595
|
+
localizations,
|
|
596
|
+
);
|
|
714
597
|
}
|
|
715
598
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
) {}
|
|
722
|
-
|
|
723
|
-
required(): Option<Role, true> {
|
|
724
|
-
return new RoleOption<true>(this.description, true, this.localizations);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
choices<const C extends readonly Role[]>(_values: C): Option<C[number], TRequired> {
|
|
728
|
-
throw new OptionValidationError("Role options do not support choices.");
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
apply(container: OptionContainer, name: string): void {
|
|
732
|
-
container.addRoleOption((option) => {
|
|
733
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
734
|
-
applyOptionLocalizations(option, this.localizations);
|
|
735
|
-
return option;
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
read(
|
|
740
|
-
interaction: ChatInputCommandInteraction,
|
|
741
|
-
name: string,
|
|
742
|
-
): TRequired extends true ? Role : Role | null {
|
|
743
|
-
return interaction.options.getRole(name, this.isRequired as boolean) as TRequired extends true
|
|
744
|
-
? Role
|
|
745
|
-
: Role | null;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
599
|
+
const ROLE_KIND: OptionKind<Role, OptionBuilder> = {
|
|
600
|
+
label: "Role",
|
|
601
|
+
add: (container, configure) => container.addRoleOption(configuring(configure)),
|
|
602
|
+
read: (interaction, name, required) => interaction.options.getRole(name, required) as Role | null,
|
|
603
|
+
};
|
|
748
604
|
|
|
749
605
|
export function createRoleOption(
|
|
750
606
|
description: string,
|
|
751
607
|
localizations: OptionLocalizations = {},
|
|
752
608
|
): Option<Role, false> {
|
|
753
|
-
return new
|
|
609
|
+
return new PlainOption<Role, false>(ROLE_KIND, description, false, localizations);
|
|
754
610
|
}
|
|
755
611
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
required(): Option<Role | User, true> {
|
|
764
|
-
return new MentionableOption<true>(this.description, true, this.localizations);
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
choices<const C extends readonly (Role | User)[]>(_values: C): Option<C[number], TRequired> {
|
|
768
|
-
throw new OptionValidationError("Mentionable options do not support choices.");
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
apply(container: OptionContainer, name: string): void {
|
|
772
|
-
container.addMentionableOption((option) => {
|
|
773
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
774
|
-
applyOptionLocalizations(option, this.localizations);
|
|
775
|
-
return option;
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
read(
|
|
780
|
-
interaction: ChatInputCommandInteraction,
|
|
781
|
-
name: string,
|
|
782
|
-
): TRequired extends true ? Role | User : Role | User | null {
|
|
783
|
-
return interaction.options.getMentionable(
|
|
784
|
-
name,
|
|
785
|
-
this.isRequired as boolean,
|
|
786
|
-
) as TRequired extends true ? Role | User : Role | User | null;
|
|
787
|
-
}
|
|
788
|
-
}
|
|
612
|
+
const MENTIONABLE_KIND: OptionKind<Role | User, OptionBuilder> = {
|
|
613
|
+
label: "Mentionable",
|
|
614
|
+
add: (container, configure) => container.addMentionableOption(configuring(configure)),
|
|
615
|
+
read: (interaction, name, required) =>
|
|
616
|
+
interaction.options.getMentionable(name, required) as Role | User | null,
|
|
617
|
+
};
|
|
789
618
|
|
|
790
619
|
export function createMentionableOption(
|
|
791
620
|
description: string,
|
|
792
621
|
localizations: OptionLocalizations = {},
|
|
793
622
|
): Option<Role | User, false> {
|
|
794
|
-
return new
|
|
623
|
+
return new PlainOption<Role | User, false>(MENTIONABLE_KIND, description, false, localizations);
|
|
795
624
|
}
|
|
796
625
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
) {}
|
|
803
|
-
|
|
804
|
-
required(): Option<Attachment, true> {
|
|
805
|
-
return new AttachmentOption<true>(this.description, true, this.localizations);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
choices<const C extends readonly Attachment[]>(_values: C): Option<C[number], TRequired> {
|
|
809
|
-
throw new OptionValidationError("Attachment options do not support choices.");
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
apply(container: OptionContainer, name: string): void {
|
|
813
|
-
container.addAttachmentOption((option) => {
|
|
814
|
-
option.setName(name).setDescription(this.description).setRequired(this.isRequired);
|
|
815
|
-
applyOptionLocalizations(option, this.localizations);
|
|
816
|
-
return option;
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
read(
|
|
821
|
-
interaction: ChatInputCommandInteraction,
|
|
822
|
-
name: string,
|
|
823
|
-
): TRequired extends true ? Attachment : Attachment | null {
|
|
824
|
-
return interaction.options.getAttachment(
|
|
825
|
-
name,
|
|
826
|
-
this.isRequired as boolean,
|
|
827
|
-
) as TRequired extends true ? Attachment : Attachment | null;
|
|
828
|
-
}
|
|
829
|
-
}
|
|
626
|
+
const ATTACHMENT_KIND: OptionKind<Attachment, OptionBuilder> = {
|
|
627
|
+
label: "Attachment",
|
|
628
|
+
add: (container, configure) => container.addAttachmentOption(configuring(configure)),
|
|
629
|
+
read: (interaction, name, required) => interaction.options.getAttachment(name, required),
|
|
630
|
+
};
|
|
830
631
|
|
|
831
632
|
export function createAttachmentOption(
|
|
832
633
|
description: string,
|
|
833
634
|
localizations: OptionLocalizations = {},
|
|
834
635
|
): Option<Attachment, false> {
|
|
835
|
-
return new
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
type AsRequired<O> = O extends Option<infer V, boolean> ? Option<V, true> : never;
|
|
839
|
-
|
|
840
|
-
/** Turn every option in a record into its required variant. */
|
|
841
|
-
export function allRequired<O extends Options>(fields: O): { [K in keyof O]: AsRequired<O[K]> } {
|
|
842
|
-
const out = {} as { [K in keyof O]: AsRequired<O[K]> };
|
|
843
|
-
for (const [key, option] of Object.entries(fields)) {
|
|
844
|
-
out[key as keyof O] = option.required() as AsRequired<O[keyof O]>;
|
|
845
|
-
}
|
|
846
|
-
return out;
|
|
636
|
+
return new PlainOption<Attachment, false>(ATTACHMENT_KIND, description, false, localizations);
|
|
847
637
|
}
|