@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
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { subtext, TimestampStyles, time } from "discord.js";
|
|
2
|
+
import type { InteractiveView } from "@/discord/components/interactive-message/interactive-message-collector";
|
|
2
3
|
import {
|
|
3
4
|
canReturn,
|
|
4
5
|
currentLevelKey,
|
|
6
|
+
indexLevels,
|
|
7
|
+
levelTrail,
|
|
5
8
|
ROOT_LEVEL_KEY,
|
|
6
9
|
type SettingsEditorLevel,
|
|
7
10
|
} from "@/discord/components/settings-editor/navigation";
|
|
@@ -20,7 +23,9 @@ import { SETTINGS_EDITOR_MESSAGES } from "@/discord/i18n";
|
|
|
20
23
|
import { type Button, createActionRow } from "@/discord/interaction/button";
|
|
21
24
|
import { type CardBlock, type CardDef, createCard } from "@/discord/ui/card";
|
|
22
25
|
import { EMBED_COLORS } from "@/discord/ui/colors";
|
|
23
|
-
import
|
|
26
|
+
import { truncateText } from "@/discord/ui/truncate-text";
|
|
27
|
+
import type { Locale } from "@/i18n/locale";
|
|
28
|
+
import type { Translator } from "@/i18n/translator";
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
31
|
* Discord refuses a card carrying more than {@link import("@/discord/ui/card").MAX_CARD_COMPONENTS}
|
|
@@ -68,6 +73,23 @@ export const MAX_CARD_BUTTON_LEVEL_ENTRIES = 20;
|
|
|
68
73
|
*/
|
|
69
74
|
const ENTRY_ACTIONS_RESERVE = 2;
|
|
70
75
|
|
|
76
|
+
/**
|
|
77
|
+
* The most characters an entry's "Current: …" line may take. Well under the
|
|
78
|
+
* 4000 a card's text may hold in total: ten entries each showing a long value
|
|
79
|
+
* must still leave room for the preview and the chrome around them.
|
|
80
|
+
*/
|
|
81
|
+
const MAX_CURRENT_VALUE_LENGTH = 200;
|
|
82
|
+
|
|
83
|
+
/** Separates a group's members on its one "Current: …" line. */
|
|
84
|
+
const GROUP_MEMBER_SEPARATOR = " · ";
|
|
85
|
+
|
|
86
|
+
/** A value's own line breaks, folded so it stays on the one line it is given. */
|
|
87
|
+
const LINE_BREAKS = /\s*\r?\n\s*/g;
|
|
88
|
+
|
|
89
|
+
function oneLine(value: string): string {
|
|
90
|
+
return value.replace(LINE_BREAKS, " ");
|
|
91
|
+
}
|
|
92
|
+
|
|
71
93
|
/**
|
|
72
94
|
* The button a menu entry's own `Section` carries, derived from the field's
|
|
73
95
|
* key rather than declared alongside it — the same relationship `ids.field`
|
|
@@ -102,30 +124,24 @@ export function createCardEditorView<S, A, F extends string>(
|
|
|
102
124
|
translator: Translator,
|
|
103
125
|
locale: Locale,
|
|
104
126
|
dressing: SettingsEditorDressing,
|
|
127
|
+
displayValue?: (subject: S, field: F) => string | null,
|
|
105
128
|
): InteractiveView<SettingsEditorState<S, A>> {
|
|
106
129
|
const screenTitle = translator.translate(locale, chrome.titleKey);
|
|
107
|
-
// Separates the levels in the breadcrumb trail.
|
|
108
|
-
const BREADCRUMB_SEPARATOR = " › ";
|
|
109
130
|
|
|
110
|
-
// The root
|
|
111
|
-
//
|
|
112
|
-
// `
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
titleKey: chrome.titleKey,
|
|
118
|
-
fields,
|
|
119
|
-
entryLayout: chrome.entryLayout,
|
|
120
|
-
};
|
|
121
|
-
const allLevels: readonly SettingsEditorLevel<F>[] = [root, ...(levels ?? [])];
|
|
131
|
+
// The root's own `entryLayout` is the chrome's, mirroring
|
|
132
|
+
// `SettingsEditorLevel.entryLayout` for the one level that is never itself a
|
|
133
|
+
// `SettingsEditorLevel`.
|
|
134
|
+
const allLevels = indexLevels(
|
|
135
|
+
{ key: ROOT_LEVEL_KEY, titleKey: chrome.titleKey, fields, entryLayout: chrome.entryLayout },
|
|
136
|
+
levels,
|
|
137
|
+
);
|
|
122
138
|
|
|
123
139
|
// A level's fields are authored, not accumulated: passing more entries than a
|
|
124
140
|
// card can carry is a mistake in the declaration, and Discord would reject
|
|
125
141
|
// the whole message rather than show the first ones that fit. Failing here
|
|
126
142
|
// names the level; failing at render time would only say the message was
|
|
127
143
|
// invalid.
|
|
128
|
-
for (const level of allLevels) {
|
|
144
|
+
for (const level of allLevels.all) {
|
|
129
145
|
// A `"buttons"` level spends its budget on rows of `ActionRow`s rather
|
|
130
146
|
// than `Section`s, so it is checked against its own, higher cap instead
|
|
131
147
|
// of the `"sections"` one — failing here names the level rather than the
|
|
@@ -149,18 +165,10 @@ export function createCardEditorView<S, A, F extends string>(
|
|
|
149
165
|
}
|
|
150
166
|
}
|
|
151
167
|
|
|
152
|
-
function levelAt(key: string): SettingsEditorLevel<F> {
|
|
153
|
-
return allLevels.find((level) => level.key === key) ?? root;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Where the reader is, as a trail rather than only the current name: a level
|
|
158
|
-
* called "Roles" says nothing on its own about which type it belongs to.
|
|
159
|
-
*/
|
|
160
168
|
function heading(state: SettingsEditorState<S, A>): string {
|
|
161
|
-
return state.path
|
|
162
|
-
|
|
163
|
-
|
|
169
|
+
return levelTrail(state.path, allLevels, (level) =>
|
|
170
|
+
translator.translate(locale, level.titleKey),
|
|
171
|
+
);
|
|
164
172
|
}
|
|
165
173
|
|
|
166
174
|
/**
|
|
@@ -170,19 +178,54 @@ export function createCardEditorView<S, A, F extends string>(
|
|
|
170
178
|
* an embed's timestamp already did.
|
|
171
179
|
*/
|
|
172
180
|
function signature(): string {
|
|
173
|
-
|
|
174
|
-
|
|
181
|
+
return subtext(`${screenTitle} • ${time(dressing.clock.now(), TimestampStyles.ShortTime)}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* What an entry currently holds, as the text after the "Current:" prefix:
|
|
186
|
+
* the hook's own answer for a single field, one `label: value` per member
|
|
187
|
+
* holding one for a group, nothing for a level. `null` when there is
|
|
188
|
+
* nothing to show — no hook, or a hook answering `null` throughout.
|
|
189
|
+
*/
|
|
190
|
+
function currentText(field: SettingsEditorField<F>, subject: S): string | null {
|
|
191
|
+
if (displayValue === undefined || field.kind === "level") {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
if (field.kind !== "group") {
|
|
195
|
+
return displayValue(subject, field.key);
|
|
196
|
+
}
|
|
197
|
+
const members = field.fields.flatMap((member) => {
|
|
198
|
+
const value = displayValue(subject, member.key);
|
|
199
|
+
return value === null ? [] : [`${translator.translate(locale, member.labelKey)}: ${value}`];
|
|
200
|
+
});
|
|
201
|
+
return members.length === 0 ? null : members.join(GROUP_MEMBER_SEPARATOR);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** {@link currentText}, prefixed and cut to {@link MAX_CURRENT_VALUE_LENGTH}; none when it is `null`. */
|
|
205
|
+
function currentLines(field: SettingsEditorField<F>, subject: S): string[] {
|
|
206
|
+
const value = currentText(field, subject);
|
|
207
|
+
if (value === null) {
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
const line = translator.translate(locale, SETTINGS_EDITOR_MESSAGES.currentValue, {
|
|
211
|
+
value: oneLine(value),
|
|
212
|
+
});
|
|
213
|
+
return [truncateText(line, MAX_CURRENT_VALUE_LENGTH)];
|
|
175
214
|
}
|
|
176
215
|
|
|
177
216
|
/**
|
|
178
217
|
* One menu entry, as the `Section` that replaces it: its label as the title,
|
|
179
|
-
* its hint as the line under it,
|
|
218
|
+
* its hint as the line under it, what it currently holds under that when the
|
|
219
|
+
* screen declares `displayValue`, and the button `mountSettingsEditor`
|
|
180
220
|
* registered for it as the accessory — the very button that opens its modal
|
|
181
221
|
* or descends into it, reached by a click instead of a pick.
|
|
182
222
|
*/
|
|
183
|
-
function entrySection(
|
|
223
|
+
function entrySection(
|
|
224
|
+
field: SettingsEditorField<F>,
|
|
225
|
+
subject: S,
|
|
226
|
+
): CardBlock<SettingsEditorState<S, A>> {
|
|
184
227
|
const title = translator.translate(locale, field.labelKey);
|
|
185
|
-
const lines = [translator.translate(locale, field.hintKey)];
|
|
228
|
+
const lines = [translator.translate(locale, field.hintKey), ...currentLines(field, subject)];
|
|
186
229
|
const action = fieldButtons.get(field.key);
|
|
187
230
|
return action === undefined
|
|
188
231
|
? { kind: "entry", title, lines }
|
|
@@ -287,7 +330,7 @@ export function createCardEditorView<S, A, F extends string>(
|
|
|
287
330
|
state: SettingsEditorState<S, A>,
|
|
288
331
|
): readonly (CardBlock<SettingsEditorState<S, A>> | null)[] {
|
|
289
332
|
const confirmingReset = state.confirming === SETTINGS_EDITOR_RESET_CONFIRMING;
|
|
290
|
-
const level =
|
|
333
|
+
const level = allLevels.at(currentLevelKey(state.path));
|
|
291
334
|
|
|
292
335
|
const notice: CardBlock<SettingsEditorState<S, A>> | null = confirmingReset
|
|
293
336
|
? {
|
|
@@ -302,10 +345,10 @@ export function createCardEditorView<S, A, F extends string>(
|
|
|
302
345
|
const entries: CardBlock<SettingsEditorState<S, A>>[] =
|
|
303
346
|
level.entryLayout === "buttons"
|
|
304
347
|
? buttonRows(levelButtons(level, state))
|
|
305
|
-
: level.fields.map((field) => entrySection(field));
|
|
348
|
+
: level.fields.map((field) => entrySection(field, state.subject));
|
|
306
349
|
|
|
307
350
|
return [
|
|
308
|
-
{ kind: "text", content:
|
|
351
|
+
{ kind: "text", content: subtext(heading(state)) },
|
|
309
352
|
notice,
|
|
310
353
|
...(chrome.extraBlocks?.(state, confirmingReset) ?? []),
|
|
311
354
|
{ kind: "separator" },
|
|
@@ -17,12 +17,15 @@ import {
|
|
|
17
17
|
type ChannelFieldDef,
|
|
18
18
|
createModal,
|
|
19
19
|
type ModalFields,
|
|
20
|
+
type ModalValues,
|
|
20
21
|
type RoleFieldDef,
|
|
21
22
|
type SelectFieldDef,
|
|
22
23
|
type TextFieldDef,
|
|
23
24
|
type UserFieldDef,
|
|
24
25
|
} from "@/discord/interaction/modal";
|
|
25
|
-
import type {
|
|
26
|
+
import type { SelectBounds } from "@/discord/interaction/select-bounds";
|
|
27
|
+
import type { Locale } from "@/i18n/locale";
|
|
28
|
+
import type { Translator } from "@/i18n/translator";
|
|
26
29
|
|
|
27
30
|
const EDITOR_FIELD_MODAL_ID = "settings-editor:field-value";
|
|
28
31
|
const EDITOR_GROUP_MODAL_ID = "settings-editor:group-value";
|
|
@@ -125,8 +128,23 @@ export async function promptEditorFieldValue<F extends string>(
|
|
|
125
128
|
? createImageModal(field, current, translator, locale)
|
|
126
129
|
: createTextModal(field, current, translator, locale);
|
|
127
130
|
|
|
131
|
+
const submitted = await collectModalSubmission(
|
|
132
|
+
interaction,
|
|
133
|
+
modal.build(nextModalOpenState(field.key)),
|
|
134
|
+
);
|
|
135
|
+
return submitted === null ? null : { interaction: submitted, ...modal.read(submitted) };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Show `built` and wait for this very opening's submission. `null` on timeout,
|
|
140
|
+
* on any failure to show or collect it, and on a submission that did not come
|
|
141
|
+
* from a message.
|
|
142
|
+
*/
|
|
143
|
+
async function collectModalSubmission(
|
|
144
|
+
interaction: MessageComponentInteraction,
|
|
145
|
+
built: ModalBuilder,
|
|
146
|
+
): Promise<ModalMessageModalSubmitInteraction | null> {
|
|
128
147
|
try {
|
|
129
|
-
const built = modal.build(nextModalOpenState(field.key));
|
|
130
148
|
const expectedCustomId = customIdOf(built);
|
|
131
149
|
await interaction.showModal(built);
|
|
132
150
|
const submitted = await interaction.awaitModalSubmit({
|
|
@@ -141,7 +159,7 @@ export async function promptEditorFieldValue<F extends string>(
|
|
|
141
159
|
if (!submitted.isFromMessage()) {
|
|
142
160
|
return null;
|
|
143
161
|
}
|
|
144
|
-
return
|
|
162
|
+
return submitted;
|
|
145
163
|
} catch {
|
|
146
164
|
return null;
|
|
147
165
|
}
|
|
@@ -192,22 +210,11 @@ export async function promptEditorGroupValue<F extends string>(
|
|
|
192
210
|
locale: Locale,
|
|
193
211
|
): Promise<SettingsEditorGroupPrompt<F> | null> {
|
|
194
212
|
const modal = createGroupModal(group, currentValue, legend, translator, locale);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
time: MODAL_TIMEOUT_MS,
|
|
201
|
-
filter: (submission) =>
|
|
202
|
-
submission.user.id === interaction.user.id && submission.customId === expectedCustomId,
|
|
203
|
-
});
|
|
204
|
-
if (!submitted.isFromMessage()) {
|
|
205
|
-
return null;
|
|
206
|
-
}
|
|
207
|
-
return { interaction: submitted, values: modal.read(submitted) };
|
|
208
|
-
} catch {
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
213
|
+
const submitted = await collectModalSubmission(
|
|
214
|
+
interaction,
|
|
215
|
+
modal.build(nextModalOpenState(group.key)),
|
|
216
|
+
);
|
|
217
|
+
return submitted === null ? null : { interaction: submitted, values: modal.read(submitted) };
|
|
211
218
|
}
|
|
212
219
|
|
|
213
220
|
/** Reading a group's submission back — the group's own counterpart of {@link EditorFieldModal}. */
|
|
@@ -340,25 +347,44 @@ function valueFieldDefOf<F extends string>(
|
|
|
340
347
|
};
|
|
341
348
|
}
|
|
342
349
|
|
|
343
|
-
/**
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
350
|
+
/**
|
|
351
|
+
* The one modal a single field opens: titled after the field, carrying
|
|
352
|
+
* `fields`, and read back into the shape every single-field caller shares.
|
|
353
|
+
*/
|
|
354
|
+
function createFieldModal<const M extends ModalFields>(
|
|
355
|
+
labelKey: string,
|
|
356
|
+
fields: M,
|
|
347
357
|
translator: Translator,
|
|
348
358
|
locale: Locale,
|
|
359
|
+
toSubmission: (values: ModalValues<M>) => ReturnType<EditorFieldModal["read"]>,
|
|
349
360
|
): EditorFieldModal {
|
|
350
|
-
const label = translator.translate(locale, field.labelKey);
|
|
351
361
|
const modal = createModal({
|
|
352
362
|
id: EDITOR_FIELD_MODAL_ID,
|
|
353
|
-
title: modalTitle(
|
|
354
|
-
fields
|
|
363
|
+
title: modalTitle(translator.translate(locale, labelKey), translator, locale),
|
|
364
|
+
fields,
|
|
355
365
|
});
|
|
356
366
|
return {
|
|
357
367
|
build: (state) => modal.build(state),
|
|
358
|
-
read: (interaction) => (
|
|
368
|
+
read: (interaction) => toSubmission(modal.read(interaction)),
|
|
359
369
|
};
|
|
360
370
|
}
|
|
361
371
|
|
|
372
|
+
/** Every field but the images: one optional text input, emptied to clear. */
|
|
373
|
+
function createTextModal<F extends string>(
|
|
374
|
+
field: SettingsEditorValueField<F>,
|
|
375
|
+
current: SettingsEditorFieldValue,
|
|
376
|
+
translator: Translator,
|
|
377
|
+
locale: Locale,
|
|
378
|
+
): EditorFieldModal {
|
|
379
|
+
return createFieldModal(
|
|
380
|
+
field.labelKey,
|
|
381
|
+
{ value: valueFieldDefOf(field, current, translator, locale) },
|
|
382
|
+
translator,
|
|
383
|
+
locale,
|
|
384
|
+
(values) => ({ value: values.value, upload: null, ids: null }),
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
362
388
|
/**
|
|
363
389
|
* An image field: a file upload and the address input side by side, both
|
|
364
390
|
* optional, two of the five components a modal may carry.
|
|
@@ -373,11 +399,9 @@ function createImageModal<F extends string>(
|
|
|
373
399
|
translator: Translator,
|
|
374
400
|
locale: Locale,
|
|
375
401
|
): EditorFieldModal {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
title: modalTitle(label, translator, locale),
|
|
380
|
-
fields: {
|
|
402
|
+
return createFieldModal(
|
|
403
|
+
field.labelKey,
|
|
404
|
+
{
|
|
381
405
|
upload: {
|
|
382
406
|
kind: "file",
|
|
383
407
|
label: translator.translate(locale, SETTINGS_EDITOR_MESSAGES.modalUploadLabel),
|
|
@@ -402,14 +426,10 @@ function createImageModal<F extends string>(
|
|
|
402
426
|
...(current.text === null ? {} : { value: current.text }),
|
|
403
427
|
},
|
|
404
428
|
},
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const values = modal.read(interaction);
|
|
410
|
-
return { value: values.value, upload: values.upload?.[0] ?? null, ids: null };
|
|
411
|
-
},
|
|
412
|
-
};
|
|
429
|
+
translator,
|
|
430
|
+
locale,
|
|
431
|
+
(values) => ({ value: values.value, upload: values.upload?.[0] ?? null, ids: null }),
|
|
432
|
+
);
|
|
413
433
|
}
|
|
414
434
|
|
|
415
435
|
/**
|
|
@@ -426,11 +446,9 @@ function createPickerModal<F extends string>(
|
|
|
426
446
|
translator: Translator,
|
|
427
447
|
locale: Locale,
|
|
428
448
|
): EditorFieldModal {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
title: modalTitle(label, translator, locale),
|
|
433
|
-
fields: {
|
|
449
|
+
return createFieldModal(
|
|
450
|
+
field.labelKey,
|
|
451
|
+
{
|
|
434
452
|
value: pickerFieldDef(
|
|
435
453
|
field,
|
|
436
454
|
pickerShared(field, translator, locale),
|
|
@@ -439,14 +457,16 @@ function createPickerModal<F extends string>(
|
|
|
439
457
|
locale,
|
|
440
458
|
),
|
|
441
459
|
},
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
460
|
+
translator,
|
|
461
|
+
locale,
|
|
462
|
+
(values) => ({ value: null, upload: null, ids: values.value as readonly string[] | null }),
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** The part of a picker component every kind of picker declares alike. */
|
|
467
|
+
interface PickerShared extends SelectBounds {
|
|
468
|
+
label: string;
|
|
469
|
+
required: boolean;
|
|
450
470
|
}
|
|
451
471
|
|
|
452
472
|
/**
|
|
@@ -457,13 +477,7 @@ function pickerShared<F extends string>(
|
|
|
457
477
|
field: SettingsEditorPickerField<F>,
|
|
458
478
|
translator: Translator,
|
|
459
479
|
locale: Locale,
|
|
460
|
-
): {
|
|
461
|
-
label: string;
|
|
462
|
-
required: boolean;
|
|
463
|
-
minValues?: number;
|
|
464
|
-
maxValues?: number;
|
|
465
|
-
placeholder?: string;
|
|
466
|
-
} {
|
|
480
|
+
): PickerShared {
|
|
467
481
|
const placeholder =
|
|
468
482
|
field.pickerPlaceholderKey === undefined
|
|
469
483
|
? undefined
|
|
@@ -483,13 +497,7 @@ function pickerShared<F extends string>(
|
|
|
483
497
|
/** The one component a picker modal carries, in the shape its field's kind names. */
|
|
484
498
|
function pickerFieldDef<F extends string>(
|
|
485
499
|
field: SettingsEditorPickerField<F>,
|
|
486
|
-
shared:
|
|
487
|
-
label: string;
|
|
488
|
-
required: boolean;
|
|
489
|
-
minValues?: number;
|
|
490
|
-
maxValues?: number;
|
|
491
|
-
placeholder?: string;
|
|
492
|
-
},
|
|
500
|
+
shared: PickerShared,
|
|
493
501
|
held: readonly string[],
|
|
494
502
|
translator: Translator,
|
|
495
503
|
locale: Locale,
|
|
@@ -522,7 +530,7 @@ function pickerFieldDef<F extends string>(
|
|
|
522
530
|
kind: "select",
|
|
523
531
|
...shared,
|
|
524
532
|
options: field.choices.map((choice) => ({
|
|
525
|
-
label: translator.translate(locale, choice.labelKey),
|
|
533
|
+
label: translator.translate(locale, choice.labelKey, choice.labelParams),
|
|
526
534
|
value: choice.value,
|
|
527
535
|
...(choice.descriptionKey === undefined
|
|
528
536
|
? {}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SettingsEditorFieldValue } from "@/discord/components/settings-editor/settings-editor-fields";
|
|
2
|
+
|
|
3
|
+
/** A text override, as the modal editing it opens on. */
|
|
4
|
+
export function textFieldValue(value: string | null): SettingsEditorFieldValue {
|
|
5
|
+
return { text: value, uploaded: false, picked: [] };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** A picker override, as the modal editing it opens on — prefilled from what it already holds. */
|
|
9
|
+
export function pickedFieldValue(ids: readonly string[]): SettingsEditorFieldValue {
|
|
10
|
+
return { text: null, uploaded: false, picked: ids };
|
|
11
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChannelType } from "discord.js";
|
|
2
2
|
import type { TextFieldStyleName } from "@/discord/interaction/modal";
|
|
3
|
-
import type { TranslationParams } from "@/i18n";
|
|
3
|
+
import type { TranslationParams } from "@/i18n/translator";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* How a field is entered.
|
|
@@ -129,6 +129,11 @@ export interface SettingsEditorChoice {
|
|
|
129
129
|
/** What is stored — never shown, so it is not translated. */
|
|
130
130
|
readonly value: string;
|
|
131
131
|
readonly labelKey: string;
|
|
132
|
+
/**
|
|
133
|
+
* Placeholders of `labelKey`, for a label computed at run time (a search
|
|
134
|
+
* result) rather than declared.
|
|
135
|
+
*/
|
|
136
|
+
readonly labelParams?: TranslationParams;
|
|
132
137
|
/** Shown under the label, as a menu entry's hint is. Optional: a two-way toggle rarely needs one. */
|
|
133
138
|
readonly descriptionKey?: string;
|
|
134
139
|
}
|
|
@@ -244,16 +249,6 @@ export interface SettingsEditorFieldValue {
|
|
|
244
249
|
readonly picked: readonly string[];
|
|
245
250
|
}
|
|
246
251
|
|
|
247
|
-
/** A text override, as the modal editing it opens on. */
|
|
248
|
-
export function textFieldValue(value: string | null): SettingsEditorFieldValue {
|
|
249
|
-
return { text: value, uploaded: false, picked: [] };
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/** A picker override, as the modal editing it opens on — prefilled from what it already holds. */
|
|
253
|
-
export function pickedFieldValue(ids: readonly string[]): SettingsEditorFieldValue {
|
|
254
|
-
return { text: null, uploaded: false, picked: ids };
|
|
255
|
-
}
|
|
256
|
-
|
|
257
252
|
/** Discord's own cap on a modal text input, whatever the embed itself would take. */
|
|
258
253
|
export const MAX_MODAL_INPUT_LENGTH = 4000;
|
|
259
254
|
|
|
@@ -8,10 +8,12 @@ import type { Clock } from "@/clock";
|
|
|
8
8
|
import type {
|
|
9
9
|
InteractiveMessagePayload,
|
|
10
10
|
InteractiveView,
|
|
11
|
-
} from "@/discord/components/interactive-message";
|
|
11
|
+
} from "@/discord/components/interactive-message/interactive-message-collector";
|
|
12
12
|
import {
|
|
13
13
|
canReturn,
|
|
14
14
|
currentLevelKey,
|
|
15
|
+
indexLevels,
|
|
16
|
+
levelTrail,
|
|
15
17
|
ROOT_LEVEL_KEY,
|
|
16
18
|
type SettingsEditorLevel,
|
|
17
19
|
type SettingsEditorPath,
|
|
@@ -33,7 +35,8 @@ import { createSelectRow, createStringSelect } from "@/discord/interaction/selec
|
|
|
33
35
|
import type { CardBlock } from "@/discord/ui/card";
|
|
34
36
|
import { EMBED_COLORS } from "@/discord/ui/colors";
|
|
35
37
|
import type { MessageFile } from "@/discord/ui/message-attachments";
|
|
36
|
-
import type { Locale
|
|
38
|
+
import type { Locale } from "@/i18n/locale";
|
|
39
|
+
import type { Translator } from "@/i18n/translator";
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
42
|
* The row type this file's own rendering builds — and, since the card layout
|
|
@@ -456,16 +459,11 @@ export function createEditorView<S, A, F extends string>(
|
|
|
456
459
|
const screenTitle = translator.translate(locale, chrome.titleKey);
|
|
457
460
|
const intro =
|
|
458
461
|
chrome.introKey === undefined ? null : translator.translate(locale, chrome.introKey);
|
|
459
|
-
// Separates the levels in the heading trail.
|
|
460
|
-
const BREADCRUMB_SEPARATOR = " › ";
|
|
461
462
|
const body = [intro, chrome.legend].filter(
|
|
462
463
|
(part): part is string => part !== undefined && part !== null,
|
|
463
464
|
);
|
|
464
465
|
|
|
465
|
-
|
|
466
|
-
// rendering never special-cases "no depth declared".
|
|
467
|
-
const root: SettingsEditorLevel<F> = { key: ROOT_LEVEL_KEY, titleKey: chrome.titleKey, fields };
|
|
468
|
-
const allLevels: readonly SettingsEditorLevel<F>[] = [root, ...(levels ?? [])];
|
|
466
|
+
const allLevels = indexLevels({ key: ROOT_LEVEL_KEY, titleKey: chrome.titleKey, fields }, levels);
|
|
469
467
|
|
|
470
468
|
// A level's fields are authored, not accumulated: passing more than a menu can
|
|
471
469
|
// hold is a mistake in the declaration, and Discord would reject the whole
|
|
@@ -474,7 +472,7 @@ export function createEditorView<S, A, F extends string>(
|
|
|
474
472
|
//
|
|
475
473
|
// Lists that *grow* — a guild's ticket types, its permission grants — are the
|
|
476
474
|
// screen's own to page, through `extraRows`. See research D7.
|
|
477
|
-
for (const level of allLevels) {
|
|
475
|
+
for (const level of allLevels.all) {
|
|
478
476
|
if (level.fields.length > MAX_SELECT_OPTIONS) {
|
|
479
477
|
throw new Error(
|
|
480
478
|
`Settings editor level "${level.key}" declares ${level.fields.length} entries; a select menu holds ${MAX_SELECT_OPTIONS}. Split it into a deeper level.`,
|
|
@@ -497,17 +495,10 @@ export function createEditorView<S, A, F extends string>(
|
|
|
497
495
|
}
|
|
498
496
|
}
|
|
499
497
|
|
|
500
|
-
// A path entry naming no declared level cannot happen — only a level field
|
|
501
|
-
// puts one there — but falling back to the root keeps a corrupted state
|
|
502
|
-
// showing a usable screen rather than an empty one.
|
|
503
|
-
function levelAt(key: string): SettingsEditorLevel<F> {
|
|
504
|
-
return allLevels.find((level) => level.key === key) ?? root;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
498
|
// One menu per level, built once: the options of a level never vary with the
|
|
508
499
|
// state, only which level is showing does.
|
|
509
500
|
const menus = new Map(
|
|
510
|
-
allLevels.map((level) => [
|
|
501
|
+
allLevels.all.map((level) => [
|
|
511
502
|
level.key,
|
|
512
503
|
createStringSelect({
|
|
513
504
|
id: ids.field,
|
|
@@ -525,14 +516,10 @@ export function createEditorView<S, A, F extends string>(
|
|
|
525
516
|
return menus.get(currentLevelKey(state.path)) ?? menus.get(ROOT_LEVEL_KEY);
|
|
526
517
|
}
|
|
527
518
|
|
|
528
|
-
/**
|
|
529
|
-
* Where the reader is, as a trail rather than only the current name: a level
|
|
530
|
-
* called "Roles" says nothing on its own about which type it belongs to.
|
|
531
|
-
*/
|
|
532
519
|
function heading(state: SettingsEditorState<S, A>): string {
|
|
533
|
-
return state.path
|
|
534
|
-
|
|
535
|
-
|
|
520
|
+
return levelTrail(state.path, allLevels, (level) =>
|
|
521
|
+
translator.translate(locale, level.titleKey),
|
|
522
|
+
);
|
|
536
523
|
}
|
|
537
524
|
|
|
538
525
|
/**
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Guild } from "discord.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The guild a gateway event concerns, read from its arguments: a `Guild`
|
|
5
|
+
* itself (`guildCreate`), or the first argument carrying a `guildId` (a
|
|
6
|
+
* message, a channel, an interaction) or a `guild` (a member, a ban, a role).
|
|
7
|
+
*
|
|
8
|
+
* @param args - the arguments discord.js passed to the listener.
|
|
9
|
+
* @returns the guild id, or `undefined` for an event bound to no guild.
|
|
10
|
+
*/
|
|
11
|
+
export function eventGuildId(args: readonly unknown[]): string | undefined {
|
|
12
|
+
for (const arg of args) {
|
|
13
|
+
const guildId = guildIdOf(arg);
|
|
14
|
+
if (guildId !== undefined) {
|
|
15
|
+
return guildId;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function guildIdOf(arg: unknown): string | undefined {
|
|
22
|
+
if (arg instanceof Guild) {
|
|
23
|
+
return arg.id;
|
|
24
|
+
}
|
|
25
|
+
if (typeof arg !== "object" || arg === null) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
if ("guildId" in arg && typeof arg.guildId === "string") {
|
|
29
|
+
return arg.guildId;
|
|
30
|
+
}
|
|
31
|
+
if ("guild" in arg && typeof arg.guild === "object" && arg.guild !== null && "id" in arg.guild) {
|
|
32
|
+
return typeof arg.guild.id === "string" ? arg.guild.id : undefined;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|